Skip to content

Commit

Permalink
A lot of fixes and improvements
Browse files Browse the repository at this point in the history
Fixed huge SPU bug
Completely rewrote timers
  • Loading branch information
allkern committed May 21, 2024
1 parent a6366b6 commit 7f9fc68
Show file tree
Hide file tree
Showing 9 changed files with 358 additions and 250 deletions.
2 changes: 1 addition & 1 deletion build-win64.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ gcc -I"$($PSX_DIR)" `
-Wno-address-of-packed-member `
-ffast-math -Ofast -g -flto

Copy-Item -Path "$($SDL2_DIR)\bin\SDL2.dll" -Destination "bin"
Copy-Item -Path "$($SDL2_DIR)\bin\SDL2.dll" -Destination "bin"
6 changes: 2 additions & 4 deletions frontend/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ void psxe_screen_reload(psxe_screen_t* screen) {
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
);

SDL_SetHint("SDL_HINT_RENDER_SCALE_QUALITY", "linear"),

screen->texture = SDL_CreateTexture(
screen->renderer,
screen->format,
Expand All @@ -146,8 +144,6 @@ void psxe_screen_reload(psxe_screen_t* screen) {
SDL_RenderSetScale(screen->renderer, width_scale, height_scale);
}

SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0);

screen->open = 1;
}

Expand Down Expand Up @@ -486,4 +482,6 @@ void psxe_gpu_vblank_event_cb(psx_gpu_t* gpu) {
psxe_screen_t* screen = gpu->udata[0];

psxe_screen_update(screen);

psxe_gpu_vblank_timer_event_cb(gpu);
}
40 changes: 31 additions & 9 deletions psx/dev/cdrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,13 @@ void cdrom_cmd_getstat(psx_cdrom_t* cdrom) {
SET_BITS(ifr, IFR_INT, IFR_INT3);
RESP_PUSH(
GETSTAT_MOTOR |
(cdrom->cdda_playing ? GETSTAT_PLAY : 0) |
((cdrom->cdda_playing || cdrom->xa_playing) ? GETSTAT_PLAY : 0) |
(cdrom->ongoing_read_command ? GETSTAT_READ : 0) |
(cdrom->disc ? 0 : GETSTAT_TRAYOPEN)
);

if (cdrom->ongoing_read_command) {
cdrom->status |= STAT_BUSYSTS_MASK;
// printf("command=%02x\n", cdrom->ongoing_read_command);
// printf("getstat command=%02x\n", cdrom->ongoing_read_command);
cdrom->state = CD_STATE_SEND_RESP2;
cdrom->delayed_command = cdrom->ongoing_read_command;
cdrom->irq_delay = DELAY_1MS;
Expand Down Expand Up @@ -398,6 +397,8 @@ void cdrom_cmd_play(psx_cdrom_t* cdrom) {
cdrom->state = CD_STATE_SEND_RESP1;
cdrom->delayed_command = CDL_PLAY;

printf("play track %u\n", track);

if (track) {
psx_disc_get_track_addr(cdrom->disc, &cdrom->cdda_msf, track);

Expand Down Expand Up @@ -964,7 +965,7 @@ void cdrom_cmd_getlocp(psx_cdrom_t* cdrom) {
RESP_PUSH(0x01);

if (cdrom->ongoing_read_command) {
//// printf("command=%02x\n", cdrom->ongoing_read_command);
printf("getlocp command=%02x\n", cdrom->ongoing_read_command);
cdrom->state = CD_STATE_SEND_RESP2;
cdrom->delayed_command = cdrom->ongoing_read_command;
cdrom->irq_delay = DELAY_1MS;
Expand Down Expand Up @@ -1034,8 +1035,15 @@ void cdrom_cmd_gettn(psx_cdrom_t* cdrom) {
RESP_PUSH(0x01);
RESP_PUSH(GETSTAT_MOTOR);

cdrom->delayed_command = CDL_NONE;
cdrom->state = CD_STATE_RECV_CMD;
if (cdrom->ongoing_read_command) {
//// printf("command=%02x\n", cdrom->ongoing_read_command);
cdrom->state = CD_STATE_SEND_RESP2;
cdrom->delayed_command = cdrom->ongoing_read_command;
cdrom->irq_delay = DELAY_1MS;
} else {
cdrom->delayed_command = CDL_NONE;
cdrom->state = CD_STATE_RECV_CMD;
}
} break;
}
}
Expand Down Expand Up @@ -1415,17 +1423,16 @@ void cdrom_cmd_readtoc(psx_cdrom_t* cdrom) {
switch (cdrom->state) {
case CD_STATE_RECV_CMD: {
cdrom->status |= STAT_BUSYSTS_MASK;
cdrom->irq_delay = DELAY_1MS * 1000;
cdrom->irq_delay = DELAY_1MS;
cdrom->state = CD_STATE_SEND_RESP1;
cdrom->delayed_command = CDL_READTOC;
} break;

case CD_STATE_SEND_RESP1: {
cdrom->status &= ~STAT_BUSYSTS_MASK;
SET_BITS(ifr, IFR_INT, 3);
RESP_PUSH(GETSTAT_MOTOR | GETSTAT_READ);

cdrom->irq_delay = DELAY_1MS * 1000;
cdrom->irq_delay = DELAY_1MS;
cdrom->state = CD_STATE_SEND_RESP2;
cdrom->delayed_command = CDL_READTOC;
} break;
Expand Down Expand Up @@ -1634,6 +1641,17 @@ void cdrom_write_cmd(psx_cdrom_t* cdrom, uint8_t value) {
cdrom->command = value;
cdrom->state = CD_STATE_RECV_CMD;

// Required for Spyro - The Year of the Dragon
if (!cdrom->command) {
cdrom->irq_delay = DELAY_1MS * 600;
cdrom->delayed_command = CDL_ERROR;
cdrom->state = CD_STATE_ERROR;
cdrom->error = ERR_INVSUBF;
cdrom->error_flags = GETSTAT_SEEKERROR;

return;
}

g_psx_cdrom_command_table[value](cdrom);
}

Expand Down Expand Up @@ -2114,6 +2132,10 @@ void cdrom_fetch_xa_sector(psx_cdrom_t* cdrom) {

msf_add_f(&cdrom->xa_msf, 1);

// Check for EOR, EOF bits
if (cdrom->xa_sector_buf[0x12] & 0x80)
return;

// Check RT and Audio bit
if ((cdrom->xa_sector_buf[0x12] & 4) != 4)
continue;
Expand Down
12 changes: 10 additions & 2 deletions psx/dev/gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1772,7 +1772,8 @@ void gpu_hblank_event(psx_gpu_t* gpu) {
// enough. Sending T2 IRQs every line fixes DoA
// but breaks a bunch of games, so I'll keep this
// like this until I actually fix the timers
// Games that cared about T2:
// Games that seem to care about T2 timing:
// - Street Fighter Alpha 2
// - Dead or Alive
// - NBA Jam
// - Doom
Expand All @@ -1782,7 +1783,14 @@ void gpu_hblank_event(psx_gpu_t* gpu) {
// - Mortal Kombat
// - PaRappa the Rapper
// - In The Hunt
// - Crash Bandicoot
// - Jackie Chan Stuntmaster
// - etc.
// Masking with 7 breaks Street Fighter Alpha 2. The game
// just stops sending commands to the CDROM while on
// Player Select. It probably uses T2 IRQs to time
// GetlocP commands, if the timer is too slow it will
// break.
if (!(gpu->line & 7))
psx_ic_irq(gpu->ic, IC_TIMER2);
} else {
Expand Down Expand Up @@ -1815,7 +1823,7 @@ void psx_gpu_update(psx_gpu_t* gpu, int cyc) {

int curr_hblank = (gpu->cycles >= GPU_CYCLES_PER_HDRAW_NTSC) &&
(gpu->cycles <= GPU_CYCLES_PER_SCANL_NTSC);

if (curr_hblank && !prev_hblank) {
if (gpu->event_cb_table[GPU_EVENT_HBLANK])
gpu->event_cb_table[GPU_EVENT_HBLANK](gpu);
Expand Down
12 changes: 6 additions & 6 deletions psx/dev/ic.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,8 @@ void psx_ic_write32(psx_ic_t* ic, uint32_t offset, uint32_t value) {
}

// Emulate acknowledge
if (!(ic->stat & ic->mask)) {
if (!(ic->stat & ic->mask))
ic->cpu->cop0_r[COP0_CAUSE] &= ~SR_IM2;
}
}

void psx_ic_write16(psx_ic_t* ic, uint32_t offset, uint16_t value) {
Expand All @@ -84,9 +83,8 @@ void psx_ic_write16(psx_ic_t* ic, uint32_t offset, uint16_t value) {
}

// Emulate acknowledge
if (!(ic->stat & ic->mask)) {
if (!(ic->stat & ic->mask))
ic->cpu->cop0_r[COP0_CAUSE] &= ~SR_IM2;
}
}

void psx_ic_write8(psx_ic_t* ic, uint32_t offset, uint8_t value) {
Expand All @@ -102,14 +100,16 @@ void psx_ic_write8(psx_ic_t* ic, uint32_t offset, uint8_t value) {
}

// Emulate acknowledge
if (!(ic->stat & ic->mask)) {
if (!(ic->stat & ic->mask))
ic->cpu->cop0_r[COP0_CAUSE] &= ~SR_IM2;
}
}

void psx_ic_irq(psx_ic_t* ic, int id) {
ic->stat |= id;

// if (ic->mask & (1 << id))
// printf("%u IRQ gone through\n");

if (ic->mask & ic->stat)
psx_cpu_set_irq_pending(ic->cpu);
}
Expand Down
6 changes: 3 additions & 3 deletions psx/dev/spu.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,9 @@ uint32_t psx_spu_get_sample(psx_spu_t* spu) {
spu->data[v].counter &= 0xfff;
spu->data[v].counter |= sample_index << 12;

if (spu->data[v].block_flags & 4)
spu->data[v].repeat_addr = spu->data[v].current_addr;

switch (spu->data[v].block_flags & 3) {
case 0: case 2: {
spu->data[v].current_addr += 0x10;
Expand All @@ -587,9 +590,6 @@ uint32_t psx_spu_get_sample(psx_spu_t* spu) {
} break;
}

if (spu->data[v].block_flags & 4)
spu->data[v].repeat_addr = spu->data[v].current_addr;

spu_read_block(spu, v);
}

Expand Down
Loading

0 comments on commit 7f9fc68

Please sign in to comment.