From 1a4599bf42f731987a682abf50796a62cf235549 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Mon, 12 Sep 2022 23:57:27 +0200 Subject: [PATCH] Added controller support with first person controls (including analog!) --- main.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index 4177530..533131e 100644 --- a/main.c +++ b/main.c @@ -19,13 +19,14 @@ #include #include #include +#include +#include #include #include #include - #include "ps1mdl.h" -#define OTLEN 256 +#define OTLEN 1024 #define SCREENWIDTH 512 #define SCREENHEIGHT 240 @@ -117,9 +118,11 @@ MATRIX light_dirs = { // Scale X coordinates to correct the aspect ratio for the chosen resolution VECTOR aspect_scale = { SCREENWIDTH * ONE / 320 , ONE, ONE }; -VECTOR cam_pos = { 0, 0, 0 }; +VECTOR cam_pos = { 0, -400, 100 }; SVECTOR cam_rot = { 0 }; +u_char padBuffer[2][34]; + void loadModel(const u_long* data, ps1mdl_t *mdl) { const char *bytes = (const char*)data; @@ -169,6 +172,12 @@ void loadSkin(const u_long* frontTim, const u_long* backTim, ps1skin_t *skin) // Init function void init(void) { + InitPAD(padBuffer[0], 34, padBuffer[1], 34); + padBuffer[0][0] = padBuffer[0][1] = 0xFF; + padBuffer[1][0] = padBuffer[1][1] = 0xFF; + StartPAD(); + ChangeClearPAD(1); // Avoid issues with VSync timeouts caused by StartPAD + // This not only resets the GPU but it also installs the library's // ISR subsystem to the kernel ResetGraph(0); @@ -524,8 +533,8 @@ void drawStuff(int counter) ScaleMatrixL(&proj_matrix, &aspect_scale); // Apply aspect ratio correction for the current resolution MATRIX view_matrix; - SVECTOR trot = { 0, 0, 0, 0 }; // TODO: inverse camera rotation (in Quake coordinates) - VECTOR tpos = { 0, 400, -100 }; // TODO: inverse camera position (in Quake coordinates) + 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) RotMatrix(&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 @@ -539,6 +548,114 @@ void drawStuff(int counter) drawModel(&view_matrix, &quadModel, &quadSkin, 0); } +void handleInput() +{ + const int moveSpeed = 32; + const short rotSpeed = 32; + + // Check if we have a connected controller on port 1 + if (padBuffer[0][0] != 0) + return; + + // Determine direction vectors of the camera + MATRIX cam_mtx; + RotMatrix(&cam_rot, &cam_mtx); + + u_short buttons = *((u_short*)(padBuffer[0]+2)); + if (!(buttons & PAD_UP)) + { + // Move forward + cam_pos.vx += (cam_mtx.m[0][1] * moveSpeed) >> 12; + cam_pos.vy += (cam_mtx.m[1][1] * moveSpeed) >> 12; + cam_pos.vz += (cam_mtx.m[2][1] * moveSpeed) >> 12; + } + if (!(buttons & PAD_DOWN)) + { + // Move backward + cam_pos.vx -= (cam_mtx.m[0][1] * moveSpeed) >> 12; + cam_pos.vy -= (cam_mtx.m[1][1] * moveSpeed) >> 12; + cam_pos.vz -= (cam_mtx.m[2][1] * moveSpeed) >> 12; + } + if (!(buttons & PAD_LEFT)) + { + // Rotate left + cam_rot.vz += rotSpeed; + } + if (!(buttons & PAD_RIGHT)) + { + // Rotate right + cam_rot.vz -= rotSpeed; + } + if (!(buttons & PAD_TRIANGLE)) + { + // Move up + cam_pos.vx += (cam_mtx.m[0][2] * moveSpeed) >> 12; + cam_pos.vy += (cam_mtx.m[1][2] * moveSpeed) >> 12; + cam_pos.vz += (cam_mtx.m[2][2] * moveSpeed) >> 12; + } + if (!(buttons & PAD_CROSS)) + { + // Move down + cam_pos.vx -= (cam_mtx.m[0][2] * moveSpeed) >> 12; + cam_pos.vy -= (cam_mtx.m[1][2] * moveSpeed) >> 12; + cam_pos.vz -= (cam_mtx.m[2][2] * moveSpeed) >> 12; + } + if (!(buttons & PAD_L1)) + { + // Strafe left + cam_pos.vx -= (cam_mtx.m[0][0] * moveSpeed) >> 12; + cam_pos.vy -= (cam_mtx.m[1][0] * moveSpeed) >> 12; + cam_pos.vz -= (cam_mtx.m[2][0] * moveSpeed) >> 12; + } + if (!(buttons & PAD_R1)) + { + // Strafe right + cam_pos.vx += (cam_mtx.m[0][0] * moveSpeed) >> 12; + cam_pos.vy += (cam_mtx.m[1][0] * moveSpeed) >> 12; + cam_pos.vz += (cam_mtx.m[2][0] * moveSpeed) >> 12; + } + if (!(buttons & PAD_L2)) + { + // Look down + cam_rot.vx -= rotSpeed; + } + if (!(buttons & PAD_R2)) + { + // Look up + cam_rot.vx += rotSpeed; + } + + // Check for analog controller + u_char padType = padBuffer[0][1] >> 4; + if (padType == 0x5 || padType == 0x7) + { + short rightJoyX = (short)(padBuffer[0][4]) - 0x80; + if (rightJoyX > -0x20 && rightJoyX < 0x20) rightJoyX = 0; + short rightJoyY = (short)(padBuffer[0][5]) - 0x80; + if (rightJoyY > -0x20 && rightJoyY < 0x20) rightJoyY = 0; + short leftJoyX = (short)(padBuffer[0][6]) - 0x80; + if (leftJoyX > -0x20 && leftJoyX < 0x20) leftJoyX = 0; + short leftJoyY = (short)(padBuffer[0][7]) - 0x80; + if (leftJoyY > -0x20 && leftJoyY < 0x20) leftJoyY = 0; + + // Move forward/backward + cam_pos.vx -= (cam_mtx.m[0][1] * leftJoyY * moveSpeed) >> 19; + cam_pos.vy -= (cam_mtx.m[1][1] * leftJoyY * moveSpeed) >> 19; + cam_pos.vz -= (cam_mtx.m[2][1] * leftJoyY * moveSpeed) >> 19; + + // Strafe left/right + cam_pos.vx += (cam_mtx.m[0][0] * leftJoyX * moveSpeed) >> 19; + cam_pos.vy += (cam_mtx.m[1][0] * leftJoyX * moveSpeed) >> 19; + cam_pos.vz += (cam_mtx.m[2][0] * leftJoyX * moveSpeed) >> 19; + + // Rotate left/right + cam_rot.vz -= (rightJoyX * rotSpeed) >> 7; + + // Look up/down + cam_rot.vx -= (rightJoyY * rotSpeed) >> 7; + } +} + // Main function, program entrypoint int main(int argc, const char *argv[]) { @@ -551,6 +668,8 @@ int main(int argc, const char *argv[]) counter = 0; while(1) { + handleInput(); + quadModel.rotation.vz = (counter << 5) % ONE; quadModel.position.vz = (isin(counter << 6) * 32) >> 12;