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