From adff38b97862d678ee37574e1a89e5fbdaef5d8a Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Sat, 14 Jan 2023 14:32:58 +0100 Subject: [PATCH] Expanded display initialization code with proper handling of both NTSC and PAL aspect ratios, and allowing PAL to render at higher resolution. Also includes provisioning for switching between progressive and interlaced modes. --- display.c | 56 ++++++++++++++++++++++++++++++++++++++++++------------- display.h | 6 ++++-- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/display.c b/display.c index 86c057f..9cc0a6b 100644 --- a/display.c +++ b/display.c @@ -47,7 +47,7 @@ MATRIX vp_matrix; u_long *curOT; // Scale X coordinates to correct the aspect ratio for the chosen resolution -VECTOR aspect_scale = { SCREENWIDTH * ONE / 320 , ONE, ONE }; +VECTOR aspect_scale = { SCREENWIDTH * ONE / 320, ONE, ONE }; void display_init() { @@ -55,15 +55,9 @@ void display_init() // ISR subsystem to the kernel ResetGraph(0); - //SetVideoMode(MODE_NTSC); - - // Define display environments, first on top and second on bottom - SetDefDispEnv(&disp[0], 0, 0, SCREENWIDTH, SCREENHEIGHT); - SetDefDispEnv(&disp[1], 0, SCREENHEIGHT, SCREENWIDTH, SCREENHEIGHT); - - // Define drawing environments, first on bottom and second on top - SetDefDrawEnv(&draw[0], 0, SCREENHEIGHT, SCREENWIDTH, SCREENHEIGHT); - SetDefDrawEnv(&draw[1], 0, 0, SCREENWIDTH, SCREENHEIGHT); + // Start the display in progressive mode + int screenHeight; + display_reset(0, &screenHeight); // Set and enable clear color setRGB0(&draw[0], 49, 77, 121); @@ -84,14 +78,51 @@ void display_init() FntLoad(960, 0); // Open up a test font text stream - FntOpen(0, 8, SCREENWIDTH, SCREENHEIGHT, 0, 512); + FntOpen(0, 8, SCREENWIDTH, screenHeight, 0, 512); // Initialize GTE InitGeom(); - gte_SetGeomOffset(SCREENWIDTH >> 1, SCREENHEIGHT >> 1); + gte_SetGeomOffset(SCREENWIDTH >> 1, screenHeight >> 1); gte_SetGeomScreen(180); // Screen depth for FOV control. Determines the distance of the camera to the near plane. } +void display_reset(u_char interlaced, int *outScreenHeight) +{ + int screenHeight, yOffset; + if (GetVideoMode() == MODE_NTSC) + { + screenHeight = SCREENHEIGHT_NTSC; + yOffset = (240 - SCREENHEIGHT_NTSC) >> 1; // Vertically center the image for NTSC displays + + // Scale Y coordinates to correct the aspect ratio for NTSC's typical visible screen area + aspect_scale.vy = 224 * ONE / 240; + } + else // MODE_PAL + { + screenHeight = SCREENHEIGHT_PAL; + yOffset = (288 - SCREENHEIGHT_PAL) >> 1; // Vertically center the image for PAL displays + + // Scale Y coordinates to correct the aspect ratio for PAL's non-square pixels + aspect_scale.vy = 256 * ONE / 240; + } + + // Define display environments, first on top and second on bottom + SetDefDispEnv(&disp[0], 0, 0, SCREENWIDTH, screenHeight); + SetDefDispEnv(&disp[1], 0, screenHeight, SCREENWIDTH, screenHeight); + + // Define drawing environments, first on bottom and second on top + SetDefDrawEnv(&draw[0], 0, screenHeight, SCREENWIDTH, screenHeight); + SetDefDrawEnv(&draw[1], 0, 0, SCREENWIDTH, screenHeight); + + disp[0].screen.y = disp[1].screen.y = yOffset; + disp[0].screen.h = disp[1].screen.h = screenHeight; + + gte_SetGeomOffset(SCREENWIDTH >> 1, screenHeight >> 1); + + if (outScreenHeight != NULL) + *outScreenHeight = screenHeight; +} + void display_start() { curOT = ot[db]; @@ -143,7 +174,6 @@ void *display_allocPrim(size_t size) if (nextpri + size > primbuff[db] + PRIMBUFLEN) return NULL; - // TODO: maybe add a bounds check? void *prim = nextpri; nextpri += size; return prim; diff --git a/display.h b/display.h index 5b88d96..fd4ded0 100644 --- a/display.h +++ b/display.h @@ -1,8 +1,9 @@ #ifndef __DISPLAY_H__ #define __DISPLAY_H__ -#define SCREENWIDTH 512 -#define SCREENHEIGHT 240 +#define SCREENWIDTH 512 +#define SCREENHEIGHT_NTSC 240 +#define SCREENHEIGHT_PAL 256 #define OTLEN 1024 @@ -10,6 +11,7 @@ extern MATRIX vp_matrix; extern u_long *curOT; void display_init(); +void display_reset(u_char interlaced, int *outScreenHeight); void display_start(); void display_finish();