diff --git a/misc/ps1/ps1defs.h b/misc/ps1/ps1defs.h index 1c8380bff..b0d308198 100644 --- a/misc/ps1/ps1defs.h +++ b/misc/ps1/ps1defs.h @@ -41,6 +41,7 @@ enum gp0_rectcmd_flags { }; enum gp1_cmd_type { + GP1_CMD_RESET_GPU = 0x00000000, GP1_CMD_DISPLAY_ACTIVE = 0x03000000, GP1_CMD_DMA_MODE = 0x04000000, GP1_CMD_DISPLAY_ADDRESS = 0x05000000, diff --git a/src/Graphics_PS1.c b/src/Graphics_PS1.c index 4dee88b83..18c9af113 100644 --- a/src/Graphics_PS1.c +++ b/src/Graphics_PS1.c @@ -14,7 +14,52 @@ #include "../misc/ps1/ps1defs.h" // Based off https://github.com/Lameguy64/PSn00bSDK/blob/master/examples/beginner/hello/main.c +#define wait_while(cond) while (cond) { __asm__ volatile(""); } + +/*########################################################################################################################* +*------------------------------------------------------GPU management-----------------------------------------------------* +*#########################################################################################################################*/ +static volatile cc_uint32 vblank_count; + +static void vblank_handler(void) { vblank_count++; } + +#define DMA_IDX_GPU (DMA_GPU * 4) +#define DMA_IDX_OTC (DMA_OTC * 4) + +void Gfx_ResetGPU(void) { + int needs_exit = EnterCriticalSection(); + InterruptCallback(IRQ_VBLANK, &vblank_handler); + if (needs_exit) ExitCriticalSection(); + + GPU_GP1 = GP1_CMD_RESET_GPU; + ChangeClearPAD(0); + + // Enable GPU and OTC DMA channels at priority 3 + DMA_DPCR |= (0xB << DMA_IDX_GPU) | (0xB << DMA_IDX_OTC); + + // Stop pending DMA + DMA_CHCR(DMA_GPU) = CHRC_MODE_SLICE | CHRC_FROM_RAM; + DMA_CHCR(DMA_OTC) = CHRC_MODE_SLICE; +} + +void Gfx_VSync(void) { + cc_uint32 counter = vblank_count; + + for (int i = 0; i < 0x100000; i++) + { + if (counter != vblank_count) return; + } + + // VSync IRQ may be swallowed by BIOS, try to undo that + Platform_LogConst("VSync timed out"); + ChangeClearPAD(0); +} + + +/*########################################################################################################################* +*------------------------------------------------------Render buffers-----------------------------------------------------* +*#########################################################################################################################*/ // Length of the ordering table, i.e. the range Z coordinates can have, 0-15 in // this case. Larger values will allow for more granularity with depth (useful // when drawing a complex 3D scene) at the expense of RAM usage and performance. @@ -24,8 +69,6 @@ // crashes due to too many primitives being drawn, increase this value. #define BUFFER_LENGTH 32768 -#define wait_while(cond) while (cond) { __asm__ volatile(""); } - struct EnvPrimities { uint32_t tag; uint32_t tpage_code[1]; @@ -51,7 +94,6 @@ static uint8_t* next_packet_end; static int active_buffer; static RenderBuffer* cur_buffer; static void* lastPoly; -static cc_bool cullingEnabled, noMemWarned; static void BuildContext(RenderBuffer* buf) { struct EnvPrimities* prim = &buf->env; @@ -105,7 +147,13 @@ static void SetupContexts(int w, int h) { OnBufferUpdated(); } + +/*########################################################################################################################* +*----------------------------------------------------------General--------------------------------------------------------* +*#########################################################################################################################*/ static GfxResourceID white_square; +static cc_bool cullingEnabled; + void Gfx_RestoreState(void) { InitDefaultResources(); @@ -907,7 +955,7 @@ void Gfx_EndFrame(void) { Platform_LogConst("OUT OF VERTEX RAM"); } WaitUntilFinished(); - VSync(0); + Gfx_VSync(); RenderBuffer* draw_buffer = &buffers[active_buffer]; RenderBuffer* disp_buffer = &buffers[active_buffer ^ 1]; diff --git a/src/Platform_PS1.c b/src/Platform_PS1.c index eaeeee543..d4f7f0ea9 100644 --- a/src/Platform_PS1.c +++ b/src/Platform_PS1.c @@ -246,8 +246,11 @@ cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ +extern void Gfx_ResetGPU(void); + void Platform_Init(void) { - ResetGraph(0); + ResetCallback(); + Gfx_ResetGPU(); Stopwatch_Init(); } diff --git a/src/Window_PS1.c b/src/Window_PS1.c index 00c95d2c5..23be62785 100644 --- a/src/Window_PS1.c +++ b/src/Window_PS1.c @@ -24,9 +24,12 @@ static cc_bool launcherMode; struct _DisplayData DisplayInfo; struct cc_window WindowInfo; -static DISPENV disp; +static int gpu_video_mode; + +void Window_PreInit(void) { + gpu_video_mode = (GPU_GP1 >> 20) & 1; +} -void Window_PreInit(void) { } void Window_Init(void) { DisplayInfo.Width = SCREEN_XRES; DisplayInfo.Height = SCREEN_YRES; @@ -49,7 +52,7 @@ void Window_Init(void) { void Window_Free(void) { } static void InitScreen(void) { - int vid = GetVideoMode(); + int vid = gpu_video_mode; int mode = (vid << 3) | GP1_HOR_RES_320 | GP1_VER_RES_240; int yMid = vid ? 0xA3 : 0x88; // PAL has more vertical lines @@ -82,9 +85,10 @@ static void ClearScreen(void) GPU_GP0 = GP0_CMD_FILL_XY(0, 0); GPU_GP0 = GP0_CMD_FILL_WH(320, 200); } +extern void Gfx_ResetGPU(void); void Window_Create2D(int width, int height) { - ResetGraph(0); + Gfx_ResetGPU(); launcherMode = true; InitScreen(); @@ -92,7 +96,7 @@ void Window_Create2D(int width, int height) { } void Window_Create3D(int width, int height) { - ResetGraph(0); + Gfx_ResetGPU(); launcherMode = false; InitScreen();