shithub: psxe

Download patch

ref: 28f41b042d9337a1080b92305e51233d0a34c63b
parent: 3f91a2038abf10e772efba06dd492c9e314eea06
author: allkern <lisandroaalarcon@gmail.com>
date: Tue Dec 19 12:23:49 EST 2023

Overall code cleanup

Fix MDEC issue

--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 .ONESHELL:
 
 CFLAGS += -g -DLOG_USE_COLOR -lSDL2 -lSDL2main
-CFLAGS += -Ofast -Wno-overflow -Wall -pedantic
+CFLAGS += -Ofast -Wno-overflow -Wall -pedantic -Wno-address-of-packed-member
 
 PLATFORM := $(shell uname -s)
 
--- a/build-win64.ps1
+++ b/build-win64.ps1
@@ -24,6 +24,7 @@
     -L"`"$($SDL2_DIR)\lib`"" `
     -m64 -lSDL2main -lSDL2 -Wno-overflow `
     -Wall -pedantic -DLOG_USE_COLOR `
+    -Wno-address-of-packed-member `
     -ffast-math -Ofast -g
 
 Copy-Item -Path "sdl2-win64/SDL2.dll" -Destination "bin"
\ No newline at end of file
--- a/frontend/screen.c
+++ b/frontend/screen.c
@@ -133,17 +133,18 @@
     void* display_buf = screen->debug_mode ?
         psx_get_vram(screen->psx) : psx_get_display_buffer(screen->psx);
 
-    // Update texture
-    int pitch;
-    uint8_t* ptr = NULL;
+    // // Update texture with Lock/UnlockTexture
+    // int pitch;
+    // uint8_t* ptr = NULL;
 
-    SDL_LockTexture(screen->texture, NULL, &ptr, &pitch);
+    // SDL_LockTexture(screen->texture, NULL, &ptr, &pitch);
 
-    for (int y = 0; y < screen->texture_height; y++)
-        memcpy(ptr + (y * pitch), display_buf + (y * PSX_GPU_FB_STRIDE), pitch);
+    // for (int y = 0; y < screen->texture_height; y++)
+    //     memcpy(ptr + (y * pitch), display_buf + (y * PSX_GPU_FB_STRIDE), pitch);
 
-    SDL_UnlockTexture(screen->texture);
+    // SDL_UnlockTexture(screen->texture);
 
+    SDL_UpdateTexture(screen->texture, NULL, display_buf, PSX_GPU_FB_STRIDE);
     SDL_RenderClear(screen->renderer);
 
     if (!screen->debug_mode) {
@@ -261,9 +262,6 @@
 void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) {
     psxe_screen_t* screen = gpu->udata[0];
 
-    int texture_width;
-    int texture_height;
-
     screen->format = psx_get_display_format(screen->psx) ?
         SDL_PIXELFORMAT_RGB24 : SDL_PIXELFORMAT_BGR555;
 
@@ -270,8 +268,8 @@
     if (screen->debug_mode) {
         screen->width = PSX_GPU_FB_WIDTH;
         screen->height = PSX_GPU_FB_HEIGHT;
-        texture_width = PSX_GPU_FB_WIDTH;
-        texture_height = PSX_GPU_FB_HEIGHT;
+        screen->texture_width = PSX_GPU_FB_WIDTH;
+        screen->texture_height = PSX_GPU_FB_HEIGHT;
     } else {
         if (screen->fullscreen) {
             screen->width = 1920;
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -5,6 +5,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "cpu_debug.h"
+
 static const psx_cpu_instruction_t g_psx_cpu_secondary_table[] = {
     psx_cpu_i_sll    , psx_cpu_i_invalid, psx_cpu_i_srl    , psx_cpu_i_sra    ,
     psx_cpu_i_sllv   , psx_cpu_i_invalid, psx_cpu_i_srlv   , psx_cpu_i_srav   ,
@@ -168,389 +170,6 @@
 #define R_A0 (cpu->r[4])
 #define R_RA (cpu->r[31])
 
-//#define CPU_TRACE
-
-static const char* g_psx_cpu_a_kcall_symtable[] = {
-    "open(filename=%08x,accessmode=%08x)",
-    "lseek(fd=%08x,offset=%08x,seektype=%08x)",
-    "read(fd=%08x,dst=%08x,length=%08x)",
-    "write(fd=%08x,src=%08x,length=%08x)",
-    "close(fd=%08x)",
-    "ioctl(fd=%08x,cmd=%08x,arg=%08x)",
-    "exit(exitcode=%08x)",
-    "isatty(fd=%08x)",
-    "getc(fd=%08x)",
-    "putc(char=%08x,fd=%08x)",
-    "todigit(char=%08x)",
-    "atof(src=%08x)",
-    "strtoul(src=%08x,src_end=%08x,base=%08x)",
-    "strtol(src=%08x,src_end=%08x,base=%08x)",
-    "abs(val=%08x)",
-    "labs(val=%08x)",
-    "atoi(src=%08x)",
-    "atol(src=%08x)",
-    "atob(src=%08x,num_dst=%08x)",
-    "setjmp(buf=%08x)",
-    "longjmp(buf=%08x,param=%08x)",
-    "strcat(dst=%08x,src=%08x)",
-    "strncat(dst=%08x,src=%08x,maxlen=%08x)",
-    "strcmp(str1=%08x,str2=%08x)",
-    "strncmp(str1=%08x,str2=%08x,maxlen=%08x)",
-    "strcpy(dst=%08x,src=%08x)",
-    "strncpy(dst=%08x,src=%08x,maxlen=%08x)",
-    "strlen(src=%08x)",
-    "index(src=%08x,char=%08x)",
-    "rindex(src=%08x,char=%08x)",
-    "strchr(src=%08x,char=%08x)",
-    "strrchr(src=%08x,char=%08x)",
-    "strpbrk(src=%08x,list=%08x)",
-    "strspn(src=%08x,list=%08x)",
-    "strcspn(src=%08x,list=%08x)",
-    "strtok(src=%08x,list=%08x)",
-    "strstr(str=%08x,substr=%08x)",
-    "toupper(char=%08x)",
-    "tolower(char=%08x)",
-    "bcopy(src=%08x,dst=%08x,len=%08x)",
-    "bzero(dst=%08x,len=%08x)",
-    "bcmp(ptr1=%08x,ptr2=%08x,len=%08x)",
-    "memcpy(dst=%08x,src=%08x,len=%08x)",
-    "memset(dst=%08x,fillbyte=%08x,len=%08x)",
-    "memmove(dst=%08x,src=%08x,len=%08x)",
-    "memcmp(src1=%08x,src2=%08x,len=%08x)",
-    "memchr(src=%08x,scanbyte=%08x,len=%08x)",
-    "rand()",
-    "srand(seed=%08x)",
-    "qsort(base=%08x,nel=%08x,width=%08x,callback=%08x)",
-    "strtod(src=%08x,src_end=%08x)",
-    "malloc(size=%08x)",
-    "free(buf=%08x)",
-    "lsearch(key=%08x,base=%08x,nel=%08x,width=%08x,callback=%08x)",
-    "bsearch(key=%08x,base=%08x,nel=%08x,width=%08x,callback=%08x)",
-    "calloc(sizx=%08x,sizy=%08x)",
-    "realloc(old_buf=%08x,new_siz=%08x)",
-    "InitHeap(addr=%08x,size=%08x)",
-    "_exit(exitcode=%08x)",
-    "getchar()",
-    "putchar(char=%08x)",
-    "gets(dst=%08x)",
-    "puts(src=%08x)",
-    "printf(txt=%08x,param1=%08x,param2=%08x,etc.=%08x)",
-    "SystemErrorUnresolvedException()",
-    "LoadTest(filename=%08x,headerbuf=%08x)",
-    "Load(filename=%08x,headerbuf=%08x)",
-    "Exec(headerbuf=%08x,param1=%08x,param2=%08x)",
-    "FlushCache()",
-    "init_a0_b0_c0_vectors()",
-    "GPU_dw(Xdst=%08x,Ydst=%08x,Xsiz=%08x,Ysiz=%08x,src=%08x)",
-    "gpu_send_dma(Xdst=%08x,Ydst=%08x,Xsiz=%08x,Ysiz=%08x,src=%08x)",
-    "SendGP1Command(gp1cmd=%08x)",
-    "GPU_cw(gp0cmd=%08x)",
-    "GPU_cwp(src=%08x,num=%08x)",
-    "send_gpu_linked_list(src=%08x)",
-    "gpu_abort_dma()",
-    "GetGPUStatus()",
-    "gpu_sync()",
-    "SystemError()",
-    "SystemError()",
-    "LoadExec(filename=%08x,stackbase=%08x,stackoffset=%08x)",
-    "GetSysSp()",
-    "SystemError()",
-    "_96_init()",
-    "_bu_init()",
-    "_96_remove()",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "dev_tty_init()",
-    "dev_tty_open(fcb=%08x, (unused)path=%08x,accessmode=%08x)",
-    "dev_tty_in_out(fcb=%08x,cmd=%08x)",
-    "dev_tty_ioctl(fcb=%08x,cmd=%08x,arg=%08x)",
-    "dev_cd_open(fcb=%08x,path=%08x,accessmode=%08x)",
-    "dev_cd_read(fcb=%08x,dst=%08x,len=%08x)",
-    "dev_cd_close(fcb=%08x)",
-    "dev_cd_firstfile(fcb=%08x,path=%08x,direntry=%08x)",
-    "dev_cd_nextfile(fcb=%08x,direntry=%08x)",
-    "dev_cd_chdir(fcb=%08x,path=%08x)",
-    "dev_card_open(fcb=%08x,path=%08x,accessmode=%08x)",
-    "dev_card_read(fcb=%08x,dst=%08x,len=%08x)",
-    "dev_card_write(fcb=%08x,src=%08x,len=%08x)",
-    "dev_card_close(fcb=%08x)",
-    "dev_card_firstfile(fcb=%08x,path=%08x,direntry=%08x)",
-    "dev_card_nextfile(fcb=%08x,direntry=%08x)",
-    "dev_card_erase(fcb=%08x,path=%08x)",
-    "dev_card_undelete(fcb=%08x,path=%08x)",
-    "dev_card_format(fcb=%08x)",
-    "dev_card_rename(fcb1=%08x,path=%08x)",
-    "card_clear_error(fcb=%08x) (?)",
-    "_bu_init()",
-    "_96_init()",
-    "_96_remove()",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "CdAsyncSeekL(src=%08x)",
-    "return 0",
-    "return 0",
-    "return 0",
-    "CdAsyncGetStatus(dst=%08x)",
-    "return 0",
-    "CdAsyncReadSector(count=%08x,dst=%08x,mode=%08x)",
-    "return 0",
-    "return 0",
-    "CdAsyncSetMode(mode=%08x)",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "CdromIoIrqFunc1()",
-    "CdromDmaIrqFunc1()",
-    "CdromIoIrqFunc2()",
-    "CdromDmaIrqFunc2()",
-    "CdromGetInt5errCode(dst1=%08x,dst2=%08x)",
-    "CdInitSubFunc()",
-    "AddCDROMDevice()",
-    "AddMemCardDevice()",
-    "AddDuartTtyDevice()",
-    "add_nullcon_driver()",
-    "SystemError()",
-    "SystemError()",
-    "SetConf(num_EvCB=%08x,num_TCB=%08x,stacktop=%08x)",
-    "GetConf(num_EvCB_dst=%08x,num_TCB_dst=%08x,stacktop_dst=%08x)",
-    "SetCdromIrqAutoAbort(type=%08x,flag=%08x)",
-    "SetMem(megabytes=%08x)",
-    "_boot()",
-    "SystemError(type=%08x,errorcode=%08x)",
-    "EnqueueCdIntr()",
-    "DequeueCdIntr()",
-    "CdGetLbn(filename=%08x)",
-    "CdReadSector(count=%08x,sector=%08x,buffer=%08x)",
-    "CdGetStatus()",
-    "bufs_cb_0()",
-    "bufs_cb_1()",
-    "bufs_cb_2()",
-    "bufs_cb_3()",
-    "_card_info(port=%08x)",
-    "_card_load(port=%08x)",
-    "_card_auto(flag=%08x)",
-    "bufs_cb_4()",
-    "card_write_test(port=%08x)",
-    "return 0",
-    "return 0",
-    "ioabort_raw(param=%08x)",
-    "return 0",
-    "GetSystemInfo(index=%08x)"
-};
-
-static const char* g_psx_cpu_b_kcall_symtable[] = {
-    "alloc_kernel_memory(size=%08x)",
-    "free_kernel_memory(buf=%08x)",
-    "init_timer(t=%08x,reload=%08x,flags=%08x)",
-    "get_timer(t=%08x)",
-    "enable_timer_irq(t=%08x)",
-    "disable_timer_irq(t=%08x)",
-    "restart_timer(t=%08x)",
-    "DeliverEvent(class=%08x, spec=%08x)",
-    "OpenEvent(class=%08x,spec=%08x,mode=%08x,func=%08x)",
-    "CloseEvent(event=%08x)",
-    "WaitEvent(event=%08x)",
-    "TestEvent(event=%08x)",
-    "EnableEvent(event=%08x)",
-    "DisableEvent(event=%08x)",
-    "OpenTh(reg_PC=%08x,reg_SP_FP=%08x,reg_GP=%08x)",
-    "CloseTh(handle=%08x)",
-    "ChangeTh(handle=%08x)",
-    "jump_to_00000000h()",
-    "InitPAD2(buf1=%08x,siz1=%08x,buf2=%08x,siz2=%08x)",
-    "StartPAD2()",
-    "StopPAD2()",
-    "PAD_init2(type=%08x,button_dest=%08x,unused=%08x,unused=%08x)",
-    "PAD_dr()",
-    "ReturnFromException()",
-    "ResetEntryInt()",
-    "HookEntryInt(addr=%08x)",
-    "SystemError()",
-    "SystemError()",
-    "SystemError()",
-    "SystemError()",
-    "SystemError()",
-    "SystemError()",
-    "UnDeliverEvent(class=%08x,spec=%08x)",
-    "SystemError()",
-    "SystemError()",
-    "SystemError()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "SystemError()",
-    "SystemError()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "jump_to_00000000h()",
-    "open(filename=%08x,accessmode=%08x)",
-    "lseek(fd=%08x,offset=%08x,seektype=%08x)",
-    "read(fd=%08x,dst=%08x,length=%08x)",
-    "write(fd=%08x,src=%08x,length=%08x)",
-    "close(fd=%08x)",
-    "ioctl(fd=%08x,cmd=%08x,arg=%08x)",
-    "exit(exitcode=%08x)",
-    "isatty(fd=%08x)",
-    "getc(fd=%08x)",
-    "putc(char=%08x,fd=%08x)",
-    "getchar()",
-    "putchar(char=%08x)",
-    "gets(dst=%08x)",
-    "puts(src=%08x)",
-    "cd(name=%08x)",
-    "format(devicename=%08x)",
-    "firstfile2(filename=%08x,direntry=%08x)",
-    "nextfile(direntry=%08x)",
-    "rename(old_filename=%08x,new_filename=%08x)",
-    "erase(filename=%08x)",
-    "undelete(filename=%08x)",
-    "AddDrv(device_info=%08x)",
-    "DelDrv(device_name_lowercase=%08x)",
-    "PrintInstalledDevices()",
-    "InitCARD2(pad_enable=%08x)",
-    "StartCARD2()",
-    "StopCARD2()",
-    "_card_info_subfunc(port=%08x)",
-    "_card_write(port=%08x,sector=%08x,src=%08x)",
-    "_card_read(port=%08x,sector=%08x,dst=%08x)",
-    "_new_card()",
-    "Krom2RawAdd(shiftjis_code=%08x)",
-    "SystemError()",
-    "Krom2Offset(shiftjis_code=%08x)",
-    "_get_errno()",
-    "_get_error(fd=%08x)",
-    "GetC0Table()",
-    "GetB0Table()",
-    "_card_chan()",
-    "testdevice(devicename=%08x)",
-    "SystemError()",
-    "ChangeClearPAD(int=%08x)",
-    "_card_status(slot=%08x)",
-    "_card_wait(slot=%08x)"
-};
-
-static const char* g_psx_cpu_c_kcall_symtable[] = {
-    "EnqueueTimerAndVblankIrqs(priority=%08x)",
-    "EnqueueSyscallHandler(priority=%08x)",
-    "SysEnqIntRP(priority=%08x,struc=%08x)",
-    "SysDeqIntRP(priority=%08x,struc=%08x)",
-    "get_free_EvCB_slot()",
-    "get_free_TCB_slot()",
-    "ExceptionHandler()",
-    "InstallExceptionHandlers()",
-    "SysInitMemory(addr=%08x,size=%08x)",
-    "SysInitKernelVariables()",
-    "ChangeClearRCnt(t=%08x,flag=%08x)",
-    "SystemError()",
-    "InitDefInt(priority=%08x)",
-    "SetIrqAutoAck(irq=%08x,flag=%08x)",
-    "return 0",
-    "return 0",
-    "return 0",
-    "return 0",
-    "InstallDevices(ttyflag=%08x)",
-    "FlushStdInOutPut()",
-    "return 0",
-    "_cdevinput(circ=%08x,char=%08x)",
-    "_cdevscan()",
-    "_circgetc(circ=%08x)",
-    "_circputc(char=%08x,circ=%08x)",
-    "_ioabort(txt1=%08x,txt2=%08x)",
-    "set_card_find_mode(mode=%08x)",
-    "KernelRedirect(ttyflag=%08x)",
-    "AdjustA0Table()",
-    "get_card_find_mode()"
-};
-
-#ifdef CPU_TRACE
-#define TRACE_M(m) \
-    log_trace("%08x: %-7s $%s, %+i($%s)", cpu->pc-8, m, g_mips_cc_register_names[T], IMM16S, g_mips_cc_register_names[S])
-
-#define TRACE_I16S(m) \
-    log_trace("%08x: %-7s $%s, 0x%04x", cpu->pc-8, m, g_mips_cc_register_names[T], IMM16)
-
-#define TRACE_I16D(m) \
-    log_trace("%08x: %-7s $%s, $%s, 0x%04x", cpu->pc-8, m, g_mips_cc_register_names[T], g_mips_cc_register_names[S], IMM16)
-
-#define TRACE_I5D(m) \
-    log_trace("%08x: %-7s $%s, $%s, %u", cpu->pc-8, m, g_mips_cc_register_names[D], g_mips_cc_register_names[T], IMM5)
-
-#define TRACE_I26(m) \
-    log_trace("%08x: %-7s 0x%07x", cpu->pc-8, m, ((cpu->pc & 0xf0000000) | (IMM26 << 2)))
-
-#define TRACE_RT(m) \
-    log_trace("%08x: %-7s $%s, $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[D], g_mips_cc_register_names[S], g_mips_cc_register_names[T])
-
-#define TRACE_C0M(m) \
-    log_trace("%08x: %-7s $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[T], g_mips_cop0_register_names[D])
-
-#define TRACE_C2M(m) \
-    log_trace("%08x: %-7s $%s, $cop2_r%u", cpu->pc-8, m, g_mips_cc_register_names[T], D)
-
-#define TRACE_C2MC(m) \
-    log_trace("%08x: %-7s $%s, $cop2_r%u", cpu->pc-8, m, g_mips_cc_register_names[T], D + 32)
-
-#define TRACE_B(m) \
-    log_trace("%08x: %-7s $%s, $%s, %-i", cpu->pc-8, m, g_mips_cc_register_names[S], g_mips_cc_register_names[T], IMM16S << 2)
-
-#define TRACE_RS(m) \
-    log_trace("%08x: %-7s $%s", cpu->pc-8, m, g_mips_cc_register_names[S])
-
-#define TRACE_MTF(m) \
-    log_trace("%08x: %-7s $%s", cpu->pc-8, m, g_mips_cc_register_names[D])
-
-#define TRACE_RD(m) \
-    log_trace("%08x: %-7s $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[D], g_mips_cc_register_names[S])
-
-#define TRACE_MD(m) \
-    log_trace("%08x: %-7s $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[S], g_mips_cc_register_names[T]);
-
-#define TRACE_I20(m) \
-    log_trace("%08x: %-7s 0x%05x", cpu->pc-8, m, CMT);
-
-#define TRACE_N(m) \
-    log_trace("%08x: %-7s", cpu->pc-8, m);
-#else
-#define TRACE_M(m)
-#define TRACE_I16S(m)
-#define TRACE_I16D(m)
-#define TRACE_I5D(m)
-#define TRACE_I26(m)
-#define TRACE_RT(m)
-#define TRACE_C0M(m)
-#define TRACE_C2M(m)
-#define TRACE_C2MC(m)
-#define TRACE_B(m)
-#define TRACE_RS(m)
-#define TRACE_MTF(m)
-#define TRACE_RD(m)
-#define TRACE_MD(m)
-#define TRACE_I20(m)
-#define TRACE_N(m)
-#endif
-
 #define DO_PENDING_LOAD \
     cpu->r[cpu->load_d] = cpu->load_v; \
     R_R0 = 0; \
@@ -557,62 +176,14 @@
     cpu->load_v = 0xffffffff; \
     cpu->load_d = 0;
 
-#ifdef CPU_TRACE
-#define DEBUG_ALL \
-    log_fatal("r0=%08x at=%08x v0=%08x v1=%08x", cpu->r[0] , cpu->r[1] , cpu->r[2] , cpu->r[3] ); \
-    log_fatal("a0=%08x a1=%08x a2=%08x a3=%08x", cpu->r[4] , cpu->r[5] , cpu->r[6] , cpu->r[7] ); \
-    log_fatal("t0=%08x t1=%08x t2=%08x t3=%08x", cpu->r[8] , cpu->r[9] , cpu->r[10], cpu->r[11]); \
-    log_fatal("t4=%08x t5=%08x t6=%08x t7=%08x", cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15]); \
-    log_fatal("s0=%08x s1=%08x s2=%08x s3=%08x", cpu->r[16], cpu->r[17], cpu->r[18], cpu->r[19]); \
-    log_fatal("s4=%08x s5=%08x s6=%08x s7=%08x", cpu->r[20], cpu->r[21], cpu->r[22], cpu->r[23]); \
-    log_fatal("t8=%08x t9=%08x k0=%08x k1=%08x", cpu->r[24], cpu->r[25], cpu->r[26], cpu->r[27]); \
-    log_fatal("gp=%08x sp=%08x fp=%08x ra=%08x", cpu->r[28], cpu->r[29], cpu->r[30], cpu->r[31]); \
-    log_fatal("pc=%08x hi=%08x lo=%08x l:%s=%08x", cpu->pc, cpu->hi, cpu->lo, g_mips_cc_register_names[cpu->load_d], cpu->load_v); \
-    exit(1)
-
-const char* g_mips_cop0_register_names[] = {
-    "cop0_r0",
-    "cop0_r1",
-    "cop0_r2",
-    "cop0_bpc",
-    "cop0_r4",
-    "cop0_bda",
-    "cop0_jumpdest",
-    "cop0_dcic",
-    "cop0_badvaddr",
-    "cop0_bdam",
-    "cop0_r10",
-    "cop0_bpcm",
-    "cop0_sr",
-    "cop0_cause",
-    "cop0_epc",
-    "cop0_prid"
-};
-
-static const char* g_mips_cc_register_names[] = {
-    "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
-    "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
-    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
-    "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
-};
-
-static const char* g_psx_cpu_syscall_function_symbol_table[] = {
-    "NoFunction",
-    "EnterCriticalSection",
-    "ExitCriticalSection",
-    "ChangeThreadSubFunction"
-    // DeliverEvent (invalid)
-};
-#endif
-
 #define SE8(v) ((int32_t)((int8_t)v))
 #define SE16(v) ((int32_t)((int16_t)v))
 
-#define BRANCH(offset) \
+#define BRANCH(offset) { \
     cpu->next_pc = cpu->next_pc + (offset); \
     cpu->next_pc = cpu->next_pc - 4; \
     cpu->branch = 1; \
-    cpu->branch_taken = 1;
+    cpu->branch_taken = 1; }
 
 void cpu_a_kcall_hook(psx_cpu_t* cpu) {
     switch (cpu->r[9]) {
@@ -682,7 +253,11 @@
 }
 
 void psx_cpu_load_state(psx_cpu_t* cpu, FILE* file) {
-    fread((char*)cpu, sizeof(*cpu) - sizeof(psx_bus_t*), 1, file);
+    if (!fread((char*)cpu, sizeof(*cpu) - sizeof(psx_bus_t*), 1, file)) {
+        perror("Error reading CPU state");
+
+        exit(1);
+    }
 }
 
 void psx_cpu_init(psx_cpu_t* cpu, psx_bus_t* bus) {
@@ -702,69 +277,19 @@
 void psx_cpu_cycle(psx_cpu_t* cpu) {
     cpu->last_cycles = 0;
 
-    // if ((cpu->pc & 0x3fffffff) == 0x000000a4) {
-    //     if (cpu->r[9] == 0x2f)
-    //         goto no_putchar;
+    if ((cpu->pc & 0x3fffffff) == 0x000000b4)
+        if (cpu->b_function_hook)
+            cpu->b_function_hook(cpu);
 
-    //     char buf[256];
-
-    //     sprintf(buf, g_psx_cpu_a_kcall_symtable[cpu->r[9]],
-    //         cpu->r[4],
-    //         cpu->r[5],
-    //         cpu->r[6],
-    //         cpu->r[7]
-    //     );
-    //     log_set_quiet(0);
-    //     log_fatal("A(%02x) %s", cpu->r[9], buf);
-    //     log_set_quiet(1);
-    // }
-
-    if ((cpu->pc & 0x3fffffff) == 0x000000b4) {
-        if (cpu->b_function_hook) cpu->b_function_hook(cpu);
-
-        // if ((cpu->r[9] == 0x3b) || (cpu->r[9] == 0x3d) || (cpu->r[9] == 0x3f) || (cpu->r[9] == 0x0b) || (cpu->r[9] == 0x17))
-        //     goto no_putchar;
-
-        // char buf[256];
-
-        // sprintf(buf, g_psx_cpu_b_kcall_symtable[cpu->r[9]],
-        //     cpu->r[4],
-        //     cpu->r[5],
-        //     cpu->r[6],
-        //     cpu->r[7]
-        // );
-        // log_set_quiet(0);
-        // log_fatal("B(%02x) %s", cpu->r[9], buf);
-        // log_set_quiet(1);
-    }
-
-    no_putchar:
-
-    // if ((cpu->pc & 0x3fffffff) == 0x000000c4) {
-    //     char buf[256];
-
-    //     sprintf(buf, g_psx_cpu_c_kcall_symtable[cpu->r[9]],
-    //         cpu->r[4],
-    //         cpu->r[5],
-    //         cpu->r[6],
-    //         cpu->r[7]
-    //     );
-    //     log_set_quiet(0);
-    //     log_fatal("C(%02x) %s", cpu->r[9], buf);
-    //     log_set_quiet(1);
-    // }
-
     cpu->saved_pc = cpu->pc;
     cpu->delay_slot = cpu->branch;
     cpu->branch = 0;
     cpu->branch_taken = 0;
 
-    if (cpu->saved_pc & 3) {
+    if (cpu->saved_pc & 3)
         psx_cpu_exception(cpu, CAUSE_ADEL);
-    }
 
     cpu->opcode = psx_bus_read32(cpu->bus, cpu->pc);
-    cpu->last_cycles = psx_bus_get_access_cycles(cpu->bus);
 
     cpu->pc = cpu->next_pc;
     cpu->next_pc += 4;
@@ -777,10 +302,8 @@
 
     g_psx_cpu_primary_table[OP](cpu);
 
-    // Discard instruction access cycles
-    psx_bus_get_access_cycles(cpu->bus);
-
-    cpu->last_cycles = 1;
+    // Not even trying to get precise timings here
+    cpu->last_cycles = 2;
     cpu->total_cycles += cpu->last_cycles;
 
     cpu->r[0] = 0;
@@ -787,12 +310,11 @@
 }
 
 int psx_cpu_check_irq(psx_cpu_t* cpu) {
-    return (cpu->cop0_r[COP0_SR] & SR_IEC) && (cpu->cop0_r[COP0_SR] & cpu->cop0_r[COP0_CAUSE] & 0x00000700);
+    return (cpu->cop0_r[COP0_SR] & SR_IEC) &&
+           (cpu->cop0_r[COP0_SR] & cpu->cop0_r[COP0_CAUSE] & 0x00000700);
 }
 
 void psx_cpu_exception(psx_cpu_t* cpu, uint32_t cause) {
-    cpu->cop0_r[COP0_CAUSE] &= 0x0000ff00;
-
     // Set excode and clear 3 LSBs
     cpu->cop0_r[COP0_CAUSE] &= 0xffffff80;
     cpu->cop0_r[COP0_CAUSE] |= cause;
@@ -804,9 +326,8 @@
         cpu->cop0_r[COP0_CAUSE] |= 0x80000000;
     }
 
-    if ((cause == CAUSE_INT) && (cpu->cop0_r[COP0_EPC] & 0xfe000000) == 0x4a000000) {
+    if ((cause == CAUSE_INT) && ((cpu->cop0_r[COP0_EPC] & 0xfe000000) == 0x4a000000))
         cpu->cop0_r[COP0_EPC] += 4;
-    }
 
     // Do exception stack push
     uint32_t mode = cpu->cop0_r[COP0_SR] & 0x3f;
@@ -816,6 +337,7 @@
 
     // Set PC to the vector selected on BEV
     cpu->pc = (cpu->cop0_r[COP0_SR] & SR_BEV) ? 0xbfc00180 : 0x80000080;
+
     cpu->next_pc = cpu->pc + 4;
 }
 
@@ -849,9 +371,8 @@
 
     DO_PENDING_LOAD;
 
-    if ((int32_t)s < (int32_t)0) {
+    if ((int32_t)s < (int32_t)0)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_bgez(psx_cpu_t* cpu) {
@@ -861,9 +382,8 @@
 
     DO_PENDING_LOAD;
 
-    if ((int32_t)s >= (int32_t)0) {
+    if ((int32_t)s >= (int32_t)0)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_bltzal(psx_cpu_t* cpu) {
@@ -875,9 +395,8 @@
 
     R_RA = cpu->next_pc;
 
-    if ((int32_t)s < (int32_t)0) {
+    if ((int32_t)s < (int32_t)0)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_bgezal(psx_cpu_t* cpu) {
@@ -889,9 +408,8 @@
 
     R_RA = cpu->next_pc;
 
-    if ((int32_t)s >= (int32_t)0) {
+    if ((int32_t)s >= (int32_t)0)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_j(psx_cpu_t* cpu) {
@@ -927,9 +445,8 @@
 
     DO_PENDING_LOAD;
 
-    if (s == t) {
+    if (s == t)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_bne(psx_cpu_t* cpu) {
@@ -943,9 +460,8 @@
 
     DO_PENDING_LOAD;
 
-    if (s != t) {
+    if (s != t)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_blez(psx_cpu_t* cpu) {
@@ -958,9 +474,8 @@
 
     DO_PENDING_LOAD;
 
-    if ((int32_t)s <= (int32_t)0) {
+    if ((int32_t)s <= (int32_t)0)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_bgtz(psx_cpu_t* cpu) {
@@ -973,9 +488,8 @@
 
     DO_PENDING_LOAD;
 
-    if ((int32_t)s > (int32_t)0) {
+    if ((int32_t)s > (int32_t)0)
         BRANCH(IMM16S << 2);
-    }
 }
 
 void psx_cpu_i_addi(psx_cpu_t* cpu) {
--- /dev/null
+++ b/psx/cpu_debug.h
@@ -1,0 +1,428 @@
+#ifdef CPU_TRACE
+
+static const char* g_psx_cpu_a_kcall_symtable[] = {
+    "open(filename=%08x,accessmode=%08x)",
+    "lseek(fd=%08x,offset=%08x,seektype=%08x)",
+    "read(fd=%08x,dst=%08x,length=%08x)",
+    "write(fd=%08x,src=%08x,length=%08x)",
+    "close(fd=%08x)",
+    "ioctl(fd=%08x,cmd=%08x,arg=%08x)",
+    "exit(exitcode=%08x)",
+    "isatty(fd=%08x)",
+    "getc(fd=%08x)",
+    "putc(char=%08x,fd=%08x)",
+    "todigit(char=%08x)",
+    "atof(src=%08x)",
+    "strtoul(src=%08x,src_end=%08x,base=%08x)",
+    "strtol(src=%08x,src_end=%08x,base=%08x)",
+    "abs(val=%08x)",
+    "labs(val=%08x)",
+    "atoi(src=%08x)",
+    "atol(src=%08x)",
+    "atob(src=%08x,num_dst=%08x)",
+    "setjmp(buf=%08x)",
+    "longjmp(buf=%08x,param=%08x)",
+    "strcat(dst=%08x,src=%08x)",
+    "strncat(dst=%08x,src=%08x,maxlen=%08x)",
+    "strcmp(str1=%08x,str2=%08x)",
+    "strncmp(str1=%08x,str2=%08x,maxlen=%08x)",
+    "strcpy(dst=%08x,src=%08x)",
+    "strncpy(dst=%08x,src=%08x,maxlen=%08x)",
+    "strlen(src=%08x)",
+    "index(src=%08x,char=%08x)",
+    "rindex(src=%08x,char=%08x)",
+    "strchr(src=%08x,char=%08x)",
+    "strrchr(src=%08x,char=%08x)",
+    "strpbrk(src=%08x,list=%08x)",
+    "strspn(src=%08x,list=%08x)",
+    "strcspn(src=%08x,list=%08x)",
+    "strtok(src=%08x,list=%08x)",
+    "strstr(str=%08x,substr=%08x)",
+    "toupper(char=%08x)",
+    "tolower(char=%08x)",
+    "bcopy(src=%08x,dst=%08x,len=%08x)",
+    "bzero(dst=%08x,len=%08x)",
+    "bcmp(ptr1=%08x,ptr2=%08x,len=%08x)",
+    "memcpy(dst=%08x,src=%08x,len=%08x)",
+    "memset(dst=%08x,fillbyte=%08x,len=%08x)",
+    "memmove(dst=%08x,src=%08x,len=%08x)",
+    "memcmp(src1=%08x,src2=%08x,len=%08x)",
+    "memchr(src=%08x,scanbyte=%08x,len=%08x)",
+    "rand()",
+    "srand(seed=%08x)",
+    "qsort(base=%08x,nel=%08x,width=%08x,callback=%08x)",
+    "strtod(src=%08x,src_end=%08x)",
+    "malloc(size=%08x)",
+    "free(buf=%08x)",
+    "lsearch(key=%08x,base=%08x,nel=%08x,width=%08x,callback=%08x)",
+    "bsearch(key=%08x,base=%08x,nel=%08x,width=%08x,callback=%08x)",
+    "calloc(sizx=%08x,sizy=%08x)",
+    "realloc(old_buf=%08x,new_siz=%08x)",
+    "InitHeap(addr=%08x,size=%08x)",
+    "_exit(exitcode=%08x)",
+    "getchar()",
+    "putchar(char=%08x)",
+    "gets(dst=%08x)",
+    "puts(src=%08x)",
+    "printf(txt=%08x,param1=%08x,param2=%08x,etc.=%08x)",
+    "SystemErrorUnresolvedException()",
+    "LoadTest(filename=%08x,headerbuf=%08x)",
+    "Load(filename=%08x,headerbuf=%08x)",
+    "Exec(headerbuf=%08x,param1=%08x,param2=%08x)",
+    "FlushCache()",
+    "init_a0_b0_c0_vectors()",
+    "GPU_dw(Xdst=%08x,Ydst=%08x,Xsiz=%08x,Ysiz=%08x,src=%08x)",
+    "gpu_send_dma(Xdst=%08x,Ydst=%08x,Xsiz=%08x,Ysiz=%08x,src=%08x)",
+    "SendGP1Command(gp1cmd=%08x)",
+    "GPU_cw(gp0cmd=%08x)",
+    "GPU_cwp(src=%08x,num=%08x)",
+    "send_gpu_linked_list(src=%08x)",
+    "gpu_abort_dma()",
+    "GetGPUStatus()",
+    "gpu_sync()",
+    "SystemError()",
+    "SystemError()",
+    "LoadExec(filename=%08x,stackbase=%08x,stackoffset=%08x)",
+    "GetSysSp()",
+    "SystemError()",
+    "_96_init()",
+    "_bu_init()",
+    "_96_remove()",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "dev_tty_init()",
+    "dev_tty_open(fcb=%08x, (unused)path=%08x,accessmode=%08x)",
+    "dev_tty_in_out(fcb=%08x,cmd=%08x)",
+    "dev_tty_ioctl(fcb=%08x,cmd=%08x,arg=%08x)",
+    "dev_cd_open(fcb=%08x,path=%08x,accessmode=%08x)",
+    "dev_cd_read(fcb=%08x,dst=%08x,len=%08x)",
+    "dev_cd_close(fcb=%08x)",
+    "dev_cd_firstfile(fcb=%08x,path=%08x,direntry=%08x)",
+    "dev_cd_nextfile(fcb=%08x,direntry=%08x)",
+    "dev_cd_chdir(fcb=%08x,path=%08x)",
+    "dev_card_open(fcb=%08x,path=%08x,accessmode=%08x)",
+    "dev_card_read(fcb=%08x,dst=%08x,len=%08x)",
+    "dev_card_write(fcb=%08x,src=%08x,len=%08x)",
+    "dev_card_close(fcb=%08x)",
+    "dev_card_firstfile(fcb=%08x,path=%08x,direntry=%08x)",
+    "dev_card_nextfile(fcb=%08x,direntry=%08x)",
+    "dev_card_erase(fcb=%08x,path=%08x)",
+    "dev_card_undelete(fcb=%08x,path=%08x)",
+    "dev_card_format(fcb=%08x)",
+    "dev_card_rename(fcb1=%08x,path=%08x)",
+    "card_clear_error(fcb=%08x) (?)",
+    "_bu_init()",
+    "_96_init()",
+    "_96_remove()",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "CdAsyncSeekL(src=%08x)",
+    "return 0",
+    "return 0",
+    "return 0",
+    "CdAsyncGetStatus(dst=%08x)",
+    "return 0",
+    "CdAsyncReadSector(count=%08x,dst=%08x,mode=%08x)",
+    "return 0",
+    "return 0",
+    "CdAsyncSetMode(mode=%08x)",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "CdromIoIrqFunc1()",
+    "CdromDmaIrqFunc1()",
+    "CdromIoIrqFunc2()",
+    "CdromDmaIrqFunc2()",
+    "CdromGetInt5errCode(dst1=%08x,dst2=%08x)",
+    "CdInitSubFunc()",
+    "AddCDROMDevice()",
+    "AddMemCardDevice()",
+    "AddDuartTtyDevice()",
+    "add_nullcon_driver()",
+    "SystemError()",
+    "SystemError()",
+    "SetConf(num_EvCB=%08x,num_TCB=%08x,stacktop=%08x)",
+    "GetConf(num_EvCB_dst=%08x,num_TCB_dst=%08x,stacktop_dst=%08x)",
+    "SetCdromIrqAutoAbort(type=%08x,flag=%08x)",
+    "SetMem(megabytes=%08x)",
+    "_boot()",
+    "SystemError(type=%08x,errorcode=%08x)",
+    "EnqueueCdIntr()",
+    "DequeueCdIntr()",
+    "CdGetLbn(filename=%08x)",
+    "CdReadSector(count=%08x,sector=%08x,buffer=%08x)",
+    "CdGetStatus()",
+    "bufs_cb_0()",
+    "bufs_cb_1()",
+    "bufs_cb_2()",
+    "bufs_cb_3()",
+    "_card_info(port=%08x)",
+    "_card_load(port=%08x)",
+    "_card_auto(flag=%08x)",
+    "bufs_cb_4()",
+    "card_write_test(port=%08x)",
+    "return 0",
+    "return 0",
+    "ioabort_raw(param=%08x)",
+    "return 0",
+    "GetSystemInfo(index=%08x)"
+};
+
+static const char* g_psx_cpu_b_kcall_symtable[] = {
+    "alloc_kernel_memory(size=%08x)",
+    "free_kernel_memory(buf=%08x)",
+    "init_timer(t=%08x,reload=%08x,flags=%08x)",
+    "get_timer(t=%08x)",
+    "enable_timer_irq(t=%08x)",
+    "disable_timer_irq(t=%08x)",
+    "restart_timer(t=%08x)",
+    "DeliverEvent(class=%08x, spec=%08x)",
+    "OpenEvent(class=%08x,spec=%08x,mode=%08x,func=%08x)",
+    "CloseEvent(event=%08x)",
+    "WaitEvent(event=%08x)",
+    "TestEvent(event=%08x)",
+    "EnableEvent(event=%08x)",
+    "DisableEvent(event=%08x)",
+    "OpenTh(reg_PC=%08x,reg_SP_FP=%08x,reg_GP=%08x)",
+    "CloseTh(handle=%08x)",
+    "ChangeTh(handle=%08x)",
+    "jump_to_00000000h()",
+    "InitPAD2(buf1=%08x,siz1=%08x,buf2=%08x,siz2=%08x)",
+    "StartPAD2()",
+    "StopPAD2()",
+    "PAD_init2(type=%08x,button_dest=%08x,unused=%08x,unused=%08x)",
+    "PAD_dr()",
+    "ReturnFromException()",
+    "ResetEntryInt()",
+    "HookEntryInt(addr=%08x)",
+    "SystemError()",
+    "SystemError()",
+    "SystemError()",
+    "SystemError()",
+    "SystemError()",
+    "SystemError()",
+    "UnDeliverEvent(class=%08x,spec=%08x)",
+    "SystemError()",
+    "SystemError()",
+    "SystemError()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "SystemError()",
+    "SystemError()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "jump_to_00000000h()",
+    "open(filename=%08x,accessmode=%08x)",
+    "lseek(fd=%08x,offset=%08x,seektype=%08x)",
+    "read(fd=%08x,dst=%08x,length=%08x)",
+    "write(fd=%08x,src=%08x,length=%08x)",
+    "close(fd=%08x)",
+    "ioctl(fd=%08x,cmd=%08x,arg=%08x)",
+    "exit(exitcode=%08x)",
+    "isatty(fd=%08x)",
+    "getc(fd=%08x)",
+    "putc(char=%08x,fd=%08x)",
+    "getchar()",
+    "putchar(char=%08x)",
+    "gets(dst=%08x)",
+    "puts(src=%08x)",
+    "cd(name=%08x)",
+    "format(devicename=%08x)",
+    "firstfile2(filename=%08x,direntry=%08x)",
+    "nextfile(direntry=%08x)",
+    "rename(old_filename=%08x,new_filename=%08x)",
+    "erase(filename=%08x)",
+    "undelete(filename=%08x)",
+    "AddDrv(device_info=%08x)",
+    "DelDrv(device_name_lowercase=%08x)",
+    "PrintInstalledDevices()",
+    "InitCARD2(pad_enable=%08x)",
+    "StartCARD2()",
+    "StopCARD2()",
+    "_card_info_subfunc(port=%08x)",
+    "_card_write(port=%08x,sector=%08x,src=%08x)",
+    "_card_read(port=%08x,sector=%08x,dst=%08x)",
+    "_new_card()",
+    "Krom2RawAdd(shiftjis_code=%08x)",
+    "SystemError()",
+    "Krom2Offset(shiftjis_code=%08x)",
+    "_get_errno()",
+    "_get_error(fd=%08x)",
+    "GetC0Table()",
+    "GetB0Table()",
+    "_card_chan()",
+    "testdevice(devicename=%08x)",
+    "SystemError()",
+    "ChangeClearPAD(int=%08x)",
+    "_card_status(slot=%08x)",
+    "_card_wait(slot=%08x)"
+};
+
+static const char* g_psx_cpu_c_kcall_symtable[] = {
+    "EnqueueTimerAndVblankIrqs(priority=%08x)",
+    "EnqueueSyscallHandler(priority=%08x)",
+    "SysEnqIntRP(priority=%08x,struc=%08x)",
+    "SysDeqIntRP(priority=%08x,struc=%08x)",
+    "get_free_EvCB_slot()",
+    "get_free_TCB_slot()",
+    "ExceptionHandler()",
+    "InstallExceptionHandlers()",
+    "SysInitMemory(addr=%08x,size=%08x)",
+    "SysInitKernelVariables()",
+    "ChangeClearRCnt(t=%08x,flag=%08x)",
+    "SystemError()",
+    "InitDefInt(priority=%08x)",
+    "SetIrqAutoAck(irq=%08x,flag=%08x)",
+    "return 0",
+    "return 0",
+    "return 0",
+    "return 0",
+    "InstallDevices(ttyflag=%08x)",
+    "FlushStdInOutPut()",
+    "return 0",
+    "_cdevinput(circ=%08x,char=%08x)",
+    "_cdevscan()",
+    "_circgetc(circ=%08x)",
+    "_circputc(char=%08x,circ=%08x)",
+    "_ioabort(txt1=%08x,txt2=%08x)",
+    "set_card_find_mode(mode=%08x)",
+    "KernelRedirect(ttyflag=%08x)",
+    "AdjustA0Table()",
+    "get_card_find_mode()"
+};
+
+#define TRACE_M(m) \
+    log_trace("%08x: %-7s $%s, %+i($%s)", cpu->pc-8, m, g_mips_cc_register_names[T], IMM16S, g_mips_cc_register_names[S])
+
+#define TRACE_I16S(m) \
+    log_trace("%08x: %-7s $%s, 0x%04x", cpu->pc-8, m, g_mips_cc_register_names[T], IMM16)
+
+#define TRACE_I16D(m) \
+    log_trace("%08x: %-7s $%s, $%s, 0x%04x", cpu->pc-8, m, g_mips_cc_register_names[T], g_mips_cc_register_names[S], IMM16)
+
+#define TRACE_I5D(m) \
+    log_trace("%08x: %-7s $%s, $%s, %u", cpu->pc-8, m, g_mips_cc_register_names[D], g_mips_cc_register_names[T], IMM5)
+
+#define TRACE_I26(m) \
+    log_trace("%08x: %-7s 0x%07x", cpu->pc-8, m, ((cpu->pc & 0xf0000000) | (IMM26 << 2)))
+
+#define TRACE_RT(m) \
+    log_trace("%08x: %-7s $%s, $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[D], g_mips_cc_register_names[S], g_mips_cc_register_names[T])
+
+#define TRACE_C0M(m) \
+    log_trace("%08x: %-7s $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[T], g_mips_cop0_register_names[D])
+
+#define TRACE_C2M(m) \
+    log_trace("%08x: %-7s $%s, $cop2_r%u", cpu->pc-8, m, g_mips_cc_register_names[T], D)
+
+#define TRACE_C2MC(m) \
+    log_trace("%08x: %-7s $%s, $cop2_r%u", cpu->pc-8, m, g_mips_cc_register_names[T], D + 32)
+
+#define TRACE_B(m) \
+    log_trace("%08x: %-7s $%s, $%s, %-i", cpu->pc-8, m, g_mips_cc_register_names[S], g_mips_cc_register_names[T], IMM16S << 2)
+
+#define TRACE_RS(m) \
+    log_trace("%08x: %-7s $%s", cpu->pc-8, m, g_mips_cc_register_names[S])
+
+#define TRACE_MTF(m) \
+    log_trace("%08x: %-7s $%s", cpu->pc-8, m, g_mips_cc_register_names[D])
+
+#define TRACE_RD(m) \
+    log_trace("%08x: %-7s $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[D], g_mips_cc_register_names[S])
+
+#define TRACE_MD(m) \
+    log_trace("%08x: %-7s $%s, $%s", cpu->pc-8, m, g_mips_cc_register_names[S], g_mips_cc_register_names[T]);
+
+#define TRACE_I20(m) \
+    log_trace("%08x: %-7s 0x%05x", cpu->pc-8, m, CMT);
+
+#define TRACE_N(m) \
+    log_trace("%08x: %-7s", cpu->pc-8, m);
+
+#define DEBUG_ALL \
+    log_fatal("r0=%08x at=%08x v0=%08x v1=%08x", cpu->r[0] , cpu->r[1] , cpu->r[2] , cpu->r[3] ); \
+    log_fatal("a0=%08x a1=%08x a2=%08x a3=%08x", cpu->r[4] , cpu->r[5] , cpu->r[6] , cpu->r[7] ); \
+    log_fatal("t0=%08x t1=%08x t2=%08x t3=%08x", cpu->r[8] , cpu->r[9] , cpu->r[10], cpu->r[11]); \
+    log_fatal("t4=%08x t5=%08x t6=%08x t7=%08x", cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15]); \
+    log_fatal("s0=%08x s1=%08x s2=%08x s3=%08x", cpu->r[16], cpu->r[17], cpu->r[18], cpu->r[19]); \
+    log_fatal("s4=%08x s5=%08x s6=%08x s7=%08x", cpu->r[20], cpu->r[21], cpu->r[22], cpu->r[23]); \
+    log_fatal("t8=%08x t9=%08x k0=%08x k1=%08x", cpu->r[24], cpu->r[25], cpu->r[26], cpu->r[27]); \
+    log_fatal("gp=%08x sp=%08x fp=%08x ra=%08x", cpu->r[28], cpu->r[29], cpu->r[30], cpu->r[31]); \
+    log_fatal("pc=%08x hi=%08x lo=%08x l:%s=%08x", cpu->pc, cpu->hi, cpu->lo, g_mips_cc_register_names[cpu->load_d], cpu->load_v); \
+    exit(1)
+
+const char* g_mips_cop0_register_names[] = {
+    "cop0_r0",
+    "cop0_r1",
+    "cop0_r2",
+    "cop0_bpc",
+    "cop0_r4",
+    "cop0_bda",
+    "cop0_jumpdest",
+    "cop0_dcic",
+    "cop0_badvaddr",
+    "cop0_bdam",
+    "cop0_r10",
+    "cop0_bpcm",
+    "cop0_sr",
+    "cop0_cause",
+    "cop0_epc",
+    "cop0_prid"
+};
+
+static const char* g_mips_cc_register_names[] = {
+    "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+    "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+    "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
+};
+
+static const char* g_psx_cpu_syscall_function_symbol_table[] = {
+    "NoFunction",
+    "EnterCriticalSection",
+    "ExitCriticalSection",
+    "ChangeThreadSubFunction"
+    // DeliverEvent (invalid)
+};
+
+#else
+#define TRACE_M(m)
+#define TRACE_I16S(m)
+#define TRACE_I16D(m)
+#define TRACE_I5D(m)
+#define TRACE_I26(m)
+#define TRACE_RT(m)
+#define TRACE_C0M(m)
+#define TRACE_C2M(m)
+#define TRACE_C2MC(m)
+#define TRACE_B(m)
+#define TRACE_RS(m)
+#define TRACE_MTF(m)
+#define TRACE_RD(m)
+#define TRACE_MD(m)
+#define TRACE_I20(m)
+#define TRACE_N(m)
+#endif
\ No newline at end of file
--- a/psx/dev/bios.c
+++ b/psx/dev/bios.c
@@ -28,7 +28,11 @@
         exit(1);
     }
 
-    fread(bios->buf, 1, PSX_BIOS_SIZE, file);
+    if (!fread(bios->buf, 1, PSX_BIOS_SIZE, file)) {
+        perror("Error reading BIOS file");
+
+        exit(1);
+    }
 
     log_info("Loaded BIOS file \"%s\"", path);
 
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -390,7 +390,9 @@
             if (cdrom->mode & MODE_XA_ADPCM) {
                 cdrom->xa_playing = 1;
 
-                printf("Play XA-ADPCM encoded song at %02u:%02u:%02x, filter=%u, file=%02x, channel=%02x\n",
+                SET_BITS(status, STAT_ADPBUSY_MASK, STAT_ADPBUSY_MASK);
+
+                printf("Play XA-ADPCM encoded song at %02u:%02u:%02u, filter=%u, file=%02x, channel=%02x\n",
                     cdrom->xa_msf.m,
                     cdrom->xa_msf.s,
                     cdrom->xa_msf.f,
@@ -590,6 +592,8 @@
             cdrom->cdda_playing = 0;
             cdrom->xa_playing = 0;
 
+            SET_BITS(status, STAT_ADPBUSY_MASK, 0);
+
             cdrom->irq_delay = DELAY_1MS;
             cdrom->state = CD_STATE_SEND_RESP1;
             cdrom->delayed_command = CDL_PAUSE;
@@ -700,8 +704,8 @@
                 return;
             }
 
-            cdrom->xa_file = PFIFO_POP;
             cdrom->xa_channel = PFIFO_POP;
+            cdrom->xa_file = PFIFO_POP;
 
             cdrom->irq_delay = DELAY_1MS;
             cdrom->delayed_command = CDL_SETFILTER;
@@ -836,7 +840,7 @@
             cdrom->delayed_command = CDL_SETSESSION;
             cdrom->state = CD_STATE_SEND_RESP1;
 
-            PFIFO_POP;
+            cdrom->pfifo_index = 0;
         } break;
 
         case CD_STATE_SEND_RESP1: {
@@ -1188,7 +1192,9 @@
             if (cdrom->mode & MODE_XA_ADPCM) {
                 cdrom->xa_playing = 1;
 
-                printf("Play XA-ADPCM encoded song at %02u:%02u:%02x, filter=%u, file=%02x, channel=%02x\n",
+                SET_BITS(status, STAT_ADPBUSY_MASK, STAT_ADPBUSY_MASK);
+
+                printf("Play XA-ADPCM encoded song at %02u:%02u:%02u, filter=%u, file=%02x, channel=%02x\n",
                     cdrom->xa_msf.m,
                     cdrom->xa_msf.s,
                     cdrom->xa_msf.f,
@@ -1196,6 +1202,9 @@
                     cdrom->xa_file,
                     cdrom->xa_channel
                 );
+
+                cdrom->state = CD_STATE_RECV_CMD;
+                cdrom->delayed_command = CDL_NONE;
             }
 
             int err = psx_disc_seek(cdrom->disc, msf);
@@ -1309,8 +1318,8 @@
     cdrom_cmd_stop,
     cdrom_cmd_pause,
     cdrom_cmd_init,
-    cdrom_cmd_unimplemented,
     cdrom_cmd_unmute,
+    cdrom_cmd_unmute,
     cdrom_cmd_setfilter,
     cdrom_cmd_setmode,
     cdrom_cmd_getparam,
@@ -1355,23 +1364,11 @@
     if (!cdrom->dfifo_full)
         return 0;
 
-    // int data_sector_size = cdrom->dfifo[0x12] & MODE_SECTOR_SIZE;
     int sector_size_bit = cdrom->mode & MODE_SECTOR_SIZE;
 
-    uint8_t m = cdrom->dfifo[0x0c];
-    uint8_t s = cdrom->dfifo[0x0d];
-    uint8_t f = cdrom->dfifo[0x0e];
-
     uint32_t sector_size = sector_size_bit ? 0x924 : 0x800;
     uint32_t offset = sector_size_bit ? 12 : 24;
 
-    // if ((m == 0) && (s == 2) && (f == 0x18)) {
-    //     if ((cdrom->dfifo_index & 0xf) == 0)
-    //         printf("\n");
-
-    //     printf("%02x ", cdrom->dfifo[offset + (cdrom->dfifo_index)]);
-    // }
-
     if (cdrom->dfifo_index < sector_size) {
         SET_BITS(status, STAT_DRQSTS_MASK, STAT_DRQSTS_MASK);
 
@@ -1383,7 +1380,7 @@
         return data;
     }
 
-    return 0x00;
+    return 0;
 }
 
 uint8_t cdrom_read_ier(psx_cdrom_t* cdrom) {
@@ -1450,12 +1447,6 @@
 void cdrom_write_ifr(psx_cdrom_t* cdrom, uint8_t value) {
     cdrom->ifr &= ~(value & 0x1f);
 
-    // if (value & 0x7) {
-    //     log_set_quiet(0);
-    //     log_fatal("Acknowledge %02x", value & 0x7);
-    //     log_set_quiet(1);
-    // }
-
     // Clear Parameter FIFO
     if (value & 0x40) {
         cdrom->pfifo_index = 0;
@@ -1547,26 +1538,21 @@
     cdrom->xa_left_buf = malloc(XA_STEREO_SAMPLES * sizeof(int16_t));
     cdrom->xa_right_buf = malloc(XA_STEREO_SAMPLES * sizeof(int16_t));
     cdrom->xa_mono_buf = malloc(XA_MONO_SAMPLES * sizeof(int16_t));
-    // cdrom->xa_decoded_buf = malloc(XA_DECODED_SAMPLES * sizeof(int16_t));
-    // cdrom->xa_left_ring_buf = malloc(XA_RINGBUF_SIZE * sizeof(int16_t));
-    // cdrom->xa_right_ring_buf = malloc(XA_RINGBUF_SIZE * sizeof(int16_t));
-    // cdrom->xa_stereo_resample_buf = malloc(XA_STEREO_RESAMPLE_SIZE * sizeof(int16_t));
-    // cdrom->xa_mono_resample_buf = malloc(XA_MONO_RESAMPLE_SIZE * sizeof(int16_t));
     cdrom->xa_upsample_buf = malloc((14112 + 6) * sizeof(int16_t));
-    cdrom->xa_resample_buf = malloc(2352 * sizeof(int16_t));
+    cdrom->xa_left_resample_buf = malloc(2352 * sizeof(int16_t));
+    cdrom->xa_right_resample_buf = malloc(2352 * sizeof(int16_t));
     cdrom->xa_step = 6;
 
+    // We will use this whenever we implement proper
+    // XA interpolation
+    (void)g_zigzag_table;
+
     memset(cdrom->xa_left_buf, 0, XA_STEREO_SAMPLES * sizeof(int16_t));
     memset(cdrom->xa_right_buf, 0, XA_STEREO_SAMPLES * sizeof(int16_t));
     memset(cdrom->xa_mono_buf, 0, XA_MONO_SAMPLES * sizeof(int16_t));
     memset(cdrom->xa_upsample_buf, 0, (14112 + 6) * sizeof(int16_t));
-    memset(cdrom->xa_resample_buf, 0, 2352 * sizeof(int16_t));
-
-    // memset(cdrom->xa_decoded_buf, 0, XA_DECODED_SAMPLES * sizeof(int16_t));
-    // memset(cdrom->xa_left_ring_buf, 0, XA_RINGBUF_SIZE * sizeof(int16_t));
-    // memset(cdrom->xa_right_ring_buf, 0, XA_RINGBUF_SIZE * sizeof(int16_t));
-    // memset(cdrom->xa_stereo_resample_buf, 0, XA_STEREO_RESAMPLE_SIZE * sizeof(int16_t));
-    // memset(cdrom->xa_mono_resample_buf, 0, XA_MONO_RESAMPLE_SIZE * sizeof(int16_t));
+    memset(cdrom->xa_left_resample_buf, 0, 2352 * sizeof(int16_t));
+    memset(cdrom->xa_right_resample_buf, 0, 2352 * sizeof(int16_t));
 }
 
 uint32_t psx_cdrom_read32(psx_cdrom_t* cdrom, uint32_t offset) {
@@ -1637,13 +1623,13 @@
                 //     g_psx_cdrom_command_names[cdrom->delayed_command],
                 //     cdrom->delayed_command
                 // );
-                log_set_quiet(1);
+                // log_set_quiet(1);
                 g_psx_cdrom_command_table[cdrom->delayed_command](cdrom);
             }
 
             // log_set_quiet(0);
             // log_fatal("CDROM INT%u", cdrom->ifr & 0x7);
-            log_set_quiet(1);
+            // log_set_quiet(1);
         }
     }
 }
@@ -1769,6 +1755,26 @@
     0,   0,  -52, -55,  -60
 };
 
+void cdrom_resample_xa_buf(psx_cdrom_t* cdrom, int16_t* dst, int16_t* src) {
+    // To-do: Account for 18KHz samples and mono
+    // int f18khz = ((cdrom->xa_sector_buf[0x13] >> 2) & 1) == 1;
+
+    for (int i = 0; i < XA_STEREO_SAMPLES; i++) {
+        int j = i * 7;
+
+        cdrom->xa_upsample_buf[j] = src[i];
+
+        // Nearest neighbor
+        for (int k = 0; k < 7; k++)
+            cdrom->xa_upsample_buf[j+k] = src[i];
+    }
+
+    for (int i = 0; i < 2352; i++)
+        dst[i] = cdrom->xa_upsample_buf[i*6];
+
+    cdrom->xa_remaining_samples = 2352;
+}
+
 void cdrom_decode_xa_block(psx_cdrom_t* cdrom, int idx, int blk, int nib, int16_t* buf, int16_t* h) {
     int shift  = 12 - (cdrom->xa_sector_buf[idx + 4 + blk * 2 + nib] & 0x0F);
     int filter =      (cdrom->xa_sector_buf[idx + 4 + blk * 2 + nib] & 0x30) >> 4;
@@ -1791,53 +1797,7 @@
     }
 }
 
-int16_t cdrom_xa_interpolate(psx_cdrom_t* cdrom, int table, int channel) {
-    int16_t* ringbuf = channel ? cdrom->xa_right_ring_buf : cdrom->xa_left_ring_buf;
-
-    int sum = 0;
-
-    for (int i = 0; i < 29; i++) {
-        int16_t* zigzag = g_zigzag_table[table];
-
-        sum += (ringbuf[(cdrom->xa_ringbuf_pos - i) & 0x1f] * zigzag[i]) / 0x8000;
-    }
-
-    return (sum > INT16_MAX) ? INT16_MAX : ((sum < INT16_MIN) ? INT16_MIN : sum);
-}
-
-int16_t* cdrom_resample_xa_sector(psx_cdrom_t* cdrom, int16_t* buf, int stereo, int f18khz, int channel) {
-    int16_t* ringbuf = channel ? cdrom->xa_right_ring_buf : cdrom->xa_left_ring_buf;
-    int16_t* resample_buf = stereo ? cdrom->xa_stereo_resample_buf : cdrom->xa_mono_resample_buf;
-
-    int sample_count = stereo ? XA_STEREO_SAMPLES : XA_MONO_SAMPLES;
-
-    for (int i = 0; i < sample_count; i++) {
-        ringbuf[cdrom->xa_ringbuf_pos++ & 0x1f] = buf[i];
-
-        cdrom->xa_step--;
-
-        if (!cdrom->xa_step) {
-            cdrom->xa_step = 6;
-
-            for (int table = 0; table < 7; table++) {
-                int16_t sample = cdrom_xa_interpolate(cdrom, table, channel);
-
-                *resample_buf++ = sample;
-
-                if (f18khz)
-                    *resample_buf++ = sample;
-            }
-        }
-    }
-
-    return resample_buf;
-}
-
 void cdrom_decode_xa_sector(psx_cdrom_t* cdrom, void* buf) {
-    int16_t* ptr = (int16_t*)buf;
-
-    cdrom->xa_coding = cdrom->xa_sector_buf[0x13];
-
     int src = 24;
 
     int16_t left[28];
@@ -1845,9 +1805,6 @@
     int16_t left_h[2] = { 0, 0 };
     int16_t right_h[2] = { 0, 0 };
 
-    int stereo = (cdrom->xa_coding & 1) == 1;
-    int f18khz = ((cdrom->xa_coding >> 2) & 1) == 1;
-
     int16_t* left_ptr = cdrom->xa_left_buf;
     int16_t* right_ptr = cdrom->xa_right_buf;
     int16_t* mono_ptr = cdrom->xa_mono_buf;
@@ -1854,7 +1811,7 @@
 
     for (int i = 0; i < 18; i++) {
         for (int blk = 0; blk < 4; blk++) {
-            if (stereo) {
+            if (cdrom->xa_sector_buf[0x13] & 1) {
                 cdrom_decode_xa_block(cdrom, src, blk, 0, left, left_h);
                 cdrom_decode_xa_block(cdrom, src, blk, 1, right, right_h);
 
@@ -1877,74 +1834,16 @@
 
         src += 128;
     }
-
-    if (stereo) {
-        for (int i = 0; i < XA_STEREO_SAMPLES; i++) {
-            int j = i * 7;
-
-            cdrom->xa_upsample_buf[j] = cdrom->xa_left_buf[i];
-
-            // Nearest neighbor
-            for (int k = 0; k < 7; k++)
-                cdrom->xa_upsample_buf[j+k] = cdrom->xa_left_buf[i];
-        }
-
-        for (int i = 0; i < 2352; i++)
-            cdrom->xa_resample_buf[i] = cdrom->xa_upsample_buf[i*6];
-
-        cdrom->xa_remaining_samples = 2352;
-    } else {
-        exit(1);
-
-        for (int i = 0; i < XA_MONO_SAMPLES; i++) {
-            *ptr++ = cdrom->xa_mono_buf[i];
-            *ptr++ = cdrom->xa_mono_buf[i];
-        }
-    }
-    
-    // if (stereo) {
-    //     int16_t* resample_buf;
-
-    //     resample_buf = cdrom_resample_xa_sector(cdrom, cdrom->xa_left_buf, 1, f18khz, 0);
-
-    //     for (int i = 0, j = 0; i < XA_STEREO_RESAMPLE_SIZE; i++) {
-    //         int16_t sample = resample_buf[i];
-
-    //         cdrom->xa_decoded_buf[j] = sample;
-
-    //         j += 2;
-    //     }
-
-    //     resample_buf = cdrom_resample_xa_sector(cdrom, cdrom->xa_right_buf, 1, f18khz, 1);
-
-    //     for (int i = 0, j = 1; i < XA_STEREO_RESAMPLE_SIZE; i++) {
-    //         int16_t sample = resample_buf[i];
-
-    //         cdrom->xa_decoded_buf[j] = sample;
-
-    //         j += 2;
-    //     }
-        
-    //     cdrom->xa_remaining_samples = XA_STEREO_RESAMPLE_SIZE;
-    // } else {
-    //     int16_t* resample_buf;
-
-    //     resample_buf = cdrom_resample_xa_sector(cdrom, cdrom->xa_mono_buf, 0, f18khz, 0);
-
-    //     for (int i = 0, j = 0; i < XA_MONO_RESAMPLE_SIZE; i++) {
-    //         int16_t sample = resample_buf[i];
-
-    //         cdrom->xa_decoded_buf[j++] = sample;
-    //         cdrom->xa_decoded_buf[j++] = sample;
-    //     }
-
-    //     cdrom->xa_remaining_samples = XA_MONO_RESAMPLE_SIZE;
-    // }
 }
 
 void cdrom_fetch_xa_sector(psx_cdrom_t* cdrom) {
     while (true) {
-        psx_disc_seek(cdrom->disc, cdrom->xa_msf);
+        if (psx_disc_seek(cdrom->disc, cdrom->xa_msf)) {
+            cdrom->xa_playing = 0;
+
+            return;
+        }
+
         psx_disc_read_sector(cdrom->disc, cdrom->xa_sector_buf);
 
         msf_add_f(&cdrom->xa_msf, 1);
@@ -1982,33 +1881,17 @@
             if (!cdrom->xa_remaining_samples) {
                 cdrom_fetch_xa_sector(cdrom);
                 cdrom_decode_xa_sector(cdrom, buf);
+                cdrom_resample_xa_buf(cdrom, cdrom->xa_left_resample_buf, cdrom->xa_left_buf);
+                cdrom_resample_xa_buf(cdrom, cdrom->xa_right_resample_buf, cdrom->xa_right_buf);
 
                 cdrom->xa_sample_idx = 0;
             }
 
-            *ptr++ = cdrom->xa_resample_buf[(cdrom->xa_sample_idx) % 2352];
-            *ptr++ = cdrom->xa_resample_buf[(cdrom->xa_sample_idx++) % 2352];
+            *ptr++ = cdrom->xa_left_resample_buf[(cdrom->xa_sample_idx) % 2352];
+            *ptr++ = cdrom->xa_right_resample_buf[(cdrom->xa_sample_idx++) % 2352];
 
             --cdrom->xa_remaining_samples;
         }
-
-        // int16_t* ptr = (int16_t*)buf;
-
-        // memset(buf, 0, size);
-
-        // if (!cdrom->xa_remaining_samples) {
-        //     cdrom->xa_sample_idx = 0;
-
-        //     cdrom_fetch_xa_sector(cdrom);
-        //     cdrom_decode_xa_sector(cdrom, buf);
-        // }
-
-        // // for (int i = 0; i < (size >> 2); i++) {
-        // //     *ptr++ = cdrom->xa_decoded_buf[cdrom->xa_sample_idx++];
-        // //     *ptr++ = cdrom->xa_decoded_buf[cdrom->xa_sample_idx++];
-        // // }
-
-        // cdrom->xa_remaining_samples -= size >> 2;
 
         return;
     }
--- a/psx/dev/cdrom.h
+++ b/psx/dev/cdrom.h
@@ -224,7 +224,8 @@
     int xa_remaining_samples;
     uint32_t xa_step;
     uint32_t xa_ringbuf_pos;
-    int16_t* xa_resample_buf;
+    int16_t* xa_left_resample_buf;
+    int16_t* xa_right_resample_buf;
     int16_t* xa_upsample_buf;
 
     const char* path;
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -184,6 +184,12 @@
 void psx_dma_do_mdec_out(psx_dma_t* dma) {
     if (!CHCR_BUSY(mdec_out))
         return;
+    
+    printf("MDEC out madr=%08x size=%04x bcnt=%04x\n",
+        dma->mdec_out.madr,
+        BCR_SIZE(mdec_out),
+        BCR_BCNT(mdec_out)
+    );
 
     size_t size = BCR_SIZE(mdec_out) * BCR_BCNT(mdec_out);
 
@@ -257,7 +263,7 @@
 }
 
 void psx_dma_do_gpu_burst(psx_dma_t* dma) {
-    log_fatal("GPU DMA burst sync mode unimplemented");
+    printf("GPU DMA burst sync mode unimplemented\n");
 
     exit(1);
 }
@@ -313,7 +319,7 @@
     uint32_t size = BCR_SIZE(cdrom);
 
     if (!size) {
-        log_fatal("0 sized CDROM DMA");
+        printf("0 sized CDROM DMA\n");
 
         exit(1);
     }
@@ -320,8 +326,6 @@
 
     dma->cdrom_irq_delay = size * 24;
 
-    uint32_t base_addr = dma->cdrom.madr;
-
     if (!CHCR_TDIR(cdrom)) {
         for (int i = 0; i < size; i++) {
             uint32_t data = 0;
@@ -338,24 +342,6 @@
     } else {
         log_fatal("Invalid CDROM DMA transfer direction");
     }
-
-    // size *= 4;
-
-    // for (int i = 0; i < size; i += 16) {
-    //     for (int k = 0; k < 16; k++) {
-    //         printf("%02x ", psx_bus_read8(dma->bus, base_addr + i + k));
-    //     }
-
-    //     printf("| ");
-
-    //     for (int k = 0; k < 16; k++) {
-    //         char c = psx_bus_read8(dma->bus, base_addr + i + k);
-
-    //         printf("%c ", isgraph(c) ? c : '.');
-    //     }
-
-    //     printf("\n");
-    // }
     
     // Clear BCR and CHCR trigger and busy bits
     dma->cdrom.chcr = 0;
@@ -381,7 +367,7 @@
     //     (dma->dicr >> 23) & 1,
     //     (dma->dicr >> 24) & 0x7f
     // );
-    log_set_quiet(1);
+    // log_set_quiet(1);
 
     uint32_t size = BCR_SIZE(spu);
     uint32_t blocks = BCR_BCNT(spu);
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -824,16 +824,6 @@
             int vertices = 3 + quad;
  
             gpu->cmd_args_remaining = (fields_per_vertex * vertices) - shaded;
-
-            // log_set_quiet(0);
-            // log_fatal("Poly: GP0(%02x) shaded=%u, quad=%u, textured=%u, argc=%u, fpv=%u, vertc=%u",
-            //     gpu->buf[0] >> 24,
-            //     shaded, quad, textured,
-            //     gpu->cmd_args_remaining,
-            //     fields_per_vertex,
-            //     vertices
-            // );
-            log_set_quiet(1);
         } break;
 
         case GPU_STATE_RECV_ARGS: {
@@ -879,15 +869,6 @@
                     gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly);
                     gpu_render_triangle(gpu, poly.v[1], poly.v[2], poly.v[3], poly);
                 } else {
-                    // log_set_quiet(0);
-                    // log_fatal("v0=(%3u, %3u, %06x) v1=(%3u, %3u, %06x) v2=(%3u, %3u, %06x) co=%u vo=%u tco=%u tpo=%u",
-                    //     poly.v[0].x, poly.v[0].y, poly.v[0].c,
-                    //     poly.v[1].x, poly.v[1].y, poly.v[1].c,
-                    //     poly.v[2].x, poly.v[2].y, poly.v[2].c,
-                    //     color_offset, vert_offset,
-                    //     texc_offset, texp_offset
-                    // );
-                    log_set_quiet(1);
                     gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly);
                 }
 
--- a/psx/dev/ic.c
+++ b/psx/dev/ic.c
@@ -87,7 +87,7 @@
 }
 
 void psx_ic_write8(psx_ic_t* ic, uint32_t offset, uint8_t value) {
-    log_fatal("Unhandled 8-bit IC write at offset %08x (%02x)", offset, value);
+    printf("Unhandled 8-bit IC write at offset %08x (%02x)\n", offset, value);
 
     exit(1);
 }
--- a/psx/dev/mcd.c
+++ b/psx/dev/mcd.c
@@ -23,8 +23,12 @@
     if (!file)
         return;
 
-    fread(mcd->buf, 1, MCD_MEMORY_SIZE, file);
+    if (!fread(mcd->buf, 1, MCD_MEMORY_SIZE, file)) {
+        perror("Error reading memory card data");
 
+        exit(1);
+    }
+
     fclose(file);
 }
 
@@ -47,7 +51,7 @@
 
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", mcd->tx_data);
-            log_set_quiet(1);
+            // log_set_quiet(1);
 
             return mcd->tx_data;
         } break;
@@ -75,7 +79,7 @@
 
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", data);
-            log_set_quiet(1);
+            // log_set_quiet(1);
 
             return data;
         } break;
@@ -86,7 +90,7 @@
 
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", 'G');
-            log_set_quiet(1);
+            // log_set_quiet(1);
 
             return 'G';
         } break;
@@ -108,7 +112,7 @@
 
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", mcd->rx_data);
-            log_set_quiet(1);
+            // log_set_quiet(1);
 
             return mcd->rx_data;
         } break;
@@ -121,7 +125,7 @@
 
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", 'G');
-            log_set_quiet(1);
+            // log_set_quiet(1);
 
             return 'G';
         } break;
@@ -132,7 +136,7 @@
 
     // log_set_quiet(0);
     // log_fatal("mcd read %02x", mcd->tx_data);
-    log_set_quiet(1);
+    // log_set_quiet(1);
 
     return mcd->tx_data;
 }
--- a/psx/dev/mdec.c
+++ b/psx/dev/mdec.c
@@ -77,12 +77,12 @@
     
     uint16_t n = *src;
 
-    src += 2;
+    ++src;
 
     while (n == 0xfe00) {
         n = *src;
 
-        src += 2;
+        ++src;
     }
 
     int q_scale = (n >> 10) & 0x3f;
@@ -104,7 +104,7 @@
 
         n = *src;
 
-        src += 2;
+        ++src;
 
         k += ((n >> 10) & 0x3f) + 1;
 
@@ -162,11 +162,14 @@
 void mdec_nop(psx_mdec_t* mdec) { /* Do nothing */ }
 
 void mdec_decode_macroblock(psx_mdec_t* mdec) {
-    return;
-
     if (mdec->output_depth < 2) {
-        rl_decode_block(mdec->yblk, mdec->input, mdec->y_quant_table, mdec->scale_table);
+        size_t block_size = (mdec->output_depth == 3) ? 512 : 768;
+        size_t size = block_size;
 
+        mdec->output = malloc(size);
+
+        rl_decode_block(mdec->yblk, (uint16_t*)mdec->input, mdec->y_quant_table, mdec->scale_table);
+
         for (int i = 0; i < 64; i++) {
             int16_t y = mdec->yblk[i] & 0xff;
 
@@ -182,59 +185,49 @@
         mdec->output_empty = 0;
         mdec->output_index = 0;
     } else {
-        uint16_t* in = mdec->input;
-        uint8_t* out;
+        uint16_t* in = (uint16_t*)mdec->input;
 
         size_t block_size = (mdec->output_depth == 3) ? 512 : 768;
         size_t size = block_size;
 
-        unsigned int bytes_processed = 0;
+        ptrdiff_t bytes_processed = 0;
 
+        int block_count = 1;
+
         while (bytes_processed < mdec->input_size) {
             if (!mdec->output) {
-                mdec->output = malloc(size);
-
-                out = mdec->output;
+                mdec->output = malloc(block_count * size);
             } else {
-                mdec->output = realloc(mdec->output, size);
+                mdec->output = realloc(mdec->output, block_count * size);
             }
-            
+
             in = rl_decode_block(mdec->crblk, in, mdec->uv_quant_table, mdec->scale_table);
             in = rl_decode_block(mdec->cbblk, in, mdec->uv_quant_table, mdec->scale_table);
             in = rl_decode_block(mdec->yblk, in, mdec->y_quant_table, mdec->scale_table);
-            yuv_to_rgb(mdec, out, 0, 0);
+            yuv_to_rgb(mdec, &mdec->output[(block_count * size) - block_size], 0, 0);
             in = rl_decode_block(mdec->yblk, in, mdec->y_quant_table, mdec->scale_table);
-            yuv_to_rgb(mdec, out, 0, 8);
+            yuv_to_rgb(mdec, &mdec->output[(block_count * size) - block_size], 0, 8);
             in = rl_decode_block(mdec->yblk, in, mdec->y_quant_table, mdec->scale_table);
-            yuv_to_rgb(mdec, out, 8, 0);
+            yuv_to_rgb(mdec, &mdec->output[(block_count * size) - block_size], 8, 0);
             in = rl_decode_block(mdec->yblk, in, mdec->y_quant_table, mdec->scale_table);
-            yuv_to_rgb(mdec, out, 8, 8);
+            yuv_to_rgb(mdec, &mdec->output[(block_count * size) - block_size], 8, 8);
 
-            size += block_size;
-            out += block_size;
-
             bytes_processed = (uintptr_t)in - (uintptr_t)mdec->input;
 
-            log_set_quiet(0);
-            log_fatal("Decompressed 1 macroblock (%u total bytes processed) output=%p, output+size=%p, output ptr=%p",
-                bytes_processed, mdec->output, mdec->output + size, out
-            );
-            log_set_quiet(1);
+            ++block_count;
         }
 
-        mdec->output_words_remaining = size >> 2;
+        mdec->output_words_remaining = ((block_count - 1) * block_size) >> 2;
         mdec->output_empty = 0;
         mdec->output_index = 0;
 
-        log_set_quiet(0);
-        log_fatal("Finished decoding %u-bit MDEC data input=(%p-%p=%04x, %04x)",
-            (mdec->output_depth == 3) ? 15 : 24,
-            in,
-            mdec->input,
-            (uintptr_t)in - (uintptr_t)mdec->input,
-            mdec->input_size
-        );
-        log_set_quiet(1);
+        // log_set_quiet(0);
+        // log_fatal("Finished decoding %u-bit MDEC data input=(%04x -> %08x)",
+        //     (mdec->output_depth == 3) ? 15 : 24,
+        //     mdec->input_size,
+        //     mdec->output_words_remaining
+        // );
+        // log_set_quiet(1);
     }
 }
 
@@ -283,11 +276,9 @@
                 // log_fatal("output read %08x", 0);
                 // log_set_quiet(1);
 
-                return 0xaaaaaaaa;
-
-                // return ((uint32_t*)mdec->output)[mdec->output_index++];
+                return ((uint32_t*)mdec->output)[mdec->output_index++];
             } else {
-                mdec->output_empty = 1;
+                mdec->output_empty = 0;
                 mdec->output_index = 0;
                 mdec->output_request = 0;
 
@@ -317,10 +308,14 @@
 
 uint16_t psx_mdec_read16(psx_mdec_t* mdec, uint32_t offset) {
     log_fatal("Unhandled 16-bit MDEC read offset=%u", offset);
+
+    exit(1);
 }
 
 uint8_t psx_mdec_read8(psx_mdec_t* mdec, uint32_t offset) {
     log_fatal("Unhandled 8-bit MDEC read offset=%u", offset);
+
+    exit(1);
 }
 
 void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) {
@@ -338,7 +333,7 @@
                     mdec->busy = 0;
                     mdec->output_request = mdec->enable_dma1;
 
-                    // g_mdec_cmd_table[mdec->cmd >> 29](mdec);
+                    g_mdec_cmd_table[mdec->cmd >> 29](mdec);
 
                     free(mdec->input);
                 }
@@ -368,7 +363,7 @@
                 case MDEC_CMD_DECODE: {
                     mdec->words_remaining = mdec->cmd & 0xffff;
 
-                    log_fatal("MDEC %08x: decode macroblock %04x",
+                    printf("MDEC %08x: decode macroblock %04x\n",
                         mdec->cmd,
                         mdec->words_remaining
                     );
@@ -393,7 +388,7 @@
                     );
                 } break;
             }
-            //log_set_quiet(1);
+            // log_set_quiet(1);
 
             if (mdec->words_remaining) {
                 mdec->input_request = mdec->enable_dma0;
--- a/psx/dev/old/cdrom.c
+++ b/psx/dev/old/cdrom.c
@@ -63,7 +63,7 @@
     cdrom->state = CD_STATE_RECV_CMD;
 }
 void cdrom_cmd_unimplemented(psx_cdrom_t* cdrom) {
-    log_fatal("Unimplemented CDROM command (%u)", cdrom->command);
+    printf("Unimplemented CDROM command (%u)\n", cdrom->command);
 
     exit(1);
 }
@@ -1218,19 +1218,19 @@
 }
 
 void cdrom_write_cmd(psx_cdrom_t* cdrom, uint8_t value) {
-    log_set_quiet(0);
-    log_fatal("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]",
-        g_psx_cdrom_command_names[value],
-        value,
-        cdrom->pfifo_index,
-        cdrom->pfifo[0],
-        cdrom->pfifo[1],
-        cdrom->pfifo[2],
-        cdrom->pfifo[3],
-        cdrom->pfifo[4],
-        cdrom->pfifo[5]
-    );
-    log_set_quiet(1);
+    // log_set_quiet(0);
+    // log_fatal("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]",
+    //     g_psx_cdrom_command_names[value],
+    //     value,
+    //     cdrom->pfifo_index,
+    //     cdrom->pfifo[0],
+    //     cdrom->pfifo[1],
+    //     cdrom->pfifo[2],
+    //     cdrom->pfifo[3],
+    //     cdrom->pfifo[4],
+    //     cdrom->pfifo[5]
+    // );
+    // log_set_quiet(1);
 
     cdrom->command = value;
     cdrom->state = CD_STATE_RECV_CMD;
@@ -1271,12 +1271,6 @@
 void cdrom_write_ifr(psx_cdrom_t* cdrom, uint8_t value) {
     cdrom->ifr &= ~(value & 0x1f);
 
-    // if (value & 0x7) {
-    //     log_set_quiet(0);
-    //     log_fatal("Acknowledge %02x", value & 0x7);
-    //     log_set_quiet(1);
-    // }
-
     // Clear Parameter FIFO
     if (value & 0x40) {
         cdrom->pfifo_index = 0;
@@ -1400,19 +1394,8 @@
 
             cdrom->irq_delay = 0;
 
-            if (cdrom->delayed_command) {
-                // log_set_quiet(0);
-                // log_fatal("%s(%02x) (Delayed)",
-                //     g_psx_cdrom_command_names[cdrom->delayed_command],
-                //     cdrom->delayed_command
-                // );
-                log_set_quiet(1);
+            if (cdrom->delayed_command)
                 g_psx_cdrom_command_table[cdrom->delayed_command](cdrom);
-            }
-
-            // log_set_quiet(0);
-            // log_fatal("CDROM INT%u", cdrom->ifr & 0x7);
-            log_set_quiet(1);
         }
     }
 }
--- a/psx/dev/pad.c
+++ b/psx/dev/pad.c
@@ -101,7 +101,7 @@
 uint32_t pad_handle_stat_read(psx_pad_t* pad) {
     // log_set_quiet(0);
     // log_fatal("pad stat read");
-    log_set_quiet(1);
+    // log_set_quiet(1);
     return 0x07;
     psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
 
--- a/psx/dev/rework/gpu.c
+++ b/psx/dev/rework/gpu.c
@@ -1589,7 +1589,7 @@
         default: {
             // log_set_quiet(0);
             // log_fatal("Unhandled GP0(%02Xh)", gpu->buf[0] >> 24);
-            log_set_quiet(1);
+            // log_set_quiet(1);
 
             // exit(1);
         } break;
--- a/psx/dev/spu.c
+++ b/psx/dev/spu.c
@@ -406,7 +406,7 @@
     if (spu_handle_write(spu, offset, value))
         return;
 
-    const uint8_t* ptr = (uint8_t*)&spu->voice[0].volumel;
+    const uint8_t* ptr = (uint8_t*)&spu->voice[0];
 
     *((uint32_t*)(ptr + offset)) = value;
 }
@@ -640,11 +640,16 @@
 
 void psx_spu_update_cdda_buffer(psx_spu_t* spu, void* buf) {
     int16_t* ptr = buf;
-    int16_t* ram = spu->ram;
+    int16_t* ram = (int16_t*)spu->ram;
 
     for (int i = 0; i < 0x400;) {
-        ram[i] = ptr[i++];
-        ram[i + 0x400] = ptr[i++];
+        ram[i] = ptr[i];
+
+        ++i;
+
+        ram[i + 0x400] = ptr[i];
+
+        ++i;
     }
 }
 
--- a/psx/disc.c
+++ b/psx/disc.c
@@ -24,7 +24,6 @@
 }
 
 int psx_disc_seek(psx_disc_t* disc, msf_t msf) {
-    log_fatal("DISC seek %02u:%02u:%02u", msf.m, msf.s, msf.f);
     return disc->seek_func(disc->udata, msf);
 }
 
--- a/psx/disc/bin.c
+++ b/psx/disc/bin.c
@@ -38,7 +38,11 @@
 
     bin->buf = malloc(bin->buf_size);
 
-    fread(bin->buf, 1, bin->buf_size, file);
+    if (!fread(bin->buf, 1, bin->buf_size, file)) {
+        perror("Error reading BIN CD image file data");
+
+        exit(1);
+    }
 
     msf_from_address(&bin->end, bin->buf_size);
 
--- a/psx/disc/cue.c
+++ b/psx/disc/cue.c
@@ -376,8 +376,13 @@
         cue->buf = cue_alloc_block(cue->buf, &offset, track->size);
 
         fseek(track_file, 0, SEEK_SET);
-        fread(cue->buf + (offset - track->size), 1, track->size, track_file);
+        
+        if (!fread(cue->buf + (offset - track->size), 1, track->size, track_file)) {
+            perror("Error reading CUE image file data");
 
+            exit(1);
+        }
+
         fclose(track_file);
         free(full_path);
     }
@@ -407,7 +412,7 @@
 
     cue->seek_offset = sectors * CD_SECTOR_SIZE;
 
-    log_fatal("CUE seek to %02u:%02u:%02u (%08x < %08x)", msf.m, msf.s, msf.f, cue->seek_offset, cue->buf_size);
+    // log_fatal("CUE seek to %02u:%02u:%02u (%08x < %08x)", msf.m, msf.s, msf.f, cue->seek_offset, cue->buf_size);
 
     if (cue->seek_offset >= cue->buf_size)
         return DISC_ERR_ADDR_OUT_OF_BOUNDS;
--- a/psx/exe.c
+++ b/psx/exe.c
@@ -15,8 +15,12 @@
     // Read header
     psx_exe_hdr_t hdr;
     
-    fread((char*)&hdr, 1, sizeof(psx_exe_hdr_t), file);
+    if (!fread((char*)&hdr, 1, sizeof(psx_exe_hdr_t), file)) {
+        perror("Error reading PS-EXE header");
 
+        exit(1);
+    }
+
     // Seek to program start 
     fseek(file, 0x800, SEEK_SET);
 
@@ -23,7 +27,11 @@
     // Read to RAM directly
     uint32_t offset = hdr.ramdest & 0x7fffffff;
 
-    fread(cpu->bus->ram->buf + offset, 1, hdr.filesz, file);
+    if (!fread(cpu->bus->ram->buf + offset, 1, hdr.filesz, file)) {
+        perror("Error reading PS-EXE data");
+
+        exit(1);
+    }
 
     // Load initial register values
     cpu->pc = hdr.ipc;
--