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  __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 
130 int 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  EE_SYNCP();
145  __asm__ __volatile__ ("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 
186 int 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 
268 void 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 
278 void 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 
297 void 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 
304 void 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 
340 void 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  EE_SYNCL();
380  EE_SYNCP();
381 
382  // If VESA, 1080I, or 720P, disable bit PRST now and delay 2.5ms.
383  if ((graph_crtmode >= 0x1A) && (graph_crtmode != 0x50) && (graph_crtmode != 0x53))
384  {
385 
386  *GS_REG_SMODE1 = smode1_val & ~((u64)1 << 16);
387  __udelay(2500);
388 
389  }
390 
391  // Now disable both bits PRST & SINT.
392  *GS_REG_SMODE1 = smode1_val & ~((u64)1 << 16) & ~((u64)1 << 17);
393 
394  // Now enable read circuits.
395  *GS_REG_PMODE = pmode_val;
396 
397  EE_SYNCL();
398  EE_SYNCP();
399 
400 }
401 
403 {
404 
405  // Get the tv screen type as defined in the osd configuration.
406  if (configGetTvScreenType() == TV_SCREEN_169)
407  {
408 
409  graph_aspect = 1.78f;
410 
411  }
412  else
413  {
414 
415  graph_aspect = 1.33f;
416 
417  }
418 
419  // Return the current aspect ratio
420  graph_aspect = graph_aspect * (graph_height / graph_width);
421 
422  return graph_aspect;
423 
424 }
425 
426 int graph_get_config(char *config)
427 {
428 
429  return graph_make_config(graph_crtmode, graph_interlace, graph_ffmd, graph_x, graph_y, graph_filter, config);
430 
431 }
432 
433 int graph_shutdown(void)
434 {
435 
437 
438  // Reset GS.
439  *GS_REG_CSR = (u64)1<<9;
440 
441  // Clear GS CSR.
442  *GS_REG_CSR = GS_SET_CSR(0,0,0,0,0,0,0,0,0,0,0,0);
443 
444  // Reset the static variables.
445  graph_aspect = 1.0f;
446  graph_width = 0.0f;
447  graph_height = 0.0f;
448  graph_filter = 0;
449  graph_crtmode = 0;
450  graph_interlace = 0;
451  graph_ffmd = 0;
452  graph_x = 0;
453  graph_y = 0;
454  graph_magh = 0;
455  graph_magv = 0;
456 
457  return 0;
458 
459 }
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:433
GRAPH_MODE_NTSC
#define GRAPH_MODE_NTSC
Definition: graph.h:15
graph_get_region
int graph_get_region(void)
Definition: graph_mode.c:114
graph_set_framebuffer_filtered
void graph_set_framebuffer_filtered(int fbp, int width, int psm, int x, int y)
Definition: graph_mode.c:268
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:304
GRAPH_MODE
Definition: graph.h:89
graph_enable_output
void graph_enable_output(void)
Definition: graph_mode.c:315
graph_aspect_ratio
float graph_aspect_ratio(void)
Definition: graph_mode.c:402
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:278
graph_set_bgcolor
void graph_set_bgcolor(unsigned char r, unsigned char g, unsigned char b)
Definition: graph_mode.c:297
graph_get_config
int graph_get_config(char *config)
Definition: graph_mode.c:426
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:186
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:333
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:130