Optimizing VGA rendering speed for emulator?

Pages: 12
Isn't code automatically optimized? Do I really need to set it in the Makefile?

No, it isn't automatically optimized. However, -O2 is apparently already set in the makefile.

called by a frequency generator I made myself

How does this generator work? If you're using something along the lines of sleep in there, the result wouldn't be surprising.
I don't know how this VGA thing works, but for software rendering systems the fastest drawing method is to keep what you want to draw in intermediate buffers and then when you're ready, acquiring a pointer to the screen and drawing the entire screen in one go. Definitely not to draw one scanline at a time.
I'm using the following frequency generator (generates x function calls a second, determined by the frequency): (I haven't found such a system in the psp yet, also the PSP doesn't have multitasking capabilities, so delays/sleeping the thread makes it move to another running thread (if you don't the thread running will keep the cpu busy forever, thus never releasing control over the cpu))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "headers/types.h" //Basic types!
#include "headers/timers.h" //Timer support function data!
#include "headers/emu/threads.h" //Thread for timer item!

//Timer step in ms! Originally 100ms
#define TIMER_STEP 10000

float timerfreqs[10] = {0,0,0,0,0,0,0,0,0,0};;
Handler timers[10] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
uint_32 counters[10] = {0,0,0,0,0,0,0,0,0,0};
char timernames[10][256] = {"","","","","","","","","",""}; //Timer name!
int TIMER_RUNNING = 0; //Whether to run timers or pause!
int action_confirmed = 0; //Action confirmed (after stop)?

//This handles all current used timers!
void timer_thread() //Handler for timer!
{
	int curtimer;
	while (1) //Keep running!
	{

		if (TIMER_RUNNING && !action_confirmed) //Request to run?
		{
			action_confirmed = 1; //Confirmed to run!
		}
		else if (!TIMER_RUNNING && !action_confirmed) //To stop running?
		{
			action_confirmed = 1; //Confirmed!
			return; //Stop timer!
		}


		for (curtimer=0; curtimer<10; curtimer++) //Process timers!
		{
			if ((timers[curtimer]!=NULL) && (timerfreqs[curtimer]!=0.0)) //Timer set?
			{
				counters[curtimer] += TIMER_STEP; //Increase counter!
				if ((counters[curtimer]-(1000000/timerfreqs[curtimer]))>=0) //Overflow?
				{
					counters[curtimer] -= (1000000/timerfreqs[curtimer]); //Decrease counter!
					char name[256];
					bzero(name,sizeof(name)); //Init name!
					strcpy(name,"timer_sub_"); //Root!
					strcat(name,timernames[curtimer]); //Set name!
					startThread(timers[curtimer],name); //Fire the timer handler
				}
				if (counters[curtimer]>10000000) //Way too much (10 seconds)?
				{
					counters[curtimer] -= 10000000; //Remove some (10 seconds)!
				}
			}
		}

		sceKernelDelayThread(TIMER_STEP); //Lousy, take 100ms breaks!
	}
}

void addtimer(float frequency, Handler timer, char *name)
{
	int i;
	for (i=0; i<10; i++) //Check for existing timer!
	{
		if (strcmp(timernames[i],name)==0) //Found?
		{
			timers[i] = timer; //Edit timer if needed!
//Leave counter alone!
			timerfreqs[i] = frequency; //Edit frequency!
//Timer name is already set!
		}
	}

//Now for new timers!

	for (i=0; i<10; i++)
	{
		if (timerfreqs[i]==0.0) //Not set?
		{
			timers[i] = timer; //Set timer!
			counters[i] = 0; //Reset counter!
			timerfreqs[i] = frequency; //Start timer!
			strcpy(timernames[i],name); //Timer name!
			break;
		}
	}
}

void cleartimers() //Clear all running timers!
{
	int i;
	for (i=0; i<10; i++)
	{
		if (timerfreqs[i]!=0.0) //Set?
		{
			if (strcmp(timernames[i],"")!=0) //Set and has a name?
			{
				removetimer(timernames[i]); //Remove!
			}
		}
	}
}

void removetimer(char *name) //Removes a timer!
{
	int i;
	for (i=0; i<10; i++)
	{
		if (timerfreqs[i]!=0.0) //Enabled?
		{
			if (strcmp(timernames[i],name)==0) //Timer enabled and selected?
			{
				timerfreqs[i] = 0.0; //Turn timer off!
				timers[i] = NULL; //Remove timer!
				counters[i] = 0; //Reset counter!
				break;
			}
		}
	}
}

void startTimers()
{
	if (!TIMER_RUNNING) //Not already running?
	{
		TIMER_RUNNING = 1; //Start timers!
		startThread(&timer_thread,"timer_thread"); //Timer thread start!
	}
}

void stopTimers()
{
	if (TIMER_RUNNING) //Running already (we can terminate it)?
	{
		action_confirmed = 0; //Init!
		TIMER_RUNNING = 0; //Stop timers command for the timer thread!
		while (!action_confirmed) //Wait to stop!
		{
			delay(1); //Wait a bit for the thread to stop!
		}
	}
}

void resetTimers() //Reset all timers to off and turn off all handlers!
{
	stopTimers(); //Stop timer thread!
	int i;
	for (i=0; i<10; i++) //Go all!
	{
		timerfreqs[i] = 0.0; //Turn timer off!
		timers[i] = NULL; //Remove timer!
		counters[i] = 0; //Reset counter!
	}
}


The delay in the frequency generator is required however: the psp won't switch threads until a delay/sleep is executed. It's also used to time the frequency generator (after every delay, some time has passed, so we can increase the counter and call the frequency handlers based upon that). See http://forums.ps2dev.org/viewtopic.php?p=87021 , bottom post by Jesil of "Mon Jan 25, 2010 4:06 pm"

Also, the delay is 0.01 second, so we can create a frequency of 100Hz max.

EDIT: Just saw the frequency generator just handles the function once every check... I'll change the if ((counters[curtimer]-(1000000/timerfreqs[curtimer]))>=0) //Overflow? to while ((counters[curtimer]-(1000000/timerfreqs[curtimer]))>=0) //Overflow? to allow infinite frequency... (At 768 lines@60Hz, this is smaller than the 10000ms we generate at MAX now: we need delays of ~21.7ms, so about 4 times as much as it's now (100ms delays min now, it'll support the 21.7ms now...))

Also, something has been bugging me: after rebooting (clearing VGA to 0's and initializing int10 function 0h with the screen mode, i get a 80x25 text mode screen with 40x25 left half 40x25 screen rendering and the right half the same, but 1 row shifted upwards, with the overflow of the 80x25 text into the right part of the screen (which is correct, only the screen gets half duplicated to the right half of the screen, instead of being unique (it's a 80x25 text mode after all, only half rendered by 40x25 and the right half by 80x25 (3rd row) and 40x25 with one line shifted upwards for all other rows?
Last edited on
New timer created:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "headers/types.h" //Basic types!
#include "headers/timers.h" //Timer support function data!
#include "headers/emu/threads.h" //Thread for timer item!

//Timer step in ms! Originally 100ms
#define TIMER_STEP 10000

float timerfreqs[10] = {0,0,0,0,0,0,0,0,0,0};;
Handler timers[10] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
uint_32 counters[10] = {0,0,0,0,0,0,0,0,0,0};
char timernames[10][256] = {"","","","","","","","","",""}; //Timer name!
int TIMER_RUNNING = 0; //Whether to run timers or pause!
int action_confirmed = 0; //Action confirmed (after stop)?

//This handles all current used timers!
void timer_thread() //Handler for timer!
{
	int curtimer;
	while (1) //Keep running!
	{

		if (TIMER_RUNNING && !action_confirmed) //Request to run?
		{
			action_confirmed = 1; //Confirmed to run!
		}
		else if (!TIMER_RUNNING && !action_confirmed) //To stop running?
		{
			action_confirmed = 1; //Confirmed!
			return; //Stop timer!
		}


		uint_32 bonus = 0; //Bonus of other running threads!
		bonus = 0; //Init bonus!
		
		for (curtimer=0; curtimer<10; curtimer++) //Process timers!
		{
			if ((timers[curtimer]!=NULL) && (timerfreqs[curtimer]!=0.0)) //Timer set?
			{
				counters[curtimer] += TIMER_STEP+bonus; //Increase counter, including the bonus gotten from the other threads running!
				while ((counters[curtimer]-(1000000/timerfreqs[curtimer]))>=0) //Overflow?
				{
					counters[curtimer] -= (1000000/timerfreqs[curtimer]); //Decrease counter!
					char name[256];
					bzero(name,sizeof(name)); //Init name!
					strcpy(name,"timer_sub_"); //Root!
					strcat(name,timernames[curtimer]); //Set name!
					startThread(timers[curtimer],name); //Fire the timer handler
					delay(10); //Little time for the thread!
					counters[curtimer] += 10; //Add the bonus of the previous thread!
					bonus += 10; //We have a bonus for multiple threads!
				}
				while (counters[curtimer]>10000000) //Way too much (10 seconds)?
				{
					counters[curtimer] -= 10000000; //Remove some (10 seconds)!
				}
			}
		}

		sceKernelDelayThread(TIMER_STEP); //Lousy, take 100ms breaks!
	}
}

void addtimer(float frequency, Handler timer, char *name)
{
	int i;
	for (i=0; i<10; i++) //Check for existing timer!
	{
		if (strcmp(timernames[i],name)==0) //Found?
		{
			timers[i] = timer; //Edit timer if needed!
//Leave counter alone!
			timerfreqs[i] = frequency; //Edit frequency!
//Timer name is already set!
		}
	}

//Now for new timers!

	for (i=0; i<10; i++)
	{
		if (timerfreqs[i]==0.0) //Not set?
		{
			timers[i] = timer; //Set timer!
			counters[i] = 0; //Reset counter!
			timerfreqs[i] = frequency; //Start timer!
			strcpy(timernames[i],name); //Timer name!
			break;
		}
	}
}

void cleartimers() //Clear all running timers!
{
	int i;
	for (i=0; i<10; i++)
	{
		if (timerfreqs[i]!=0.0) //Set?
		{
			if (strcmp(timernames[i],"")!=0) //Set and has a name?
			{
				removetimer(timernames[i]); //Remove!
			}
		}
	}
}

void removetimer(char *name) //Removes a timer!
{
	int i;
	for (i=0; i<10; i++)
	{
		if (timerfreqs[i]!=0.0) //Enabled?
		{
			if (strcmp(timernames[i],name)==0) //Timer enabled and selected?
			{
				timerfreqs[i] = 0.0; //Turn timer off!
				timers[i] = NULL; //Remove timer!
				counters[i] = 0; //Reset counter!
				break;
			}
		}
	}
}

void startTimers()
{
	if (!TIMER_RUNNING) //Not already running?
	{
		TIMER_RUNNING = 1; //Start timers!
		startThread(&timer_thread,"timer_thread"); //Timer thread start!
	}
}

void stopTimers()
{
	if (TIMER_RUNNING) //Running already (we can terminate it)?
	{
		action_confirmed = 0; //Init!
		TIMER_RUNNING = 0; //Stop timers command for the timer thread!
		while (!action_confirmed) //Wait to stop!
		{
			delay(1); //Wait a bit for the thread to stop!
		}
	}
}

void resetTimers() //Reset all timers to off and turn off all handlers!
{
	stopTimers(); //Stop timer thread!
	int i;
	for (i=0; i<10; i++) //Go all!
	{
		timerfreqs[i] = 0.0; //Turn timer off!
		timers[i] = NULL; //Remove timer!
		counters[i] = 0; //Reset counter!
	}
}
Last edited on
Topic archived. No new replies allowed.
Pages: 12