PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
graph_mode.c
1#include <stdlib.h>
2#include <kernel.h>
3#include <osd_config.h>
4#include <rom0_info.h>
5
6#include <gs_privileged.h>
7
8#include <graph.h>
9#include <graph_config.h>
10
11/* y offset is non-interlaced */
12GRAPH_MODE graph_mode[22] =
13{
14
15 { 0, 0, 0, 0, 0 }, // AUTO
16 { 652, 26, 2560, 224, 0x02 }, // NTSC-NI
17 { 680, 37, 2560, 256, 0x03 }, // PAL-NI
18 { 232, 35, 1440, 480, 0x50 }, // 480P
19 { 320, 64, 1312, 576, 0x53 }, // 576P only in bios>=220
20 { 420, 40, 1280, 720, 0x52 }, // 720P
21 { 300, 120, 1920, 540, 0x51 }, // 1080I
22 { 280, 18, 1280, 480, 0x1A }, // VGA 640x480@60
23 { 330, 18, 1280, 480, 0x1B }, // VGA 640x480@72
24 { 360, 18, 1280, 480, 0x1C }, // VGA 640x480@75
25 { 260, 18, 1280, 480, 0x1D }, // VGA 640x480@85
26 { 450, 25, 1600, 600, 0x2A }, // VGA 800x600@56
27 { 465, 25, 1600, 600, 0x2B }, // VGA 800x600@60
28 { 465, 25, 1600, 600, 0x2C }, // VGA 800x600@72
29 { 510, 25, 1600, 600, 0x2D }, // VGA 800x600@75
30 { 500, 25, 1600, 600, 0x2E }, // VGA 800x600@85
31 { 580, 30, 2048, 768, 0x3B }, // VGA 1024x768@60
32 { 266, 30, 1024, 768, 0x3C }, // VGA 1024x768@70
33 { 260, 30, 1024, 768, 0x3D }, // VGA 1024x768@75
34 { 290, 30, 1024, 768, 0x3E }, // VGA 1024x768@85
35 { 350, 40, 1280, 1024, 0x4A }, // VGA 1280x1024@60
36 { 350, 40, 1280, 1024, 0x4B }, // VGA 1280x1024@75
37
38};
39
40static float graph_width = 0.0f;
41static float graph_height = 0.0f;
42static float graph_aspect = 1.0f;
43
44static int graph_filter = 0;
45static int graph_crtmode = 0;
46static int graph_interlace = 0;
47static int graph_ffmd = 0;
48static int graph_x = 0;
49static int graph_y = 0;
50static int graph_magh = 0;
51static int graph_magv = 0;
52
53static u64 graph_pmode = 0;
54
55// old bios has GCONT enabled
56u64 smode1_values[22] =
57{
58
59 0,
60 GS_SET_SMODE1(4,32,1,0,2,0,1,1,0,0,4,0,0,0,0,0,1,1,1,1,0), //0x02
61 GS_SET_SMODE1(4,32,1,0,3,0,1,1,0,0,4,0,0,0,0,0,1,1,1,1,0), //0x03
62 GS_SET_SMODE1(4,32,1,0,0,0,1,1,0,0,2,0,0,0,0,0,1,1,1,1,1), //0x50
63 GS_SET_SMODE1(4,32,1,0,0,0,1,1,0,1,2,0,0,0,0,0,1,1,1,1,1), //0x53
64 GS_SET_SMODE1(2,22,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,1), //0x52
65 GS_SET_SMODE1(2,22,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,0), //0x51
66 GS_SET_SMODE1(2,15,1,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x1A
67 GS_SET_SMODE1(3,28,1,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x1B
68 GS_SET_SMODE1(3,28,1,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x1C
69 GS_SET_SMODE1(3,16,0,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x1D
70 GS_SET_SMODE1(3,16,0,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x2A
71 GS_SET_SMODE1(6,71,1,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x2B
72 GS_SET_SMODE1(5,74,1,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x2C
73 GS_SET_SMODE1(3,44,1,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x2D
74 GS_SET_SMODE1(3,25,0,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x2E
75 GS_SET_SMODE1(3,29,0,0,0,0,0,1,0,0,2,0,0,0,0,0,1,1,1,0,1), //0x3B
76 GS_SET_SMODE1(6,67,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,1), //0x3C
77 GS_SET_SMODE1(3,35,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,1), //0x3D
78 GS_SET_SMODE1(1, 7,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,1), //0x3E
79 GS_SET_SMODE1(1, 8,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,1), //0x4A
80 GS_SET_SMODE1(1,10,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,1), //0x4B
81
82};
83
84static inline int __udelay(unsigned int usecs)
85{
86
87 register unsigned int loops_total = 0;
88 register unsigned int loops_end = usecs * 148;
89
90 if (usecs > loops_end)
91 {
92
93 return -1;
94
95 }
96
97 asm volatile (
98 ".set push\n\t"
99 ".set noreorder\n\t"
100 "0:\n\t"
101 "beq %0,%2,0f\n\t"
102 "addiu %0,1\n\t"
103 "bne %0,%2,0b\n\t"
104 "addiu %0,1\n\t"
105 "0:\n\t"
106 ".set pop\n\t"
107 :"=r" (loops_total)
108 :"0" (loops_total), "r" (loops_end));
109
110 return 0;
111
112}
113
115{
116
117 char romname[14];
118
119 GetRomName((char *)romname);
120
121 if (romname[4] == 'E')
122 {
123 return GRAPH_MODE_PAL;
124 }
125
126 return GRAPH_MODE_NTSC;
127
128}
129
130int graph_set_mode(int interlace, int mode, int ffmd, int flicker_filter)
131{
132
133
134 // Reset GS.
135 *GS_REG_CSR = (u64)1<<9;
136
137 // Clear GS CSR.
138 *GS_REG_CSR = GS_SET_CSR(0,0,0,0,0,0,0,0,0,0,0,0);
139
140 // Unmask GS VSYNC Interrupt.
141 GsPutIMR(0x00007700);
142
143 // Ensure registers are written prior to setting another mode.
144 asm volatile ("sync.p\n\t"
145 "nop\n\t");
146
147 // If 576P is requested, check if bios supports it.
148 if (mode == GRAPH_MODE_HDTV_576P)
149 {
150 char romname[14];
151
152 GetRomName((char *)romname);
153
154 if (strtol(romname,NULL,10) < 220) { mode = GRAPH_MODE_PAL; }
155
156 }
157
158 // 1080I is forced to be interlaced so correct value just in case.
159 if (mode == GRAPH_MODE_HDTV_1080I)
160 {
161
162 interlace = GRAPH_MODE_INTERLACED;
163
164 }
165
166 if (interlace == GRAPH_MODE_NONINTERLACED)
167 {
168
169 flicker_filter = GRAPH_DISABLE;
170
171 }
172
173 // Set graph's mode, interlacing and field mode.
174 graph_crtmode = mode;
175 graph_interlace = interlace;
176 graph_ffmd = ffmd;
177 graph_filter = flicker_filter;
178
179 // Set the requested mode.
180 SetGsCrt(graph_interlace, graph_mode[mode].mode, graph_ffmd);
181
182 return 0;
183
184}
185
186int graph_set_screen(int x, int y, int width, int height)
187{
188
189 int dx,dy,dw,dh;
190
191 graph_x = x;
192 graph_y = y;
193
194 graph_width = (float)width;
195 graph_height = (float)height;
196
197 // Check if the mode has been set
198 if (graph_crtmode == GRAPH_MODE_AUTO)
199 {
200
201 return -1;
202
203 }
204
205 // Add X adjustment to default X offset
206 dx = graph_mode[graph_crtmode].x + graph_x;
207
208 // Get default Y offset
209 dy = graph_mode[graph_crtmode].y;
210
211 // Get screen's width and height
212 dw = graph_mode[graph_crtmode].width;
213 dh = graph_mode[graph_crtmode].height;
214
215 // Double Y offset for interlacing in FIELD mode
216 // Double screen's height parameter
217 if ((graph_interlace) && (graph_ffmd == GRAPH_MODE_FIELD))
218 {
219
220 dy = (dy - 1) * 2;
221 dh = graph_mode[graph_crtmode].height * 2;
222
223 }
224
225 // Now add Y adjustment
226 dy += graph_y;
227
228 // Determine magnification
229 graph_magh = dw / width;
230 graph_magv = dh / height;
231
232 // Make sure it doesn't turn negative
233 if (graph_magh < 1)
234 {
235
236 graph_magh = 1;
237
238 }
239
240 if (graph_magv < 1)
241 {
242
243 graph_magv = 1;
244
245 }
246
247 // Set the display attributes but use the user defined height.
248 if (graph_filter)
249 {
250
251 // For flicker filter, we need to get add an extra line.
252 *GS_REG_DISPLAY1 = GS_SET_DISPLAY(dx,dy,graph_magh-1,graph_magv-1,dw-1,height-1);
253 *GS_REG_DISPLAY2 = GS_SET_DISPLAY(dx,dy,graph_magh-1,graph_magv-1,dw-1,height-2);
254
255 }
256 else
257 {
258
259 *GS_REG_DISPLAY1 = GS_SET_DISPLAY(dx,dy,graph_magh-1,graph_magv-1,dw-1,height-1);
260 *GS_REG_DISPLAY2 = GS_SET_DISPLAY(dx,dy,graph_magh-1,graph_magv-1,dw-1,height-1);
261
262 }
263
264 return 0;
265
266}
267
268void graph_set_framebuffer_filtered(int fbp, int width, int psm, int x, int y)
269{
270
271 *GS_REG_DISPFB1 = GS_SET_DISPFB(fbp>>11,width>>6,psm,x,y);
272
273 // For flicker filter, we need to offset the lines by 1 for the other read circuit.
274 *GS_REG_DISPFB2 = GS_SET_DISPFB(fbp>>11,width>>6,psm,x,y+1);
275
276}
277
278void graph_set_framebuffer(int context, int fbp, int width, int psm, int x, int y)
279{
280
281 if (context == 0)
282 {
283
284 *GS_REG_DISPFB1 = GS_SET_DISPFB(fbp>>11,width>>6,psm,x,y);
285
286 }
287 else
288 {
289
290 // For flicker filter, we need to offset the lines by 1 for the other read circuit.
291 *GS_REG_DISPFB2 = GS_SET_DISPFB(fbp>>11,width>>6,psm,x,y);
292
293 }
294
295}
296
297void graph_set_bgcolor(unsigned char r, unsigned char g, unsigned char b)
298{
299
300 *GS_REG_BGCOLOR = GS_SET_BGCOLOR(r,g,b);
301
302}
303
304void graph_set_output(int rc1, int rc2, int alpha_select, int alpha_output, int blend_method, unsigned char alpha)
305{
306
307 graph_pmode = GS_SET_PMODE(rc1, rc2, alpha_select, alpha_output, blend_method, alpha);
308 *GS_REG_PMODE = graph_pmode;
309
310}
311
312// Sets up the frame in rc1 to be blended with rc2 using a constant alpha value.
313// By offsetting the frame a line in the rc2 display/dispfb registers, the odd
314// numbered lines are more biased against the even lines, producing less jitter.
316{
317
318 if (graph_filter)
319 {
320
321 graph_set_output(GRAPH_ENABLE,GRAPH_ENABLE,GRAPH_VALUE_ALPHA,GRAPH_RC1_ALPHA,GRAPH_BLEND_RC2,0x70);
322
323 }
324 else
325 {
326
327 graph_set_output(0,1,0,1,0,0x80);
328
329 }
330
331}
332
334{
335
336 graph_set_output(0,0,0,0,0,0);
337
338}
339
340void graph_set_smode1(char cmod, char gcont)
341{
342
343 u64 pmode_val;
344 u64 smode1_val;
345
346 // Get the current values;
347 pmode_val = graph_pmode;
348 smode1_val = smode1_values[graph_crtmode];
349
350 if (smode1_val == 0)
351 {
352
353 return;
354
355 }
356
357 // If not VESA, set analog or digital output.
358 if ((graph_crtmode < 0x04) || (graph_crtmode > 0x50))
359 {
360
361 smode1_val |= (u64)(gcont & 1) << 25;
362
363 }
364
365 // If mode is a TV mode, set carrier modulation.
366 if ((graph_crtmode < 0x04) && (cmod > 0x01) && (cmod < 0x04))
367 {
368
369 smode1_val |= (u64)(cmod & 3) << 13;
370
371 }
372
373 // Turn off read circuits.
374 *GS_REG_PMODE = graph_pmode & ~3;
375
376 // Disable PRST for TV modes and enable for all other modes.
377 *GS_REG_SMODE1 = smode1_val | (u64)1 << 16;
378
379 asm volatile ("sync.l; sync.p;");
380
381 // If VESA, 1080I, or 720P, disable bit PRST now and delay 2.5ms.
382 if ((graph_crtmode >= 0x1A) && (graph_crtmode != 0x50) && (graph_crtmode != 0x53))
383 {
384
385 *GS_REG_SMODE1 = smode1_val & ~((u64)1 << 16);
386 __udelay(2500);
387
388 }
389
390 // Now disable both bits PRST & SINT.
391 *GS_REG_SMODE1 = smode1_val & ~((u64)1 << 16) & ~((u64)1 << 17);
392
393 // Now enable read circuits.
394 *GS_REG_PMODE = pmode_val;
395
396 asm volatile ("sync.l; sync.p;");
397
398}
399
401{
402
403 // Get the tv screen type as defined in the osd configuration.
404 if (configGetTvScreenType() == TV_SCREEN_169)
405 {
406
407 graph_aspect = 1.78f;
408
409 }
410 else
411 {
412
413 graph_aspect = 1.33f;
414
415 }
416
417 // Return the current aspect ratio
418 graph_aspect = graph_aspect * (graph_height / graph_width);
419
420 return graph_aspect;
421
422}
423
424int graph_get_config(char *config)
425{
426
427 return graph_make_config(graph_crtmode, graph_interlace, graph_ffmd, graph_x, graph_y, graph_filter, config);
428
429}
430
432{
433
435
436 // Reset GS.
437 *GS_REG_CSR = (u64)1<<9;
438
439 // Clear GS CSR.
440 *GS_REG_CSR = GS_SET_CSR(0,0,0,0,0,0,0,0,0,0,0,0);
441
442 // Reset the static variables.
443 graph_aspect = 1.0f;
444 graph_width = 0.0f;
445 graph_height = 0.0f;
446 graph_filter = 0;
447 graph_crtmode = 0;
448 graph_interlace = 0;
449 graph_ffmd = 0;
450 graph_x = 0;
451 graph_y = 0;
452 graph_magh = 0;
453 graph_magv = 0;
454
455 return 0;
456
457}
#define GRAPH_MODE_NTSC
Definition graph.h:15
int graph_set_screen(int x, int y, int width, int height)
Definition graph_mode.c:186
void graph_set_bgcolor(unsigned char r, unsigned char g, unsigned char b)
Definition graph_mode.c:297
#define GRAPH_DISABLE
Definition graph.h:67
void graph_set_output(int rc1, int rc2, int alpha_select, int alpha_output, int blend_method, unsigned char alpha)
Definition graph_mode.c:304
#define GRAPH_MODE_AUTO
Definition graph.h:13
#define GRAPH_MODE_HDTV_576P
Definition graph.h:21
#define GRAPH_MODE_HDTV_1080I
Definition graph.h:25
#define GRAPH_RC1_ALPHA
Definition graph.h:82
void graph_enable_output(void)
Definition graph_mode.c:315
void graph_set_framebuffer_filtered(int fbp, int width, int psm, int x, int y)
Definition graph_mode.c:268
int graph_get_region(void)
Definition graph_mode.c:114
int graph_shutdown(void)
Definition graph_mode.c:431
#define GRAPH_MODE_PAL
Definition graph.h:17
void graph_disable_output(void)
Definition graph_mode.c:333
float graph_aspect_ratio(void)
Definition graph_mode.c:400
int graph_set_mode(int interlace, int mode, int ffmd, int flicker_filter)
Definition graph_mode.c:130
#define GRAPH_BLEND_RC2
Definition graph.h:86
void graph_set_framebuffer(int context, int fbp, int width, int psm, int x, int y)
Definition graph_mode.c:278
int graph_get_config(char *config)
Definition graph_mode.c:424
int graph_make_config(int mode, int interlace, int ffmd, int x, int y, int flicker_filter, char *config)
Definition graph_config.c:8
#define GS_REG_CSR
#define GS_REG_DISPFB1
#define GS_REG_BGCOLOR
#define GS_REG_SMODE1
#define GS_REG_DISPLAY1
#define GS_REG_PMODE
#define GS_REG_DISPLAY2
#define GS_REG_DISPFB2
int configGetTvScreenType(void)
char * GetRomName(char *romname)