From 51d6248b95d411128e0998f40e7ef9f13e735c2d Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 28 Mar 2024 21:39:12 +0100 Subject: [PATCH 01/44] md, fix vdp reset handling --- pico/pico.c | 14 ++------------ pico/pico_int.h | 1 + pico/videoport.c | 34 +++++++++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/pico/pico.c b/pico/pico.c index cc5ef7cc8..1d60afd51 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -72,18 +72,11 @@ void PicoPower(void) memset(&Pico.m,0,sizeof(Pico.m)); memset(&Pico.t,0,sizeof(Pico.t)); - Pico.video.pending_ints=0; z80_reset(); // my MD1 VA6 console has this in IO PicoMem.ioports[1] = PicoMem.ioports[2] = PicoMem.ioports[3] = 0xff; - // default VDP register values (based on Fusion) - Pico.video.reg[0] = Pico.video.reg[1] = 0x04; - Pico.video.reg[0xc] = 0x81; - Pico.video.reg[0xf] = 0x02; - PicoVideoFIFOMode(0, 1); - if (PicoIn.AHW & PAHW_MCD) PicoPowerMCD(); @@ -178,20 +171,17 @@ int PicoReset(void) // s68k doesn't have the TAS quirk, so we just globally set normal TAS handler in MCD mode (used by Batman games). SekSetRealTAS(PicoIn.AHW & PAHW_MCD); - Pico.m.dirtyPal = 1; - Pico.m.z80_bank68k = 0; Pico.m.z80_reset = 1; PicoDetectRegion(); - Pico.video.status = 0x3428 | Pico.m.pal; // 'always set' bits | vblank | collision | pal - Pico.video.hint_irq = (PicoIn.AHW & PAHW_PICO ? 5 : 4); + + PicoVideoReset(); PsndReset(); // pal must be known here // create an empty "dma" to cause 68k exec start at random frame location Pico.t.m68c_line_start = Pico.t.m68c_aim; - PicoDrawBgcDMA(NULL, 0, 0, 0, 0); PicoVideoFIFOWrite(rand() & 0x1fff, 0, 0, PVS_CPURD); SekFinishIdleDet(); diff --git a/pico/pico_int.h b/pico/pico_int.h index 31802f4ca..d39e98096 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -958,6 +958,7 @@ int PicoVideoFIFOHint(void); void PicoVideoFIFOMode(int active, int h40); int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags); void PicoVideoInit(void); +void PicoVideoReset(void); void PicoVideoSync(int skip); void PicoVideoSave(void); void PicoVideoLoad(void); diff --git a/pico/videoport.c b/pico/videoport.c index d4a986f1e..1cf93a4b8 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -986,11 +986,13 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) default: return; } - SATaddr = ((pvid->reg[5]&0x7f) << 9) | ((pvid->reg[6]&0x20) << 11); - SATmask = ~0x1ff; - if (pvid->reg[12]&1) - SATaddr &= ~0x200, SATmask &= ~0x200; // H40, zero lowest SAT bit - //elprintf(EL_STATUS, "spritep moved to %04x", SATaddr); + if (Pico.est.rendstatus & PDRAW_DIRTY_SPRITES) { + SATaddr = ((pvid->reg[5]&0x7f) << 9) | ((pvid->reg[6]&0x20) << 11); + SATmask = ~0x1ff; + if (pvid->reg[12]&1) + SATaddr &= ~0x200, SATmask &= ~0x200; // H40, zero lowest SAT bit + //elprintf(EL_STATUS, "spritep moved to %04x", SATaddr); + } return; update_irq: @@ -1160,6 +1162,28 @@ unsigned char PicoVideoRead8HV_L(int is_from_z80) return d; } +void PicoVideoReset(void) +{ + Pico.video.hint_irq = (PicoIn.AHW & PAHW_PICO ? 5 : 4); + Pico.video.pending_ints=0; + + // default VDP register values (based on Fusion) + Pico.video.reg[0] = Pico.video.reg[1] = 0x04; + Pico.video.reg[0xc] = 0x81; + Pico.video.reg[0xf] = 0x02; + SATaddr = 0x0000; + SATmask = ~0x1ff; + + memset(VdpSATCache, 0, sizeof(VdpSATCache)); + memset(&VdpFIFO, 0, sizeof(VdpFIFO)); + Pico.m.dirtyPal = 1; + + Pico.video.status = 0x3428 | Pico.m.pal; // 'always set' bits | vblank | collision | pal + + PicoDrawBgcDMA(NULL, 0, 0, 0, 0); + PicoVideoFIFOMode(0, 1); +} + void PicoVideoCacheSAT(int load) { struct PicoVideo *pv = &Pico.video; From c7661b80ef4a8543cfe598f2f08f57bebe542111 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 12 Apr 2024 20:08:33 +0200 Subject: [PATCH 02/44] md, fix vdp reset handling --- pico/pico.c | 9 +++++++++ pico/videoport.c | 15 ++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pico/pico.c b/pico/pico.c index 1d60afd51..340265779 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -77,6 +77,15 @@ void PicoPower(void) // my MD1 VA6 console has this in IO PicoMem.ioports[1] = PicoMem.ioports[2] = PicoMem.ioports[3] = 0xff; + // powerup default VDP register values from TMSS BIOS + Pico.video.reg[0] = Pico.video.reg[1] = 0x04; + Pico.video.reg[0xc] = 0x81; + Pico.video.reg[0xf] = 0x02; + SATaddr = 0x0000; + SATmask = ~0x3ff; + + Pico.video.hint_irq = (PicoIn.AHW & PAHW_PICO ? 5 : 4); + if (PicoIn.AHW & PAHW_MCD) PicoPowerMCD(); diff --git a/pico/videoport.c b/pico/videoport.c index 1cf93a4b8..b4d676776 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -982,6 +982,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) case 0x0c: // renderers should update their palettes if sh/hi mode is changed if ((d^dold)&8) Pico.m.dirtyPal = 1; + if ((d^dold)&1) Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; break; default: return; @@ -1164,22 +1165,14 @@ unsigned char PicoVideoRead8HV_L(int is_from_z80) void PicoVideoReset(void) { - Pico.video.hint_irq = (PicoIn.AHW & PAHW_PICO ? 5 : 4); Pico.video.pending_ints=0; + Pico.video.reg[1] &= ~0x40; // TODO verify display disabled after reset + Pico.video.reg[10] = 0xff; // HINT is turned off after reset + Pico.video.status = 0x3428 | Pico.m.pal; // 'always set' bits | vblank | collision | pal - // default VDP register values (based on Fusion) - Pico.video.reg[0] = Pico.video.reg[1] = 0x04; - Pico.video.reg[0xc] = 0x81; - Pico.video.reg[0xf] = 0x02; - SATaddr = 0x0000; - SATmask = ~0x1ff; - - memset(VdpSATCache, 0, sizeof(VdpSATCache)); memset(&VdpFIFO, 0, sizeof(VdpFIFO)); Pico.m.dirtyPal = 1; - Pico.video.status = 0x3428 | Pico.m.pal; // 'always set' bits | vblank | collision | pal - PicoDrawBgcDMA(NULL, 0, 0, 0, 0); PicoVideoFIFOMode(0, 1); } From db2b6d996608f7323b04dcf425bee2796a36dbbe Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 12 Apr 2024 20:29:50 +0200 Subject: [PATCH 03/44] core z80, fix cycle counting in reset state --- pico/debug.c | 2 +- pico/pico.c | 3 +-- pico/pico_cmn.c | 2 +- pico/pico_int.h | 4 ++-- pico/sms.c | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pico/debug.c b/pico/debug.c index e928d73bb..5a85a30ad 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -389,7 +389,7 @@ void PDebugZ80Frame(void) else lines = 262; - z80_resetCycles(); + z80_resetCycles(Pico.t.z80c_aim); PsndStartFrame(); if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) { diff --git a/pico/pico.c b/pico/pico.c index 340265779..d913e0822 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -72,8 +72,6 @@ void PicoPower(void) memset(&Pico.m,0,sizeof(Pico.m)); memset(&Pico.t,0,sizeof(Pico.t)); - z80_reset(); - // my MD1 VA6 console has this in IO PicoMem.ioports[1] = PicoMem.ioports[2] = PicoMem.ioports[3] = 0xff; @@ -169,6 +167,7 @@ int PicoReset(void) memset(&PicoIn.padInt, 0, sizeof(PicoIn.padInt)); + z80_reset(); if (PicoIn.AHW & PAHW_SMS) { PicoResetMS(); return 0; diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index c3b14caa6..519aba351 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -141,8 +141,8 @@ static int PicoFrameHints(void) skip = PicoIn.skipFrame; + z80_resetCycles(cycles_68k_to_z80(Pico.t.m68c_aim - Pico.t.m68c_frame_start)); Pico.t.m68c_frame_start = Pico.t.m68c_aim; - z80_resetCycles(); PsndStartFrame(); hint = pv->hint_cnt; diff --git a/pico/pico_int.h b/pico/pico_int.h index d39e98096..c576ecbf4 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -201,8 +201,8 @@ extern struct DrZ80 drZ80; #define Z80_STATE_SIZE 0x60 -#define z80_resetCycles() \ - Pico.t.z80c_cnt -= Pico.t.z80c_aim, Pico.t.z80c_aim = Pico.t.z80_scanline = 0 +#define z80_resetCycles(aim) \ + Pico.t.z80c_cnt -= (aim < Pico.t.z80c_cnt ? aim : Pico.t.z80c_cnt), Pico.t.z80c_aim = Pico.t.z80_scanline = 0 #define z80_cyclesDone() \ (Pico.t.z80c_aim - z80_cyclesLeft) diff --git a/pico/sms.c b/pico/sms.c index 6b1425b25..e954bc8b9 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -846,7 +846,7 @@ void PicoFrameMS(void) int nmi; int y; - z80_resetCycles(); + z80_resetCycles(Pico.t.z80c_aim); PsndStartFrame(); // for SMS the pause button generates an NMI, for GG ths is not the case From 44479027112489b8bbe4a03eb08d49ec9d57554f Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 19 Apr 2024 20:53:52 +0200 Subject: [PATCH 04/44] mcd, revisit track handling in cdd --- pico/cd/cdd.c | 372 ++++++++++++++------------------------------------ 1 file changed, 102 insertions(+), 270 deletions(-) diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index 78fae75d9..9715c679e 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -196,67 +196,52 @@ static void cdd_change_track(int index, int lba) cdda_start_play(base, lba_offset, lb_len); } -int cdd_context_save(uint8 *state) -{ - int bufferptr = 0; - - save_param(&cdd.cycles, sizeof(cdd.cycles)); - save_param(&cdd.latency, sizeof(cdd.latency)); - save_param(&cdd.index, sizeof(cdd.index)); - save_param(&cdd.lba, sizeof(cdd.lba)); - save_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); - save_param(&cdd.volume, sizeof(cdd.volume)); - save_param(&cdd.status, sizeof(cdd.status)); - - return bufferptr; -} +static off_t read_pos = -1; -int cdd_context_load(uint8 *state) +void cdd_seek(int index, int lba) { - int lba; - int bufferptr = 0; + int aindex = (index < 0 ? -index : index); #ifdef USE_LIBTREMOR #ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) + /* check if track index has changed */ + if (index != cdd.index) { - ogg_free(cdd.index); + /* close previous track VORBIS file structure to save memory */ + if (cdd.index >= 0 && cdd.toc.tracks[cdd.index].vf.datasource) + { + ogg_free(cdd.index); + } + + /* open current track VORBIS file */ + if (cdd.toc.tracks[aindex].vf.seekable) + { + ov_open(cdd.toc.tracks[aindex].fd,&cdd.toc.tracks[aindex].vf,0,0); + } } #endif #endif - load_param(&cdd.cycles, sizeof(cdd.cycles)); - load_param(&cdd.latency, sizeof(cdd.latency)); - load_param(&cdd.index, sizeof(cdd.index)); - load_param(&cdd.lba, sizeof(cdd.lba)); - load_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); - load_param(&cdd.volume, sizeof(cdd.volume)); - load_param(&cdd.status, sizeof(cdd.status)); + /* update current track index and LBA */ + cdd.index = aindex; + cdd.lba = lba; - /* adjust current LBA within track limit */ - lba = cdd.lba; + /* stay within track limits when seeking files */ if (lba < cdd.toc.tracks[cdd.index].start) { lba = cdd.toc.tracks[cdd.index].start; } - /* seek to current track position */ + /* seek to current block */ if (!is_audio(cdd.index)) { /* DATA track */ - if (cdd.toc.tracks[cdd.index].fd) - { - pm_seek(cdd.toc.tracks[cdd.index].fd, lba * cdd.sectorSize, SEEK_SET); - } + read_pos = lba * cdd.sectorSize; + pm_seek(cdd.toc.tracks[cdd.index].fd, read_pos, SEEK_SET); } #ifdef USE_LIBTREMOR else if (cdd.toc.tracks[cdd.index].vf.seekable) { -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* VORBIS file need to be opened first */ - ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); -#endif /* VORBIS AUDIO track */ ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset); } @@ -273,6 +258,37 @@ int cdd_context_load(uint8 *state) cdd_change_track(cdd.index, lba); } #endif +} + +int cdd_context_save(uint8 *state) +{ + int bufferptr = 0; + + save_param(&cdd.cycles, sizeof(cdd.cycles)); + save_param(&cdd.latency, sizeof(cdd.latency)); + save_param(&cdd.index, sizeof(cdd.index)); + save_param(&cdd.lba, sizeof(cdd.lba)); + save_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); + save_param(&cdd.volume, sizeof(cdd.volume)); + save_param(&cdd.status, sizeof(cdd.status)); + + return bufferptr; +} + +int cdd_context_load(uint8 *state) +{ + int bufferptr = 0; + + load_param(&cdd.cycles, sizeof(cdd.cycles)); + load_param(&cdd.latency, sizeof(cdd.latency)); + load_param(&cdd.index, sizeof(cdd.index)); + load_param(&cdd.lba, sizeof(cdd.lba)); + load_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); + load_param(&cdd.volume, sizeof(cdd.volume)); + load_param(&cdd.status, sizeof(cdd.status)); + + /* seek to current track position */ + cdd_seek(-cdd.index, cdd.lba); return bufferptr; } @@ -280,6 +296,8 @@ int cdd_context_load(uint8 *state) int cdd_context_load_old(uint8 *state) { memcpy(&cdd.lba, state + 8, sizeof(cdd.lba)); + cdd_seek(-cdd.index, cdd.lba); + return 12 * 4; } @@ -510,17 +528,29 @@ int cdd_unload(void) void cdd_read_data(uint8 *dst) { /* only read DATA track sectors */ - if (!is_audio(cdd.index) && (cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[cdd.index].end)) + if (!is_audio(cdd.index) && (cdd.lba >= cdd.toc.tracks[cdd.index].start) && + (cdd.lba < cdd.toc.tracks[cdd.index].end)) { + off_t pos; + /* BIN format ? */ if (cdd.sectorSize == 2352) { /* skip 16-byte header */ - pm_seek(cdd.toc.tracks[cdd.index].fd, cdd.lba * 2352 + 16, SEEK_SET); + pos = cdd.lba * 2352 + 16; + } + else + { + pos = cdd.lba * cdd.sectorSize; + } + + if (pos != read_pos) { + pm_seek(cdd.toc.tracks[cdd.index].fd, pos, SEEK_SET); + read_pos = pos; } /* read sector data (Mode 1 = 2048 bytes) */ - pm_read(dst, 2048, cdd.toc.tracks[cdd.index].fd); + read_pos += pm_read(dst, 2048, cdd.toc.tracks[cdd.index].fd); } } @@ -719,7 +749,7 @@ void cdd_update(void) header[3] = 0x01; /* data track sector read is controlled by CDC */ - cdd.lba += cdc_decoder_update(header); + cdc_decoder_update(header); } else { @@ -734,51 +764,19 @@ void cdd_update(void) /* audio blocks are still sent to CDC as well as CD DAC/Fader */ cdc_decoder_update(header); - - /* next audio block is automatically read */ - cdd.lba++; } + + /* next block is automatically read */ + cdd.lba++; /* check end of current track */ if (cdd.lba >= cdd.toc.tracks[cdd.index].end) { -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } -#endif -#endif - /* play next track */ - cdd.index++; - /* PAUSE between tracks */ Pico_mcd->s68k_regs[0x36+0] = 0x01; /* seek to next audio track start */ -#ifdef USE_LIBTREMOR - if (cdd.toc.tracks[cdd.index].vf.seekable) - { -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* VORBIS file need to be opened first */ - ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); -#endif - ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset); - } - else -#endif -#if 0 - if (cdd.toc.tracks[cdd.index].fd) - { - fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); - } -#else - { - cdd_change_track(cdd.index, cdd.lba); - } -#endif + cdd_seek(cdd.index + 1, cdd.lba); } } @@ -791,100 +789,45 @@ void cdd_update(void) /* check current track limits */ if (cdd.lba >= cdd.toc.tracks[cdd.index].end) { -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } -#endif -#endif /* next track */ - cdd.index++; + if (cdd.index >= cdd.toc.last) + { + /* no AUDIO track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; - /* skip directly to track start position */ - cdd.lba = cdd.toc.tracks[cdd.index].start; - - /* AUDIO track playing ? */ - if (cdd.status == CD_PLAY) + /* end of disc */ + cdd.lba = cdd.toc.end; + cdd.status = CD_END; + } + else { - Pico_mcd->s68k_regs[0x36+0] = 0x00; + cdd_seek(cdd.index + 1, cdd.toc.tracks[cdd.index+1].start); + + /* AUDIO track playing ? */ + if (cdd.status == CD_PLAY && is_audio(cdd.index)) + { + Pico_mcd->s68k_regs[0x36+0] = 0x00; + } } } else if (cdd.lba < cdd.toc.tracks[cdd.index].start) { -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) + /* previous track */ + if (cdd.index <= 0) { - ogg_free(cdd.index); + cdd_seek(0, 0); + } + else + { + cdd_seek(cdd.index - 1, cdd.toc.tracks[cdd.index-1].end); } -#endif -#endif - - /* previous track */ - cdd.index--; - - /* skip directly to track end position */ - cdd.lba = cdd.toc.tracks[cdd.index].end; - } - - /* check disc limits */ - if (cdd.index < 0) - { - cdd.index = 0; - cdd.lba = 0; - } - else if (cdd.index >= cdd.toc.last) - { - /* no AUDIO track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; - - /* end of disc */ - cdd.index = cdd.toc.last; - cdd.lba = cdd.toc.end; - cdd.status = CD_END; - return; } - /* seek to current block */ if (!is_audio(cdd.index)) { /* no AUDIO track playing */ Pico_mcd->s68k_regs[0x36+0] = 0x01; - - /* DATA track */ - pm_seek(cdd.toc.tracks[cdd.index].fd, cdd.lba * cdd.sectorSize, SEEK_SET); } -#ifdef USE_LIBTREMOR - else if (cdd.toc.tracks[cdd.index].vf.seekable) - { -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* check if a new track is being played */ - if (!cdd.toc.tracks[cdd.index].vf.datasource) - { - /* VORBIS file need to be opened first */ - ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); - } -#endif - /* VORBIS AUDIO track */ - ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset); - } -#endif -#if 0 - else if (cdd.toc.tracks[cdd.index].fd) - { - /* PCM AUDIO track */ - fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); - } -#else - else - { - cdd_change_track(cdd.index, cdd.lba); - } -#endif } } @@ -910,7 +853,7 @@ void cdd_process(void) Pico_mcd->s68k_regs[0x38+1] == 0x00 || Pico_mcd->s68k_regs[0x38+1] == 0x01) { - int lba = cdd.lba + 150; + int lba = cdd.lba + 150 - cdd.latency; if (Pico_mcd->s68k_regs[0x38+1] == 0x01) lba = abs(cdd.lba - cdd.toc.tracks[cdd.index].start); if (Pico_mcd->s68k_regs[0x38+1] == 0x0f) @@ -1081,66 +1024,10 @@ void cdd_process(void) cdd.latency += (((cdd.lba - lba) * 120) / 270000); } - /* update current LBA */ - cdd.lba = lba; - /* get track index */ while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* check if track index has changed */ - if (index != cdd.index) - { - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } - - /* open current track VORBIS file */ - if (cdd.toc.tracks[index].vf.seekable) - { - ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0); - } - } -#endif -#endif - - /* update current track index */ - cdd.index = index; - - /* stay within track limits when seeking files */ - if (lba < cdd.toc.tracks[index].start) - { - lba = cdd.toc.tracks[index].start; - } - - /* seek to current block */ - if (!is_audio(cdd.index)) - { - /* DATA track */ - pm_seek(cdd.toc.tracks[cdd.index].fd, lba * cdd.sectorSize, SEEK_SET); - } -#ifdef USE_LIBTREMOR - else if (cdd.toc.tracks[index].vf.seekable) - { - /* VORBIS AUDIO track */ - ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset); - } -#endif -#if 0 - else if (cdd.toc.tracks[index].fd) - { - /* PCM AUDIO track */ - fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET); - } -#else - else - { - cdd_change_track(index, lba); - } -#endif + cdd_seek(index, lba); /* no audio track playing (yet) */ Pico_mcd->s68k_regs[0x36+0] = 0x01; @@ -1180,66 +1067,11 @@ void cdd_process(void) cdd.latency = ((cdd.lba - lba) * 120) / 270000; } - /* update current LBA */ - cdd.lba = lba; - /* get current track index */ while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* check if track index has changed */ - if (index != cdd.index) - { - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } - - /* open current track VORBIS file */ - if (cdd.toc.tracks[index].vf.seekable) - { - ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0); - } - } -#endif -#endif - - /* update current track index */ - cdd.index = index; - - /* stay within track limits */ - if (lba < cdd.toc.tracks[index].start) - { - lba = cdd.toc.tracks[index].start; - } - /* seek to current block */ - if (!is_audio(cdd.index)) - { - /* DATA track */ - pm_seek(cdd.toc.tracks[cdd.index].fd, lba * cdd.sectorSize, SEEK_SET); - } -#ifdef USE_LIBTREMOR - else if (cdd.toc.tracks[index].vf.seekable) - { - /* VORBIS AUDIO track */ - ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset); - } -#endif -#if 0 - else if (cdd.toc.tracks[index].fd) - { - /* PCM AUDIO track */ - fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET); - } -#else - else - { - cdd_change_track(index, lba); - } -#endif + cdd_seek(index, lba); /* no audio track playing */ Pico_mcd->s68k_regs[0x36+0] = 0x01; From 691abdfa0fe8668f8c9fa313f2691e89f7541f85 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 19 Apr 2024 21:08:09 +0200 Subject: [PATCH 05/44] mcd, some improvements (dma timing, interrupt handling) --- pico/cd/cdc.c | 15 ++++++++------- pico/cd/mcd.c | 5 ++--- pico/cd/memory.c | 21 ++++++++++++--------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/pico/cd/cdc.c b/pico/cd/cdc.c index de16acbc7..1163cb28a 100644 --- a/pico/cd/cdc.c +++ b/pico/cd/cdc.c @@ -66,6 +66,7 @@ /* PicoDrive: doing DMA at once, not using callbacks */ //#define DMA_BYTES_PER_LINE 512 +#define DMA_CYCLES_PER_BYTE 4 // or 6? enum dma_type { word_ram_0_dma_w = 1, @@ -354,7 +355,7 @@ void cdc_dma_update(void) do_dma(cdc.dma_w, cdc.dbc + 1); /* reset data byte counter (DBCH bits 4-7 should be set to 1) */ - cdc.dbc = 0xf000; + cdc.dbc = 0xffff; /* clear !DTEN and !DTBSY */ cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); @@ -405,6 +406,9 @@ int cdc_decoder_update(uint8 header[4]) /* set !VALST */ cdc.stat[3] = 0x00; + /* set CRCOK bit */ + cdc.stat[0] = BIT_DECEN; + /* pending decoder interrupt */ cdc.ifstat &= ~BIT_DECI; @@ -602,7 +606,7 @@ void cdc_reg_w(unsigned char data) } if (cdc.dma_w) - pcd_event_schedule_s68k(PCD_EVENT_DMA, cdc.dbc / 2); + pcd_event_schedule_s68k(PCD_EVENT_DMA, cdc.dbc * DMA_CYCLES_PER_BYTE); } Pico_mcd->s68k_regs[0x04+1] = 0x07; @@ -643,11 +647,8 @@ void cdc_reg_w(unsigned char data) case 0x0a: /* CTRL0 */ { - /* set CRCOK bit only if decoding is enabled */ - cdc.stat[0] = data & BIT_DECEN; - /* reset DECI if decoder turned off */ - if (!cdc.stat[0]) + if (!(data & BIT_DECEN)) cdc.ifstat |= BIT_DECI; /* update decoding mode */ @@ -827,7 +828,7 @@ unsigned short cdc_host_r(void) if ((int16)cdc.dbc <= 0) { /* reset data byte counter (DBCH bits 4-7 should be set to 1) */ - cdc.dbc = 0xf000; + cdc.dbc = 0xffff; /* clear !DTEN and !DTBSY */ cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 44376322d..2fdbe7252 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -149,7 +149,7 @@ static void pcd_cdc_event(unsigned int now) /* reset CDD command wait flag */ Pico_mcd->s68k_regs[0x4b] = 0xf0; - if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) { + if ((Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) && (Pico_mcd->s68k_regs[0x37] & 4)) { elprintf(EL_INTS|EL_CD, "s68k: cdd irq 4"); pcd_irq_s68k(4, 1); } @@ -209,8 +209,7 @@ void pcd_event_schedule(unsigned int now, enum pcd_event event, int after) void pcd_event_schedule_s68k(enum pcd_event event, int after) { - if (SekCyclesLeftS68k > after) - SekEndRunS68k(after); + SekEndRunS68k(after); pcd_event_schedule(SekCyclesDoneS68k(), event, after); } diff --git a/pico/cd/memory.c b/pico/cd/memory.c index b13644b13..fc4ddb725 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -142,7 +142,7 @@ static u32 m68k_reg_read16(u32 a) // comm flag/cmd/status (0xE-0x2F) m68k_comm_check(a); d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; - goto end; + return d; } elprintf(EL_UIO, "m68k_regs FIXME invalid read @ %02x", a); @@ -172,7 +172,8 @@ void m68k_reg_write8(u32 a, u32 d) elprintf(EL_INTS, "m68k: s68k irq 2"); pcd_sync_s68k(SekCyclesDone(), 0); pcd_irq_s68k(2, 1); - } + } else + pcd_irq_s68k(2, 0); return; case 1: d &= 3; @@ -456,9 +457,9 @@ void s68k_reg_write8(u32 a, u32 d) case 0x33: // IRQ mask elprintf(EL_CDREGS|EL_CD, "s68k irq mask: %02x", d); d &= 0x7e; - if ((d ^ Pico_mcd->s68k_regs[0x33]) & d & PCDS_IEN4) { + if ((d ^ Pico_mcd->s68k_regs[0x33]) & PCDS_IEN4) { // XXX: emulate pending irq instead? - if (Pico_mcd->s68k_regs[0x37] & 4) { + if ((d & PCDS_IEN4) && (Pico_mcd->s68k_regs[0x37] & 4)) { elprintf(EL_INTS, "cdd export irq 4 (unmask)"); pcd_irq_s68k(4, 1); } @@ -474,11 +475,12 @@ void s68k_reg_write8(u32 a, u32 d) case 0x37: { u32 d_old = Pico_mcd->s68k_regs[0x37]; Pico_mcd->s68k_regs[0x37] = d & 7; - if ((d&4) && !(d_old&4)) { + if ((d ^ d_old) & 4) { // ?? - pcd_event_schedule_s68k(PCD_EVENT_CDC, 12500000/75); + if (d & 4) + pcd_event_schedule_s68k(PCD_EVENT_CDC, 12500000/75); - if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) { + if ((d & 4) && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4)) { elprintf(EL_INTS, "cdd export irq 4"); pcd_irq_s68k(4, 1); } @@ -1223,9 +1225,10 @@ static void m68k_mem_setup_cd(void); PICO_INTERNAL void PicoMemSetupCD(void) { - if (!Pico_mcd) + if (!Pico_mcd) { Pico_mcd = plat_mmap(0x05000000, sizeof(mcd_state), 0, 0); - memset(Pico_mcd, 0, sizeof(mcd_state)); + memset(Pico_mcd, 0, sizeof(mcd_state)); + } pcd_base_address = (Pico.romsize > 0x20000 ? 0x400000 : 0x000000); // setup default main68k map From d9bb2921eeb861d5a5158c2757a0bc0566cd3021 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 21 Apr 2024 16:20:28 +0200 Subject: [PATCH 06/44] mcd, implement pre/post reading in play/read state --- pico/cd/cdd.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index 9715c679e..1db9a8f58 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -829,6 +829,12 @@ void cdd_update(void) Pico_mcd->s68k_regs[0x36+0] = 0x01; } } + + if (Pico_mcd->s68k_regs[0x4b] & 0x1) { + /* pending delayed command */ + cdd_process(); + Pico_mcd->s68k_regs[0x4b] &= ~0x1; + } } #define set_reg16(r, v) { \ @@ -844,7 +850,7 @@ void cdd_process(void) { case 0x00: /* Drive Status */ { - if (cdd.latency <= 3) { + if (cdd.latency == 0) { /* RS1-RS8 normally unchanged */ Pico_mcd->s68k_regs[0x38+0] = cdd.status; @@ -999,6 +1005,12 @@ void cdd_process(void) (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 + (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; + /* if drive is currently reading, another block or 2 are decoded before the seek starts */ + if (cdd.status == CD_PLAY && !(Pico_mcd->s68k_regs[0x4b] & 0x1)) { + Pico_mcd->s68k_regs[0x4b] |= 0x1; + return; + } + /* CD drive latency */ if (!cdd.latency) { @@ -1024,9 +1036,14 @@ void cdd_process(void) cdd.latency += (((cdd.lba - lba) * 120) / 270000); } + /* block transfer always starts 3 blocks earlier */ + cdd.latency -= 3; + lba -= 3; + /* get track index */ while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; + /* seek to block */ cdd_seek(index, lba); /* no audio track playing (yet) */ @@ -1041,7 +1058,7 @@ void cdd_process(void) set_reg16(0x3c, 0x0000); set_reg16(0x3e, 0x0000); set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f); - break; + return; } case 0x04: /* Seek */ @@ -1054,6 +1071,12 @@ void cdd_process(void) (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 + (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; + /* if drive is currently reading, another block or 2 are decoded before the seek starts */ + if (cdd.status == CD_PLAY && !(Pico_mcd->s68k_regs[0x4b] & 0x1)) { + Pico_mcd->s68k_regs[0x4b] |= 0x1; + return; + } + /* CD drive seek time */ /* We are using similar linear model as above, although still not exactly accurate, */ /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */ @@ -1067,10 +1090,10 @@ void cdd_process(void) cdd.latency = ((cdd.lba - lba) * 120) / 270000; } - /* get current track index */ + /* get track index */ while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; - /* seek to current block */ + /* seek to block */ cdd_seek(index, lba); /* no audio track playing */ @@ -1090,6 +1113,8 @@ void cdd_process(void) case 0x06: /* Pause */ { + /* TODO another block is decoded before pausing? */ + /* no audio track playing */ Pico_mcd->s68k_regs[0x36+0] = 0x01; @@ -1100,6 +1125,17 @@ void cdd_process(void) case 0x07: /* Resume */ { + int lba = (cdd.lba < 0 ? 0 : cdd.lba); + + /* CD drive latency */ + if (!cdd.latency) + { + cdd.latency = 11; + } + + /* always restart 4 blocks earlier */ + cdd_seek(cdd.index, lba - 4); + /* update status (RS1-RS8 unchanged) */ cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY; break; From c7b771de6cfb1e432e72fb05fe01cad2147be314 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 24 Apr 2024 21:51:01 +0200 Subject: [PATCH 07/44] 32x, make sh2 sram poll detection less agressive --- pico/32x/memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 2e7befe1c..4b6d9b595 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -284,7 +284,7 @@ u32 REGPARM(3) p32x_sh2_poll_memory16(u32 a, u32 d, SH2 *sh2) d = (s16)sh2_poll_read(a, d, cycles, sh2); } - p32x_sh2_poll_detect(a, sh2, SH2_STATE_RPOLL, 5); + p32x_sh2_poll_detect(a, sh2, SH2_STATE_RPOLL, 7); DRC_RESTORE_SR(sh2); return d; @@ -305,7 +305,7 @@ u32 REGPARM(3) p32x_sh2_poll_memory32(u32 a, u32 d, SH2 *sh2) ((u16)sh2_poll_read(a+2, d, cycles, sh2)); } - p32x_sh2_poll_detect(a, sh2, SH2_STATE_RPOLL, 5); + p32x_sh2_poll_detect(a, sh2, SH2_STATE_RPOLL, 7); DRC_RESTORE_SR(sh2); return d; From ce5c904a3955abee20e3c38fd0f3ddc8d09d4a94 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 27 Apr 2024 00:32:04 +0200 Subject: [PATCH 08/44] mcd, improve pre/post reading --- pico/cd/cdd.c | 21 ++++++++++++--------- pico/pico_int.h | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index 1db9a8f58..89ca183b1 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -162,7 +162,7 @@ void cdd_reset(void) cdd.latency = 0; /* reset track index */ - cdd.index = 0; + cdd.index = -1; /* reset logical block address */ cdd.lba = 0; @@ -830,10 +830,10 @@ void cdd_update(void) } } - if (Pico_mcd->s68k_regs[0x4b] & 0x1) { + if (Pico_mcd->m.state_flags & PCD_ST_CDD_CMD) { /* pending delayed command */ cdd_process(); - Pico_mcd->s68k_regs[0x4b] &= ~0x1; + Pico_mcd->m.state_flags &= ~PCD_ST_CDD_CMD; } } @@ -1006,8 +1006,8 @@ void cdd_process(void) (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; /* if drive is currently reading, another block or 2 are decoded before the seek starts */ - if (cdd.status == CD_PLAY && !(Pico_mcd->s68k_regs[0x4b] & 0x1)) { - Pico_mcd->s68k_regs[0x4b] |= 0x1; + if (cdd.status == CD_PLAY && !(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) { + Pico_mcd->m.state_flags |= PCD_ST_CDD_CMD; return; } @@ -1037,7 +1037,6 @@ void cdd_process(void) } /* block transfer always starts 3 blocks earlier */ - cdd.latency -= 3; lba -= 3; /* get track index */ @@ -1072,8 +1071,8 @@ void cdd_process(void) (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; /* if drive is currently reading, another block or 2 are decoded before the seek starts */ - if (cdd.status == CD_PLAY && !(Pico_mcd->s68k_regs[0x4b] & 0x1)) { - Pico_mcd->s68k_regs[0x4b] |= 0x1; + if (cdd.status == CD_PLAY && !(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) { + Pico_mcd->m.state_flags |= PCD_ST_CDD_CMD; return; } @@ -1113,7 +1112,11 @@ void cdd_process(void) case 0x06: /* Pause */ { - /* TODO another block is decoded before pausing? */ + /* if drive is currently reading, another block or 2 are decoded before the seek starts */ + if (cdd.status == CD_PLAY && !(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) { + Pico_mcd->m.state_flags |= PCD_ST_CDD_CMD; + return; + } /* no audio track playing */ Pico_mcd->s68k_regs[0x36+0] = 0x01; diff --git a/pico/pico_int.h b/pico/pico_int.h index c576ecbf4..fbdeb8736 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -523,6 +523,7 @@ struct mcd_pcm #define PCD_ST_S68K_SLEEP 4 #define PCD_ST_S68K_POLL 16 #define PCD_ST_M68K_POLL 32 +#define PCD_ST_CDD_CMD 64 #define PCD_ST_S68K_IFL2 0x100 struct mcd_misc From e61dbac103aac78cdf087e791e145beba26e004b Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 27 Apr 2024 10:12:25 +0200 Subject: [PATCH 09/44] mcd, fix irq2 handling (not cleared on disable) --- pico/cd/memory.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index fc4ddb725..17abd049f 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -166,14 +166,15 @@ void m68k_reg_write8(u32 a, u32 d) switch (a) { case 0: d &= 1; - Pico_mcd->m.state_flags &= ~PCD_ST_S68K_IFL2; - if (d) Pico_mcd->m.state_flags |= PCD_ST_S68K_IFL2; + pcd_sync_s68k(SekCyclesDone(), 0); if (d && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN2)) { elprintf(EL_INTS, "m68k: s68k irq 2"); - pcd_sync_s68k(SekCyclesDone(), 0); + Pico_mcd->m.state_flags |= PCD_ST_S68K_IFL2; pcd_irq_s68k(2, 1); - } else + } else { + Pico_mcd->m.state_flags &= ~PCD_ST_S68K_IFL2; pcd_irq_s68k(2, 0); + } return; case 1: d &= 3; @@ -193,6 +194,7 @@ void m68k_reg_write8(u32 a, u32 d) Pico_mcd->m.state_flags &= ~(PCD_ST_S68K_RST|PCD_ST_S68K_POLL|PCD_ST_S68K_SLEEP); elprintf(EL_CDREGS, "m68k: resetting s68k"); SekResetS68k(); + SekCycleCntS68k += 40; } if (((dold & 3) == 1) != ((d & 3) == 1)) { elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1); From 4985bad0fb1e3d2eb88aaf8ee0e47ec8bf750044 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 27 Apr 2024 09:53:33 +0200 Subject: [PATCH 10/44] mcd, add poll detection for gfx busy --- pico/cd/gfx.c | 4 ++++ pico/cd/memory.c | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pico/cd/gfx.c b/pico/cd/gfx.c index 84c4f43c2..4df1c34f9 100644 --- a/pico/cd/gfx.c +++ b/pico/cd/gfx.c @@ -409,6 +409,8 @@ void gfx_start(uint32 base) /* start graphics operation */ Pico_mcd->s68k_regs[0x58] = 0x80; + Pico_mcd->m.state_flags &= ~PCD_ST_S68K_POLL; + Pico_mcd->m.s68k_poll_cnt = 0; gfx_schedule(); } @@ -451,6 +453,8 @@ void gfx_update(unsigned int cycles) Pico_mcd->s68k_regs[0x64] = Pico_mcd->s68k_regs[0x65] = 0; + Pico_mcd->m.state_flags &= ~PCD_ST_S68K_POLL; + Pico_mcd->m.s68k_poll_cnt = 0; if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) { elprintf(EL_INTS|EL_CD, "s68k: gfx_cd irq 1"); pcd_irq_s68k(1, 1); diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 17abd049f..d6cf12730 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -366,8 +366,8 @@ u32 s68k_reg_read16(u32 a) d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; - if (a >= 0x0e && a < 0x30) - return s68k_poll_detect(a, d); + if ((a >= 0x0e && a < 0x30) || a == 0x58) + d = s68k_poll_detect(a, d); end: return d; @@ -995,7 +995,7 @@ static u32 PicoReadS68k8_pr(u32 a) a &= 0x1ff; if (a >= 0x0e && a < 0x30) { d = Pico_mcd->s68k_regs[a]; - s68k_poll_detect(a & ~1, d); + d = s68k_poll_detect(a & ~1, d); goto regs_done; } d = s68k_reg_read16(a & ~1); From b8a38093edd3e63ea8704698c6a3eefdebe64939 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 27 Apr 2024 09:44:43 +0200 Subject: [PATCH 11/44] core vdp, fix regression (irq not cleared on disable) --- pico/videoport.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pico/videoport.c b/pico/videoport.c index b4d676776..7ed3092f6 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -999,18 +999,22 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) update_irq: #ifndef EMU_CORE_DEBUG // update IRQ level - if (!SekShouldInterrupt()) // hack { int lines, pints, irq = 0; lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); pints = pvid->pending_ints & lines; if (pints & 0x20) irq = 6; else if (pints & 0x10) irq = pvid->hint_irq; - if (SekIrqLevel < irq) + if (irq) { + // VDP irqs have highest prio, overwrite old level SekInterrupt(irq); // update line - // this is broken because cost of current insn isn't known here - if (irq) SekEndRun(21); // make it delayed + // this is broken because cost of current insn isn't known here + SekEndRun(21); // make it delayed + } else if (SekIrqLevel >= pvid->hint_irq) { + // no VDP irq, query lower irqs + SekInterrupt(PicoPicoIrqAck(0)); + } } #endif } From c5d8fe3c039dd79b2594e09d53a3939f1f1ead8e Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 28 Apr 2024 21:18:36 +0200 Subject: [PATCH 12/44] prerelease 2.00-beta3 --- platform/common/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/common/version.h b/platform/common/version.h index 22a919051..1ab6c6503 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "pre-2.00-beta2" REVISION +#define VERSION "pre-2.00-beta3" REVISION From 0290987ccb8fed2a88e4e1c66f88b4423afaf04c Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 5 May 2024 18:12:40 +0200 Subject: [PATCH 13/44] core vdp, fix regression (irq not cleared on disable) --- pico/videoport.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pico/videoport.c b/pico/videoport.c index 7ed3092f6..0a05348d7 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -998,22 +998,24 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) update_irq: #ifndef EMU_CORE_DEBUG - // update IRQ level + // update IRQ level; TODO hack, still fire irq if disabling now + if (!SekShouldInterrupt() || SekIrqLevel < pvid->hint_irq) { int lines, pints, irq = 0; lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); pints = pvid->pending_ints & lines; if (pints & 0x20) irq = 6; else if (pints & 0x10) irq = pvid->hint_irq; + if (irq) { - // VDP irqs have highest prio, overwrite old level + // VDP irqs have highest prio, just overwrite old level SekInterrupt(irq); // update line - // this is broken because cost of current insn isn't known here + // TODO this is broken because cost of current insn isn't known here SekEndRun(21); // make it delayed } else if (SekIrqLevel >= pvid->hint_irq) { // no VDP irq, query lower irqs - SekInterrupt(PicoPicoIrqAck(0)); + SekInterrupt(PicoIn.AHW & PAHW_PICO ? PicoPicoIrqAck(0) : 0); } } #endif From eec6905e0b24db65a18b925d049943b0d952267a Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 5 May 2024 11:59:41 +0200 Subject: [PATCH 14/44] 32x, some reset related fixes --- pico/32x/32x.c | 39 ++++++++++++++++++++++++++------------- pico/32x/memory.c | 14 +++----------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index d88b23f05..fdde99079 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -35,6 +35,9 @@ void p32x_update_irls(SH2 *active_sh2, unsigned int m68k_cycles) int irqs, mlvl = 0, slvl = 0; int mrun, srun; + if ((Pico32x.regs[0] & (P32XS_nRES|P32XS_ADEN)) != (P32XS_nRES|P32XS_ADEN)) + return; + if (active_sh2 != NULL) m68k_cycles = sh2_cycles_done_m68k(active_sh2); @@ -100,13 +103,21 @@ void Pico32xStartup(void) { elprintf(EL_STATUS|EL_32X, "32X startup"); - // TODO: OOM handling PicoIn.AHW |= PAHW_32X; - sh2_init(&msh2, 0, &ssh2); - msh2.irq_callback = sh2_irq_cb; - sh2_init(&ssh2, 1, &msh2); - ssh2.irq_callback = sh2_irq_cb; + // TODO: OOM handling + if (Pico32xMem == NULL) { + Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0); + if (Pico32xMem == NULL) { + elprintf(EL_STATUS, "OOM"); + return; + } + memset(Pico32xMem, 0, sizeof(struct Pico32xMem)); + sh2_init(&msh2, 0, &ssh2); + msh2.irq_callback = sh2_irq_cb; + sh2_init(&ssh2, 1, &msh2); + ssh2.irq_callback = sh2_irq_cb; + } PicoMemSetup32x(); p32x_pwm_ctl_changed(); p32x_timers_recalc(); @@ -117,6 +128,8 @@ void Pico32xStartup(void) if (!Pico.m.pal) Pico32x.vdp_regs[0] |= P32XV_nPAL; + else + Pico32x.vdp_regs[0] &= ~P32XV_nPAL; rendstatus_old = -1; @@ -126,11 +139,8 @@ void Pico32xStartup(void) void Pico32xShutdown(void) { - sh2_finish(&msh2); - sh2_finish(&ssh2); - - Pico32x.vdp_regs[0] |= P32XS_nRES; - Pico32x.vdp_regs[6] |= P32XS_RV; + Pico32x.sh2_regs[0] &= ~P32XS2_ADEN; + Pico32x.regs[6] |= P32XS_RV; rendstatus_old = -1; @@ -212,6 +222,9 @@ void PicoUnload32x(void) if (PicoIn.AHW & PAHW_32X) Pico32xShutdown(); + sh2_finish(&msh2); + sh2_finish(&ssh2); + if (Pico32xMem != NULL) plat_munmap(Pico32xMem, sizeof(*Pico32xMem)); Pico32xMem = NULL; @@ -226,6 +239,7 @@ void PicoReset32x(void) p32x_pwm_ctl_changed(); p32x_timers_recalc(); Pico32x.vdp_regs[0] &= ~P32XV_Mx; // 32X graphics disabled + Pico32x.pending_fb = Pico32x.vdp_regs[0x0a/2] & P32XV_FS; } } @@ -264,9 +278,8 @@ static void p32x_start_blank(void) // FB swap waits until vblank if ((Pico32x.vdp_regs[0x0a/2] ^ Pico32x.pending_fb) & P32XV_FS) { - Pico32x.vdp_regs[0x0a/2] &= ~P32XV_FS; - Pico32x.vdp_regs[0x0a/2] |= Pico32x.pending_fb; - Pico32xSwapDRAM(Pico32x.pending_fb ^ 1); + Pico32x.vdp_regs[0x0a/2] ^= P32XV_FS; + Pico32xSwapDRAM(Pico32x.pending_fb ^ P32XV_FS); } p32x_trigger_irq(NULL, Pico.t.m68c_aim, P32XI_VINT); diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 4b6d9b595..150d40141 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -695,12 +695,12 @@ static void p32x_vdp_write8(u32 a, u32 d) r[4 / 2] = d & 0xff; break; case 0x0b: - d &= 1; + d &= P32XV_FS; Pico32x.pending_fb = d; // if we are blanking and FS bit is changing if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) { r[0x0a/2] ^= P32XV_FS; - Pico32xSwapDRAM(d ^ 1); + Pico32xSwapDRAM(d ^ P32XV_FS); elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS); } break; @@ -2303,14 +2303,6 @@ void PicoMemSetup32x(void) unsigned int rs; int i; - if (Pico32xMem == NULL) - Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0); - if (Pico32xMem == NULL) { - elprintf(EL_STATUS, "OOM"); - return; - } - memset(Pico32xMem, 0, sizeof(struct Pico32xMem)); - get_bios(); // cartridge area becomes unmapped @@ -2446,7 +2438,7 @@ void PicoMemSetup32x(void) ssh2_read32_map[0xc0/2].addr = MAP_MEMORY(ssh2.data_array); // map DRAM area, both 68k and SH2 - Pico32xSwapDRAM(1); + Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS); msh2.read8_map = msh2_read8_map; ssh2.read8_map = ssh2_read8_map; msh2.read16_map = msh2_read16_map; ssh2.read16_map = ssh2_read16_map; From c9f945341430fd5f1de1d613c763c634106e07d1 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 7 May 2024 00:41:59 +0300 Subject: [PATCH 15/44] 32x: adjust handlers according to hw tests "Pico32x.regs[6] |= P32XS_RV;" had wrong offset, but tests show this doesn't happen at all so remove. --- pico/32x/32x.c | 2 +- pico/32x/memory.c | 104 +++++++++++++++++++++++++++++----------------- 2 files changed, 68 insertions(+), 38 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index fdde99079..6a2d37b3d 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -140,7 +140,6 @@ void Pico32xStartup(void) void Pico32xShutdown(void) { Pico32x.sh2_regs[0] &= ~P32XS2_ADEN; - Pico32x.regs[6] |= P32XS_RV; rendstatus_old = -1; @@ -214,6 +213,7 @@ void PicoPower32x(void) memset(&Pico32x, 0, sizeof(Pico32x)); Pico32x.regs[0] = P32XS_REN|P32XS_nRES; // verified + Pico32x.regs[0x10/2] = 0xffff; Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_PEN; } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 150d40141..e4df386f6 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -1234,28 +1234,46 @@ void PicoWrite8_32x(u32 a, u32 d) if ((PicoIn.opt & POPT_EN_32X) && (a & 0xffc0) == 0x5100) // a15100 { u16 *r = Pico32x.regs; + u8 *r8 = (u8 *)r; elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); a &= 0x3f; - if (a == 1) { - if ((d ^ r[0]) & d & P32XS_ADEN) { - Pico32xStartup(); - r[0] &= ~P32XS_nRES; // causes reset if specified by this write - r[0] |= P32XS_ADEN; - p32x_reg_write8(a, d); // forward for reset processing - } - return; - } - if (a == 7) { - r[0x06/2] &= ~P32XS_RV; - r[0x06/2] |= d & P32XS_RV; - } - // allow only COMM for now - if ((a & 0x30) == 0x20) { - u8 *r8 = (u8 *)r; - r8[MEM_BE2(a)] = d; + switch (a) { + case 0x00: + r8[MEM_BE2(a)] = d & (P32XS_FM>>8); + return; + case 0x01: + if ((d ^ r[0]) & d & P32XS_ADEN) { + Pico32xStartup(); + r[0] &= ~P32XS_nRES; // causes reset if specified by this write + r[0] |= P32XS_ADEN; + p32x_reg_write8(a, d); // forward for reset processing + } + else { + r[0] &= ~(P32XS_nRES|P32XS_ADEN); + r[0] |= d & (P32XS_nRES|P32XS_ADEN); + } + return; + case 0x03: r8[MEM_BE2(a)] = d & 3; return; + case 0x05: r8[MEM_BE2(a)] = d & 3; return; + case 0x07: r8[MEM_BE2(a)] = d & 7; return; + case 0x09: r8[MEM_BE2(a)] = d ; return; + case 0x0a: r8[MEM_BE2(a)] = d ; return; + case 0x0b: r8[MEM_BE2(a)] = d & 0xfe; return; + case 0x0d: r8[MEM_BE2(a)] = d ; return; + case 0x0e: r8[MEM_BE2(a)] = d ; return; + case 0x0f: r8[MEM_BE2(a)] = d ; return; + case 0x10: r8[MEM_BE2(a)] = d ; return; + case 0x11: r8[MEM_BE2(a)] = d & 0xfc; return; + case 0x1a: r8[MEM_BE2(a)] = d & 1; return; + case 0x1b: r8[MEM_BE2(a)] = d & 1; return; + case 0x20: case 0x21: case 0x22: case 0x23: // COMM + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + r8[MEM_BE2(a)] = d; + return; } - return; } elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); @@ -1267,26 +1285,38 @@ void PicoWrite16_32x(u32 a, u32 d) { u16 *r = Pico32x.regs; - elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); a &= 0x3e; - if (a == 0) { - if ((d ^ r[0]) & d & P32XS_ADEN) { - Pico32xStartup(); - r[0] &= ~P32XS_nRES; // causes reset if specified by this write - r[0] |= P32XS_ADEN; - p32x_reg_write16(a, d); // forward for reset processing - } - return; - } - if (a == 6) { - r[0x06/2] &= ~P32XS_RV; - r[0x06/2] |= d & P32XS_RV; + switch (a) { + case 0x00: + if ((d ^ r[0]) & d & P32XS_ADEN) { + Pico32xStartup(); + r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN); + // causes reset if specified by this write + r[0] |= d & (P32XS_FM|P32XS_ADEN); + p32x_reg_write16(a, d); // forward for reset processing + } + else { + r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN); + r[0] |= d & (P32XS_FM|P32XS_nRES|P32XS_ADEN); + } + return; + case 0x02: r[a / 2] = d & 3; return; + case 0x04: r[a / 2] = d & 3; return; + case 0x06: r[a / 2] = d & 7; return; + case 0x08: r[a / 2] = d & 0x00ff; return; + case 0x0a: r[a / 2] = d & 0xfffe; return; + case 0x0c: r[a / 2] = d & 0x00ff; return; + case 0x0e: r[a / 2] = d ; return; + case 0x10: r[a / 2] = d & 0xfffc; return; + case 0x1a: r[a / 2] = d & 0x0101; return; + case 0x20: case 0x22: // COMM + case 0x24: case 0x26: + case 0x28: case 0x2a: + case 0x2c: case 0x2e: + r[a / 2] = d; + return; } - - // allow only COMM for now - if ((a & 0x30) == 0x20) - r[a / 2] = d; - return; } elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); @@ -2328,7 +2358,7 @@ void PicoMemSetup32x(void) cpu68k_map_set(m68k_write16_map, 0x880000, 0x880000 + rs - 1, PicoWrite16_cart, 1); // 32X ROM (banked) - bank_switch_rom_68k(0); + bank_switch_rom_68k(Pico32x.regs[4 / 2]); cpu68k_map_set(m68k_write8_map, 0x900000, 0x9fffff, PicoWrite8_bank, 1); cpu68k_map_set(m68k_write16_map, 0x900000, 0x9fffff, PicoWrite16_bank, 1); } From 274dd51a6084a1d485d5efa6c52239434bdd2b08 Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 7 May 2024 23:10:27 +0200 Subject: [PATCH 16/44] core z80, cycle counting fixes (reset, bus request) --- pico/cd/mcd.c | 2 +- pico/debug.c | 2 +- pico/memory.c | 12 +++++++----- pico/pico_cmn.c | 4 ++-- pico/pico_int.h | 4 ++-- pico/sms.c | 2 +- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 2fdbe7252..60acd6df2 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -312,7 +312,7 @@ static int SekSyncM68k(int once); void pcd_run_cpus_normal(int m68k_cycles) { // TODO this is suspicious. ~1 cycle refresh delay every 256 cycles? - SekAimM68k(m68k_cycles, 0x43); // Fhey area + SekAimM68k(m68k_cycles, 0x42); // Fhey area while (CYCLES_GT(Pico.t.m68c_aim, Pico.t.m68c_cnt)) { if (SekShouldInterrupt()) { diff --git a/pico/debug.c b/pico/debug.c index 5a85a30ad..064e97a92 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -389,7 +389,6 @@ void PDebugZ80Frame(void) else lines = 262; - z80_resetCycles(Pico.t.z80c_aim); PsndStartFrame(); if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) { @@ -407,6 +406,7 @@ void PDebugZ80Frame(void) PsndGetSamples(lines); timers_cycle(Pico.t.z80c_aim); + z80_resetCycles(); Pico.t.m68c_aim = Pico.t.m68c_cnt; } diff --git a/pico/memory.c b/pico/memory.c index 1bd230d0e..0c06acaea 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -530,20 +530,21 @@ void NOINLINE ctl_write_z80busreq(u32 d) { if (d) { - Pico.t.z80c_cnt = z80_cycles_from_68k() + (Pico.t.z80_busdelay >> 8); + Pico.t.z80c_aim = Pico.t.z80c_cnt = z80_cycles_from_68k() + (Pico.t.z80_busdelay >> 8) + 2; Pico.t.z80_busdelay &= 0xff; } else { if ((PicoIn.opt & POPT_EN_Z80) && !Pico.m.z80_reset) { - // Z80 grants bus 2 cycles after the next M cycle, even within an insn + // Z80 grants bus after the current M cycle, even within an insn // simulate this by accumulating the last insn overhang in busdelay - unsigned granted = z80_cycles_from_68k() + 6; + unsigned granted; pprof_start(m68k); PicoSyncZ80(SekCyclesDone()); + pprof_end_sub(m68k); + granted = Pico.t.z80c_aim + 6; // M cycle is 3-6 cycles Pico.t.z80_busdelay += (Pico.t.z80c_cnt - granted) << 8; Pico.t.z80c_cnt = granted; - pprof_end_sub(m68k); } } Pico.m.z80Run = d; @@ -563,12 +564,13 @@ void NOINLINE ctl_write_z80reset(u32 d) PicoSyncZ80(SekCyclesDone()); pprof_end_sub(m68k); } + Pico.t.z80_busdelay &= 0xff; // also resets bus request YM2612ResetChip(); timers_reset(); } else { - Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; + Pico.t.z80c_aim = Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; z80_reset(); } Pico.m.z80_reset = d; diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 519aba351..af2e598cf 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -81,7 +81,7 @@ static __inline void SekAimM68k(int cyc, int mult) static __inline void SekRunM68k(int cyc) { // TODO 0x100 would be 2 cycles/128, moreover far too sensitive - SekAimM68k(cyc, 0x10c); // OutRunners, testpico, VDPFIFOTesting + SekAimM68k(cyc, 0x108); // OutRunners, testpico, VDPFIFOTesting SekSyncM68k(0); } @@ -141,7 +141,6 @@ static int PicoFrameHints(void) skip = PicoIn.skipFrame; - z80_resetCycles(cycles_68k_to_z80(Pico.t.m68c_aim - Pico.t.m68c_frame_start)); Pico.t.m68c_frame_start = Pico.t.m68c_aim; PsndStartFrame(); @@ -340,6 +339,7 @@ static int PicoFrameHints(void) PsndGetSamples(y); timers_cycle(cycles_68k_to_z80(Pico.t.m68c_aim - Pico.t.m68c_frame_start)); + z80_resetCycles(); pv->hint_cnt = hint; diff --git a/pico/pico_int.h b/pico/pico_int.h index fbdeb8736..995f8c16a 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -201,8 +201,8 @@ extern struct DrZ80 drZ80; #define Z80_STATE_SIZE 0x60 -#define z80_resetCycles(aim) \ - Pico.t.z80c_cnt -= (aim < Pico.t.z80c_cnt ? aim : Pico.t.z80c_cnt), Pico.t.z80c_aim = Pico.t.z80_scanline = 0 +#define z80_resetCycles() \ + Pico.t.z80c_cnt -= Pico.t.z80c_aim, Pico.t.z80c_aim = Pico.t.z80_scanline = 0 #define z80_cyclesDone() \ (Pico.t.z80c_aim - z80_cyclesLeft) diff --git a/pico/sms.c b/pico/sms.c index e954bc8b9..c56111c85 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -846,7 +846,6 @@ void PicoFrameMS(void) int nmi; int y; - z80_resetCycles(Pico.t.z80c_aim); PsndStartFrame(); // for SMS the pause button generates an NMI, for GG ths is not the case @@ -923,6 +922,7 @@ void PicoFrameMS(void) z80_exec(Pico.t.z80c_line_start + cycles_line); } + z80_resetCycles(); PsndGetSamplesMS(lines); } From ebde43de9dc500a91c1a8133c4ba2155e46d9304 Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 7 May 2024 23:11:54 +0200 Subject: [PATCH 17/44] core z80, bus blocking for VDP DMA --- pico/memory.c | 5 ++++- pico/pico_cmn.c | 6 ++++++ pico/pico_int.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pico/memory.c b/pico/memory.c index 0c06acaea..eca0ba457 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -565,6 +565,7 @@ void NOINLINE ctl_write_z80reset(u32 d) pprof_end_sub(m68k); } Pico.t.z80_busdelay &= 0xff; // also resets bus request + Pico.video.status &= ~PVS_Z80WAIT; YM2612ResetChip(); timers_reset(); } @@ -1369,8 +1370,10 @@ void PicoWrite16_32x(u32 a, u32 d) {} static void access_68k_bus(int delay) // bus delay as Q8 { // TODO: if the 68K is in DMA wait, Z80 has to wait until DMA ends - if (Pico.video.status & (PVS_CPUWR|PVS_CPURD)) + if (Pico.video.status & (PVS_CPUWR|PVS_CPURD)) { z80_subCLeft(z80_cyclesLeft); // rather rough on both condition and action + Pico.video.status |= PVS_Z80WAIT; + } // 68k bus access delay for z80. The fractional part needs to be accumulated // until an additional cycle is full. That is then added to the integer part. diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index af2e598cf..cd037899f 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -125,6 +125,12 @@ static void do_timing_hacks_start(struct PicoVideo *pv) int cycles = PicoVideoFIFOHint(); SekCyclesBurn(cycles); // prolong cpu HOLD if necessary + if (pv->status & PVS_Z80WAIT) { + Pico.t.z80c_cnt += cycles_68k_to_z80(cycles); + if (!(pv->status & (PVS_CPUWR|PVS_CPURD))) + pv->status &= ~PVS_Z80WAIT; + } + // XXX how to handle Z80 bus cycle stealing during DMA correctly? if ((Pico.t.z80_buscycles -= cycles) < 0) Pico.t.z80_buscycles = 0; diff --git a/pico/pico_int.h b/pico/pico_int.h index 995f8c16a..49361f145 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -299,6 +299,7 @@ extern SH2 sh2s[2]; #define PVS_DMAFILL (1 << 20) // DMA fill is waiting for fill data #define PVS_DMABG (1 << 21) // background DMA operation is running #define PVS_FIFORUN (1 << 22) // FIFO is processing +#define PVS_Z80WAIT (1 << 23) // Z80 blocked by VDP DMA struct PicoVideo { From 52cb58c50dda09d2f4b3ed448461230a3907c09b Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 7 May 2024 23:12:54 +0200 Subject: [PATCH 18/44] core z80, improve save/load (cycles) --- pico/state.c | 2 -- pico/z80if.c | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pico/state.c b/pico/state.c index bd801b157..957c43cd4 100644 --- a/pico/state.c +++ b/pico/state.c @@ -599,8 +599,6 @@ static int state_load(void *file) z80_unpack(buff_z80); - // due to dep from 68k cycles.. - Pico.t.m68c_frame_start = Pico.t.m68c_aim; if (PicoIn.AHW & PAHW_32X) Pico32xStateLoaded(0); if (PicoIn.AHW & PAHW_MCD) diff --git a/pico/z80if.c b/pico/z80if.c index 558607c6e..b8f1320c8 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -157,7 +157,8 @@ struct z80_state { u8 im; // irq mode u8 irq_pending; // irq line level, 1 if active u8 irq_vector[3]; // up to 3 byte vector for irq mode0 handling - u8 reserved[8]; + u16 cyc; + u8 reserved[6]; }; void z80_pack(void *data) @@ -165,6 +166,7 @@ void z80_pack(void *data) struct z80_state *s = data; memset(data, 0, Z80_STATE_SIZE); memcpy(s->magic, "Z80a", 4); + s->cyc = Pico.t.z80c_cnt; #if defined(_USE_DRZ80) #define DRR8(n) (drZ80.Z80##n >> 24) #define DRR16(n) (drZ80.Z80##n >> 16) @@ -222,6 +224,7 @@ int z80_unpack(const void *data) elprintf(EL_STATUS, "legacy z80 state - ignored"); return 0; } + Pico.t.z80c_cnt = s->cyc; #if defined(_USE_DRZ80) #define DRW8(n, v) drZ80.Z80##n = (u32)(v) << 24 From 695e6de85e06d47043003664531fc491eaa91240 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 8 May 2024 01:18:59 +0200 Subject: [PATCH 19/44] 32x, internal BIOS hack for jumping to 0x140 --- pico/32x/memory.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pico/32x/memory.c b/pico/32x/memory.c index e4df386f6..e6c55f2e6 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -2238,10 +2238,16 @@ static void get_bios(void) } else { pl = (u32 *)&Pico32xMem->sh2_rom_m; + ps = (u16 *)pl; // fill exception vector table to our trap address - for (i = 0; i < 128; i++) + for (i = 0; i < 80; i++) pl[i] = CPU_BE2(0x200); + // CD titles by Digital Pictures jump to 0x140 for resetting ... + for (i = 0x140/2; i < 0x1fc/2; i++) + ps[i] = 0x0009; // nop // ... so fill the remainder with nops + ps[i++] = 0xa002; // bra 0x204 // ... and jump over the trap + ps[i++] = 0x0009; // nop // start pl[0] = pl[2] = CPU_BE2(0x204); From fb79e7baa8ad87276262ec42aaa1a6794694f317 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 10 May 2024 23:22:01 +0200 Subject: [PATCH 20/44] platform opendingux, add some keys (gkd mini, rs97) --- platform/opendingux/inputmap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/opendingux/inputmap.c b/platform/opendingux/inputmap.c index 8df598d65..e8eace455 100644 --- a/platform/opendingux/inputmap.c +++ b/platform/opendingux/inputmap.c @@ -78,6 +78,9 @@ const char * _in_sdl_key_names[SDLK_LAST] = { [SDLK_KP_DIVIDE] = "L3", [SDLK_KP_PERIOD] = "R3", [SDLK_HOME] = "POWER", + /* gkd (mini) */ + /*[SDLK_HOME] = "MENU",*/ + [SDLK_END] = "EXIT", /* gcw0 */ [SDLK_POWER] = "POWER", [SDLK_PAUSE] = "LOCK", @@ -85,6 +88,9 @@ const char * _in_sdl_key_names[SDLK_LAST] = { [SDLK_RALT] = "L2", [SDLK_RSHIFT] = "R2", [SDLK_RCTRL] = "RESET", + /* retrofw */ + [SDLK_LEFTBRACKET] = "SETUP", /* actually brightness setting */ + /*[SDLK_END] = "POWER",*/ }; const char * const *in_sdl_key_names = _in_sdl_key_names; @@ -130,5 +136,6 @@ void plat_target_setup_input(void) } else if (strcmp(plat_device, "retrofw") == 0 || strcmp(plat_device, "dingux") == 0) { /* single L/R keys */ nameset(SDLK_TAB, "L"); nameset(SDLK_BACKSPACE, "R"); + nameset(SDLK_END, "POWER"); } } From 83416730541100e153c00874e3ffb560ef62ffdb Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 12 May 2024 10:06:24 +0200 Subject: [PATCH 21/44] 32x, fix reset interrupt handling --- pico/32x/32x.c | 9 ++++----- pico/32x/draw.c | 2 +- pico/32x/memory.c | 2 +- pico/debug.c | 2 +- pico/pico_int.h | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 6a2d37b3d..6e2cb4bce 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -44,13 +44,13 @@ void p32x_update_irls(SH2 *active_sh2, unsigned int m68k_cycles) // find top bit = highest irq number (0 <= irl <= 14/2) by binary search // msh2 - irqs = Pico32x.sh2irqs | Pico32x.sh2irqi[0]; + irqs = Pico32x.sh2irqi[0]; if (irqs >= 0x10) mlvl += 8, irqs >>= 4; if (irqs >= 0x04) mlvl += 4, irqs >>= 2; if (irqs >= 0x02) mlvl += 2, irqs >>= 1; // ssh2 - irqs = Pico32x.sh2irqs | Pico32x.sh2irqi[1]; + irqs = Pico32x.sh2irqi[1]; if (irqs >= 0x10) slvl += 8, irqs >>= 4; if (irqs >= 0x04) slvl += 4, irqs >>= 2; if (irqs >= 0x02) slvl += 2, irqs >>= 1; @@ -77,7 +77,8 @@ void p32x_update_irls(SH2 *active_sh2, unsigned int m68k_cycles) // TODO: test on hw.. void p32x_trigger_irq(SH2 *sh2, unsigned int m68k_cycles, unsigned int mask) { - Pico32x.sh2irqs |= mask & P32XI_VRES; + Pico32x.sh2irqi[0] |= mask & P32XI_VRES; + Pico32x.sh2irqi[1] |= mask & P32XI_VRES; Pico32x.sh2irqi[0] |= mask & (Pico32x.sh2irq_mask[0] << 3); Pico32x.sh2irqi[1] |= mask & (Pico32x.sh2irq_mask[1] << 3); @@ -238,8 +239,6 @@ void PicoReset32x(void) p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_IDLE_STATES, SekCyclesDone()); p32x_pwm_ctl_changed(); p32x_timers_recalc(); - Pico32x.vdp_regs[0] &= ~P32XV_Mx; // 32X graphics disabled - Pico32x.pending_fb = Pico32x.vdp_regs[0x0a/2] & P32XV_FS; } } diff --git a/pico/32x/draw.c b/pico/32x/draw.c index 0ec5669ce..52b33ee62 100644 --- a/pico/32x/draw.c +++ b/pico/32x/draw.c @@ -10,7 +10,7 @@ // NB: 32X officially doesn't support H32 mode. However, it does work since the // cartridge slot carries the EDCLK signal which is always H40 clock and is used -// as video clock by the 32X. The H32 MD image is overlayed with the 320 px 32X +// as video clock by the 32X. The H32 MD image is overlaid with the 320 px 32X // image which has the same on-screen width. How the /YS signal on the cartridge // slot (signalling the display of background color) is processed in this case // is however unclear and might lead to glitches due to race conditions by the diff --git a/pico/32x/memory.c b/pico/32x/memory.c index e6c55f2e6..7d964f20c 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -930,7 +930,7 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) Pico32x.regs[0] |= d & P32XS_FM; break; case 0x14/2: - Pico32x.sh2irqs &= ~P32XI_VRES; + Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VRES; goto irls; case 0x16/2: Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT; diff --git a/pico/debug.c b/pico/debug.c index 064e97a92..9ee58d2a1 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -77,7 +77,7 @@ char *PDebug32x(void) } r = Pico32x.sh2_regs; sprintf(dstrp, "SH: %04x %04x %04x IRQs: %02x eflags: %02x\n", - r[0], r[1], r[2], Pico32x.sh2irqs, Pico32x.emu_flags); MVP; + r[0], r[1], r[2], Pico32x.sh2irqi[0]|Pico32x.sh2irqi[1], Pico32x.emu_flags); MVP; i = 0; r = Pico32x.vdp_regs; diff --git a/pico/pico_int.h b/pico/pico_int.h index 49361f145..2f70b31db 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -641,7 +641,7 @@ struct Pico32x unsigned int emu_flags; unsigned char sh2irq_mask[2]; unsigned char sh2irqi[2]; // individual - unsigned int sh2irqs; // common irqs + unsigned int pad4; // was sh2irqs unsigned short dmac_fifo[DMAC_FIFO_LEN]; unsigned int pad[4]; unsigned int dmac0_fifo_ptr; From dab0c363166f4596a8e3c0a90c1a741cb2d960a7 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 16 May 2024 20:32:55 +0000 Subject: [PATCH 22/44] build, change executable name to lowercase --- Makefile | 18 +++++++++--------- platform/gp2x/Makefile | 2 +- platform/pandora/Makefile | 7 ++++++- platform/ps2/Makefile | 2 +- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 7b87043ee..2566e740b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ $(LD) ?= $(CC) -TARGET ?= PicoDrive +TARGET ?= picodrive ASAN ?= 0 DEBUG ?= 0 CFLAGS += -I$(PWD) @@ -111,7 +111,7 @@ endif # TODO this should somehow go to the platform directory? ifeq "$(PLATFORM)" "generic" -$(TARGET).zip: $(TARGET) +PicoDrive.zip: $(TARGET) $(RM) -rf .od_data mkdir .od_data cp -r platform/linux/skin .od_data @@ -119,7 +119,7 @@ $(TARGET).zip: $(TARGET) cp $< .od_data/PicoDrive $(STRIP) .od_data/PicoDrive cd .od_data && zip -9 -r ../$@ * -all: $(TARGET).zip +all: PicoDrive.zip endif ifeq "$(PLATFORM)" "opendingux" @@ -134,22 +134,22 @@ ifeq "$(PLATFORM)" "opendingux" ifneq (,$(filter %__DINGUX__, $(CFLAGS))) # "legacy" dingux without opk support -$(TARGET)-dge.zip: .od_data +PicoDrive-dge.zip: .od_data rm -f .od_data/default.*.desktop cd .od_data && zip -9 -r ../$@ * -all: $(TARGET)-dge.zip +all: PicoDrive-dge.zip CFLAGS += -DSDL_SURFACE_SW # some legacy dinguces had bugs in HWSURFACE else ifneq (,$(filter %__MIYOO__, $(CFLAGS))) -$(TARGET)-miyoo.zip: .od_data +PicoDrive-miyoo.zip: .od_data rm -f .od_data/default.*.desktop .od_data/PicoDrive.dge cd .od_data && zip -9 -r ../$@ * -all: $(TARGET)-miyoo.zip +all: PicoDrive-miyoo.zip else -$(TARGET).opk: .od_data +PicoDrive.opk: .od_data rm -f .od_data/PicoDrive.dge mksquashfs .od_data $@ -all-root -noappend -no-exports -no-xattrs -all: $(TARGET).opk +all: PicoDrive.opk endif endif diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index 083ce14fc..7756689e3 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -20,7 +20,7 @@ readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog CODE940 = code940/pico940_v3.bin -PicoDrive: ../../PicoDrive +PicoDrive: ../../picodrive $(STRIP) $^ -o $@ rel: PicoDrive PicoDrive.gpe $(CODE940) readme.txt ../game_def.cfg \ diff --git a/platform/pandora/Makefile b/platform/pandora/Makefile index fd362696e..0eb65193f 100644 --- a/platform/pandora/Makefile +++ b/platform/pandora/Makefile @@ -8,6 +8,8 @@ ifneq "$(BUILD)" "" VER := $(VER)_$(BUILD) endif +include ../../config.mak + PND_MAKE ?= pnd_make all: rel @@ -21,7 +23,10 @@ all: rel /tmp/PicoDrive.pxml: PicoDrive.pxml.template FORCE ./make_pxml.sh $< $@ -rel: ../../PicoDrive PicoDrive.sh picorestore \ +PicoDrive: ../../picodrive + $(STRIP) $^ -o $@ + +rel: PicoDrive PicoDrive.sh picorestore \ PicoDrive.png PicoDrive_p.png \ ../../pico/carthw.cfg skin \ ../../README.md /tmp/PicoDrive.pxml diff --git a/platform/ps2/Makefile b/platform/ps2/Makefile index a0e20095c..50672385f 100644 --- a/platform/ps2/Makefile +++ b/platform/ps2/Makefile @@ -14,7 +14,7 @@ include ../../config.mak readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog ../../tools/textfilter ../base_readme.txt $@ PS2 -PicoDrive: ../../PicoDrive +PicoDrive: ../../picodrive $(STRIP) $^ -o $@ PicoDrive.elf: PicoDrive From 67c9ba38cb3e1b363d344e2d7d2d0922939ef705 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 17 May 2024 19:11:34 +0000 Subject: [PATCH 23/44] core, improve system and mapper detection --- pico/media.c | 2 +- pico/sms.c | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/pico/media.c b/pico/media.c index 63d3d9979..b217fa0ab 100644 --- a/pico/media.c +++ b/pico/media.c @@ -358,7 +358,7 @@ enum media_type_e PicoLoadMedia(const char *filename, ext = NULL; } } - if (ext && !strcasecmp(ext,"gg") && !PicoIn.hwSelect) { + if (ext && !strcasecmp(ext,"gg")) { PicoIn.AHW |= PAHW_GG; lprintf("detected GG ROM\n"); } else if (ext && !strcasecmp(ext,"sg")) { diff --git a/pico/sms.c b/pico/sms.c index c56111c85..d85fb8506 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -357,7 +357,7 @@ static void write_bank_codem(unsigned short a, unsigned char d) // MSX mapper. 4 selectable 8KB banks at the top static void write_bank_msx(unsigned short a, unsigned char d) { - if (a > 0x0003 || !(Pico.m.hardware & PMS_HW_JAP)) return; + if (a > 0x0003) return; // don't detect linear mapping to avoid confusing with Codemasters if (Pico.ms.mapper != PMS_MAP_MSX && (Pico.ms.mapper || (a|d) == 0 || d >= 0x80)) return; elprintf(EL_Z80BNK, "bank msx %04x %02x @ %04x", a, d, z80_pc()); @@ -471,7 +471,7 @@ static void write_bank_jang(unsigned short a, unsigned char d) static void write_bank_xor(unsigned short a, unsigned char d) { // 4x8KB bank select @0x2000 - if ((a&0x6000) != 0x2000) return; + if ((a&0x6800) != 0x2000) return; if (Pico.ms.mapper != PMS_MAP_XOR && Pico.ms.mapper) return; elprintf(EL_Z80BNK, "bank xor %04x %02x @ %04x", a, d, z80_pc()); @@ -559,7 +559,7 @@ static void xwrite(unsigned int a, unsigned char d) case PMS_MAP_AUTO: // disable autodetection after some time - if ((a >= 0xc000 && a < 0xfff8) || Pico.ms.mapcnt > 20) break; + if ((a >= 0xc000 && a < 0xfff8) || Pico.ms.mapcnt > 30) break; // NB the sequence of mappers is crucial for the auto detection if (PicoIn.AHW & PAHW_SC) { write_bank_x32k(a,d); @@ -590,31 +590,33 @@ static void xwrite(unsigned int a, unsigned char d) static u32 region_pal[] = { // cf Meka, meka/meka.nam 0x40207067 /* Addams Family */, 0x40207020 /* Back.Future 3 */, 0x40207058 /* Battlemaniacs */, 0x40007105 /* Cal.Games 2 */, - 0x40207065 /* Dracula */ , 0x40007109 /* Home Alone */, + 0x402f7065 /* Dracula */ , 0x40007109 /* Home Alone */, 0x40009024 /* Pwr.Strike 2 */ , 0x40207047 /* Predator 2 EU */, 0x40002519 /* Quest.Yak */ , 0x40207064 /* Robocop 3 */, - 0x40205014 /* Sens.Soccer */ , 0x40002573 /* Sonic Blast */, + 0x4f205014 /* Sens.Soccer */ , 0x40002573 /* Sonic Blast */, 0x40007080 /* S.Harrier EU */ , 0x40007038 /* Taito Chase */, - 0x40009015 /* Sonic 2 EU */ , /* NBA Jam: no valid id/cksum in TMR */ + 0x40009015 /* Sonic 2 EU */ , /* NBA Jam: no valid id/cksum */ 0x4fff8872 /* Excell.Dizzy */ , 0x4ffffac4 /* Fantast.Dizzy */, 0x4fff4a89 /* Csm.Spacehead */, 0x4fffe352 /* Micr.Machines */, + 0x4fffa203 /* Bad Apple */ }; // TMR product codes and hardware type for known non-FM games static u32 no_fmsound[] = { // cf Meka, meka/meka.pat - 0x40002070 /* Walter Payton */, 0x40007020 /* American Pro */, + 0x40002070 /* Walter Payton */, 0x40017020 /* American Pro */, 0x4fffe890 /* Wanted */ }; // TMR product codes and hardware type for known GG carts running in SMS mode // NB GG carts having the system type set to 4 (eg. HTH games) run as SMS anyway static u32 gg_smsmode[] = { // cf https://www.smspower.org/Tags/SMS-GG - 0x60002401 /* Castl.Ilusion */, 0x60101018 /* Taito Chase */, - 0x70709018 /* Olympic Gold */ , 0x70009038 /* Outrun EU */, + 0x60002401 /* Castl.Ilusion */, 0x6f101018 /* Taito Chase */, + 0x70709018 /* Olympic Gold */ , 0x70079038 /* Outrun EU */, 0x60801068 /* Predator 2 */ , 0x70408098 /* Prince.Persia */, - 0x50101037 /* Rastan Saga */ , 0x70006018 /* RC Grandprix */, + 0x50101037 /* Rastan Saga */ , 0x7f086018 /* RC Grandprix */, 0x60002415 /* Super Kickoff */, 0x60801108 /* WWF.Steelcage */, /* Excell.Dizzy, Fantast.Dizzy, Super Tetris: no valid id/cksum in TMR */ + 0x4f813028 /* Tesserae */ }; void PicoResetMS(void) @@ -645,7 +647,10 @@ void PicoResetMS(void) for (tmr = 0x2000; tmr < 0xbfff && tmr <= Pico.romsize; tmr *= 2) { if (!memcmp(Pico.rom + tmr-16, "TMR SEGA", 8)) { hw = Pico.rom[tmr-1] >> 4; - if (!PicoIn.hwSelect) { + id = CPU_LE4(*(u32 *)&Pico.rom[tmr-4]); + ck = *(u16 *)&Pico.rom[tmr-6] | (id&0xf0000000) | 0xfff0000; + + if (!PicoIn.hwSelect && hw && ((id+1)&0xfffe) != 0) { PicoIn.AHW &= ~(PAHW_GG|PAHW_SG|PAHW_SC); if (hw >= 0x5 && hw < 0x8) PicoIn.AHW |= PAHW_GG; // GG cartridge detected @@ -655,8 +660,6 @@ void PicoResetMS(void) if (hw == 0x5 || hw == 0x3) Pico.m.hardware |= PMS_HW_JAP; // region Japan } - id = CPU_LE4(*(u32 *)&Pico.rom[tmr-4]) & 0xf0f0ffff; - ck = (CPU_LE4(*(u32 *)&Pico.rom[tmr-8])>>16) | (id&0xf0000000) | 0xfff0000; for (i = 0; i < sizeof(region_pal)/sizeof(*region_pal); i++) if ((id == region_pal[i] || ck == region_pal[i]) && !PicoIn.regionOverride) { @@ -666,6 +669,7 @@ void PicoResetMS(void) for (i = 0; i < sizeof(gg_smsmode)/sizeof(*gg_smsmode); i++) if ((id == gg_smsmode[i] || ck == gg_smsmode[i]) && !PicoIn.hwSelect) { PicoIn.AHW &= ~PAHW_GG; // requires SMS mode + if (hw < 0x5) PicoIn.AHW |= PAHW_GG; break; } for (i = 0; i < sizeof(no_fmsound)/sizeof(*no_fmsound); i++) @@ -871,7 +875,7 @@ void PicoFrameMS(void) switch (is_pal ? -lines_vis : lines_vis) { case 192: if (y > 218) pv->v_counter = y - (lines-256); break; case 224: if (y > 234) pv->v_counter = y - (lines-256); break; -/* case 240: if (y > 252) pv->v_counter = y - (lines-256); break; ? */ +/* case 240: if (y > 242) pv->v_counter = y - (lines-256); break; ? */ case -192: if (y > 242) pv->v_counter = y - (lines-256); break; case -224: if (y > 258) pv->v_counter = y - (lines-256); break; case -240: if (y > 266) pv->v_counter = y - (lines-256); break; From 864ac1d6a68fd6c7212781b3e914bb03a6521cca Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 18 May 2024 11:35:22 +0200 Subject: [PATCH 24/44] sound, don't reinitialize after menu if not needed --- pico/sound/sn76496.c | 12 +++++++++-- pico/sound/sn76496.h | 1 + pico/sound/sound.c | 49 +++++++++++++++++++++++++------------------- pico/sound/ym2612.c | 5 +++++ 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c index 0837839c8..1624d136b 100644 --- a/pico/sound/sn76496.c +++ b/pico/sound/sn76496.c @@ -279,6 +279,15 @@ static void SN76496_set_gain(struct SN76496 *R,int gain) } +//static +void SN76496_set_clockrate(int clock,int sample_rate) +{ + struct SN76496 *R = &ono_sn; + + R->SampleRate = sample_rate; + SN76496_set_clock(R,clock); +} + //static int SN76496_init(int clock,int sample_rate) { @@ -287,8 +296,7 @@ int SN76496_init(int clock,int sample_rate) //R->Channel = stream_create(0,1, sample_rate,R,SN76496Update); - R->SampleRate = sample_rate; - SN76496_set_clock(R,clock); + SN76496_set_clockrate(clock,sample_rate); for (i = 0;i < 4;i++) R->Volume[i] = 0; diff --git a/pico/sound/sn76496.h b/pico/sound/sn76496.h index 707bb5dd1..8677ea93d 100644 --- a/pico/sound/sn76496.h +++ b/pico/sound/sn76496.h @@ -4,6 +4,7 @@ void SN76496Write(int data); void SN76496Update(short *buffer,int length,int stereo); void SN76496Config(int panning); +void SN76496_set_clockrate(int clock,int sample_rate); int SN76496_init(int clock,int sample_rate); #endif diff --git a/pico/sound/sound.c b/pico/sound/sound.c index edf9c8960..2150f68da 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -33,7 +33,6 @@ static int (*PsndFMUpdate)(s32 *buffer, int length, int stereo, int is_buf_empty // ym2413 static OPLL *opll = NULL; -static OPLL old_opll; static struct { uint32_t adr; uint8_t reg[sizeof(opll->reg)]; @@ -152,6 +151,10 @@ static int YM2612UpdateONE(s32 *buffer, int length, int stereo, int is_buf_empty return YM2612UpdateOne(buffer, length, stereo, is_buf_empty); } +static int ymclock; +static int ymrate; +static int ymopts; + // to be called after changing sound rate or chips void PsndRerate(int preserve_state) { @@ -159,54 +162,58 @@ void PsndRerate(int preserve_state) int target_fps = Pico.m.pal ? 50 : 60; int target_lines = Pico.m.pal ? 313 : 262; int sms_clock = Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15; + int ym2413_rate = (sms_clock + 36) / 72; int ym2612_clock = Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7; int ym2612_rate = YM2612_NATIVE_RATE(); - int ym2413_rate = (sms_clock + 36) / 72; + int ym2612_init = !preserve_state; - if (preserve_state) { + // don't init YM2612 if preserve_state and no parameter changes + ym2612_init |= ymclock != ym2612_clock || ymopts != (PicoIn.opt & (POPT_DIS_FM_SSGEG|POPT_EN_FM_DAC)); + ym2612_init |= ymrate != (PicoIn.opt & POPT_EN_FM_FILTER ? ym2612_rate : PicoIn.sndRate); + ymclock = ym2612_clock; + ymrate = (PicoIn.opt & POPT_EN_FM_FILTER ? ym2612_rate : PicoIn.sndRate); + ymopts = PicoIn.opt & (POPT_DIS_FM_SSGEG|POPT_EN_FM_DAC); + + if (preserve_state && ym2612_init) { state = malloc(0x204); if (state == NULL) return; ym2612_pack_state(); memcpy(state, YM2612GetRegs(), 0x204); - - if (opll != NULL) - memcpy(&old_opll, opll, sizeof(OPLL)); // remember old state } + if (PicoIn.AHW & PAHW_SMS) { OPLL_setRate(opll, ym2413_rate); - OPLL_reset(opll); + if (!preserve_state) + OPLL_reset(opll); YMFM_setup_FIR(ym2413_rate, PicoIn.sndRate, 0); PsndFMUpdate = YM2413UpdateFIR; } else if ((PicoIn.opt & POPT_EN_FM_FILTER) && ym2612_rate != PicoIn.sndRate) { // polyphase FIR resampler, resampling directly from native to output rate - YM2612Init(ym2612_clock, ym2612_rate, + if (ym2612_init) + YM2612Init(ym2612_clock, ym2612_rate, ((PicoIn.opt&POPT_DIS_FM_SSGEG) ? 0 : ST_SSG) | ((PicoIn.opt&POPT_EN_FM_DAC) ? ST_DAC : 0)); YMFM_setup_FIR(ym2612_rate, PicoIn.sndRate, PicoIn.opt & POPT_EN_STEREO); PsndFMUpdate = YM2612UpdateFIR; } else { - YM2612Init(ym2612_clock, PicoIn.sndRate, + if (ym2612_init) + YM2612Init(ym2612_clock, PicoIn.sndRate, ((PicoIn.opt&POPT_DIS_FM_SSGEG) ? 0 : ST_SSG) | ((PicoIn.opt&POPT_EN_FM_DAC) ? ST_DAC : 0)); PsndFMUpdate = YM2612UpdateONE; } - if (preserve_state) { + + if (preserve_state && ym2612_init) { // feed it back it's own registers, just like after loading state memcpy(YM2612GetRegs(), state, 0x204); ym2612_unpack_state(); - - if (opll != NULL) { - memcpy(&opll->adr, &old_opll.adr, sizeof(OPLL)-20); // restore old state - OPLL_forceRefresh(opll); - } + free(state); } - if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state - SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate); - if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state - - if (state) - free(state); + if (preserve_state) + SN76496_set_clockrate(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate); + else + SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate); // calculate Pico.snd.len Pico.snd.len = PicoIn.sndRate / target_fps; diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index f8a18625d..f0e60b428 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -193,6 +193,8 @@ UINT16 ym_tl_tab2[13*TL_RES_LEN]; /* sin waveform table in 'decibel' scale (use only period/4 values) */ static UINT16 ym_sin_tab[256]; +static int ym_init_tab; + /* sustain level table (3dB per step) */ /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */ /* 1, 2, 4, 8, 16, 32, 64 (value)*/ @@ -1467,6 +1469,9 @@ static void init_tables(void) signed int n; double o,m; + if (ym_init_tab) return; + ym_init_tab = 1; + for (i=0; i < 256; i++) { /* non-standard sinus */ From 41670496668459cd9a957a633b2c2b77bdc4dbeb Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 18 May 2024 21:58:25 +0200 Subject: [PATCH 25/44] core, fix floating bus read for 68k (regression) --- pico/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico/memory.c b/pico/memory.c index eca0ba457..487c5deb5 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -204,7 +204,7 @@ u32 PicoRead16_floating(u32 a) // faking open bus u32 d = (Pico.m.rotate += 0x41); d ^= (d << 5) ^ (d << 8); - if ((a & 0xff0000) == 0xa10000) d = 0; // MegaCD pulldowns don't work here curiously + if ((a & 0xff0000) == 0xa10000) return d; // MegaCD pulldowns don't work here curiously return (PicoIn.AHW & PAHW_MCD) ? 0x00 : d; // pulldown if MegaCD2 attached } From 2531b6fd16543cfa3afc6528c949c6a05787542b Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 18 May 2024 21:59:18 +0200 Subject: [PATCH 26/44] sms, minor optimization --- pico/mode4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pico/mode4.c b/pico/mode4.c index b396af66a..eada9741f 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -174,7 +174,7 @@ static void ParseSpritesM4(int scanline) if (zoomed) h *= 2; sprite_base = (pv->reg[6] & 4) << (13-2-1); - m = 0; + m = pv->status & SR_C; memset(sprites_map, 0, sizeof(sprites_map)); for (i = s = 0; i < 64; i++) { @@ -448,7 +448,7 @@ static void ParseSpritesTMS(int scanline) if (zoomed) h *= 2; sprite_base = (pv->reg[6] & 0x7) << 11; - m = 0; + m = pv->status & SR_C; memset(sprites_map, 0, sizeof(sprites_map)); /* find sprites on this scanline */ for (i = s = 0; i < 32; i++) From 96e5982134e284fa5380bea12a3a8497ea82d577 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 18 May 2024 22:00:41 +0200 Subject: [PATCH 27/44] core vdp, reset fix --- pico/pico.c | 14 +++++++------- pico/videoport.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pico/pico.c b/pico/pico.c index d913e0822..0e7e1d8fc 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -75,13 +75,6 @@ void PicoPower(void) // my MD1 VA6 console has this in IO PicoMem.ioports[1] = PicoMem.ioports[2] = PicoMem.ioports[3] = 0xff; - // powerup default VDP register values from TMSS BIOS - Pico.video.reg[0] = Pico.video.reg[1] = 0x04; - Pico.video.reg[0xc] = 0x81; - Pico.video.reg[0xf] = 0x02; - SATaddr = 0x0000; - SATmask = ~0x3ff; - Pico.video.hint_irq = (PicoIn.AHW & PAHW_PICO ? 5 : 4); if (PicoIn.AHW & PAHW_MCD) @@ -91,6 +84,13 @@ void PicoPower(void) PicoPower32x(); PicoReset(); + + // powerup default VDP register values from TMSS BIOS + Pico.video.reg[0] = Pico.video.reg[1] = 0x04; + Pico.video.reg[0xc] = 0x81; + Pico.video.reg[0xf] = 0x02; + SATaddr = 0x0000; + SATmask = ~0x3ff; } PICO_INTERNAL void PicoDetectRegion(void) diff --git a/pico/videoport.c b/pico/videoport.c index 0a05348d7..4adf7a7ed 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -1180,7 +1180,7 @@ void PicoVideoReset(void) Pico.m.dirtyPal = 1; PicoDrawBgcDMA(NULL, 0, 0, 0, 0); - PicoVideoFIFOMode(0, 1); + PicoVideoFIFOMode(Pico.video.reg[1]&0x40, Pico.video.reg[12]&1); } void PicoVideoCacheSAT(int load) From faf754baf86843a96c6584fd1a6d2c4fc63dd2b7 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 18 May 2024 22:12:56 +0200 Subject: [PATCH 28/44] update copyright --- platform/common/menu_pico.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 00f2aa690..a4abd7a6a 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -1144,7 +1144,7 @@ static void draw_frame_credits(void) static const char credits[] = "PicoDrive v" VERSION "\n" - "(c) notaz, 2006-2013; irixxxx, 2018-2023\n\n" + "(c) notaz, 2006-2013; irixxxx, 2018-2024\n\n" "Credits:\n" "fDave: initial code\n" #ifdef EMU_C68K From 735a987b27592b6add258ae8f4d7edc67d589224 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 18 May 2024 22:33:23 +0300 Subject: [PATCH 29/44] pandora: some fixes for 2.0 --- platform/pandora/plat.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 20f9ca8f2..bb7774f2b 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -171,8 +171,13 @@ void pemu_finalize_frame(const char *fps, const char *notice) } if (notice && notice[0]) emu_osd_text16(2 + g_osd_start_x, g_osd_y, notice); - if (fps && fps[0] && (currentConfig.EmuOpt & EOPT_SHOW_FPS)) - emu_osd_text16(g_osd_fps_x, g_osd_y, fps); + if (fps && fps[0] && (currentConfig.EmuOpt & EOPT_SHOW_FPS)) { + const char *p; + // avoid wrapping when fps is very high + if (fps[5] != ' ' && (p = strchr(fps, '/'))) + fps = p; + emu_osd_text16(g_osd_fps_x, g_osd_y, fps); + } if ((PicoIn.AHW & PAHW_MCD) && (currentConfig.EmuOpt & EOPT_EN_CD_LEDS)) draw_cd_leds(); } @@ -186,8 +191,12 @@ void plat_video_flip(void) xenv_update(NULL, NULL, NULL, NULL); } +// pnd doesn't use multiple renderers, but we have to handle this since it's +// called on 32x enable and PicoDrawSetOutFormat() sets up the 32x layers void plat_video_toggle_renderer(int change, int is_menu) { + if (!is_menu) + PicoDrawSetOutFormat(PDF_RGB555, 0); } void plat_video_menu_enter(int is_rom_loaded) From 65b37c5a3b057b3c78c0d9d48f5c4bf93f151039 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 19 May 2024 20:45:44 +0000 Subject: [PATCH 30/44] sh2 drc, fix conditional immediate for armv7 --- cpu/drc/emit_arm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index d32954e0b..ed4732f6a 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -425,11 +425,11 @@ static void emith_flush(void) #define EOP_MSR_IMM(ror2,imm) EOP_C_MSR_IMM(A_COND_AL,ror2,imm) #define EOP_MSR_REG(rm) EOP_C_MSR_REG(A_COND_AL,rm) -#define EOP_MOVW(rd,imm) \ - EMIT(0xe3000000 | ((rd)<<12) | ((imm)&0xfff) | (((imm)<<4)&0xf0000), M1(rd), NO) +#define EOP_MOVW(cond,rd,imm) \ + EMIT(((cond)<<28) | 0x03000000 | ((rd)<<12) | ((imm)&0xfff) | (((imm)<<4)&0xf0000), M1(rd), NO) -#define EOP_MOVT(rd,imm) \ - EMIT(0xe3400000 | ((rd)<<12) | (((imm)>>16)&0xfff) | (((imm)>>12)&0xf0000), M1(rd), NO) +#define EOP_MOVT(cond,rd,imm) \ + EMIT(((cond)<<28) | 0x03400000 | ((rd)<<12) | (((imm)>>16)&0xfff) | (((imm)>>12)&0xf0000), M1(rd), NO) // host literal pool; must be significantly smaller than 1024 (max LDR offset = 4096) #define MAX_HOST_LITERALS 128 @@ -486,9 +486,9 @@ static void emith_op_imm2(int cond, int s, int op, int rd, int rn, unsigned int if (op == A_OP_MVN) imm = ~imm; // ...prefer movw/movt - EOP_MOVW(rd, imm); + EOP_MOVW(cond,rd, imm); if (imm & 0xffff0000) - EOP_MOVT(rd, imm); + EOP_MOVT(cond,rd, imm); return; } #else @@ -512,7 +512,7 @@ static void emith_op_imm2(int cond, int s, int op, int rd, int rn, unsigned int EOP_C_DOP_IMM(cond, A_OP_ADD, 0,rd,rd,0,o); else if (o < 0) EOP_C_DOP_IMM(cond, A_OP_SUB, 0,rd,rd,0,-o); - return; + return; } #endif break; From c055f15cd5abe93d07ac3fe21cb52c462798773c Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 20 May 2024 09:30:35 +0200 Subject: [PATCH 31/44] build, add ps2 to release script --- tools/release.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/release.sh b/tools/release.sh index d5d134ea9..6e789bf83 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -5,7 +5,7 @@ # creates builds for the supported platforms in the release directory # # usage: release.sh [platform...] -# platforms: gph dingux retrofw gcw0 opendingux miyoo psp pandora odbeta-gcw0 odbeta-lepus odbeta-rg99 +# platforms: gph dingux retrofw gcw0 opendingux miyoo psp ps2 pandora odbeta-gcw0 odbeta-lepus odbeta-rg99 # # expects toolchains to be installed in these docker containers: # gph: ghcr.io/irixxxx/toolchain-gp2x @@ -14,6 +14,7 @@ # gcw0,opendingux:ghcr.io/irixxxx/toolchain-opendingux # miyoo: ghcr.io/irixxxx/toolchain-miyoo # psp: docker.io/pspdev/pspdev +# psp: docker.io/ps2dev/ps2dev # pandora: ghcr.io/irixxxx/toolchain-pandora # odbeta-gcw0: ghcr.io/irixxxx/toolchain-odbeta-gcw0 # odbeta-lepus: ghcr.io/irixxxx/toolchain-odbeta-lepus @@ -25,7 +26,7 @@ rel=$1 mkdir -p release-$rel shift; plat=" $* " -[ -z "$(echo $plat|tr -d ' ')" ] && plat=" gph dingux retrofw gcw0 opendingux miyoo psp pandora odbeta-gcw0 odbeta-lepus odbeta-rg99 " +[ -z "$(echo $plat|tr -d ' ')" ] && plat=" gph dingux retrofw gcw0 opendingux miyoo psp ps2 pandora odbeta-gcw0 odbeta-lepus odbeta-rg99 " [ -z "${plat##* gph *}" ] && { @@ -102,6 +103,18 @@ echo " apk add git gcc g++ zip && export CROSS_COMPILE=psp- &&\ mv PicoDrive_psp_$rel.zip release-$rel/PicoDrive-psp_$rel.zip } +[ -z "${plat##* ps2 *}" ] && { +# ps2 (experimental), ps2dev SDK toolchain +docker pull --platform=linux/amd64 ps2dev/ps2dev +echo " apk add build-base cmake git zip make && export CROSS_COMPILE=mips64r5900el-ps2-elf- &&\ + git config --global --add safe.directory /home/picodrive &&\ + ./configure --platform=ps2 &&\ + make clean && make -j2 all &&\ + make -C platform/ps2 rel VER=$rel "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ps2dev/ps2dev sh && +mv PicoDrive_ps2_$rel.zip release-$rel/PicoDrive-ps2_$rel.zip +} + [ -z "${plat##* pandora *}" ] && { # pandora (untested), openpandora SDK toolchain docker pull ghcr.io/irixxxx/toolchain-pandora From 257baf1520b02ba5049a53a79503a2b86562908a Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 20 May 2024 10:07:42 +0200 Subject: [PATCH 32/44] platform ps2, fixes for gcc14 --- pico/pico_int.h | 1 + platform/common/mp3.c | 2 +- platform/ps2/emu.c | 12 ++++++------ platform/ps2/in_ps2.c | 3 ++- platform/ps2/plat.c | 1 + 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pico/pico_int.h b/pico/pico_int.h index 2f70b31db..06f00c2f5 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -969,6 +969,7 @@ void PicoVideoCacheSAT(int load); // misc.c PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count); PICO_INTERNAL_ASM void memset32(void *dest, int c, int count); +PICO_INTERNAL_ASM void memset32_uncached(int *dest, int c, int count); // eeprom.c void EEPROM_write8(unsigned int a, unsigned int d); diff --git a/platform/common/mp3.c b/platform/common/mp3.c index 7c50652e2..2f3846f58 100644 --- a/platform/common/mp3.c +++ b/platform/common/mp3.c @@ -131,7 +131,7 @@ void mp3_start_play(void *f_, int pos1024) void mp3_update(s32 *buffer, int length, int stereo) { int length_mp3; - void (*mix_samples)(int *dest_buf, short *mp3_buf, int count, int fac16) = mix_16h_to_32_resample_stereo; + void (*mix_samples)(s32 *dest_buf, short *mp3_buf, int count, int fac16) = mix_16h_to_32_resample_stereo; if (mp3_current_file == NULL || mp3_file_pos >= mp3_file_len) return; /* no file / EOF */ diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 35db97447..bd06d162d 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -64,7 +64,7 @@ static GSTEXTURE *g_screens[2]; static int g_screen_index; static GSTEXTURE *g_screen; static GSPRIMUVPOINT *g_screen_vertices; -static u16 *g_screen_palette; +static void *g_screen_palette; static GSTEXTURE *osd; static uint32_t osd_vertices_count; @@ -386,7 +386,7 @@ void set_g_screen_values() { g_screen_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); for (i = 0; i < 2; i++) { g_screens[i] = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - g_screens[i]->Mem = (uint32_t *)malloc(g_screenSize); + g_screens[i]->Mem = malloc(g_screenSize); g_screens[i]->Width = 328; g_screens[i]->Height = 256; @@ -414,7 +414,7 @@ void set_cdleds_values() { size_t cdledsSize = gsKit_texture_size_ee(14, 5, GS_PSM_CT16); cdleds = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - cdleds->Mem = (uint32_t *)malloc(cdledsSize); + cdleds->Mem = malloc(cdledsSize); cdleds_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); cdleds->Width = 14; @@ -435,7 +435,7 @@ void set_osd_values() { int num_osds = 4, i; osd = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - osd->Mem = (uint32_t *)malloc(osdSize); + osd->Mem = malloc(osdSize); osd_vertices_count = 2*num_osds; osd_vertices = (GSPRIMUVPOINT *)calloc(osd_vertices_count, sizeof(GSPRIMUVPOINT)); @@ -488,7 +488,7 @@ static void video_init(void) set_osd_values(); set_cdleds_values(); - g_menubg_ptr = (uint8_t *)malloc(2 * g_menuscreen_pp * g_menuscreen_h); + g_menubg_ptr = malloc(2 * g_menuscreen_pp * g_menuscreen_h); g_menubg_src_w = g_screen->Width; g_menubg_src_h = g_screen->Height; g_menubg_src_pp = g_screen->Width; @@ -654,7 +654,7 @@ static void osd_text(int x, const char *text) int old_pitch = g_screen_ppitch; int len = strlen(text) * 8; - u16 *osd_buf = osd->Mem; + u16 *osd_buf = (u16 *)osd->Mem; int *p, h; g_screen_ptr = osd_buf; diff --git a/platform/ps2/in_ps2.c b/platform/ps2/in_ps2.c index d58d514cb..0b033f372 100644 --- a/platform/ps2/in_ps2.c +++ b/platform/ps2/in_ps2.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "libpad.h" #include "libmtap.h" @@ -21,7 +22,7 @@ static int in_ps2_combo_keys = 0; static int in_ps2_combo_acts = 0; -static uintptr_t padBuf[2][4]; +static void *padBuf[2][4]; static uint32_t padConnected[2][4]; // 2 ports, 4 slots static uint32_t padOpen[2][4]; static uint32_t maxslot[2]; diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index 253e18784..408137925 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include From 75a6b6a954e7c3a1437712a398e8e9c1c8b1c531 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 May 2024 18:54:59 +0200 Subject: [PATCH 33/44] md, add some unlicensed carts --- pico/carthw.cfg | 31 ++++++++++++++++++++++++++++++- pico/carthw_cfg.c | 25 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/pico/carthw.cfg b/pico/carthw.cfg index 013b04cf3..5932dd7c5 100644 --- a/pico/carthw.cfg +++ b/pico/carthw.cfg @@ -168,11 +168,16 @@ check_size_gt = 0x020000 hw = x_in_1_mapper # radica -[radica_v1] +[Arcade Legends Sega] check_str = 0x150, "KID CHAMELEON" check_size_gt = 0x100000 hw = radica_mapper +[Arcade Legends Capcom] +check_str = 0x150, "STREET FIGHTER" +check_size_gt = 0x300000 +hw = radica_mapper + # realtec [Earth Defend, The (Unl)] check_str = 0x94, "THE EARTH DEFEND" @@ -197,6 +202,12 @@ check_str = 0x150, "FRANK THOMAS BIGHURT BASEBAL" eeprom_type = 3 eeprom_lines = 8,0,0 +[Greatest Heavyweights] +check_str = 0x150, "GREATEST HEAVYWEIGHTS" +sram_range = 0x200000,0x200001 +eeprom_type = 1 +eeprom_lines = 1,0,0 + [MICRO MACHINES II] check_str = 0x150, "MICRO MACHINES II" sram_range = 0x300000,0x380001 @@ -265,6 +276,12 @@ sram_range = 0x200000,0x200001 eeprom_type = 1 eeprom_lines = 6,7,7 +[Sports Talk Baseball] +check_str = 0x150, "MLBPA SPORTS TALK BASEBALL" +sram_range = 0x200000,0x200001 +eeprom_type = 1 +eeprom_lines = 1,0,0 + # Unlicensed games with simple protections # some of these come from Haze, some from myself (notaz). # more added by irixxxx from Mame and G+GX @@ -281,6 +298,11 @@ check_str = 0x104, " are Registered Trademarks" check_crc32 = 0x4c98cc30 hw = lk3_mapper +[Gunfight 3-in-1 (Unl)] +check_str = 0x104, " are Registered Trademarks" +check_crc32 = 0x6ec032cb +hw = lk3_mapper + [Pocket Monsters II (Unl)] check_str = 0x104, " " check_crc32 = 0x0d097f5c @@ -413,6 +435,13 @@ hw = prot prot_rw_value16 = 0x400000,0xc00000,0 prot_rw_value16 = 0x400004,0xc00004,0 +[Final Fantasy (Unl)] # Taikong zhanshi (russian bootleg) +check_csum = 0x5ff9 +check_crc32 = 0x4b2b163a +hw = prot +prot_rw_value16 = 0x400000,0xc00000,0 +prot_rw_value16 = 0x400004,0xc00004,0 + [Water Margin (Unl)] # Shuihu Zhuan check_csum = 0x6001 check_crc32 = 0xfa80956a diff --git a/pico/carthw_cfg.c b/pico/carthw_cfg.c index 97e7ddae5..8c46a5fa4 100644 --- a/pico/carthw_cfg.c +++ b/pico/carthw_cfg.c @@ -98,6 +98,11 @@ static const char builtin_carthw_cfg[] = "check_size_gt=0x100000\n" "hw=radica_mapper\n" "[]\n" + "check_str=0x150,\"STREET FIGHTER\"\n" + "check_str=0x161,\"SPECIAL CHAMPION EDITION\"\n" + "check_size_gt=0x300000\n" + "hw=radica_mapper\n" + "[]\n" "check_str=0x94,\"THE EARTH DEFEND\"\n" "hw=realtec_mapper\n" "[]\n" @@ -115,6 +120,11 @@ static const char builtin_carthw_cfg[] = "eeprom_type=3\n" "eeprom_lines=8,0,0\n" "[]\n" + "check_str=0x150,\"GREATEST HEAVYWEIGHTS\"\n" + "sram_range=0x200000,0x200001\n" + "eeprom_type=1\n" + "eeprom_lines=1,0,0\n" + "[]\n" "check_str=0x150,\"MICRO MACHINES II\"\n" "sram_range=0x300000,0x380001\n" "eeprom_type=2\n" @@ -172,6 +182,11 @@ static const char builtin_carthw_cfg[] = "eeprom_type=1\n" "eeprom_lines=6,7,7\n" "[]\n" + "check_str=0x150,\"MLBPA SPORTS TALK BASEBALL\"\n" + "sram_range=0x200000,0x200001\n" + "eeprom_type=1\n" + "eeprom_lines=1,0,0\n" + "[]\n" "check_str=0x104,\" are Registered Trademarks\"\n" "check_crc32=0xc9706e25\n" "hw=lk3_mapper\n" @@ -180,6 +195,10 @@ static const char builtin_carthw_cfg[] = "check_crc32=0x4c98cc30\n" "hw=lk3_mapper\n" "[]\n" + "check_str=0x104,\" are Registered Trademarks\"\n" + "check_crc32=0x6ec032cb\n" + "hw=lk3_mapper\n" + "[]\n" "check_str=0x104,\" \"\n" "check_crc32=0x0d097f5c\n" "hw=lk3_mapper\n" @@ -288,6 +307,12 @@ static const char builtin_carthw_cfg[] = "prot_rw_value16=0x400000,0xc00000,0\n" "prot_rw_value16=0x400004,0xc00004,0\n" "[]\n" + "check_csum=0x5ff9\n" + "check_crc32=0x4b2b163a\n" + "hw=prot\n" + "prot_rw_value16=0x400000,0xc00000,0\n" + "prot_rw_value16=0x400004,0xc00004,0\n" + "[]\n" "check_csum=0x6001\n" "check_crc32=0xfa80956a\n" "hw=prot\n" From 1eb630c232ee27dbfd61c393861444a39d95c23b Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 May 2024 18:58:10 +0200 Subject: [PATCH 34/44] md, no floating bus in cart address space --- pico/memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index 487c5deb5..fa3cf0f9e 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -211,13 +211,13 @@ u32 PicoRead16_floating(u32 a) static u32 m68k_unmapped_read8(u32 a) { elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); - return (u8)PicoRead16_floating(a); + return a < 0x400000 ? 0 : (u8)PicoRead16_floating(a); } static u32 m68k_unmapped_read16(u32 a) { elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); - return PicoRead16_floating(a); + return a < 0x400000 ? 0 : PicoRead16_floating(a); } static void m68k_unmapped_write8(u32 a, u32 d) From b72095041e08e048d8c0a66762f11f4e0f5af83e Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 May 2024 19:01:26 +0200 Subject: [PATCH 35/44] sms, fixes to bios initialisation and mapper autodetection --- pico/sms.c | 16 ++++++++-------- pico/z80if.c | 11 +++++------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/pico/sms.c b/pico/sms.c index d85fb8506..9537caff0 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -442,7 +442,7 @@ static unsigned char read_flipped_jang(unsigned a) static void write_bank_jang(unsigned short a, unsigned char d) { // address is 0xfffe, 0xffff, 0x4000, 0x6000, 0x8000, 0xa000 - if ((a|1) != 0xffff && (!((a^(a<<1)) & 0x8000) || (a & 0x1fff))) return; + if ((a|1) != 0xffff && (a < 0x4000 || a > 0xa000 || (a & 0x1fff))) return; // never autodetected, selectable only via config if (Pico.ms.mapper != PMS_MAP_JANGGUN) return; elprintf(EL_Z80BNK, "bank jang %04x %02x @ %04x", a, d, z80_pc()); @@ -471,7 +471,7 @@ static void write_bank_jang(unsigned short a, unsigned char d) static void write_bank_xor(unsigned short a, unsigned char d) { // 4x8KB bank select @0x2000 - if ((a&0x6800) != 0x2000) return; + if ((a&0xff00) != 0x2000) return; if (Pico.ms.mapper != PMS_MAP_XOR && Pico.ms.mapper) return; elprintf(EL_Z80BNK, "bank xor %04x %02x @ %04x", a, d, z80_pc()); @@ -488,7 +488,7 @@ static void write_bank_xor(unsigned short a, unsigned char d) static void write_bank_x8k(unsigned short a, unsigned char d) { // 8KB address range @ 0x2000 (adaptor) or @ 0x8000 (cartridge) - if ((a&0xe000) != 0x2000 && (a&0xe000) != 0x8000) return; + if (((a&0xe000) != 0x2000 && (a&0xe000) != 0x8000) || (a & 0x0f) == 5) return; if (Pico.ms.mapper != PMS_MAP_8KBRAM && Pico.ms.mapper) return; elprintf(EL_Z80BNK, "bank x8k %04x %02x @ %04x", a, d, z80_pc()); @@ -538,7 +538,7 @@ char *mappers[] = { // Before adding more mappers this should be revised. static void xwrite(unsigned int a, unsigned char d) { - int sz = (PicoIn.AHW & (PAHW_SG|PAHW_SC) ? 2 : 8) * 1024; + int sz = (/*PicoIn.AHW & (PAHW_SG|PAHW_SC) ? 2 :*/ 8) * 1024; elprintf(EL_IO, "z80 write [%04x] %02x", a, d); if (a >= 0xc000) @@ -559,7 +559,7 @@ static void xwrite(unsigned int a, unsigned char d) case PMS_MAP_AUTO: // disable autodetection after some time - if ((a >= 0xc000 && a < 0xfff8) || Pico.ms.mapcnt > 30) break; + if ((a >= 0xc000 && a < 0xfff8) || Pico.ms.mapcnt > 50) break; // NB the sequence of mappers is crucial for the auto detection if (PicoIn.AHW & PAHW_SC) { write_bank_x32k(a,d); @@ -733,7 +733,7 @@ void PicoPowerMS(void) void PicoMemSetupMS(void) { u8 mapper = Pico.ms.mapper; - int sz = (PicoIn.AHW & (PAHW_SG|PAHW_SC) ? 2 : 8) * 1024; + int sz = (/*PicoIn.AHW & (PAHW_SG|PAHW_SC) ? 2 :*/ 8) * 1024; u32 a; // RAM and its mirrors @@ -741,8 +741,8 @@ void PicoMemSetupMS(void) z80_map_set(z80_read_map, a, a + sz-1, PicoMem.zram, 0); z80_map_set(z80_write_map, a, a + sz-1, PicoMem.zram, 0); } - a = 0x10000 - (1<> Z80_MEM_SHIFT] << 1; #endif - drZ80.Z80SP = drZ80.Z80SP_BASE + 0xffff; + drZ80.Z80SP = drZ80.Z80SP_BASE + (is_sms ? 0xdff0 : 0xffff); // simulate BIOS drZ80.z80_irq_callback = NULL; // use auto-clear - if (PicoIn.AHW & PAHW_SMS) { - drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS + if (PicoIn.AHW & PAHW_8BIT) drZ80.z80_irq_callback = dz80_noop_irq_ack; - } // XXX: since we use direct SP pointer, it might make sense to force it to RAM, // but we'll rely on built-in stack protection for now #endif #ifdef _USE_CZ80 Cz80_Reset(&CZ80); Cz80_Set_Reg(&CZ80, CZ80_SP, 0xffff); - if (PicoIn.AHW & PAHW_SMS) + if (is_sms) Cz80_Set_Reg(&CZ80, CZ80_SP, 0xdff0); #endif } From 3b480be4c0ef9dd82df9d9634987ee02e8eed028 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 24 May 2024 00:06:39 +0200 Subject: [PATCH 36/44] core z80, partially revert ebde43d (bus blocking DMA) it causes audio lag in OD2 --- pico/memory.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pico/memory.c b/pico/memory.c index fa3cf0f9e..de5e3e5ef 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -1372,7 +1372,8 @@ static void access_68k_bus(int delay) // bus delay as Q8 // TODO: if the 68K is in DMA wait, Z80 has to wait until DMA ends if (Pico.video.status & (PVS_CPUWR|PVS_CPURD)) { z80_subCLeft(z80_cyclesLeft); // rather rough on both condition and action - Pico.video.status |= PVS_Z80WAIT; + // TODO the next line will cause audio lag in Overdrive 2 demo? + //Pico.video.status |= PVS_Z80WAIT; } // 68k bus access delay for z80. The fractional part needs to be accumulated From cc1174c988c9d815e4108bb61f863db7131534fe Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 21 May 2024 01:09:40 +0300 Subject: [PATCH 37/44] update libchdr for zstd support --- Makefile | 18 ++++++++++++++---- jni/Android.mk | 44 ++++++++++++++++++++++++++++++++++---------- pico/cd/libchdr | 2 +- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 2566e740b..99c339163 100644 --- a/Makefile +++ b/Makefile @@ -328,16 +328,26 @@ CHDR_OBJS += $(CHDR)/src/libchdr_chd.o $(CHDR)/src/libchdr_cdrom.o CHDR_OBJS += $(CHDR)/src/libchdr_flac.o CHDR_OBJS += $(CHDR)/src/libchdr_bitstream.o $(CHDR)/src/libchdr_huffman.o -# lzma - use 19.00 as newer versions have compile problems with libretro platforms -LZMA = $(CHDR)/deps/lzma-19.00 +LZMA = $(CHDR)/deps/lzma-24.05 LZMA_OBJS += $(LZMA)/src/CpuArch.o $(LZMA)/src/Alloc.o $(LZMA)/src/LzmaEnc.o LZMA_OBJS += $(LZMA)/src/Sort.o $(LZMA)/src/LzmaDec.o $(LZMA)/src/LzFind.o LZMA_OBJS += $(LZMA)/src/Delta.o -$(LZMA_OBJS): CFLAGS += -D_7ZIP_ST +$(LZMA_OBJS): CFLAGS += -DZ7_ST -Wno-unused + +ZSTD = $(CHDR)/deps/zstd-1.5.6/lib +ZSTD_OBJS += $(ZSTD)/common/entropy_common.o $(ZSTD)/common/error_private.o +ZSTD_OBJS += $(ZSTD)/common/fse_decompress.o $(ZSTD)/common/xxhash.o +ZSTD_OBJS += $(ZSTD)/common/zstd_common.o +ZSTD_OBJS += $(ZSTD)/decompress/huf_decompress.o +ZSTD_OBJS += $(ZSTD)/decompress/huf_decompress_amd64.o +ZSTD_OBJS += $(ZSTD)/decompress/zstd_ddict.o +ZSTD_OBJS += $(ZSTD)/decompress/zstd_decompress_block.o +ZSTD_OBJS += $(ZSTD)/decompress/zstd_decompress.o +$(ZSTD_OBJS) $(CHDR_OBJS): CFLAGS += -I$(ZSTD) -Wno-unused OBJS += $(CHDR_OBJS) ifneq ($(STATIC_LINKING), 1) -OBJS += $(LZMA_OBJS) +OBJS += $(LZMA_OBJS) $(ZSTD_OBJS) endif # ouf... prepend includes to overload headers available in the toolchain CFLAGS := -I$(LZMA)/include -I$(CHDR)/include $(CFLAGS) diff --git a/jni/Android.mk b/jni/Android.mk index b4d0143cd..43680aa76 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -53,6 +53,10 @@ endif include $(COMMON_DIR)/common.mak +LCHDR = $(CORE_DIR)/pico/cd/libchdr +LCHDR_LZMA = $(LCHDR)/deps/lzma-24.05 +LCHDR_ZSTD = $(LCHDR)/deps/zstd-1.5.6/lib + SOURCES_C := $(LIBRETRO_DIR)/libretro.c \ $(LIBRETRO_COMM_DIR)/formats/png/rpng.c \ $(LIBRETRO_COMM_DIR)/streams/trans_stream.c \ @@ -70,16 +74,36 @@ SOURCES_C := $(LIBRETRO_DIR)/libretro.c \ $(COMMON_DIR)/mp3_sync.c \ $(COMMON_DIR)/mp3_dummy.c \ $(UNZIP_DIR)/unzip.c \ - $(CORE_DIR)/pico/cd/libchdr/src/libchdr_bitstream.c \ - $(CORE_DIR)/pico/cd/libchdr/src/libchdr_cdrom.c \ - $(CORE_DIR)/pico/cd/libchdr/src/libchdr_chd.c \ - $(CORE_DIR)/pico/cd/libchdr/src/libchdr_flac.c \ - $(CORE_DIR)/pico/cd/libchdr/src/libchdr_huffman.c \ - $(CORE_DIR)/pico/cd/libchdr/deps/lzma-19.00/src/LzFind.c \ - $(CORE_DIR)/pico/cd/libchdr/deps/lzma-19.00/src/LzmaDec.c \ - $(CORE_DIR)/pico/cd/libchdr/deps/lzma-19.00/src/LzmaEnc.c - -COREFLAGS := $(addprefix -D,$(DEFINES)) -fno-strict-aliasing -DUSE_LIBCHDR=1 -D_7ZIP_ST -I$(CORE_DIR)/pico/cd/libchdr/include -I$(CORE_DIR)/pico/cd/libchdr/deps/lzma-19.00/include + $(LCHDR)/src/libchdr_bitstream.c \ + $(LCHDR)/src/libchdr_cdrom.c \ + $(LCHDR)/src/libchdr_chd.c \ + $(LCHDR)/src/libchdr_flac.c \ + $(LCHDR)/src/libchdr_huffman.c \ + $(LCHDR_LZMA)/src/Alloc.c \ + $(LCHDR_LZMA)/src/CpuArch.c \ + $(LCHDR_LZMA)/src/Delta.c \ + $(LCHDR_LZMA)/src/LzFind.c \ + $(LCHDR_LZMA)/src/LzmaDec.c \ + $(LCHDR_LZMA)/src/LzmaEnc.c \ + $(LCHDR_LZMA)/src/Sort.c \ + $(LCHDR_ZSTD)/common/entropy_common.c \ + $(LCHDR_ZSTD)/common/error_private.c \ + $(LCHDR_ZSTD)/common/fse_decompress.c \ + $(LCHDR_ZSTD)/common/xxhash.c \ + $(LCHDR_ZSTD)/common/zstd_common.c \ + $(LCHDR_ZSTD)/decompress/huf_decompress.c \ + $(LCHDR_ZSTD)/decompress/zstd_ddict.c \ + $(LCHDR_ZSTD)/decompress/zstd_decompress_block.c \ + $(LCHDR_ZSTD)/decompress/zstd_decompress.c + +COREFLAGS := $(addprefix -D,$(DEFINES)) -fno-strict-aliasing -DUSE_LIBCHDR=1 -DZ7_ST -DZSTD_DISABLE_ASM +COREFLAGS += -I$(LCHDR)/include -I$(LCHDR_LZMA)/include -I$(LCHDR_ZSTD) +ifeq (,$(call gte,$(APP_PLATFORM_LEVEL),18)) +ifneq ($(TARGET_ARCH_ABI),arm64-v8a) +# HACK +COREFLAGS += -Dgetauxval=0* +endif +endif GIT_REVISION := $(shell git rev-parse --short HEAD || echo unknown) COREFLAGS += -DREVISION=\"$(GIT_REVISION)\" diff --git a/pico/cd/libchdr b/pico/cd/libchdr index 4ad57f9e7..0b5a86fe0 160000 --- a/pico/cd/libchdr +++ b/pico/cd/libchdr @@ -1 +1 @@ -Subproject commit 4ad57f9e71ea35a8e62be20a059463bfe3abf043 +Subproject commit 0b5a86fe0c8b64497d7c6cbc23db72fd6fb1b982 From 8d0480151879eb0beb4c197d183f1a377ea573c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kelemen=20=28vudiq=29?= Date: Fri, 24 May 2024 19:50:37 +0200 Subject: [PATCH 38/44] remove fflush() call before exit() the buffer is flushed anyways at exit() and fixes compile error with gcc14: pico/carthw/svp/compiler.c: In function 'ssp_translate_block': pico/carthw/svp/compiler.c:1800:24: error: passing argument 1 of 'rfflush' from incompatible pointer type [-Wincompatible-pointer-types] 1800 | fflush(stdout); | ^~~~~~ | | | FILE * In file included from ./pico/pico_port.h:12, from ./pico/pico_int.h:15, from pico/carthw/svp/compiler.c:9: platform/libretro/libretro-common/include/streams/file_stream_transforms.h:89:25: note: expected 'RFILE *' but argument is of type 'FILE *' 89 | int64_t rfflush(RFILE * stream); | ~~~~~~~~^~~~~~ this error presents itself when building the libretro core, so this could be also solved by wrapping the call to fflush(): #ifndef __LIBRETRO__ fflush(stdout); #else fflush((RFILE *)stdout); #endif --- pico/carthw/svp/compiler.c | 1 - 1 file changed, 1 deletion(-) diff --git a/pico/carthw/svp/compiler.c b/pico/carthw/svp/compiler.c index c472a6008..941187ce6 100644 --- a/pico/carthw/svp/compiler.c +++ b/pico/carthw/svp/compiler.c @@ -1797,7 +1797,6 @@ void *ssp_translate_block(int pc) if (tcache_ptr - (u32 *)tcache > DRC_TCACHE_SIZE/4) { elprintf(EL_ANOMALY|EL_STATUS|EL_SVP, "tcache overflow!\n"); - fflush(stdout); exit(1); } From 68e50296e675d3f5a6e23a26029a64930cdea7dc Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 27 May 2024 23:53:26 +0200 Subject: [PATCH 39/44] sh2 drc, small fixes (cycle counting, invalidation) --- Makefile | 2 +- cpu/drc/emit_arm.c | 13 +++--- cpu/drc/emit_x86.c | 3 +- cpu/sh2/compiler.c | 87 ++++++++++++++++++++++------------------ platform/common/disarm.c | 9 +++++ 5 files changed, 67 insertions(+), 47 deletions(-) diff --git a/Makefile b/Makefile index 99c339163..835238958 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ asm_32xmemory ?= 1 else use_fame ?= 1 use_cz80 ?= 1 -ifneq (,$(filter x86% i386% mips% aarch% riscv% powerpc% ppc%, $(ARCH))) +ifneq (,$(filter x86% i386% i686% mips% aarch% riscv% powerpc% ppc%, $(ARCH))) use_sh2drc ?= 1 endif endif diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index ed4732f6a..454ff87b4 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -1329,9 +1329,10 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) int t2 = rcache_get_tmp(); \ int t3 = rcache_get_tmp(); \ /* if (sr < 0) return */ \ - emith_asrf(t2, sr, 12); \ + emith_cmp_r_imm(sr, 0); \ EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ + emith_asr(t2, sr, 12); \ emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ @@ -1362,13 +1363,11 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) } while (0) #define emith_carry_to_t(srr, is_sub) do { \ - if (is_sub) { /* has inverted C on ARM */ \ + emith_bic_r_imm(srr, 1); \ + if (is_sub) /* has inverted C on ARM */ \ emith_or_r_imm_c(A_COND_CC, srr, 1); \ - emith_bic_r_imm_c(A_COND_CS, srr, 1); \ - } else { \ + else \ emith_or_r_imm_c(A_COND_CS, srr, 1); \ - emith_bic_r_imm_c(A_COND_CC, srr, 1); \ - } \ } while (0) #define emith_t_to_carry(srr, is_sub) do { \ @@ -1494,7 +1493,7 @@ static void emith_sync_t(int sr) else if (tcond == A_COND_NV) emith_bic_r_imm(sr, T); else if (tcond >= 0) { - emith_bic_r_imm_c(emith_invert_cond(tcond),sr, T); + emith_bic_r_imm(sr, T); emith_or_r_imm_c(tcond, sr, T); } tcond = -1; diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 6fbe5abf8..6a815e85e 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -1269,9 +1269,10 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common if (t3 == xAX) { t3 = t1; t1 = xAX; } /* for MUL */ \ if (t3 == xDX) { t3 = t2; t2 = xDX; } \ /* if (sr < 0) return */ \ - emith_asrf(t2, sr, 12); \ + emith_cmp_r_imm(sr, 0); \ EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ + emith_asr(t2, sr, 12); \ emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index d7ae8960f..b87f2b9b7 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -260,7 +260,7 @@ static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr) printf("trace eof at %08lx\n",ftell(trace[idx])); exit(1); } - fsh2.sr = (fsh2.sr & 0xbff) | (sh2->sr & ~0xbff); + fsh2.sr = (fsh2.sr & 0x3ff) | (sh2->sr & ~0x3ff); fsh2.is_slave = idx; if (memcmp(&fsh2, sh2, offsetof(SH2, read8_map)) || 0)//memcmp(&fsh2.pdb_io_csum, &sh2->pdb_io_csum, sizeof(sh2->pdb_io_csum))) @@ -3250,6 +3250,7 @@ static void emit_branch_linkage_code(SH2 *sh2, struct block_desc *block, int tca } static void *dr_get_pc_base(u32 pc, SH2 *sh2); +static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, int free); static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) { @@ -3319,6 +3320,13 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) block = dr_find_inactive_block(tcache_id, crc, base_pc, end_pc - base_pc, base_literals, end_literals - base_literals); +#if (DRC_DEBUG & (256|512)) + // remove any (partial) old blocks which might get in the way, to make sure + // the same branch targets are used in the recording/playback code. Not needed + // normally since the SH2 code wasn't overwritten and should be the same. + sh2_smc_rm_blocks(base_pc, end_pc - base_pc, tcache_id, 0); +#endif + if (block) { dbg(2, "== %csh2 reuse block %08x-%08x,%08x-%08x -> %p", sh2->is_slave ? 's' : 'm', base_pc, end_pc, base_literals, end_literals, block->entryp->tcache_ptr); @@ -3539,7 +3547,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) // if exiting a pinned loop pinned regs must be written back to ctx // since they are reloaded in the loop entry code emith_cmp_r_imm(sr, 0); - EMITH_JMP_START(DCOND_GT); + EMITH_JMP_START(DCOND_GE); rcache_save_pinned(); if (blx_target_count < ARRAY_SIZE(blx_targets)) { @@ -3554,7 +3562,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_jump(sh2_drc_exit); rcache_free_tmp(tmp); } - EMITH_JMP_END(DCOND_GT); + EMITH_JMP_END(DCOND_GE); } else #endif { @@ -3568,10 +3576,10 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) // blx table full, must inline exit code tmp = rcache_get_tmp_arg(0); emith_cmp_r_imm(sr, 0); - EMITH_SJMP_START(DCOND_GT); - emith_move_r_imm_c(DCOND_LE, tmp, pc); - emith_jump_cond(DCOND_LE, sh2_drc_exit); - EMITH_SJMP_END(DCOND_GT); + EMITH_SJMP_START(DCOND_GE); + emith_move_r_imm_c(DCOND_LT, tmp, pc); + emith_jump_cond(DCOND_LT, sh2_drc_exit); + EMITH_SJMP_END(DCOND_GE); rcache_free_tmp(tmp); } } @@ -5627,7 +5635,7 @@ static void sh2_generate_utils(void) #endif } -static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, u32 shift) +static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, int free) { struct block_list **blist, *entry, *next; u32 mask = RAM_SIZE(tcache_id) - 1; @@ -5635,40 +5643,43 @@ static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, u32 shift) u32 start_addr, end_addr; u32 start_lit, end_lit; struct block_desc *block; -#if (DRC_DEBUG & 2) - int removed = 0; -#endif + int removed = 0, rest; + u32 _a = a; // ignore cache-through a &= wtmask; - blist = &inval_lookup[tcache_id][(a & mask) / INVAL_PAGE_SIZE]; - entry = *blist; - // go through the block list for this range - while (entry != NULL) { - next = entry->next; - block = entry->block; - start_addr = block->addr & wtmask; - end_addr = start_addr + block->size; - start_lit = block->addr_lit & wtmask; - end_lit = start_lit + block->size_lit; - // disable/delete block if it covers the modified address - if ((start_addr < a+len && a < end_addr) || - (start_lit < a+len && a < end_lit)) - { - dbg(2, "smc remove @%08x", a); - end_addr = (start_lit < a+len && block->size_lit ? a : 0); - dr_rm_block_entry(block, tcache_id, end_addr, 0); -#if (DRC_DEBUG & 2) - removed = 1; -#endif + do { + blist = &inval_lookup[tcache_id][(a & mask) / INVAL_PAGE_SIZE]; + entry = *blist; + // go through the block list for this range + while (entry != NULL) { + next = entry->next; + block = entry->block; + start_addr = block->addr & wtmask; + end_addr = start_addr + block->size; + start_lit = block->addr_lit & wtmask; + end_lit = start_lit + block->size_lit; + // disable/delete block if it covers the modified address + if ((start_addr < a+len && a < end_addr) || + (start_lit < a+len && a < end_lit)) + { + dbg(2, "smc remove @%08x", a); + end_addr = (start_lit < a+len && block->size_lit ? a : 0); + dr_rm_block_entry(block, tcache_id, end_addr, free); + removed = 1; + } + entry = next; } - entry = next; + rest = INVAL_PAGE_SIZE - (a & (INVAL_PAGE_SIZE-1)); + a += rest, len -= rest; + } while (len > 0); + + if (!removed && len <= 4) { + dbg(2, "rm_blocks called @%08x, no work?", _a); + return; } -#if (DRC_DEBUG & 2) - if (!removed) - dbg(2, "rm_blocks called @%08x, no work?", a); -#endif + #if BRANCH_CACHE if (tcache_id) memset32(sh2s[tcache_id-1].branch_cache, -1, sizeof(sh2s[0].branch_cache)/4); @@ -5691,12 +5702,12 @@ static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, u32 shift) void sh2_drc_wcheck_ram(u32 a, unsigned len, SH2 *sh2) { - sh2_smc_rm_blocks(a, len, 0, SH2_DRCBLK_RAM_SHIFT); + sh2_smc_rm_blocks(a, len, 0, 0); } void sh2_drc_wcheck_da(u32 a, unsigned len, SH2 *sh2) { - sh2_smc_rm_blocks(a, len, 1 + sh2->is_slave, SH2_DRCBLK_DA_SHIFT); + sh2_smc_rm_blocks(a, len, 1 + sh2->is_slave, 0); } int sh2_execute_drc(SH2 *sh2c, int cycles) diff --git a/platform/common/disarm.c b/platform/common/disarm.c index 249922064..90d0b80df 100644 --- a/platform/common/disarm.c +++ b/platform/common/disarm.c @@ -207,6 +207,15 @@ static int data_processing(unsigned int pc, unsigned int insn, char *buf, size_t snprintf(buf, buf_len, "%s%s%s %s,%s,%s%s", name, condition(insn), s, register_name(rd), register_name(rn), register_name(rm), shift(insn, tmp_buf, sizeof(tmp_buf))); } } + else if ((insn & 0x0fb00000) == 0x03000000) + { + unsigned int imm; + char *half = (insn & 0x00400000) ? "t" : "w"; + + imm = (insn & 0x00000fff) | ((insn & 0x000f0000) >> 4); + + snprintf(buf, buf_len, "mov%s%s %s%s", half, condition(insn), register_name(rd), immediate(imm, 0, 1, tmp_buf, sizeof(tmp_buf))); + } else { unsigned int imm; From 38fd3bd8669827e3670be8f788f182945fa6f45c Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 2 Jun 2024 07:48:15 +0000 Subject: [PATCH 40/44] sh2 drc, fix mul/add saturation --- cpu/drc/emit_arm.c | 30 +++++++++++++++--------------- cpu/drc/emit_arm64.c | 24 ++++++++++++------------ cpu/drc/emit_mips.c | 24 ++++++++++++------------ cpu/drc/emit_ppc.c | 24 ++++++++++++------------ cpu/drc/emit_riscv.c | 24 ++++++++++++------------ cpu/drc/emit_x86.c | 30 +++++++++++++++--------------- 6 files changed, 78 insertions(+), 78 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 454ff87b4..7d51c357b 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -1333,7 +1333,7 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ emith_asr(t2, sr, 12); \ - emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ + emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles))); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ if (reg >= 0) { \ @@ -1427,16 +1427,16 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) emith_sext(mh, mh, 16); \ emith_mula_s64(ml, mh, rn, rm); \ /* overflow if top 17 bits of MACH aren't all 1 or 0 */ \ - /* to check: add MACH[15] to MACH[31:16]. this is 0 if no overflow */ \ - emith_asrf(rn, mh, 16); /* sum = (MACH>>16) + ((MACH>>15)&1) */ \ - emith_adcf_r_imm(rn, 0); /* (MACH>>15) is in carry after shift */ \ - EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> ov */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x0000); /* -overflow */ \ - emith_move_r_imm_c(DCOND_NE, mh, 0x8000); \ - EMITH_SJMP_START(DCOND_LE); /* sum > 0 -> +ovl */ \ - emith_sub_r_imm_c(DCOND_GT, ml, 1); /* 0xffffffff */ \ - emith_sub_r_imm_c(DCOND_GT, mh, 1); /* 0x00007fff */ \ - EMITH_SJMP_END(DCOND_LE); \ + /* to check: add MACH >> 31 to MACH >> 15. this is 0 if no overflow */ \ + emith_asr(rn, mh, 15); \ + emith_addf_r_r_r_lsr(rn, rn, mh, 31); \ + EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> -ovl */ \ + emith_move_r_imm_c(DCOND_NE, ml, 0x00000000); \ + emith_move_r_imm_c(DCOND_NE, mh, 0x00008000); \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0xffffffff */ \ + emith_sub_r_imm_c(DCOND_PL, mh, 1); /* 0x00007fff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP2_END(DCOND_NE); \ } while (0) @@ -1456,10 +1456,10 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> overflow */ \ /* XXX: LSB signalling only in SH1, or in SH2 too? */ \ emith_move_r_imm_c(DCOND_NE, mh, 0x00000001); /* LSB of MACH */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* negative ovrfl */ \ - EMITH_SJMP_START(DCOND_LE); /* sum > 0 -> positive ovrfl */ \ - emith_sub_r_imm_c(DCOND_GT, ml, 1); /* 0x7fffffff */ \ - EMITH_SJMP_END(DCOND_LE); \ + emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* -ovrfl */ \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovrfl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0x7fffffff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP2_END(DCOND_NE); \ } while (0) diff --git a/cpu/drc/emit_arm64.c b/cpu/drc/emit_arm64.c index f97583d24..b8ae926ad 100644 --- a/cpu/drc/emit_arm64.c +++ b/cpu/drc/emit_arm64.c @@ -1242,7 +1242,7 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode) EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ emith_asr(t2, sr, 12); \ - emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ + emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles))); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ if (reg >= 0) { \ @@ -1309,13 +1309,13 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode) /* to check: add MACH >> 31 to MACH >> 15. this is 0 if no overflow */ \ emith_asr(rn, mh, 15); \ emith_addf_r_r_r_lsr(rn, rn, mh, 31); \ - EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> ov */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x0000); /* -overflow */ \ - emith_move_r_imm_c(DCOND_NE, mh, 0x8000); \ - EMITH_SJMP_START(DCOND_LE); /* sum > 0 -> +ovl */ \ - emith_sub_r_imm_c(DCOND_GT, ml, 1); /* 0xffffffff */ \ - emith_sub_r_imm_c(DCOND_GT, mh, 1); /* 0x00007fff */ \ - EMITH_SJMP_END(DCOND_LE); \ + EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> -ovl */ \ + emith_move_r_imm_c(DCOND_NE, ml, 0x00000000); \ + emith_move_r_imm_c(DCOND_NE, mh, 0x00008000); \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0xffffffff */ \ + emith_sub_r_imm_c(DCOND_PL, mh, 1); /* 0x00007fff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) @@ -1336,10 +1336,10 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode) EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> overflow */ \ /* XXX: LSB signalling only in SH1, or in SH2 too? */ \ emith_move_r_imm_c(DCOND_NE, mh, 0x00000001); /* LSB of MACH */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* negative ovrfl */ \ - EMITH_SJMP_START(DCOND_LE); /* sum > 0 -> positive ovrfl */ \ - emith_sub_r_imm_c(DCOND_GT, ml, 1); /* 0x7fffffff */ \ - EMITH_SJMP_END(DCOND_LE); \ + emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* -ovrfl */ \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovrfl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0x7fffffff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) diff --git a/cpu/drc/emit_mips.c b/cpu/drc/emit_mips.c index d2964dca3..d775fdd80 100644 --- a/cpu/drc/emit_mips.c +++ b/cpu/drc/emit_mips.c @@ -1736,7 +1736,7 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ emith_asr(t2, sr, 12); \ - emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ + emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles))); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ if (reg >= 0) { \ @@ -1806,13 +1806,13 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) emith_asr(rn, mh, 15); \ emith_add_r_r_r_lsr(rn, rn, mh, 31); /* sum = (MACH>>31)+(MACH>>15) */ \ emith_teq_r_r(rn, Z0); /* (need only N and Z flags) */ \ - EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> ov */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x0000); /* -overflow */ \ - emith_move_r_imm_c(DCOND_NE, mh, 0x8000); \ - EMITH_SJMP_START(DCOND_PL); /* sum > 0 -> +ovl */ \ - emith_sub_r_imm_c(DCOND_MI, ml, 1); /* 0xffffffff */ \ - emith_sub_r_imm_c(DCOND_MI, mh, 1); /* 0x00007fff */ \ - EMITH_SJMP_END(DCOND_PL); \ + EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> -ovl */ \ + emith_move_r_imm_c(DCOND_NE, ml, 0x00000000); \ + emith_move_r_imm_c(DCOND_NE, mh, 0x00008000); \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0xffffffff */ \ + emith_sub_r_imm_c(DCOND_PL, mh, 1); /* 0x00007fff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) @@ -1835,10 +1835,10 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> overflow */ \ /* XXX: LSB signalling only in SH1, or in SH2 too? */ \ emith_move_r_imm_c(DCOND_NE, mh, 0x00000001); /* LSB of MACH */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* negative ovrfl */ \ - EMITH_SJMP_START(DCOND_PL); /* sum > 0 -> positive ovrfl */ \ - emith_sub_r_imm_c(DCOND_MI, ml, 1); /* 0x7fffffff */ \ - EMITH_SJMP_END(DCOND_PL); \ + emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* -ovrfl */ \ + EMITH_SJMP_START(DCOND_MI); /* sum < 0 -> +ovrfl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0x7fffffff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) diff --git a/cpu/drc/emit_ppc.c b/cpu/drc/emit_ppc.c index d856f100d..f8e05b14f 100644 --- a/cpu/drc/emit_ppc.c +++ b/cpu/drc/emit_ppc.c @@ -1670,7 +1670,7 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ emith_asr(t2, sr, 12); \ - emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ + emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles))); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ if (reg >= 0) { \ @@ -1742,13 +1742,13 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) emith_asr(rn, mh, 15); \ emith_add_r_r_r_lsr(rn, rn, mh, 31); /* sum = (MACH>>31)+(MACH>>15) */ \ emith_tst_r_r(rn, rn); /* (need only N and Z flags) */ \ - EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> ov */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x0000); /* -overflow */ \ - emith_move_r_imm_c(DCOND_NE, mh, 0x8000); \ - EMITH_SJMP_START(DCOND_PL); /* sum > 0 -> +ovl */ \ - emith_sub_r_imm_c(DCOND_MI, ml, 1); /* 0xffffffff */ \ - emith_sub_r_imm_c(DCOND_MI, mh, 1); /* 0x00007fff */ \ - EMITH_SJMP_END(DCOND_PL); \ + EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> -ovl */ \ + emith_move_r_imm_c(DCOND_NE, ml, 0x00000000); \ + emith_move_r_imm_c(DCOND_NE, mh, 0x00008000); \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0xffffffff */ \ + emith_sub_r_imm_c(DCOND_PL, mh, 1); /* 0x00007fff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) @@ -1771,10 +1771,10 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> overflow */ \ /* XXX: LSB signalling only in SH1, or in SH2 too? */ \ emith_move_r_imm_c(DCOND_NE, mh, 0x00000001); /* LSB of MACH */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* negative ovrfl */ \ - EMITH_SJMP_START(DCOND_PL); /* sum > 0 -> positive ovrfl */ \ - emith_sub_r_imm_c(DCOND_MI, ml, 1); /* 0x7fffffff */ \ - EMITH_SJMP_END(DCOND_PL); \ + emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* -ovrfl */ \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovrfl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0x7fffffff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) diff --git a/cpu/drc/emit_riscv.c b/cpu/drc/emit_riscv.c index 832575b24..d4fd65b82 100644 --- a/cpu/drc/emit_riscv.c +++ b/cpu/drc/emit_riscv.c @@ -1494,7 +1494,7 @@ static int emith_cond_check(int cond, int *r, int *s) EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ emith_asr(t2, sr, 12); \ - emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ + emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles))); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ if (reg >= 0) { \ @@ -1564,13 +1564,13 @@ static int emith_cond_check(int cond, int *r, int *s) emith_asr(rn, mh, 15); \ emith_add_r_r_r_lsr(rn, rn, mh, 31); /* sum = (MACH>>31)+(MACH>>15) */ \ emith_teq_r_r(rn, Z0); /* (need only N and Z flags) */ \ - EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> ov */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x0000); /* -overflow */ \ - emith_move_r_imm_c(DCOND_NE, mh, 0x8000); \ - EMITH_SJMP_START(DCOND_PL); /* sum > 0 -> +ovl */ \ - emith_sub_r_imm_c(DCOND_MI, ml, 1); /* 0xffffffff */ \ - emith_sub_r_imm_c(DCOND_MI, mh, 1); /* 0x00007fff */ \ - EMITH_SJMP_END(DCOND_PL); \ + EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> -ovl */ \ + emith_move_r_imm_c(DCOND_NE, ml, 0x00000000); \ + emith_move_r_imm_c(DCOND_NE, mh, 0x00008000); \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0xffffffff */ \ + emith_sub_r_imm_c(DCOND_PL, mh, 1); /* 0x00007fff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) @@ -1593,10 +1593,10 @@ static int emith_cond_check(int cond, int *r, int *s) EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> overflow */ \ /* XXX: LSB signalling only in SH1, or in SH2 too? */ \ emith_move_r_imm_c(DCOND_NE, mh, 0x00000001); /* LSB of MACH */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* negative ovrfl */ \ - EMITH_SJMP_START(DCOND_PL); /* sum > 0 -> positive ovrfl */ \ - emith_sub_r_imm_c(DCOND_MI, ml, 1); /* 0x7fffffff */ \ - EMITH_SJMP_END(DCOND_PL); \ + emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* -ovrfl */ \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +ovrfl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0x7fffffff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 6a815e85e..53d52385f 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -1273,7 +1273,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common EMITH_JMP_START(DCOND_LE); \ /* turns = sr.cycles / cycles */ \ emith_asr(t2, sr, 12); \ - emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles)) + 1); \ + emith_move_r_imm(t3, (u32)((1ULL<<32) / (cycles))); \ emith_mul_u64(t1, t2, t2, t3); /* multiply by 1/x */ \ rcache_free_tmp(t3); \ if (reg >= 0) { \ @@ -1363,16 +1363,16 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common emith_tst_r_imm(sr, S); \ EMITH_SJMP_START(DCOND_EQ); \ /* overflow if top 17 bits of MACH aren't all 1 or 0 */ \ - /* to check: add MACH[15] to MACH[31:16]. this is 0 if no overflow */ \ - emith_asrf(rn, mh, 16); /* sum = (MACH>>16) + ((MACH>>15)&1) */ \ - emith_adcf_r_imm(rn, 0); /* (MACH>>15) is in carry after shift */ \ - EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> ov */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x0000); /* -overflow */ \ - emith_move_r_imm_c(DCOND_NE, mh, 0x8000); \ - EMITH_SJMP_START(DCOND_LE); /* sum > 0 -> +ovl */ \ - emith_sub_r_imm_c(DCOND_GT, ml, 1); /* 0xffffffff */ \ - emith_sub_r_imm_c(DCOND_GT, mh, 1); /* 0x00007fff */ \ - EMITH_SJMP_END(DCOND_LE); \ + /* to check: add MACH >> 31 to MACH >> 15. this is 0 if no overflow */ \ + emith_asr(rn, mh, 15); \ + emith_addf_r_r_r_lsr(rn, rn, mh, 31); \ + EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> -ovl */ \ + emith_move_r_imm_c(DCOND_NE, ml, 0x00000000); \ + emith_move_r_imm_c(DCOND_NE, mh, 0x00008000); \ + EMITH_SJMP_START(DCOND_MI); /* sum < 0 -> -ovl */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0xffffffff */ \ + emith_sub_r_imm_c(DCOND_PL, mh, 1); /* 0x00007fff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) @@ -1394,10 +1394,10 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> overflow */ \ /* XXX: LSB signalling only in SH1, or in SH2 too? */ \ emith_move_r_imm_c(DCOND_NE, mh, 0x00000001); /* LSB of MACH */ \ - emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* negative ovrfl */ \ - EMITH_SJMP_START(DCOND_LE); /* sum > 0 -> positive ovrfl */ \ - emith_sub_r_imm_c(DCOND_GT, ml, 1); /* 0x7fffffff */ \ - EMITH_SJMP_END(DCOND_LE); \ + emith_move_r_imm_c(DCOND_NE, ml, 0x80000000); /* -overflow */ \ + EMITH_SJMP_START(DCOND_MI); /* sum > 0 -> +overflow */ \ + emith_sub_r_imm_c(DCOND_PL, ml, 1); /* 0x7fffffff */ \ + EMITH_SJMP_END(DCOND_MI); \ EMITH_SJMP_END(DCOND_EQ); \ EMITH_SJMP_END(DCOND_EQ); \ } while (0) From 4af2edc365222c3cfc8a511b9be71405310b41ea Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 2 Jun 2024 07:53:04 +0000 Subject: [PATCH 41/44] 32x, fixes for comparing cycles --- cpu/sh2/sh2.h | 2 +- pico/32x/32x.c | 4 ++-- pico/32x/memory.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index bb8debe02..95c5658fb 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -54,7 +54,7 @@ typedef struct SH2_ #define SH2_IN_DRC (1 << 7) // DRC in use unsigned int state; uint32_t poll_addr; - int poll_cycles; + unsigned int poll_cycles; int poll_cnt; // NB MUST be a bit unused in SH2 SR, see also cpu/sh2/compiler.c! #define SH2_NO_POLLING (1 << 10) // poll detection control diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 6e2cb4bce..00239a112 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -583,10 +583,10 @@ void sync_sh2s_lockstep(unsigned int m68k_target) unsigned int mcycles; mcycles = msh2.m68krcycles_done; - if (ssh2.m68krcycles_done < mcycles) + if (CYCLES_GT(mcycles, ssh2.m68krcycles_done)) mcycles = ssh2.m68krcycles_done; - while (mcycles < m68k_target) { + while (CYCLES_GT(m68k_target, mcycles)) { mcycles += STEP_LS; sync_sh2s_normal(mcycles); } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 7d964f20c..1d17f9f62 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -72,7 +72,7 @@ static int m68k_poll_detect(u32 a, u32 cycles, u32 flags) // support polling on 2 addresses - seen in Wolfenstein int match = (a - m68k_poll.addr1 <= 3 || a - m68k_poll.addr2 <= 3); - if (match && cycles - m68k_poll.cycles <= 64 && !SekNotPolling) + if (match && CYCLES_GT(64, cycles - m68k_poll.cycles) && !SekNotPolling) { // detect split 32bit access by same cycle count, and ignore those if (cycles != m68k_poll.cycles && ++m68k_poll.cnt >= POLL_THRESHOLD) { @@ -160,7 +160,7 @@ void NOINLINE p32x_sh2_poll_event(u32 a, SH2 *sh2, u32 flags, u32 m68k_cycles) elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state, sh2->state & ~flags); - if (sh2->m68krcycles_done < m68k_cycles && !(sh2->state & SH2_STATE_RUN)) + if (CYCLES_GT(m68k_cycles, sh2->m68krcycles_done) && !(sh2->state & SH2_STATE_RUN)) sh2->m68krcycles_done = m68k_cycles; pevt_log_sh2_o(sh2, EVT_POLL_END); From a43c77c0e538cf132a5406164980a0323091c9e7 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 9 Jun 2024 22:24:45 +0000 Subject: [PATCH 42/44] build, fix libchd zstd support for libretro static linking --- Makefile | 4 ++-- pico/cd/libchdr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 835238958..713cbe90d 100644 --- a/Makefile +++ b/Makefile @@ -345,9 +345,9 @@ ZSTD_OBJS += $(ZSTD)/decompress/zstd_decompress_block.o ZSTD_OBJS += $(ZSTD)/decompress/zstd_decompress.o $(ZSTD_OBJS) $(CHDR_OBJS): CFLAGS += -I$(ZSTD) -Wno-unused -OBJS += $(CHDR_OBJS) +OBJS += $(CHDR_OBJS) $(ZSTD_OBJS) ifneq ($(STATIC_LINKING), 1) -OBJS += $(LZMA_OBJS) $(ZSTD_OBJS) +OBJS += $(LZMA_OBJS) endif # ouf... prepend includes to overload headers available in the toolchain CFLAGS := -I$(LZMA)/include -I$(CHDR)/include $(CFLAGS) diff --git a/pico/cd/libchdr b/pico/cd/libchdr index 0b5a86fe0..e62ac5995 160000 --- a/pico/cd/libchdr +++ b/pico/cd/libchdr @@ -1 +1 @@ -Subproject commit 0b5a86fe0c8b64497d7c6cbc23db72fd6fb1b982 +Subproject commit e62ac5995b1c7ef65ece35293914843b8ee57d49 From 31efd4546e9246c7999dbb748cd1c7727df5896a Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 9 Jun 2024 22:30:51 +0000 Subject: [PATCH 43/44] sh2 drc, several bug fixes --- cpu/drc/emit_arm.c | 4 ++-- cpu/drc/emit_arm64.c | 2 +- cpu/drc/emit_mips.c | 10 +++++++- cpu/drc/emit_ppc.c | 2 +- cpu/drc/emit_riscv.c | 6 ++--- cpu/drc/emit_x86.c | 5 ++-- cpu/sh2/compiler.c | 45 ++++++++++++++++++------------------ cpu/sh2/mame/sh2pico.c | 2 +- pico/32x/sh2soc.c | 11 +++++---- platform/libretro/libretro.c | 2 +- platform/linux/emu.c | 2 +- 11 files changed, 51 insertions(+), 40 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 7d51c357b..ecaf06e29 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -1,7 +1,7 @@ /* * Basic macros to emit ARM instructions and some utils * Copyright (C) 2008,2009,2010 notaz - * Copyright (C) 2019 kub + * Copyright (C) 2019-2024 kub * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -1196,7 +1196,7 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) #define emith_jump_at(ptr, target) do { \ u32 *ptr_ = (u32 *)ptr; \ - u32 val_ = (u32 *)(target) - (u32 *)(ptr) - 2; \ + u32 val_ = (u32 *)(target) - ptr_ - 2; \ EOP_C_B_PTR(ptr_, A_COND_AL, 0, val_ & 0xffffff); \ } while (0) #define emith_jump_at_size() 4 diff --git a/cpu/drc/emit_arm64.c b/cpu/drc/emit_arm64.c index b8ae926ad..10eb8a2aa 100644 --- a/cpu/drc/emit_arm64.c +++ b/cpu/drc/emit_arm64.c @@ -1,6 +1,6 @@ /* * Basic macros to emit ARM A64 instructions and some utils - * Copyright (C) 2019 kub + * Copyright (C) 2019-2024 kub * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. diff --git a/cpu/drc/emit_mips.c b/cpu/drc/emit_mips.c index d775fdd80..a92709d3d 100644 --- a/cpu/drc/emit_mips.c +++ b/cpu/drc/emit_mips.c @@ -1,6 +1,6 @@ /* * Basic macros to emit MIPS32/MIPS64 Release 1 or 2 instructions and some utils - * Copyright (C) 2019 kub + * Copyright (C) 2019-2024 kub * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -1671,12 +1671,20 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) asm volatile( " rdhwr %2, $1;" " bal 0f;" // needed to allow for jr.hb: +#if _MIPS_SZPTR == 64 + "0: daddiu $ra, $ra, 3f-0b;" // set ra to insn after jr.hb +#else "0: addiu $ra, $ra, 3f-0b;" // set ra to insn after jr.hb +#endif " beqz %2, 3f;" "1: synci 0(%0);" " sltu %3, %0, %1;" +#if _MIPS_SZPTR == 64 + " daddu %0, %0, %2;" +#else " addu %0, %0, %2;" +#endif " bnez %3, 1b;" " sync;" diff --git a/cpu/drc/emit_ppc.c b/cpu/drc/emit_ppc.c index f8e05b14f..a765eb1e0 100644 --- a/cpu/drc/emit_ppc.c +++ b/cpu/drc/emit_ppc.c @@ -1,6 +1,6 @@ /* * Basic macros to emit PowerISA 2.03 64 bit instructions and some utils - * Copyright (C) 2020 kub + * Copyright (C) 2020-2024 kub * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. diff --git a/cpu/drc/emit_riscv.c b/cpu/drc/emit_riscv.c index d4fd65b82..0670a45ce 100644 --- a/cpu/drc/emit_riscv.c +++ b/cpu/drc/emit_riscv.c @@ -1,6 +1,6 @@ /* * Basic macros to emit RISC-V RV64IM instructions and some utils - * Copyright (C) 2019 kub + * Copyright (C) 2019-2024 kub * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -710,9 +710,9 @@ static void emith_move_imm(int r, uintptr_t imm) if (lui >> 12) { EMIT(R5_MOVT_IMM(r, lui)); if (imm & 0xfff) - EMIT(R5_ADD_IMM(r, r, imm)); + EMIT(R5_ADDW_IMM(r, r, imm)); } else - EMIT(R5_ADD_IMM(r, Z0, imm)); + EMIT(R5_ADDW_IMM(r, Z0, imm)); } static void emith_move_ptr_imm(int r, uintptr_t imm) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 53d52385f..628adbddc 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -1,7 +1,7 @@ /* * Basic macros to emit x86 instructions and some utils * Copyright (C) 2008,2009,2010 notaz - * Copyright (C) 2019 kub + * Copyright (C) 2019-2024 kub * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -1365,7 +1365,8 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common /* overflow if top 17 bits of MACH aren't all 1 or 0 */ \ /* to check: add MACH >> 31 to MACH >> 15. this is 0 if no overflow */ \ emith_asr(rn, mh, 15); \ - emith_addf_r_r_r_lsr(rn, rn, mh, 31); \ + emith_lsr(rm, mh, 31); \ + emith_addf_r_r(rn, rm); \ EMITH_SJMP_START(DCOND_EQ); /* sum != 0 -> -ovl */ \ emith_move_r_imm_c(DCOND_NE, ml, 0x00000000); \ emith_move_r_imm_c(DCOND_NE, mh, 0x00008000); \ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index b87f2b9b7..0714eb941 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -1,7 +1,7 @@ /* * SH2 recompiler * (C) notaz, 2009,2010,2013 - * (C) kub, 2018,2019,2020 + * (C) kub, 2018-2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -2610,7 +2610,8 @@ static uptr split_address(uptr la, uptr mask, s32 *offs) #ifdef __arm__ // arm32 offset has an add/sub flag and an unsigned 8 bit value, which only // allows values of [-255...255]. the value -256 thus can't be used. - if (*offs + sign == 0) { + if (*offs < 0) { // TODO not working at all with negative offsets on ARM? + //if (*offs == -sign) { la -= sign; *offs += sign; } @@ -2631,7 +2632,7 @@ static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, s32 *offs) // is r constant and points to a memory region? if (! gconst_get(r, &a)) return -1; - poffs = dr_ctx_get_mem_ptr(sh2, a, &mask); + poffs = dr_ctx_get_mem_ptr(sh2, a + *offs, &mask); if (poffs == -1) return -1; @@ -3244,10 +3245,11 @@ static void emit_branch_linkage_code(SH2 *sh2, struct block_desc *block, int tca } #define FLUSH_CYCLES(sr) \ - if (cycles > 0) { \ + if (cycles > 0) \ emith_sub_r_imm(sr, cycles << 12); \ - cycles = 0; \ - } + else if (cycles < 0) /* may happen after a branch not taken */ \ + emith_add_r_imm(sr, -cycles << 12); \ + cycles = 0; \ static void *dr_get_pc_base(u32 pc, SH2 *sh2); static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, int free); @@ -3960,10 +3962,10 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) #if DIV_OPTIMIZER if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) { // divide 32/16 - tmp = rcache_get_tmp_arg(1); - emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_get_reg_arg(0, div(opd).rn, NULL); rcache_get_reg_arg(2, div(opd).rm, NULL); + tmp = rcache_get_tmp_arg(1); + emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_invalidate_tmp(); emith_abicall(sh2_drc_divu32); tmp = rcache_get_tmp_ret(); @@ -3979,16 +3981,17 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_or_r_r_r(sr, sr, tmp3); // T rcache_free_tmp(tmp3); skip_op = div(opd).div1 + div(opd).rotcl; + cycles += skip_op; } else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) { // divide 64/32 tmp4 = rcache_get_reg(div(opd).ro, RC_GR_READ, NULL); emith_ctx_write(tmp4, offsetof(SH2, drc_tmp)); rcache_free(tmp4); - tmp = rcache_get_tmp_arg(1); - emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_get_reg_arg(0, div(opd).rn, NULL); rcache_get_reg_arg(2, div(opd).rm, NULL); + tmp = rcache_get_tmp_arg(1); + emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_invalidate_tmp(); emith_abicall(sh2_drc_divu64); tmp = rcache_get_tmp_ret(); @@ -4004,6 +4007,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); rcache_free_tmp(tmp3); skip_op = div(opd).div1 + div(opd).rotcl; + cycles += skip_op; } #endif break; @@ -4085,13 +4089,12 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) #if DIV_OPTIMIZER if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) { // divide 32/16 - tmp = rcache_get_tmp_arg(1); - emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp)); - rcache_get_reg_arg(0, div(opd).rn, NULL); + tmp = rcache_get_reg_arg(0, div(opd).rn, NULL); tmp2 = rcache_get_reg_arg(2, div(opd).rm, NULL); - tmp3 = rcache_get_tmp(); + tmp3 = rcache_get_tmp_arg(1); emith_lsr(tmp3, tmp2, 31); emith_or_r_r_lsl(sr, tmp3, M_SHIFT); // M = Rm[31] + emith_add_r_r_ptr_imm(tmp3, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_invalidate_tmp(); emith_abicall(sh2_drc_divs32); tmp = rcache_get_tmp_ret(); @@ -4108,6 +4111,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_or_r_r_r(sr, sr, tmp3); // T rcache_free_tmp(tmp3); skip_op = div(opd).div1 + div(opd).rotcl; + cycles += skip_op; } else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) { // divide 64/32 @@ -4138,6 +4142,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); // Q = !Ro[0]^M rcache_free_tmp(tmp3); skip_op = div(opd).div1 + div(opd).rotcl; + cycles += skip_op; } else #endif { @@ -5113,7 +5118,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_move_r_imm_s8_patch(rtsadd, tcache_ptr - (u8 *)rtsret); #endif - // branch not taken, correct cycle count + // branch not taken, correct cycle count (now, cycles < 0) if (ctaken) cycles -= ctaken; // set T bit to reflect branch not taken for OP_BRANCH_CT/CF @@ -5243,10 +5248,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) printf("~~~\n"); */ -#if (DRC_DEBUG) - fflush(stdout); -#endif - return block_entry_ptr; } @@ -5675,8 +5676,9 @@ static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, int free) a += rest, len -= rest; } while (len > 0); - if (!removed && len <= 4) { - dbg(2, "rm_blocks called @%08x, no work?", _a); + if (!removed) { + if (len <= 4) + dbg(2, "rm_blocks called @%08x, no work?", _a); return; } @@ -5984,7 +5986,6 @@ int sh2_drc_init(SH2 *sh2) // disasm the utils tcache_dsm_ptrs[0] = tcache; do_host_disasm(0); - fflush(stdout); #endif #if (DRC_DEBUG & 1) hash_collisions = 0; diff --git a/cpu/sh2/mame/sh2pico.c b/cpu/sh2/mame/sh2pico.c index 65f4757e8..2c2ea4066 100644 --- a/cpu/sh2/mame/sh2pico.c +++ b/cpu/sh2/mame/sh2pico.c @@ -1,7 +1,7 @@ #include "../sh2.h" #ifdef DRC_CMP -#include "../compiler.c" +#include "../compiler.h" #define BUSY_LOOP_HACKS 0 #else #define BUSY_LOOP_HACKS 1 diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index fb1cf1e9c..6b122eacf 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -435,24 +435,25 @@ void REGPARM(3) sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) old = r[a / 4]; r[a / 4] = d; + // TODO: DRC doesn't correctly extend 'd' parameter register to 64bit :-/ switch (a) { // division unit (TODO: verify): case 0x104: // DVDNT: divident L, starts divide elprintf_sh2(sh2, EL_32XP, "divide %08x / %08x", - d, r[0x100 / 4]); + r[0x104 / 4], r[0x100 / 4]); if (r[0x100 / 4]) { signed int divisor = r[0x100 / 4]; - r[0x118 / 4] = r[0x110 / 4] = (signed int)d % divisor; - r[0x104 / 4] = r[0x11c / 4] = r[0x114 / 4] = (signed int)d / divisor; + r[0x118 / 4] = r[0x110 / 4] = (signed int)r[0x104 / 4] % divisor; + r[0x104 / 4] = r[0x11c / 4] = r[0x114 / 4] = (signed int)r[0x104 / 4] / divisor; } else r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ? break; case 0x114: elprintf_sh2(sh2, EL_32XP, "divide %08x%08x / %08x @%08x", - r[0x110 / 4], d, r[0x100 / 4], sh2_pc(sh2)); + r[0x110 / 4], r[0x114 / 4], r[0x100 / 4], sh2_pc(sh2)); if (r[0x100 / 4]) { - signed long long divident = (signed long long)r[0x110 / 4] << 32 | d; + signed long long divident = (signed long long)r[0x110 / 4] << 32 | r[0x114 / 4]; signed int divisor = r[0x100 / 4]; // XXX: undocumented mirroring to 0x118,0x11c? r[0x118 / 4] = r[0x110 / 4] = divident % divisor; diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 62c09103f..fa3f7e5ac 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -2542,7 +2542,7 @@ void retro_init(void) | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX | POPT_EN_32X|POPT_EN_PWM | POPT_ACC_SPRITES|POPT_DIS_32C_BORDER; -#ifdef __arm__ +#ifdef DRC_SH2 #ifdef _3DS if (ctr_svchack_successful) #endif diff --git a/platform/linux/emu.c b/platform/linux/emu.c index 5d65ad5ee..7417ca098 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -36,7 +36,7 @@ void pemu_prep_defconfig(void) void pemu_validate_config(void) { -#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) && !defined(__riscv__) && !defined(__riscv) && !defined(__powerpc__) && !defined(__ppc__) && !defined(__PPC__) && !defined(__i386__) && !defined(__x86_64__) +#if !defined(DRC_SH2) PicoIn.opt &= ~POPT_EN_DRC; #endif } From 7647f87b295ac7bbe1ffaa042e76622154a128f6 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 14 Jun 2024 23:05:37 +0200 Subject: [PATCH 44/44] md vdp, fix v_counter reading, some cleanup --- pico/videoport.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/pico/videoport.c b/pico/videoport.c index 4adf7a7ed..1410d1e9b 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -944,13 +944,8 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) } d &= 0xff; - if (num == 0 && !(pvid->reg[0]&2) && (d&2)) - pvid->hv_latch = PicoVideoRead(0x08); - if (num == 12 && ((pvid->reg[12]^d)&0x01)) - PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1); if (num == 1 && ((pvid->reg[1]^d)&0x40)) { - PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1); // handle line blanking before line rendering. Only the last switch // before the 1st sync for other reasons is honoured. PicoVideoSync(1); @@ -965,15 +960,21 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) switch (num) { case 0x00: + if ((~dold&d)&2) { + unsigned c = SekCyclesDone() - Pico.t.m68c_line_start; + pvid->hv_latch = VdpFIFO.fifo_hcounts[c/clkdiv] | (pvid->v_counter << 8); + } elprintf(EL_INTSW, "hint_onoff: %i->%i [%u] pend=%i @ %06x", (dold&0x10)>>4, (d&0x10)>>4, SekCyclesDone(), (pvid->pending_ints&0x10)>>4, SekPc); goto update_irq; case 0x01: - elprintf(EL_INTSW, "vint_onoff: %i->%i [%u] pend=%i @ %06x", (dold&0x20)>>5, - (d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc); + if ((d^dold)&0x40) + PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1); if (!(pvid->status & PVS_VB2)) pvid->status &= ~SR_VB; pvid->status |= ((d >> 3) ^ SR_VB) & SR_VB; // forced blanking + elprintf(EL_INTSW, "vint_onoff: %i->%i [%u] pend=%i @ %06x", (dold&0x20)>>5, + (d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc); goto update_irq; case 0x05: case 0x06: @@ -982,7 +983,10 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) case 0x0c: // renderers should update their palettes if sh/hi mode is changed if ((d^dold)&8) Pico.m.dirtyPal = 1; - if ((d^dold)&1) Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; + if ((d^dold)&1) { + PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1); + Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; + } break; default: return; @@ -1154,8 +1158,11 @@ unsigned char PicoVideoRead8CtlL(int is_from_z80) unsigned char PicoVideoRead8HV_H(int is_from_z80) { - elprintf(EL_HVCNT, "vcounter: %02x [%u] @ %06x", Pico.video.v_counter, SekCyclesDone(), SekPc); - return Pico.video.v_counter; + u32 d = Pico.video.v_counter; + if (Pico.video.reg[0]&2) + d = Pico.video.hv_latch >> 8; + elprintf(EL_HVCNT, "vcounter: %02x [%u] @ %06x", d, SekCyclesDone(), SekPc); + return d; } // FIXME: broken