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 typedef struct {
12  int x,y;
13  int width, height;
14  int mode;
15 } GRAPH_MODE;
16 
17 /* y offset is non-interlaced */
18 static 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 
46 static float graph_width = 0.0f;
47 static float graph_height = 0.0f;
48 
49 static int graph_filter = 0;
50 static int graph_crtmode = 0;
51 static int graph_interlace = 0;
52 static int graph_ffmd = 0;
53 static int graph_x = 0;
54 static int graph_y = 0;
55 static int graph_magh = 0;
56 static int graph_magv = 0;
57 
58 static u64 graph_pmode = 0;
59 
60 // old bios has GCONT enabled
61 static 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 
89 static 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 
139 int 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 
195 int 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 
277 void 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 
287 void 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 
306 void 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 
313 void 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 
349 void 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 
433 int 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 
440 int graph_shutdown(void)
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 }
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:440
GRAPH_MODE_NTSC
#define GRAPH_MODE_NTSC
Definition: graph.h:15
graph_get_region
int graph_get_region(void)
Definition: graph_mode.c:123
graph_set_framebuffer_filtered
void graph_set_framebuffer_filtered(int fbp, int width, int psm, int x, int y)
Definition: graph_mode.c:277
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:313
graph_enable_output
void graph_enable_output(void)
Definition: graph_mode.c:324
graph_aspect_ratio
float graph_aspect_ratio(void)
Definition: graph_mode.c:411
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:287
graph_set_bgcolor
void graph_set_bgcolor(unsigned char r, unsigned char g, unsigned char b)
Definition: graph_mode.c:306
graph_get_config
int graph_get_config(char *config)
Definition: graph_mode.c:433
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:195
GRAPH_RC1_ALPHA
#define GRAPH_RC1_ALPHA
Definition: graph.h:82
GRAPH_MODE
Definition: graph_mode.c:11
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:342
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:139