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