Find_CurTrack(cdr.SetSectorPlay);
if (!Config.Cdda)
CDR_play(cdr.SetSectorPlay);
- if (psxRegs.interrupt & (1 << PSXINT_CDRPLAY_OLD))
- CDRPLAYREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 1);
}
if ((cdr.freeze_ver & 0xffffff00) != 0x63647200) {
next_interupt = c + min;
}
-static void unusedInterrupt()
-{
-}
-
typedef void (irq_func)();
static irq_func * const irq_funcs[] = {
[PSXINT_GPUOTCDMA] = gpuotcInterrupt,
[PSXINT_CDRDMA] = cdrDmaInterrupt,
[PSXINT_CDRLID] = cdrLidSeekInterrupt,
- [PSXINT_CDRPLAY_OLD] = unusedInterrupt,
+ [PSXINT_IRQ10] = irq10Interrupt,
[PSXINT_SPU_UPDATE] = spuUpdate,
[PSXINT_RCNT] = psxRcntUpdate,
};
static void map_rcnt_rcount0(u32 mode)
{
- if (mode & 0x100) { // pixel clock
+ if (mode & 0x001) { // sync mode
+ map_item(&mem_iortab[IOMEM32(0x1100)], psxRcntRcount0, 1);
+ map_item(&mem_iortab[IOMEM16(0x1100)], psxRcntRcount0, 1);
+ }
+ else if (mode & 0x100) { // pixel clock
map_item(&mem_iortab[IOMEM32(0x1100)], rcnt0_read_count_m1, 1);
map_item(&mem_iortab[IOMEM16(0x1100)], rcnt0_read_count_m1, 1);
}
static void map_rcnt_rcount1(u32 mode)
{
- if (mode & 0x100) { // hcnt
+ if (mode & 0x001) { // sync mode
+ map_item(&mem_iortab[IOMEM32(0x1110)], psxRcntRcount1, 1);
+ map_item(&mem_iortab[IOMEM16(0x1110)], psxRcntRcount1, 1);
+ }
+ else if (mode & 0x100) { // hcnt
map_item(&mem_iortab[IOMEM32(0x1110)], rcnt1_read_count_m1, 1);
map_item(&mem_iortab[IOMEM16(0x1110)], rcnt1_read_count_m1, 1);
}
static void map_rcnt_rcount2(u32 mode)
{
- if (mode & 0x01) { // gate
+ if ((mode & 7) == 1 || (mode & 7) == 7) { // sync mode
map_item(&mem_iortab[IOMEM32(0x1120)], &psxH[0x1000], 0);
map_item(&mem_iortab[IOMEM16(0x1120)], &psxH[0x1000], 0);
}
#endif
#define make_rcnt_funcs(i) \
-static u32 io_rcnt_read_count##i() { return psxRcntRcount(i); } \
static u32 io_rcnt_read_mode##i() { return psxRcntRmode(i); } \
static u32 io_rcnt_read_target##i() { return psxRcntRtarget(i); } \
static void io_rcnt_write_count##i(u32 val) { psxRcntWcount(i, val & 0xffff); } \
}
map_item(&mem_iortab[IOMEM32(0x1040)], io_read_sio32, 1);
- map_item(&mem_iortab[IOMEM16(0x1044)], sioReadStat16, 1);
- map_item(&mem_iortab[IOMEM32(0x1100)], io_rcnt_read_count0, 1);
+ map_item(&mem_iortab[IOMEM32(0x1100)], psxRcntRcount0, 1);
map_item(&mem_iortab[IOMEM32(0x1104)], io_rcnt_read_mode0, 1);
map_item(&mem_iortab[IOMEM32(0x1108)], io_rcnt_read_target0, 1);
- map_item(&mem_iortab[IOMEM32(0x1110)], io_rcnt_read_count1, 1);
+ map_item(&mem_iortab[IOMEM32(0x1110)], psxRcntRcount1, 1);
map_item(&mem_iortab[IOMEM32(0x1114)], io_rcnt_read_mode1, 1);
map_item(&mem_iortab[IOMEM32(0x1118)], io_rcnt_read_target1, 1);
- map_item(&mem_iortab[IOMEM32(0x1120)], io_rcnt_read_count2, 1);
+ map_item(&mem_iortab[IOMEM32(0x1120)], psxRcntRcount2, 1);
map_item(&mem_iortab[IOMEM32(0x1124)], io_rcnt_read_mode2, 1);
map_item(&mem_iortab[IOMEM32(0x1128)], io_rcnt_read_target2, 1);
// map_item(&mem_iortab[IOMEM32(0x1810)], GPU_readData, 1);
map_item(&mem_iortab[IOMEM16(0x1048)], sioReadMode16, 1);
map_item(&mem_iortab[IOMEM16(0x104a)], sioReadCtrl16, 1);
map_item(&mem_iortab[IOMEM16(0x104e)], sioReadBaud16, 1);
- map_item(&mem_iortab[IOMEM16(0x1100)], io_rcnt_read_count0, 1);
+ map_item(&mem_iortab[IOMEM16(0x1100)], psxRcntRcount0, 1);
map_item(&mem_iortab[IOMEM16(0x1104)], io_rcnt_read_mode0, 1);
map_item(&mem_iortab[IOMEM16(0x1108)], io_rcnt_read_target0, 1);
- map_item(&mem_iortab[IOMEM16(0x1110)], io_rcnt_read_count1, 1);
+ map_item(&mem_iortab[IOMEM16(0x1110)], psxRcntRcount1, 1);
map_item(&mem_iortab[IOMEM16(0x1114)], io_rcnt_read_mode1, 1);
map_item(&mem_iortab[IOMEM16(0x1118)], io_rcnt_read_target1, 1);
- map_item(&mem_iortab[IOMEM16(0x1120)], io_rcnt_read_count2, 1);
+ map_item(&mem_iortab[IOMEM16(0x1120)], psxRcntRcount2, 1);
map_item(&mem_iortab[IOMEM16(0x1124)], io_rcnt_read_mode2, 1);
map_item(&mem_iortab[IOMEM16(0x1128)], io_rcnt_read_target2, 1);
PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
#endif
- a0&= 0x3;
- if (a0 != 3) v0 = psxRcntRcount(a0);
- else v0 = 0;
+ switch (a0 & 0x3)
+ {
+ case 0: v0 = psxRcntRcount0(); break;
+ case 1: v0 = psxRcntRcount1(); break;
+ case 2: v0 = psxRcntRcount2(); break;
+ case 3: v0 = 0; break;
+ }
pc0 = ra;
}
enum
{
- Rc0Gate = 0x0001, // 0 not implemented
- Rc1Gate = 0x0001, // 0 not implemented
- Rc2Disable = 0x0001, // 0 partially implemented
- RcUnknown1 = 0x0002, // 1 ?
- RcUnknown2 = 0x0004, // 2 ?
+ RcSyncModeEnable = 0x0001, // 0
+ Rc01BlankPause = 0 << 1, // 1,2
+ Rc01UnblankReset = 1 << 1, // 1,2
+ Rc01UnblankReset2 = 2 << 1, // 1,2
+ Rc2Stop = 0 << 1, // 1,2
+ Rc2Stop2 = 3 << 1, // 1,2
RcCountToTarget = 0x0008, // 3
RcIrqOnTarget = 0x0010, // 4
RcIrqOnOverflow = 0x0020, // 5
}
// TODO: wcount must work.
- if( value & Rc2Disable )
+ if( (value & 7) == (RcSyncModeEnable | Rc2Stop) ||
+ (value & 7) == (RcSyncModeEnable | Rc2Stop2) )
{
rcnts[index].rate = 0xffffffff;
}
void psxRcntUpdate()
{
- u32 cycle;
+ u32 cycle, cycles_passed;
cycle = psxRegs.cycle;
// rcnt 0.
- while( cycle - rcnts[0].cycleStart >= rcnts[0].cycle )
+ cycles_passed = cycle - rcnts[0].cycleStart;
+ while( cycles_passed >= rcnts[0].cycle )
{
- psxRcntReset( 0 );
+ if (((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) ||
+ (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2))
+ && cycles_passed > PSXCLK / 60 / 263)
+ {
+ u32 q = cycles_passed / (PSXCLK / 60 / 263 + 1u);
+ rcnts[0].cycleStart += q * (PSXCLK / 60) / 263u;
+ break;
+ }
+ else
+ psxRcntReset( 0 );
+
+ cycles_passed = cycle - rcnts[0].cycleStart;
}
// rcnt 1.
// Update lace.
if( hSyncCount >= HSyncTotal[Config.PsxType] )
{
- u32 status, field = 0;
+ u32 status, field = 0, i;
rcnts[3].cycleStart += Config.PsxType ? PSXCLK / 50 : PSXCLK / 60;
hSyncCount = 0;
frame_counter++;
}
HW_GPU_STATUS = SWAP32(status);
GPU_vBlank(0, field);
+
+ for (i = 0; i < 2; i++)
+ {
+ if ((rcnts[i].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) ||
+ (rcnts[i].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2))
+ {
+ rcnts[i].cycleStart = rcnts[3].cycleStart;
+ }
+ }
}
scheduleRcntBase();
/******************************************************************************/
-u32 psxRcntRcount( u32 index )
+u32 psxRcntRcount0()
+{
+ u32 index = 0;
+ u32 count;
+
+ if ((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) ||
+ (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2))
+ {
+ count = psxRegs.cycle - rcnts[index].cycleStart;
+ count = ((16u * count) % (16u * PSXCLK / 60 / 263)) / 16u;
+ rcnts[index].cycleStart = psxRegs.cycle - count;
+ }
+ else
+ count = _psxRcntRcount( index );
+
+ verboseLog( 2, "[RCNT 0] rcount: %04x m: %04x\n", count, rcnts[index].mode);
+
+ return count;
+}
+
+u32 psxRcntRcount1()
+{
+ u32 index = 1;
+ u32 count;
+
+ count = _psxRcntRcount( index );
+
+ verboseLog( 2, "[RCNT 1] rcount: %04x m: %04x\n", count, rcnts[index].mode);
+
+ return count;
+}
+
+u32 psxRcntRcount2()
{
+ u32 index = 2;
u32 count;
count = _psxRcntRcount( index );
- verboseLog( 2, "[RCNT %i] rcount: %x\n", index, count );
+ verboseLog( 2, "[RCNT 2] rcount: %04x m: %04x\n", count, rcnts[index].mode);
return count;
}
void psxRcntWmode(u32 index, u32 value);
void psxRcntWtarget(u32 index, u32 value);
-u32 psxRcntRcount(u32 index);
+u32 psxRcntRcount0();
+u32 psxRcntRcount1();
+u32 psxRcntRcount2();
u32 psxRcntRmode(u32 index);
u32 psxRcntRtarget(u32 index);
return 0x80;\r
case 0x1f801100:
- hard = psxRcntRcount(0);
+ hard = psxRcntRcount0();
#ifdef PSXHW_LOG
PSXHW_LOG("T0 count read16: %x\n", hard);
#endif
#endif
return hard;
case 0x1f801110:
- hard = psxRcntRcount(1);
+ hard = psxRcntRcount1();
#ifdef PSXHW_LOG
PSXHW_LOG("T1 count read16: %x\n", hard);
#endif
#endif
return hard;
case 0x1f801120:
- hard = psxRcntRcount(2);
+ hard = psxRcntRcount2();
#ifdef PSXHW_LOG
PSXHW_LOG("T2 count read16: %x\n", hard);
#endif
// time for rootcounters :)
case 0x1f801100:
- hard = psxRcntRcount(0);
+ hard = psxRcntRcount0();
#ifdef PSXHW_LOG
PSXHW_LOG("T0 count read32: %x\n", hard);
#endif
#endif
return hard;
case 0x1f801110:
- hard = psxRcntRcount(1);
+ hard = psxRcntRcount1();
#ifdef PSXHW_LOG
PSXHW_LOG("T1 count read32: %x\n", hard);
#endif
#endif
return hard;
case 0x1f801120:
- hard = psxRcntRcount(2);
+ hard = psxRcntRcount2();
#ifdef PSXHW_LOG
PSXHW_LOG("T2 count read32: %x\n", hard);
#endif
cdrLidSeekInterrupt();
}
}
+ if (psxRegs.interrupt & (1 << PSXINT_IRQ10)) { // irq10 - controller port pin8
+ if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_IRQ10].sCycle) >= psxRegs.intCycle[PSXINT_IRQ10].cycle) {
+ psxRegs.interrupt &= ~(1 << PSXINT_IRQ10);
+ irq10Interrupt();
+ }
+ }
if (psxRegs.interrupt & (1 << PSXINT_SPU_UPDATE)) { // scheduled spu update
if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_SPU_UPDATE].sCycle) >= psxRegs.intCycle[PSXINT_SPU_UPDATE].cycle) {
psxRegs.interrupt &= ~(1 << PSXINT_SPU_UPDATE);
SysPrintf("non-standard BIOS detected (%d, %08x)\n", i, psxRegs.pc);
}
+// irq10 stuff, very preliminary
+static int irq10count;
+
+static void psxScheduleIrq10One(u32 cycles_abs) {
+ // schedule relative to frame start
+ u32 c = cycles_abs - rcnts[3].cycleStart;
+ assert((s32)c >= 0);
+ psxRegs.interrupt |= 1 << PSXINT_IRQ10;
+ psxRegs.intCycle[PSXINT_IRQ10].cycle = c;
+ psxRegs.intCycle[PSXINT_IRQ10].sCycle = rcnts[3].cycleStart;
+ new_dyna_set_event(PSXINT_IRQ10, c);
+}
+
+void irq10Interrupt() {
+ u32 prevc = psxRegs.intCycle[PSXINT_IRQ10].sCycle
+ + psxRegs.intCycle[PSXINT_IRQ10].cycle;
+
+ psxHu32ref(0x1070) |= SWAPu32(0x400);
+
+#if 0
+ s32 framec = psxRegs.cycle - rcnts[3].cycleStart;
+ printf("%d:%03d irq10 #%d %3d m=%d,%d\n", frame_counter,
+ (s32)((float)framec / (PSXCLK / 60 / 263.0f)),
+ irq10count, psxRegs.cycle - prevc,
+ (psxRegs.CP0.n.SR & 0x401) != 0x401, !(psxHu32(0x1074) & 0x400));
+#endif
+ if (--irq10count > 0)
+ psxScheduleIrq10One(prevc + PSXCLK / 60 / 263);
+}
+
+void psxScheduleIrq10(int irq_count, int x_cycles, int y) {
+ //printf("%s %d, %d, %d\n", __func__, irq_count, x_cycles, y);
+ u32 cycles_per_frame = Config.PsxType ? PSXCLK / 50 : PSXCLK / 60;
+ u32 cycles = rcnts[3].cycleStart + cycles_per_frame;
+ cycles += y * cycles_per_frame / (Config.PsxType ? 314 : 263);
+ cycles += x_cycles;
+ psxScheduleIrq10One(cycles);
+ irq10count = irq_count;
+}
PSXINT_NEWDRC_CHECK,
PSXINT_RCNT,
PSXINT_CDRLID,
- PSXINT_CDRPLAY_OLD, /* unused */
+ PSXINT_IRQ10,
PSXINT_SPU_UPDATE,
PSXINT_COUNT
};
void psxExecuteBios();
void psxJumpTest();
+void irq10Interrupt();
+void psxScheduleIrq10(int irq_count, int x_cycles, int y);
+
#ifdef __cplusplus
}
#endif