You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
5.4 KiB
194 lines
5.4 KiB
#include "common.h"
|
|
#include "display.h"
|
|
|
|
#include <inline_c.h>
|
|
|
|
// Define display/draw environments for double buffering
|
|
static DISPENV disp[2];
|
|
static DRAWENV draw[2];
|
|
static int db;
|
|
|
|
static u_long ot[2][OTLEN]; // Ordering tables, two arrays for double buffering. These are basically the buckets for bucket sorting of polygons.
|
|
|
|
const MATRIX identity = {
|
|
ONE, 0, 0,
|
|
0, ONE, 0,
|
|
0, 0, ONE,
|
|
0, 0, 0,
|
|
};
|
|
|
|
// Transform to change the coordinate system from PS1 Default (Y down, Z forward) to Quake (Z up, Y forward)
|
|
const MATRIX quake_swizzle = {
|
|
ONE, 0, 0,
|
|
0, 0, -ONE,
|
|
0, ONE, 0,
|
|
0, 0, 0,
|
|
};
|
|
|
|
MATRIX light_cols = {
|
|
ONE, 0, 0,
|
|
ONE, 0, 0,
|
|
ONE, 0, 0
|
|
};
|
|
|
|
MATRIX light_dirs = {
|
|
ONE, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0
|
|
};
|
|
|
|
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 };
|
|
|
|
u_short polyCount;
|
|
|
|
void display_init()
|
|
{
|
|
// This not only resets the GPU but it also installs the library's
|
|
// ISR subsystem to the kernel
|
|
ResetGraph(0);
|
|
|
|
// Initialize GTE
|
|
InitGeom();
|
|
gte_SetGeomScreen(180); // Screen depth for FOV control. Determines the distance of the camera to the near plane.
|
|
|
|
// Start the display in progressive mode
|
|
int screenHeight;
|
|
display_reset(GetVideoMode(), 0, 0, &screenHeight);
|
|
|
|
// Clear double buffer counter
|
|
db = 0;
|
|
|
|
// Apply the GPU environments
|
|
PutDispEnv(&disp[db]);
|
|
PutDrawEnv(&draw[db]);
|
|
|
|
// Load test font
|
|
FntLoad(960, 0);
|
|
|
|
// Open up a test font text stream
|
|
FntOpen(0, 16, SCREENWIDTH, screenHeight, 0, 512);
|
|
}
|
|
|
|
void display_reset(int mode, u_char interlaced, u_char widescreen, int *outScreenHeight)
|
|
{
|
|
if (mode != GetVideoMode())
|
|
SetVideoMode(mode);
|
|
|
|
int screenHeight, yOffset;
|
|
if (mode == 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 = 216 * ONE / 240;
|
|
}
|
|
else // MODE_PAL
|
|
{
|
|
screenHeight = SCREENHEIGHT_PAL;
|
|
yOffset = (296 - 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;
|
|
}
|
|
|
|
if (interlaced)
|
|
{
|
|
screenHeight <<= 1;
|
|
yOffset <<= 1;
|
|
aspect_scale.vy <<= 1;
|
|
|
|
// Define display environments, interlaced images cover the same area in VRAM
|
|
SetDefDispEnv(&disp[0], 0, 0, SCREENWIDTH, screenHeight);
|
|
SetDefDispEnv(&disp[1], 0, 0, SCREENWIDTH, screenHeight);
|
|
|
|
// Define drawing environments, interlaced images cover the same area in VRAM
|
|
SetDefDrawEnv(&draw[0], 0, 0, SCREENWIDTH, screenHeight);
|
|
SetDefDrawEnv(&draw[1], 0, 0, SCREENWIDTH, screenHeight);
|
|
|
|
disp[0].isinter = disp[1].isinter = 1;
|
|
}
|
|
else
|
|
{
|
|
// 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].isinter = disp[1].isinter = 0;
|
|
}
|
|
|
|
// Scale X coordinates to set the aspect ratio for 4:3 or 16:9 widescreen
|
|
aspect_scale.vx = SCREENWIDTH * ONE / (widescreen ? 426 : 320);
|
|
|
|
disp[0].screen.y = disp[1].screen.y = yOffset;
|
|
disp[0].screen.h = disp[1].screen.h = screenHeight;
|
|
|
|
// Set and enable clear color
|
|
setRGB0(&draw[0], 49, 77, 121);
|
|
setRGB0(&draw[1], 49, 77, 121);
|
|
draw[0].isbg = 1;
|
|
draw[0].dtd = 1;
|
|
draw[1].isbg = 1;
|
|
draw[1].dtd = 1;
|
|
|
|
gte_SetGeomOffset(SCREENWIDTH >> 1, screenHeight >> 1);
|
|
|
|
if (outScreenHeight != NULL)
|
|
*outScreenHeight = screenHeight;
|
|
}
|
|
|
|
void display_start()
|
|
{
|
|
curOT = ot[db];
|
|
ClearOTagR(curOT, OTLEN);
|
|
|
|
mem_prim_reset(db);
|
|
polyCount = 0;
|
|
|
|
gte_SetBackColor(48, 48, 48); // Ambient light color
|
|
gte_SetColorMatrix(&light_cols); // Light color (up to three different lights)
|
|
gte_SetLightMatrix(&identity);
|
|
|
|
MATRIX proj_matrix = quake_swizzle; // Swizzle coordinates so that everything is in Quake coordinate system (Z up)
|
|
ScaleMatrixL(&proj_matrix, &aspect_scale); // Apply aspect ratio correction for the current resolution
|
|
|
|
MATRIX view_matrix;
|
|
SVECTOR trot = { -cam_rot.vx, -cam_rot.vy, -cam_rot.vz, 0 }; // Inverse camera rotation (in Quake coordinates)
|
|
VECTOR tpos = { -cam_pos.vx, -cam_pos.vy, -cam_pos.vz }; // Inverse camera position (in Quake coordinates)
|
|
RotMatrixQ(&trot, &view_matrix); // Set camera rotation part of the view matrix
|
|
ApplyMatrixLV(&view_matrix, &tpos, &tpos); // Apply camera rotation to camera position
|
|
TransMatrix(&view_matrix, &tpos); // Apply transformed position to the translation part of the view matrix
|
|
|
|
// Compose view and projection matrices to obtain a combined view-projection matrix
|
|
CompMatrixLV(&proj_matrix, &view_matrix, &vp_matrix);
|
|
}
|
|
|
|
void display_finish()
|
|
{
|
|
// Flip buffer index
|
|
db = !db;
|
|
|
|
// Wait for all drawing to complete
|
|
DrawSync(0);
|
|
|
|
// Wait for vertical sync to cap the logic to 60fps (or 50 in PAL mode)
|
|
// and prevent screen tearing
|
|
//VSync(0);
|
|
|
|
// Switch pages
|
|
PutDispEnv(&disp[db]);
|
|
PutDrawEnv(&draw[db]);
|
|
|
|
// Enable display output, ResetGraph() disables it by default
|
|
SetDispMask(1);
|
|
|
|
DrawOTag(curOT + OTLEN - 1); // This performs a DMA transfer to quickly send all the primitives off to the GPU
|
|
}
|