ref: e145a4e8ae7b9e150e6c093b395eb71ab5fe4111
parent: 4055e8901d4fd29cbdd6914ebe9941f5db11bae3
author: allkern <lisandroaalarcon@gmail.com>
date: Sat Jul 20 09:02:03 EDT 2024
Fix report IRQ emulation Fixes Doom games Improve read start timings (fixes MMX5/6 MDEC movies) Fix non-read pause timings (fixes DoA music) Delay execution when running from BIOS
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -291,6 +291,9 @@
cpu->opcode = psx_bus_read32(cpu->bus, cpu->pc);
+ cpu->last_cycles = 2;
+ cpu->last_cycles += psx_bus_get_access_cycles(cpu->bus);
+
cpu->pc = cpu->next_pc;
cpu->next_pc += 4;
@@ -312,7 +315,6 @@
g_psx_cpu_primary_table[OP](cpu);
// Not even trying to get precise timings here
- cpu->last_cycles = 2;
cpu->total_cycles += cpu->last_cycles;
cpu->r[0] = 0;
--- a/psx/dev/cdrom/audio.c
+++ b/psx/dev/cdrom/audio.c
@@ -294,10 +294,11 @@
cdrom->cdda_remaining_samples = 0;
cdrom->cdda_sample_index = 0;
cdrom->state = CD_STATE_IDLE;
+ cdrom->cdda_prev_track = 0;
+ cdrom->cdda_playing = 0;
memset(buf, 0, size);
- // Send autopause IRQ (INT4)
if (cdrom->mode & MODE_AUTOPAUSE)
cdrom_send_autopause_irq(cdrom);
@@ -304,24 +305,6 @@
return 0;
}
- int track = psx_disc_get_track_number(cdrom->disc, cdrom->lba);
-
- // Sense a track change
- if ((track != cdrom->cdda_prev_track) && (cdrom->mode & MODE_AUTOPAUSE)) {- cdrom->cdda_remaining_samples = 0;
- cdrom->cdda_sample_index = 0;
- cdrom->state = CD_STATE_IDLE;
-
- memset(buf, 0, size);
-
- // Send autopause IRQ (INT4)
- cdrom_send_autopause_irq(cdrom);
-
- return 0;
- } else {- cdrom->cdda_prev_track = track;
- }
-
cdrom->cdda_remaining_samples = CD_SECTOR_SIZE >> 1;
cdrom->cdda_sample_index = 0;
@@ -339,8 +322,30 @@
int track = psx_disc_get_track_number(cdrom->disc, cdrom->lba);
int track_lba = psx_disc_get_track_lba(cdrom->disc, track);
- int32_t diff = cdrom->lba - track_lba;
+ // Sense a track change
+ if ((track != cdrom->cdda_prev_track) && (cdrom->mode & MODE_AUTOPAUSE)) {+ cdrom->cdda_remaining_samples = 0;
+ cdrom->cdda_sample_index = 0;
+ cdrom->state = CD_STATE_IDLE;
+ cdrom->cdda_prev_track = 0;
+ cdrom->cdda_playing = 0;
+ printf("prev_track=%u track=%u\n", cdrom->cdda_prev_track, track);+
+ cdrom_send_autopause_irq(cdrom);
+
+ return;
+ } else {+ cdrom->cdda_prev_track = track;
+ }
+
+ int relative = (cdrom->cdda_sectors_played & 0x10) != 0;
+
+ int32_t diff = cdrom->lba;
+
+ if (relative)
+ diff = cdrom->lba - track_lba;
+
if (diff < 0)
diff = -diff;
@@ -348,9 +353,10 @@
int ss = (diff % (60 * 75)) / 75;
int ff = (diff % (60 * 75)) % 75;
- printf("report: track %u %02u:%02u:%02u\n",+ printf("report: track %u %02u:%02u:%02u relative=%d\n",track,
- mm, ss, ff
+ mm, ss, ff,
+ relative
);
queue_push(cdrom->response, cdrom_get_stat(cdrom));
@@ -357,7 +363,7 @@
queue_push(cdrom->response, ITOB(track));
queue_push(cdrom->response, 1);
queue_push(cdrom->response, ITOB(mm));
- queue_push(cdrom->response, ITOB(ss) | 0x80);
+ queue_push(cdrom->response, ITOB(ss) | (relative ? 0x80 : 0));
queue_push(cdrom->response, ITOB(ff));
queue_push(cdrom->response, 0);
queue_push(cdrom->response, 0);
@@ -393,10 +399,10 @@
++cdrom->cdda_sectors_played;
- if (cdrom->cdda_sectors_played == 75) {+ if ((cdrom->cdda_sectors_played & 0xf) == 0) {cdrom_send_report_irq(cdrom);
- cdrom->cdda_sectors_played = 0;
+ cdrom->cdda_sectors_played &= 0x3f;
}
}
--- a/psx/dev/cdrom/cdrom.c
+++ b/psx/dev/cdrom/cdrom.c
@@ -205,9 +205,7 @@
}
int cdrom_get_seek_delay(psx_cdrom_t* cdrom, int ts) {- int delay = CD_DELAY_FR;
-
- delay += cdrom->pending_speed_switch_delay;
+ int delay = cdrom->pending_speed_switch_delay;
cdrom->pending_speed_switch_delay = 0;
--- a/psx/dev/cdrom/cdrom.h
+++ b/psx/dev/cdrom/cdrom.h
@@ -34,7 +34,7 @@
#define CD_DELAY_STOP_DS 25845878
#define CD_DELAY_READ_SS (33868800 / 75)
#define CD_DELAY_READ_DS (33868800 / (2*75))
-#define CD_DELAY_START_READ (cdrom_get_read_delay(cdrom))
+#define CD_DELAY_START_READ (cdrom_get_read_delay(cdrom) + cdrom_get_seek_delay(cdrom, ts))
#define CD_DELAY_ONGOING_READ (cdrom_get_read_delay(cdrom) + (CD_DELAY_1MS * 4))
#define XA_STEREO_SAMPLES 2016 // Samples per sector
--- a/psx/dev/cdrom/impl.c
+++ b/psx/dev/cdrom/impl.c
@@ -162,6 +162,8 @@
queue_push(cdrom->response, cdrom_get_stat(cdrom));
+ cdrom_process_setloc(cdrom);
+
int track = -1;
if (!queue_is_empty(cdrom->parameters)) {@@ -168,13 +170,11 @@
int track = BTOI(queue_pop(cdrom->parameters));
if (track)
- cdrom->pending_lba = psx_disc_get_track_lba(cdrom->disc, track);
+ cdrom->lba = psx_disc_get_track_lba(cdrom->disc, track);
} else {- track = psx_disc_get_track_number(cdrom->disc, cdrom->pending_lba);
+ track = psx_disc_get_track_number(cdrom->disc, cdrom->lba);
}
- cdrom_process_setloc(cdrom);
-
int mm = cdrom->lba / (60 * 75);
int ss = (cdrom->lba % (60 * 75)) / 75;
int ff = (cdrom->lba % (60 * 75)) % 75;
@@ -234,7 +234,7 @@
cdrom->state = CD_STATE_READ;
cdrom->prev_state = CD_STATE_READ;
- cdrom->delay = cdrom_get_seek_delay(cdrom, ts);
+ cdrom->delay = CD_DELAY_START_READ;
cdrom->read_ongoing = 1;
}
@@ -274,13 +274,7 @@
cdrom_process_setloc(cdrom);
- cdrom->prev_state = CD_STATE_IDLE;
- cdrom->state = CD_STATE_IDLE;
- cdrom->pending_command = 0;
- cdrom->busy = 0;
- cdrom->cdda_playing = 0;
- cdrom->xa_playing = 0;
- cdrom->read_ongoing = 0;
+ cdrom_pause(cdrom);
}
}
@@ -291,14 +285,8 @@
queue_push(cdrom->response, cdrom_get_stat(cdrom));
// Pausing at 1x takes 70ms, 2x takes 35ms
- if (!cdrom->read_ongoing) {- cdrom->delay = 7000;
- } else {- cdrom->delay = cdrom_get_pause_delay(cdrom);
- }
-
+ cdrom->delay = cdrom_get_pause_delay(cdrom);
cdrom->state = CD_STATE_TX_RESP2;
- cdrom->busy = 1;
} else {cdrom_set_int(cdrom, 2);
@@ -492,7 +480,7 @@
int tn = psx_disc_get_track_count(cdrom->disc);
- printf("tn=%u (%02x)\n", tn, ITOB(tn));+ printf("getstat=%02x\n", cdrom_get_stat(cdrom));queue_push(cdrom->response, cdrom_get_stat(cdrom));
queue_push(cdrom->response, 1);
@@ -718,7 +706,7 @@
cdrom->state = CD_STATE_READ;
cdrom->prev_state = CD_STATE_READ;
- cdrom->delay = cdrom_get_seek_delay(cdrom, ts);
+ cdrom->delay = CD_DELAY_START_READ;
cdrom->read_ongoing = 1;
}
--
⑨