From 492c47c4b8413a6c02efe761c8217c190cefffb8 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 24 Jan 2024 21:14:42 +0100 Subject: [PATCH 01/66] core, some updates for Pico adpcm --- pico/pico/xpcm.c | 73 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/pico/pico/xpcm.c b/pico/pico/xpcm.c index 91749bacd..7d69b43e0 100644 --- a/pico/pico/xpcm.c +++ b/pico/pico/xpcm.c @@ -7,6 +7,17 @@ * See COPYING file in the top-level directory. * * The following ADPCM algorithm was derived from MAME upd7759 driver. + * + * The Pico is using this chip in slave mode. In this mode there are no ROM + * headers, but the first byte sent to the chip is used to start the ADPCM + * engine. This byte is discarded, i.e. not processed by the engine. + * + * Data is fed into the chip through a FIFO. An Interrupt is created if the + * FIFO has been drained below the low water mark. + * + * The Pico has 2 extensions to the standard upd7759 chip: + * - gain control, used to control the volume of the ADPCM output + * - filtering, used to remove (some of) the ADPCM compression artifacts */ #include @@ -42,21 +53,24 @@ static const int step_deltas[16][16] = static const int state_deltas[16] = { -1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3 }; -s32 stepsamples = (44100LL<<16)/ADPCM_CLOCK; +static s32 stepsamples; // ratio as Q16, host sound rate / chip sample rate static struct xpcm_state { s32 samplepos; // leftover duration for current sample wrt sndrate, Q16 int sample; // current sample - short state; // ADPCM engine state + short state; // ADPCM decoder state short samplegain; // programmable gain char startpin; // value on the !START pin char irqenable; // IRQ enabled? - char portstate; // data stream state + char portstate; // ADPCM stream state short silence; // silence blocks still to be played short rate, nibbles; // ADPCM nibbles still to be played - unsigned char highlow, cache; // nibble selector and cache + unsigned char highlow, cache; // nibble selector and cache + + char filter; // filter selector + s32 x[3], y[3]; // filter history } xpcm; enum { RESET, START, HDR, COUNT }; // portstate @@ -66,15 +80,15 @@ enum { RESET, START, HDR, COUNT }; // portstate #define QB 16 // mantissa bits #define FP(f) (int)((f)*(1<= rate/2) { memset(iir, 0, sizeof(*iir)); return; @@ -95,12 +109,12 @@ static int PicoPicoFilterApply(struct iir2 *iir, int sample) return sample; // NB Butterworth specific! - iir->x[0] = iir->x[1]; iir->x[1] = iir->x[2]; - iir->x[2] = sample * iir->gain; // Qb - iir->y[0] = iir->y[1]; iir->y[1] = iir->y[2]; - iir->y[2] = (iir->x[0] + 2*iir->x[1] + iir->x[2] - + iir->y[0]*iir->a[1] + iir->y[1]*iir->a[0]) >> QB; - return iir->y[2]; + xpcm.x[0] = xpcm.x[1]; xpcm.x[1] = xpcm.x[2]; + xpcm.x[2] = sample * iir->gain; // Qb + xpcm.y[0] = xpcm.y[1]; xpcm.y[1] = xpcm.y[2]; + xpcm.y[2] = (xpcm.x[0] + 2*xpcm.x[1] + xpcm.x[2] + + xpcm.y[0]*iir->a[1] + xpcm.y[1]*iir->a[0]) >> QB; + return xpcm.y[2]; } @@ -131,13 +145,23 @@ PICO_INTERNAL int PicoPicoPCMBusyN(void) PICO_INTERNAL void PicoPicoPCMRerate(void) { + s32 nextstep = ((u64)PicoIn.sndRate<<16)/ADPCM_CLOCK; + + // if the sound rate changes, erase filter history to avoid freak behaviour + if (stepsamples != nextstep) { + memset(xpcm.x, 0, sizeof(xpcm.x)); + memset(xpcm.y, 0, sizeof(xpcm.y)); + } + // output samples per chip clock - stepsamples = ((u64)PicoIn.sndRate<<16)/ADPCM_CLOCK; + stepsamples = nextstep; // compute filter coefficients, cutoff at half the ADPCM sample rate PicoPicoFilterCoeff(&filters[1], 6000/2, PicoIn.sndRate); // 5-6 KHz PicoPicoFilterCoeff(&filters[2], 9000/2, PicoIn.sndRate); // 8-12 KHz PicoPicoFilterCoeff(&filters[3], 15000/2, PicoIn.sndRate); // 14-16 KHz + + PicoPicoPCMFilter(xpcm.filter); } PICO_INTERNAL void PicoPicoPCMGain(int gain) @@ -147,6 +171,13 @@ PICO_INTERNAL void PicoPicoPCMGain(int gain) PICO_INTERNAL void PicoPicoPCMFilter(int index) { + // if the filter changes, erase the history to avoid freak behaviour + if (index != xpcm.filter) { + memset(xpcm.x, 0, sizeof(xpcm.x)); + memset(xpcm.y, 0, sizeof(xpcm.y)); + } + + xpcm.filter = index; filter = filters+index; if (filter->a[0] == 0) filter = NULL; @@ -204,12 +235,13 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) // loop over FIFO data, generating ADPCM samples while (length > 0 && src < lim) { - if (xpcm.silence > 0) { + // ADPCM state engine + if (xpcm.silence > 0) { // generate silence xpcm.silence --; xpcm.sample = 0; xpcm.samplepos += stepsamples*256; - } else if (xpcm.nibbles > 0) { + } else if (xpcm.nibbles > 0) { // produce samples xpcm.nibbles --; if (xpcm.highlow) @@ -221,7 +253,7 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) do_sample((xpcm.cache & 0xf0) >> 4); xpcm.samplepos += stepsamples*xpcm.rate; - } else switch (xpcm.portstate) { + } else switch (xpcm.portstate) { // handle stream headers case RESET: xpcm.sample = 0; xpcm.samplepos += length<<16; @@ -301,15 +333,13 @@ PICO_INTERNAL int PicoPicoPCMSave(void *buffer, int length) { u8 *bp = buffer; - if (length < sizeof(xpcm) + sizeof(filters)) { + if (length < sizeof(xpcm)) { elprintf(EL_ANOMALY, "save buffer too small?"); return 0; } memcpy(bp, &xpcm, sizeof(xpcm)); bp += sizeof(xpcm); - memcpy(bp, filters, sizeof(filters)); - bp += sizeof(filters); return (bp - (u8*)buffer); } @@ -320,7 +350,4 @@ PICO_INTERNAL void PicoPicoPCMLoad(void *buffer, int length) if (length >= sizeof(xpcm)) memcpy(&xpcm, bp, sizeof(xpcm)); bp += sizeof(xpcm); - if (length >= sizeof(xpcm) + sizeof(filters)) - memcpy(filters, bp, sizeof(filters)); - bp += sizeof(filters); } From db1ee7a2df5570b900a57bb3438eabf9c80eddff Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 28 Jan 2024 19:23:25 +0000 Subject: [PATCH 02/66] core, handle background color DMA (arm asm) --- pico/draw.c | 66 +++++++++++++++++++++++++------------------------ pico/draw_arm.S | 10 ++++++-- pico/pico.h | 1 + 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/pico/draw.c b/pico/draw.c index 40903e74f..3584b6a20 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1607,46 +1607,46 @@ static int BgcDMAlen, BgcDMAoffs; static #endif // handle DMA to background color -int BgcDMA(u16 *pd, int len, struct PicoEState *est) +void BgcDMA(struct PicoEState *est) { + u16 *pd=est->DrawLineDest; + int len = (est->Pico->video.reg[12]&1) ? 320 : 256; + // TODO for now handles the line as all background. int xl = (len == 320 ? 38 : 33); // DMA slots during HSYNC int upscale = (est->rendstatus & PDRAW_SOFTSCALE) && len < 320; + u16 *q = upscale ? DefOutBuff : pd; + int i, l = len; + u16 t; - if (BgcDMAlen > 0) { - // BG color DMA under way. TODO for now handles the line as all background. - int i, l = len; - u16 *q = upscale ? DefOutBuff : pd; - u16 t; - - if ((est->rendstatus & PDRAW_BORDER_32) && !upscale) - q += (320-len) / 2; + if ((est->rendstatus & PDRAW_BORDER_32) && !upscale) + q += (320-len) / 2; - BgcDMAlen -= (l>>1)+xl; - if (BgcDMAlen < 0) - // partial line - l += 2*BgcDMAlen; + BgcDMAlen -= ((l-BgcDMAoffs)>>1)+xl; + if (BgcDMAlen <= 0) { + // partial line + l += 2*BgcDMAlen; + est->rendstatus &= ~PDRAW_BGC_DMA; + } - for (i = 0; i < l; i += 2) { - // TODO use ps to overwrite only real bg pixels - t = BgcDMAbase[BgcDMAsrc++ & BgcDMAmask]; - q[i] = q[i+1] = PXCONV(t); - } - BgcDMAsrc += xl; // HSYNC DMA + for (i = BgcDMAoffs; i < l; i += 2) { + // TODO use ps to overwrite only real bg pixels + t = BgcDMAbase[BgcDMAsrc++ & BgcDMAmask]; + q[i] = q[i+1] = PXCONV(t); + } + BgcDMAsrc += xl; // HSYNC DMA + BgcDMAoffs = 0; - t = est->HighPal[Pico.video.reg[7] & 0x3f]; - while (i < len) q[i++] = t; // fill partial line with BG + t = est->HighPal[Pico.video.reg[7] & 0x3f]; + while (i < len) q[i++] = t; // fill partial line with BG - if (upscale) { - switch (PicoIn.filter) { - case 3: h_upscale_bl4_4_5(pd, 320, q, 256, len, f_nop); break; - case 2: h_upscale_bl2_4_5(pd, 320, q, 256, len, f_nop); break; - case 1: h_upscale_snn_4_5(pd, 320, q, 256, len, f_nop); break; - default: h_upscale_nn_4_5(pd, 320, q, 256, len, f_nop); break; - } + if (upscale) { + switch (PicoIn.filter) { + case 3: h_upscale_bl4_4_5(pd, 320, q, 256, len, f_nop); break; + case 2: h_upscale_bl2_4_5(pd, 320, q, 256, len, f_nop); break; + case 1: h_upscale_snn_4_5(pd, 320, q, 256, len, f_nop); break; + default: h_upscale_nn_4_5(pd, 320, q, 256, len, f_nop); break; } - return 1; } - return 0; } // -------------------------------------------- @@ -1747,8 +1747,8 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) else if ((PicoIn.AHW & PAHW_SMS) && (est->Pico->video.reg[0] & 0x20)) len -= 8, ps += 8; - if (BgcDMA(pd, len, est)) - return; + if (est->rendstatus & PDRAW_BGC_DMA) + return BgcDMA(est); if ((est->rendstatus & PDRAW_SOFTSCALE) && len < 320) { if (len >= 240 && len <= 256) { @@ -2193,6 +2193,8 @@ void PicoDrawBgcDMA(u16 *base, u32 source, u32 mask, int dlen, int sl) BgcDMAlen -= (len>>1)+xl; BgcDMAoffs = 0; } + if (BgcDMAlen > 0) + est->rendstatus |= PDRAW_BGC_DMA; } // also works for fast renderer diff --git a/pico/draw_arm.S b/pico/draw_arm.S index e3ef3e281..05f8ba3de 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -20,6 +20,7 @@ .equ PDRAW_SHHI_DONE, (1<<7) .equ PDRAW_BORDER_32, (1<<9) .equ PDRAW_32X_SCALE, (1<<12) +.equ PDRAW_BGC_DMA, (1<<14) .equ PDRAW_SOFTSCALE, (1<<15) @ helpers @@ -1632,10 +1633,16 @@ PicoDoHighPal555_end: FinalizeLine555: stmfd sp!, {r4-r11,lr} mov r11,r2 @ est - ldr r8, [r11, #OFS_EST_Pico] + ldr r4, [r11, #OFS_EST_rendstatus] bl PicoDrawUpdateHighPal + tst r4, #PDRAW_BGC_DMA + movne r0, r11 + ldmnefd sp!, {r4-r11,lr} + bne BgcDMA + + ldr r8, [r11, #OFS_EST_Pico] add r3, r11, #OFS_EST_HighPal mov lr, #0xff @@ -1644,7 +1651,6 @@ FinalizeLine555: ldr r5, [r11, #OFS_EST_PicoOpt] ldr r1, [r11, #OFS_EST_HighCol] ldr r0, [r11, #OFS_EST_DrawLineDest] - ldr r4, [r11, #OFS_EST_rendstatus] ldr r7, [r5, #OFS_PicoIn_AHW-OFS_PicoIn_opt] ldrb r12,[r8, #OFS_Pico_video_reg+12] ldrb r6, [r8, #OFS_Pico_video_reg+0] diff --git a/pico/pico.h b/pico/pico.h index 2db502d5b..6759f73d6 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -235,6 +235,7 @@ void PicoDoHighPal555(int sh, int line, struct PicoEState *est); #define PDRAW_30_ROWS (1<<11) // 30 rows mode (240 lines) #define PDRAW_32X_SCALE (1<<12) // scale CLUT layer for 32X #define PDRAW_SMS_BLANK_1 (1<<13) // 1st column blanked +#define PDRAW_BGC_DMA (1<<14) // in background color DMA #define PDRAW_SOFTSCALE (1<<15) // H32 upscaling #define PDRAW_SYNC_NEEDED (1<<16) // redraw needed #define PDRAW_SYNC_NEXT (1<<17) // redraw next frame From f1dbe7642f4449633d1366d97d893b4bf7a2830d Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 28 Jan 2024 22:34:17 +0100 Subject: [PATCH 03/66] core, improve bg color DMA handling (and some vdp cleanup) --- pico/draw.c | 8 ++-- pico/draw_arm.S | 12 ++--- pico/videoport.c | 115 +++++++++++++++++++++++++---------------------- 3 files changed, 72 insertions(+), 63 deletions(-) diff --git a/pico/draw.c b/pico/draw.c index 3584b6a20..d47240cf7 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1636,7 +1636,7 @@ void BgcDMA(struct PicoEState *est) BgcDMAsrc += xl; // HSYNC DMA BgcDMAoffs = 0; - t = est->HighPal[Pico.video.reg[7] & 0x3f]; + t = PXCONV(PicoMem.cram[Pico.video.reg[7] & 0x3f]); while (i < len) q[i++] = t; // fill partial line with BG if (upscale) { @@ -1737,6 +1737,9 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) if (DrawLineDestIncrement == 0) return; + if (est->rendstatus & PDRAW_BGC_DMA) + return BgcDMA(est); + PicoDrawUpdateHighPal(); len = 256; @@ -1747,9 +1750,6 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) else if ((PicoIn.AHW & PAHW_SMS) && (est->Pico->video.reg[0] & 0x20)) len -= 8, ps += 8; - if (est->rendstatus & PDRAW_BGC_DMA) - return BgcDMA(est); - if ((est->rendstatus & PDRAW_SOFTSCALE) && len < 320) { if (len >= 240 && len <= 256) { pd += (256-len)>>1; diff --git a/pico/draw_arm.S b/pico/draw_arm.S index 05f8ba3de..2b1b2e4f8 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -1631,17 +1631,17 @@ PicoDoHighPal555_end: .global FinalizeLine555 FinalizeLine555: + ldr r3, [r11, #OFS_EST_rendstatus] + mov r0, r2 + tst r3, #PDRAW_BGC_DMA + bne BgcDMA + stmfd sp!, {r4-r11,lr} mov r11,r2 @ est - ldr r4, [r11, #OFS_EST_rendstatus] + mov r4, r3 bl PicoDrawUpdateHighPal - tst r4, #PDRAW_BGC_DMA - movne r0, r11 - ldmnefd sp!, {r4-r11,lr} - bne BgcDMA - ldr r8, [r11, #OFS_EST_Pico] add r3, r11, #OFS_EST_HighPal diff --git a/pico/videoport.c b/pico/videoport.c index dcfc58c8c..503e0eb32 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -439,8 +439,9 @@ void PicoVideoFIFOMode(int active, int h40) static __inline void AutoIncrement(void) { - Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]); - if (Pico.video.addr < Pico.video.reg[0xf]) Pico.video.addr_u ^= 1; + struct PicoVideo *pvid = &Pico.video; + pvid->addr=(unsigned short)(pvid->addr+pvid->reg[0xf]); + if (pvid->addr < pvid->reg[0xf]) pvid->addr_u ^= 1; } static NOINLINE void VideoWriteVRAM128(u32 a, u16 d) @@ -458,23 +459,24 @@ static NOINLINE void VideoWriteVRAM128(u32 a, u16 d) static void VideoWrite(u16 d) { - unsigned int a = Pico.video.addr; + struct PicoVideo *pvid = &Pico.video; + unsigned int a = pvid->addr; - switch (Pico.video.type) + switch (pvid->type) { case 1: if (a & 1) d = (u16)((d << 8) | (d >> 8)); - a |= Pico.video.addr_u << 16; + a |= pvid->addr_u << 16; VideoWriteVRAM(a, d); break; - case 3: if (PicoMem.cram [(a >> 1) & 0x3f] != d) Pico.m.dirtyPal = 1; + case 3: if (PicoMem.cram [(a >> 1) & 0x3f] != (d & 0xeee)) Pico.m.dirtyPal = 1; PicoMem.cram [(a >> 1) & 0x3f] = d & 0xeee; break; case 5: PicoMem.vsram[(a >> 1) & 0x3f] = d & 0x7ff; break; case 0x81: - a |= Pico.video.addr_u << 16; + a |= pvid->addr_u << 16; VideoWriteVRAM128(a, d); break; - //default:elprintf(EL_ANOMALY, "VDP write %04x with bad type %i", d, Pico.video.type); break; + //default:elprintf(EL_ANOMALY, "VDP write %04x with bad type %i", d, pvid->type); break; } AutoIncrement(); @@ -482,21 +484,22 @@ static void VideoWrite(u16 d) static unsigned int VideoRead(int is_from_z80) { + struct PicoVideo *pvid = &Pico.video; unsigned int a, d = VdpFIFO.fifo_data[(VdpFIFO.fifo_dx+1)&3]; - a=Pico.video.addr; a>>=1; + a=pvid->addr; a>>=1; if (!is_from_z80) SekCyclesBurnRun(PicoVideoFIFORead()); - switch (Pico.video.type) + switch (pvid->type) { case 0: d=PicoMem.vram [a & 0x7fff]; break; case 8: d=PicoMem.cram [a & 0x003f] | (d & ~0x0eee); break; case 4: if ((a & 0x3f) >= 0x28) a = 0; d=PicoMem.vsram [a & 0x003f] | (d & ~0x07ff); break; - case 12:a=PicoMem.vram [a & 0x7fff]; if (Pico.video.addr&1) a >>= 8; + case 12:a=PicoMem.vram [a & 0x7fff]; if (pvid->addr&1) a >>= 8; d=(a & 0x00ff) | (d & ~0x00ff); break; - default:elprintf(EL_ANOMALY, "VDP read with bad type %i", Pico.video.type); break; + default:elprintf(EL_ANOMALY, "VDP read with bad type %i", pvid->type); break; } AutoIncrement(); @@ -518,17 +521,18 @@ static int GetDmaLength(void) static void DmaSlow(int len, u32 source) { - u32 inc = Pico.video.reg[0xf]; - u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e; + struct PicoVideo *pvid=&Pico.video; + u32 inc = pvid->reg[0xf]; + u32 a = pvid->addr | (pvid->addr_u << 16), e; u16 *r, *base = NULL; u32 mask = 0x1ffff; int lc = SekCyclesDone()-Pico.t.m68c_line_start; elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%u] @ %06x", - Pico.video.type, source, a, len, inc, (Pico.video.status&SR_VB)||!(Pico.video.reg[1]&0x40), + pvid->type, source, a, len, inc, (pvid->status&SR_VB)||!(pvid->reg[1]&0x40), SekCyclesDone(), SekPc); - SekCyclesBurnRun(PicoVideoFIFOWrite(len, FQ_FGDMA | (Pico.video.type == 1), + SekCyclesBurnRun(PicoVideoFIFOWrite(len, FQ_FGDMA | (pvid->type == 1), PVS_DMABG, SR_DMA | PVS_CPUWR)); if ((source & 0xe00000) == 0xe00000) { // Ram @@ -569,7 +573,7 @@ static void DmaSlow(int len, u32 source) base = m68k_dma_source(source); } if (!base) { - elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: invalid src", Pico.video.type, source, a); + elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: invalid src", pvid->type, source, a); return; } @@ -577,7 +581,7 @@ static void DmaSlow(int len, u32 source) source >>= 1; mask >>= 1; - switch (Pico.video.type) + switch (pvid->type) { case 1: // vram e = a + len*2-1; @@ -604,7 +608,8 @@ static void DmaSlow(int len, u32 source) case 3: // cram Pico.m.dirtyPal = 1; r = PicoMem.cram; - if (inc == 0 && (Pico.video.reg[7] & 0x3f) == ((a/2) & 0x3f)) { // bg color DMA + if (inc == 0 && !(pvid->reg[1] & 0x40) && + (pvid->reg[7] & 0x3f) == ((a/2) & 0x3f)) { // bg color DMA PicoVideoSync(1); int sl = VdpFIFO.fifo_hcounts[lc/clkdiv]; if (sl > VdpFIFO.fifo_hcounts[0]-5) // hint delay is 5 slots @@ -612,6 +617,9 @@ static void DmaSlow(int len, u32 source) // TODO this is needed to cover timing inaccuracies if (sl <= 12) sl = -2; PicoDrawBgcDMA(base, source, mask, len, sl); + // do last DMA cycle since it's all going to the same cram location + source = source+len-1; + len = 1; } for (; len; len--) { @@ -642,20 +650,21 @@ static void DmaSlow(int len, u32 source) break; default: - if (Pico.video.type != 0 || (EL_LOGMASK & EL_VDPDMA)) - elprintf(EL_VDPDMA|EL_ANOMALY, "DMA with bad type %i", Pico.video.type); + if (pvid->type != 0 || (EL_LOGMASK & EL_VDPDMA)) + elprintf(EL_VDPDMA|EL_ANOMALY, "DMA with bad type %i", pvid->type); break; } // remember addr - Pico.video.addr = a; - Pico.video.addr_u = a >> 16; + pvid->addr = a; + pvid->addr_u = a >> 16; } static void DmaCopy(int len) { - u32 a = Pico.video.addr | (Pico.video.addr_u << 16); + struct PicoVideo *pvid=&Pico.video; + u32 a = pvid->addr | (pvid->addr_u << 16); u8 *vr = (u8 *)PicoMem.vram; - u8 inc = Pico.video.reg[0xf]; + u8 inc = pvid->reg[0xf]; int source; elprintf(EL_VDPDMA, "DmaCopy len %i [%u]", len, SekCyclesDone()); @@ -663,8 +672,8 @@ static void DmaCopy(int len) SekCyclesBurnRun(PicoVideoFIFOWrite(2*len, FQ_BGDMA, // 2 slots each (rd+wr) PVS_CPUWR, SR_DMA | PVS_DMABG)); - source =Pico.video.reg[0x15]; - source|=Pico.video.reg[0x16]<<8; + source =pvid->reg[0x15]; + source|=pvid->reg[0x16]<<8; for (; len; len--) { @@ -675,16 +684,17 @@ static void DmaCopy(int len) a = (a+inc) & ~0x20000; } // remember addr - Pico.video.addr = a; - Pico.video.addr_u = a >> 16; + pvid->addr = a; + pvid->addr_u = a >> 16; } static NOINLINE void DmaFill(int data) { - u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e; + struct PicoVideo *pvid=&Pico.video; + u32 a = pvid->addr | (pvid->addr_u << 16), e; u8 *vr = (u8 *)PicoMem.vram; u8 high = (u8)(data >> 8); - u8 inc = Pico.video.reg[0xf]; + u8 inc = pvid->reg[0xf]; int source; int len, l; @@ -694,7 +704,7 @@ static NOINLINE void DmaFill(int data) SekCyclesBurnRun(PicoVideoFIFOWrite(len, FQ_BGDMA, // 1 slot each (wr) PVS_CPUWR | PVS_DMAFILL, SR_DMA | PVS_DMABG)); - switch (Pico.video.type) + switch (pvid->type) { case 1: // vram e = a + len-1; @@ -751,16 +761,15 @@ static NOINLINE void DmaFill(int data) } // remember addr - Pico.video.addr = a; - Pico.video.addr_u = a >> 16; + pvid->addr = a; + pvid->addr_u = a >> 16; // register update - Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; - source = Pico.video.reg[0x15]; - source |= Pico.video.reg[0x16] << 8; + pvid->reg[0x13] = pvid->reg[0x14] = 0; + source = pvid->reg[0x15]; + source |= pvid->reg[0x16] << 8; source += len; - Pico.video.reg[0x15] = source; - Pico.video.reg[0x16] = source >> 8; - + pvid->reg[0x15] = source; + pvid->reg[0x16] = source >> 8; } // VDP command handling @@ -780,9 +789,9 @@ static NOINLINE void CommandDma(void) } len = GetDmaLength(); - source =Pico.video.reg[0x15]; - source|=Pico.video.reg[0x16] << 8; - source|=Pico.video.reg[0x17] << 16; + source = pvid->reg[0x15]; + source |= pvid->reg[0x16] << 8; + source |= pvid->reg[0x17] << 16; method=pvid->reg[0x17]>>6; if (method < 2) @@ -794,9 +803,9 @@ static NOINLINE void CommandDma(void) return; } source += len; - Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; - Pico.video.reg[0x15] = source; - Pico.video.reg[0x16] = source >> 8; + pvid->reg[0x13] = pvid->reg[0x14] = 0; + pvid->reg[0x15] = source; + pvid->reg[0x16] = source >> 8; } static NOINLINE void CommandChange(struct PicoVideo *pvid) @@ -893,7 +902,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) SekCyclesBurnRun(PicoVideoFIFOWrite(1, pvid->type == 1, 0, PVS_CPUWR)); elprintf(EL_ASVDP, "VDP data write: [%04x] %04x [%u] {%i} @ %06x", - Pico.video.addr, d, SekCyclesDone(), Pico.video.type, SekPc); + pvid->addr, d, SekCyclesDone(), pvid->type, SekPc); } VideoWrite(d); @@ -948,7 +957,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) lineenabled = (d&0x40) ? Pico.m.scanline : -1; linedisabled = (d&0x40) ? -1 : Pico.m.scanline; lineoffset = SekCyclesDone() - Pico.t.m68c_line_start; - } else if (((1<reg[num] != d) + } else if (((1<reg[num] != d) // VDP regs 0-7,11-13,16-18 influence rendering, ignore all others PicoVideoSync(InHblank(93)); // Toy Story pvid->reg[num] = d; @@ -1064,11 +1073,11 @@ static u32 VideoSr(const struct PicoVideo *pv) PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) { + struct PicoVideo *pv = &Pico.video; a &= 0x1c; if (a == 0x04) // control port { - struct PicoVideo *pv = &Pico.video; u32 d = VideoSr(pv); if (pv->pending) { CommandChange(pv); @@ -1084,11 +1093,11 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) u32 d; c = SekCyclesDone() - Pico.t.m68c_line_start; - if (Pico.video.reg[0]&2) - d = Pico.video.hv_latch; - else d = VdpFIFO.fifo_hcounts[c/clkdiv] | (Pico.video.v_counter << 8); + if (pv->reg[0]&2) + d = pv->hv_latch; + else d = VdpFIFO.fifo_hcounts[c/clkdiv] | (pv->v_counter << 8); - elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc); + elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, pv->v_counter, SekCyclesDone(), SekPc); return d; } From b5d8374c6ab959582491397b17a9c0a2c71e2343 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 14 Feb 2024 23:32:12 +0100 Subject: [PATCH 04/66] build, add -flto for all builds if available --- Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index bd8a5b5c5..d8f7cae04 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,8 @@ CFLAGS += $(call chkCCflag, -fno-caller-saves -fno-guess-branch-probability -fno # very old gcc toolchains may not have these options CFLAGS += $(call chkCCflag, -fno-tree-loop-if-convert -fipa-pta -fno-ipa-cp) endif +else +CFLAGS += $(call chkCCflag, -flto) endif # revision info from repository if this not a tagged release @@ -149,10 +151,6 @@ all: $(TARGET).opk endif endif -ifneq (,$(filter %mips32r2, $(CFLAGS))) -CFLAGS += -DMIPS_USE_SYNCI # mips32r2 clear_cache uses SYNCI instead of a syscall -endif - OBJS += platform/opendingux/inputmap.o use_inputmap ?= 1 @@ -416,6 +414,10 @@ ifneq (,$(findstring -flto,$(CFLAGS))) # to avoid saving and reloading it. However, this collides with the use of LTO. pico/32x/memory.o: CFLAGS += -fno-lto pico/32x/sh2soc.o: CFLAGS += -fno-lto +cpu/sh2/compiler.o: CFLAGS += -fno-lto +endif +ifneq (,$(filter mips64%, $(ARCH))$(filter %mips32r2, $(CFLAGS))) +CFLAGS += -DMIPS_USE_SYNCI # mips32r2 clear_cache uses SYNCI instead of a syscall endif endif From b38c0ea6f9d61f529eb6ca0b34c2587232300660 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 14 Feb 2024 23:36:43 +0100 Subject: [PATCH 05/66] core, fix some bugs reported by ASAN --- pico/draw.c | 11 +++++------ pico/videoport.c | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pico/draw.c b/pico/draw.c index d47240cf7..1b4ceb3cf 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -2095,17 +2095,16 @@ static void PicoLine(int line, int offs, int sh, int bgc, int off, int on) void PicoDrawSync(int to, int off, int on) { struct PicoEState *est = &Pico.est; - int line, offs = 0; + int line, offs; int sh = (est->Pico->video.reg[0xC] & 8) >> 3; // shadow/hilight? int bgc = est->Pico->video.reg[7] & 0x3f; pprof_start(draw); - if (rendlines != 240) { - offs = 8; - if (to > 223) - to = 223; - } + offs = (240-rendlines) >> 1; + if (to >= rendlines) + to = rendlines-1; + if (est->DrawScanline <= to && (est->rendstatus & (PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES))) ParseSprites(to + 1, on); diff --git a/pico/videoport.c b/pico/videoport.c index 503e0eb32..73c90edbe 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -397,7 +397,7 @@ int PicoVideoFIFOHint(void) // reset slot to start of scanline vf->fifo_slot = 0; // only need to refresh sprite position if we are synced - if (Pico.est.DrawScanline == Pico.m.scanline) + if (Pico.est.DrawScanline == Pico.m.scanline && !(pv->status & SR_VB)) PicoDrawRefreshSprites(); // if CPU is waiting for the bus, advance CPU and FIFO until bus is free From b4bc262418940ffed43bbb7923f72c419fc4c041 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 14 Feb 2024 23:37:40 +0100 Subject: [PATCH 06/66] platform, cleanup main emu loop --- platform/common/emu.c | 58 +++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index 309178c5a..92375ea50 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1395,17 +1395,17 @@ static void emu_loop_prep(void) } /* our tick here is 1 us right now */ -#define ms_to_ticks(x) (int)(x * 1000) -#define get_ticks() plat_get_ticks_us() -#define vsync_delay_x3 3*ms_to_ticks(1) +#define ms_to_ticks(x) (int)(x * 1000) +#define get_ticks() plat_get_ticks_us() +#define vsync_delay ms_to_ticks(1) void emu_loop(void) { int frames_done, frames_shown; /* actual frames for fps counter */ - int target_frametime_x3; - unsigned int timestamp_x3 = 0; - unsigned int timestamp_aim_x3 = 0; - unsigned int timestamp_fps_x3 = 0; + int target_frametime; + unsigned int timestamp = 0; + unsigned int timestamp_aim = 0; + unsigned int timestamp_fps = 0; char *notice_msg = NULL; char fpsbuff[24]; int fskip_cnt = 0; @@ -1420,9 +1420,9 @@ void emu_loop(void) /* number of ticks per frame */ if (Pico.m.pal) - target_frametime_x3 = 3 * ms_to_ticks(1000) / 50; + target_frametime = ms_to_ticks(1000) / 50; else - target_frametime_x3 = 3 * ms_to_ticks(1000) / 60; + target_frametime = ms_to_ticks(1000) / 60; reset_timing = 1; frames_done = frames_shown = 0; @@ -1438,22 +1438,22 @@ void emu_loop(void) if (reset_timing) { reset_timing = 0; plat_video_wait_vsync(); - timestamp_aim_x3 = get_ticks() * 3; - timestamp_fps_x3 = timestamp_aim_x3; + timestamp_aim = get_ticks(); + timestamp_fps = timestamp_aim; fskip_cnt = 0; } else if (currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) { - timestamp_aim_x3 = get_ticks() * 3; + timestamp_aim = get_ticks(); } - timestamp_x3 = get_ticks() * 3; + timestamp = get_ticks(); // show notice_msg message? if (notice_msg_time != 0) { static int noticeMsgSum; - if (timestamp_x3 - ms_to_ticks(notice_msg_time) * 3 - > ms_to_ticks(STATUS_MSG_TIMEOUT) * 3) + if (timestamp - ms_to_ticks(notice_msg_time) + > ms_to_ticks(STATUS_MSG_TIMEOUT)) { notice_msg_time = 0; notice_msg = NULL; @@ -1470,7 +1470,7 @@ void emu_loop(void) } // second changed? - if (timestamp_x3 - timestamp_fps_x3 >= ms_to_ticks(1000) * 3) + if (timestamp - timestamp_fps >= ms_to_ticks(1000)) { #ifdef BENCHMARK static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; @@ -1488,13 +1488,13 @@ void emu_loop(void) snprintf(fpsbuff, 8, "%02i/%02i ", frames_shown, frames_done); #endif frames_shown = frames_done = 0; - timestamp_fps_x3 += ms_to_ticks(1000) * 3; + timestamp_fps += ms_to_ticks(1000); } #ifdef PFRAMES sprintf(fpsbuff, "%i", Pico.m.frame_count); #endif - diff = timestamp_aim_x3 - timestamp_x3; + diff = timestamp_aim - timestamp; if (currentConfig.Frameskip >= 0) // frameskip enabled (or 0) { @@ -1506,7 +1506,7 @@ void emu_loop(void) fskip_cnt = 0; } } - else if (diff < -target_frametime_x3) + else if (diff < -target_frametime) { /* no time left for this frame - skip */ /* limit auto frameskip to max_skip */ @@ -1521,14 +1521,14 @@ void emu_loop(void) fskip_cnt = 0; // don't go in debt too much - while (diff < -target_frametime_x3 * 3) { - timestamp_aim_x3 += target_frametime_x3; - diff = timestamp_aim_x3 - timestamp_x3; + while (diff < -target_frametime * 3) { + timestamp_aim += target_frametime; + diff = timestamp_aim - timestamp; } emu_update_input(); if (skip) { - int do_audio = diff > -target_frametime_x3 * 2; + int do_audio = diff > -target_frametime * 2; PicoIn.skipFrame = do_audio ? 1 : 2; PicoFrame(); PicoIn.skipFrame = 0; @@ -1539,7 +1539,7 @@ void emu_loop(void) frames_shown++; } frames_done++; - timestamp_aim_x3 += target_frametime_x3; + timestamp_aim += target_frametime; if (!skip && !flip_after_sync) plat_video_flip(); @@ -1549,18 +1549,18 @@ void emu_loop(void) && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) { unsigned int timestamp = get_ticks(); - diff = timestamp_aim_x3 - timestamp * 3; + diff = timestamp_aim - timestamp; // sleep or vsync if we are still too fast - if (diff > target_frametime_x3 + vsync_delay_x3 && (currentConfig.EmuOpt & EOPT_VSYNC)) { + if (diff > target_frametime + vsync_delay && (currentConfig.EmuOpt & EOPT_VSYNC)) { // we are too fast plat_video_wait_vsync(); timestamp = get_ticks(); - diff = timestamp_aim_x3 - timestamp * 3; + diff = timestamp_aim - timestamp; } - if (diff > target_frametime_x3 + vsync_delay_x3) { + if (diff > target_frametime + vsync_delay) { // still too fast - plat_wait_till_us(timestamp + (diff - target_frametime_x3) / 3); + plat_wait_till_us(timestamp + (diff - target_frametime)); } } From af386f93c10d540d38f06ca93c0c7517e6d5b23c Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 14 Feb 2024 23:39:06 +0100 Subject: [PATCH 07/66] platform, fix BGR/RGB menu handling --- platform/common/menu_pico.c | 44 ++++++++++++++++--------------------- platform/libpicofe | 2 +- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 1492738ad..94eb283ef 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -14,6 +14,8 @@ #include "input_pico.h" #include "version.h" +#include "../libpicofe/plat.h" + #include #include @@ -23,16 +25,8 @@ #define MENU_X2 0 #endif -#if defined USE_BGR555 -#define COL_ROM 0x5eff -#define COL_OTH 0x5ff5 -#elif defined USE_BGR565 -#define COL_ROM 0xfdf7 -#define COL_OTH 0xaff5 -#else -#define COL_ROM 0xbdff -#define COL_OTH 0xaff5 -#endif +#define COL_ROM PXMAKE(0xbf, 0xbf, 0xff) +#define COL_OTH PXMAKE(0xaf, 0xff, 0xaf) // FIXME #ifndef REVISION @@ -65,7 +59,7 @@ static unsigned short fname2color(const char *fname) if (strcasecmp(ext, rom_exts[i]) == 0) return COL_ROM; for (i = 0; i < array_size(other_exts); i++) if (strcasecmp(ext, other_exts[i]) == 0) return COL_OTH; - return 0xffff; + return PXMAKE(0xff, 0xff, 0xff); } #include @@ -113,7 +107,7 @@ static void make_bg(int no_scale, int from_screen) for (y = 0; y < h; y++, src += pp, d += g_menuscreen_w*2/2) { for (x = 0; x < w; x++) { t = src[x]; - t = ((t & 0xf79e)>>1) - ((t & 0xc618)>>3); + t = (PXMASKH(t,1)>>1) - (PXMASKH(t,3)>>3); t |= t << 16; d[x] = d[x + g_menuscreen_w / 2] = t; } @@ -232,8 +226,8 @@ static void cdload_progress_cb(const char *fname, int percent) copy_bg(0); menuscreen_memset_lines(dst, 0xff, me_sfont_h - 2); - smalltext_out16(1, 3 * me_sfont_h, "Processing CD image / MP3s", 0xffff); - smalltext_out16(1, 4 * me_sfont_h, fname, 0xffff); + smalltext_out16(1, 3 * me_sfont_h, "Processing CD image / MP3s", PXMAKE(0xff, 0xff, 0xff)); + smalltext_out16(1, 4 * me_sfont_h, fname, PXMAKE(0xff, 0xff, 0xff)); dst += g_menuscreen_pp * me_sfont_h * 3; if (len > g_menuscreen_w) @@ -254,8 +248,8 @@ void menu_romload_prepare(const char *rom_name) p--; menu_draw_begin(1, 1); - smalltext_out16(1, 1, "Loading", 0xffff); - smalltext_out16(1, me_sfont_h, p, 0xffff); + smalltext_out16(1, 1, "Loading", PXMAKE(0xff, 0xff, 0xff)); + smalltext_out16(1, me_sfont_h, p, PXMAKE(0xff, 0xff, 0xff)); /* copy menu to bg for callbacks. OK since we are not in menu_loop here */ copy_bg(1); menu_draw_end(); @@ -273,7 +267,7 @@ void menu_romload_end(void) menu_draw_begin(0, 1); copy_bg(0); smalltext_out16(1, (cdload_called ? 6 : 3) * me_sfont_h, - "Starting emulation...", 0xffff); + "Starting emulation...", PXMAKE(0xff, 0xff, 0xff)); menu_draw_end(); } @@ -293,12 +287,12 @@ static void draw_patchlist(int sel) if (pos < 0) continue; if (pos >= max_cnt) break; active = PicoPatches[i].active; - smalltext_out16(14, pos * me_sfont_h, active ? "ON " : "OFF", active ? 0xfff6 : 0xffff); - smalltext_out16(14 + me_sfont_w*4, pos * me_sfont_h, PicoPatches[i].name, active ? 0xfff6 : 0xffff); + smalltext_out16(14, pos * me_sfont_h, active ? "ON " : "OFF", PXMAKE(0xff, 0xff, active ? 0xff : 0xb0)); + smalltext_out16(14 + me_sfont_w*4, pos * me_sfont_h, PicoPatches[i].name, PXMAKE(0xff, 0xff, active ? 0xff : 0xb0)); } pos = start + i; if (pos < max_cnt) - smalltext_out16(14, pos * me_sfont_h, "done", 0xffff); + smalltext_out16(14, pos * me_sfont_h, "done", PXMAKE(0xff, 0xff, 0xff)); text_out16(5, max_cnt / 2 * me_sfont_h, ">"); menu_draw_end(); @@ -1009,7 +1003,7 @@ static void draw_text_debug(const char *str, int skip, int from) str = p; for (line = from; line < g_menuscreen_h / me_sfont_h; line++) { - smalltext_out16(1, line * me_sfont_h, str, 0xffff); + smalltext_out16(1, line * me_sfont_h, str, PXMAKE(0xff, 0xff, 0xff)); while (*p && *p != '\n') p++; if (*p == 0) @@ -1038,8 +1032,8 @@ static void draw_frame_debug(void) pemu_forced_frame(1, 0); make_bg(1, 1); - smalltext_out16(4, 1, "build: r" REVISION " "__DATE__ " " __TIME__ " " COMPILER, 0xffff); - smalltext_out16(4, g_menuscreen_h - me_sfont_h, layer_str, 0xffff); + smalltext_out16(4, 1, "build: r" REVISION " "__DATE__ " " __TIME__ " " COMPILER, PXMAKE(0xff, 0xff, 0xff)); + smalltext_out16(4, g_menuscreen_h - me_sfont_h, layer_str, PXMAKE(0xff, 0xff, 0xff)); } static void debug_menu_loop(void) @@ -1063,7 +1057,7 @@ static void debug_menu_loop(void) draw_text_debug(tmp, 0, 0); if (dumped) { smalltext_out16(g_menuscreen_w - 6 * me_sfont_h, - g_menuscreen_h - me_mfont_h, "dumped", 0xffff); + g_menuscreen_h - me_mfont_h, "dumped", PXMAKE(0xff, 0xff, 0xff)); dumped = 0; } break; @@ -1137,7 +1131,7 @@ static void debug_menu_loop(void) static void draw_frame_credits(void) { - smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__, 0xe7fc); + smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__, PXMAKE(0xe0, 0xff, 0xe0)); } static const char credits[] = diff --git a/platform/libpicofe b/platform/libpicofe index 7cddc27ac..c825b167e 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 7cddc27accc089fdb58e99cdac0071cc904ecef1 +Subproject commit c825b167e9c08afaec23721f983ba003d86b838a From 33bde0c3c55309fcb9e2b8fb733621fac9010448 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 15 Feb 2024 00:01:09 +0100 Subject: [PATCH 08/66] psp, fix for pspdev update --- platform/psp/psp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/psp/psp.c b/platform/psp/psp.c index 081723afc..0a53cce7e 100644 --- a/platform/psp/psp.c +++ b/platform/psp/psp.c @@ -257,14 +257,14 @@ char *psp_get_status_line(void) { static char buff[64]; int ret, bat_percent, bat_time; - pspTime time; + ScePspDateTime time; ret = sceRtcGetCurrentClockLocalTime(&time); bat_percent = scePowerGetBatteryLifePercent(); bat_time = scePowerGetBatteryLifeTime(); if (ret < 0 || bat_percent < 0 || bat_time < 0) return NULL; - snprintf(buff, sizeof(buff), "%02i:%02i bat: %3i%%", time.hour, time.minutes, bat_percent); + snprintf(buff, sizeof(buff), "%02i:%02i bat: %3i%%", time.hour, time.minute, bat_percent); if (!scePowerIsPowerOnline()) snprintf(buff+strlen(buff), sizeof(buff)-strlen(buff), " (%i:%02i)", bat_time/60, bat_time%60); return buff; From 089f516d6c87c6feddcf25de3d5d0e2af31cdef2 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 17 Feb 2024 21:32:45 +0100 Subject: [PATCH 09/66] make sound rates platform dependent --- platform/common/menu_pico.c | 6 ++++-- platform/common/plat_sdl.c | 3 ++- platform/gp2x/emu.c | 2 +- platform/libpicofe | 2 +- platform/psp/emu.c | 1 + platform/psp/plat.c | 2 ++ 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 94eb283ef..e48fa4020 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -637,10 +637,12 @@ static int menu_loop_adv_options(int id, int keys) static int sndrate_prevnext(int rate, int dir) { - static const int rates[] = { 8000, 11025, 16000, 22050, 44100, 53000 }; - int rate_count = sizeof(rates)/sizeof(rates[0]); + const int *rates = plat_target.sound_rates; + int rate_count; int i; + for (rate_count = 0; rates[rate_count] != -1; rate_count++) + ; for (i = 0; i < rate_count; i++) if (rates[i] == rate) break; diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index c47ef1b7f..785fb1bf7 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -30,7 +30,8 @@ static struct in_pdata in_sdl_platform_data = { .defbinds = in_sdl_defbinds, }; -struct plat_target plat_target; +static int sound_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 53000, -1 }; +struct plat_target plat_target = { .sound_rates = sound_rates }; #if defined __MIYOO__ const char *plat_device = "miyoo"; diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index d59f3ecae..460b1541e 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -778,7 +778,7 @@ void pemu_sound_start(void) } } -static const int sound_rates[] = { 53000, 44100, 32000, 22050, 16000, 11025, 8000 }; +static const int sound_rates[] = { 52000, 44100, 32000, 22050, 16000, 11025, 8000 }; void pemu_sound_stop(void) { diff --git a/platform/libpicofe b/platform/libpicofe index c825b167e..82b485477 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit c825b167e9c08afaec23721f983ba003d86b838a +Subproject commit 82b4854771302e23201de274eee2969fc28be8be diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 54773387d..8b5a49810 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2007,2008 + * (C) irixxxx, 2022-2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. diff --git a/platform/psp/plat.c b/platform/psp/plat.c index 271d35dd1..b23bc386b 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -273,6 +273,7 @@ static int plat_bat_capacity_get(void) return scePowerGetBatteryLifePercent(); } +static int sound_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, -1 }; struct plat_target plat_target = { .cpu_clock_get = plat_cpu_clock_get, .cpu_clock_set = plat_cpu_clock_set, @@ -280,6 +281,7 @@ struct plat_target plat_target = { // .gamma_set = plat_gamma_set, // .hwfilter_set = plat_hwfilter_set, // .hwfilters = plat_hwfilters, + .sound_rates = sound_rates, }; int _flush_cache (char *addr, const int size, const int op) From cb774958736c62c637eab56c6aab1887d29a10fa Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sat, 30 Dec 2023 21:56:14 +0100 Subject: [PATCH 10/66] First PS2 compilation --- .github/workflows/ci.yml | 24 +++++++++ Makefile | 6 +++ configure | 13 ++++- platform/ps2/Makefile | 27 ++++++++++ platform/ps2/plat.c | 108 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 platform/ps2/Makefile create mode 100644 platform/ps2/plat.c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af1f43920..fe8d360ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,6 +94,30 @@ jobs: name: PSP path: PicoDrive_psp_*.zip + build-ps2: + runs-on: ubuntu-latest + container: ps2dev/ps2dev + steps: + - name: build environment + run: | + apk add build-base cmake git zip make + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + export CROSS_COMPILE=mips64r5900el-ps2-elf- + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + ./configure --platform=ps2 + make -j2 + make -C platform/ps2 rel VER=$ver + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: PS2 + path: PicoDrive_ps2_*.zip + build-dingux: runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index d8f7cae04..4174c2941 100644 --- a/Makefile +++ b/Makefile @@ -235,6 +235,12 @@ OBJS += platform/psp/asm_utils.o OBJS += platform/psp/mp3.o USE_FRONTEND = 1 endif +ifeq "$(PLATFORM)" "ps2" +CFLAGS += -DUSE_BGR555 # -DLOG_TO_FILE +LDLIBS += -lpatches -lgskit -ldmakit -lps2_drivers +OBJS += platform/ps2/plat.o +USE_FRONTEND = 1 +endif ifeq "$(PLATFORM)" "libretro" OBJS += platform/libretro/libretro.o ifneq ($(STATIC_LINKING), 1) diff --git a/configure b/configure index fd2d9a7e3..dc887617f 100755 --- a/configure +++ b/configure @@ -39,7 +39,7 @@ check_define() # "" means "autodetect". # TODO this is annoyingly messy. should have platform and device -platform_list="generic pandora gph dingux retrofw opendingux[-gcw0] odbeta[-gcw0] miyoo rpi1 rpi2 psp" +platform_list="generic pandora gph dingux retrofw opendingux[-gcw0] odbeta[-gcw0] miyoo rpi1 rpi2 ps2 psp" platform="generic" sound_driver_list="oss alsa sdl" sound_drivers="" @@ -59,6 +59,7 @@ CC="${CC-${CROSS_COMPILE}gcc}" CXX="${CXX-${CROSS_COMPILE}g++}" AS="${AS-${CROSS_COMPILE}as}" STRIP="${STRIP-${CROSS_COMPILE}strip}" +LD="${LD-${CROSS_COMPILE}gcc}" # Use better gcc for linking SYSROOT=`$CC $CFLAGS $LDFLAGS --print-sysroot 2> /dev/null || true` config_mak="config.mak" @@ -150,6 +151,15 @@ set_platform() MFLAGS="-march=allegrex" ARCH=mipsel ;; + ps2) + # use newlib + SYSLIBS="" + MFLAGS="" + ARCH=mips64r5900el + ASFLAGS="$ASFLAGS -G0 -call_shared" + CFLAGS="$CFLAGS -D_EE -G0 -I${PS2SDK}/ee/include -I${PS2SDK}/common/include -I${PS2SDK}/ports/include" + LDFLAGS="$LDFLAGS -Wl,-zmax-page-size=128 -T${PS2SDK}/ee/startup/linkfile -L${PS2SDK}/ee/lib -L${PS2SDK}/ports/lib" + ;; *) fail "unsupported platform: $platform" ;; @@ -457,6 +467,7 @@ echo "CC = $CC" >> $config_mak echo "CXX = $CXX" >> $config_mak echo "AS = $AS" >> $config_mak echo "STRIP = $STRIP" >> $config_mak +echo "LD = $LD" >> $config_mak echo "CFLAGS += $MFLAGS $CFLAGS" >> $config_mak echo "ASFLAGS += $MFLAGS $ASFLAGS" >> $config_mak echo "LDFLAGS += $LDFLAGS" >> $config_mak diff --git a/platform/ps2/Makefile b/platform/ps2/Makefile new file mode 100644 index 000000000..42ba39d6f --- /dev/null +++ b/platform/ps2/Makefile @@ -0,0 +1,27 @@ + +# ----------- release ----------- +ifneq ($(findstring rel,$(MAKECMDGOALS)),) +ifeq ($(VER),) +$(error need VER) +endif +endif + +../../tools/textfilter: ../../tools/textfilter.c + make -C ../../tools/ textfilter + +readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog + ../../tools/textfilter ../base_readme.txt $@ PS2 + +# ? +rel: ../../PicoDrive readme.txt ../game_def.cfg + mkdir -p PicoDrive/skin/ + cp $^ PicoDrive/ + cp ../../skin/* PicoDrive/skin/ + zip -9 -r ../../PicoDrive_ps2_$(VER).zip PicoDrive + rm -rf PicoDrive + mkdir bin_to_cso_mp3 + cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/ + zip -9 -r ../../PicoDrive_ps2_$(VER).zip bin_to_cso_mp3 + rm -rf bin_to_cso_mp3 + + diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c new file mode 100644 index 000000000..026817348 --- /dev/null +++ b/platform/ps2/plat.c @@ -0,0 +1,108 @@ +#include +#include + +#include "../libpicofe/plat.h" + +const char *renderer_names[] = { "Software", "Hardware" }; +const char *renderer_names32x[] = { "Software", "Hardware", "Hardware (fast)" }; + +struct plat_target plat_target = {}; + +int plat_parse_arg(int argc, char *argv[], int *x) { return 1; } + +void plat_early_init(void) {} + +int plat_target_init(void) { return 0; } + +void plat_init(void) {} + +void plat_video_menu_enter(int is_rom_loaded) {} + +void plat_video_menu_leave(void) {} + +void plat_finish(void) {} + +void plat_target_finish(void) {} + +void plat_video_menu_begin(void) {} + +void plat_video_menu_end(void) {} + +int plat_get_root_dir(char *dst, int len) { return 0; } + + +unsigned int plat_get_ticks_ms(void) { return 0; } + +unsigned int plat_get_ticks_us(void) { return 0; } + +void plat_sleep_ms(int ms) {} + +void plat_video_toggle_renderer(int change, int menu_call) {} + +void plat_update_volume(int has_changed, int is_up) {} + +int plat_is_dir(const char *path) { return 0; } + +void plat_status_msg_busy_first(const char *msg) {} + +void pemu_prep_defconfig(void) {} + +void pemu_validate_config(void) {} + +void plat_status_msg_clear(void) {} + +void plat_status_msg_busy_next(const char *msg) {} + +void plat_video_loop_prepare(void) {} + +int plat_get_data_dir(char *dst, int len) { return 0; } + +void plat_video_flip(void) {} + +void plat_video_wait_vsync(void) {} + +void plat_wait_till_us(unsigned int us) {} + +int plat_get_skin_dir(char *dst, int len) { return 0; } + +void plat_debug_cat(char *str) {} + +int plat_wait_event(int *fds_hnds, int count, int timeout_ms) { return 0; } + +void pemu_loop_prep(void) {} + +void pemu_sound_start(void) {} + +void pemu_loop_end(void) {} + +void *plat_mem_get_for_drc(size_t size) { return NULL; } + +void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) { return NULL; } + +void *plat_mremap(void *ptr, size_t oldsize, size_t newsize) { return NULL; } + +void plat_munmap(void *ptr, size_t size) {} + +int plat_mem_set_exec(void *ptr, size_t size) { return 0; } + +void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) {} + +void pemu_forced_frame(int no_scale, int do_emu) {} + +void pemu_finalize_frame(const char *fps, const char *notice_msg) {} + +int _flush_cache (char *addr, const int size, const int op) { return 0; } + +/* lprintf */ +void lprintf(const char *fmt, ...) +{ + va_list vl; + + va_start(vl, fmt); +#if defined(LOG_TO_FILE) + vfprintf(logFile, fmt, vl); +#else + vprintf(fmt, vl); +#endif + va_end(vl); +} \ No newline at end of file From 936f164b559ccec173d7beed43049bd20f8bcd0f Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sun, 31 Dec 2023 00:38:09 +0100 Subject: [PATCH 11/66] Starting to boot --- platform/ps2/plat.c | 268 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 223 insertions(+), 45 deletions(-) diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index 026817348..c3585dff2 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -1,5 +1,21 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include #include "../libpicofe/plat.h" @@ -8,90 +24,222 @@ const char *renderer_names32x[] = { "Software", "Hardware", "Hardware (fast)" }; struct plat_target plat_target = {}; -int plat_parse_arg(int argc, char *argv[], int *x) { return 1; } - -void plat_early_init(void) {} - -int plat_target_init(void) { return 0; } +static void reset_IOP() { + SifInitRpc(0); +#if !defined(DEBUG) || defined(BUILD_FOR_PCSX2) + /* Comment this line if you don't wanna debug the output */ + while (!SifIopReset(NULL, 0)) {}; +#endif -void plat_init(void) {} + while (!SifIopSync()) {}; + SifInitRpc(0); + sbv_patch_enable_lmb(); + sbv_patch_disable_prefix_check(); +} -void plat_video_menu_enter(int is_rom_loaded) {} +static void init_drivers() { + init_ps2_filesystem_driver(); +} -void plat_video_menu_leave(void) {} +static void deinit_drivers() { + deinit_ps2_filesystem_driver(); +} -void plat_finish(void) {} +void plat_init(void) +{ + init_joystick_driver(false); + init_audio_driver(); +} -void plat_target_finish(void) {} -void plat_video_menu_begin(void) {} +void plat_finish(void) { + deinit_audio_driver(); + deinit_joystick_driver(false); +} -void plat_video_menu_end(void) {} +int plat_target_init(void) +{ + return 0; +} -int plat_get_root_dir(char *dst, int len) { return 0; } +/* System level deinitialization */ +void plat_target_finish(void) +{ + deinit_drivers(); +} +/* display a completed frame buffer and prepare a new render buffer */ +void plat_video_flip(void) +{ -unsigned int plat_get_ticks_ms(void) { return 0; } +} -unsigned int plat_get_ticks_us(void) { return 0; } +/* wait for start of vertical blanking */ +void plat_video_wait_vsync(void) +{ +} -void plat_sleep_ms(int ms) {} +/* switch from emulation display to menu display */ +void plat_video_menu_enter(int is_rom_loaded) +{ -void plat_video_toggle_renderer(int change, int menu_call) {} +} -void plat_update_volume(int has_changed, int is_up) {} +/* start rendering a menu screen */ +void plat_video_menu_begin(void) +{ -int plat_is_dir(const char *path) { return 0; } +} -void plat_status_msg_busy_first(const char *msg) {} +/* display a completed menu screen */ +void plat_video_menu_end(void) +{ -void pemu_prep_defconfig(void) {} +} -void pemu_validate_config(void) {} +/* terminate menu display */ +void plat_video_menu_leave(void) +{ -void plat_status_msg_clear(void) {} +} -void plat_status_msg_busy_next(const char *msg) {} +int plat_parse_arg(int argc, char *argv[], int *x) +{ + return 1; +} -void plat_video_loop_prepare(void) {} +/* Preliminary initialization needed at program start */ +void plat_early_init(void) { + reset_IOP(); + init_drivers(); +#if defined(LOG_TO_FILE) + log_init(); +#endif +} -int plat_get_data_dir(char *dst, int len) { return 0; } +/* base directory for configuration and save files */ +int plat_get_root_dir(char *dst, int len) +{ + getcwd(dst, len); + // We need to append / at the end + strcat(dst, "/"); + return strlen(dst); +} + +/* base directory for emulator resources */ +int plat_get_skin_dir(char *dst, int len) +{ + if (len > 5) + strcpy(dst, "skin/"); + else if (len > 0) + *dst = 0; + return strlen(dst); +} + +/* top directory for rom images */ +int plat_get_data_dir(char *dst, int len) +{ + getcwd(dst, len); + return strlen(dst); +} -void plat_video_flip(void) {} +/* check if path is a directory */ +int plat_is_dir(const char *path) +{ + DIR *dir; + if ((dir = opendir(path))) { + closedir(dir); + return 1; + } + return 0; +} + +/* current time in ms */ +unsigned int plat_get_ticks_ms(void) +{ + struct timeval tv; + unsigned int ret; -void plat_video_wait_vsync(void) {} + gettimeofday(&tv, NULL); -void plat_wait_till_us(unsigned int us) {} + ret = (unsigned)tv.tv_sec * 1000; + /* approximate /= 1000 */ + ret += ((unsigned)tv.tv_usec * 4195) >> 22; -int plat_get_skin_dir(char *dst, int len) { return 0; } + return ret; +} -void plat_debug_cat(char *str) {} +/* current time in us */ +unsigned int plat_get_ticks_us(void) +{ + struct timeval tv; + unsigned int ret; -int plat_wait_event(int *fds_hnds, int count, int timeout_ms) { return 0; } + gettimeofday(&tv, NULL); -void pemu_loop_prep(void) {} + ret = (unsigned)tv.tv_sec * 1000000; + ret += (unsigned)tv.tv_usec; -void pemu_sound_start(void) {} + return ret; +} -void pemu_loop_end(void) {} +/* sleep for some time in ms */ +void plat_sleep_ms(int ms) +{ + usleep(ms * 1000); +} -void *plat_mem_get_for_drc(size_t size) { return NULL; } +/* sleep for some time in us */ +void plat_wait_till_us(unsigned int us_to) +{ + usleep(us_to - plat_get_ticks_us()); +} -void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) { return NULL; } +/* wait until some event occurs, or timeout */ +int plat_wait_event(int *fds_hnds, int count, int timeout_ms) +{ + return 0; // unused +} -void *plat_mremap(void *ptr, size_t oldsize, size_t newsize) { return NULL; } +/* memory mapping functions */ +void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) +{ + return malloc(size); +} -void plat_munmap(void *ptr, size_t size) {} +void *plat_mremap(void *ptr, size_t oldsize, size_t newsize) +{ + return realloc(ptr, newsize); +} -int plat_mem_set_exec(void *ptr, size_t size) { return 0; } +void plat_munmap(void *ptr, size_t size) +{ + free(ptr); +} -void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) {} +void *plat_mem_get_for_drc(size_t size) +{ + return NULL; +} -void pemu_forced_frame(int no_scale, int do_emu) {} +int plat_mem_set_exec(void *ptr, size_t size) +{ + return 0; +} -void pemu_finalize_frame(const char *fps, const char *notice_msg) {} +int _flush_cache (char *addr, const int size, const int op) +{ + FlushCache(WRITEBACK_DCACHE); /* WRITEBACK_DCACHE */ + FlushCache(INVALIDATE_ICACHE); /* INVALIDATE_ICACHE */ + return 0; +} -int _flush_cache (char *addr, const int size, const int op) { return 0; } +int posix_memalign(void **p, size_t align, size_t size) +{ + if (p) + *p = memalign(align, size); + return (p ? *p ? 0 : ENOMEM : EINVAL); +} /* lprintf */ void lprintf(const char *fmt, ...) @@ -105,4 +253,34 @@ void lprintf(const char *fmt, ...) vprintf(fmt, vl); #endif va_end(vl); -} \ No newline at end of file +} + +void plat_video_toggle_renderer(int change, int menu_call) {} + +void plat_update_volume(int has_changed, int is_up) {} + +void plat_status_msg_busy_first(const char *msg) {} + +void pemu_prep_defconfig(void) {} + +void pemu_validate_config(void) {} + +void plat_status_msg_clear(void) {} + +void plat_status_msg_busy_next(const char *msg) {} + +void plat_video_loop_prepare(void) {} + +void plat_debug_cat(char *str) {} + +void pemu_loop_prep(void) {} + +void pemu_sound_start(void) {} + +void pemu_loop_end(void) {} + +void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) {} + +void pemu_forced_frame(int no_scale, int do_emu) {} + +void pemu_finalize_frame(const char *fps, const char *notice_msg) {} \ No newline at end of file From 9b4c95a951f87a2169952d1017253e273ca71ffb Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sun, 31 Dec 2023 00:51:49 +0100 Subject: [PATCH 12/66] Fix folder creation --- platform/common/emu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index 92375ea50..5e51d9340 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1243,7 +1243,7 @@ static void mkdir_path(char *path_with_reserve, int pos, const char *name) strcpy(path_with_reserve + pos, name); if (plat_is_dir(path_with_reserve)) return; - if (mkdir(path_with_reserve, 0777) < 0) + if (mkdir(path_with_reserve, 0755) < 0) lprintf("failed to create: %s\n", path_with_reserve); } From 8b65c92f1f7084212fbebed4a9465c79f1dcc582 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sun, 31 Dec 2023 00:52:01 +0100 Subject: [PATCH 13/66] Use MenuX2 in PS2 --- 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 e48fa4020..a9fc79001 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -19,7 +19,7 @@ #include #include -#ifdef PANDORA +#if defined(PANDORA) || defined(__PS2__) #define MENU_X2 1 #else #define MENU_X2 0 From e22b24b81ae63f29596eeae2fb2112e75e424f5b Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sun, 31 Dec 2023 17:00:46 +0100 Subject: [PATCH 14/66] First dummy input implementation --- Makefile | 2 + platform/ps2/emu.c | 41 +++++++ platform/ps2/in_ps2.c | 268 ++++++++++++++++++++++++++++++++++++++++++ platform/ps2/in_ps2.h | 6 + platform/ps2/plat.c | 12 -- 5 files changed, 317 insertions(+), 12 deletions(-) create mode 100644 platform/ps2/emu.c create mode 100644 platform/ps2/in_ps2.c create mode 100644 platform/ps2/in_ps2.h diff --git a/Makefile b/Makefile index 4174c2941..cbed7900b 100644 --- a/Makefile +++ b/Makefile @@ -239,6 +239,8 @@ ifeq "$(PLATFORM)" "ps2" CFLAGS += -DUSE_BGR555 # -DLOG_TO_FILE LDLIBS += -lpatches -lgskit -ldmakit -lps2_drivers OBJS += platform/ps2/plat.o +OBJS += platform/ps2/emu.o +OBJS += platform/ps2/in_ps2.o USE_FRONTEND = 1 endif ifeq "$(PLATFORM)" "libretro" diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c new file mode 100644 index 000000000..4ff7f16ad --- /dev/null +++ b/platform/ps2/emu.c @@ -0,0 +1,41 @@ +#include + +#include +#include +#include + +#include "in_ps2.h" +#include "../libpicofe/input.h" +#include "../common/input_pico.h" +#include "../common/emu.h" + +static struct in_default_bind in_ps2_defbinds[] = +{ + { PAD_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, + { PAD_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN }, + { PAD_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT }, + { PAD_RIGHT, IN_BINDTYPE_PLAYER12, GBTN_RIGHT }, + { PAD_SQUARE, IN_BINDTYPE_PLAYER12, GBTN_A }, + { PAD_CROSS, IN_BINDTYPE_PLAYER12, GBTN_B }, + { PAD_CIRCLE, IN_BINDTYPE_PLAYER12, GBTN_C }, + { PAD_START, IN_BINDTYPE_PLAYER12, GBTN_START }, + { PAD_TRIANGLE, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, + { PAD_L1, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, + { PAD_R1, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, + { PAD_SELECT, IN_BINDTYPE_EMU, PEVB_MENU }, + { 0, 0, 0 } +}; + +void plat_init(void) +{ + init_joystick_driver(false); + in_ps2_init(in_ps2_defbinds); + in_probe(); + init_audio_driver(); + // plat_get_data_dir(rom_fname_loaded, sizeof(rom_fname_loaded)); +} + +void plat_finish(void) { + deinit_audio_driver(); + deinit_joystick_driver(false); +} \ No newline at end of file diff --git a/platform/ps2/in_ps2.c b/platform/ps2/in_ps2.c new file mode 100644 index 000000000..d58d514cb --- /dev/null +++ b/platform/ps2/in_ps2.c @@ -0,0 +1,268 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "libpad.h" +#include "libmtap.h" + +#include "../libpicofe/input.h" +#include "in_ps2.h" + +#define IN_PS2_PREFIX "ps2:" +#define IN_PS2_NBUTTONS 32 +#define ANALOG_DEADZONE 80 + +/* note: in_ps2 handles combos (if 2 btns have the same bind, + * both must be pressed for action to happen) */ +static int in_ps2_combo_keys = 0; +static int in_ps2_combo_acts = 0; + +static uintptr_t padBuf[2][4]; +static uint32_t padConnected[2][4]; // 2 ports, 4 slots +static uint32_t padOpen[2][4]; +static uint32_t maxslot[2]; + + +static const char *in_ps2_keys[IN_PS2_NBUTTONS] = { + [0 ... IN_PS2_NBUTTONS-1] = NULL, +}; + + +/* calculate bit number from bit mask (logarithm to the basis 2) */ +static int lg2(unsigned v) +{ + /* credits to https://graphics.stanford.edu/~seander/bithacks.html */ + int r, s; + + r = (v > 0xFFFF) << 4; v >>= r; + s = (v > 0xFF ) << 3; v >>= s; r |= s; + s = (v > 0xF ) << 2; v >>= s; r |= s; + s = (v > 0x3 ) << 1; v >>= s; r |= s; + r |= (v >> 1); + return r; +} + +static unsigned int ps2_pad_read() +{ + unsigned int paddata; + struct padButtonStatus buttons; + int32_t ret, port, slot; + + + // Using for now port 0, slot 0 + port = 0; + slot = 0; + + ret = padRead(port, slot, &buttons); + + if (ret != 0) { + paddata = 0xffff ^ buttons.btns; + } + + // analog.. + // buttons &= ~(PS2_NUB_UP|PS2_NUB_DOWN|PS2_NUB_LEFT|PS2_NUB_RIGHT); + // if (pad.Lx < 128 - ANALOG_DEADZONE) buttons |= PS2_NUB_LEFT; + // if (pad.Lx > 128 + ANALOG_DEADZONE) buttons |= PS2_NUB_RIGHT; + // if (pad.Ly < 128 - ANALOG_DEADZONE) buttons |= PS2_NUB_UP; + // if (pad.Ly > 128 + ANALOG_DEADZONE) buttons |= PS2_NUB_DOWN; + + return paddata; +} + +static unsigned in_ps2_get_bits(void) +{ + unsigned mask = + PAD_UP|PAD_DOWN|PAD_LEFT|PAD_RIGHT | + PAD_CIRCLE|PAD_CROSS|PAD_TRIANGLE|PAD_SQUARE | + PAD_L1|PAD_R1|PAD_SELECT|PAD_START; + // PS2_NUB_UP|PS2_NUB_DOWN|PS2_NUB_LEFT|PS2_NUB_RIGHT | + + return ps2_pad_read() & mask; +} + +static void in_ps2_probe(const in_drv_t *drv) +{ + in_register(IN_PS2_PREFIX "PS2 pad", -1, NULL, + IN_PS2_NBUTTONS, in_ps2_keys, 1); +} + +static void in_ps2_free(void *drv_data) +{ + +} + +static const char * const * +in_ps2_get_key_names(const in_drv_t *drv, int *count) +{ + *count = IN_PS2_NBUTTONS; + return in_ps2_keys; +} + +/* ORs result with pressed buttons */ +static int in_ps2_update(void *drv_data, const int *binds, int *result) +{ + int type_start = 0; + int i, t; + unsigned keys; + + keys = in_ps2_get_bits(); + + if (keys & in_ps2_combo_keys) { + result[IN_BINDTYPE_EMU] = in_combos_do(keys, binds, IN_PS2_NBUTTONS, + in_ps2_combo_keys, in_ps2_combo_acts); + type_start = IN_BINDTYPE_PLAYER12; + } + + for (i = 0; keys; i++, keys >>= 1) { + if (!(keys & 1)) + continue; + + for (t = type_start; t < IN_BINDTYPE_COUNT; t++) + result[t] |= binds[IN_BIND_OFFS(i, t)]; + } + + return 0; +} + +int in_ps2_update_keycode(void *data, int *is_down) +{ + static unsigned old_val = 0; + unsigned val, diff, i; + + val = in_ps2_get_bits(); + diff = val ^ old_val; + if (diff == 0) + return -1; + + /* take one bit only */ + for (i = 0; i < sizeof(diff)*8; i++) + if (diff & (1< kc */ + keycode = -keycode; + for (i = 0; i < KEY_PBTN_MAP_SIZE; i++) + if (key_pbtn_map[i].pbtn == keycode) + return key_pbtn_map[i].key; + } + else + { + for (i = 0; i < KEY_PBTN_MAP_SIZE; i++) + if (key_pbtn_map[i].key == keycode) + return key_pbtn_map[i].pbtn; + } + + return 0; +} + +/* remove binds of missing keys, count remaining ones */ +static int in_ps2_clean_binds(void *drv_data, int *binds, int *def_binds) +{ + int i, count = 0; + + for (i = 0; i < IN_PS2_NBUTTONS; i++) { + int t, offs; + for (t = 0; t < IN_BINDTYPE_COUNT; t++) { + offs = IN_BIND_OFFS(i, t); + if (in_ps2_keys[i] == NULL) + binds[offs] = def_binds[offs] = 0; + if (binds[offs]) + count++; + } + } + + in_combos_find(binds, IN_PS2_NBUTTONS, &in_ps2_combo_keys, &in_ps2_combo_acts); + + return count; +} + +static const in_drv_t in_ps2_drv = { + .prefix = IN_PS2_PREFIX, + .probe = in_ps2_probe, + .free = in_ps2_free, + .get_key_names = in_ps2_get_key_names, + .clean_binds = in_ps2_clean_binds, + .update = in_ps2_update, + .update_keycode = in_ps2_update_keycode, + .menu_translate = in_ps2_menu_translate, +}; + +void in_ps2_init(struct in_default_bind *defbinds) +{ + int i, j; + + for (j = 0; j < 2; j++) { + mtapPortOpen(j); + + for (i = 0; i < 4; i++) { + padConnected[j][i] = 0; + padOpen[j][i] = 0; + padBuf[j][i] = memalign(64, 256); + padPortOpen(j, i, padBuf[j][i]); + } + } + + /* PS2 keys have bit masks, Picodrive wants bit numbers */ + for (i = 0; defbinds[i].code; i++) + defbinds[i].code = lg2(defbinds[i].code); + for (i = 0; i < KEY_PBTN_MAP_SIZE; i++) + key_pbtn_map[i].key = lg2(key_pbtn_map[i].key); + + in_ps2_combo_keys = in_ps2_combo_acts = 0; + + /* fill keys array, converting key bitmasks to bit numbers */ + in_ps2_keys[lg2(PAD_UP)] = "Up"; + in_ps2_keys[lg2(PAD_LEFT)] = "Left"; + in_ps2_keys[lg2(PAD_DOWN)] = "Down"; + in_ps2_keys[lg2(PAD_RIGHT)] = "Right"; + in_ps2_keys[lg2(PAD_START)] = "Start"; + in_ps2_keys[lg2(PAD_SELECT)] = "Select"; + in_ps2_keys[lg2(PAD_L1)] = "L1"; + in_ps2_keys[lg2(PAD_R1)] = "R1"; + in_ps2_keys[lg2(PAD_TRIANGLE)] = "Triangle"; + in_ps2_keys[lg2(PAD_CIRCLE)] = "Circle"; + in_ps2_keys[lg2(PAD_CROSS)] = "Cross"; + in_ps2_keys[lg2(PAD_SQUARE)] = "Square"; + // in_ps2_keys[lg2(PS2_NUB_UP)] = "Analog up"; + // in_ps2_keys[lg2(PS2_NUB_LEFT)] = "Analog left"; + // in_ps2_keys[lg2(PS2_NUB_DOWN)] = "Analog down"; + // in_ps2_keys[lg2(PS2_NUB_RIGHT)] = "Analog right"; + + in_register_driver(&in_ps2_drv, defbinds, NULL); +} + diff --git a/platform/ps2/in_ps2.h b/platform/ps2/in_ps2.h new file mode 100644 index 000000000..0f9bc8df1 --- /dev/null +++ b/platform/ps2/in_ps2.h @@ -0,0 +1,6 @@ + +struct in_default_bind; + +void in_ps2_init(struct in_default_bind *defbinds); + +void in_ps2_deinit(); diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index c3585dff2..02b3d73d7 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -45,18 +45,6 @@ static void deinit_drivers() { deinit_ps2_filesystem_driver(); } -void plat_init(void) -{ - init_joystick_driver(false); - init_audio_driver(); -} - - -void plat_finish(void) { - deinit_audio_driver(); - deinit_joystick_driver(false); -} - int plat_target_init(void) { return 0; From ebf2b007d1a8b04e3d2fed4147727245758a484f Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sun, 31 Dec 2023 18:10:25 +0100 Subject: [PATCH 15/66] Starting to copy some logic for emu from PSP --- platform/ps2/emu.c | 265 ++++++++++++++++++++++++++++++++++++++++++++ platform/ps2/plat.c | 35 +----- 2 files changed, 267 insertions(+), 33 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 4ff7f16ad..c0dd7d258 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -1,14 +1,26 @@ #include +#include #include #include #include #include "in_ps2.h" #include "../libpicofe/input.h" +#include "../libpicofe/plat.h" #include "../common/input_pico.h" #include "../common/emu.h" +#include + +#define OSD_FPS_X 220 + +static int osd_buf_cnt, osd_cdleds; + +static int out_x, out_y; +static int out_w, out_h; +static float hscale, vscale; + static struct in_default_bind in_ps2_defbinds[] = { { PAD_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, @@ -26,6 +38,145 @@ static struct in_default_bind in_ps2_defbinds[] = { 0, 0, 0 } }; +const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast", NULL }; +const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL }; +enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; + +#define is_16bit_mode() \ + (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X)) + +static int get_renderer(void) +{ + if (PicoIn.AHW & PAHW_32X) + return currentConfig.renderer32x; + else + return currentConfig.renderer; +} + +static void change_renderer(int diff) +{ + int *r; + if (PicoIn.AHW & PAHW_32X) + r = ¤tConfig.renderer32x; + else + r = ¤tConfig.renderer; + *r += diff; + + if (*r >= RT_COUNT) + *r = 0; + else if (*r < 0) + *r = RT_COUNT - 1; +} + +static void apply_renderer(void) +{ + PicoIn.opt &= ~(POPT_ALT_RENDERER|POPT_EN_SOFTSCALE); + PicoIn.opt |= POPT_DIS_32C_BORDER; + + switch (get_renderer()) { + case RT_16BIT: + PicoDrawSetOutFormat(PDF_RGB555, 0); + break; + case RT_8BIT_ACC: + PicoDrawSetOutFormat(PDF_8BIT, 0); + break; + case RT_8BIT_FAST: + PicoIn.opt |= POPT_ALT_RENDERER; + PicoDrawSetOutFormat(PDF_NONE, 0); + break; + } +} + +static void osd_text(int x, const char *text) +{ + +} + +static void blit_osd(void) +{ + +} + +static void cd_leds(void) +{ + +} + +static void blit_cdleds(void) +{ + +} + +void blitscreen_clut(void) +{ + + blit_osd(); + blit_cdleds(); +} + +static void draw_pico_ptr(void) +{ + // unsigned char *p = (unsigned char *)g_screen_ptr + 8; + + // // only if pen enabled and for 8bit mode + // if (pico_inp_mode == 0 || is_16bit_mode()) return; + + // p += 512 * (pico_pen_y + PICO_PEN_ADJUST_Y); + // p += pico_pen_x + PICO_PEN_ADJUST_X; + // if (!(Pico.video.reg[12]&1) && !(PicoIn.opt & POPT_DIS_32C_BORDER)) + // p += 32; + + // p[ -1] = 0xe0; p[ 0] = 0xf0; p[ 1] = 0xe0; + // p[ 511] = 0xf0; p[ 512] = 0xf0; p[ 513] = 0xf0; + // p[1023] = 0xe0; p[1024] = 0xf0; p[1025] = 0xe0; +} + +static void vidResetMode(void) {} + +void pemu_sound_start(void) {} +void pemu_sound_stop(void) {} + +/* set default configuration values */ +void pemu_prep_defconfig(void) +{ + defaultConfig.s_PsndRate = 44100; + defaultConfig.s_PicoCDBuffers = 64; + defaultConfig.filter = EOPT_FILTER_BILINEAR; // bilinear filtering + defaultConfig.scaling = EOPT_SCALE_43; + defaultConfig.vscaling = EOPT_VSCALE_FULL; + defaultConfig.renderer = RT_8BIT_ACC; + defaultConfig.renderer32x = RT_8BIT_ACC; + defaultConfig.EmuOpt |= EOPT_SHOW_RTC; +} + +/* check configuration for inconsistencies */ +void pemu_validate_config(void) +{ + if (currentConfig.gamma < -4 || currentConfig.gamma > 16) + currentConfig.gamma = 0; + if (currentConfig.gamma2 < 0 || currentConfig.gamma2 > 2) + currentConfig.gamma2 = 0; +} + +/* finalize rendering a frame */ +void pemu_finalize_frame(const char *fps, const char *notice) +{ + int emu_opt = currentConfig.EmuOpt; + + if (PicoIn.AHW & PAHW_PICO) + draw_pico_ptr(); + + osd_buf_cnt = 0; + if (notice) osd_text(4, notice); + if (emu_opt & 2) osd_text(OSD_FPS_X, fps); + + osd_cdleds = 0; + if ((emu_opt & 0x400) && (PicoIn.AHW & PAHW_MCD)) + cd_leds(); + + FlushCache(WRITEBACK_DCACHE); +} + void plat_init(void) { init_joystick_driver(false); @@ -38,4 +189,118 @@ void plat_init(void) void plat_finish(void) { deinit_audio_driver(); deinit_joystick_driver(false); +} + +/* display emulator status messages before holding emulation */ +void plat_status_msg_busy_first(const char *msg) +{ + plat_status_msg_busy_next(msg); +} + +void plat_status_msg_busy_next(const char *msg) +{ + plat_status_msg_clear(); + pemu_finalize_frame("", msg); + plat_video_flip(); + emu_status_msg(""); + reset_timing = 1; +} + +/* clear status message area */ +void plat_status_msg_clear(void) +{ + // not needed since the screen buf is cleared through the GU +} + +/* change the audio volume setting */ +void plat_update_volume(int has_changed, int is_up) +{ +} + +/* prepare for MD screen mode change */ +void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) +{ + int h43 = (col_count >= 192 ? 320 : col_count); // ugh, mind GG... + int v43 = (line_count >= 192 ? Pico.m.pal ? 240 : 224 : line_count); + + out_y = start_line; out_x = start_col; + out_h = line_count; out_w = col_count; + + if (col_count == 248) // mind aspect ratio when blanking 1st column + col_count = 256; + + switch (currentConfig.vscaling) { + case EOPT_VSCALE_FULL: + line_count = v43; + vscale = (float)270/line_count; + break; + case EOPT_VSCALE_NOBORDER: + vscale = (float)270/line_count; + break; + default: + vscale = 1; + break; + } + + switch (currentConfig.scaling) { + case EOPT_SCALE_43: + hscale = (vscale*h43)/col_count; + break; + case EOPT_SCALE_STRETCH: + hscale = (vscale*h43/2 + 480/2)/col_count; + break; + case EOPT_SCALE_WIDE: + hscale = (float)480/col_count; + break; + default: + hscale = vscale; + break; + } + + vidResetMode(); +} + +/* render one frame in RGB */ +void pemu_forced_frame(int no_scale, int do_emu) +{ + Pico.m.dirtyPal = 1; + + if (!no_scale) + no_scale = currentConfig.scaling == EOPT_SCALE_NONE; + emu_cmn_forced_frame(no_scale, do_emu, g_screen_ptr); +} + +/* change the platform output rendering */ +void plat_video_toggle_renderer(int change, int is_menu_call) +{ + change_renderer(change); + + if (is_menu_call) + return; + + apply_renderer(); + vidResetMode(); + rendstatus_old = -1; + + if (PicoIn.AHW & PAHW_32X) + emu_status_msg(renderer_names32x[get_renderer()]); + else + emu_status_msg(renderer_names[get_renderer()]); +} + +/* prepare for emulator output rendering */ +void plat_video_loop_prepare(void) +{ + apply_renderer(); + vidResetMode(); +} + +/* prepare for entering the emulator loop */ +void pemu_loop_prep(void) +{ +} + +/* terminate the emulator loop */ +void pemu_loop_end(void) +{ } \ No newline at end of file diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index 02b3d73d7..418e53101 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -19,9 +19,6 @@ #include "../libpicofe/plat.h" -const char *renderer_names[] = { "Software", "Hardware" }; -const char *renderer_names32x[] = { "Software", "Hardware", "Hardware (fast)" }; - struct plat_target plat_target = {}; static void reset_IOP() { @@ -59,7 +56,7 @@ void plat_target_finish(void) /* display a completed frame buffer and prepare a new render buffer */ void plat_video_flip(void) { - + blitscreen_clut(); } /* wait for start of vertical blanking */ @@ -243,32 +240,4 @@ void lprintf(const char *fmt, ...) va_end(vl); } -void plat_video_toggle_renderer(int change, int menu_call) {} - -void plat_update_volume(int has_changed, int is_up) {} - -void plat_status_msg_busy_first(const char *msg) {} - -void pemu_prep_defconfig(void) {} - -void pemu_validate_config(void) {} - -void plat_status_msg_clear(void) {} - -void plat_status_msg_busy_next(const char *msg) {} - -void plat_video_loop_prepare(void) {} - -void plat_debug_cat(char *str) {} - -void pemu_loop_prep(void) {} - -void pemu_sound_start(void) {} - -void pemu_loop_end(void) {} - -void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) {} - -void pemu_forced_frame(int no_scale, int do_emu) {} - -void pemu_finalize_frame(const char *fps, const char *notice_msg) {} \ No newline at end of file +void plat_debug_cat(char *str) {} \ No newline at end of file From 888ca0b83ba33424a7ecd242f4fb23c402aade30 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sun, 31 Dec 2023 18:27:46 +0100 Subject: [PATCH 16/66] Adding gskit dependency --- configure | 4 +-- platform/ps2/emu.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/configure b/configure index dc887617f..e73c69597 100755 --- a/configure +++ b/configure @@ -157,8 +157,8 @@ set_platform() MFLAGS="" ARCH=mips64r5900el ASFLAGS="$ASFLAGS -G0 -call_shared" - CFLAGS="$CFLAGS -D_EE -G0 -I${PS2SDK}/ee/include -I${PS2SDK}/common/include -I${PS2SDK}/ports/include" - LDFLAGS="$LDFLAGS -Wl,-zmax-page-size=128 -T${PS2SDK}/ee/startup/linkfile -L${PS2SDK}/ee/lib -L${PS2SDK}/ports/lib" + CFLAGS="$CFLAGS -D_EE -G0 -I${PS2SDK}/ee/include -I${PS2SDK}/common/include -I${PS2DEV}/gsKit/include -I${PS2SDK}/ports/include" + LDFLAGS="$LDFLAGS -Wl,-zmax-page-size=128 -T${PS2SDK}/ee/startup/linkfile -L${PS2SDK}/ee/lib -L${PS2DEV}/gsKit/lib -L${PS2SDK}/ports/lib" ;; *) fail "unsupported platform: $platform" diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index c0dd7d258..a2562f45c 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -1,9 +1,14 @@ #include +#include #include #include #include #include +#include +#include +#include +#include #include "in_ps2.h" #include "../libpicofe/input.h" @@ -15,6 +20,11 @@ #define OSD_FPS_X 220 +/* turn black GS Screen */ +#define GS_BLACK GS_SETREG_RGBA(0x00, 0x00, 0x00, 0x80) +/* Generic tint color */ +#define GS_TEXT GS_SETREG_RGBA(0x80, 0x80, 0x80, 0x80) + static int osd_buf_cnt, osd_cdleds; static int out_x, out_y; @@ -42,9 +52,70 @@ const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL }; enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; +typedef struct ps2_video { + GSGLOBAL *gsGlobal; + + GSTEXTURE *scrbitmap; + GSTEXTURE *tex_spr0; + GSTEXTURE *tex_spr1; + GSTEXTURE *tex_spr2; + GSTEXTURE *tex_fix; + uint32_t offset; + uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ + uint8_t pixel_format; +} ps2_video_t; + +ps2_video_t *ps2_video = NULL; + #define is_16bit_mode() \ (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X)) +static void video_init(void) +{ + ps2_video = (ps2_video_t*)calloc(1, sizeof(ps2_video_t)); + + GSGLOBAL *gsGlobal; + + gsGlobal = gsKit_init_global(); + + gsGlobal->Mode = GS_MODE_NTSC; + gsGlobal->Height = 448; + + gsGlobal->PSM = GS_PSM_CT24; + gsGlobal->PSMZ = GS_PSMZ_16S; + gsGlobal->ZBuffering = GS_SETTING_OFF; + gsGlobal->DoubleBuffering = GS_SETTING_ON; + gsGlobal->PrimAlphaEnable = GS_SETTING_ON; + gsGlobal->Dithering = GS_SETTING_OFF; + + gsKit_set_primalpha(gsGlobal, GS_SETREG_ALPHA(0, 1, 0, 1, 0), 0); + + dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); + dmaKit_chan_init(DMA_CHANNEL_GIF); + + gsKit_set_clamp(gsGlobal, GS_CMODE_REPEAT); + + gsKit_vram_clear(gsGlobal); + + gsKit_init_screen(gsGlobal); + + gsKit_TexManager_init(gsGlobal); + + gsKit_mode_switch(gsGlobal, GS_ONESHOT); + gsKit_clear(gsGlobal, GS_BLACK); + ps2_video->gsGlobal = gsGlobal; +} + +static void video_deinit(void) +{ + if (!ps2_video) return; + + gsKit_clear(ps2_video->gsGlobal, GS_BLACK); + gsKit_vram_clear(ps2_video->gsGlobal); + gsKit_deinit_global(ps2_video->gsGlobal); + free(ps2_video); +} + static int get_renderer(void) { if (PicoIn.AHW & PAHW_32X) @@ -179,6 +250,7 @@ void pemu_finalize_frame(const char *fps, const char *notice) void plat_init(void) { + video_init(); init_joystick_driver(false); in_ps2_init(in_ps2_defbinds); in_probe(); @@ -189,6 +261,7 @@ void plat_init(void) void plat_finish(void) { deinit_audio_driver(); deinit_joystick_driver(false); + video_deinit(); } /* display emulator status messages before holding emulation */ From 862e969bab60a74cc94e45bef46aa419e21940b2 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Mon, 1 Jan 2024 12:24:10 +0100 Subject: [PATCH 17/66] Adding background objects --- platform/ps2/emu.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index a2562f45c..c25fc2bd3 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -55,11 +55,8 @@ enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; typedef struct ps2_video { GSGLOBAL *gsGlobal; - GSTEXTURE *scrbitmap; - GSTEXTURE *tex_spr0; - GSTEXTURE *tex_spr1; - GSTEXTURE *tex_spr2; - GSTEXTURE *tex_fix; + GSTEXTURE *g_menuscreen; + uint8_t *g_menubg_ptr; uint32_t offset; uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ uint8_t pixel_format; @@ -70,6 +67,29 @@ ps2_video_t *ps2_video = NULL; #define is_16bit_mode() \ (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X)) +static void set_g_menuscreen_values(ps2_video_t *ps2_video) +{ + GSTEXTURE *g_menuscreen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); + size_t g_menuscreenSize = gsKit_texture_size_ee(ps2_video->gsGlobal->Width, ps2_video->gsGlobal->Height, GS_PSM_CT16); + g_menuscreen->Width = ps2_video->gsGlobal->Width; + g_menuscreen->Height = ps2_video->gsGlobal->Height; + g_menuscreen->PSM = GS_PSM_CT16; + g_menuscreen->Mem = (uint32_t *)malloc(g_menuscreenSize); + + ps2_video->g_menuscreen = g_menuscreen; + ps2_video->g_menubg_ptr = (uint8_t *)malloc(g_menuscreenSize);; + + g_menuscreen_w = g_menuscreen->Width; + g_menuscreen_h = g_menuscreen->Height; + g_menuscreen_pp = g_menuscreen->Width; + g_menuscreen_ptr = g_menuscreen->Mem; + + g_menubg_src_w = g_menuscreen->Width; + g_menubg_src_h = g_menuscreen->Height; + g_menubg_src_pp = g_menuscreen->Width; + g_menubg_ptr = ps2_video->g_menubg_ptr; +} + static void video_init(void) { ps2_video = (ps2_video_t*)calloc(1, sizeof(ps2_video_t)); @@ -104,12 +124,19 @@ static void video_init(void) gsKit_mode_switch(gsGlobal, GS_ONESHOT); gsKit_clear(gsGlobal, GS_BLACK); ps2_video->gsGlobal = gsGlobal; + + set_g_menuscreen_values(ps2_video); } static void video_deinit(void) { if (!ps2_video) return; + free(ps2_video->g_menuscreen->Mem); + free(ps2_video->g_menuscreen); + + free(ps2_video->g_menubg_ptr); + gsKit_clear(ps2_video->gsGlobal, GS_BLACK); gsKit_vram_clear(ps2_video->gsGlobal); gsKit_deinit_global(ps2_video->gsGlobal); From 8633b583f0bddb3401470387939df964c246df30 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Mon, 1 Jan 2024 13:08:17 +0100 Subject: [PATCH 18/66] Starting to see the menu in the screen --- platform/ps2/emu.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ platform/ps2/plat.c | 35 ---------------------- 2 files changed, 71 insertions(+), 35 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index c25fc2bd3..15a0e3045 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -13,6 +13,7 @@ #include "in_ps2.h" #include "../libpicofe/input.h" #include "../libpicofe/plat.h" +#include "../libpicofe/menu.h" #include "../common/input_pico.h" #include "../common/emu.h" @@ -56,6 +57,8 @@ typedef struct ps2_video { GSGLOBAL *gsGlobal; GSTEXTURE *g_menuscreen; + uint32_t g_menuscreen_vertices_count; + GSPRIMUVPOINT *g_menuscreen_vertices; uint8_t *g_menubg_ptr; uint32_t offset; uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ @@ -88,6 +91,20 @@ static void set_g_menuscreen_values(ps2_video_t *ps2_video) g_menubg_src_h = g_menuscreen->Height; g_menubg_src_pp = g_menuscreen->Width; g_menubg_ptr = ps2_video->g_menubg_ptr; + + uint32_t g_menuscreen_vertices_count = 2; + GSPRIMUVPOINT *g_menuscreen_vertices = (GSPRIMUVPOINT *)calloc(g_menuscreen_vertices_count, sizeof(GSPRIMUVPOINT)); + + g_menuscreen_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 0, 0, 0); + g_menuscreen_vertices[0].uv = vertex_to_UV(g_menuscreen, 0, 0); + g_menuscreen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + g_menuscreen_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, g_menuscreen->Width, g_menuscreen->Height, 0); + g_menuscreen_vertices[1].uv = vertex_to_UV(g_menuscreen, g_menuscreen->Width, g_menuscreen->Height); + g_menuscreen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + ps2_video->g_menuscreen_vertices_count = g_menuscreen_vertices_count; + ps2_video->g_menuscreen_vertices = g_menuscreen_vertices; } static void video_init(void) @@ -231,6 +248,60 @@ static void draw_pico_ptr(void) static void vidResetMode(void) {} +static void flipScreen(void *data, bool vsync) +{ + ps2_video_t *ps2 = (ps2_video_t*)data; + + gsKit_queue_exec(ps2->gsGlobal); + gsKit_finish(); + + if (vsync) gsKit_sync_flip(ps2->gsGlobal); + + gsKit_TexManager_nextFrame(ps2->gsGlobal); + gsKit_clear(ps2->gsGlobal, GS_BLACK); +} + + +/* display a completed frame buffer and prepare a new render buffer */ +void plat_video_flip(void) +{ + blitscreen_clut(); +} + +/* wait for start of vertical blanking */ +void plat_video_wait_vsync(void) +{ +} + +/* switch from emulation display to menu display */ +void plat_video_menu_enter(int is_rom_loaded) +{ +} + +/* start rendering a menu screen */ +void plat_video_menu_begin(void) +{ + gsKit_TexManager_invalidate(ps2_video->gsGlobal, ps2_video->g_menuscreen); +} + +/* display a completed menu screen */ +void plat_video_menu_end(void) +{ + gsKit_TexManager_bind(ps2_video->gsGlobal, ps2_video->g_menuscreen); + gskit_prim_list_sprite_texture_uv_3d( + ps2_video->gsGlobal, + ps2_video->g_menuscreen, + ps2_video->g_menuscreen_vertices_count, + ps2_video->g_menuscreen_vertices + ); + flipScreen(ps2_video, 1); +} + +/* terminate menu display */ +void plat_video_menu_leave(void) +{ +} + void pemu_sound_start(void) {} void pemu_sound_stop(void) {} diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index 418e53101..7b6d22677 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -53,41 +53,6 @@ void plat_target_finish(void) deinit_drivers(); } -/* display a completed frame buffer and prepare a new render buffer */ -void plat_video_flip(void) -{ - blitscreen_clut(); -} - -/* wait for start of vertical blanking */ -void plat_video_wait_vsync(void) -{ -} - -/* switch from emulation display to menu display */ -void plat_video_menu_enter(int is_rom_loaded) -{ - -} - -/* start rendering a menu screen */ -void plat_video_menu_begin(void) -{ - -} - -/* display a completed menu screen */ -void plat_video_menu_end(void) -{ - -} - -/* terminate menu display */ -void plat_video_menu_leave(void) -{ - -} - int plat_parse_arg(int argc, char *argv[], int *x) { return 1; From 1107e618f5e3e9eb7cffb866fa3d6c25d32cea85 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Tue, 2 Jan 2024 00:10:21 +0100 Subject: [PATCH 19/66] Starting to see the emulator on the screen --- platform/ps2/emu.c | 166 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 158 insertions(+), 8 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 15a0e3045..862d91876 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -59,6 +59,19 @@ typedef struct ps2_video { GSTEXTURE *g_menuscreen; uint32_t g_menuscreen_vertices_count; GSPRIMUVPOINT *g_menuscreen_vertices; + + GSTEXTURE *g_screen; + uint32_t g_screen_vertices_count; + GSPRIMUVPOINT *g_screen_vertices; + + GSTEXTURE *osd; + uint32_t osd_vertices_count; + GSPRIMUVPOINT *osd_vertices; + + GSTEXTURE *cdleds; + uint32_t cdleds_vertices_count; + GSPRIMUVPOINT *cdleds_vertices; + uint8_t *g_menubg_ptr; uint32_t offset; uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ @@ -107,6 +120,91 @@ static void set_g_menuscreen_values(ps2_video_t *ps2_video) ps2_video->g_menuscreen_vertices = g_menuscreen_vertices; } +void set_g_screen_values(ps2_video_t *ps2_video) { + GSTEXTURE *g_screen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); + size_t g_screenSize = gsKit_texture_size_ee(328, 256, GS_PSM_CT16); + g_screen->Width = 328; + g_screen->Height = 256; + g_screen->PSM = GS_PSM_CT16; + g_screen->Mem = (uint32_t *)malloc(g_screenSize); + + g_screen_width = 328; + g_screen_height = 256; + g_screen_ppitch = 328; + g_screen_ptr = g_screen->Mem; + + ps2_video->g_screen = g_screen; + + uint32_t g_screen_vertices_count = 2; + GSPRIMUVPOINT *g_screen_vertices = (GSPRIMUVPOINT *)calloc(g_screen_vertices_count, sizeof(GSPRIMUVPOINT)); + + g_screen_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 0, 0, 2); + g_screen_vertices[0].uv = vertex_to_UV(g_screen, 0, 0); + g_screen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + g_screen_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, g_screen->Width, g_screen->Height, 2); + g_screen_vertices[1].uv = vertex_to_UV(g_screen, g_screen->Width, g_screen->Height); + g_screen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + ps2_video->g_screen_vertices_count = g_screen_vertices_count; + ps2_video->g_screen_vertices = g_screen_vertices; + + if (is_16bit_mode()) + PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2); + else + PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch); +} + +void set_cdleds_values(ps2_video_t *ps2_video) { + GSTEXTURE *cdleds = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); + size_t cdledsSize = gsKit_texture_size_ee(14, 5, GS_PSM_CT16); + cdleds->Width = 14; + cdleds->Height = 5; + cdleds->PSM = GS_PSM_CT16; + cdleds->Mem = (uint32_t *)malloc(cdledsSize); + + ps2_video->cdleds = cdleds; + + uint32_t cdleds_vertices_count = 2; + GSPRIMUVPOINT *cdleds_vertices = (GSPRIMUVPOINT *)calloc(cdleds_vertices_count, sizeof(GSPRIMUVPOINT)); + + cdleds_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 4, 1, 2); + cdleds_vertices[0].uv = vertex_to_UV(cdleds, 0, 0); + cdleds_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + cdleds_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, cdleds->Width, cdleds->Height, 0); + cdleds_vertices[1].uv = vertex_to_UV(cdleds, cdleds->Width, cdleds->Height); + cdleds_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + ps2_video->cdleds_vertices_count = cdleds_vertices_count; + ps2_video->cdleds_vertices = cdleds_vertices; +} + +void set_osd_values(ps2_video_t *ps2_video) { + GSTEXTURE *osd = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); + size_t osdSize = gsKit_texture_size_ee(512, 8, GS_PSM_CT16); + osd->Width = 512; + osd->Height = 8; + osd->PSM = GS_PSM_CT16; + osd->Mem = (uint32_t *)malloc(osdSize); + + ps2_video->osd = osd; + + uint32_t osd_vertices_count = 2; + GSPRIMUVPOINT *osd_vertices = (GSPRIMUVPOINT *)calloc(osd_vertices_count, sizeof(GSPRIMUVPOINT)); + + osd_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 0, 0, 0); + osd_vertices[0].uv = vertex_to_UV(osd, 0, 0); + osd_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + osd_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, osd->Width, osd->Height, 0); + osd_vertices[1].uv = vertex_to_UV(osd, osd->Width, osd->Height); + osd_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + ps2_video->osd_vertices_count = osd_vertices_count; + ps2_video->osd_vertices = osd_vertices; +} + static void video_init(void) { ps2_video = (ps2_video_t*)calloc(1, sizeof(ps2_video_t)); @@ -141,6 +239,7 @@ static void video_init(void) gsKit_mode_switch(gsGlobal, GS_ONESHOT); gsKit_clear(gsGlobal, GS_BLACK); ps2_video->gsGlobal = gsGlobal; + ps2_video->vsync = 0; set_g_menuscreen_values(ps2_video); } @@ -151,6 +250,7 @@ static void video_deinit(void) free(ps2_video->g_menuscreen->Mem); free(ps2_video->g_menuscreen); + free(ps2_video->g_menuscreen_vertices); free(ps2_video->g_menubg_ptr); @@ -204,29 +304,71 @@ static void apply_renderer(void) static void osd_text(int x, const char *text) { + // int len = strlen(text) * 8; + // int *p, h; + // void *tmp = g_screen_ptr; + // printf("osd_text, text: %s\n", text); + // g_screen_ptr = osd_buf; + // for (h = 0; h < 8; h++) { + // p = (int *) (osd_buf+x+512*h); + // p = (int *) ((int)p & ~3); // align + // memset32_uncached(p, 0, len/2); + // } + // emu_text_out16(x, 0, text); + // g_screen_ptr = tmp; + + // osd_buf_x[osd_buf_cnt] = x; + // osd_buf_l[osd_buf_cnt] = len; + // osd_buf_cnt ++; } -static void blit_osd(void) +static void blit_screen(void) { + gsKit_TexManager_invalidate(ps2_video->gsGlobal, ps2_video->g_screen); + gsKit_TexManager_bind(ps2_video->gsGlobal, ps2_video->g_screen); + gskit_prim_list_sprite_texture_uv_3d( + ps2_video->gsGlobal, + ps2_video->g_screen, + ps2_video->g_screen_vertices_count, + ps2_video->g_screen_vertices + ); } -static void cd_leds(void) +static void blit_osd(void) { } -static void blit_cdleds(void) +static void cd_leds(void) { + unsigned int reg, col_g, col_r, *p; + gsKit_TexManager_invalidate(ps2_video->gsGlobal, ps2_video->cdleds); + reg = Pico_mcd->s68k_regs[0]; + + p = (unsigned int *)ps2_video->cdleds->Mem; + col_g = (reg & 2) ? 0x06000600 : 0; + col_r = (reg & 1) ? 0x00180018 : 0; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; + + osd_cdleds = 1; } -void blitscreen_clut(void) +static void blit_cdleds(void) { + if (!osd_cdleds) return; - blit_osd(); - blit_cdleds(); + gsKit_TexManager_bind(ps2_video->gsGlobal, ps2_video->cdleds); + gskit_prim_list_sprite_texture_uv_3d( + ps2_video->gsGlobal, + ps2_video->cdleds, + ps2_video->cdleds_vertices_count, + ps2_video->cdleds_vertices + ); } static void draw_pico_ptr(void) @@ -265,7 +407,12 @@ static void flipScreen(void *data, bool vsync) /* display a completed frame buffer and prepare a new render buffer */ void plat_video_flip(void) { - blitscreen_clut(); + blit_screen(); + blit_osd(); + blit_cdleds(); + + // flipScreen(ps2_video, ps2_video->vsync); + flipScreen(ps2_video, 1); } /* wait for start of vertical blanking */ @@ -313,7 +460,7 @@ void pemu_prep_defconfig(void) defaultConfig.filter = EOPT_FILTER_BILINEAR; // bilinear filtering defaultConfig.scaling = EOPT_SCALE_43; defaultConfig.vscaling = EOPT_VSCALE_FULL; - defaultConfig.renderer = RT_8BIT_ACC; + defaultConfig.renderer = RT_16BIT; defaultConfig.renderer32x = RT_8BIT_ACC; defaultConfig.EmuOpt |= EOPT_SHOW_RTC; } @@ -469,9 +616,12 @@ void plat_video_loop_prepare(void) /* prepare for entering the emulator loop */ void pemu_loop_prep(void) { + set_g_screen_values(ps2_video); + set_cdleds_values(ps2_video); } /* terminate the emulator loop */ void pemu_loop_end(void) { + pemu_sound_stop(); } \ No newline at end of file From 30f7602e65fc887b84e2c2f3f1754940e08f0ad1 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Fri, 5 Jan 2024 18:02:51 +0100 Subject: [PATCH 20/66] Disable alpha and improve vsync logic --- platform/ps2/emu.c | 67 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 862d91876..0c38260c1 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -53,6 +53,8 @@ const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL }; enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; +static int vsync_sema_id; + typedef struct ps2_video { GSGLOBAL *gsGlobal; @@ -72,8 +74,9 @@ typedef struct ps2_video { uint32_t cdleds_vertices_count; GSPRIMUVPOINT *cdleds_vertices; - uint8_t *g_menubg_ptr; uint32_t offset; + int32_t vsync_callback_id; + uint8_t *g_menubg_ptr; uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ uint8_t pixel_format; } ps2_video_t; @@ -83,6 +86,14 @@ ps2_video_t *ps2_video = NULL; #define is_16bit_mode() \ (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X)) +static int vsync_handler(void) +{ + iSignalSema(vsync_sema_id); + + ExitHandler(); + return 0; +} + static void set_g_menuscreen_values(ps2_video_t *ps2_video) { GSTEXTURE *g_menuscreen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); @@ -142,7 +153,7 @@ void set_g_screen_values(ps2_video_t *ps2_video) { g_screen_vertices[0].uv = vertex_to_UV(g_screen, 0, 0); g_screen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - g_screen_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, g_screen->Width, g_screen->Height, 2); + g_screen_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, ps2_video->gsGlobal->Width, ps2_video->gsGlobal->Height, 2); g_screen_vertices[1].uv = vertex_to_UV(g_screen, g_screen->Width, g_screen->Height); g_screen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); @@ -207,8 +218,15 @@ void set_osd_values(ps2_video_t *ps2_video) { static void video_init(void) { + ee_sema_t sema; + + sema.init_count = 0; + sema.max_count = 1; + sema.option = 0; ps2_video = (ps2_video_t*)calloc(1, sizeof(ps2_video_t)); + vsync_sema_id = CreateSema(&sema); + GSGLOBAL *gsGlobal; gsGlobal = gsKit_init_global(); @@ -220,15 +238,17 @@ static void video_init(void) gsGlobal->PSMZ = GS_PSMZ_16S; gsGlobal->ZBuffering = GS_SETTING_OFF; gsGlobal->DoubleBuffering = GS_SETTING_ON; - gsGlobal->PrimAlphaEnable = GS_SETTING_ON; + gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; gsGlobal->Dithering = GS_SETTING_OFF; - gsKit_set_primalpha(gsGlobal, GS_SETREG_ALPHA(0, 1, 0, 1, 0), 0); + // gsKit_set_primalpha(gsGlobal, GS_SETREG_ALPHA(0, 1, 0, 1, 0), 0); dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); dmaKit_chan_init(DMA_CHANNEL_GIF); gsKit_set_clamp(gsGlobal, GS_CMODE_REPEAT); + // gsKit_set_test(gsGlobal, GS_ZTEST_OFF); + // gsKit_set_test(gsGlobal, GS_ATEST_OFF); gsKit_vram_clear(gsGlobal); @@ -240,6 +260,7 @@ static void video_init(void) gsKit_clear(gsGlobal, GS_BLACK); ps2_video->gsGlobal = gsGlobal; ps2_video->vsync = 0; + ps2_video->vsync_callback_id = gsKit_add_vsync_handler(vsync_handler); set_g_menuscreen_values(ps2_video); } @@ -257,6 +278,11 @@ static void video_deinit(void) gsKit_clear(ps2_video->gsGlobal, GS_BLACK); gsKit_vram_clear(ps2_video->gsGlobal); gsKit_deinit_global(ps2_video->gsGlobal); + gsKit_remove_vsync_handler(ps2_video->vsync_callback_id); + + if (vsync_sema_id >= 0) + DeleteSema(vsync_sema_id); + free(ps2_video); } @@ -390,6 +416,32 @@ static void draw_pico_ptr(void) static void vidResetMode(void) {} +/* Copy of gsKit_sync_flip, but without the 'flip' */ +static void gsKit_sync(GSGLOBAL *gsGlobal) +{ + if (!gsGlobal->FirstFrame) + WaitSema(vsync_sema_id); + + while (PollSema(vsync_sema_id) >= 0); +} + +/* Copy of gsKit_sync_flip, but without the 'sync' */ +static void gsKit_flip(GSGLOBAL *gsGlobal) +{ + if (!gsGlobal->FirstFrame) + { + if (gsGlobal->DoubleBuffering == GS_SETTING_ON) + { + GS_SET_DISPFB2(gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192, + gsGlobal->Width / 64, gsGlobal->PSM, 0, 0); + + gsGlobal->ActiveBuffer ^= 1; + } + } + + gsKit_setactive(gsGlobal); +} + static void flipScreen(void *data, bool vsync) { ps2_video_t *ps2 = (ps2_video_t*)data; @@ -397,7 +449,9 @@ static void flipScreen(void *data, bool vsync) gsKit_queue_exec(ps2->gsGlobal); gsKit_finish(); - if (vsync) gsKit_sync_flip(ps2->gsGlobal); + if (ps2->vsync) + gsKit_sync(ps2->gsGlobal); + gsKit_flip(ps2->gsGlobal); gsKit_TexManager_nextFrame(ps2->gsGlobal); gsKit_clear(ps2->gsGlobal, GS_BLACK); @@ -411,8 +465,7 @@ void plat_video_flip(void) blit_osd(); blit_cdleds(); - // flipScreen(ps2_video, ps2_video->vsync); - flipScreen(ps2_video, 1); + flipScreen(ps2_video, ps2_video->vsync); } /* wait for start of vertical blanking */ From 6724ae42f3b85050e54977785ae03ab382c22c00 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Fri, 5 Jan 2024 18:59:21 +0100 Subject: [PATCH 21/66] Some clean up around emu.c --- platform/ps2/emu.c | 236 +++++++++++++++++++-------------------------- 1 file changed, 101 insertions(+), 135 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 0c38260c1..98d2ed06f 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -53,35 +53,24 @@ const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL }; enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; -static int vsync_sema_id; - -typedef struct ps2_video { - GSGLOBAL *gsGlobal; +static GSGLOBAL *gsGlobal; - GSTEXTURE *g_menuscreen; - uint32_t g_menuscreen_vertices_count; - GSPRIMUVPOINT *g_menuscreen_vertices; +static GSTEXTURE *g_menuscreen; +static GSPRIMUVPOINT *g_menuscreen_vertices; - GSTEXTURE *g_screen; - uint32_t g_screen_vertices_count; - GSPRIMUVPOINT *g_screen_vertices; +static GSTEXTURE *g_screen; +static GSPRIMUVPOINT *g_screen_vertices; - GSTEXTURE *osd; - uint32_t osd_vertices_count; - GSPRIMUVPOINT *osd_vertices; +static GSTEXTURE *osd; +static uint32_t osd_vertices_count; +static GSPRIMUVPOINT *osd_vertices; - GSTEXTURE *cdleds; - uint32_t cdleds_vertices_count; - GSPRIMUVPOINT *cdleds_vertices; +static GSTEXTURE *cdleds; +static GSPRIMUVPOINT *cdleds_vertices; - uint32_t offset; - int32_t vsync_callback_id; - uint8_t *g_menubg_ptr; - uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ - uint8_t pixel_format; -} ps2_video_t; - -ps2_video_t *ps2_video = NULL; +static int vsync_sema_id; +static int32_t vsync_callback_id; +static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ #define is_16bit_mode() \ (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X)) @@ -94,17 +83,22 @@ static int vsync_handler(void) return 0; } -static void set_g_menuscreen_values(ps2_video_t *ps2_video) +static void set_g_menuscreen_values() { - GSTEXTURE *g_menuscreen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - size_t g_menuscreenSize = gsKit_texture_size_ee(ps2_video->gsGlobal->Width, ps2_video->gsGlobal->Height, GS_PSM_CT16); - g_menuscreen->Width = ps2_video->gsGlobal->Width; - g_menuscreen->Height = ps2_video->gsGlobal->Height; + if (g_menuscreen != NULL) { + free(g_menuscreen->Mem); + free(g_menuscreen); + free(g_menubg_ptr); + free(g_menuscreen_vertices); + } + g_menuscreen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); + size_t g_menuscreenSize = gsKit_texture_size_ee(gsGlobal->Width, gsGlobal->Height, GS_PSM_CT16); + g_menuscreen->Width = gsGlobal->Width; + g_menuscreen->Height = gsGlobal->Height; g_menuscreen->PSM = GS_PSM_CT16; - g_menuscreen->Mem = (uint32_t *)malloc(g_menuscreenSize); + g_menuscreen->Mem = malloc(g_menuscreenSize); - ps2_video->g_menuscreen = g_menuscreen; - ps2_video->g_menubg_ptr = (uint8_t *)malloc(g_menuscreenSize);; + g_menubg_ptr = (uint8_t *)malloc(g_menuscreenSize); g_menuscreen_w = g_menuscreen->Width; g_menuscreen_h = g_menuscreen->Height; @@ -114,25 +108,25 @@ static void set_g_menuscreen_values(ps2_video_t *ps2_video) g_menubg_src_w = g_menuscreen->Width; g_menubg_src_h = g_menuscreen->Height; g_menubg_src_pp = g_menuscreen->Width; - g_menubg_ptr = ps2_video->g_menubg_ptr; - uint32_t g_menuscreen_vertices_count = 2; - GSPRIMUVPOINT *g_menuscreen_vertices = (GSPRIMUVPOINT *)calloc(g_menuscreen_vertices_count, sizeof(GSPRIMUVPOINT)); + g_menuscreen_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); - g_menuscreen_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 0, 0, 0); + g_menuscreen_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 2); g_menuscreen_vertices[0].uv = vertex_to_UV(g_menuscreen, 0, 0); g_menuscreen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - g_menuscreen_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, g_menuscreen->Width, g_menuscreen->Height, 0); + g_menuscreen_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, g_menuscreen->Width, g_menuscreen->Height, 2); g_menuscreen_vertices[1].uv = vertex_to_UV(g_menuscreen, g_menuscreen->Width, g_menuscreen->Height); g_menuscreen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - - ps2_video->g_menuscreen_vertices_count = g_menuscreen_vertices_count; - ps2_video->g_menuscreen_vertices = g_menuscreen_vertices; } -void set_g_screen_values(ps2_video_t *ps2_video) { - GSTEXTURE *g_screen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); +void set_g_screen_values() { + if (g_screen != NULL) { + free(g_screen->Mem); + free(g_screen); + free(g_screen_vertices); + } + g_screen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); size_t g_screenSize = gsKit_texture_size_ee(328, 256, GS_PSM_CT16); g_screen->Width = 328; g_screen->Height = 256; @@ -144,76 +138,69 @@ void set_g_screen_values(ps2_video_t *ps2_video) { g_screen_ppitch = 328; g_screen_ptr = g_screen->Mem; - ps2_video->g_screen = g_screen; - - uint32_t g_screen_vertices_count = 2; - GSPRIMUVPOINT *g_screen_vertices = (GSPRIMUVPOINT *)calloc(g_screen_vertices_count, sizeof(GSPRIMUVPOINT)); + g_screen_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); - g_screen_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 0, 0, 2); + g_screen_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 0); g_screen_vertices[0].uv = vertex_to_UV(g_screen, 0, 0); g_screen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - g_screen_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, ps2_video->gsGlobal->Width, ps2_video->gsGlobal->Height, 2); + g_screen_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, gsGlobal->Width, gsGlobal->Height, 0); g_screen_vertices[1].uv = vertex_to_UV(g_screen, g_screen->Width, g_screen->Height); g_screen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - ps2_video->g_screen_vertices_count = g_screen_vertices_count; - ps2_video->g_screen_vertices = g_screen_vertices; - if (is_16bit_mode()) PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2); else PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch); } -void set_cdleds_values(ps2_video_t *ps2_video) { - GSTEXTURE *cdleds = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); +void set_cdleds_values() { + if (cdleds != NULL) { + free(cdleds->Mem); + free(cdleds); + free(cdleds_vertices); + } + cdleds = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); size_t cdledsSize = gsKit_texture_size_ee(14, 5, GS_PSM_CT16); cdleds->Width = 14; cdleds->Height = 5; cdleds->PSM = GS_PSM_CT16; cdleds->Mem = (uint32_t *)malloc(cdledsSize); - ps2_video->cdleds = cdleds; - - uint32_t cdleds_vertices_count = 2; - GSPRIMUVPOINT *cdleds_vertices = (GSPRIMUVPOINT *)calloc(cdleds_vertices_count, sizeof(GSPRIMUVPOINT)); + cdleds_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); - cdleds_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 4, 1, 2); + cdleds_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 4, 1, 1); cdleds_vertices[0].uv = vertex_to_UV(cdleds, 0, 0); cdleds_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - cdleds_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, cdleds->Width, cdleds->Height, 0); + cdleds_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, cdleds->Width, cdleds->Height, 1); cdleds_vertices[1].uv = vertex_to_UV(cdleds, cdleds->Width, cdleds->Height); cdleds_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - - ps2_video->cdleds_vertices_count = cdleds_vertices_count; - ps2_video->cdleds_vertices = cdleds_vertices; } -void set_osd_values(ps2_video_t *ps2_video) { - GSTEXTURE *osd = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); +void set_osd_values() { + if (osd != NULL) { + free(osd->Mem); + free(osd); + free(osd_vertices); + } + osd = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); size_t osdSize = gsKit_texture_size_ee(512, 8, GS_PSM_CT16); osd->Width = 512; osd->Height = 8; osd->PSM = GS_PSM_CT16; osd->Mem = (uint32_t *)malloc(osdSize); - ps2_video->osd = osd; - - uint32_t osd_vertices_count = 2; - GSPRIMUVPOINT *osd_vertices = (GSPRIMUVPOINT *)calloc(osd_vertices_count, sizeof(GSPRIMUVPOINT)); + osd_vertices_count = 2; + osd_vertices = (GSPRIMUVPOINT *)calloc(osd_vertices_count, sizeof(GSPRIMUVPOINT)); - osd_vertices[0].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, 0, 0, 0); + osd_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 1); osd_vertices[0].uv = vertex_to_UV(osd, 0, 0); osd_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - osd_vertices[1].xyz2 = vertex_to_XYZ2(ps2_video->gsGlobal, osd->Width, osd->Height, 0); + osd_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, osd->Width, osd->Height, 1); osd_vertices[1].uv = vertex_to_UV(osd, osd->Width, osd->Height); osd_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - - ps2_video->osd_vertices_count = osd_vertices_count; - ps2_video->osd_vertices = osd_vertices; } static void video_init(void) @@ -223,14 +210,10 @@ static void video_init(void) sema.init_count = 0; sema.max_count = 1; sema.option = 0; - ps2_video = (ps2_video_t*)calloc(1, sizeof(ps2_video_t)); vsync_sema_id = CreateSema(&sema); - GSGLOBAL *gsGlobal; - gsGlobal = gsKit_init_global(); - gsGlobal->Mode = GS_MODE_NTSC; gsGlobal->Height = 448; @@ -241,49 +224,37 @@ static void video_init(void) gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; gsGlobal->Dithering = GS_SETTING_OFF; - // gsKit_set_primalpha(gsGlobal, GS_SETREG_ALPHA(0, 1, 0, 1, 0), 0); dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); dmaKit_chan_init(DMA_CHANNEL_GIF); gsKit_set_clamp(gsGlobal, GS_CMODE_REPEAT); - // gsKit_set_test(gsGlobal, GS_ZTEST_OFF); - // gsKit_set_test(gsGlobal, GS_ATEST_OFF); gsKit_vram_clear(gsGlobal); - gsKit_init_screen(gsGlobal); - gsKit_TexManager_init(gsGlobal); - gsKit_mode_switch(gsGlobal, GS_ONESHOT); gsKit_clear(gsGlobal, GS_BLACK); - ps2_video->gsGlobal = gsGlobal; - ps2_video->vsync = 0; - ps2_video->vsync_callback_id = gsKit_add_vsync_handler(vsync_handler); + vsync = 0; + vsync_callback_id = gsKit_add_vsync_handler(vsync_handler); - set_g_menuscreen_values(ps2_video); + set_g_menuscreen_values(); } static void video_deinit(void) { - if (!ps2_video) return; + free(g_menuscreen->Mem); + free(g_menuscreen); + free(g_menuscreen_vertices); + free(g_menubg_ptr); - free(ps2_video->g_menuscreen->Mem); - free(ps2_video->g_menuscreen); - free(ps2_video->g_menuscreen_vertices); - - free(ps2_video->g_menubg_ptr); - - gsKit_clear(ps2_video->gsGlobal, GS_BLACK); - gsKit_vram_clear(ps2_video->gsGlobal); - gsKit_deinit_global(ps2_video->gsGlobal); - gsKit_remove_vsync_handler(ps2_video->vsync_callback_id); + gsKit_clear(gsGlobal, GS_BLACK); + gsKit_vram_clear(gsGlobal); + gsKit_deinit_global(gsGlobal); + gsKit_remove_vsync_handler(vsync_callback_id); if (vsync_sema_id >= 0) DeleteSema(vsync_sema_id); - - free(ps2_video); } static int get_renderer(void) @@ -351,14 +322,14 @@ static void osd_text(int x, const char *text) static void blit_screen(void) { - gsKit_TexManager_invalidate(ps2_video->gsGlobal, ps2_video->g_screen); + gsKit_TexManager_invalidate(gsGlobal, g_screen); - gsKit_TexManager_bind(ps2_video->gsGlobal, ps2_video->g_screen); + gsKit_TexManager_bind(gsGlobal, g_screen); gskit_prim_list_sprite_texture_uv_3d( - ps2_video->gsGlobal, - ps2_video->g_screen, - ps2_video->g_screen_vertices_count, - ps2_video->g_screen_vertices + gsGlobal, + g_screen, + 2, + g_screen_vertices ); } @@ -370,11 +341,11 @@ static void blit_osd(void) static void cd_leds(void) { unsigned int reg, col_g, col_r, *p; - gsKit_TexManager_invalidate(ps2_video->gsGlobal, ps2_video->cdleds); + gsKit_TexManager_invalidate(gsGlobal, cdleds); reg = Pico_mcd->s68k_regs[0]; - p = (unsigned int *)ps2_video->cdleds->Mem; + p = (unsigned int *)cdleds->Mem; col_g = (reg & 2) ? 0x06000600 : 0; col_r = (reg & 1) ? 0x00180018 : 0; *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; @@ -388,12 +359,12 @@ static void blit_cdleds(void) { if (!osd_cdleds) return; - gsKit_TexManager_bind(ps2_video->gsGlobal, ps2_video->cdleds); + gsKit_TexManager_bind(gsGlobal, cdleds); gskit_prim_list_sprite_texture_uv_3d( - ps2_video->gsGlobal, - ps2_video->cdleds, - ps2_video->cdleds_vertices_count, - ps2_video->cdleds_vertices + gsGlobal, + cdleds, + 2, + cdleds_vertices ); } @@ -442,19 +413,14 @@ static void gsKit_flip(GSGLOBAL *gsGlobal) gsKit_setactive(gsGlobal); } -static void flipScreen(void *data, bool vsync) +static void flipScreen() { - ps2_video_t *ps2 = (ps2_video_t*)data; - - gsKit_queue_exec(ps2->gsGlobal); + gsKit_queue_exec(gsGlobal); gsKit_finish(); + gsKit_flip(gsGlobal); - if (ps2->vsync) - gsKit_sync(ps2->gsGlobal); - gsKit_flip(ps2->gsGlobal); - - gsKit_TexManager_nextFrame(ps2->gsGlobal); - gsKit_clear(ps2->gsGlobal, GS_BLACK); + gsKit_TexManager_nextFrame(gsGlobal); + gsKit_clear(gsGlobal, GS_BLACK); } @@ -464,13 +430,13 @@ void plat_video_flip(void) blit_screen(); blit_osd(); blit_cdleds(); - - flipScreen(ps2_video, ps2_video->vsync); + flipScreen(); } /* wait for start of vertical blanking */ void plat_video_wait_vsync(void) { + gsKit_sync(gsGlobal); } /* switch from emulation display to menu display */ @@ -481,20 +447,20 @@ void plat_video_menu_enter(int is_rom_loaded) /* start rendering a menu screen */ void plat_video_menu_begin(void) { - gsKit_TexManager_invalidate(ps2_video->gsGlobal, ps2_video->g_menuscreen); + gsKit_TexManager_invalidate(gsGlobal, g_menuscreen); } /* display a completed menu screen */ void plat_video_menu_end(void) { - gsKit_TexManager_bind(ps2_video->gsGlobal, ps2_video->g_menuscreen); + gsKit_TexManager_bind(gsGlobal, g_menuscreen); gskit_prim_list_sprite_texture_uv_3d( - ps2_video->gsGlobal, - ps2_video->g_menuscreen, - ps2_video->g_menuscreen_vertices_count, - ps2_video->g_menuscreen_vertices + gsGlobal, + g_menuscreen, + 2, + g_menuscreen_vertices ); - flipScreen(ps2_video, 1); + flipScreen(1); } /* terminate menu display */ @@ -553,7 +519,7 @@ void plat_init(void) in_ps2_init(in_ps2_defbinds); in_probe(); init_audio_driver(); - // plat_get_data_dir(rom_fname_loaded, sizeof(rom_fname_loaded)); + plat_get_data_dir(rom_fname_loaded, sizeof(rom_fname_loaded)); } void plat_finish(void) { @@ -669,8 +635,8 @@ void plat_video_loop_prepare(void) /* prepare for entering the emulator loop */ void pemu_loop_prep(void) { - set_g_screen_values(ps2_video); - set_cdleds_values(ps2_video); + set_g_screen_values(); + set_cdleds_values(); } /* terminate the emulator loop */ From b4a8b47113362738e86b661dc2a9ee7abc6a617c Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sat, 6 Jan 2024 00:01:22 +0100 Subject: [PATCH 22/66] Some progress about centering image --- platform/ps2/emu.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 98d2ed06f..cd5302c37 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -28,8 +28,6 @@ static int osd_buf_cnt, osd_cdleds; -static int out_x, out_y; -static int out_w, out_h; static float hscale, vscale; static struct in_default_bind in_ps2_defbinds[] = @@ -546,13 +544,11 @@ void plat_status_msg_busy_next(const char *msg) /* clear status message area */ void plat_status_msg_clear(void) { - // not needed since the screen buf is cleared through the GU + // not needed since the screen buf is cleared through the gskit_clear } /* change the audio volume setting */ -void plat_update_volume(int has_changed, int is_up) -{ -} +void plat_update_volume(int has_changed, int is_up) {} /* prepare for MD screen mode change */ void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) @@ -560,11 +556,11 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co int h43 = (col_count >= 192 ? 320 : col_count); // ugh, mind GG... int v43 = (line_count >= 192 ? Pico.m.pal ? 240 : 224 : line_count); - out_y = start_line; out_x = start_col; - out_h = line_count; out_w = col_count; - if (col_count == 248) // mind aspect ratio when blanking 1st column col_count = 256; + + g_screen_vertices[0].uv = vertex_to_UV(g_screen, start_col, start_line); + g_screen_vertices[1].uv = vertex_to_UV(g_screen, col_count, line_count); switch (currentConfig.vscaling) { case EOPT_VSCALE_FULL: From 455cecf973706ef7a6538859ca0d542ef9fe4512 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sat, 6 Jan 2024 12:43:23 +0100 Subject: [PATCH 23/66] Sound almost working --- platform/ps2/emu.c | 204 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 3 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index cd5302c37..05d7d8dd3 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "in_ps2.h" #include "../libpicofe/input.h" @@ -70,6 +71,204 @@ static int vsync_sema_id; static int32_t vsync_callback_id; static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ +/* sound stuff */ +#define SOUND_BLOCK_SIZE_NTSC (1470*2) // 1024 // 1152 +#define SOUND_BLOCK_SIZE_PAL (1764*2) +#define SOUND_BLOCK_COUNT 8 + +static short __attribute__((aligned(4))) sndBuffer[SOUND_BLOCK_SIZE_PAL*SOUND_BLOCK_COUNT + 54000/50*2]; +static short *snd_playptr = NULL, *sndBuffer_endptr = NULL; +static int samples_made = 0, samples_done = 0, samples_block = 0; +static int sound_thread_exit = 0; +static int32_t sound_sem = -1; +static uint8_t stack[0x10000] __attribute__((aligned(16))); +extern void *_gp; + +static int mp3_init(void) { return 0; } + +static void writeSound(int len) +{ + int ret; + + // printf("writeSound, len: %i\n", len); + + PicoIn.sndOut += len / 2; + /*if (PicoIn.sndOut > sndBuffer_endptr) { + memcpy((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) * 2); + PicoIn.sndOut = &sndBuffer[PicoIn.sndOut - endptr]; + lprintf("mov\n"); + } + else*/ + if (PicoIn.sndOut > sndBuffer_endptr) lprintf("snd oflow %i!\n", PicoIn.sndOut - sndBuffer_endptr); + if (PicoIn.sndOut >= sndBuffer_endptr) + PicoIn.sndOut = sndBuffer; + + // signal the snd thread + samples_made += len / 2; + if (samples_made - samples_done > samples_block*2) { + lprintf("signal, %i/%i\n", samples_done, samples_made); + ret = SignalSema(sound_sem); + //if (ret < 0) lprintf("snd signal ret %08x\n", ret); + } +} + +static int sound_thread(void *argp) +{ + int ret = 0; + + while (!sound_thread_exit) + { + if (samples_made - samples_done < samples_block) { + // wait for data (use at least 2 blocks) + //lprintf("sthr: wait... (%i)\n", samples_made - samples_done); + while (samples_made - samples_done <= samples_block*2 && !sound_thread_exit) { + printf("sthr: WaitSema\n"); + ret = WaitSema(sound_sem); + } + if (ret < 0) lprintf("sthr: WaitSema: %i\n", ret); + continue; + } + + // lprintf("sthr: got data: %i\n", samples_made - samples_done); + int buflen = samples_block * 2; + ret = (audsrv_play_audio((char *)snd_playptr, buflen) != buflen) ? -1 : 0; + printf("audsrv_play_audio ret: %i, buflen: %i\n", ret, buflen); + // ret = sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, snd_playptr); + + samples_done += samples_block; + snd_playptr += samples_block; + if (snd_playptr >= sndBuffer_endptr) + snd_playptr = sndBuffer; + // 1.5 kernel returns 0, newer ones return # of samples queued + if (ret < 0) + lprintf("sthr: audsrv_play_audio: %08x; pos %i/%i\n", ret, samples_done, samples_made); + + // shouln't happen, but just in case + if (samples_made - samples_done >= samples_block*3) { + //lprintf("sthr: block skip (%i)\n", samples_made - samples_done); + samples_done += samples_block; // skip + snd_playptr += samples_block; + } + + } + + lprintf("sthr: exit\n"); + ExitDeleteThread(); + return 0; +} + +static void sound_init(void) +{ + int thid; + int ret; + ee_sema_t sema; + ee_thread_t thread; + + sema.max_count = 1; + sema.init_count = 0; + sema.option = (u32) "sndsem"; + if ((sound_sem = CreateSema(&sema)) < 0) + return; + + thread.func = &sound_thread; + thread.stack = stack; + thread.stack_size = sizeof(stack); + thread.gp_reg = &_gp; + thread.option = (u32) "sndthread"; + thread.initial_priority = 0x12; + thid = CreateThread(&thread); + + if (thid >= 0) { + ret = StartThread(thid, NULL); + if (ret < 0) lprintf("sound_init: StartThread returned %08x\n", ret); + }else { + DeleteSema(sound_sem); + lprintf("CreateThread failed: %i\n", thid); + } +} + +void pemu_sound_start(void) { + static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; + static int mp3_init_done; + int ret, stereo; + struct audsrv_fmt_t format; + + samples_made = samples_done = 0; + + if (!(currentConfig.EmuOpt & EOPT_EN_SOUND)) + return; + + if (PicoIn.AHW & PAHW_MCD) { + // mp3... + if (!mp3_init_done) { + ret = mp3_init(); + mp3_init_done = 1; + if (ret) emu_status_msg("mp3 init failed (%i)", ret); + } + } + + if (PicoIn.sndRate > 52000 && PicoIn.sndRate < 54000) + PicoIn.sndRate = YM2612_NATIVE_RATE(); + ret = POPT_EN_FM|POPT_EN_PSG|POPT_EN_STEREO; + if (PicoIn.sndRate != PsndRate_old || (PicoIn.opt&ret) != (PicoOpt_old&ret) || Pico.m.pal != pal_old) { + PsndRerate(Pico.m.frame_count ? 1 : 0); + } + stereo=(PicoIn.opt&8)>>3; + + samples_block = Pico.m.pal ? SOUND_BLOCK_SIZE_PAL : SOUND_BLOCK_SIZE_NTSC; + printf("samples_block: %i\n", samples_block); + if (PicoIn.sndRate <= 22050) samples_block /= 2; + sndBuffer_endptr = &sndBuffer[samples_block*SOUND_BLOCK_COUNT]; + + lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", + PicoIn.sndRate, Pico.snd.len, stereo, Pico.m.pal, samples_block); + + format.bits = 16; + format.freq = PicoIn.sndRate; + format.channels = 2; + ret = audsrv_set_format(&format); + audsrv_set_volume(MAX_VOLUME); + if (ret < 0) { + lprintf("audsrv_set_format() failed: %i\n", ret); + emu_status_msg("sound init failed (%i), snd disabled", ret); + currentConfig.EmuOpt &= ~EOPT_EN_SOUND; + } else { + PicoIn.writeSound = writeSound; + memset32((int *)(void *)sndBuffer, 0, sizeof(sndBuffer)/4); + snd_playptr = sndBuffer_endptr - samples_block; + samples_made = samples_block; // send 1 empty block first.. + PicoIn.sndOut = sndBuffer; + PsndRate_old = PicoIn.sndRate; + PicoOpt_old = PicoIn.opt; + pal_old = Pico.m.pal; + } +} + +void pemu_sound_stop(void) +{ + int i; + if (samples_done == 0) + { + // if no data is written between sceAudioSRCChReserve and sceAudioSRCChRelease calls, + // we get a deadlock on next sceAudioSRCChReserve call + // so this is yet another workaround: + memset32((int *)(void *)sndBuffer, 0, samples_block*4/4); + samples_made = samples_block * 3; + SignalSema(sound_sem); + } + plat_sleep_ms(100); + samples_made = samples_done = 0; + audsrv_stop_audio(); +} + +static void sound_deinit(void) +{ + sound_thread_exit = 1; + SignalSema(sound_sem); + DeleteSema(sound_sem); + sound_sem = -1; +} + #define is_16bit_mode() \ (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X)) @@ -466,9 +665,6 @@ void plat_video_menu_leave(void) { } -void pemu_sound_start(void) {} -void pemu_sound_stop(void) {} - /* set default configuration values */ void pemu_prep_defconfig(void) { @@ -517,10 +713,12 @@ void plat_init(void) in_ps2_init(in_ps2_defbinds); in_probe(); init_audio_driver(); + sound_init(); plat_get_data_dir(rom_fname_loaded, sizeof(rom_fname_loaded)); } void plat_finish(void) { + sound_deinit(); deinit_audio_driver(); deinit_joystick_driver(false); video_deinit(); From 4abc40d56b2f9d6bb3246b8a07925262abc55557 Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 5 Feb 2024 20:14:06 +0100 Subject: [PATCH 24/66] fixes for audio and video, add psp-like scaling --- platform/common/menu_pico.c | 2 + platform/ps2/emu.c | 833 ++++++++++++++++++++---------------- platform/ps2/menu.c | 21 + platform/ps2/menu.h | 10 + platform/ps2/plat.c | 5 +- 5 files changed, 498 insertions(+), 373 deletions(-) create mode 100644 platform/ps2/menu.c create mode 100644 platform/ps2/menu.h diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index a9fc79001..78dfcc33f 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -72,6 +72,8 @@ static int menu_w, menu_h; #include #elif defined(__PSP__) #include +#elif defined(__PS2__) +#include #elif defined(PANDORA) #include #else diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 05d7d8dd3..a5de6493f 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -20,7 +20,7 @@ #include -#define OSD_FPS_X 220 +#define OSD_FPS_X (gsGlobal->Width - 80) /* turn black GS Screen */ #define GS_BLACK GS_SETREG_RGBA(0x00, 0x00, 0x00, 0x80) @@ -29,6 +29,8 @@ static int osd_buf_cnt, osd_cdleds; +static int out_x, out_y; +static int out_w, out_h; static float hscale, vscale; static struct in_default_bind in_ps2_defbinds[] = @@ -51,14 +53,18 @@ static struct in_default_bind in_ps2_defbinds[] = const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast", NULL }; const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL }; enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; +static int is_bg_frame; static GSGLOBAL *gsGlobal; static GSTEXTURE *g_menuscreen; static GSPRIMUVPOINT *g_menuscreen_vertices; +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 GSTEXTURE *osd; static uint32_t osd_vertices_count; @@ -72,84 +78,73 @@ static int32_t vsync_callback_id; static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ /* sound stuff */ -#define SOUND_BLOCK_SIZE_NTSC (1470*2) // 1024 // 1152 -#define SOUND_BLOCK_SIZE_PAL (1764*2) #define SOUND_BLOCK_COUNT 8 +#define SOUND_BUFFER_SIZE (2*54000/50*SOUND_BLOCK_COUNT) // max.rate/min.frames -static short __attribute__((aligned(4))) sndBuffer[SOUND_BLOCK_SIZE_PAL*SOUND_BLOCK_COUNT + 54000/50*2]; +static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_SIZE]; static short *snd_playptr = NULL, *sndBuffer_endptr = NULL; static int samples_made = 0, samples_done = 0, samples_block = 0; static int sound_thread_exit = 0; static int32_t sound_sem = -1; -static uint8_t stack[0x10000] __attribute__((aligned(16))); +static uint8_t stack[0x4000] __attribute__((aligned(16))); extern void *_gp; static int mp3_init(void) { return 0; } static void writeSound(int len) { - int ret; - - // printf("writeSound, len: %i\n", len); + int ret, l; PicoIn.sndOut += len / 2; - /*if (PicoIn.sndOut > sndBuffer_endptr) { - memcpy((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) * 2); - PicoIn.sndOut = &sndBuffer[PicoIn.sndOut - endptr]; - lprintf("mov\n"); - } - else*/ - if (PicoIn.sndOut > sndBuffer_endptr) lprintf("snd oflow %i!\n", PicoIn.sndOut - sndBuffer_endptr); - if (PicoIn.sndOut >= sndBuffer_endptr) + + l = PicoIn.sndOut - sndBuffer; + if (l > sizeof(sndBuffer)/2) + lprintf("ovfl %d %d\n", len, PicoIn.sndOut - sndBuffer); + if (l > samples_block * 6) { + sndBuffer_endptr = PicoIn.sndOut; PicoIn.sndOut = sndBuffer; + } + if (sndBuffer_endptr < PicoIn.sndOut) + sndBuffer_endptr = PicoIn.sndOut; // signal the snd thread samples_made += len / 2; - if (samples_made - samples_done > samples_block*2) { - lprintf("signal, %i/%i\n", samples_done, samples_made); - ret = SignalSema(sound_sem); - //if (ret < 0) lprintf("snd signal ret %08x\n", ret); - } +// lprintf("signal, %i/%i\n", samples_done, samples_made); + ret = SignalSema(sound_sem); +// if (ret < 0) lprintf("snd signal ret %08x\n", ret); } static int sound_thread(void *argp) { - int ret = 0; - while (!sound_thread_exit) { + int ret = 0; + if (samples_made - samples_done < samples_block) { // wait for data (use at least 2 blocks) - //lprintf("sthr: wait... (%i)\n", samples_made - samples_done); - while (samples_made - samples_done <= samples_block*2 && !sound_thread_exit) { - printf("sthr: WaitSema\n"); +// lprintf("sthr: wait... (%i)\n", samples_made - samples_done); + while (samples_made - samples_done < samples_block*2 && !sound_thread_exit) ret = WaitSema(sound_sem); - } if (ret < 0) lprintf("sthr: WaitSema: %i\n", ret); continue; } +// lprintf("sthr: got data: %i\n", samples_made - samples_done); + short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; + int buflen = samples_block * 2; + if (sndOut >= snd_playptr) + buflen = sndOut - snd_playptr; + else buflen = sndEnd - snd_playptr; + if (buflen > samples_block) + buflen = samples_block; + ret = audsrv_play_audio((char *)snd_playptr, buflen*2); +// if (ret != buflen*2 && ret >= 0) lprintf("sthr: play ret: %i, buflen: %i\n", ret, buflen*2); + if (ret < 0) lprintf("sthr: play: ret %08x; pos %i/%i\n", ret, samples_done, samples_made); + + samples_done += buflen; + snd_playptr += buflen; - // lprintf("sthr: got data: %i\n", samples_made - samples_done); - int buflen = samples_block * 2; - ret = (audsrv_play_audio((char *)snd_playptr, buflen) != buflen) ? -1 : 0; - printf("audsrv_play_audio ret: %i, buflen: %i\n", ret, buflen); - // ret = sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, snd_playptr); - - samples_done += samples_block; - snd_playptr += samples_block; if (snd_playptr >= sndBuffer_endptr) snd_playptr = sndBuffer; - // 1.5 kernel returns 0, newer ones return # of samples queued - if (ret < 0) - lprintf("sthr: audsrv_play_audio: %08x; pos %i/%i\n", ret, samples_done, samples_made); - - // shouln't happen, but just in case - if (samples_made - samples_done >= samples_block*3) { - //lprintf("sthr: block skip (%i)\n", samples_made - samples_done); - samples_done += samples_block; // skip - snd_playptr += samples_block; - } - } lprintf("sthr: exit\n"); @@ -162,36 +157,39 @@ static void sound_init(void) int thid; int ret; ee_sema_t sema; - ee_thread_t thread; - - sema.max_count = 1; - sema.init_count = 0; - sema.option = (u32) "sndsem"; - if ((sound_sem = CreateSema(&sema)) < 0) - return; - - thread.func = &sound_thread; - thread.stack = stack; - thread.stack_size = sizeof(stack); - thread.gp_reg = &_gp; - thread.option = (u32) "sndthread"; - thread.initial_priority = 0x12; - thid = CreateThread(&thread); - - if (thid >= 0) { + ee_thread_t thread; + + sema.max_count = 1; + sema.init_count = 0; + sema.option = (u32) "sndsem"; + if ((sound_sem = CreateSema(&sema)) < 0) + return; + audsrv_init(); + + thread.func = &sound_thread; + thread.stack = stack; + thread.stack_size = sizeof(stack); + thread.gp_reg = &_gp; + thread.option = (u32) "sndthread"; + thread.initial_priority = 40; + thid = CreateThread(&thread); + + samples_block = 22050/50; // needs to be initialized before thread start + if (thid >= 0) { ret = StartThread(thid, NULL); if (ret < 0) lprintf("sound_init: StartThread returned %08x\n", ret); - }else { - DeleteSema(sound_sem); + ChangeThreadPriority(0, 64); + } else { + DeleteSema(sound_sem); lprintf("CreateThread failed: %i\n", thid); - } + } } void pemu_sound_start(void) { - static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; + static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; static int mp3_init_done; int ret, stereo; - struct audsrv_fmt_t format; + struct audsrv_fmt_t format; samples_made = samples_done = 0; @@ -215,49 +213,35 @@ void pemu_sound_start(void) { } stereo=(PicoIn.opt&8)>>3; - samples_block = Pico.m.pal ? SOUND_BLOCK_SIZE_PAL : SOUND_BLOCK_SIZE_NTSC; - printf("samples_block: %i\n", samples_block); - if (PicoIn.sndRate <= 22050) samples_block /= 2; - sndBuffer_endptr = &sndBuffer[samples_block*SOUND_BLOCK_COUNT]; + samples_block = PicoIn.sndRate * (stereo ? 2 : 1) / (Pico.m.pal ? 50 : 60); lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", PicoIn.sndRate, Pico.snd.len, stereo, Pico.m.pal, samples_block); format.bits = 16; - format.freq = PicoIn.sndRate; - format.channels = 2; + format.freq = PicoIn.sndRate; + format.channels = 2; ret = audsrv_set_format(&format); - audsrv_set_volume(MAX_VOLUME); + audsrv_set_volume(MAX_VOLUME); if (ret < 0) { lprintf("audsrv_set_format() failed: %i\n", ret); emu_status_msg("sound init failed (%i), snd disabled", ret); currentConfig.EmuOpt &= ~EOPT_EN_SOUND; } else { PicoIn.writeSound = writeSound; - memset32((int *)(void *)sndBuffer, 0, sizeof(sndBuffer)/4); - snd_playptr = sndBuffer_endptr - samples_block; - samples_made = samples_block; // send 1 empty block first.. - PicoIn.sndOut = sndBuffer; + snd_playptr = PicoIn.sndOut = sndBuffer_endptr = sndBuffer; + PsndRate_old = PicoIn.sndRate; PicoOpt_old = PicoIn.opt; pal_old = Pico.m.pal; } + ret = audsrv_play_audio((char *)snd_playptr, 4); } void pemu_sound_stop(void) { - int i; - if (samples_done == 0) - { - // if no data is written between sceAudioSRCChReserve and sceAudioSRCChRelease calls, - // we get a deadlock on next sceAudioSRCChReserve call - // so this is yet another workaround: - memset32((int *)(void *)sndBuffer, 0, samples_block*4/4); - samples_made = samples_block * 3; - SignalSema(sound_sem); - } - plat_sleep_ms(100); samples_made = samples_done = 0; + plat_sleep_ms(100); audsrv_stop_audio(); } @@ -270,192 +254,297 @@ static void sound_deinit(void) } #define is_16bit_mode() \ - (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X)) + (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X) || is_bg_frame) static int vsync_handler(void) { - iSignalSema(vsync_sema_id); + iSignalSema(vsync_sema_id); + + ExitHandler(); + return 0; +} + +/* Copy of gsKit_sync_flip, but without the 'flip' */ +static void gsKit_sync(GSGLOBAL *gsGlobal) +{ + if (!gsGlobal->FirstFrame) + WaitSema(vsync_sema_id); + + while (PollSema(vsync_sema_id) >= 0); +} + +/* Copy of gsKit_sync_flip, but without the 'sync' */ +static void gsKit_flip(GSGLOBAL *gsGlobal) +{ + if (!gsGlobal->FirstFrame) + { + if (gsGlobal->DoubleBuffering == GS_SETTING_ON) + { + GS_SET_DISPFB2(gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192, + gsGlobal->Width / 64, gsGlobal->PSM, 0, 0); + + gsGlobal->ActiveBuffer ^= 1; + } + } + + gsKit_setactive(gsGlobal); +} + +static void flipScreen() +{ + gsKit_flip(gsGlobal); - ExitHandler(); - return 0; + gsKit_TexManager_nextFrame(gsGlobal); } -static void set_g_menuscreen_values() + +static void set_g_menuscreen_values(void) { - if (g_menuscreen != NULL) { - free(g_menuscreen->Mem); - free(g_menuscreen); - free(g_menubg_ptr); - free(g_menuscreen_vertices); - } - g_menuscreen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - size_t g_menuscreenSize = gsKit_texture_size_ee(gsGlobal->Width, gsGlobal->Height, GS_PSM_CT16); - g_menuscreen->Width = gsGlobal->Width; - g_menuscreen->Height = gsGlobal->Height; - g_menuscreen->PSM = GS_PSM_CT16; - g_menuscreen->Mem = malloc(g_menuscreenSize); + size_t g_menuscreenSize = gsKit_texture_size_ee(gsGlobal->Width, gsGlobal->Height, GS_PSM_CT16); - g_menubg_ptr = (uint8_t *)malloc(g_menuscreenSize); + g_menuscreen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); + g_menuscreen->Mem = malloc(g_menuscreenSize); + g_menuscreen_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); - g_menuscreen_w = g_menuscreen->Width; - g_menuscreen_h = g_menuscreen->Height; - g_menuscreen_pp = g_menuscreen->Width; - g_menuscreen_ptr = g_menuscreen->Mem; + g_menuscreen->Width = gsGlobal->Width; + g_menuscreen->Height = gsGlobal->Height; + g_menuscreen->PSM = GS_PSM_CT16; - g_menubg_src_w = g_menuscreen->Width; - g_menubg_src_h = g_menuscreen->Height; - g_menubg_src_pp = g_menuscreen->Width; + g_menuscreen_w = g_menuscreen->Width; + g_menuscreen_h = g_menuscreen->Height; + g_menuscreen_pp = g_menuscreen->Width; + g_menuscreen_ptr = g_menuscreen->Mem; - g_menuscreen_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); - - g_menuscreen_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 2); + g_menuscreen_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 2); g_menuscreen_vertices[0].uv = vertex_to_UV(g_menuscreen, 0, 0); g_menuscreen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - g_menuscreen_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, g_menuscreen->Width, g_menuscreen->Height, 2); - g_menuscreen_vertices[1].uv = vertex_to_UV(g_menuscreen, g_menuscreen->Width, g_menuscreen->Height); - g_menuscreen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + g_menuscreen_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, g_menuscreen->Width, g_menuscreen->Height, 2); + g_menuscreen_vertices[1].uv = vertex_to_UV(g_menuscreen, g_menuscreen->Width, g_menuscreen->Height); + g_menuscreen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); } void set_g_screen_values() { - if (g_screen != NULL) { - free(g_screen->Mem); - free(g_screen); - free(g_screen_vertices); - } - g_screen = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - size_t g_screenSize = gsKit_texture_size_ee(328, 256, GS_PSM_CT16); - g_screen->Width = 328; - g_screen->Height = 256; - g_screen->PSM = GS_PSM_CT16; - g_screen->Mem = (uint32_t *)malloc(g_screenSize); - - g_screen_width = 328; - g_screen_height = 256; - g_screen_ppitch = 328; - g_screen_ptr = g_screen->Mem; - - g_screen_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); - - g_screen_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 0); - g_screen_vertices[0].uv = vertex_to_UV(g_screen, 0, 0); - g_screen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - - g_screen_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, gsGlobal->Width, gsGlobal->Height, 0); - g_screen_vertices[1].uv = vertex_to_UV(g_screen, g_screen->Width, g_screen->Height); - g_screen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - - if (is_16bit_mode()) - PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2); - else - PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch); + size_t g_screenSize = gsKit_texture_size_ee(328, 256, GS_PSM_CT16); + int i; + + g_screen_palette = malloc(gsKit_texture_size_ee(16, 16, GS_PSM_CT16)); + 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]->Width = 328; + g_screens[i]->Height = 256; + g_screens[i]->PSM = GS_PSM_CT16; + g_screens[i]->Filter = GS_FILTER_LINEAR; + + g_screens[i]->Clut = g_screen_palette; + g_screens[i]->ClutPSM = GS_PSM_CT16; + } + g_screen = g_screens[g_screen_index]; + g_screen_ptr = g_screen->Mem; + + g_screen_width = 328; + g_screen_height = 256; + g_screen_ppitch = 328; + + g_screen_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 0); + g_screen_vertices[0].uv = vertex_to_UV(g_screen, 0, 0); + g_screen_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + g_screen_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, gsGlobal->Width, gsGlobal->Height, 0); + g_screen_vertices[1].uv = vertex_to_UV(g_screen, g_screen->Width, g_screen->Height); + g_screen_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); } void set_cdleds_values() { - if (cdleds != NULL) { - free(cdleds->Mem); - free(cdleds); - free(cdleds_vertices); - } - cdleds = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - size_t cdledsSize = gsKit_texture_size_ee(14, 5, GS_PSM_CT16); - cdleds->Width = 14; - cdleds->Height = 5; - cdleds->PSM = GS_PSM_CT16; - cdleds->Mem = (uint32_t *)malloc(cdledsSize); - - cdleds_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); - - cdleds_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 4, 1, 1); - cdleds_vertices[0].uv = vertex_to_UV(cdleds, 0, 0); - cdleds_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - - cdleds_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, cdleds->Width, cdleds->Height, 1); - cdleds_vertices[1].uv = vertex_to_UV(cdleds, cdleds->Width, cdleds->Height); - cdleds_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + 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_vertices = (GSPRIMUVPOINT *)calloc(2, sizeof(GSPRIMUVPOINT)); + + cdleds->Width = 14; + cdleds->Height = 5; + cdleds->PSM = GS_PSM_CT16; + + cdleds_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 4, 1, 1); + cdleds_vertices[0].uv = vertex_to_UV(cdleds, 0, 0); + cdleds_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + + cdleds_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, cdleds->Width, cdleds->Height, 1); + cdleds_vertices[1].uv = vertex_to_UV(cdleds, cdleds->Width, cdleds->Height); + cdleds_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); } void set_osd_values() { - if (osd != NULL) { - free(osd->Mem); - free(osd); - free(osd_vertices); - } - osd = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); - size_t osdSize = gsKit_texture_size_ee(512, 8, GS_PSM_CT16); - osd->Width = 512; - osd->Height = 8; - osd->PSM = GS_PSM_CT16; - osd->Mem = (uint32_t *)malloc(osdSize); - - osd_vertices_count = 2; - osd_vertices = (GSPRIMUVPOINT *)calloc(osd_vertices_count, sizeof(GSPRIMUVPOINT)); - - osd_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 1); - osd_vertices[0].uv = vertex_to_UV(osd, 0, 0); - osd_vertices[0].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); - - osd_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, osd->Width, osd->Height, 1); - osd_vertices[1].uv = vertex_to_UV(osd, osd->Width, osd->Height); - osd_vertices[1].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); + size_t osdSize = gsKit_texture_size_ee(gsGlobal->Width, 8, GS_PSM_CT16); + int num_osds = 4, i; + + osd = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); + osd->Mem = (uint32_t *)malloc(osdSize); + + osd_vertices_count = 2*num_osds; + osd_vertices = (GSPRIMUVPOINT *)calloc(osd_vertices_count, sizeof(GSPRIMUVPOINT)); + + osd->Width = gsGlobal->Width; + osd->Height = 8; + osd->PSM = GS_PSM_CT16; + + for (i = 0; i < 2*num_osds; i++) + osd_vertices[i].rgbaq = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0); } static void video_init(void) { - ee_sema_t sema; + ee_sema_t sema; + + sema.init_count = 0; + sema.max_count = 1; + sema.option = 0; - sema.init_count = 0; - sema.max_count = 1; - sema.option = 0; + vsync_sema_id = CreateSema(&sema); - vsync_sema_id = CreateSema(&sema); + gsGlobal = gsKit_init_global(); +// gsGlobal->Mode = GS_MODE_NTSC; +// gsGlobal->Height = 448; - gsGlobal = gsKit_init_global(); - gsGlobal->Mode = GS_MODE_NTSC; - gsGlobal->Height = 448; + gsGlobal->PSM = GS_PSM_CT16; + gsGlobal->PSMZ = GS_PSMZ_16S; + gsGlobal->ZBuffering = GS_SETTING_OFF; + gsGlobal->DoubleBuffering = GS_SETTING_ON; + gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; + gsGlobal->Dithering = GS_SETTING_OFF; - gsGlobal->PSM = GS_PSM_CT24; - gsGlobal->PSMZ = GS_PSMZ_16S; - gsGlobal->ZBuffering = GS_SETTING_OFF; - gsGlobal->DoubleBuffering = GS_SETTING_ON; - gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; - gsGlobal->Dithering = GS_SETTING_OFF; + dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); + dmaKit_chan_init(DMA_CHANNEL_GIF); - dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); - dmaKit_chan_init(DMA_CHANNEL_GIF); + gsKit_set_clamp(gsGlobal, GS_CMODE_REPEAT); - gsKit_set_clamp(gsGlobal, GS_CMODE_REPEAT); + gsKit_vram_clear(gsGlobal); + gsKit_init_screen(gsGlobal); + gsKit_TexManager_init(gsGlobal); + gsKit_mode_switch(gsGlobal, GS_ONESHOT); + gsKit_clear(gsGlobal, GS_BLACK); + vsync = 0; + vsync_callback_id = gsKit_add_vsync_handler(vsync_handler); - gsKit_vram_clear(gsGlobal); - gsKit_init_screen(gsGlobal); - gsKit_TexManager_init(gsGlobal); - gsKit_mode_switch(gsGlobal, GS_ONESHOT); - gsKit_clear(gsGlobal, GS_BLACK); - vsync = 0; - vsync_callback_id = gsKit_add_vsync_handler(vsync_handler); + set_g_screen_values(); + set_g_menuscreen_values(); + set_osd_values(); + set_cdleds_values(); - set_g_menuscreen_values(); + g_menubg_ptr = (uint8_t *)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; } static void video_deinit(void) { - free(g_menuscreen->Mem); - free(g_menuscreen); - free(g_menuscreen_vertices); - free(g_menubg_ptr); + free(g_screens[0]->Mem); + free(g_screens[0]); + free(g_screens[1]->Mem); + free(g_screens[1]); + free(g_screen_vertices); + free(g_screen_palette); - gsKit_clear(gsGlobal, GS_BLACK); - gsKit_vram_clear(gsGlobal); - gsKit_deinit_global(gsGlobal); - gsKit_remove_vsync_handler(vsync_callback_id); + free(g_menuscreen->Mem); + free(g_menuscreen); + free(g_menuscreen_vertices); + free(g_menubg_ptr); - if (vsync_sema_id >= 0) - DeleteSema(vsync_sema_id); + free(osd->Mem); + free(osd); + free(osd_vertices); + + free(cdleds->Mem); + free(cdleds); + free(cdleds_vertices); + + gsKit_clear(gsGlobal, GS_BLACK); + gsKit_vram_clear(gsGlobal); + gsKit_deinit_global(gsGlobal); + gsKit_remove_vsync_handler(vsync_callback_id); + + if (vsync_sema_id >= 0) + DeleteSema(vsync_sema_id); +} + +static void set_scaling_params(void) +{ + int width, height, xoffs, yoffs; + int u[2], v[2]; + + height = (int)(out_h * vscale + 0.5); + width = (int)(out_w * hscale + 0.5); + + if (width & 1) width++; // make even + if (height & 1) height++; + + if (width >= gsGlobal->Width) { + u[0] = out_x + (width-gsGlobal->Width)/2; + u[1] = out_x + out_w - (width-gsGlobal->Width)/2 - 1; + width = gsGlobal->Width; + xoffs = 0; + } else { + u[0] = out_x; + u[1] = out_x + out_w; + xoffs = gsGlobal->Width/2 - width/2; + } + + if (height >= gsGlobal->Height) { + v[0] = out_y + (height-gsGlobal->Height)/2; + v[1] = out_y + out_h - (height-gsGlobal->Height)/2; + height = gsGlobal->Height; + yoffs = 0; + } else { + v[0] = out_y; + v[1] = out_y + out_h; + yoffs = gsGlobal->Height/2 - height/2; + } + + if (xoffs < 0) xoffs = 0; + if (yoffs < 0) yoffs = 0; + g_screen_vertices[0].xyz2 = vertex_to_XYZ2(gsGlobal, xoffs, yoffs, 0); + g_screen_vertices[1].xyz2 = vertex_to_XYZ2(gsGlobal, xoffs + width, yoffs + height, 0); + + if (!is_16bit_mode()) { + // 8-bit modes have an 8 px overlap area on the left + u[0] += 8; u[1] += 8; + } + g_screen_vertices[0].uv = vertex_to_UV(g_screen, u[0], v[0]); + g_screen_vertices[1].uv = vertex_to_UV(g_screen, u[1], v[1]); + +// lprintf("set_scaling_params: wxh = %ix%i\n",gsGlobal->Width,gsGlobal->Height); +// lprintf("offs: %i, %i wh: %i, %i\n", xoffs, yoffs, width, height); +// lprintf("uv0, uv1: %i, %i; %i, %i\n", u[0], v[0], u[1], v[1]); +} + +static void make_ps2_palette(void) +{ + PicoDrawUpdateHighPal(); + + // Rotate CLUT. PS2 is special since entries in CLUT are not in sequence. + unsigned short int *pal=(void *)g_screen_palette; + int i; + + for (i = 0; i < 256; i+=8) { + if ((i&0x18) == 0x08) + memcpy(pal+i,Pico.est.HighPal+i+8,16); + else if ((i&0x18) == 0x10) + memcpy(pal+i,Pico.est.HighPal+i-8,16); + else + memcpy(pal+i,Pico.est.HighPal+i,16); + } } static int get_renderer(void) { + if (is_bg_frame) + return RT_16BIT; if (PicoIn.AHW & PAHW_32X) return currentConfig.renderer32x; else @@ -480,7 +569,6 @@ static void change_renderer(int diff) static void apply_renderer(void) { PicoIn.opt &= ~(POPT_ALT_RENDERER|POPT_EN_SOFTSCALE); - PicoIn.opt |= POPT_DIS_32C_BORDER; switch (get_renderer()) { case RT_16BIT: @@ -496,57 +584,65 @@ static void apply_renderer(void) } } -static void osd_text(int x, const char *text) +static void blit_screen(void) { - // int len = strlen(text) * 8; - // int *p, h; - // void *tmp = g_screen_ptr; - // printf("osd_text, text: %s\n", text); + if (!is_16bit_mode() && Pico.m.dirtyPal) + make_ps2_palette(); - // g_screen_ptr = osd_buf; - // for (h = 0; h < 8; h++) { - // p = (int *) (osd_buf+x+512*h); - // p = (int *) ((int)p & ~3); // align - // memset32_uncached(p, 0, len/2); - // } - // emu_text_out16(x, 0, text); - // g_screen_ptr = tmp; + g_screen->PSM = is_16bit_mode() ? GS_PSM_CT16 : GS_PSM_T8; + g_screen->Filter = (currentConfig.filter ? GS_FILTER_LINEAR : GS_FILTER_NEAREST); - // osd_buf_x[osd_buf_cnt] = x; - // osd_buf_l[osd_buf_cnt] = len; - // osd_buf_cnt ++; + gsKit_TexManager_bind(gsGlobal, g_screen); + gskit_prim_list_sprite_texture_uv_3d(gsGlobal, g_screen, 2, g_screen_vertices); } -static void blit_screen(void) +static void osd_text(int x, const char *text) { - gsKit_TexManager_invalidate(gsGlobal, g_screen); + void *old_ptr = g_screen_ptr; + int old_pitch = g_screen_ppitch; + + int len = strlen(text) * 8; + u16 *osd_buf = osd->Mem; + int *p, h; + + g_screen_ptr = osd_buf; + g_screen_ppitch = gsGlobal->Width; + for (h = 0; h < 8; h++) { + p = (int *) (osd_buf + x + gsGlobal->Width*h); + p = (int *) ((int)p & ~3); // align + memset32_uncached(p, 0, len/2); + } + emu_text_out16(x, 0, text); + g_screen_ptr = old_ptr; + g_screen_ppitch = old_pitch; - gsKit_TexManager_bind(gsGlobal, g_screen); - gskit_prim_list_sprite_texture_uv_3d( - gsGlobal, - g_screen, - 2, - g_screen_vertices - ); + osd_vertices[osd_buf_cnt].xyz2 = vertex_to_XYZ2(gsGlobal, x, gsGlobal->Height-8, 1); + osd_vertices[osd_buf_cnt].uv = vertex_to_UV(osd, x, 0); + osd_vertices[osd_buf_cnt+1].xyz2 = vertex_to_XYZ2(gsGlobal, x+len, gsGlobal->Height, 1); + osd_vertices[osd_buf_cnt+1].uv = vertex_to_UV(osd, x+len, 8); + osd_buf_cnt += 2; } static void blit_osd(void) { - + gsKit_TexManager_bind(gsGlobal, osd); + while (osd_buf_cnt > 0) { + osd_buf_cnt -= 2; + gskit_prim_list_sprite_texture_uv_3d(gsGlobal, osd, 2, osd_vertices+osd_buf_cnt); + } } static void cd_leds(void) { - unsigned int reg, col_g, col_r, *p; - gsKit_TexManager_invalidate(gsGlobal, cdleds); + unsigned int reg, col_g, col_r, *p; reg = Pico_mcd->s68k_regs[0]; p = (unsigned int *)cdleds->Mem; col_g = (reg & 2) ? 0x06000600 : 0; col_r = (reg & 1) ? 0x00180018 : 0; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += gsGlobal->Width/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += gsGlobal->Width/2 - 12/2; *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; osd_cdleds = 1; @@ -554,126 +650,131 @@ static void cd_leds(void) static void blit_cdleds(void) { - if (!osd_cdleds) return; + if (!osd_cdleds) return; - gsKit_TexManager_bind(gsGlobal, cdleds); - gskit_prim_list_sprite_texture_uv_3d( - gsGlobal, - cdleds, - 2, - cdleds_vertices - ); + gsKit_TexManager_bind(gsGlobal, cdleds); + gskit_prim_list_sprite_texture_uv_3d(gsGlobal, cdleds, 2, cdleds_vertices); } static void draw_pico_ptr(void) { - // unsigned char *p = (unsigned char *)g_screen_ptr + 8; + int x = pico_pen_x, y = pico_pen_y, offs; + int pp = g_screen_ppitch; - // // only if pen enabled and for 8bit mode - // if (pico_inp_mode == 0 || is_16bit_mode()) return; + x = (x * out_w * ((1ULL<<32) / 320)) >> 32; + y = (y * out_h * ((1ULL<<32) / 224)) >> 32; - // p += 512 * (pico_pen_y + PICO_PEN_ADJUST_Y); - // p += pico_pen_x + PICO_PEN_ADJUST_X; - // if (!(Pico.video.reg[12]&1) && !(PicoIn.opt & POPT_DIS_32C_BORDER)) - // p += 32; + offs = g_screen_ppitch * (out_y+y) + (out_x+x); - // p[ -1] = 0xe0; p[ 0] = 0xf0; p[ 1] = 0xe0; - // p[ 511] = 0xf0; p[ 512] = 0xf0; p[ 513] = 0xf0; - // p[1023] = 0xe0; p[1024] = 0xf0; p[1025] = 0xe0; -} + if (is_16bit_mode()) { + unsigned short *p = (unsigned short *)g_screen_ptr + offs; -static void vidResetMode(void) {} + p[ -1] = 0x0000; p[ 0] = 0x001f; p[ 1] = 0x0000; + p[ pp-1] = 0x001f; p[ pp] = 0x001f; p[ pp+1] = 0x001f; + p[2*pp-1] = 0x0000; p[2*pp] = 0x001f; p[2*pp+1] = 0x0000; + } else { + unsigned char *p = (unsigned char *)g_screen_ptr + offs + 8; -/* Copy of gsKit_sync_flip, but without the 'flip' */ -static void gsKit_sync(GSGLOBAL *gsGlobal) + p[ -1] = 0xe0; p[ 0] = 0xf0; p[ 1] = 0xe0; + p[ pp-1] = 0xf0; p[ pp] = 0xf0; p[ pp+1] = 0xf0; + p[2*pp-1] = 0xe0; p[2*pp] = 0xf0; p[2*pp+1] = 0xe0; + } +} + +static void vidResetMode(void) { - if (!gsGlobal->FirstFrame) - WaitSema(vsync_sema_id); + set_scaling_params(); - while (PollSema(vsync_sema_id) >= 0); + Pico.m.dirtyPal = 1; } -/* Copy of gsKit_sync_flip, but without the 'sync' */ -static void gsKit_flip(GSGLOBAL *gsGlobal) +/* finalize rendering a frame */ +void pemu_finalize_frame(const char *fps, const char *notice) { - if (!gsGlobal->FirstFrame) - { - if (gsGlobal->DoubleBuffering == GS_SETTING_ON) - { - GS_SET_DISPFB2(gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192, - gsGlobal->Width / 64, gsGlobal->PSM, 0, 0); + int emu_opt = currentConfig.EmuOpt; - gsGlobal->ActiveBuffer ^= 1; - } - } + if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) + if (pico_inp_mode) draw_pico_ptr(); - gsKit_setactive(gsGlobal); -} + osd_buf_cnt = 0; + if (notice) osd_text(4, notice); + if (emu_opt & 2) osd_text(OSD_FPS_X, fps); -static void flipScreen() -{ - gsKit_queue_exec(gsGlobal); - gsKit_finish(); - gsKit_flip(gsGlobal); + osd_cdleds = 0; + if ((emu_opt & 0x400) && (PicoIn.AHW & PAHW_MCD)) + cd_leds(); - gsKit_TexManager_nextFrame(gsGlobal); - gsKit_clear(gsGlobal, GS_BLACK); + FlushCache(WRITEBACK_DCACHE); } - /* display a completed frame buffer and prepare a new render buffer */ void plat_video_flip(void) { - blit_screen(); - blit_osd(); + gsKit_TexManager_invalidate(gsGlobal, osd); + gsKit_TexManager_invalidate(gsGlobal, cdleds); + gsKit_TexManager_invalidate(gsGlobal, g_screen); + + gsKit_finish(); + flipScreen(); + + gsKit_clear(gsGlobal, GS_BLACK); + blit_screen(); + blit_osd(); blit_cdleds(); - flipScreen(); + gsKit_queue_exec(gsGlobal); + + g_screen_index ^= 1; + g_screen = g_screens[g_screen_index]; + g_screen_ptr = g_screen->Mem; + + plat_video_set_buffer(g_screen_ptr); } /* wait for start of vertical blanking */ void plat_video_wait_vsync(void) { - gsKit_sync(gsGlobal); + gsKit_sync(gsGlobal); } /* switch from emulation display to menu display */ void plat_video_menu_enter(int is_rom_loaded) { + g_screen_ptr = NULL; } /* start rendering a menu screen */ void plat_video_menu_begin(void) { - gsKit_TexManager_invalidate(gsGlobal, g_menuscreen); } /* display a completed menu screen */ void plat_video_menu_end(void) { - gsKit_TexManager_bind(gsGlobal, g_menuscreen); - gskit_prim_list_sprite_texture_uv_3d( - gsGlobal, - g_menuscreen, - 2, - g_menuscreen_vertices - ); - flipScreen(1); + gsKit_TexManager_bind(gsGlobal, g_menuscreen); + gskit_prim_list_sprite_texture_uv_3d( gsGlobal, g_menuscreen, 2, g_menuscreen_vertices); + gsKit_queue_exec(gsGlobal); + gsKit_finish(); + gsKit_TexManager_invalidate(gsGlobal, g_menuscreen); + + flipScreen(); } /* terminate menu display */ void plat_video_menu_leave(void) { + g_screen_ptr = g_screen->Mem; + plat_video_set_buffer(g_screen_ptr); } /* set default configuration values */ void pemu_prep_defconfig(void) { - defaultConfig.s_PsndRate = 44100; + defaultConfig.s_PsndRate = 22050; defaultConfig.s_PicoCDBuffers = 64; defaultConfig.filter = EOPT_FILTER_BILINEAR; // bilinear filtering defaultConfig.scaling = EOPT_SCALE_43; defaultConfig.vscaling = EOPT_VSCALE_FULL; - defaultConfig.renderer = RT_16BIT; + defaultConfig.renderer = RT_8BIT_ACC; defaultConfig.renderer32x = RT_8BIT_ACC; defaultConfig.EmuOpt |= EOPT_SHOW_RTC; } @@ -681,47 +782,24 @@ void pemu_prep_defconfig(void) /* check configuration for inconsistencies */ void pemu_validate_config(void) { - if (currentConfig.gamma < -4 || currentConfig.gamma > 16) - currentConfig.gamma = 0; - if (currentConfig.gamma2 < 0 || currentConfig.gamma2 > 2) - currentConfig.gamma2 = 0; -} - -/* finalize rendering a frame */ -void pemu_finalize_frame(const char *fps, const char *notice) -{ - int emu_opt = currentConfig.EmuOpt; - - if (PicoIn.AHW & PAHW_PICO) - draw_pico_ptr(); - - osd_buf_cnt = 0; - if (notice) osd_text(4, notice); - if (emu_opt & 2) osd_text(OSD_FPS_X, fps); - - osd_cdleds = 0; - if ((emu_opt & 0x400) && (PicoIn.AHW & PAHW_MCD)) - cd_leds(); - - FlushCache(WRITEBACK_DCACHE); } -void plat_init(void) +void plat_init(void) { - video_init(); - init_joystick_driver(false); - in_ps2_init(in_ps2_defbinds); - in_probe(); - init_audio_driver(); - sound_init(); - plat_get_data_dir(rom_fname_loaded, sizeof(rom_fname_loaded)); + video_init(); + init_joystick_driver(false); + in_ps2_init(in_ps2_defbinds); + in_probe(); + init_audio_driver(); + sound_init(); + plat_get_data_dir(rom_fname_loaded, sizeof(rom_fname_loaded)); } void plat_finish(void) { - sound_deinit(); - deinit_audio_driver(); - deinit_joystick_driver(false); - video_deinit(); + sound_deinit(); + deinit_audio_driver(); + deinit_joystick_driver(false); + video_deinit(); } /* display emulator status messages before holding emulation */ @@ -754,37 +832,38 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co int h43 = (col_count >= 192 ? 320 : col_count); // ugh, mind GG... int v43 = (line_count >= 192 ? Pico.m.pal ? 240 : 224 : line_count); + out_y = start_line; out_x = start_col; + out_h = line_count; out_w = col_count; + if (col_count == 248) // mind aspect ratio when blanking 1st column col_count = 256; - - g_screen_vertices[0].uv = vertex_to_UV(g_screen, start_col, start_line); - g_screen_vertices[1].uv = vertex_to_UV(g_screen, col_count, line_count); switch (currentConfig.vscaling) { case EOPT_VSCALE_FULL: line_count = v43; - vscale = (float)270/line_count; + vscale = (float)gsGlobal->Height/line_count; break; case EOPT_VSCALE_NOBORDER: - vscale = (float)270/line_count; + vscale = (float)gsGlobal->Height/line_count; break; default: vscale = 1; break; } + hscale = vscale * (gsGlobal->Aspect == GS_ASPECT_16_9 ? (4./3)/(16./9) : 1); switch (currentConfig.scaling) { case EOPT_SCALE_43: - hscale = (vscale*h43)/col_count; + hscale = (hscale*h43)/col_count; break; case EOPT_SCALE_STRETCH: - hscale = (vscale*h43/2 + 480/2)/col_count; + hscale = (hscale*h43/2 + gsGlobal->Width/2)/col_count; break; case EOPT_SCALE_WIDE: - hscale = (float)480/col_count; + hscale = (float)gsGlobal->Width/col_count; break; default: - hscale = vscale; + // hscale = vscale, computed before switch break; } @@ -794,11 +873,15 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co /* render one frame in RGB */ void pemu_forced_frame(int no_scale, int do_emu) { + is_bg_frame = 1; Pico.m.dirtyPal = 1; if (!no_scale) no_scale = currentConfig.scaling == EOPT_SCALE_NONE; emu_cmn_forced_frame(no_scale, do_emu, g_screen_ptr); + + g_menubg_src_ptr = g_screen_ptr; + is_bg_frame = 0; } /* change the platform output rendering */ @@ -819,8 +902,17 @@ void plat_video_toggle_renderer(int change, int is_menu_call) emu_status_msg(renderer_names[get_renderer()]); } +/* set the buffer for emulator output rendering */ +void plat_video_set_buffer(void *buf) +{ + if (is_16bit_mode()) + PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2); + else + PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch); +} + /* prepare for emulator output rendering */ -void plat_video_loop_prepare(void) +void plat_video_loop_prepare(void) { apply_renderer(); vidResetMode(); @@ -829,12 +921,11 @@ void plat_video_loop_prepare(void) /* prepare for entering the emulator loop */ void pemu_loop_prep(void) { - set_g_screen_values(); - set_cdleds_values(); } /* terminate the emulator loop */ void pemu_loop_end(void) { - pemu_sound_stop(); -} \ No newline at end of file + pemu_sound_stop(); + pemu_forced_frame(0, 1); +} diff --git a/platform/ps2/menu.c b/platform/ps2/menu.c new file mode 100644 index 000000000..c44164487 --- /dev/null +++ b/platform/ps2/menu.c @@ -0,0 +1,21 @@ + +static const char *men_vscaling_opts[] = { "OFF", "fullscreen", "borderless", NULL }; +static const char *men_hscaling_opts[] = { "1:1", "4:3", "extended", "fullwidth", NULL }; +static const char *men_filter_opts[] = { "nearest", "bilinear", NULL }; + +#define MENU_OPTIONS_GFX \ + mee_enum ("Vertical scaling", MA_OPT_VSCALING, currentConfig.vscaling, men_vscaling_opts), \ + mee_enum ("Aspect ratio", MA_OPT_SCALING, currentConfig.scaling, men_hscaling_opts), \ + mee_enum ("Scaler type", MA_OPT3_FILTERING, currentConfig.filter, men_filter_opts), \ + mee_onoff ("Wait for vsync", MA_OPT3_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC), \ + +#define MENU_OPTIONS_ADV + +static menu_entry e_menu_sms_options[]; +static menu_entry e_menu_keyconfig[]; + +void psp_menu_init(void) +{ + me_enable(e_menu_sms_options, MA_SMSOPT_GHOSTING, 0); + me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0); +} diff --git a/platform/ps2/menu.h b/platform/ps2/menu.h new file mode 100644 index 000000000..d5aa60820 --- /dev/null +++ b/platform/ps2/menu.h @@ -0,0 +1,10 @@ + +void menu_loop(void); +int menu_loop_tray(void); +void menu_romload_prepare(const char *rom_name); +void menu_romload_end(void); + + +#define CONFIGURABLE_KEYS (PBTN_UP|PBTN_LEFT|PBTN_RIGHT|PBTN_DOWN|PBTN_L|PBTN_R|PBTN_TRIANGLE|PBTN_CIRCLE|PBTN_X|PBTN_SQUARE|PBTN_START| \ + PBTN_NUB_UP|PBTN_NUB_RIGHT|PBTN_NUB_DOWN|PBTN_NUB_LEFT|PBTN_NOTE) + diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index 7b6d22677..d645b5ef7 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -19,7 +19,8 @@ #include "../libpicofe/plat.h" -struct plat_target plat_target = {}; +static int sound_rates[] = { 11025, 22050, 44100, -1 }; +struct plat_target plat_target = { .sound_rates = sound_rates }; static void reset_IOP() { SifInitRpc(0); @@ -205,4 +206,4 @@ void lprintf(const char *fmt, ...) va_end(vl); } -void plat_debug_cat(char *str) {} \ No newline at end of file +void plat_debug_cat(char *str) {} From 3eb1d645852e3142d30b7bf1ce2b00d8d3b35041 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 14 Feb 2024 23:41:24 +0100 Subject: [PATCH 25/66] ps2, minor audio and gfx fixes --- platform/ps2/emu.c | 16 +++++++--------- platform/ps2/plat.c | 2 +- platform/psp/plat.c | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index a5de6493f..a423f6ec0 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -78,7 +78,7 @@ static int32_t vsync_callback_id; static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ /* sound stuff */ -#define SOUND_BLOCK_COUNT 8 +#define SOUND_BLOCK_COUNT 6 #define SOUND_BUFFER_SIZE (2*54000/50*SOUND_BLOCK_COUNT) // max.rate/min.frames static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_SIZE]; @@ -100,7 +100,7 @@ static void writeSound(int len) l = PicoIn.sndOut - sndBuffer; if (l > sizeof(sndBuffer)/2) lprintf("ovfl %d %d\n", len, PicoIn.sndOut - sndBuffer); - if (l > samples_block * 6) { + if (l > samples_block * (SOUND_BLOCK_COUNT-2)) { sndBuffer_endptr = PicoIn.sndOut; PicoIn.sndOut = sndBuffer; } @@ -111,11 +111,12 @@ static void writeSound(int len) samples_made += len / 2; // lprintf("signal, %i/%i\n", samples_done, samples_made); ret = SignalSema(sound_sem); -// if (ret < 0) lprintf("snd signal ret %08x\n", ret); + if (ret < 0) lprintf("snd signal ret %08x\n", ret); } static int sound_thread(void *argp) { + lprintf("sthr: start\n"); while (!sound_thread_exit) { int ret = 0; @@ -130,14 +131,13 @@ static int sound_thread(void *argp) } // lprintf("sthr: got data: %i\n", samples_made - samples_done); short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; - int buflen = samples_block * 2; + int buflen = sndEnd - snd_playptr; if (sndOut >= snd_playptr) buflen = sndOut - snd_playptr; - else buflen = sndEnd - snd_playptr; if (buflen > samples_block) buflen = samples_block; ret = audsrv_play_audio((char *)snd_playptr, buflen*2); -// if (ret != buflen*2 && ret >= 0) lprintf("sthr: play ret: %i, buflen: %i\n", ret, buflen*2); + if (ret != buflen*2 && ret >= 0) lprintf("sthr: play ret: %i, buflen: %i\n", ret, buflen*2); if (ret < 0) lprintf("sthr: play: ret %08x; pos %i/%i\n", ret, samples_done, samples_made); samples_done += buflen; @@ -241,7 +241,7 @@ void pemu_sound_start(void) { void pemu_sound_stop(void) { samples_made = samples_done = 0; - plat_sleep_ms(100); + plat_sleep_ms(200); audsrv_stop_audio(); } @@ -336,8 +336,6 @@ void set_g_screen_values() { g_screens[i]->Width = 328; g_screens[i]->Height = 256; - g_screens[i]->PSM = GS_PSM_CT16; - g_screens[i]->Filter = GS_FILTER_LINEAR; g_screens[i]->Clut = g_screen_palette; g_screens[i]->ClutPSM = GS_PSM_CT16; diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index d645b5ef7..17cfdc082 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -115,7 +115,7 @@ unsigned int plat_get_ticks_ms(void) ret = (unsigned)tv.tv_sec * 1000; /* approximate /= 1000 */ - ret += ((unsigned)tv.tv_usec * 4195) >> 22; + ret += ((unsigned)tv.tv_usec * 4194) >> 22; return ret; } diff --git a/platform/psp/plat.c b/platform/psp/plat.c index b23bc386b..64ae04325 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -181,7 +181,7 @@ unsigned int plat_get_ticks_ms(void) ret = (unsigned)tv.tv_sec * 1000; /* approximate /= 1000 */ - ret += ((unsigned)tv.tv_usec * 4195) >> 22; + ret += ((unsigned)tv.tv_usec * 4194) >> 22; return ret; } From dedf7fa7d5577577f8029ccdd5aceb6207488355 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 14 Feb 2024 23:42:50 +0100 Subject: [PATCH 26/66] ps2, kludge for timer bugs in ps2sdk --- platform/ps2/plat.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/platform/ps2/plat.c b/platform/ps2/plat.c index 17cfdc082..253e18784 100644 --- a/platform/ps2/plat.c +++ b/platform/ps2/plat.c @@ -134,16 +134,38 @@ unsigned int plat_get_ticks_us(void) return ret; } -/* sleep for some time in ms */ -void plat_sleep_ms(int ms) +/* Unfortunately the SetTimerAlarm function in ps2sdk has a bug which makes it + * waiting much too long in some cases. For now, replaced by SetAlarm and a + * polling loop with RotateThreadReadyQueue for yielding to other threads. + */ + +static void alarm_cb(int id, unsigned short time, void *arg) { - usleep(ms * 1000); + iWakeupThread((s32)arg); } /* sleep for some time in us */ void plat_wait_till_us(unsigned int us_to) { - usleep(us_to - plat_get_ticks_us()); + // TODO hsync depends on NTSC/PAL (15750/15625 Hz), it however doesn't + // matter if it falls a bit short, the while loop will catch the rest + unsigned hsyncs = (us_to - plat_get_ticks_us()) * 15620 / 1000000; + + if (hsyncs && SetAlarm(hsyncs, alarm_cb, (void *)GetThreadId()) >= 0) + SleepThread(); + while ((int)(us_to - plat_get_ticks_us()) > 0) + RotateThreadReadyQueue(0); + +// unsigned int ticks = plat_get_ticks_us(); +// if ((int)(us_to - ticks) > 0) +// usleep(us_to - ticks); +} + +/* sleep for some time in ms */ +void plat_sleep_ms(int ms) +{ + plat_wait_till_us(plat_get_ticks_us() + ms*1000); +// usleep(ms * 1000); } /* wait until some event occurs, or timeout */ From fd604aa720093043caa374b0d8a3404e3b3cbe5f Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 15 Feb 2024 23:08:24 +0100 Subject: [PATCH 27/66] ps2, kludge for handling audsrv shortcomings --- platform/ps2/emu.c | 107 ++++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index a423f6ec0..8632fc068 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -79,9 +79,10 @@ static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ /* sound stuff */ #define SOUND_BLOCK_COUNT 6 -#define SOUND_BUFFER_SIZE (2*54000/50*SOUND_BLOCK_COUNT) // max.rate/min.frames +#define SOUND_BUFFER_CHUNK (2*54000/50) // max.rate/min.frames, stereo -static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_SIZE]; +static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_CHUNK*SOUND_BLOCK_COUNT]; +static short __attribute__((aligned(4))) nulBuffer[SOUND_BUFFER_CHUNK]; static short *snd_playptr = NULL, *sndBuffer_endptr = NULL; static int samples_made = 0, samples_done = 0, samples_block = 0; static int sound_thread_exit = 0; @@ -91,6 +92,23 @@ extern void *_gp; static int mp3_init(void) { return 0; } +/* audsrv in ps2sdk has shortcomings: + * - it has a bug which prevents it from discerning "ringbuffer empty" from + * "ringbuffer full", which leads to audio not stopped if all queued samples + * have been played. Hence, it repeats the complete ringbuffer over and again. + * - on audsrv_set_format the ringbuffer is preset to be about 40% filled, + * regardless of the data in the buffer at that moment. Old data is played out + * if audio play is started. + * - stopping audio play is keeping any remaining samples in the buffer, which + * are played first after the next audio play. There's no method to clear the + * ringbuffer. + * + * To cope with this, audio samples are always pushed to audsrv to prevent the + * ringbuffer from emptying, even in the menu. This also avoids stopping audio. + * Since silence is played in the menu, the behaviour of set_format when leaving + * the menu is covered since the buffer is filled with silence at that time. + */ + static void writeSound(int len) { int ret, l; @@ -106,45 +124,72 @@ static void writeSound(int len) } if (sndBuffer_endptr < PicoIn.sndOut) sndBuffer_endptr = PicoIn.sndOut; + samples_made += len / 2; // signal the snd thread - samples_made += len / 2; -// lprintf("signal, %i/%i\n", samples_done, samples_made); - ret = SignalSema(sound_sem); - if (ret < 0) lprintf("snd signal ret %08x\n", ret); +// ret = SignalSema(sound_sem); +// if (ret < 0) lprintf("snd signal ret %08x\n", ret); } static int sound_thread(void *argp) { lprintf("sthr: start\n"); + while (!sound_thread_exit) { int ret = 0; - if (samples_made - samples_done < samples_block) { - // wait for data (use at least 2 blocks) -// lprintf("sthr: wait... (%i)\n", samples_made - samples_done); - while (samples_made - samples_done < samples_block*2 && !sound_thread_exit) - ret = WaitSema(sound_sem); - if (ret < 0) lprintf("sthr: WaitSema: %i\n", ret); - continue; + // curb the sample queue to prevent it from filling + while (samples_made - samples_done > 4*samples_block) { + short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; + + int buflen = sndEnd - snd_playptr; + if (sndOut > snd_playptr) + buflen = sndOut - snd_playptr; + if (buflen > samples_made - samples_done - 4*samples_block) + buflen = samples_made - samples_done - 4*samples_block; + + samples_done += buflen; + snd_playptr += buflen; + if (snd_playptr >= sndBuffer_endptr) + snd_playptr -= sndBuffer_endptr - sndBuffer; + } + + // queue samples to audsrv, minimum 2 frames + // if there aren't enough samlpes, queue silence + int queued = audsrv_queued()/2; + while (queued < 2*samples_block) { + short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; + + // compute sample chunk size + int buflen = sndEnd - snd_playptr; + if (sndOut > snd_playptr) + buflen = sndOut - snd_playptr; + if (buflen > samples_made - samples_done) + buflen = samples_made - samples_done; + if (buflen > 4*samples_block - queued) + buflen = 4*samples_block - queued; + + // play audio + if (buflen > 0) { + ret = audsrv_play_audio((char *)snd_playptr, buflen*2); + + samples_done += buflen; + snd_playptr += buflen; + if (snd_playptr >= sndBuffer_endptr) + snd_playptr -= sndBuffer_endptr - sndBuffer; + } else { + buflen = 3*samples_block - queued; + ret = audsrv_play_audio((char *)nulBuffer, buflen*2); + } + if (ret != buflen*2 && ret >= 0) lprintf("sthr: play ret: %i, buflen: %i\n", ret, buflen*2); + if (ret < 0) lprintf("sthr: play: ret %08x; pos %i/%i\n", ret, samples_done, samples_made); + + queued = audsrv_queued()/2; } -// lprintf("sthr: got data: %i\n", samples_made - samples_done); - short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; - int buflen = sndEnd - snd_playptr; - if (sndOut >= snd_playptr) - buflen = sndOut - snd_playptr; - if (buflen > samples_block) - buflen = samples_block; - ret = audsrv_play_audio((char *)snd_playptr, buflen*2); - if (ret != buflen*2 && ret >= 0) lprintf("sthr: play ret: %i, buflen: %i\n", ret, buflen*2); - if (ret < 0) lprintf("sthr: play: ret %08x; pos %i/%i\n", ret, samples_done, samples_made); - - samples_done += buflen; - snd_playptr += buflen; - - if (snd_playptr >= sndBuffer_endptr) - snd_playptr = sndBuffer; + + ret = WaitSema(sound_sem); + if (ret < 0) lprintf("sthr: WaitSema failed (%d)\n", ret); } lprintf("sthr: exit\n"); @@ -235,14 +280,13 @@ void pemu_sound_start(void) { PicoOpt_old = PicoIn.opt; pal_old = Pico.m.pal; } - ret = audsrv_play_audio((char *)snd_playptr, 4); + audsrv_play_audio((char *)snd_playptr, 2*2); } void pemu_sound_stop(void) { samples_made = samples_done = 0; plat_sleep_ms(200); - audsrv_stop_audio(); } static void sound_deinit(void) @@ -259,6 +303,7 @@ static void sound_deinit(void) static int vsync_handler(void) { iSignalSema(vsync_sema_id); + iSignalSema(sound_sem); ExitHandler(); return 0; From e2b9687b3f3130a1d8c3ef54b5042f610f95f28f Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 17 Feb 2024 19:37:11 +0100 Subject: [PATCH 28/66] ps2, more audio fixes --- platform/ps2/emu.c | 123 ++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 56 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 8632fc068..d5385930e 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -78,15 +78,16 @@ static int32_t vsync_callback_id; static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ /* sound stuff */ -#define SOUND_BLOCK_COUNT 6 -#define SOUND_BUFFER_CHUNK (2*54000/50) // max.rate/min.frames, stereo +#define SOUND_BLOCK_COUNT 7 +#define SOUND_BUFFER_CHUNK (2*54000/50) // max.rate/min.frames in stereo static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_CHUNK*SOUND_BLOCK_COUNT]; static short __attribute__((aligned(4))) nulBuffer[SOUND_BUFFER_CHUNK]; static short *snd_playptr = NULL, *sndBuffer_endptr = NULL; -static int samples_made = 0, samples_done = 0, samples_block = 0; -static int sound_thread_exit = 0; -static int32_t sound_sem = -1; +static int samples_made, samples_done, samples_block; + +static int sound_thread_exit = 0, sound_stopped = 1; +static int32_t sound_sem = -1, sound_mutex = -1; static uint8_t stack[0x4000] __attribute__((aligned(16))); extern void *_gp; @@ -113,22 +114,41 @@ static void writeSound(int len) { int ret, l; - PicoIn.sndOut += len / 2; + if (samples_made - samples_done < samples_block * (SOUND_BLOCK_COUNT-3)) { + samples_made += len / 2; + PicoIn.sndOut += len / 2; + } else + lprintf("ovfl %d\n", samples_made - samples_done); + if (sndBuffer_endptr < PicoIn.sndOut) + sndBuffer_endptr = PicoIn.sndOut; l = PicoIn.sndOut - sndBuffer; if (l > sizeof(sndBuffer)/2) - lprintf("ovfl %d %d\n", len, PicoIn.sndOut - sndBuffer); + lprintf("ovrn %d %d\n", len, PicoIn.sndOut - sndBuffer); if (l > samples_block * (SOUND_BLOCK_COUNT-2)) { sndBuffer_endptr = PicoIn.sndOut; PicoIn.sndOut = sndBuffer; } - if (sndBuffer_endptr < PicoIn.sndOut) - sndBuffer_endptr = PicoIn.sndOut; - samples_made += len / 2; // signal the snd thread -// ret = SignalSema(sound_sem); -// if (ret < 0) lprintf("snd signal ret %08x\n", ret); + SignalSema(sound_sem); +} + +static void resetSound() +{ + struct audsrv_fmt_t format; + int stereo = (PicoIn.opt&8)>>3; + int ret; + + format.bits = 16; + format.freq = PicoIn.sndRate; + format.channels = stereo ? 2 : 1; + ret = audsrv_set_format(&format); + if (ret < 0) { + lprintf("audsrv_set_format() failed: %i\n", ret); + emu_status_msg("sound init failed (%i), snd disabled", ret); + currentConfig.EmuOpt &= ~EOPT_EN_SOUND; + } } static int sound_thread(void *argp) @@ -137,26 +157,11 @@ static int sound_thread(void *argp) while (!sound_thread_exit) { - int ret = 0; - - // curb the sample queue to prevent it from filling - while (samples_made - samples_done > 4*samples_block) { - short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; - - int buflen = sndEnd - snd_playptr; - if (sndOut > snd_playptr) - buflen = sndOut - snd_playptr; - if (buflen > samples_made - samples_done - 4*samples_block) - buflen = samples_made - samples_done - 4*samples_block; - - samples_done += buflen; - snd_playptr += buflen; - if (snd_playptr >= sndBuffer_endptr) - snd_playptr -= sndBuffer_endptr - sndBuffer; - } + int ret = WaitSema(sound_mutex); + if (ret < 0) lprintf("sthr: WaitSema mutex failed (%d)\n", ret); // queue samples to audsrv, minimum 2 frames - // if there aren't enough samlpes, queue silence + // if there aren't enough samples, queue silence int queued = audsrv_queued()/2; while (queued < 2*samples_block) { short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; @@ -167,8 +172,8 @@ static int sound_thread(void *argp) buflen = sndOut - snd_playptr; if (buflen > samples_made - samples_done) buflen = samples_made - samples_done; - if (buflen > 4*samples_block - queued) - buflen = 4*samples_block - queued; + if (buflen > 3*samples_block - queued) + buflen = 3*samples_block - queued; // play audio if (buflen > 0) { @@ -179,17 +184,23 @@ static int sound_thread(void *argp) if (snd_playptr >= sndBuffer_endptr) snd_playptr -= sndBuffer_endptr - sndBuffer; } else { - buflen = 3*samples_block - queued; + buflen = (3*samples_block - queued) & ~1; + while (buflen > sizeof(nulBuffer)/2) { + audsrv_play_audio((char *)nulBuffer, sizeof(nulBuffer)); + buflen -= sizeof(nulBuffer)/2; + } ret = audsrv_play_audio((char *)nulBuffer, buflen*2); } - if (ret != buflen*2 && ret >= 0) lprintf("sthr: play ret: %i, buflen: %i\n", ret, buflen*2); + if (ret != buflen*2 && ret > 0) lprintf("sthr: play ret: %i, buflen: %i\n", ret, buflen*2); if (ret < 0) lprintf("sthr: play: ret %08x; pos %i/%i\n", ret, samples_done, samples_made); + if (ret == 0) resetSound(); queued = audsrv_queued()/2; } + SignalSema(sound_mutex); ret = WaitSema(sound_sem); - if (ret < 0) lprintf("sthr: WaitSema failed (%d)\n", ret); + if (ret < 0) lprintf("sthr: WaitSema sound failed (%d)\n", ret); } lprintf("sthr: exit\n"); @@ -209,6 +220,11 @@ static void sound_init(void) sema.option = (u32) "sndsem"; if ((sound_sem = CreateSema(&sema)) < 0) return; + sema.max_count = 1; + sema.init_count = 1; + sema.option = (u32) "sndmutex"; + if ((sound_mutex = CreateSema(&sema)) < 0) + return; audsrv_init(); thread.func = &sound_thread; @@ -234,7 +250,6 @@ void pemu_sound_start(void) { static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; static int mp3_init_done; int ret, stereo; - struct audsrv_fmt_t format; samples_made = samples_done = 0; @@ -250,43 +265,38 @@ void pemu_sound_start(void) { } } + ret = WaitSema(sound_mutex); + if (ret < 0) lprintf("WaitSema mutex failed (%d)\n", ret); + if (PicoIn.sndRate > 52000 && PicoIn.sndRate < 54000) PicoIn.sndRate = YM2612_NATIVE_RATE(); ret = POPT_EN_FM|POPT_EN_PSG|POPT_EN_STEREO; if (PicoIn.sndRate != PsndRate_old || (PicoIn.opt&ret) != (PicoOpt_old&ret) || Pico.m.pal != pal_old) { PsndRerate(Pico.m.frame_count ? 1 : 0); } - stereo=(PicoIn.opt&8)>>3; - + stereo = (PicoIn.opt&8)>>3; samples_block = PicoIn.sndRate * (stereo ? 2 : 1) / (Pico.m.pal ? 50 : 60); lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", PicoIn.sndRate, Pico.snd.len, stereo, Pico.m.pal, samples_block); - format.bits = 16; - format.freq = PicoIn.sndRate; - format.channels = 2; - ret = audsrv_set_format(&format); - audsrv_set_volume(MAX_VOLUME); - if (ret < 0) { - lprintf("audsrv_set_format() failed: %i\n", ret); - emu_status_msg("sound init failed (%i), snd disabled", ret); - currentConfig.EmuOpt &= ~EOPT_EN_SOUND; - } else { - PicoIn.writeSound = writeSound; - snd_playptr = PicoIn.sndOut = sndBuffer_endptr = sndBuffer; + resetSound(); + PicoIn.writeSound = writeSound; + snd_playptr = PicoIn.sndOut = sndBuffer_endptr = sndBuffer; - PsndRate_old = PicoIn.sndRate; - PicoOpt_old = PicoIn.opt; - pal_old = Pico.m.pal; - } + PsndRate_old = PicoIn.sndRate; + PicoOpt_old = PicoIn.opt; + pal_old = Pico.m.pal; + + sound_stopped = 0; audsrv_play_audio((char *)snd_playptr, 2*2); + SignalSema(sound_mutex); } void pemu_sound_stop(void) { + sound_stopped = 1; samples_made = samples_done = 0; - plat_sleep_ms(200); } static void sound_deinit(void) @@ -303,7 +313,8 @@ static void sound_deinit(void) static int vsync_handler(void) { iSignalSema(vsync_sema_id); - iSignalSema(sound_sem); + if (sound_stopped) + iSignalSema(sound_sem); ExitHandler(); return 0; From a0abaf2adab530c58c4869a2219c8eaf5c0b270d Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 20 Feb 2024 22:04:13 +0100 Subject: [PATCH 29/66] ps2, minor fixes --- platform/ps2/Makefile | 26 +++++++++++++++----------- platform/ps2/emu.c | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/platform/ps2/Makefile b/platform/ps2/Makefile index 42ba39d6f..a0e20095c 100644 --- a/platform/ps2/Makefile +++ b/platform/ps2/Makefile @@ -6,22 +6,26 @@ $(error need VER) endif endif +include ../../config.mak + ../../tools/textfilter: ../../tools/textfilter.c make -C ../../tools/ textfilter readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog ../../tools/textfilter ../base_readme.txt $@ PS2 -# ? -rel: ../../PicoDrive readme.txt ../game_def.cfg - mkdir -p PicoDrive/skin/ - cp $^ PicoDrive/ - cp ../../skin/* PicoDrive/skin/ - zip -9 -r ../../PicoDrive_ps2_$(VER).zip PicoDrive - rm -rf PicoDrive - mkdir bin_to_cso_mp3 - cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/ - zip -9 -r ../../PicoDrive_ps2_$(VER).zip bin_to_cso_mp3 - rm -rf bin_to_cso_mp3 +PicoDrive: ../../PicoDrive + $(STRIP) $^ -o $@ + +PicoDrive.elf: PicoDrive + ps2-packer $^ $@ +rel: PicoDrive.elf readme.txt ../game_def.cfg + mkdir -p out/PicoDrive/skin/ out/bin_to_cso_mp3 + cp $^ out/PicoDrive/ + cp ../../skin/* out/PicoDrive/skin/ + #mkdir -p out/bin_to_cso_mp3 + #cp ../../tools/bin_to_cso_mp3/* out/bin_to_cso_mp3/ + cd out && zip -9 -r ../../../PicoDrive_ps2_$(VER).zip * + rm -rf out diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index d5385930e..e738fba4b 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -114,7 +114,7 @@ static void writeSound(int len) { int ret, l; - if (samples_made - samples_done < samples_block * (SOUND_BLOCK_COUNT-3)) { + if (samples_made - samples_done <= samples_block * (SOUND_BLOCK_COUNT-3)) { samples_made += len / 2; PicoIn.sndOut += len / 2; } else From d97d056c462d4ddf62349c11cc6b1eee0e947aa8 Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 20 Feb 2024 22:05:33 +0100 Subject: [PATCH 30/66] core md, assert z80 vint for complete scanline --- pico/memory.c | 37 ++++++++++++++++++------------------- pico/pico_cmn.c | 9 +++++++-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index cf2db5ba8..c2a40f70b 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -678,7 +678,7 @@ static u32 PicoRead8_z80(u32 a) if (((Pico.m.z80Run & 1) || Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); // open bus. Pulled down if MegaCD2 is attached. - return 0; + return (PicoIn.AHW & PAHW_MCD ? 0 : d); } if ((a & 0x4000) == 0x0000) { @@ -755,13 +755,13 @@ u32 PicoRead8_io(u32 a) d ^= d << 6; if ((a & 0xfc00) == 0x1000) { - // bit8 seems to be readable in this range - if (!(a & 1)) - d &= ~0x01; - if ((a & 0xff01) == 0x1100) { // z80 busreq (verified) - d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; - elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc); + // bit8 seems to be readable in this range + if (!(a & 1)) { + d &= ~0x01; + d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; + elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc); + } } goto end; } @@ -788,9 +788,8 @@ u32 PicoRead16_io(u32 a) // bit8 seems to be readable in this range if ((a & 0xfc00) == 0x1000) { - d &= ~0x0100; - if ((a & 0xff00) == 0x1100) { // z80 busreq + d &= ~0x0100; d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8; elprintf(EL_BUSREQ, "get_zrun: %04x [%u] @%06x", d, SekCyclesDone(), SekPc); } @@ -855,22 +854,22 @@ void PicoWrite16_io(u32 a, u32 d) // TODO: verify if lower byte goes to PSG on word writes u32 PicoRead8_vdp(u32 a) { + u32 d = 0; if ((a & 0x00f0) == 0x0000) { switch (a & 0x0d) { - case 0x00: return PicoVideoRead8DataH(0); - case 0x01: return PicoVideoRead8DataL(0); - case 0x04: return PicoVideoRead8CtlH(0); - case 0x05: return PicoVideoRead8CtlL(0); + case 0x00: d = PicoVideoRead8DataH(0); break; + case 0x01: d = PicoVideoRead8DataL(0); break; + case 0x04: d = PicoVideoRead8CtlH(0); break; + case 0x05: d = PicoVideoRead8CtlL(0); break; case 0x08: - case 0x0c: return PicoVideoRead8HV_H(0); + case 0x0c: d = PicoVideoRead8HV_H(0); break; case 0x09: - case 0x0d: return PicoVideoRead8HV_L(0); + case 0x0d: d = PicoVideoRead8HV_L(0); break; } - } - - elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); - return 0; + } else + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + return d; } static u32 PicoRead16_vdp(u32 a) diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index d51477f1a..29fc82ceb 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -250,9 +250,10 @@ static int PicoFrameHints(void) SekInterrupt(6); } - if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) { + // assert Z80 interrupt for one scanline even in busrq hold (Teddy Blues) + if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) { elprintf(EL_INTS, "zint"); - z80_int(); + z80_int_assert(1); } // Run scanline: @@ -262,6 +263,10 @@ static int PicoFrameHints(void) if (PicoLineHook) PicoLineHook(); pevt_log_m68k_o(EVT_NEXT_LINE); + if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) + PicoSyncZ80(Pico.t.m68c_aim); + z80_int_assert(0); + // === VBLANK === lines = Pico.m.pal ? 313 : 262; for (y++; y < lines - 1; y++) From 7f3b89a7f224cb4f37b03209ceef134469ada748 Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 20 Feb 2024 22:22:23 +0100 Subject: [PATCH 31/66] ci, use available processor cores --- .github/workflows/ci.yml | 80 ++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe8d360ea..50847c340 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ jobs: build-linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install dependencies @@ -14,16 +14,16 @@ jobs: - name: configure run: DUMP_CONFIG_LOG=1 ./configure - name: make - run: make -j2 + run: make -j$(getconf _NPROCESSORS_ONLN) build-libretro: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: make - run: LDFLAGS=-Wl,--no-undefined make -j2 -f Makefile.libretro + run: LDFLAGS=-Wl,--no-undefined make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.libretro build-gp2x: @@ -32,7 +32,7 @@ jobs: permissions: packages: read steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -40,11 +40,11 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=gph - make -j2 PLATFORM_MP3=0 + make -j$(getconf _NPROCESSORS_ONLN) PLATFORM_MP3=0 make -C platform/gp2x rel VER=$ver mv PicoDrive_$ver.zip PicoDrive-gph_$ver.zip - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: GP2X path: PicoDrive-gph_*.zip @@ -53,7 +53,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-pandora steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -61,11 +61,11 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=pandora - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) make -C platform/pandora rel VER=$ver mv platform/pandora/PicoDrive_*.pnd . - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Pandora path: PicoDrive_*.pnd @@ -77,7 +77,7 @@ jobs: - name: build environment run: | apk add git gcc g++ zip - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -86,10 +86,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=psp - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) make -C platform/psp rel VER=$ver - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: PSP path: PicoDrive_psp_*.zip @@ -101,7 +101,7 @@ jobs: - name: build environment run: | apk add build-base cmake git zip make - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -110,10 +110,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=ps2 - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) make -C platform/ps2 rel VER=$ver - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: PS2 path: PicoDrive_ps2_*.zip @@ -125,7 +125,7 @@ jobs: packages: read container: ghcr.io/irixxxx/toolchain-dingux steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -133,10 +133,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=dingux - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive-dge.zip PicoDrive-dge-$ver.zip - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Dingux path: PicoDrive-dge*.zip @@ -145,7 +145,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-opendingux steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -153,10 +153,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=opendingux-gcw0 - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-gcw0-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: GCW0 path: PicoDrive-gcw0*.opk @@ -165,7 +165,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-opendingux steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -173,10 +173,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=opendingux - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-opendingux-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Opendingux path: PicoDrive-opendingux*.opk @@ -187,7 +187,7 @@ jobs: packages: read container: ghcr.io/irixxxx/toolchain-miyoo steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -195,10 +195,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=miyoo - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive-miyoo.zip PicoDrive-miyoo-$ver.zip - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Miyoo path: PicoDrive-miyoo*.zip @@ -207,7 +207,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-retrofw steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -215,10 +215,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=retrofw - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-retrofw-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: RetroFW path: PicoDrive-retrofw*.opk @@ -227,7 +227,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-odbeta-gcw0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -235,10 +235,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=odbeta - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-odbeta-gcw0-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ODbeta gcw0 path: PicoDrive-odbeta-*.opk @@ -247,7 +247,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-odbeta-lepus steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -255,10 +255,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=odbeta - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-odbeta-lepus-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ODbeta lepus path: PicoDrive-odbeta-*.opk @@ -267,7 +267,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-odbeta-rs90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -275,10 +275,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=odbeta - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-odbeta-rg99-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ODbeta rg99 path: PicoDrive-odbeta-*.opk From d89e9fb04a0ba37f8fb943707794032dcc1408d4 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 21 Feb 2024 19:10:44 +0100 Subject: [PATCH 32/66] core, fix arm asm regression (bg color DMA crash) --- pico/draw_arm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico/draw_arm.S b/pico/draw_arm.S index 2b1b2e4f8..c01439aa4 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -1631,7 +1631,7 @@ PicoDoHighPal555_end: .global FinalizeLine555 FinalizeLine555: - ldr r3, [r11, #OFS_EST_rendstatus] + ldr r3, [r2, #OFS_EST_rendstatus] mov r0, r2 tst r3, #PDRAW_BGC_DMA bne BgcDMA From bfe516c3a94ab9cc604c73771ea5d8908522d0dd Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 21 Feb 2024 19:12:10 +0100 Subject: [PATCH 33/66] core, system detection by extension in zip files --- pico/media.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pico/media.c b/pico/media.c index 7c147b2f1..63d3d9979 100644 --- a/pico/media.c +++ b/pico/media.c @@ -138,16 +138,18 @@ static int detect_media(const char *fname, const unsigned char *rom, unsigned in extension_check: /* probably some headerless thing. Maybe check the extension after all. */ + ext_ptr = pmf && *pmf->ext ? pmf->ext : ext; + for (i = 0; i < ARRAY_SIZE(md_exts); i++) - if (strcasecmp(ext, md_exts[i]) == 0) + if (strcasecmp(ext_ptr, md_exts[i]) == 0) goto looks_like_md; for (i = 0; i < ARRAY_SIZE(sms_exts); i++) - if (strcasecmp(ext, sms_exts[i]) == 0) + if (strcasecmp(ext_ptr, sms_exts[i]) == 0) goto looks_like_sms; for (i = 0; i < ARRAY_SIZE(pico_exts); i++) - if (strcasecmp(ext, pico_exts[i]) == 0) + if (strcasecmp(ext_ptr, pico_exts[i]) == 0) goto looks_like_pico; /* If everything else fails, make a guess on the reset vector */ From ad43165afc30cda2600da40f52e95a77cdf5b884 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 22 Feb 2024 21:01:37 +0100 Subject: [PATCH 34/66] core, fix z80 irq handling, reset defaults (cz80, drz80) --- cpu/DrZ80/drz80.S | 20 ++++++++++++++------ cpu/cz80/cz80.c | 2 ++ cpu/cz80/cz80_op.c | 11 +---------- cpu/cz80/cz80_opED.c | 31 ++++++++++++------------------- pico/pico_int.h | 2 +- pico/z80if.c | 5 +++-- 6 files changed, 33 insertions(+), 38 deletions(-) diff --git a/cpu/DrZ80/drz80.S b/cpu/DrZ80/drz80.S index edcebb8ba..37e6e8840 100644 --- a/cpu/DrZ80/drz80.S +++ b/cpu/DrZ80/drz80.S @@ -855,7 +855,8 @@ z80_xmap_rebase_sp: strb \reg,[z80sp,#-1]! .else mov r0,\reg - sub z80sp,z80sp,#2 + subs z80sp,z80sp,#2 + @ addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 .endif @@ -872,7 +873,8 @@ z80_xmap_rebase_sp: strb r1,[z80sp,#-1]! .else mov r0,\reg,lsr #16 - sub z80sp,z80sp,#2 + subs z80sp,z80sp,#2 + @ addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 .endif @@ -1472,7 +1474,7 @@ DoInterrupt: ;@ r0 == z80if stmfd sp!,{r2,lr} - tst r0,#4 ;@ check halt + tst r0,#Z80_HALT ;@ check halt addne z80pc,z80pc,#1 ldrb r1,[cpucontext,#z80im] @@ -1503,7 +1505,8 @@ DoInterrupt_mode0: strb r1,[z80sp,#-1]! strb r0,[z80sp,#-1]! .else - sub z80sp,z80sp,#2 + subs z80sp,z80sp,#2 + @ addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 ldr r2,[cpucontext, #z80irqvector] @@ -1577,7 +1580,9 @@ DoInterrupt_end: ;@ interupt accepted so callback irq interface ldr r0,[cpucontext, #z80irqcallback] tst r0,r0 - streqb r0,[cpucontext,#z80irq] ;@ default handling + ldreqb r0,[cpucontext,#z80irq] ;@ default handling + biceq r0,r0,#1 + streqb r0,[cpucontext,#z80irq] ldmeqfd sp!,{r2,pc} stmfd sp!,{r3,r12} mov lr,pc @@ -5758,7 +5763,10 @@ opcode_F_3: ldrb r1,[cpucontext,#z80if] bic r1,r1,#(Z80_IF1)|(Z80_IF2) strb r1,[cpucontext,#z80if] - fetch 4 + + ldrb r0,[z80pc],#1 + eatcycles 4 + ldr pc,[opcodes, r0, lsl #2] ;@CALL P,NN opcode_F_4: tst z80f,#1<R, 0, (FPTR)&CPU->BasePC - (FPTR)&CPU->R); + Cz80_Set_Reg(CPU, CZ80_FA, 0xffff); + Cz80_Set_Reg(CPU, CZ80_SP, 0xffff); Cz80_Set_Reg(CPU, CZ80_PC, 0); } diff --git a/cpu/cz80/cz80_op.c b/cpu/cz80/cz80_op.c index cf3062e26..566782cfd 100644 --- a/cpu/cz80/cz80_op.c +++ b/cpu/cz80/cz80_op.c @@ -711,15 +711,6 @@ switch (Opcode) USE_CYCLES(4) if (!zIFF1) { - zIFF1 = zIFF2 = (1 << 2); - while (GET_OP() == 0xfb) - { - USE_CYCLES(4) - PC++; -#if CZ80_EMULATE_R_EXACTLY - zR++; -#endif - } if (CPU->IRQState) { CPU->Status |= CZ80_HAS_INT; @@ -727,7 +718,7 @@ switch (Opcode) CPU->ICount = 0; } } - else zIFF2 = (1 << 2); + zIFF1 = zIFF2 = (1 << 2); goto Cz80_Exec_nocheck; /*----------------------------------------- diff --git a/cpu/cz80/cz80_opED.c b/cpu/cz80/cz80_opED.c index 71f7dbce5..844d91eec 100644 --- a/cpu/cz80/cz80_opED.c +++ b/cpu/cz80/cz80_opED.c @@ -407,36 +407,29 @@ switch (Opcode) RET(8) /*----------------------------------------- - RETN + RETI/RETN -----------------------------------------*/ - OPED(0x45): // RETN; - OPED(0x55): // RETN; - OPED(0x65): // RETN; - OPED(0x75): // RETN; + // works the same, but Z80 PIO can detect the opcode + OPED(0x45): // RETN + OPED(0x55): // RETN + OPED(0x65): // RETN + OPED(0x75): // RETN + + OPED(0x4d): // RETI + OPED(0x5d): // RETI + OPED(0x6d): // RETI + OPED(0x7d): // RETI POP_16(res); SET_PC(res); if (!zIFF1 && zIFF2) { - zIFF1 = (1 << 2); if (CPU->IRQState) { CPU->Status |= CZ80_HAS_INT; } } - else zIFF1 = zIFF2; - RET(10) - -/*----------------------------------------- - RETI ------------------------------------------*/ - - OPED(0x4d): // RETI - OPED(0x5d): // RETI - OPED(0x6d): // RETI - OPED(0x7d): // RETI - POP_16(res); - SET_PC(res); + zIFF1 = zIFF2; RET(10) /*----------------------------------------- diff --git a/pico/pico_int.h b/pico/pico_int.h index 86259cd75..a3c875676 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -166,7 +166,7 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) ((cycles) - DrZ80Run(&drZ80, cycles)) #define z80_run_nr(cycles) DrZ80Run(&drZ80, cycles) #define z80_int() drZ80.Z80_IRQ = 1 -#define z80_int_assert(a) drZ80.Z80_IRQ = (a) +#define z80_int_assert(a) drZ80.Z80_IRQ = (a ? 2 : 0) #define z80_nmi() drZ80.Z80IF |= 8 #define z80_cyclesLeft drZ80.cycles diff --git a/pico/z80if.c b/pico/z80if.c index 7fbfc3421..35710cba2 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -112,10 +112,11 @@ void z80_reset(void) drZ80.Z80IF = 0; drZ80.z80irqvector = 0xff0000; // RST 38h drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1; + drZ80.Z80SP = 0xffff; + drZ80.Z80F = 0xff; + drZ80.Z80A = 0xff << 24; // others not changed, undefined on cold boot /* - drZ80.Z80F = (1<<2); // set ZFlag - drZ80.Z80F2 = (1<<2); // set ZFlag drZ80.Z80IX = 0xFFFF << 16; drZ80.Z80IY = 0xFFFF << 16; */ From 4aaedc899e61d10e43b3d427f1c2d70ce859a80d Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 23 Feb 2024 19:21:39 +0100 Subject: [PATCH 35/66] mcd, fix audio not playing when buffer RAM enabled --- pico/cd/cdd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index a3c3c93a0..78fae75d9 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -182,7 +182,7 @@ static void cdd_change_track(int index, int lba) { int i, base, lba_offset, lb_len; - for (i = index; i > 0; i--) + for (i = index; i >= 0; i--) if (cdd.toc.tracks[i].fd != NULL) break; @@ -510,7 +510,7 @@ int cdd_unload(void) void cdd_read_data(uint8 *dst) { /* only read DATA track sectors */ - if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[cdd.index].end)) + if (!is_audio(cdd.index) && (cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[cdd.index].end)) { /* BIN format ? */ if (cdd.sectorSize == 2352) From 2eeee072ea99edd7c7f675dc22d8f1e026690b31 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 23 Feb 2024 19:22:34 +0100 Subject: [PATCH 36/66] mcd, increase audio volume slightly --- pico/sound/mix.c | 18 ++++++++-------- pico/sound/mix_arm.S | 51 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/pico/sound/mix.c b/pico/sound/mix.c index 1c79b4854..edcdbb5f5 100644 --- a/pico/sound/mix.c +++ b/pico/sound/mix.c @@ -114,7 +114,7 @@ void mix_16h_to_32(s32 *dest_buf, s16 *mp3_buf, int count) { while (count--) { - *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; } } @@ -123,8 +123,8 @@ void mix_16h_to_32_s1(s32 *dest_buf, s16 *mp3_buf, int count) count >>= 1; while (count--) { - *dest_buf++ += *mp3_buf++ >> 1; - *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; mp3_buf += 1*2; } } @@ -134,8 +134,8 @@ void mix_16h_to_32_s2(s32 *dest_buf, s16 *mp3_buf, int count) count >>= 1; while (count--) { - *dest_buf++ += *mp3_buf++ >> 1; - *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; mp3_buf += 3*2; } } @@ -146,8 +146,8 @@ void mix_16h_to_32_resample_stereo(s32 *dest_buf, s16 *cdda_buf, int count, int int pos16 = 0; while (count--) { int pos = 2 * (pos16>>16); - *dest_buf++ += cdda_buf[pos ] >> 1; - *dest_buf++ += cdda_buf[pos+1] >> 1; + *dest_buf++ += (cdda_buf[pos ] * 5) >> 3; + *dest_buf++ += (cdda_buf[pos+1] * 5) >> 3; pos16 += fac16; } } @@ -158,8 +158,8 @@ void mix_16h_to_32_resample_mono(s32 *dest_buf, s16 *cdda_buf, int count, int fa int pos16 = 0; while (count--) { int pos = 2 * (pos16>>16); - *dest_buf += cdda_buf[pos ] >> 2; - *dest_buf++ += cdda_buf[pos+1] >> 2; + *dest_buf += (cdda_buf[pos ] * 5) >> 4; + *dest_buf++ += (cdda_buf[pos+1] * 5) >> 4; pos16 += fac16; } } diff --git a/pico/sound/mix_arm.S b/pico/sound/mix_arm.S index dc9e980b4..835d30abc 100644 --- a/pico/sound/mix_arm.S +++ b/pico/sound/mix_arm.S @@ -31,12 +31,16 @@ m16_32_loop: ldmia r0, {r3-r6} ldmia r1!,{r12,lr} subs r2, r2, #4 - add r4, r4, r12,asr #17 @ we use half volume + add r4, r4, r12,asr #17 @ we use 5/8 volume + add r4, r4, r12,asr #19 mov r12,r12,lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 mov lr, lr, lsl #16 add r5, r5, lr, asr #17 + add r5, r5, lr, asr #19 stmia r0!,{r3-r6} bpl m16_32_loop @@ -47,7 +51,9 @@ m16_32_end: ldmia r0, {r3,r4} mov r12,r5, lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r4, r4, r5, asr #17 + add r4, r4, r5, asr #19 stmia r0!,{r3,r4} m16_32_no_unal2: @@ -56,6 +62,7 @@ m16_32_no_unal2: ldrsh r4, [r1], #2 ldr r3, [r0] add r3, r3, r4, asr #1 + add r3, r3, r4, asr #3 str r3, [r0], #4 ldmfd sp!, {r4-r6,lr} @@ -76,12 +83,16 @@ m16_32_s1_loop: ldr r12,[r1], #8 ldr lr, [r1], #8 subs r2, r2, #4 - add r4, r4, r12,asr #17 + add r4, r4, r12,asr #17 @ we use 5/8 volume + add r4, r4, r12,asr #19 mov r12,r12,lsl #16 - add r3, r3, r12,asr #17 @ we use half volume + add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 mov lr, lr, lsl #16 add r5, r5, lr, asr #17 + add r5, r5, lr, asr #19 stmia r0!,{r3-r6} bpl m16_32_s1_loop @@ -92,7 +103,9 @@ m16_32_s1_end: ldmia r0, {r3,r4} mov r12,r5, lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r4, r4, r5, asr #17 + add r4, r4, r5, asr #19 stmia r0!,{r3,r4} m16_32_s1_no_unal2: @@ -101,6 +114,7 @@ m16_32_s1_no_unal2: ldrsh r4, [r1], #2 ldr r3, [r0] add r3, r3, r4, asr #1 + add r3, r3, r4, asr #3 str r3, [r0], #4 ldmfd sp!, {r4-r6,lr} @@ -121,12 +135,16 @@ m16_32_s2_loop: ldr r12,[r1], #16 ldr lr, [r1], #16 subs r2, r2, #4 - add r4, r4, r12,asr #17 + add r4, r4, r12,asr #17 @ we use 5/8 volume + add r4, r4, r12,asr #19 mov r12,r12,lsl #16 - add r3, r3, r12,asr #17 @ we use half volume + add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 mov lr, lr, lsl #16 add r5, r5, lr, asr #17 + add r5, r5, lr, asr #19 stmia r0!,{r3-r6} bpl m16_32_s2_loop @@ -137,7 +155,9 @@ m16_32_s2_end: ldmia r0, {r3,r4} mov r12,r5, lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r4, r4, r5, asr #17 + add r4, r4, r5, asr #19 stmia r0!,{r3,r4} m16_32_s2_no_unal2: @@ -146,6 +166,7 @@ m16_32_s2_no_unal2: ldrsh r4, [r1], #2 ldr r3, [r0] add r3, r3, r4, asr #1 + add r3, r3, r4, asr #3 str r3, [r0], #4 ldmfd sp!, {r4-r6,lr} @@ -171,12 +192,16 @@ m16_32_rss_loop: ldr lr ,[r1, r9, lsl #2] add r4, r4, r3 subs r2, r2, #2 - add r6, r6, r12,asr #17 + add r6, r6, r12,asr #17 @ we use 5/8 volume + add r6, r6, r12,asr #19 mov r12,r12,lsl #16 - add r5, r5, r12,asr #17 @ we use half volume + add r5, r5, r12,asr #17 + add r5, r5, r12,asr #19 add r8, r8, lr, asr #17 + add r8, r8, lr, asr #19 mov lr, lr, lsl #16 add r7, r7, lr, asr #17 + add r7, r7, lr, asr #19 stmia r0!,{r5-r8} bpl m16_32_rss_loop @@ -188,7 +213,9 @@ m16_32_rss_end: ldmia r0, {r5,r6} mov r12,lr, lsl #16 add r5, r5, r12,asr #17 + add r5, r5, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 stmia r0!,{r5,r6} ldmfd sp!, {r4-r9,lr} @@ -214,12 +241,16 @@ m16_32_rsm_loop: ldr lr ,[r1, r9, lsl #2] add r4, r4, r3 subs r2, r2, #2 - add r5, r5, r12,asr #18 + add r5, r5, r12,asr #18 @ we use 5/8 volume (= 5/16 vol per channel) + add r5, r5, r12,asr #20 mov r12,r12,lsl #16 - add r5, r5, r12,asr #18 @ we use half volume (= quarter vol per channel) + add r5, r5, r12,asr #18 + add r5, r5, r12,asr #20 add r6, r6, lr, asr #18 + add r6, r6, lr, asr #20 mov lr, lr, lsl #16 add r6, r6, lr, asr #18 + add r6, r6, lr, asr #20 stmia r0!,{r5-r6} bpl m16_32_rsm_loop @@ -231,7 +262,9 @@ m16_32_rsm_end: ldr r5, [r0] mov r12,lr, lsl #16 add r5, r5, r12,asr #18 + add r5, r5, r12,asr #20 add r5, r5, lr, asr #18 + add r5, r5, lr, asr #20 str r5, [r0] ldmfd sp!, {r4-r6,r9,lr} From d128474f6f0b36fe0c84932d0375cd9bff6efcbe Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 26 Feb 2024 23:10:35 +0100 Subject: [PATCH 37/66] mcd, fix crash (plat_mmap not zeroing memory) --- pico/cd/memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index ac42b8c53..075782845 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -1225,6 +1225,7 @@ PICO_INTERNAL void PicoMemSetupCD(void) { if (!Pico_mcd) Pico_mcd = plat_mmap(0x05000000, sizeof(mcd_state), 0, 0); + memset(Pico_mcd, 0, sizeof(mcd_state)); pcd_base_address = (Pico.romsize > 0x20000 ? 0x400000 : 0x000000); // setup default main68k map From 2a87da47c08ae69560b18fcb3e44f21711e70a9b Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 2 Mar 2024 10:34:04 +0100 Subject: [PATCH 38/66] ps2, fix some audio related bugs --- platform/ps2/emu.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index e738fba4b..6eb4dcc43 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -83,7 +83,7 @@ static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_CHUNK*SOUND_BLOCK_COUNT]; static short __attribute__((aligned(4))) nulBuffer[SOUND_BUFFER_CHUNK]; -static short *snd_playptr = NULL, *sndBuffer_endptr = NULL; +static short *snd_playptr, *sndBuffer_endptr; static int samples_made, samples_done, samples_block; static int sound_thread_exit = 0, sound_stopped = 1; @@ -112,9 +112,9 @@ static int mp3_init(void) { return 0; } static void writeSound(int len) { - int ret, l; + int l; - if (samples_made - samples_done <= samples_block * (SOUND_BLOCK_COUNT-3)) { + if (samples_made - samples_done < samples_block * (SOUND_BLOCK_COUNT-2) - 4) { samples_made += len / 2; PicoIn.sndOut += len / 2; } else @@ -168,7 +168,7 @@ static int sound_thread(void *argp) // compute sample chunk size int buflen = sndEnd - snd_playptr; - if (sndOut > snd_playptr) + if (sndOut >= snd_playptr) buflen = sndOut - snd_playptr; if (buflen > samples_made - samples_done) buflen = samples_made - samples_done; @@ -268,14 +268,12 @@ void pemu_sound_start(void) { ret = WaitSema(sound_mutex); if (ret < 0) lprintf("WaitSema mutex failed (%d)\n", ret); - if (PicoIn.sndRate > 52000 && PicoIn.sndRate < 54000) - PicoIn.sndRate = YM2612_NATIVE_RATE(); ret = POPT_EN_FM|POPT_EN_PSG|POPT_EN_STEREO; if (PicoIn.sndRate != PsndRate_old || (PicoIn.opt&ret) != (PicoOpt_old&ret) || Pico.m.pal != pal_old) { PsndRerate(Pico.m.frame_count ? 1 : 0); } stereo = (PicoIn.opt&8)>>3; - samples_block = PicoIn.sndRate * (stereo ? 2 : 1) / (Pico.m.pal ? 50 : 60); + samples_block = (PicoIn.sndRate / (Pico.m.pal ? 50 : 60)) * (stereo ? 2 : 1); lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", PicoIn.sndRate, Pico.snd.len, stereo, Pico.m.pal, samples_block); From 506adbd5eb585f3c1fe6ee424ba53bdb55c2ce5f Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 2 Mar 2024 10:34:50 +0100 Subject: [PATCH 39/66] core, another fix for z80 reset --- cpu/DrZ80/drz80.S | 17 +++++++++++++---- cpu/cz80/cz80.c | 2 -- pico/z80if.c | 7 ------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cpu/DrZ80/drz80.S b/cpu/DrZ80/drz80.S index 37e6e8840..f047664af 100644 --- a/cpu/DrZ80/drz80.S +++ b/cpu/DrZ80/drz80.S @@ -827,6 +827,7 @@ z80_xmap_rebase_sp: mov r0,z80sp readmem16 add z80sp,z80sp,#2 + bic z80sp,z80sp,#1<<16 .endif .endm @@ -856,7 +857,7 @@ z80_xmap_rebase_sp: .else mov r0,\reg subs z80sp,z80sp,#2 - @ addcc z80sp,z80sp,#1<<16 + addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 .endif @@ -874,7 +875,7 @@ z80_xmap_rebase_sp: .else mov r0,\reg,lsr #16 subs z80sp,z80sp,#2 - @ addcc z80sp,z80sp,#1<<16 + addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 .endif @@ -1506,7 +1507,7 @@ DoInterrupt_mode0: strb r0,[z80sp,#-1]! .else subs z80sp,z80sp,#2 - @ addcc z80sp,z80sp,#1<<16 + addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 ldr r2,[cpucontext, #z80irqvector] @@ -4732,6 +4733,9 @@ opcode_3_2: ;@INC SP opcode_3_3: add z80sp,z80sp,#1 +.if !FAST_Z80SP + bic z80sp,z80sp,#1<<16 +.endif fetch 6 ;@INC (HL) opcode_3_4: @@ -4782,7 +4786,10 @@ opcode_3_A: fetch 13 ;@DEC SP opcode_3_B: - sub z80sp,z80sp,#1 + subs z80sp,z80sp,#1 +.if !FAST_Z80SP + addcc z80sp,z80sp,#1<<16 +.endif fetch 6 ;@INC A opcode_3_C: @@ -5745,6 +5752,7 @@ opcode_F_1: mov r0,z80sp readmem16 add z80sp,z80sp,#2 + bic z80sp,z80sp,#1<<16 and z80a,r0,#0xFF00 mov z80a,z80a,lsl#16 and z80f,r0,#0xFF @@ -7638,6 +7646,7 @@ opcode_DD_E1: readmem16 ldmfd sp!,{r2,z80xx} add z80sp,z80sp,#2 + bic z80sp,z80sp,#1<<16 .endif strh r0,[z80xx,#2] fetch 14 diff --git a/cpu/cz80/cz80.c b/cpu/cz80/cz80.c index 90356019e..888478efe 100644 --- a/cpu/cz80/cz80.c +++ b/cpu/cz80/cz80.c @@ -212,8 +212,6 @@ void Cz80_Reset(cz80_struc *CPU) { // I, R, CPU and interrupts logic is reset, registers are untouched memset(&CPU->R, 0, (FPTR)&CPU->BasePC - (FPTR)&CPU->R); - Cz80_Set_Reg(CPU, CZ80_FA, 0xffff); - Cz80_Set_Reg(CPU, CZ80_SP, 0xffff); Cz80_Set_Reg(CPU, CZ80_PC, 0); } diff --git a/pico/z80if.c b/pico/z80if.c index 35710cba2..4df40da6e 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -112,14 +112,7 @@ void z80_reset(void) drZ80.Z80IF = 0; drZ80.z80irqvector = 0xff0000; // RST 38h drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1; - drZ80.Z80SP = 0xffff; - drZ80.Z80F = 0xff; - drZ80.Z80A = 0xff << 24; // others not changed, undefined on cold boot -/* - drZ80.Z80IX = 0xFFFF << 16; - drZ80.Z80IY = 0xFFFF << 16; -*/ #ifdef FAST_Z80SP // drZ80 is locked in single bank drz80_sp_base = (PicoIn.AHW & PAHW_SMS) ? 0xc000 : 0x0000; From 80f51a1d59e54aa6b628e5a514434bdd30b8b856 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 2 Mar 2024 10:36:49 +0100 Subject: [PATCH 40/66] core, slightly increase accuracy of some hw timers --- pico/cd/memory.c | 4 ++-- pico/memory.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 075782845..b13644b13 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -97,9 +97,9 @@ void m68k_comm_check(u32 a) u32 pcd_stopwatch_read(int sub) { - // ugh.. + // ugh... stopwatch runs 384 cycles per step, divide by mult with inverse u32 d = sub ? SekCyclesDoneS68k() : pcd_cycles_m68k_to_s68k(SekCyclesDone()); - d = (d - Pico_mcd->m.stopwatch_base_c) / 384; + d = ((d - Pico_mcd->m.stopwatch_base_c) * ((1LL << 32) / 384)) >> 32; return d & 0x0fff; } diff --git a/pico/memory.c b/pico/memory.c index c2a40f70b..46e0bd4a1 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -1092,7 +1092,7 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) * Starting a timer takes place at the next tick, so xcycles needs to be * rounded up to that: t = next tick# = (xcycles / TICK_ZCYCLES) + 1 */ - unsigned t = ((xcycles * (((1<<20)/TIMER_A_TICK_ZCYCLES)+1))>>20) + 1; + unsigned t = ((xcycles * (((1LL<<32)/TIMER_A_TICK_ZCYCLES)+1))>>32) + 1; Pico.t.timer_a_next_oflow = t*TIMER_A_TICK_ZCYCLES + Pico.t.timer_a_step; } } @@ -1115,7 +1115,7 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) * reset by loading timer b. The first run of timer b after loading is * therefore shorter by up to 15 ticks. */ - unsigned t = ((xcycles * (((1<<20)/TIMER_A_TICK_ZCYCLES)+1))>>20) + 1; + unsigned t = ((xcycles * (((1LL<<32)/TIMER_A_TICK_ZCYCLES)+1))>>32) + 1; int step = Pico.t.timer_b_step - TIMER_A_TICK_ZCYCLES*(t&15); Pico.t.timer_b_next_oflow = t*TIMER_A_TICK_ZCYCLES + step; } From d12dd1b4ea38dad9366957a9f4308070ab5f4276 Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 20 Feb 2024 22:01:47 +0100 Subject: [PATCH 41/66] psp, rendering fix, some build changes --- platform/base_readme.txt | 2 -- platform/psp/Makefile | 39 +++++++++++++++++---------------------- platform/psp/plat.c | 12 +++++++----- platform/psp/psp.c | 23 +++++------------------ platform/psp/psp.h | 12 +++++++----- 5 files changed, 36 insertions(+), 52 deletions(-) diff --git a/platform/base_readme.txt b/platform/base_readme.txt index 5925a4725..d45752157 100644 --- a/platform/base_readme.txt +++ b/platform/base_readme.txt @@ -26,8 +26,6 @@ the root of SD, etc). If you are running a custom firmware, just copy the whole PicoDrive directory to /PSP/GAME or /PSP/GAMEXXX directory in your memory stick (it shouldn't matter which one GAME* directory to use). - -If you are on 1.5, there is a separate KXploited version for it. #endif #ifdef PANDORA Just copy the .pnd to /pandora/menu or /pandora/desktop. diff --git a/platform/psp/Makefile b/platform/psp/Makefile index 6231d1eaf..2caf4aedf 100644 --- a/platform/psp/Makefile +++ b/platform/psp/Makefile @@ -6,32 +6,27 @@ $(error need VER) endif endif +include ../../config.mak + +#PSPSDK ?= $(shell psp-config --pspsdk-path) +#include $(PSPSDK)/lib/build.mak + +#PSP_EBOOT_TITLE = PicoDrive +#PSP_EBOOT_ICON = data/icon.png + +#EBOOT.PBP: + ../../tools/textfilter: ../../tools/textfilter.c make -C ../../tools/ textfilter readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog ../../tools/textfilter ../base_readme.txt $@ PSP -# ? rel: ../../EBOOT.PBP readme.txt ../game_def.cfg - mkdir -p PicoDrive/skin/ - cp $^ PicoDrive/ - cp skin/* PicoDrive/skin/ - zip -9 -r ../../PicoDrive_psp_$(VER).zip PicoDrive - rm -rf PicoDrive - mkdir bin_to_cso_mp3 - cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/ - zip -9 -r ../../PicoDrive_psp_$(VER).zip bin_to_cso_mp3 - rm -rf bin_to_cso_mp3 - -rel_kxploit: readme.txt ../game_def.cfg - mkdir -p PicoDrive/skin/ - cp $^ PicoDrive/ - cp skin/* PicoDrive/skin/ - zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip PicoDrive - zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip PicoDrive% - mkdir bin_to_cso_mp3 - cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/ - zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip bin_to_cso_mp3 - rm -rf bin_to_cso_mp3 - + mkdir -p out/PicoDrive/skin/ out/bin_to_cso_mp3 + cp $^ out/PicoDrive/ + cp ../../skin/* out/PicoDrive/skin/ + #mkdir -p out/bin_to_cso_mp3 + #cp ../../tools/bin_to_cso_mp3/* out/bin_to_cso_mp3/ + cd out && zip -9 -r ../../../PicoDrive_psp_$(VER).zip * + rm -rf out diff --git a/platform/psp/plat.c b/platform/psp/plat.c index 64ae04325..86b15e770 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -70,15 +70,16 @@ void plat_target_finish(void) /* display a completed frame buffer and prepare a new render buffer */ void plat_video_flip(void) { - int offs = (psp_screen == VRAM_FB0) ? VRAMOFFS_FB0 : VRAMOFFS_FB1; + unsigned long offs; g_menubg_src_ptr = psp_screen; sceGuSync(0, 0); // sync with prev - psp_video_flip(currentConfig.EmuOpt & EOPT_VSYNC, 0); + psp_video_flip(currentConfig.EmuOpt & EOPT_VSYNC); + offs = (unsigned long)psp_screen - VRAM_ADDR; // back buffer offset sceGuStart(GU_DIRECT, guCmdList); - sceGuDrawBuffer(GU_PSM_5650, (void *)offs, 512); // point to back buffer + sceGuDrawBuffer(GU_PSM_5650, (void *)offs, 512); sceGuClearColor(0); sceGuClearDepth(0); sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT); @@ -87,7 +88,7 @@ void plat_video_flip(void) sceGuFinish(); - g_screen_ptr = VRAM_CACHED_STUFF + (psp_screen - VRAM_FB0); + g_screen_ptr = VRAM_CACHED_STUFF + offs; plat_video_set_buffer(g_screen_ptr); } @@ -100,6 +101,7 @@ void plat_video_wait_vsync(void) /* switch from emulation display to menu display */ void plat_video_menu_enter(int is_rom_loaded) { + g_screen_ptr = NULL; } /* start rendering a menu screen */ @@ -112,7 +114,7 @@ void plat_video_menu_begin(void) void plat_video_menu_end(void) { g_menuscreen_ptr = NULL; - psp_video_flip(1, 0); + psp_video_flip(1); } /* terminate menu display */ diff --git a/platform/psp/psp.c b/platform/psp/psp.c index 0a53cce7e..f3ca9b3bd 100644 --- a/platform/psp/psp.c +++ b/platform/psp/psp.c @@ -65,9 +65,7 @@ int psp_unhandled_suspend = 0; unsigned int __attribute__((aligned(16))) guCmdList[GU_CMDLIST_SIZE]; -void *psp_screen = VRAM_FB0; - -static int current_screen = 0; /* front bufer */ +void *psp_screen = VRAM_FB0; /* back buffer */ static SceUID main_thread_id = -1; @@ -145,7 +143,6 @@ void psp_init(void) /* video */ sceDisplaySetMode(0, 480, 272); sceDisplaySetFrameBuf(VRAM_FB1, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); - current_screen = 1; psp_screen = VRAM_FB0; /* gu */ @@ -193,27 +190,17 @@ void psp_finish(void) sceKernelExitGame(); } -void psp_video_flip(int wait_vsync, int other) +void psp_video_flip(int wait_vsync) { - unsigned long fb = (unsigned long)psp_screen & ~0x40000000; - if (other) fb ^= 0x44000; if (wait_vsync) sceDisplayWaitVblankStart(); - sceDisplaySetFrameBuf((void *)fb, 512, PSP_DISPLAY_PIXEL_FORMAT_565, + sceDisplaySetFrameBuf(psp_screen, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_IMMEDIATE); - current_screen ^= 1; - psp_screen = current_screen ? VRAM_FB0 : VRAM_FB1; + psp_screen = (void *)((unsigned long)psp_screen ^ (VRAMOFFS_FB1 ^ VRAMOFFS_FB0)); } void *psp_video_get_active_fb(void) { - return current_screen ? VRAM_FB1 : VRAM_FB0; -} - -void psp_video_switch_to_single(void) -{ - psp_screen = VRAM_FB0; - sceDisplaySetFrameBuf(psp_screen, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); - current_screen = 0; + return (void *)((unsigned long)psp_screen ^ (VRAMOFFS_FB1 ^ VRAMOFFS_FB0)); } void psp_msleep(int ms) diff --git a/platform/psp/psp.h b/platform/psp/psp.h index c8d4de829..c4c6404cd 100644 --- a/platform/psp/psp.h +++ b/platform/psp/psp.h @@ -25,11 +25,13 @@ void psp_msleep(int ms); #define VRAMOFFS_DEPTH 0x00088000 #define VRAMOFFS_STUFF 0x000cc000 -#define VRAM_FB0 ((void *) (0x44000000+VRAMOFFS_FB0)) -#define VRAM_FB1 ((void *) (0x44000000+VRAMOFFS_FB1)) -#define VRAM_STUFF ((void *) (0x44000000+VRAMOFFS_STUFF)) +#define VRAM_ADDR 0x44000000 +#define VRAM_FB0 ((void *) (VRAM_ADDR+VRAMOFFS_FB0)) +#define VRAM_FB1 ((void *) (VRAM_ADDR+VRAMOFFS_FB1)) +#define VRAM_STUFF ((void *) (VRAM_ADDR+VRAMOFFS_STUFF)) -#define VRAM_CACHED_STUFF ((void *) (0x04000000+VRAMOFFS_STUFF)) +#define VRAM_CACHEDADDR 0x04000000 +#define VRAM_CACHED_STUFF ((void *) (VRAM_CACHEDADDR+VRAMOFFS_STUFF)) #define GU_CMDLIST_SIZE (16*1024) @@ -38,7 +40,7 @@ extern int psp_unhandled_suspend; void *psp_video_get_active_fb(void); void psp_video_switch_to_single(void); -void psp_video_flip(int wait_vsync, int other); +void psp_video_flip(int wait_vsync); extern void *psp_screen; unsigned int psp_pad_read(int blocking); From e28fd20f08c96b58d2589504d770dfe82c4d41bd Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 22 Feb 2024 20:51:08 +0100 Subject: [PATCH 42/66] psp, revisit audio handling sound rates 44100, 22050, 11025 Hz, internally upsampled conversion to stereo since mono isn't supported well on psp --- platform/common/emu.c | 5 +- platform/psp/emu.c | 210 +++++++++++++++++++++++++++--------------- platform/psp/plat.c | 2 +- 3 files changed, 138 insertions(+), 79 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index 5e51d9340..6895498cb 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1349,15 +1349,16 @@ void emu_sound_start(void) { int is_stereo = (PicoIn.opt & POPT_EN_STEREO) ? 1 : 0; + memset(sndBuffer, 0, sizeof(sndBuffer)); + PicoIn.sndOut = sndBuffer; PsndRerate(Pico.m.frame_count ? 1 : 0); printf("starting audio: %i len: %i stereo: %i, pal: %i\n", PicoIn.sndRate, Pico.snd.len, is_stereo, Pico.m.pal); + sndout_start(PicoIn.sndRate, is_stereo); PicoIn.writeSound = snd_write_nonblocking; plat_update_volume(0, 0); - memset(sndBuffer, 0, sizeof(sndBuffer)); - PicoIn.sndOut = sndBuffer; } } diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 8b5a49810..4a60311f4 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -415,54 +415,139 @@ static void vidResetMode(void) } /* sound stuff */ -#define SOUND_BLOCK_SIZE_NTSC (1470*2) // 1024 // 1152 -#define SOUND_BLOCK_SIZE_PAL (1764*2) -#define SOUND_BLOCK_COUNT 8 +#define SOUND_BLOCK_COUNT 7 +#define SOUND_BUFFER_CHUNK (2*44100/50) // max.rate/min.frames in stereo + +static short sndBuffer_emu[SOUND_BUFFER_CHUNK+4]; // 4 for sample rounding overhang +static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_CHUNK*SOUND_BLOCK_COUNT]; +static short *sndBuffer_endptr; +static int samples_block; + +static short *snd_playptr, *sndBuffer_ptr; +static int samples_made, samples_done; -static short __attribute__((aligned(4))) sndBuffer[SOUND_BLOCK_SIZE_PAL*SOUND_BLOCK_COUNT + 54000/50*2]; -static short *snd_playptr = NULL, *sndBuffer_endptr = NULL; -static int samples_made = 0, samples_done = 0, samples_block = 0; static int sound_thread_exit = 0; static SceUID sound_sem = -1; -static void writeSound(int len); +// There are problems if the sample rate used with the PSP isn't 44100 Hz stereo. +// Hence, use only 11025,22050,44100 here and handle duplication and upsampling. +// Upsample by nearest neighbour, which is the fastest but may create artifacts. -static int sound_thread(SceSize args, void *argp) +static void writeSound(int len) +{ + // make sure there is (samples_block+2) free space in the buffer after + // this frame, else the next frame may overwrite old stored samples. + if (samples_made - samples_done < samples_block * (SOUND_BLOCK_COUNT-2) - 4) { + sndBuffer_ptr += len / 2; + if (sndBuffer_ptr - sndBuffer > sizeof(sndBuffer)/2) + lprintf("snd ovrn %d %d\n", len, PicoIn.sndOut - sndBuffer); + if (sndBuffer_ptr >= sndBuffer_endptr) { + int wrap = sndBuffer_ptr - sndBuffer_endptr; + if (wrap > 0) + memcpy(sndBuffer, sndBuffer_endptr, 2*wrap); + sndBuffer_ptr -= sndBuffer_endptr - sndBuffer; + } + + samples_made += len / 2; + } else + lprintf("snd oflow %i!\n", samples_made - samples_done); + + // signal the snd thread + sceKernelSignalSema(sound_sem, 1); +} + +static void writeSound_44100_stereo(int len) +{ + writeSound(len); + PicoIn.sndOut = sndBuffer_ptr; +} + +static void writeSound_44100_mono(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i++, p+=2) + p[0] = p[1] = PicoIn.sndOut[i]; + writeSound(2*len); +} + +static void writeSound_22050_stereo(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i+=2, p+=4) { + p[0] = p[2] = PicoIn.sndOut[i]; + p[1] = p[3] = PicoIn.sndOut[i+1]; + } + writeSound(2*len); +} + +static void writeSound_22050_mono(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i++, p+=4) { + p[0] = p[2] = PicoIn.sndOut[i]; + p[1] = p[3] = PicoIn.sndOut[i]; + } + writeSound(4*len); +} + +static void writeSound_11025_stereo(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i+=2, p+=8) { + p[0] = p[2] = p[4] = p[6] = PicoIn.sndOut[i]; + p[1] = p[3] = p[5] = p[7] = PicoIn.sndOut[i+1]; + } + writeSound(4*len); +} + +static void writeSound_11025_mono(int len) { - int ret = 0; + short *p = sndBuffer_ptr; + int i; + for (i = 0; i < len / 2; i++, p+=8) { + p[0] = p[2] = p[4] = p[6] = PicoIn.sndOut[i]; + p[1] = p[3] = p[5] = p[7] = PicoIn.sndOut[i]; + } + writeSound(8*len); +} + +static int sound_thread(SceSize args, void *argp) +{ lprintf("sthr: started, priority %i\n", sceKernelGetThreadCurrentPriority()); while (!sound_thread_exit) { + int ret; + if (samples_made - samples_done < samples_block) { // wait for data (use at least 2 blocks) //lprintf("sthr: wait... (%i)\n", samples_made - samples_done); - while (samples_made - samples_done <= samples_block*2 && !sound_thread_exit) + while (samples_made - samples_done < samples_block*2 && !sound_thread_exit) { ret = sceKernelWaitSema(sound_sem, 1, 0); - if (ret < 0) lprintf("sthr: sceKernelWaitSema: %i\n", ret); - continue; + if (ret < 0) lprintf("sthr: sceKernelWaitSema: %i\n", ret); + } } - // lprintf("sthr: got data: %i\n", samples_made - samples_done); - + // if the sample buffer runs low, push some extra + if (sceAudioOutput2GetRestSample()*2 < samples_block/4) + ret = sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, snd_playptr); ret = sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, snd_playptr); + // 1.5 kernel returns 0, newer ones return # of samples queued + if (ret < 0) lprintf("sthr: play: ret %08x; pos %i/%i\n", ret, samples_done, samples_made); samples_done += samples_block; snd_playptr += samples_block; if (snd_playptr >= sndBuffer_endptr) - snd_playptr = sndBuffer; - // 1.5 kernel returns 0, newer ones return # of samples queued - if (ret < 0) - lprintf("sthr: sceAudioSRCOutputBlocking: %08x; pos %i/%i\n", ret, samples_done, samples_made); - - // shouln't happen, but just in case - if (samples_made - samples_done >= samples_block*3) { - //lprintf("sthr: block skip (%i)\n", samples_made - samples_done); - samples_done += samples_block; // skip - snd_playptr += samples_block; - } - + snd_playptr -= sndBuffer_endptr - sndBuffer; } lprintf("sthr: exit\n"); @@ -479,7 +564,7 @@ static void sound_init(void) if (sound_sem < 0) lprintf("sceKernelCreateSema() failed: %i\n", sound_sem); samples_made = samples_done = 0; - samples_block = SOUND_BLOCK_SIZE_NTSC; // make sure it goes to sema + samples_block = 2*22050/60; // make sure it goes to sema sound_thread_exit = 0; thid = sceKernelCreateThread("sndthread", sound_thread, 0x12, 0x10000, 0, NULL); if (thid >= 0) @@ -491,11 +576,13 @@ static void sound_init(void) lprintf("sceKernelCreateThread failed: %i\n", thid); } +#define PSP_RATE 44100 // PicoIn.sndRate + void pemu_sound_start(void) { static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; static int mp3_init_done; - int ret, stereo; + int ret, stereo, factor; samples_made = samples_done = 0; @@ -511,34 +598,38 @@ void pemu_sound_start(void) } } - if (PicoIn.sndRate > 52000 && PicoIn.sndRate < 54000) - PicoIn.sndRate = YM2612_NATIVE_RATE(); ret = POPT_EN_FM|POPT_EN_PSG|POPT_EN_STEREO; if (PicoIn.sndRate != PsndRate_old || (PicoIn.opt&ret) != (PicoOpt_old&ret) || Pico.m.pal != pal_old) { PsndRerate(Pico.m.frame_count ? 1 : 0); } - stereo=(PicoIn.opt&8)>>3; + stereo = (PicoIn.opt&8)>>3; - samples_block = Pico.m.pal ? SOUND_BLOCK_SIZE_PAL : SOUND_BLOCK_SIZE_NTSC; - if (PicoIn.sndRate <= 22050) samples_block /= 2; - sndBuffer_endptr = &sndBuffer[samples_block*SOUND_BLOCK_COUNT]; + // PSP doesn't support mono in SRC, always use stereo and convert + factor = PSP_RATE / PicoIn.sndRate; + samples_block = (PSP_RATE / (Pico.m.pal ? 50 : 60)) * 2; lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", PicoIn.sndRate, Pico.snd.len, stereo, Pico.m.pal, samples_block); - // while (sceAudioOutput2GetRestSample() > 0) psp_msleep(100); - // sceAudioSRCChRelease(); - ret = sceAudioSRCChReserve(samples_block/2, PicoIn.sndRate, 2); // seems to not need that stupid 64byte alignment + ret = sceAudioSRCChReserve(samples_block/2, PSP_RATE, 2); // seems to not need that stupid 64byte alignment if (ret < 0) { lprintf("sceAudioSRCChReserve() failed: %i\n", ret); emu_status_msg("sound init failed (%i), snd disabled", ret); currentConfig.EmuOpt &= ~EOPT_EN_SOUND; } else { - PicoIn.writeSound = writeSound; - memset32((int *)(void *)sndBuffer, 0, sizeof(sndBuffer)/4); - snd_playptr = sndBuffer_endptr - samples_block; - samples_made = samples_block; // send 1 empty block first.. - PicoIn.sndOut = sndBuffer; + switch (factor) { + case 1: PicoIn.writeSound = stereo ? writeSound_44100_stereo:writeSound_44100_mono; break; + case 2: PicoIn.writeSound = stereo ? writeSound_22050_stereo:writeSound_22050_mono; break; + case 4: PicoIn.writeSound = stereo ? writeSound_11025_stereo:writeSound_11025_mono; break; + } + sndBuffer_endptr = sndBuffer + (SOUND_BLOCK_COUNT-1)*samples_block; + snd_playptr = sndBuffer_ptr = sndBuffer; + PicoIn.sndOut = (factor == 1 && stereo ? sndBuffer_ptr : sndBuffer_emu); + + // push one audio block to cover time to first frame audio +// memset32(PicoIn.sndOut, 0, samples_block/2); +// writeSound(samples_block*2); + PsndRate_old = PicoIn.sndRate; PicoOpt_old = PicoIn.opt; pal_old = Pico.m.pal; @@ -564,14 +655,6 @@ void pemu_sound_stop(void) sceAudioSRCChRelease(); } -/* wait until we can write more sound */ -void pemu_sound_wait(void) -{ - // TODO: test this - while (!sound_thread_exit && samples_made - samples_done > samples_block * 4) - psp_msleep(10); -} - static void sound_deinit(void) { sound_thread_exit = 1; @@ -580,31 +663,6 @@ static void sound_deinit(void) sound_sem = -1; } -static void writeSound(int len) -{ - int ret; - - PicoIn.sndOut += len / 2; - /*if (PicoIn.sndOut > sndBuffer_endptr) { - memcpy((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) * 2); - PicoIn.sndOut = &sndBuffer[PicoIn.sndOut - endptr]; - lprintf("mov\n"); - } - else*/ - if (PicoIn.sndOut > sndBuffer_endptr) lprintf("snd oflow %i!\n", PicoIn.sndOut - sndBuffer_endptr); - if (PicoIn.sndOut >= sndBuffer_endptr) - PicoIn.sndOut = sndBuffer; - - // signal the snd thread - samples_made += len / 2; - if (samples_made - samples_done > samples_block*2) { - // lprintf("signal, %i/%i\n", samples_done, samples_made); - ret = sceKernelSignalSema(sound_sem, 1); - //if (ret < 0) lprintf("snd signal ret %08x\n", ret); - } -} - - /* set default configuration values */ void pemu_prep_defconfig(void) { @@ -615,7 +673,7 @@ void pemu_prep_defconfig(void) defaultConfig.scaling = EOPT_SCALE_43; defaultConfig.vscaling = EOPT_VSCALE_FULL; defaultConfig.renderer = RT_8BIT_ACC; - defaultConfig.renderer32x = RT_8BIT_ACC; + defaultConfig.renderer32x = RT_8BIT_FAST; defaultConfig.EmuOpt |= EOPT_SHOW_RTC; } diff --git a/platform/psp/plat.c b/platform/psp/plat.c index 86b15e770..b8a29e5f6 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -275,7 +275,7 @@ static int plat_bat_capacity_get(void) return scePowerGetBatteryLifePercent(); } -static int sound_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, -1 }; +static int sound_rates[] = { 11025, 22050, 44100, -1 }; struct plat_target plat_target = { .cpu_clock_get = plat_cpu_clock_get, .cpu_clock_set = plat_cpu_clock_set, From 56ec20d2629e16a9636ce24682ab123717825900 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Mar 2024 09:45:01 +0100 Subject: [PATCH 43/66] psp, small fixes --- platform/psp/emu.c | 2 +- platform/psp/menu.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 4a60311f4..b53a0f91e 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -566,7 +566,7 @@ static void sound_init(void) samples_made = samples_done = 0; samples_block = 2*22050/60; // make sure it goes to sema sound_thread_exit = 0; - thid = sceKernelCreateThread("sndthread", sound_thread, 0x12, 0x10000, 0, NULL); + thid = sceKernelCreateThread("sndthread", sound_thread, 0x12, 0x1000, 0, NULL); if (thid >= 0) { ret = sceKernelStartThread(thid, 0, 0); diff --git a/platform/psp/menu.c b/platform/psp/menu.c index 25ca98939..99a7d0e2e 100644 --- a/platform/psp/menu.c +++ b/platform/psp/menu.c @@ -3,12 +3,14 @@ static const char *men_vscaling_opts[] = { "OFF", "fullscreen", "borderless", NU static const char *men_hscaling_opts[] = { "1:1", "4:3", "extended", "fullwidth", NULL }; static const char *men_filter_opts[] = { "nearest", "bilinear", NULL }; +static const char h_8bit[] = "This option only works for 8bit renderers"; + #define MENU_OPTIONS_GFX \ mee_enum ("Vertical scaling", MA_OPT_VSCALING, currentConfig.vscaling, men_vscaling_opts), \ mee_enum ("Aspect ratio", MA_OPT_SCALING, currentConfig.scaling, men_hscaling_opts), \ mee_enum ("Scaler type", MA_OPT3_FILTERING, currentConfig.filter, men_filter_opts), \ - mee_range ("Gamma adjustment", MA_OPT3_GAMMAA, currentConfig.gamma, -4, 16), \ - mee_range ("Black level", MA_OPT3_BLACKLVL, currentConfig.gamma2, 0, 2), \ + mee_range_h ("Gamma adjustment", MA_OPT3_GAMMAA, currentConfig.gamma, -4, 16, h_8bit), \ + mee_range_h ("Black level", MA_OPT3_BLACKLVL, currentConfig.gamma2, 0, 2, h_8bit), \ mee_onoff ("Wait for vsync", MA_OPT3_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC), \ #define MENU_OPTIONS_ADV From a17fb0210bc60c2eacdb7125e12d4f14abb17f99 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Mar 2024 13:01:51 +0100 Subject: [PATCH 44/66] core z80, some timing improvements --- pico/memory.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index 46e0bd4a1..fc7ad740c 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -675,14 +675,15 @@ static void PicoWrite16_sram(u32 a, u32 d) static u32 PicoRead8_z80(u32 a) { u32 d = 0xff; - if (((Pico.m.z80Run & 1) || Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { + if ((Pico.m.z80Run | Pico.m.z80_reset | (z80_cycles_from_68k() < Pico.t.z80c_cnt)) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); // open bus. Pulled down if MegaCD2 is attached. return (PicoIn.AHW & PAHW_MCD ? 0 : d); } + Pico.t.z80c_cnt += 3; + SekCyclesBurnRun(1); if ((a & 0x4000) == 0x0000) { - SekCyclesBurnRun(1); d = PicoMem.zram[a & 0x1fff]; } else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff d = ym2612_read_local_68k(); @@ -699,14 +700,15 @@ static u32 PicoRead16_z80(u32 a) static void PicoWrite8_z80(u32 a, u32 d) { - if (((Pico.m.z80Run & 1) || Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { + if ((Pico.m.z80Run | Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { // verified on real hw elprintf(EL_ANOMALY, "68k z80 write with no bus or reset! [%06x] %02x @ %06x", a, d&0xff, SekPc); return; } + Pico.t.z80c_cnt += 3; + SekCyclesBurnRun(1); if ((a & 0x4000) == 0x0000) { // z80 RAM - SekCyclesBurnRun(1); PicoMem.zram[a & 0x1fff] = (u8)d; return; } @@ -759,6 +761,8 @@ u32 PicoRead8_io(u32 a) // bit8 seems to be readable in this range if (!(a & 1)) { d &= ~0x01; + // Z80 ahead of 68K only if in BUSREQ, BUSACK only after 68K reached Z80 + d |= (z80_cycles_from_68k() < Pico.t.z80c_cnt); d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc); } @@ -790,6 +794,7 @@ u32 PicoRead16_io(u32 a) if ((a & 0xfc00) == 0x1000) { if ((a & 0xff00) == 0x1100) { // z80 busreq d &= ~0x0100; + d |= (z80_cycles_from_68k() < Pico.t.z80c_cnt) << 8; d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8; elprintf(EL_BUSREQ, "get_zrun: %04x [%u] @%06x", d, SekCyclesDone(), SekPc); } @@ -1344,6 +1349,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)) + z80_subCLeft(z80_cyclesLeft); // rather rough on both condition and action + // 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. Pico.t.z80_busdelay = (delay&0xff) + (Pico.t.z80_busdelay&0xff); // accumulate @@ -1379,7 +1388,7 @@ static unsigned char z80_md_vdp_read(unsigned short a) static unsigned char z80_md_bank_read(unsigned short a) { unsigned int addr68k; - unsigned char ret; + unsigned char ret = 0xff; // 68k bus access delay=3.3 per kabuto, but for notaz picotest 3.023.02)-0x351(<3.32) @@ -1387,7 +1396,8 @@ static unsigned char z80_md_bank_read(unsigned short a) addr68k = Pico.m.z80_bank68k << 15; addr68k |= a & 0x7fff; - ret = m68k_read8(addr68k); + if (addr68k < 0xe00000) // can't read from 68K RAM + ret = m68k_read8(addr68k); elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); return ret; From 1d78204a90f5b68e3bcbea6ac7509d5b327210ee Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Mar 2024 13:02:13 +0100 Subject: [PATCH 45/66] prerelease 2.00-beta1 --- 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 db39ac35a..65c9150e0 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "pre-2.00-alpha3" REVISION +#define VERSION "pre-2.00-beta1" REVISION From c066c40ba9a3cc7ee617b9d511cf615996cb1857 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Mar 2024 22:55:35 +0100 Subject: [PATCH 46/66] core z80, more timing fixes --- pico/memory.c | 8 +++----- pico/z80if.c | 4 +++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index fc7ad740c..fc8e33db1 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -521,7 +521,7 @@ void NOINLINE ctl_write_z80busreq(u32 d) { if (d) { - Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; + Pico.t.z80c_cnt = z80_cycles_from_68k() + 1; } else { @@ -553,7 +553,7 @@ void NOINLINE ctl_write_z80reset(u32 d) } else { - Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; + Pico.t.z80c_cnt = z80_cycles_from_68k() + 1; z80_reset(); } Pico.m.z80_reset = d; @@ -680,7 +680,6 @@ static u32 PicoRead8_z80(u32 a) // open bus. Pulled down if MegaCD2 is attached. return (PicoIn.AHW & PAHW_MCD ? 0 : d); } - Pico.t.z80c_cnt += 3; SekCyclesBurnRun(1); if ((a & 0x4000) == 0x0000) { @@ -705,7 +704,6 @@ static void PicoWrite8_z80(u32 a, u32 d) elprintf(EL_ANOMALY, "68k z80 write with no bus or reset! [%06x] %02x @ %06x", a, d&0xff, SekPc); return; } - Pico.t.z80c_cnt += 3; SekCyclesBurnRun(1); if ((a & 0x4000) == 0x0000) { // z80 RAM @@ -1359,7 +1357,7 @@ static void access_68k_bus(int delay) // bus delay as Q8 z80_subCLeft((delay>>8) + (Pico.t.z80_busdelay>>8)); // don't use SekCyclesBurn() here since the Z80 doesn't run in cycle lock to // the 68K. Count the stolen cycles to be accounted later in the 68k CPU runs - Pico.t.z80_buscycles += 7; + Pico.t.z80_buscycles += 8; } static unsigned char z80_md_vdp_read(unsigned short a) diff --git a/pico/z80if.c b/pico/z80if.c index 4df40da6e..6243675cb 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -112,12 +112,13 @@ void z80_reset(void) drZ80.Z80IF = 0; drZ80.z80irqvector = 0xff0000; // RST 38h drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1; - // others not changed, undefined on cold boot + // other registers not changed, undefined on cold boot #ifdef FAST_Z80SP // drZ80 is locked in single bank drz80_sp_base = (PicoIn.AHW & PAHW_SMS) ? 0xc000 : 0x0000; drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1; #endif + drZ80.Z80SP = drZ80.Z80SP_BASE + 0xffff; drZ80.z80_irq_callback = NULL; // use auto-clear if (PicoIn.AHW & PAHW_SMS) { drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS @@ -128,6 +129,7 @@ void z80_reset(void) #endif #ifdef _USE_CZ80 Cz80_Reset(&CZ80); + Cz80_Set_Reg(&CZ80, CZ80_SP, 0xffff); if (PicoIn.AHW & PAHW_SMS) Cz80_Set_Reg(&CZ80, CZ80_SP, 0xdff0); #endif From 83025d7abe85fd9a7992a468cd78d70b7416f60b Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Mar 2024 22:57:58 +0100 Subject: [PATCH 47/66] core, implement ym2612 busy flag --- pico/memory.c | 13 ++++++++----- pico/pico_int.h | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index fc8e33db1..e9232d15f 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -1066,6 +1066,8 @@ static int get_scanline(int is_from_z80) } #define ym2612_update_status(xcycles) \ + ym2612.OPN.ST.status &= ~0x80; \ + ym2612.OPN.ST.status |= (xcycles < Pico.t.ym2612_busy) * 0x80; \ if (xcycles >= Pico.t.timer_a_next_oflow) \ ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 1; \ if (xcycles >= Pico.t.timer_b_next_oflow) \ @@ -1131,6 +1133,7 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) // ym2612 DAC and timer I/O handlers for z80 static int ym2612_write_local(u32 a, u32 d, int is_from_z80) { + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); int addr; a &= 3; @@ -1150,6 +1153,10 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8); ym2612.REGS[addr] = d; + // the busy flag in the YM2612 status is actually a 32 cycle timer + // (89.6 Z80 cycles), triggered by any write to the data port. + Pico.t.ym2612_busy = (cycles + 90) << 8; // Q8 for convenience + switch (addr) { case 0x24: // timer A High 8 @@ -1158,7 +1165,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) : ((ym2612.OPN.ST.TA & 0x3fc)|(d&3)); if (ym2612.OPN.ST.TA != TAnew) { - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); ym2612_sync_timers(cycles, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); //elprintf(EL_STATUS, "timer a set %i", TAnew); ym2612.OPN.ST.TA = TAnew; @@ -1171,7 +1177,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) } case 0x26: // timer B if (ym2612.OPN.ST.TB != d) { - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); ym2612_sync_timers(cycles, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); //elprintf(EL_STATUS, "timer b set %i", d); ym2612.OPN.ST.TB = d; @@ -1183,7 +1188,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) return 0; case 0x27: { /* mode, timer control */ int old_mode = ym2612.OPN.ST.mode; - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); elprintf(EL_YMTIMER, "st mode %02x", d); ym2612_sync_timers(cycles, old_mode, d); @@ -1208,7 +1212,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) return 0; } case 0x2a: { /* DAC data */ - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); //elprintf(EL_STATUS, "%03i dac w %08x z80 %i", cycles, d, is_from_z80); if (ym2612.dacen) PsndDoDAC(cycles); @@ -1230,7 +1233,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) if (PicoIn.opt & POPT_EXT_FM) return YM2612Write_940(a, d, get_scanline(is_from_z80)); #endif - PsndDoFM(is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k()); + PsndDoFM(cycles); return YM2612Write_(a, d); } diff --git a/pico/pico_int.h b/pico/pico_int.h index a3c875676..80c00fbfd 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -457,6 +457,7 @@ struct PicoTiming int timer_a_next_oflow, timer_a_step; // in z80 cycles int timer_b_next_oflow, timer_b_step; + int ym2612_busy; int vcnt_wrap, vcnt_adj; }; @@ -897,6 +898,8 @@ void ym2612_unpack_state(void); #define TIMER_B_TICK_ZCYCLES cycles_68k_to_z80(256LL*16*72*2) // Q8 #define timers_cycle(ticks) \ + if (Pico.t.ym2612_busy > 0) \ + Pico.t.ym2612_busy -= ticks << 8; \ if (Pico.t.timer_a_next_oflow < TIMER_NO_OFLOW) \ Pico.t.timer_a_next_oflow -= ticks << 8; \ if (Pico.t.timer_b_next_oflow < TIMER_NO_OFLOW) \ @@ -904,6 +907,7 @@ void ym2612_unpack_state(void); ym2612_sync_timers(0, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); #define timers_reset() \ + Pico.t.ym2612_busy = 0; \ Pico.t.timer_a_next_oflow = Pico.t.timer_b_next_oflow = TIMER_NO_OFLOW; \ Pico.t.timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \ Pico.t.timer_b_step = TIMER_B_TICK_ZCYCLES * 256; \ From 02d578601bbe749b97e3cd8184789146fe7f2a2a Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 7 Mar 2024 20:36:00 +0100 Subject: [PATCH 48/66] core, fix crash bug in DrZ80 (SP wrap) --- cpu/DrZ80/drz80.S | 2 ++ pico/memory.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cpu/DrZ80/drz80.S b/cpu/DrZ80/drz80.S index f047664af..655814ca3 100644 --- a/cpu/DrZ80/drz80.S +++ b/cpu/DrZ80/drz80.S @@ -208,6 +208,7 @@ z80_xmap_read16: @ addr bl z80_xmap_read8 mov r9,r0 add r0,r8,#1 + bic r0,r0,#1<<16 bl z80_xmap_read8 orr r0,r9,r0,lsl #8 ldmfd sp!,{r2,r8,r9,pc} @@ -236,6 +237,7 @@ z80_xmap_write16: @ data, addr bl z80_xmap_write8 mov r0,r8,lsr #8 add r1,r9,#1 + bic r1,r1,#1<<16 bl z80_xmap_write8 ldmfd sp!,{r2,r8,r9,pc} diff --git a/pico/memory.c b/pico/memory.c index e9232d15f..693f96035 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -675,7 +675,7 @@ static void PicoWrite16_sram(u32 a, u32 d) static u32 PicoRead8_z80(u32 a) { u32 d = 0xff; - if ((Pico.m.z80Run | Pico.m.z80_reset | (z80_cycles_from_68k() < Pico.t.z80c_cnt)) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { + if ((Pico.m.z80Run | Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); // open bus. Pulled down if MegaCD2 is attached. return (PicoIn.AHW & PAHW_MCD ? 0 : d); From 3f5918225a73bf7485abddd003b5749bca1a2fb4 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 7 Mar 2024 20:42:24 +0100 Subject: [PATCH 49/66] core, fix 68k cycles in cyclone,fame (exceptions,bit ops,ADDI.L,TAS,CHK,MUL*,DIV*) also syncs these changes between fame and cyclone in accordance with the test_inst_speed, available here: https://gendev.spritesmind.net/forum/viewtopic.php?t=3321 DIV* is only closely approximated, it can be slightly on the high side. --- .gitmodules | 2 +- cpu/cyclone | 2 +- cpu/fame/famec.c | 13 +- cpu/fame/famec_opcodes.h | 649 ++++++++++++++++++++++++++------------- 4 files changed, 438 insertions(+), 228 deletions(-) diff --git a/.gitmodules b/.gitmodules index 4f610dff6..5d28012a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/irixxxx/libpicofe.git [submodule "cpu/cyclone"] path = cpu/cyclone - url = https://github.com/notaz/cyclone68000.git + url = https://github.com/irixxxx/cyclone68000.git [submodule "pico/sound/emu2413"] path = pico/sound/emu2413 url = https://github.com/digital-sound-antiques/emu2413.git diff --git a/cpu/cyclone b/cpu/cyclone index 425e3a406..ee45bb2b1 160000 --- a/cpu/cyclone +++ b/cpu/cyclone @@ -1 +1 @@ -Subproject commit 425e3a4066ee1cc8a3bae28956fbbdc9a516001d +Subproject commit ee45bb2b10b3abf10a4335ea24fc029e3f61c10a diff --git a/cpu/fame/famec.c b/cpu/fame/famec.c index 9e832bc4e..a2edb3d6e 100644 --- a/cpu/fame/famec.c +++ b/cpu/fame/famec.c @@ -183,6 +183,11 @@ // internals core macros ///////////////////////// +// helper macros +#define BITCOUNT(r,v) \ + (r = (v) - (((v)>>1)&0x55555555), r = (r&0x33333333) + ((r>>2)&0x33333333), \ + r = (((r + (r>>4))&0x0f0f0f0f) * 0x01010101)>>24) + #define XB MEM_LE4(0) #define XW MEM_LE2(0) @@ -525,13 +530,13 @@ static const s32 exception_cycle_table[256] = 50, // 2: Bus Error 50, // 3: Address Error 34, // 4: Illegal Instruction - 38, // 5: Divide by Zero - 40, // 6: CHK + 34, // 5: Divide by Zero + 34, // 6: CHK 34, // 7: TRAPV 34, // 8: Privilege Violation 34, // 9: Trace - 4, // 10: - 4, // 11: + 34, // 10: Line A + 34, // 11: Line F 4, // 12: RESERVED 4, // 13: Coprocessor Protocol Violation 4, // 14: Format Error diff --git a/cpu/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index ffb7c4ed9..d5b9a0421 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -1074,11 +1074,7 @@ OPCODE(0x0280) flag_NotZ = res; flag_N = res >> 24; DREGu32((Opcode >> 0) & 7) = res; -#ifdef USE_CYCLONE_TIMING -RET(14) -#else RET(16) -#endif } // ANDI @@ -1303,7 +1299,11 @@ OPCODE(0x027C) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -1953,7 +1953,11 @@ OPCODE(0x0A7C) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING RET(0) +#else + RET(4) +#endif } RET(20) } @@ -3904,7 +3908,12 @@ OPCODE(0x0840) flag_NotZ = res & src; res ^= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(10) +#else RET(12) +#endif } // BCHGn @@ -4087,7 +4096,12 @@ OPCODE(0x0880) flag_NotZ = res & src; res &= ~src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(12) +#else RET(14) +#endif } // BCLRn @@ -4270,7 +4284,12 @@ OPCODE(0x08C0) flag_NotZ = res & src; res |= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(10) +#else RET(12) +#endif } // BSETn @@ -4663,7 +4682,12 @@ OPCODE(0x0140) flag_NotZ = res & src; res ^= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(6) +#else RET(8) +#endif } // BCHG @@ -4846,7 +4870,12 @@ OPCODE(0x0180) flag_NotZ = res & src; res &= ~src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(8) +#else RET(10) +#endif } // BCLR @@ -5029,7 +5058,12 @@ OPCODE(0x01C0) flag_NotZ = res & src; res |= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(6) +#else RET(8) +#endif } // BSET @@ -16571,7 +16605,11 @@ OPCODE(0x46C0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(12) } @@ -16600,7 +16638,11 @@ OPCODE(0x46D0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16630,7 +16672,11 @@ OPCODE(0x46D8) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16660,7 +16706,11 @@ OPCODE(0x46E0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(18) } @@ -16690,7 +16740,11 @@ OPCODE(0x46E8) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -16720,7 +16774,11 @@ OPCODE(0x46F0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(22) } @@ -16750,7 +16808,11 @@ OPCODE(0x46F8) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -16779,7 +16841,11 @@ OPCODE(0x46F9) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(24) } @@ -16809,7 +16875,11 @@ OPCODE(0x46FA) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -16839,7 +16909,11 @@ OPCODE(0x46FB) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(22) } @@ -16865,7 +16939,11 @@ OPCODE(0x46FC) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16895,7 +16973,11 @@ OPCODE(0x46DF) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16925,7 +17007,11 @@ OPCODE(0x46E7) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(18) } @@ -18327,7 +18413,7 @@ OPCODE(0x4AD0) POST_IO #ifdef USE_CYCLONE_TIMING -RET(18) +RET(14) #else RET(8) #endif @@ -18357,7 +18443,7 @@ OPCODE(0x4AD8) POST_IO #ifdef USE_CYCLONE_TIMING -RET(18) +RET(14) #else RET(8) #endif @@ -18387,7 +18473,7 @@ OPCODE(0x4AE0) POST_IO #ifdef USE_CYCLONE_TIMING -RET(20) +RET(16) #else RET(10) #endif @@ -18417,7 +18503,7 @@ OPCODE(0x4AE8) POST_IO #ifdef USE_CYCLONE_TIMING -RET(22) +RET(18) #else RET(12) #endif @@ -18447,7 +18533,7 @@ OPCODE(0x4AF0) POST_IO #ifdef USE_CYCLONE_TIMING -RET(24) +RET(20) #else RET(14) #endif @@ -18476,7 +18562,7 @@ OPCODE(0x4AF8) POST_IO #ifdef USE_CYCLONE_TIMING -RET(22) +RET(18) #else RET(12) #endif @@ -18505,7 +18591,7 @@ OPCODE(0x4AF9) POST_IO #ifdef USE_CYCLONE_TIMING -RET(26) +RET(22) #else RET(16) #endif @@ -18535,7 +18621,7 @@ OPCODE(0x4ADF) POST_IO #ifdef USE_CYCLONE_TIMING -RET(18) +RET(14) #else RET(8) #endif @@ -18593,7 +18679,7 @@ RET(0) OPCODE(0xF000) { SET_PC(execute_exception(ctx, M68K_1111_EX, GET_PC-2, GET_SR)); -RET(0) // 4 already taken by exc. handler +RET(0) } // MOVEMaR @@ -19154,7 +19240,11 @@ RET(12) OPCODE(0x4E40) { SET_PC(execute_exception(ctx, M68K_TRAP_BASE_EX + (Opcode & 0xF), GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } // LINK @@ -19225,7 +19315,11 @@ OPCODE(0x4E60) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } res = AREGu32((Opcode >> 0) & 7); ASP = res; @@ -19241,7 +19335,11 @@ OPCODE(0x4E68) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } res = ASP; AREG((Opcode >> 0) & 7) = res; @@ -19257,7 +19355,11 @@ OPCODE(0x4E70) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } PRE_IO if (ctx->reset_handler) ctx->reset_handler(); @@ -19281,7 +19383,11 @@ OPCODE(0x4E72) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } FETCH_WORD(res); res &= M68K_SR_MASK; @@ -19305,7 +19411,11 @@ OPCODE(0x4E73) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } PRE_IO POP_16_F(res) @@ -19342,8 +19452,12 @@ RET(16) // TRAPV OPCODE(0x4E76) { - if (flag_V & 0x80) + if (flag_V & 0x80) { SET_PC(execute_exception(ctx, M68K_TRAPV_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#endif + } RET(4) } @@ -19606,6 +19720,7 @@ OPCODE(0x4180) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(4) } RET(10) } @@ -19624,6 +19739,7 @@ OPCODE(0x4190) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19644,6 +19760,7 @@ OPCODE(0x4198) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19664,6 +19781,7 @@ OPCODE(0x41A0) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(10) } POST_IO RET(16) @@ -19684,6 +19802,7 @@ OPCODE(0x41A8) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(12) } POST_IO RET(18) @@ -19704,6 +19823,7 @@ OPCODE(0x41B0) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(14) } POST_IO RET(20) @@ -19723,6 +19843,7 @@ OPCODE(0x41B8) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(12) } POST_IO RET(18) @@ -19742,6 +19863,7 @@ OPCODE(0x41B9) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(16) } POST_IO RET(22) @@ -19762,6 +19884,7 @@ OPCODE(0x41BA) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(12) } POST_IO RET(18) @@ -19782,6 +19905,7 @@ OPCODE(0x41BB) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(14) } POST_IO RET(20) @@ -19799,6 +19923,7 @@ OPCODE(0x41BC) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19819,6 +19944,7 @@ OPCODE(0x419F) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19839,6 +19965,7 @@ OPCODE(0x41A7) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(10) } POST_IO RET(16) @@ -27099,9 +27226,9 @@ OPCODE(0x80C0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(140) +RET(4) #else -RET(10) +RET(14) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27115,7 +27242,7 @@ RET(10) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(140) +RET(10) #else RET(70) #endif @@ -27126,12 +27253,12 @@ RET(70) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(140) +RET(138-BITCOUNT(res,q)*2) #else RET(90) #endif + } } // DIVU @@ -27147,9 +27274,9 @@ OPCODE(0x80D0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27163,7 +27290,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27174,12 +27301,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27196,9 +27323,9 @@ OPCODE(0x80D8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27212,7 +27339,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27223,12 +27350,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27245,9 +27372,9 @@ OPCODE(0x80E0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(10) #else -RET(16) +RET(20) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27261,7 +27388,7 @@ RET(16) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(16) #else RET(76) #endif @@ -27272,12 +27399,12 @@ RET(146) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(144-BITCOUNT(res,q)*2) #else RET(96) #endif + } } // DIVU @@ -27294,9 +27421,9 @@ OPCODE(0x80E8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(12) #else -RET(18) +RET(22) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27310,7 +27437,7 @@ RET(18) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(18) #else RET(78) #endif @@ -27321,12 +27448,12 @@ RET(148) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(146-BITCOUNT(res,q)*2) #else RET(98) #endif + } } // DIVU @@ -27343,9 +27470,9 @@ OPCODE(0x80F0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(14) #else -RET(20) +RET(24) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27359,7 +27486,7 @@ RET(20) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(20) #else RET(80) #endif @@ -27370,12 +27497,12 @@ RET(150) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(148-BITCOUNT(res,q)*2) #else RET(100) #endif + } } // DIVU @@ -27391,9 +27518,9 @@ OPCODE(0x80F8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(12) #else -RET(18) +RET(22) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27407,7 +27534,7 @@ RET(18) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(18) #else RET(78) #endif @@ -27418,12 +27545,12 @@ RET(148) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(146-BITCOUNT(res,q)*2) #else RET(98) #endif + } } // DIVU @@ -27439,9 +27566,9 @@ OPCODE(0x80F9) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(152) +RET(16) #else -RET(22) +RET(26) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27455,7 +27582,7 @@ RET(22) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(152) +RET(22) #else RET(82) #endif @@ -27466,12 +27593,12 @@ RET(152) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(152) +RET(150-BITCOUNT(res,q)*2) #else RET(102) #endif + } } // DIVU @@ -27488,9 +27615,9 @@ OPCODE(0x80FA) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(12) #else -RET(18) +RET(22) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27504,7 +27631,7 @@ RET(18) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(18) #else RET(78) #endif @@ -27515,12 +27642,12 @@ RET(148) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(146-BITCOUNT(res,q)*2) #else RET(98) #endif + } } // DIVU @@ -27537,9 +27664,9 @@ OPCODE(0x80FB) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(14) #else -RET(20) +RET(24) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27553,7 +27680,7 @@ RET(20) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(20) #else RET(80) #endif @@ -27564,12 +27691,12 @@ RET(150) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(148-BITCOUNT(res,q)*2) #else RET(100) #endif + } } // DIVU @@ -27583,9 +27710,9 @@ OPCODE(0x80FC) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27599,7 +27726,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27610,12 +27737,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27632,9 +27759,9 @@ OPCODE(0x80DF) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27648,7 +27775,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27659,12 +27786,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27681,9 +27808,9 @@ OPCODE(0x80E7) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(10) #else -RET(16) +RET(20) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27697,7 +27824,7 @@ RET(16) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(16) #else RET(76) #endif @@ -27708,12 +27835,12 @@ RET(146) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(144-BITCOUNT(res,q)*2) #else RET(96) #endif + } } // DIVS @@ -27727,9 +27854,10 @@ OPCODE(0x81C0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81C0; +RET(4) +#else + RET(14) #endif - RET(10) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27739,9 +27867,10 @@ goto end81C0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81C0; -#endif +RET(16+(dst>>31)*2) +#else RET(50) +#endif } { s32 q, r; @@ -27753,9 +27882,12 @@ goto end81C0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81C0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(16+(dst>>31)*2) +} else RET(152+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(80) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27763,11 +27895,12 @@ goto end81C0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81C0: ctx->io_cycle_counter -= 50; -#endif +RET(152+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(108) +#endif + } } // DIVS @@ -27783,9 +27916,10 @@ OPCODE(0x81D0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81D0; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27795,9 +27929,10 @@ goto end81D0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D0; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -27809,9 +27944,12 @@ goto end81D0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27819,11 +27957,12 @@ goto end81D0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81D0: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -27840,9 +27979,10 @@ OPCODE(0x81D8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81D8; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27852,9 +27992,10 @@ goto end81D8; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D8; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -27866,9 +28007,12 @@ goto end81D8; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D8; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27876,11 +28020,12 @@ goto end81D8; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81D8: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -27897,9 +28042,10 @@ OPCODE(0x81E0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81E0; +RET(10) +#else + RET(20) #endif - RET(16) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27909,9 +28055,10 @@ goto end81E0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E0; -#endif +RET(22+(dst>>31)*2) +#else RET(56) +#endif } { s32 q, r; @@ -27923,9 +28070,12 @@ goto end81E0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(22+(dst>>31)*2) +} else RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(86) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27933,11 +28083,12 @@ goto end81E0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81E0: ctx->io_cycle_counter -= 50; -#endif +RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(114) +#endif + } } // DIVS @@ -27954,9 +28105,10 @@ OPCODE(0x81E8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81E8; +RET(12) +#else + RET(22) #endif - RET(18) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27966,9 +28118,10 @@ goto end81E8; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E8; -#endif +RET(24+(dst>>31)*2) +#else RET(58) +#endif } { s32 q, r; @@ -27980,9 +28133,12 @@ goto end81E8; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E8; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(24+(dst>>31)*2) +} else RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(88) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27990,11 +28146,12 @@ goto end81E8; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81E8: ctx->io_cycle_counter -= 50; -#endif +RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(116) +#endif + } } // DIVS @@ -28011,9 +28168,10 @@ OPCODE(0x81F0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81F0; +RET(14) +#else + RET(24) #endif - RET(20) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28023,9 +28181,10 @@ goto end81F0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F0; -#endif +RET(26+(dst>>31)*2) +#else RET(60) +#endif } { s32 q, r; @@ -28037,9 +28196,12 @@ goto end81F0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(26+(dst>>31)*2) +} else RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(90) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28047,11 +28209,12 @@ goto end81F0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81F0: ctx->io_cycle_counter -= 50; -#endif +RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(118) +#endif + } } // DIVS @@ -28067,9 +28230,10 @@ OPCODE(0x81F8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81F8; +RET(12) +#else + RET(22) #endif - RET(18) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28079,9 +28243,10 @@ goto end81F8; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F8; -#endif +RET(24+(dst>>31)*2) +#else RET(58) +#endif } { s32 q, r; @@ -28093,9 +28258,12 @@ goto end81F8; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F8; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(24+(dst>>31)*2) +} else RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(88) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28103,11 +28271,12 @@ goto end81F8; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81F8: ctx->io_cycle_counter -= 50; -#endif +RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(116) +#endif + } } // DIVS @@ -28123,9 +28292,10 @@ OPCODE(0x81F9) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81F9; +RET(16) +#else + RET(26) #endif - RET(22) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28135,9 +28305,10 @@ goto end81F9; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F9; -#endif +RET(28+(dst>>31)*2) +#else RET(62) +#endif } { s32 q, r; @@ -28149,9 +28320,12 @@ goto end81F9; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F9; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(28+(dst>>31)*2) +} else RET(164+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(92) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28159,11 +28333,12 @@ goto end81F9; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81F9: ctx->io_cycle_counter -= 50; -#endif +RET(164+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(120) +#endif + } } // DIVS @@ -28180,9 +28355,10 @@ OPCODE(0x81FA) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81FA; +RET(12) +#else + RET(22) #endif - RET(18) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28192,9 +28368,10 @@ goto end81FA; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FA; -#endif +RET(24+(dst>>31)*2) +#else RET(58) +#endif } { s32 q, r; @@ -28206,9 +28383,12 @@ goto end81FA; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FA; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(24+(dst>>31)*2) +} else RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(88) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28216,11 +28396,12 @@ goto end81FA; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81FA: ctx->io_cycle_counter -= 50; -#endif +RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(116) +#endif + } } // DIVS @@ -28237,9 +28418,10 @@ OPCODE(0x81FB) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81FB; +RET(14) +#else + RET(24) #endif - RET(20) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28249,9 +28431,10 @@ goto end81FB; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FB; -#endif +RET(26+(dst>>31)*2) +#else RET(60) +#endif } { s32 q, r; @@ -28263,9 +28446,12 @@ goto end81FB; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FB; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(26+(dst>>31)*2) +} else RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(90) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28273,11 +28459,12 @@ goto end81FB; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81FB: ctx->io_cycle_counter -= 50; -#endif +RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(118) +#endif + } } // DIVS @@ -28291,9 +28478,10 @@ OPCODE(0x81FC) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81FC; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28303,9 +28491,10 @@ goto end81FC; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FC; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -28317,9 +28506,12 @@ goto end81FC; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FC; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28327,11 +28519,12 @@ goto end81FC; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81FC: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -28348,9 +28541,10 @@ OPCODE(0x81DF) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81DF; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28360,9 +28554,10 @@ goto end81DF; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81DF; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -28374,9 +28569,12 @@ goto end81DF; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81DF; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28384,11 +28582,12 @@ goto end81DF; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81DF: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -28405,9 +28604,10 @@ OPCODE(0x81E7) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81E7; +RET(10) +#else + RET(20) #endif - RET(16) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28417,9 +28617,10 @@ goto end81E7; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E7; -#endif +RET(22+(dst>>31)*2) +#else RET(56) +#endif } { s32 q, r; @@ -28431,9 +28632,12 @@ goto end81E7; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E7; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(22+(dst>>31)*2) +} else RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(86) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28441,11 +28645,12 @@ goto end81E7; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81E7: ctx->io_cycle_counter -= 50; -#endif +RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(114) +#endif + } } // SUBaD @@ -34309,7 +34514,7 @@ OPCODE(0xC0C0) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(54) +RET(38+BITCOUNT(res,src)*2) #else RET(50) #endif @@ -34332,7 +34537,7 @@ OPCODE(0xC0D0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34356,7 +34561,7 @@ OPCODE(0xC0D8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34380,7 +34585,7 @@ OPCODE(0xC0E0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src)*2) #else RET(56) #endif @@ -34404,7 +34609,7 @@ OPCODE(0xC0E8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src)*2) #else RET(58) #endif @@ -34428,7 +34633,7 @@ OPCODE(0xC0F0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src)*2) #else RET(60) #endif @@ -34451,7 +34656,7 @@ OPCODE(0xC0F8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src)*2) #else RET(58) #endif @@ -34474,7 +34679,7 @@ OPCODE(0xC0F9) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(66) +RET(50+BITCOUNT(res,src)*2) #else RET(62) #endif @@ -34498,7 +34703,7 @@ OPCODE(0xC0FA) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src)*2) #else RET(58) #endif @@ -34522,7 +34727,7 @@ OPCODE(0xC0FB) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src)*2) #else RET(60) #endif @@ -34542,7 +34747,7 @@ OPCODE(0xC0FC) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34566,7 +34771,7 @@ OPCODE(0xC0DF) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34590,7 +34795,7 @@ OPCODE(0xC0E7) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src)*2) #else RET(56) #endif @@ -34610,7 +34815,7 @@ OPCODE(0xC1C0) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(54) +RET(38+BITCOUNT(res,src^(src<<1))) #else RET(50) #endif @@ -34633,7 +34838,7 @@ OPCODE(0xC1D0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34657,7 +34862,7 @@ OPCODE(0xC1D8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34681,7 +34886,7 @@ OPCODE(0xC1E0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src^(src<<1))*2) #else RET(56) #endif @@ -34705,7 +34910,7 @@ OPCODE(0xC1E8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src^(src<<1))*2) #else RET(58) #endif @@ -34729,7 +34934,7 @@ OPCODE(0xC1F0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src^(src<<1))*2) #else RET(60) #endif @@ -34752,7 +34957,7 @@ OPCODE(0xC1F8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src^(src<<1))*2) #else RET(58) #endif @@ -34775,7 +34980,7 @@ OPCODE(0xC1F9) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(66) +RET(50+BITCOUNT(res,src^(src<<1))*2) #else RET(62) #endif @@ -34799,7 +35004,7 @@ OPCODE(0xC1FA) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src^(src<<1))*2) #else RET(58) #endif @@ -34823,7 +35028,7 @@ OPCODE(0xC1FB) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src^(src<<1))*2) #else RET(60) #endif @@ -34843,7 +35048,7 @@ OPCODE(0xC1FC) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34867,7 +35072,7 @@ OPCODE(0xC1DF) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34891,7 +35096,7 @@ OPCODE(0xC1E7) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src^(src<<1))*2) #else RET(56) #endif From 8cca318242ba13c40b1a362f321eae898923f9df Mon Sep 17 00:00:00 2001 From: saulfabreg Wii VC Project Date: Fri, 8 Mar 2024 13:32:10 -0500 Subject: [PATCH 50/66] Libretro: Fix Wii compiling by adding required -ffat-lto-objects Otherwise when compiling the final dol will result in compilation errors because of missing Libretro dependencies. (dirty, quick-fix) workaround for stop the compiler messages of "plugin needed to handle lto object" --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index 60e6bfdd1..d849be811 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -276,7 +276,7 @@ else ifeq ($(platform), wii) TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float + CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -ffat-lto-objects STATIC_LINKING = 1 STATIC_LINKING_LINK = 1 From eac7a97e4fde429a0490429fe949290ecd104702 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 9 Mar 2024 22:04:16 +0200 Subject: [PATCH 51/66] drc: align tcache_default to 64k on arm Newer arm64 hw supports 64k pages, and recent Linux distros provide kernel packages like linux-image-generic-64k (can be used on r-pi4 with Ubuntu for example). It affects 32bit mode also, so assume that an arm32 binary compiled for vfp may be used on such kernel. Without this mprotect() fails to set exec permission because of bad alignment. --- cpu/drc/cmn.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cpu/drc/cmn.c b/cpu/drc/cmn.c index 3f174a031..b0b7308f8 100644 --- a/cpu/drc/cmn.c +++ b/cpu/drc/cmn.c @@ -10,7 +10,13 @@ #include #include "cmn.h" -u8 ALIGNED(4096) tcache_default[DRC_TCACHE_SIZE]; +#if defined(__aarch64__) || defined(__VFP_FP__) +// might be running on a 64k-page kernel +#define PICO_PAGE_ALIGN 65536 +#else +#define PICO_PAGE_ALIGN 4096 +#endif +u8 ALIGNED(PICO_PAGE_ALIGN) tcache_default[DRC_TCACHE_SIZE]; u8 *tcache; void drc_cmn_init(void) From 5adcc165343cf344cd4bb02da5a0f3839a9fbec3 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 10 Mar 2024 01:26:06 +0000 Subject: [PATCH 52/66] 68k, some fixes for musashi --- cpu/cyclone | 2 +- cpu/musashi/m68kcpu.c | 6 +++--- cpu/musashi/m68kcpu.h | 10 +++++++--- pico/pico_int.h | 3 +++ platform/common/common.mak | 1 + 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cpu/cyclone b/cpu/cyclone index ee45bb2b1..3ac7cf1bd 160000 --- a/cpu/cyclone +++ b/cpu/cyclone @@ -1 +1 @@ -Subproject commit ee45bb2b10b3abf10a4335ea24fc029e3f61c10a +Subproject commit 3ac7cf1bdeecb60e2414980e8dc72ff092f69769 diff --git a/cpu/musashi/m68kcpu.c b/cpu/musashi/m68kcpu.c index d729f2cfa..1415d0d3d 100644 --- a/cpu/musashi/m68kcpu.c +++ b/cpu/musashi/m68kcpu.c @@ -787,12 +787,12 @@ void m68k_set_cpu_type(unsigned int cpu_type) /* ASG: removed per-instruction interrupt checks */ int m68k_execute(int num_cycles) { + // notaz + m68ki_check_interrupts(); + /* Make sure we're not stopped */ if(!CPU_STOPPED) { - // notaz - m68ki_check_interrupts(); - /* Set our pool of clock cycles available */ SET_CYCLES(num_cycles); m68ki_initial_cycles = num_cycles; diff --git a/cpu/musashi/m68kcpu.h b/cpu/musashi/m68kcpu.h index 6ab0ba0b6..3b40765f2 100644 --- a/cpu/musashi/m68kcpu.h +++ b/cpu/musashi/m68kcpu.h @@ -71,8 +71,12 @@ typedef uint8_t UINT8; #define uint32 unsigned int /* AWJ: changed from long to int */ /* signed and unsigned int must be at least 32 bits wide */ -#define sint signed int -#define uint unsigned int +//#define sint signed int +//#define uint unsigned int +#define sint _sint +#define uint _uint +typedef signed int sint; +typedef unsigned int uint; #if M68K_USE_64_BIT @@ -1537,7 +1541,7 @@ INLINE void m68ki_set_sr_noint_nosp(uint value) INLINE void m68ki_set_sr(uint value) { m68ki_set_sr_noint(value); - if (GET_CYCLES() >= 0) // notaz + if (GET_CYCLES() > 0) // notaz m68ki_check_interrupts(); } diff --git a/pico/pico_int.h b/pico/pico_int.h index 80c00fbfd..5535e1429 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -91,6 +91,9 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; #ifdef EMU_M68K #include +#undef INLINE +#undef USE_CYCLES +#undef ADD_CYCLES extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #ifndef SekCyclesLeft #define SekCyclesLeft PicoCpuMM68k.cyc_remaining_cycles diff --git a/platform/common/common.mak b/platform/common/common.mak index 550de72f9..36053129b 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -207,6 +207,7 @@ $(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/cyclone/*.cpp $(FR)cpu/cyclone/*.h $(FR)cpu/musashi/m68kops.c: @make -C $(R)cpu/musashi +$(FR)cpu/musashi/m68kcpu.c: $(FR)cpu/musashi/m68kops.c deps_set = yes endif # deps_set From 1ab87d2b9a7bff3f5342dcc85db74b433e27153b Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 14 Mar 2024 20:51:19 +0100 Subject: [PATCH 53/66] core 68k, minor improvement for division in fame --- cpu/fame/famec_opcodes.h | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/cpu/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index d5b9a0421..7a7832cfc 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -27884,7 +27884,7 @@ RET(16+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(16+(dst>>31)*2) -} else RET(152+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(152+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(80) #endif @@ -27896,7 +27896,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(152+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(152+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(108) #endif @@ -27946,7 +27946,7 @@ RET(20+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(20+(dst>>31)*2) -} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(84) #endif @@ -27958,7 +27958,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(112) #endif @@ -28009,7 +28009,7 @@ RET(20+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(20+(dst>>31)*2) -} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(84) #endif @@ -28021,7 +28021,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(112) #endif @@ -28072,7 +28072,7 @@ RET(22+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(22+(dst>>31)*2) -} else RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(86) #endif @@ -28084,7 +28084,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(114) #endif @@ -28135,7 +28135,7 @@ RET(24+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(24+(dst>>31)*2) -} else RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(88) #endif @@ -28147,7 +28147,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(116) #endif @@ -28198,7 +28198,7 @@ RET(26+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(26+(dst>>31)*2) -} else RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(90) #endif @@ -28210,7 +28210,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(118) #endif @@ -28260,7 +28260,7 @@ RET(24+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(24+(dst>>31)*2) -} else RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(88) #endif @@ -28272,7 +28272,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(116) #endif @@ -28322,7 +28322,7 @@ RET(28+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(28+(dst>>31)*2) -} else RET(164+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(164+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(92) #endif @@ -28334,7 +28334,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(164+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(164+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(120) #endif @@ -28385,7 +28385,7 @@ RET(24+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(24+(dst>>31)*2) -} else RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(88) #endif @@ -28397,7 +28397,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(160+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(116) #endif @@ -28448,7 +28448,7 @@ RET(26+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(26+(dst>>31)*2) -} else RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(90) #endif @@ -28460,7 +28460,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(162+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(118) #endif @@ -28508,7 +28508,7 @@ RET(20+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(20+(dst>>31)*2) -} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(84) #endif @@ -28520,7 +28520,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(112) #endif @@ -28571,7 +28571,7 @@ RET(20+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(20+(dst>>31)*2) -} else RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(84) #endif @@ -28583,7 +28583,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(156+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(112) #endif @@ -28634,7 +28634,7 @@ RET(22+(dst>>31)*2) #ifdef USE_CYCLONE_TIMING_DIV if (q > 0xFFFF || q < -0x10000) { RET(22+(dst>>31)*2) -} else RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +} else RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(86) #endif @@ -28646,7 +28646,7 @@ if (q > 0xFFFF || q < -0x10000) { res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -RET(158+(dst>>31)*4+((src^dst)>>31)*2-BITCOUNT(res,abs(q))*2) +RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) #else RET(114) #endif From 8b0e2b4f9ad588408fe3957425a8933b705fc6dd Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 14 Mar 2024 23:10:33 +0100 Subject: [PATCH 54/66] core 68k, make musashi timing more similar to fame --- cpu/musashi/m68k_in.c | 159 ++++++++++++++++++++++++++++++------- cpu/musashi/m68kcpu.c | 24 +++--- platform/common/common.mak | 2 +- 3 files changed, 145 insertions(+), 40 deletions(-) diff --git a/cpu/musashi/m68k_in.c b/cpu/musashi/m68k_in.c index 14c1347d2..04fedf876 100644 --- a/cpu/musashi/m68k_in.c +++ b/cpu/musashi/m68k_in.c @@ -257,11 +257,62 @@ void m68ki_build_opcode_table(void) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX M68KMAKE_OPCODE_HANDLER_HEADER +#include #include "m68kcpu.h" extern void m68040_fpu_op0(void); extern void m68040_fpu_op1(void); +/* Count non-0 bits */ +INLINE int m68ki_bit_count(uint32 arg) +{ + arg = arg - ((arg>>1)&0x55555555); + arg = (arg&0x33333333) + ((arg>>2)&0x33333333); + return (((arg + (arg>>4))&0x0f0f0f0f) * 0x01010101) >> 24; +} + +INLINE int m68ki_mulu_cycles(uint32 arg) +{ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return m68ki_bit_count(arg) * 2; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return m68ki_bit_count(arg); /* guesswork */ + else + return m68ki_bit_count(arg) / 2; /* guesswork */ +} + +INLINE int m68ki_muls_cycles(sint32 arg) +{ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return m68ki_bit_count(arg ^ (arg<<1)) * 2; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return m68ki_bit_count(arg ^ (arg<<1)); /* guesswork */ + else + return m68ki_bit_count(arg ^ (arg<<1)) / 2; /* guesswork */ +} + +INLINE int m68ki_divu_cycles(uint32 arg) +{ + /* approximation only. Doesn't factor in shorter cycles by carry */ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return 128 - m68ki_bit_count(arg) * 2; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return 96; /* guesswork */ + else + return 32; /* guesswork */ +} + +INLINE int m68ki_divs_cycles(uint32 scyc, sint32 arg) +{ + /* approximation only. Doesn't factor in shorter cycles by carry */ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return 128 - m68ki_bit_count(abs(arg)) * 2 + scyc*2 + 8; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return 96 + scyc*2 + 8; /* guesswork */ + else + return 32 + scyc + 4; /* guesswork */ +} + /* ======================================================================== */ /* ========================= INSTRUCTION HANDLERS ========================= */ /* ======================================================================== */ @@ -418,7 +469,7 @@ andi 8 . d 0000001000000... .......... U U U U 8 8 2 2 andi 8 . . 0000001000...... A+-DXWL... U U U U 12 12 4 4 andi 16 . d 0000001001000... .......... U U U U 8 8 2 2 andi 16 . . 0000001001...... A+-DXWL... U U U U 12 12 4 4 -andi 32 . d 0000001010000... .......... U U U U 14 14 2 2 +andi 32 . d 0000001010000... .......... U U U U 16 14 2 2 andi 32 . . 0000001010...... A+-DXWL... U U U U 20 20 4 4 asr 8 s . 1110...000000... .......... U U U U 6 6 6 6 asr 16 s . 1110...001000... .......... U U U U 6 6 6 6 @@ -438,13 +489,13 @@ bcc 8 . . 0110............ .......... U U U U 10 10 6 6 bcc 16 . . 0110....00000000 .......... U U U U 10 10 6 6 bcc 32 . . 0110....11111111 .......... U U U U 10 10 6 6 bchg 8 r . 0000...101...... A+-DXWL... U U U U 8 8 4 4 -bchg 32 r d 0000...101000... .......... U U U U 8 8 4 4 +bchg 32 r d 0000...101000... .......... U U U U 6 6 4 4 bchg 8 s . 0000100001...... A+-DXWL... U U U U 12 12 4 4 -bchg 32 s d 0000100001000... .......... U U U U 12 12 4 4 -bclr 8 r . 0000...110...... A+-DXWL... U U U U 8 10 4 4 -bclr 32 r d 0000...110000... .......... U U U U 10 10 4 4 +bchg 32 s d 0000100001000... .......... U U U U 10 10 4 4 +bclr 8 r . 0000...110...... A+-DXWL... U U U U 8 8 4 4 +bclr 32 r d 0000...110000... .......... U U U U 8 8 4 4 bclr 8 s . 0000100010...... A+-DXWL... U U U U 12 12 4 4 -bclr 32 s d 0000100010000... .......... U U U U 14 14 4 4 +bclr 32 s d 0000100010000... .......... U U U U 12 12 4 4 bfchg 32 . d 1110101011000... .......... . . U U . . 12 12 timing not quite correct bfchg 32 . . 1110101011...... A..DXWL... . . U U . . 20 20 bfclr 32 . d 1110110011000... .......... . . U U . . 12 12 @@ -465,10 +516,10 @@ bkpt 0 . . 0100100001001... .......... . U U U . 10 10 10 bra 8 . . 01100000........ .......... U U U U 10 10 10 10 bra 16 . . 0110000000000000 .......... U U U U 10 10 10 10 bra 32 . . 0110000011111111 .......... U U U U 10 10 10 10 -bset 32 r d 0000...111000... .......... U U U U 8 8 4 4 +bset 32 r d 0000...111000... .......... U U U U 6 6 4 4 bset 8 r . 0000...111...... A+-DXWL... U U U U 8 8 4 4 bset 8 s . 0000100011...... A+-DXWL... U U U U 12 12 4 4 -bset 32 s d 0000100011000... .......... U U U U 12 12 4 4 +bset 32 s d 0000100011000... .......... U U U U 10 10 4 4 bsr 8 . . 01100001........ .......... U U U U 18 18 7 7 bsr 16 . . 0110000100000000 .......... U U U U 18 18 7 7 bsr 32 . . 0110000111111111 .......... U U U U 18 18 7 7 @@ -482,8 +533,8 @@ cas 16 . . 0000110011...... A+-DXWL... . . U U . . 12 12 cas 32 . . 0000111011...... A+-DXWL... . . U U . . 12 12 cas2 16 . . 0000110011111100 .......... . . U U . . 12 12 cas2 32 . . 0000111011111100 .......... . . U U . . 12 12 -chk 16 . d 0100...110000... .......... U U U U 10 8 8 8 -chk 16 . . 0100...110...... A+-DXWLdxI U U U U 10 8 8 8 +chk 16 . d 0100...110000... .......... U U U U 4 2 2 2 +chk 16 . . 0100...110...... A+-DXWLdxI U U U U 4 2 2 2 chk 32 . d 0100...100000... .......... . . U U . . 8 8 chk 32 . . 0100...100...... A+-DXWLdxI . . U U . . 8 8 chk2cmp2 8 . pcdi 0000000011111010 .......... . . U U . . 23 23 @@ -541,10 +592,10 @@ cptrapcc 32 . . 1111...001111... .......... . . U . . . 4 . dbt 16 . . 0101000011001... .......... U U U U 12 12 6 6 dbf 16 . . 0101000111001... .......... U U U U 12 12 6 6 dbcc 16 . . 0101....11001... .......... U U U U 12 12 6 6 -divs 16 . d 1000...111000... .......... U U U U 158 122 56 56 -divs 16 . . 1000...111...... A+-DXWLdxI U U U U 158 122 56 56 -divu 16 . d 1000...011000... .......... U U U U 140 108 44 44 -divu 16 . . 1000...011...... A+-DXWLdxI U U U U 140 108 44 44 +divs 16 . d 1000...111000... .......... U U U U 16 16 16 16 cycles depending on operands +divs 16 . . 1000...111...... A+-DXWLdxI U U U U 16 16 16 16 cycles depending on operands +divu 16 . d 1000...011000... .......... U U U U 10 10 10 10 cycles depending on operands +divu 16 . . 1000...011...... A+-DXWLdxI U U U U 10 10 10 10 cycles depending on operands divl 32 . d 0100110001000... .......... . . U U . . 84 84 divl 32 . . 0100110001...... A+-DXWLdxI . . U U . . 84 84 eor 8 . d 1011...100000... .......... U U U U 4 4 2 2 @@ -696,10 +747,10 @@ moves 8 . . 0000111000...... A+-DXWL... . S S S . 14 5 5 moves 16 . . 0000111001...... A+-DXWL... . S S S . 14 5 5 moves 32 . . 0000111010...... A+-DXWL... . S S S . 16 5 5 move16 32 . . 1111011000100... .......... . . . U . . . 4 TODO: correct timing -muls 16 . d 1100...111000... .......... U U U U 54 32 27 27 -muls 16 . . 1100...111...... A+-DXWLdxI U U U U 54 32 27 27 -mulu 16 . d 1100...011000... .......... U U U U 54 30 27 27 -mulu 16 . . 1100...011...... A+-DXWLdxI U U U U 54 30 27 27 +muls 16 . d 1100...111000... .......... U U U U 38 28 20 20 cycles depending on operands +muls 16 . . 1100...111...... A+-DXWLdxI U U U U 38 28 20 20 cycles depending on operands +mulu 16 . d 1100...011000... .......... U U U U 38 26 20 20 cycles depending on operands +mulu 16 . . 1100...011...... A+-DXWLdxI U U U U 38 26 20 20 cycles depending on operands mull 32 . d 0100110000000... .......... . . U U . . 43 43 mull 32 . . 0100110000...... A+-DXWLdxI . . U U . . 43 43 nbcd 8 . d 0100100000000... .......... U U U U 6 6 6 6 @@ -835,7 +886,7 @@ subx 16 mm . 1001...101001... .......... U U U U 18 18 12 12 subx 32 mm . 1001...110001... .......... U U U U 30 30 12 12 swap 32 . . 0100100001000... .......... U U U U 4 4 4 4 tas 8 . d 0100101011000... .......... U U U U 4 4 4 4 -tas 8 . . 0100101011...... A+-DXWL... U U U U 14 14 12 12 +tas 8 . . 0100101011...... A+-DXWL... U U U U 10 10 8 8 trap 0 . . 010011100100.... .......... U U U U 4 4 4 4 trapt 0 . . 0101000011111100 .......... . . U U . . 4 4 trapt 16 . . 0101000011111010 .......... . . U U . . 6 6 @@ -2332,6 +2383,8 @@ M68KMAKE_OP(bchg, 32, r, d) uint* r_dst = &DY; uint mask = 1 << (DX & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst ^= mask; } @@ -2353,6 +2406,8 @@ M68KMAKE_OP(bchg, 32, s, d) uint* r_dst = &DY; uint mask = 1 << (OPER_I_8() & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst ^= mask; } @@ -2374,6 +2429,8 @@ M68KMAKE_OP(bclr, 32, r, d) uint* r_dst = &DY; uint mask = 1 << (DX & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst &= ~mask; } @@ -2395,6 +2452,8 @@ M68KMAKE_OP(bclr, 32, s, d) uint* r_dst = &DY; uint mask = 1 << (OPER_I_8() & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst &= ~mask; } @@ -3182,6 +3241,8 @@ M68KMAKE_OP(bset, 32, r, d) uint* r_dst = &DY; uint mask = 1 << (DX & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst |= mask; } @@ -3203,6 +3264,8 @@ M68KMAKE_OP(bset, 32, s, d) uint* r_dst = &DY; uint mask = 1 << (OPER_I_8() & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst |= mask; } @@ -3490,6 +3553,7 @@ M68KMAKE_OP(chk, 16, ., d) if(src >= 0 && src <= bound) { + USE_CYCLES(6); return; } FLAG_N = (src < 0)<<7; @@ -3508,6 +3572,7 @@ M68KMAKE_OP(chk, 16, ., .) if(src >= 0 && src <= bound) { + USE_CYCLES(6); return; } FLAG_N = (src < 0)<<7; @@ -4487,8 +4552,10 @@ M68KMAKE_OP(divs, 16, ., d) { uint* r_dst = &DX; sint src = MAKE_INT_16(DY); + sint dst = MAKE_INT_32(*r_dst); sint quotient; sint remainder; + int cycles; if(src != 0) { @@ -4499,12 +4566,21 @@ M68KMAKE_OP(divs, 16, ., d) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = 0; + USE_CYCLES(m68ki_divs_cycles(2, 0)); return; } - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; + if(abs(dst) >= abs(src<<16)) + { + FLAG_V = VFLAG_SET; + USE_CYCLES(2*(dst < 0)); + return; + } + + quotient = dst / src; + remainder = dst % src; + cycles = m68ki_divs_cycles(2*(dst < 0) + (quotient < 0), quotient); if(quotient == MAKE_INT_16(quotient)) { FLAG_Z = quotient; @@ -4512,12 +4588,15 @@ M68KMAKE_OP(divs, 16, ., d) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(cycles); return; } FLAG_V = VFLAG_SET; + USE_CYCLES(cycles); return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(12); } @@ -4525,8 +4604,10 @@ M68KMAKE_OP(divs, 16, ., .) { uint* r_dst = &DX; sint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + sint dst = MAKE_INT_32(*r_dst); sint quotient; sint remainder; + int cycles; if(src != 0) { @@ -4537,12 +4618,21 @@ M68KMAKE_OP(divs, 16, ., .) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = 0; + USE_CYCLES(m68ki_divs_cycles(2, 0)); + return; + } + + if(abs(dst) >= abs(src<<16)) + { + FLAG_V = VFLAG_SET; + USE_CYCLES(2*(dst < 0)); return; } - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; + quotient = dst / src; + remainder = dst % src; + cycles = m68ki_divs_cycles(2*(dst < 0) + (quotient < 0), quotient); if(quotient == MAKE_INT_16(quotient)) { FLAG_Z = quotient; @@ -4550,12 +4640,15 @@ M68KMAKE_OP(divs, 16, ., .) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(cycles); return; } FLAG_V = VFLAG_SET; + USE_CYCLES(cycles); return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(12); } @@ -4576,12 +4669,14 @@ M68KMAKE_OP(divu, 16, ., d) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(m68ki_divu_cycles(quotient)); return; } FLAG_V = VFLAG_SET; return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(6); } @@ -4602,12 +4697,14 @@ M68KMAKE_OP(divu, 16, ., .) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(m68ki_divu_cycles(quotient)); return; } FLAG_V = VFLAG_SET; return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(6); } @@ -7500,9 +7597,11 @@ M68KMAKE_OP(move16, 32, ., .) M68KMAKE_OP(muls, 16, ., d) { uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + uint x = MAKE_INT_16(DY); + uint res = MASK_OUT_ABOVE_32(x * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); *r_dst = res; + USE_CYCLES(m68ki_muls_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); @@ -7514,9 +7613,11 @@ M68KMAKE_OP(muls, 16, ., d) M68KMAKE_OP(muls, 16, ., .) { uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + uint x = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + uint res = MASK_OUT_ABOVE_32(x * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); *r_dst = res; + USE_CYCLES(m68ki_muls_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); @@ -7528,9 +7629,11 @@ M68KMAKE_OP(muls, 16, ., .) M68KMAKE_OP(mulu, 16, ., d) { uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); + uint x = MASK_OUT_ABOVE_16(DY); + uint res = x * MASK_OUT_ABOVE_16(*r_dst); *r_dst = res; + USE_CYCLES(m68ki_mulu_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); @@ -7542,9 +7645,11 @@ M68KMAKE_OP(mulu, 16, ., d) M68KMAKE_OP(mulu, 16, ., .) { uint* r_dst = &DX; - uint res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst); + uint x = M68KMAKE_GET_OPER_AY_16; + uint res = x * MASK_OUT_ABOVE_16(*r_dst); *r_dst = res; + USE_CYCLES(m68ki_mulu_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); diff --git a/cpu/musashi/m68kcpu.c b/cpu/musashi/m68kcpu.c index 1415d0d3d..1ac1a5d95 100644 --- a/cpu/musashi/m68kcpu.c +++ b/cpu/musashi/m68kcpu.c @@ -133,13 +133,13 @@ uint8 m68ki_exception_cycle_table[4][256] = 50, /* 2: Bus Error (unemulated) */ 50, /* 3: Address Error (unemulated) */ 34, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero -- ASG: changed from 42 */ - 40, /* 6: CHK -- ASG: chanaged from 44 */ + 34, /* 5: Divide by Zero -- ASG: changed from 42 */ + 34, /* 6: CHK -- ASG: chanaged from 44 */ 34, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 34, /* 9: Trace */ - 4, /* 10: 1010 */ - 4, /* 11: 1111 */ + 34, /* 10: 1010 */ + 34, /* 11: 1111 */ 4, /* 12: RESERVED */ 4, /* 13: Coprocessor Protocol Violation (unemulated) */ 4, /* 14: Format Error */ @@ -206,13 +206,13 @@ uint8 m68ki_exception_cycle_table[4][256] = 126, /* 2: Bus Error (unemulated) */ 126, /* 3: Address Error (unemulated) */ 38, /* 4: Illegal Instruction */ - 44, /* 5: Divide by Zero */ - 44, /* 6: CHK */ + 38, /* 5: Divide by Zero */ + 38, /* 6: CHK */ 34, /* 7: TRAPV */ 38, /* 8: Privilege Violation */ 38, /* 9: Trace */ - 4, /* 10: 1010 */ - 4, /* 11: 1111 */ + 38, /* 10: 1010 */ + 38, /* 11: 1111 */ 4, /* 12: RESERVED */ 4, /* 13: Coprocessor Protocol Violation (unemulated) */ 4, /* 14: Format Error */ @@ -279,8 +279,8 @@ uint8 m68ki_exception_cycle_table[4][256] = 50, /* 2: Bus Error (unemulated) */ 50, /* 3: Address Error (unemulated) */ 20, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ + 34, /* 5: Divide by Zero */ + 34, /* 6: CHK */ 20, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 25, /* 9: Trace */ @@ -352,8 +352,8 @@ uint8 m68ki_exception_cycle_table[4][256] = 50, /* 2: Bus Error (unemulated) */ 50, /* 3: Address Error (unemulated) */ 20, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ + 34, /* 5: Divide by Zero */ + 34, /* 6: CHK */ 20, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 25, /* 9: Trace */ diff --git a/platform/common/common.mak b/platform/common/common.mak index 36053129b..68ca6ff6b 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -205,7 +205,7 @@ $(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/$(CYCLONE_CONFIG) $(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/cyclone/*.cpp $(FR)cpu/cyclone/*.h -$(FR)cpu/musashi/m68kops.c: +$(FR)cpu/musashi/m68kops.c: $(FR)cpu/musashi/m68k_in.c @make -C $(R)cpu/musashi $(FR)cpu/musashi/m68kcpu.c: $(FR)cpu/musashi/m68kops.c From 71f9c68f5b5888ea6b2178a8a4995633621367f0 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 14 Mar 2024 23:15:16 +0100 Subject: [PATCH 55/66] core z80, improve timing for bus request/grant timing from 68k --- pico/memory.c | 18 +++++++++++++----- pico/pico_cmn.c | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index 693f96035..bedcc1d33 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -521,13 +521,19 @@ void NOINLINE ctl_write_z80busreq(u32 d) { if (d) { - Pico.t.z80c_cnt = z80_cycles_from_68k() + 1; + Pico.t.z80c_cnt = z80_cycles_from_68k() + (Pico.t.z80_busdelay >> 8); + 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 + // simulate this by accumulating the last insn overhang in busdelay + unsigned granted = z80_cycles_from_68k() + 6; pprof_start(m68k); PicoSyncZ80(SekCyclesDone()); + Pico.t.z80_busdelay += (Pico.t.z80c_cnt - granted) << 8; + Pico.t.z80c_cnt = granted; pprof_end_sub(m68k); } } @@ -553,7 +559,7 @@ void NOINLINE ctl_write_z80reset(u32 d) } else { - Pico.t.z80c_cnt = z80_cycles_from_68k() + 1; + Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; z80_reset(); } Pico.m.z80_reset = d; @@ -675,7 +681,8 @@ static void PicoWrite16_sram(u32 a, u32 d) static u32 PicoRead8_z80(u32 a) { u32 d = 0xff; - if ((Pico.m.z80Run | Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { + if ((Pico.m.z80Run | Pico.m.z80_reset | (z80_cycles_from_68k() < Pico.t.z80c_cnt)) && + !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); // open bus. Pulled down if MegaCD2 is attached. return (PicoIn.AHW & PAHW_MCD ? 0 : d); @@ -759,7 +766,7 @@ u32 PicoRead8_io(u32 a) // bit8 seems to be readable in this range if (!(a & 1)) { d &= ~0x01; - // Z80 ahead of 68K only if in BUSREQ, BUSACK only after 68K reached Z80 + // Z80 ahead of 68K only if in BUSREQ, BUSACK only after 68K reached Z80 d |= (z80_cycles_from_68k() < Pico.t.z80c_cnt); d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc); @@ -1356,8 +1363,9 @@ static void access_68k_bus(int delay) // bus delay as Q8 // 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. - Pico.t.z80_busdelay = (delay&0xff) + (Pico.t.z80_busdelay&0xff); // accumulate + Pico.t.z80_busdelay += (delay&0xff); // accumulate z80_subCLeft((delay>>8) + (Pico.t.z80_busdelay>>8)); + Pico.t.z80_busdelay &= 0xff; // leftover cycle fraction // don't use SekCyclesBurn() here since the Z80 doesn't run in cycle lock to // the 68K. Count the stolen cycles to be accounted later in the 68k CPU runs Pico.t.z80_buscycles += 8; diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 29fc82ceb..c3b14caa6 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -80,7 +80,7 @@ static __inline void SekAimM68k(int cyc, int mult) static __inline void SekRunM68k(int cyc) { - // TODO 0x100 would by 2 cycles/128, moreover far too sensitive + // TODO 0x100 would be 2 cycles/128, moreover far too sensitive SekAimM68k(cyc, 0x10c); // OutRunners, testpico, VDPFIFOTesting SekSyncM68k(0); } From 9f29605f55460e6f5094e41d74ce4f7726097237 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 16 Mar 2024 15:58:38 +0100 Subject: [PATCH 56/66] core, floating bus read for 68k in some more places --- pico/memory.c | 37 +++++++++++++++++++++++-------------- pico/pico_int.h | 1 + pico/videoport.c | 4 ++-- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index bedcc1d33..1bd230d0e 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -199,16 +199,25 @@ void cpu68k_map_all_funcs(u32 start_addr, u32 end_addr, u32 (*r8)(u32), u32 (*r1 r8map[i] = ar8, r16map[i] = ar16, w8map[i] = aw8, w16map[i] = aw16; } +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 + return (PicoIn.AHW & PAHW_MCD) ? 0x00 : d; // pulldown if MegaCD2 attached +} + static u32 m68k_unmapped_read8(u32 a) { elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); - return (PicoIn.AHW & PAHW_MCD) ? 0x00 : 0xff; // pulldown if MegaCD2 attached + return (u8)PicoRead16_floating(a); } static u32 m68k_unmapped_read16(u32 a) { elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); - return (PicoIn.AHW & PAHW_MCD) ? 0x00 : 0xffff; + return PicoRead16_floating(a); } static void m68k_unmapped_write8(u32 a, u32 d) @@ -680,12 +689,11 @@ static void PicoWrite16_sram(u32 a, u32 d) // TODO: verify mirrors VDP and bank reg (bank area mirroring verified) static u32 PicoRead8_z80(u32 a) { - u32 d = 0xff; + u32 d; if ((Pico.m.z80Run | Pico.m.z80_reset | (z80_cycles_from_68k() < Pico.t.z80c_cnt)) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); - // open bus. Pulled down if MegaCD2 is attached. - return (PicoIn.AHW & PAHW_MCD ? 0 : d); + return (u8)PicoRead16_floating(a); } SekCyclesBurnRun(1); @@ -693,8 +701,10 @@ static u32 PicoRead8_z80(u32 a) d = PicoMem.zram[a & 0x1fff]; } else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff d = ym2612_read_local_68k(); - else + else { elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + d = (u8)PicoRead16_floating(a); + } return d; } @@ -757,9 +767,7 @@ u32 PicoRead8_io(u32 a) goto end; } - // faking open bus (MegaCD pulldowns don't work here curiously) - d = Pico.m.rotate++; - d ^= d << 6; + d = PicoRead16_floating(a); if ((a & 0xfc00) == 0x1000) { if ((a & 0xff01) == 0x1100) { // z80 busreq (verified) @@ -791,9 +799,7 @@ u32 PicoRead16_io(u32 a) goto end; } - // faking open bus - d = (Pico.m.rotate += 0x41); - d ^= (d << 5) ^ (d << 8); + d = PicoRead16_floating(a); // bit8 seems to be readable in this range if ((a & 0xfc00) == 0x1000) { @@ -864,7 +870,7 @@ void PicoWrite16_io(u32 a, u32 d) // TODO: verify if lower byte goes to PSG on word writes u32 PicoRead8_vdp(u32 a) { - u32 d = 0; + u32 d; if ((a & 0x00f0) == 0x0000) { switch (a & 0x0d) { @@ -876,9 +882,12 @@ u32 PicoRead8_vdp(u32 a) case 0x0c: d = PicoVideoRead8HV_H(0); break; case 0x09: case 0x0d: d = PicoVideoRead8HV_L(0); break; + default: d = (u8)PicoRead16_floating(a); break; } - } else + } else { elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + d = (u8)PicoRead16_floating(a); + } return d; } diff --git a/pico/pico_int.h b/pico/pico_int.h index 5535e1429..31802f4ca 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -740,6 +740,7 @@ void PicoDrawSetOutputSMS(pdso_t which); // memory.c PICO_INTERNAL void PicoMemSetup(void); +PICO_INTERNAL u32 PicoRead16_floating(u32 a); u32 PicoRead8_io(u32 a); u32 PicoRead16_io(u32 a); void PicoWrite8_io(u32 a, u32 d); diff --git a/pico/videoport.c b/pico/videoport.c index 73c90edbe..d4a986f1e 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -1087,7 +1087,7 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) return d; } - if ((a&0x1c)==0x08) + if (a == 0x08) { unsigned int c; u32 d; @@ -1106,7 +1106,7 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) return VideoRead(0); } - return 0; + return PicoRead16_floating(a | 0xc00000); } unsigned char PicoVideoRead8DataH(int is_from_z80) From c87e36d750d712d199df366cf7d74f778b34f1f0 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 17 Mar 2024 10:44:57 +0100 Subject: [PATCH 57/66] core+platforms, revise pico pen handling the MSB in the tablet position register denotes pen on surface. add logic and a hotkey for handling pen not on surface. This allows for repositioning of the pen without the storyware reacting to it. --- pico/pico/pico.c | 2 ++ platform/common/emu.c | 26 +++++++++------ platform/common/emu.h | 4 +-- platform/common/input_pico.h | 10 +++--- platform/common/inputmap_kbd.c | 3 +- platform/common/menu_pico.c | 3 +- platform/gp2x/emu.c | 19 ++++++----- platform/libretro/libretro.c | 60 +++++++++++++++++++++++++--------- platform/linux/emu.c | 12 ++++--- platform/pandora/plat.c | 15 +++++---- platform/ps2/emu.c | 23 +++++++------ platform/psp/emu.c | 20 +++++++----- 12 files changed, 127 insertions(+), 70 deletions(-) diff --git a/pico/pico/pico.c b/pico/pico/pico.c index d190a9402..99f21f4a2 100644 --- a/pico/pico/pico.c +++ b/pico/pico/pico.c @@ -36,6 +36,8 @@ static void PicoResetPico(void) PicoPicohw.fifo_bytes = 0; PicoPicohw.r12 = 0; + PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; + PicoPicoPCMIrqEn(0); PicoPicoPCMFilter(0); PicoPicoPCMGain(8); diff --git a/platform/common/emu.c b/platform/common/emu.c index 6895498cb..d576b4398 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1050,10 +1050,9 @@ void run_events_pico(unsigned int events) switch (pico_inp_mode) { case 2: emu_status_msg("Input: Pen on Pad"); break; case 1: emu_status_msg("Input: Pen on Storyware"); break; - case 0: emu_status_msg("Input: Joystick"); - PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; - break; + case 0: emu_status_msg("Input: Joystick"); break; } + PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; } if (events & PEV_PICO_PPREV) { PicoPicohw.page--; @@ -1067,10 +1066,15 @@ void run_events_pico(unsigned int events) PicoPicohw.page = 6; emu_status_msg("Page %i", PicoPicohw.page); } - if (events & PEV_PICO_PEN) { + if (events & PEV_PICO_SHPEN) { currentConfig.EmuOpt ^= EOPT_PICO_PEN; emu_status_msg("%s Pen", currentConfig.EmuOpt & EOPT_PICO_PEN ? "Show" : "Hide"); } + if (events & PEV_PICO_PPOSV) { + PicoPicohw.pen_pos[0] ^= 0x8000; + PicoPicohw.pen_pos[1] ^= 0x8000; + emu_status_msg("Pen %s", PicoPicohw.pen_pos[0] & 0x8000 ? "Up" : "Down"); + } if (pico_inp_mode == 0) return; @@ -1084,15 +1088,17 @@ void run_events_pico(unsigned int events) if (pico_pen_y < PICO_PEN_ADJUST_Y) pico_pen_y = PICO_PEN_ADJUST_Y; - if (pico_pen_y > 224 - PICO_PEN_ADJUST_Y) - pico_pen_y = 224 - PICO_PEN_ADJUST_Y; + if (pico_pen_y > 224-1 - PICO_PEN_ADJUST_Y) + pico_pen_y = 224-1 - PICO_PEN_ADJUST_Y; if (pico_pen_x < PICO_PEN_ADJUST_X) pico_pen_x = PICO_PEN_ADJUST_X; - if (pico_pen_x > 320 - PICO_PEN_ADJUST_X) - pico_pen_x = 320 - PICO_PEN_ADJUST_X; + if (pico_pen_x > 320-1 - PICO_PEN_ADJUST_X) + pico_pen_x = 320-1 - PICO_PEN_ADJUST_X; - PicoPicohw.pen_pos[0] = 0x03c + pico_pen_x; - PicoPicohw.pen_pos[1] = pico_inp_mode == 1 ? (0x2f8 + pico_pen_y) : (0x1fc + pico_pen_y); + PicoPicohw.pen_pos[0] &= 0x8000; + PicoPicohw.pen_pos[1] &= 0x8000; + PicoPicohw.pen_pos[0] |= 0x03c + pico_pen_x; + PicoPicohw.pen_pos[1] |= (pico_inp_mode == 1 ? 0x2f8 : 0x1fc) + pico_pen_y; } static void do_turbo(unsigned short *pad, int acts) diff --git a/platform/common/emu.h b/platform/common/emu.h index d32cf7058..959ce0b55 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -107,8 +107,8 @@ extern unsigned char *movie_data; extern int reset_timing; extern int flip_after_sync; -#define PICO_PEN_ADJUST_X 2 -#define PICO_PEN_ADJUST_Y 2 +#define PICO_PEN_ADJUST_X 1 +#define PICO_PEN_ADJUST_Y 1 extern int pico_pen_x, pico_pen_y; extern int pico_inp_mode; diff --git a/platform/common/input_pico.h b/platform/common/input_pico.h index b3138d0b3..10d651181 100644 --- a/platform/common/input_pico.h +++ b/platform/common/input_pico.h @@ -28,8 +28,9 @@ #define PEVB_PICO_PNEXT 21 #define PEVB_PICO_PPREV 20 #define PEVB_PICO_SWINP 19 -#define PEVB_PICO_PEN 18 -#define PEVB_RESET 17 +#define PEVB_PICO_SHPEN 18 +#define PEVB_PICO_PPOSV 17 +#define PEVB_RESET 16 #define PEV_VOL_DOWN (1 << PEVB_VOL_DOWN) #define PEV_VOL_UP (1 << PEVB_VOL_UP) @@ -43,9 +44,10 @@ #define PEV_PICO_PNEXT (1 << PEVB_PICO_PNEXT) #define PEV_PICO_PPREV (1 << PEVB_PICO_PPREV) #define PEV_PICO_SWINP (1 << PEVB_PICO_SWINP) -#define PEV_PICO_PEN (1 << PEVB_PICO_PEN) +#define PEV_PICO_SHPEN (1 << PEVB_PICO_SHPEN) +#define PEV_PICO_PPOSV (1 << PEVB_PICO_PPOSV) #define PEV_RESET (1 << PEVB_RESET) -#define PEV_MASK 0x7ffe0000 +#define PEV_MASK 0x7fff0000 #endif /* INCLUDE_c48097f3ff2a6a9af1cce8fd7a9b3f0c */ diff --git a/platform/common/inputmap_kbd.c b/platform/common/inputmap_kbd.c index 038651122..821a8ee02 100644 --- a/platform/common/inputmap_kbd.c +++ b/platform/common/inputmap_kbd.c @@ -30,7 +30,8 @@ const struct in_default_bind in_sdl_defbinds[] = { { SDLK_F6, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, { SDLK_F7, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, - { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_PEN }, + { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_SHPEN }, + { SDLK_F10, IN_BINDTYPE_EMU, PEVB_PICO_PPOSV }, { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF }, { 0, 0, 0 } }; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 78dfcc33f..ffd916121 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -362,7 +362,8 @@ me_bind_action emuctrl_actions[] = { "Pico Next page ", PEV_PICO_PNEXT }, { "Pico Prev page ", PEV_PICO_PPREV }, { "Pico Switch input", PEV_PICO_SWINP }, - { "Pico Display pen ", PEV_PICO_PEN }, + { "Pico Pen sensor ", PEV_PICO_PPOSV }, + { "Pico Show pen ", PEV_PICO_SHPEN }, { NULL, 0 } }; diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 460b1541e..f20f29a22 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -194,10 +194,11 @@ static void draw_cd_leds(void) static void draw_pico_ptr(void) { + int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; int x, y, pitch = 320, offs; - x = ((pico_pen_x * colcount * ((1ULL<<32) / 320)) >> 32) + firstcol; - y = ((pico_pen_y * linecount * ((1ULL<<32) / 224)) >> 32) + firstline; + x = ((pico_pen_x * colcount * ((1ULL<<32)/320 + 1)) >> 32) + firstcol; + y = ((pico_pen_y * linecount * ((1ULL<<32)/224 + 1)) >> 32) + firstline; if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { pitch = 240; @@ -207,16 +208,18 @@ static void draw_pico_ptr(void) if (is_16bit_mode()) { unsigned short *p = (unsigned short *)g_screen_ptr + offs; + int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); - p[0] ^= 0xffff; - p[pitch-1] ^= 0xffff; p[pitch] ^= 0xffff; p[pitch+1] ^= 0xffff; - p[pitch*2] ^= 0xffff; + p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; + p[1] ^= o; p[0] ^= o; p[1] ^= o; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; } else { unsigned char *p = (unsigned char *)g_screen_ptr + offs; + int o = (up ? 0xe0 : 0xf0), _ = (up ? 0xf0 : 0xe0); - p[-1] = 0xe0; p[0] = 0xf0; p[1] = 0xe0; - p[pitch-1] = 0xf0; p[pitch] = 0xf0; p[pitch+1] = 0xf0; - p[2*pitch-1] = 0xe0; p[2*pitch] = 0xf0; p[2*pitch+1] = 0xe0; + p[-pitch-1] = _; p[-pitch] = o; p[-pitch+1] = _; + p[-1] = o; p[0] = o; p[1] = o; + p[pitch-1] = _; p[pitch] = o; p[pitch+1] = _; } } diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 600c01598..26b89ac1b 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -154,7 +154,7 @@ static bool retro_audio_buff_underrun = false; static unsigned audio_latency = 0; static bool update_audio_latency = false; static uint16_t pico_events; -int pico_inp_mode; +int pico_inp_mode, pico_pen_visible; int pico_pen_x = 320/2, pico_pen_y = 240/2; static void retro_audio_buff_status_cb( @@ -1455,6 +1455,8 @@ bool retro_load_game(const struct retro_game_info *info) { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Red Button" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Pen Button" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,"Switch input" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Pen sensor" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Pen visibility" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Previous page" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Next page" }, @@ -2055,6 +2057,22 @@ void emu_status_msg(const char *format, ...) environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &rmsg); } +static void draw_pico_ptr(void) +{ + int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; + int x, y, pitch = vout_width, offs; + unsigned short *p = (unsigned short *)((char *)vout_buf + vout_offset); + int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); + + x = ((pico_pen_x * vout_width * ((1ULL<<32) / 320 + 1)) >> 32); + y = ((pico_pen_y * vout_height * ((1ULL<<32) / 224 + 1)) >> 32); + p += x + y * pitch; + + p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; + p[-1] ^= o; p[0] ^= o; p[1] ^= o; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; +} + void run_events_pico(unsigned int events) { int lim_x; @@ -2066,10 +2084,9 @@ void run_events_pico(unsigned int events) switch (pico_inp_mode) { case 2: emu_status_msg("Input: Pen on Pad"); break; case 1: emu_status_msg("Input: Pen on Storyware"); break; - case 0: emu_status_msg("Input: Joystick"); - PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; - break; + case 0: emu_status_msg("Input: Joystick"); break; } + PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; } if (events & (1 << RETRO_DEVICE_ID_JOYPAD_L)) { PicoPicohw.page--; @@ -2083,6 +2100,15 @@ void run_events_pico(unsigned int events) PicoPicohw.page = 6; emu_status_msg("Page %i", PicoPicohw.page); } + if (events & (1 << RETRO_DEVICE_ID_JOYPAD_X)) { + pico_pen_visible = !pico_pen_visible; + emu_status_msg("%s Pen", pico_pen_visible ? "Show" : "Hide"); + } + if (events & (1 << RETRO_DEVICE_ID_JOYPAD_START)) { + PicoPicohw.pen_pos[0] ^= 0x8000; + PicoPicohw.pen_pos[1] ^= 0x8000; + emu_status_msg("Pen %s", PicoPicohw.pen_pos[0] & 0x8000 ? "Up" : "Down"); + } if (pico_inp_mode == 0) return; @@ -2094,21 +2120,19 @@ void run_events_pico(unsigned int events) if (PicoIn.pad[0] & 8) pico_pen_x++; PicoIn.pad[0] &= ~0x0f; // release UDLR - lim_x = (Pico.video.reg[12]&1) ? 319 : 255; if (pico_pen_y < PICO_PEN_ADJUST_Y) pico_pen_y = PICO_PEN_ADJUST_Y; - if (pico_pen_y > 224 - PICO_PEN_ADJUST_Y) - pico_pen_y = 224 - PICO_PEN_ADJUST_Y; + if (pico_pen_y > 224-1 - PICO_PEN_ADJUST_Y) + pico_pen_y = 224-1 - PICO_PEN_ADJUST_Y; if (pico_pen_x < PICO_PEN_ADJUST_X) pico_pen_x = PICO_PEN_ADJUST_X; - if (pico_pen_x > lim_x - PICO_PEN_ADJUST_X) - pico_pen_x = lim_x - PICO_PEN_ADJUST_X; + if (pico_pen_x > 320-1 - PICO_PEN_ADJUST_X) + pico_pen_x = 320-1 - PICO_PEN_ADJUST_X; - PicoPicohw.pen_pos[0] = pico_pen_x; - if (!(Pico.video.reg[12] & 1)) - PicoPicohw.pen_pos[0] += pico_pen_x / 4; - PicoPicohw.pen_pos[0] += 0x3c; - PicoPicohw.pen_pos[1] = pico_inp_mode == 1 ? (0x2f8 + pico_pen_y) : (0x1fc + pico_pen_y); + PicoPicohw.pen_pos[0] &= 0x8000; + PicoPicohw.pen_pos[1] &= 0x8000; + PicoPicohw.pen_pos[0] |= 0x3c + pico_pen_x; + PicoPicohw.pen_pos[1] |= (pico_inp_mode == 1 ? 0x2f8 : 0x1fc) + pico_pen_y; } void retro_run(void) @@ -2158,7 +2182,10 @@ void retro_run(void) PicoIn.pad[pad] |= retro_pico_map[i]; if (PicoIn.AHW == PAHW_PICO) { - uint16_t ev = input[0] & ((1 << RETRO_DEVICE_ID_JOYPAD_L) | (1 << RETRO_DEVICE_ID_JOYPAD_R) | (1 << RETRO_DEVICE_ID_JOYPAD_SELECT)); + uint16_t ev = input[0] & + ((1 << RETRO_DEVICE_ID_JOYPAD_L) | (1 << RETRO_DEVICE_ID_JOYPAD_R) | + (1 << RETRO_DEVICE_ID_JOYPAD_X) | (1 << RETRO_DEVICE_ID_JOYPAD_SELECT) | + (1 << RETRO_DEVICE_ID_JOYPAD_START)); uint16_t new_ev = ev & ~pico_events; pico_events = ev; run_events_pico(new_ev); @@ -2305,6 +2332,9 @@ void retro_run(void) } } + if ((PicoIn.AHW & PAHW_PICO) && pico_pen_visible) + if (pico_inp_mode) draw_pico_ptr(); + buff = (char*)vout_buf + vout_offset; #endif diff --git a/platform/linux/emu.c b/platform/linux/emu.c index 9519a6bf7..ba384ba40 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -87,17 +87,19 @@ static void draw_cd_leds(void) static void draw_pico_ptr(void) { + int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; + int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); int pitch = g_screen_ppitch; u16 *p = g_screen_ptr; int x = pico_pen_x, y = pico_pen_y; - x = (x * out_w * ((1ULL<<32) / 320)) >> 32; - y = (y * out_h * ((1ULL<<32) / 224)) >> 32; + x = (x * out_w * ((1ULL<<32) / 320 + 1)) >> 32; + y = (y * out_h * ((1ULL<<32) / 224 + 1)) >> 32; p += (screen_y+y)*pitch + (screen_x+x); - p[-pitch] ^= 0xffff; - p[-1] ^= 0xffff; p[0] ^= 0xffff; p[1] ^= 0xffff; - p[pitch] ^= 0xffff; + p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; + p[-1] ^= o; p[0] ^= o; p[1] ^= o; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; } /* render/screen buffer handling: diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 575f1612b..32177ace8 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -76,7 +76,8 @@ static struct in_default_bind in_evdev_defbinds[] = { KEY_5, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, { KEY_6, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, { KEY_7, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, - { KEY_8, IN_BINDTYPE_EMU, PEVB_PICO_PEN }, + { KEY_8, IN_BINDTYPE_EMU, PEVB_PICO_SHPEN }, + { KEY_9, IN_BINDTYPE_EMU, PEVB_PICO_PPOSV }, { 0, 0, 0 } }; @@ -138,16 +139,18 @@ static void draw_cd_leds(void) static void draw_pico_ptr(void) { + int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; + int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); int x = pico_pen_x, y = pico_pen_y, pitch = g_screen_ppitch; unsigned short *p = (unsigned short *)g_screen_ptr; - x = (x * saved_col_count * ((1ULL<<32) / 320)) >> 32; - y = (y * saved_line_count * ((1ULL<<32) / 224)) >> 32; + x = (x * saved_col_count * ((1ULL<<32) / 320 + 1)) >> 32; + y = (y * saved_line_count * ((1ULL<<32) / 224 + 1)) >> 32; p += (saved_start_col+x) + (saved_start_line+y) * pitch; - p[-pitch] ^= 0xffff; - p[-1] ^= 0xffff; p[0] ^= 0xffff; p[1] ^= 0xffff; - p[pitch] ^= 0xffff; + p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; + p[-1] ^= o; p[0] ^= o; p[1] ^= o; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; } void pemu_finalize_frame(const char *fps, const char *notice) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 6eb4dcc43..b15c60363 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -710,26 +710,29 @@ static void blit_cdleds(void) static void draw_pico_ptr(void) { + int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; int x = pico_pen_x, y = pico_pen_y, offs; - int pp = g_screen_ppitch; + int pitch = g_screen_ppitch; - x = (x * out_w * ((1ULL<<32) / 320)) >> 32; - y = (y * out_h * ((1ULL<<32) / 224)) >> 32; + x = (x * out_w * ((1ULL<<32) / 320 + 1)) >> 32; + y = (y * out_h * ((1ULL<<32) / 224 + 1)) >> 32; - offs = g_screen_ppitch * (out_y+y) + (out_x+x); + offs = pitch * (out_y+y) + (out_x+x); if (is_16bit_mode()) { unsigned short *p = (unsigned short *)g_screen_ptr + offs; + int o = (up ? 0x0000 : 0x7fff), _ = (up ? 0x7fff : 0x0000); - p[ -1] = 0x0000; p[ 0] = 0x001f; p[ 1] = 0x0000; - p[ pp-1] = 0x001f; p[ pp] = 0x001f; p[ pp+1] = 0x001f; - p[2*pp-1] = 0x0000; p[2*pp] = 0x001f; p[2*pp+1] = 0x0000; + p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; + p[1] ^= o; p[0] ^= o; p[1] ^= o; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; } else { unsigned char *p = (unsigned char *)g_screen_ptr + offs + 8; + int o = (up ? 0xe0 : 0xf0), _ = (up ? 0xf0 : 0xe0); - p[ -1] = 0xe0; p[ 0] = 0xf0; p[ 1] = 0xe0; - p[ pp-1] = 0xf0; p[ pp] = 0xf0; p[ pp+1] = 0xf0; - p[2*pp-1] = 0xe0; p[2*pp] = 0xf0; p[2*pp+1] = 0xe0; + p[-pitch-1] = _; p[-pitch] = o; p[-pitch+1] = _; + p[-1] = o; p[0] = o; p[1] = o; + p[pitch-1] = _; p[pitch] = o; p[pitch+1] = _; } } diff --git a/platform/psp/emu.c b/platform/psp/emu.c index b53a0f91e..624d02a97 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -370,25 +370,29 @@ void blitscreen_clut(void) static void draw_pico_ptr(void) { + int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; int x = pico_pen_x, y = pico_pen_y, offs; + int pitch = g_screen_ppitch; - x = (x * out_w * ((1ULL<<32) / 320)) >> 32; - y = (y * out_h * ((1ULL<<32) / 224)) >> 32; + x = (x * out_w * ((1ULL<<32) / 320 + 1)) >> 32; + y = (y * out_h * ((1ULL<<32) / 224 + 1)) >> 32; offs = 512 * (out_y+y) + (out_x+x); if (is_16bit_mode()) { unsigned short *p = (unsigned short *)g_screen_ptr + offs; + int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); - p[ -1] = 0x0000; p[ 0] = 0x001f; p[ 1] = 0x0000; - p[ 511] = 0x001f; p[ 512] = 0x001f; p[ 513] = 0x001f; - p[1023] = 0x0000; p[1024] = 0x001f; p[1025] = 0x0000; + p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; + p[1] ^= o; p[0] ^= o; p[1] ^= o; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; } else { unsigned char *p = (unsigned char *)g_screen_ptr + offs + 8; + int o = (up ? 0xe0 : 0xf0), _ = (up ? 0xf0 : 0xe0); - p[ -1] = 0xe0; p[ 0] = 0xf0; p[ 1] = 0xe0; - p[ 511] = 0xf0; p[ 512] = 0xf0; p[ 513] = 0xf0; - p[1023] = 0xe0; p[1024] = 0xf0; p[1025] = 0xe0; + p[-pitch-1] = _; p[-pitch] = o; p[-pitch+1] = _; + p[-1] = o; p[0] = o; p[1] = o; + p[pitch-1] = _; p[pitch] = o; p[pitch+1] = _; } } From 0ef1674dd1757f3be0109e121a1461fd2602b68b Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 18 Mar 2024 19:40:01 +0100 Subject: [PATCH 58/66] drc: only use 64kb aligned tcache_default if on arm linux --- cpu/drc/cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/drc/cmn.c b/cpu/drc/cmn.c index b0b7308f8..65ffd0439 100644 --- a/cpu/drc/cmn.c +++ b/cpu/drc/cmn.c @@ -10,7 +10,7 @@ #include #include "cmn.h" -#if defined(__aarch64__) || defined(__VFP_FP__) +#if defined(__linux__) && (defined(__aarch64__) || defined(__VFP_FP__)) // might be running on a 64k-page kernel #define PICO_PAGE_ALIGN 65536 #else From a33c391027cdd9425d044cc9080505a2b7407f24 Mon Sep 17 00:00:00 2001 From: saulfabreg Wii VC Project Date: Wed, 20 Mar 2024 16:13:27 -0500 Subject: [PATCH 59/66] Libretro: silence a warning regarding to memmap --- platform/libretro/libretro-common/memmap/memmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/libretro/libretro-common/memmap/memmap.c b/platform/libretro/libretro-common/memmap/memmap.c index e84e0875d..5062abaae 100644 --- a/platform/libretro/libretro-common/memmap/memmap.c +++ b/platform/libretro/libretro-common/memmap/memmap.c @@ -21,6 +21,7 @@ */ #include +#include #include #ifndef PROT_READ From 64360d13b092b6fc7ca1094af02707da7ff2739f Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 21 Mar 2024 19:08:54 +0100 Subject: [PATCH 60/66] core, big endian fix (save/load) --- pico/state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico/state.c b/pico/state.c index 3b93765fa..635c95d2b 100644 --- a/pico/state.c +++ b/pico/state.c @@ -187,7 +187,7 @@ static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = { "32X events", }; -static int write_chunk(chunk_name_e name, int len, void *data, void *file) +static int write_chunk(unsigned char name, int len, void *data, void *file) { size_t bwritten = 0; bwritten += areaWrite(&name, 1, 1, file); From da4148881e4308879b30864a30c76e264575df86 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 24 Mar 2024 17:45:10 +0100 Subject: [PATCH 61/66] sms, fix save/load bugs (irq, mapper) --- pico/sms.c | 5 +++++ pico/state.c | 9 +++++---- pico/z80if.c | 5 +++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pico/sms.c b/pico/sms.c index 615ba36ea..6b1425b25 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -795,6 +795,9 @@ void PicoMemSetupMS(void) void PicoStateLoadedMS(void) { u8 mapper = Pico.ms.mapper; + u8 zram_dff0[16]; // TODO xwrite also writes to zram :-/ + + memcpy(zram_dff0, PicoMem.zram+0x1ff0, 16); if (mapper == PMS_MAP_8KBRAM || mapper == PMS_MAP_32KBRAM) { u16 a = Pico.ms.carthw[0] << 12; xwrite(a, *(unsigned char *)(PicoMem.vram+0x4000)); @@ -828,6 +831,7 @@ void PicoStateLoadedMS(void) xwrite(0xfffe, Pico.ms.carthw[0x0e]); xwrite(0xffff, Pico.ms.carthw[0x0f]); } + memcpy(PicoMem.zram+0x1ff0, zram_dff0, 16); } void PicoFrameMS(void) @@ -868,6 +872,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 -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; diff --git a/pico/state.c b/pico/state.c index 635c95d2b..bd801b157 100644 --- a/pico/state.c +++ b/pico/state.c @@ -605,12 +605,13 @@ static int state_load(void *file) Pico32xStateLoaded(0); if (PicoIn.AHW & PAHW_MCD) pcd_state_loaded(); + if (!(PicoIn.AHW & PAHW_SMS)) { + Pico.video.status &= ~(SR_VB | SR_F); + Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB; + Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F; + } Pico.m.dirtyPal = 1; - Pico.video.status &= ~(SR_VB | SR_F); - Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB; - Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F; - retval = 0; out: diff --git a/pico/z80if.c b/pico/z80if.c index 6243675cb..558607c6e 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -209,7 +209,7 @@ void z80_pack(void *data) s->iff1 = !!zIFF1; s->iff2 = !!zIFF2; s->im = zIM; - s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) == HOLD_LINE); + s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) != CLEAR_LINE); s->irq_vector[0] = 0xff; } #endif @@ -276,7 +276,8 @@ int z80_unpack(const void *data) Cz80_Set_Reg(&CZ80, CZ80_IFF1, s->iff1); Cz80_Set_Reg(&CZ80, CZ80_IFF2, s->iff2); zIM = s->im; - Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? HOLD_LINE : CLEAR_LINE); + Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? ASSERT_LINE : CLEAR_LINE); + Cz80_Set_IRQ(&CZ80, 0, Cz80_Get_Reg(&CZ80, CZ80_IRQ)); return 0; } #else From 15cc45c0da19205557139b0c3f30792beb883565 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 20 Mar 2024 23:43:10 +0100 Subject: [PATCH 62/66] platforms, display pad overlay and storyware pages for Pico --- Makefile | 18 +++-- pico/pico/pico.c | 3 +- platform/common/emu.c | 117 +++++++++++++++++++++++++++------ platform/common/emu.h | 2 + platform/common/input_pico.h | 12 ++-- platform/common/inputmap_kbd.c | 6 +- platform/common/menu_pico.c | 47 ++++++------- platform/gp2x/emu.c | 30 ++++++--- platform/libpicofe | 2 +- platform/linux/blit.c | 1 + platform/linux/emu.c | 27 ++++++-- platform/pandora/plat.c | 32 ++++++--- platform/ps2/emu.c | 30 ++++++--- platform/psp/emu.c | 32 ++++++--- 14 files changed, 255 insertions(+), 104 deletions(-) diff --git a/Makefile b/Makefile index cbed7900b..3fe87cbe2 100644 --- a/Makefile +++ b/Makefile @@ -246,18 +246,24 @@ endif ifeq "$(PLATFORM)" "libretro" OBJS += platform/libretro/libretro.o ifneq ($(STATIC_LINKING), 1) +CFLAGS += -DHAVE_ZLIB +OBJS += platform/libretro/libretro-common/formats/png/rpng.o +OBJS += platform/libretro/libretro-common/streams/trans_stream.o +OBJS += platform/libretro/libretro-common/streams/trans_stream_pipe.o +OBJS += platform/libretro/libretro-common/streams/trans_stream_zlib.o +OBJS += platform/libretro/libretro-common/file/file_path_io.o +OBJS += platform/libretro/libretro-common/file/file_path.o +OBJS += platform/libretro/libretro-common/vfs/vfs_implementation.o +OBJS += platform/libretro/libretro-common/time/rtime.o +OBJS += platform/libretro/libretro-common/string/stdstring.o OBJS += platform/libretro/libretro-common/compat/compat_strcasestr.o +OBJS += platform/libretro/libretro-common/encodings/encoding_utf.o +OBJS += platform/libretro/libretro-common/compat/compat_strl.o ifeq "$(USE_LIBRETRO_VFS)" "1" OBJS += platform/libretro/libretro-common/compat/compat_posix_string.o -OBJS += platform/libretro/libretro-common/compat/compat_strl.o OBJS += platform/libretro/libretro-common/compat/fopen_utf8.o -OBJS += platform/libretro/libretro-common/encodings/encoding_utf.o -OBJS += platform/libretro/libretro-common/string/stdstring.o -OBJS += platform/libretro/libretro-common/time/rtime.o OBJS += platform/libretro/libretro-common/streams/file_stream.o OBJS += platform/libretro/libretro-common/streams/file_stream_transforms.o -OBJS += platform/libretro/libretro-common/file/file_path.o -OBJS += platform/libretro/libretro-common/vfs/vfs_implementation.o endif endif ifeq "$(USE_LIBRETRO_VFS)" "1" diff --git a/pico/pico/pico.c b/pico/pico/pico.c index 99f21f4a2..94c80f203 100644 --- a/pico/pico/pico.c +++ b/pico/pico/pico.c @@ -60,6 +60,5 @@ PICO_INTERNAL void PicoInitPico(void) PicoIn.AHW = PAHW_PICO; memset(&PicoPicohw, 0, sizeof(PicoPicohw)); - PicoPicohw.pen_pos[0] = 0x03c + 320/2; - PicoPicohw.pen_pos[1] = 0x200 + 240/2; + PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; } diff --git a/platform/common/emu.c b/platform/common/emu.c index d576b4398..051f8b4d0 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2007-2010 + * (C) irixxxx, 2019-2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -19,6 +20,7 @@ #include "../libpicofe/fonts.h" #include "../libpicofe/sndout.h" #include "../libpicofe/lprintf.h" +#include "../libpicofe/readpng.h" #include "../libpicofe/plat.h" #include "emu.h" #include "input_pico.h" @@ -618,7 +620,7 @@ void emu_prep_defconfig(void) { memset(&defaultConfig, 0, sizeof(defaultConfig)); defaultConfig.EmuOpt = EOPT_EN_SRAM | EOPT_EN_SOUND | EOPT_16BPP | - EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | 0x10/*?*/; + EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | EOPT_PICO_PEN; defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_GG_LCD|POPT_EN_YM2413 | POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX | @@ -1041,19 +1043,76 @@ void emu_reset_game(void) reset_timing = 1; } -void run_events_pico(unsigned int events) +static int pico_page; +static int pico_w, pico_h; +static u16 *pico_overlay; + +static u16 *load_pico_overlay(int page, int w, int h) { - if (events & PEV_PICO_SWINP) { - pico_inp_mode++; - if (pico_inp_mode > 2) - pico_inp_mode = 0; - switch (pico_inp_mode) { - case 2: emu_status_msg("Input: Pen on Pad"); break; - case 1: emu_status_msg("Input: Pen on Storyware"); break; - case 0: emu_status_msg("Input: Joystick"); break; + static const char *pic_exts[] = { "png", "PNG" }; + char *ext, *fname = NULL; + int extpos, i; + + if (pico_page == page && pico_w == w && pico_h == h) + return pico_overlay; + pico_page = page; + pico_w = w, pico_h = h; + + ext = strrchr(rom_fname_loaded, '.'); + extpos = ext ? ext-rom_fname_loaded : strlen(rom_fname_loaded); + strcpy(static_buff, rom_fname_loaded); + static_buff[extpos++] = '_'; + if (page < 0) { + static_buff[extpos++] = 'p'; + static_buff[extpos++] = 'a'; + static_buff[extpos++] = 'd'; + } else + static_buff[extpos++] = '0'+PicoPicohw.page; + static_buff[extpos++] = '.'; + + for (i = 0; i < ARRAY_SIZE(pic_exts); i++) { + strcpy(static_buff+extpos, pic_exts[i]); + if (access(static_buff, R_OK) == 0) { + printf("found Pico file: %s\n", static_buff); + fname = static_buff; + break; } - PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; } + + pico_overlay = realloc(pico_overlay, w*h*2); + memset(pico_overlay, 0, w*h*2); + if (!fname || !pico_overlay || readpng(pico_overlay, fname, READPNG_SCALE, w, h)) { + if (pico_overlay) + free(pico_overlay); + pico_overlay = NULL; + } + + return pico_overlay; +} + +void emu_pico_overlay(u16 *pd, int w, int h, int pitch) +{ + u16 *overlay = NULL; + int y, oh = h; + + // get overlay + if (pico_inp_mode == 1) { + oh = (w/2 < h ? w/2 : h); // storyware has squished h + overlay = load_pico_overlay(PicoPicohw.page, w, oh); + } else if (pico_inp_mode == 2) + overlay = load_pico_overlay(-1, w, oh); + + // copy overlay onto buffer + if (overlay) { + for (y = 0; y < oh; y++) + memcpy(pd + y*pitch, overlay + y*w, w*2); + if (y < h) + memset(pd + y*pitch, 0, w*2); + } +} + +void run_events_pico(unsigned int events) +{ if (events & PEV_PICO_PPREV) { PicoPicohw.page--; if (PicoPicohw.page < 0) @@ -1066,16 +1125,35 @@ void run_events_pico(unsigned int events) PicoPicohw.page = 6; emu_status_msg("Page %i", PicoPicohw.page); } - if (events & PEV_PICO_SHPEN) { - currentConfig.EmuOpt ^= EOPT_PICO_PEN; - emu_status_msg("%s Pen", currentConfig.EmuOpt & EOPT_PICO_PEN ? "Show" : "Hide"); + if (events & PEV_PICO_STORY) { + if (pico_inp_mode == 1) { + pico_inp_mode = 0; + emu_status_msg("Input: D-Pad"); + } else { + pico_inp_mode = 1; + emu_status_msg("Input: Pen on Storyware"); + } + } + if (events & PEV_PICO_PAD) { + if (pico_inp_mode == 2) { + pico_inp_mode = 0; + emu_status_msg("Input: D-Pad"); + } else { + pico_inp_mode = 2; + emu_status_msg("Input: Pen on Pad"); + } } - if (events & PEV_PICO_PPOSV) { + if (events & PEV_PICO_PENST) { PicoPicohw.pen_pos[0] ^= 0x8000; PicoPicohw.pen_pos[1] ^= 0x8000; emu_status_msg("Pen %s", PicoPicohw.pen_pos[0] & 0x8000 ? "Up" : "Down"); } + if ((currentConfig.EmuOpt & EOPT_PICO_PEN) && + (PicoIn.pad[0]&0x20) && pico_inp_mode && pico_overlay) { + pico_inp_mode = 0; + emu_status_msg("Input: D-Pad"); + } if (pico_inp_mode == 0) return; @@ -1086,14 +1164,15 @@ void run_events_pico(unsigned int events) if (PicoIn.pad[0] & 8) pico_pen_x++; PicoIn.pad[0] &= ~0x0f; // release UDLR + /* cursor position, cursor drawing must not cross screen borders */ if (pico_pen_y < PICO_PEN_ADJUST_Y) pico_pen_y = PICO_PEN_ADJUST_Y; - if (pico_pen_y > 224-1 - PICO_PEN_ADJUST_Y) - pico_pen_y = 224-1 - PICO_PEN_ADJUST_Y; + if (pico_pen_y > 223-1 - PICO_PEN_ADJUST_Y) + pico_pen_y = 223-1 - PICO_PEN_ADJUST_Y; if (pico_pen_x < PICO_PEN_ADJUST_X) pico_pen_x = PICO_PEN_ADJUST_X; - if (pico_pen_x > 320-1 - PICO_PEN_ADJUST_X) - pico_pen_x = 320-1 - PICO_PEN_ADJUST_X; + if (pico_pen_x > 319-1 - PICO_PEN_ADJUST_X) + pico_pen_x = 319-1 - PICO_PEN_ADJUST_X; PicoPicohw.pen_pos[0] &= 0x8000; PicoPicohw.pen_pos[1] &= 0x8000; diff --git a/platform/common/emu.h b/platform/common/emu.h index 959ce0b55..c477883ef 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -160,6 +160,8 @@ void emu_get_game_name(char *str150); void emu_set_fastforward(int set_on); void emu_status_msg(const char *format, ...); +void emu_pico_overlay(unsigned short *pd, int w, int h, int pitch); + /* default sound code */ void emu_sound_start(void); void emu_sound_stop(void); diff --git a/platform/common/input_pico.h b/platform/common/input_pico.h index 10d651181..2f3de4186 100644 --- a/platform/common/input_pico.h +++ b/platform/common/input_pico.h @@ -27,9 +27,9 @@ #define PEVB_FF 22 #define PEVB_PICO_PNEXT 21 #define PEVB_PICO_PPREV 20 -#define PEVB_PICO_SWINP 19 -#define PEVB_PICO_SHPEN 18 -#define PEVB_PICO_PPOSV 17 +#define PEVB_PICO_STORY 19 +#define PEVB_PICO_PAD 18 +#define PEVB_PICO_PENST 17 #define PEVB_RESET 16 #define PEV_VOL_DOWN (1 << PEVB_VOL_DOWN) @@ -43,9 +43,9 @@ #define PEV_FF (1 << PEVB_FF) #define PEV_PICO_PNEXT (1 << PEVB_PICO_PNEXT) #define PEV_PICO_PPREV (1 << PEVB_PICO_PPREV) -#define PEV_PICO_SWINP (1 << PEVB_PICO_SWINP) -#define PEV_PICO_SHPEN (1 << PEVB_PICO_SHPEN) -#define PEV_PICO_PPOSV (1 << PEVB_PICO_PPOSV) +#define PEV_PICO_STORY (1 << PEVB_PICO_STORY) +#define PEV_PICO_PAD (1 << PEVB_PICO_PAD) +#define PEV_PICO_PENST (1 << PEVB_PICO_PENST) #define PEV_RESET (1 << PEVB_RESET) #define PEV_MASK 0x7fff0000 diff --git a/platform/common/inputmap_kbd.c b/platform/common/inputmap_kbd.c index 821a8ee02..c41abbb38 100644 --- a/platform/common/inputmap_kbd.c +++ b/platform/common/inputmap_kbd.c @@ -29,9 +29,9 @@ const struct in_default_bind in_sdl_defbinds[] = { { SDLK_F5, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, { SDLK_F6, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, { SDLK_F7, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, - { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, - { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_SHPEN }, - { SDLK_F10, IN_BINDTYPE_EMU, PEVB_PICO_PPOSV }, + { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_STORY }, + { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_PAD }, + { SDLK_F10, IN_BINDTYPE_EMU, PEVB_PICO_PENST }, { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF }, { 0, 0, 0 } }; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index ffd916121..00f2aa690 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2010,2011 + * (C) irixxxx, 2023,2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -349,21 +350,21 @@ me_bind_action me_ctrl_actions[] = me_bind_action emuctrl_actions[] = { - { "Load State ", PEV_STATE_LOAD }, - { "Save State ", PEV_STATE_SAVE }, - { "Prev Save Slot ", PEV_SSLOT_PREV }, - { "Next Save Slot ", PEV_SSLOT_NEXT }, - { "Switch Renderer ", PEV_SWITCH_RND }, - { "Volume Down ", PEV_VOL_DOWN }, - { "Volume Up ", PEV_VOL_UP }, - { "Fast forward ", PEV_FF }, - { "Reset Game ", PEV_RESET }, - { "Enter Menu ", PEV_MENU }, - { "Pico Next page ", PEV_PICO_PNEXT }, - { "Pico Prev page ", PEV_PICO_PPREV }, - { "Pico Switch input", PEV_PICO_SWINP }, - { "Pico Pen sensor ", PEV_PICO_PPOSV }, - { "Pico Show pen ", PEV_PICO_SHPEN }, + { "Load State ", PEV_STATE_LOAD }, + { "Save State ", PEV_STATE_SAVE }, + { "Prev Save Slot ", PEV_SSLOT_PREV }, + { "Next Save Slot ", PEV_SSLOT_NEXT }, + { "Switch Renderer", PEV_SWITCH_RND }, + { "Volume Down ", PEV_VOL_DOWN }, + { "Volume Up ", PEV_VOL_UP }, + { "Fast forward ", PEV_FF }, + { "Reset Game ", PEV_RESET }, + { "Enter Menu ", PEV_MENU }, + { "Pico Next page ", PEV_PICO_PNEXT }, + { "Pico Prev page ", PEV_PICO_PPREV }, + { "Pico Storyware ", PEV_PICO_STORY }, + { "Pico Pad ", PEV_PICO_PAD }, + { "Pico Pen state ", PEV_PICO_PENST }, { NULL, 0 } }; @@ -463,15 +464,17 @@ static const char h_fmsound[] = "Disabling improves performance, but breaks sou static const char h_dacnoise[] = "FM chips in the 1st Mega Drive model have DAC noise,\n" "newer models used different chips without this"; static const char h_fmfilter[] = "Improves sound accuracy but is noticeably slower,\n" - "best´quality if native rate isn't working"; + "best quality if native rate isn't working"; +static const char h_picopen[] = "Enabling resets Pico display and d-pad input back to\n" + "screen if the Pico pen button is pressed"; static menu_entry e_menu_md_options[] = { - mee_enum_h ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names, h_renderer), - mee_onoff_h ("FM audio", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM, h_fmsound), - mee_onoff_h ("FM filter", MA_OPT_FM_FILTER, PicoIn.opt, POPT_EN_FM_FILTER, h_fmfilter), - mee_onoff_h ("FM DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC, h_dacnoise), - mee_onoff ("Show Pico pen", MA_OPT_PICO_PEN, currentConfig.EmuOpt, EOPT_PICO_PEN), + mee_enum_h ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names, h_renderer), + mee_onoff_h ("FM audio", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM, h_fmsound), + mee_onoff_h ("FM filter", MA_OPT_FM_FILTER, PicoIn.opt, POPT_EN_FM_FILTER, h_fmfilter), + mee_onoff_h ("FM DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC, h_dacnoise), + mee_onoff_h ("Pen button shows screen", MA_OPT_PICO_PEN, currentConfig.EmuOpt, EOPT_PICO_PEN, h_picopen), mee_end, }; @@ -1295,8 +1298,6 @@ static const char *mgn_picopage(int id, int *offs) static int mh_picopage(int id, int keys) { - int ret; - if (keys & (PBTN_LEFT|PBTN_RIGHT)) { // multi choice PicoPicohw.page += (keys & PBTN_LEFT) ? -1 : 1; if (PicoPicohw.page < 0) PicoPicohw.page = 6; diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index f20f29a22..aae7fbd53 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -196,9 +196,12 @@ static void draw_pico_ptr(void) { int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; int x, y, pitch = 320, offs; + // storyware pages are actually squished, 2:1 + int h = (pico_inp_mode == 1 ? 160 : linecount); + if (h < 224) y++; x = ((pico_pen_x * colcount * ((1ULL<<32)/320 + 1)) >> 32) + firstcol; - y = ((pico_pen_y * linecount * ((1ULL<<32)/224 + 1)) >> 32) + firstline; + y = ((pico_pen_y * h * ((1ULL<<32)/224 + 1)) >> 32) + firstline; if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { pitch = 240; @@ -210,16 +213,18 @@ static void draw_pico_ptr(void) unsigned short *p = (unsigned short *)g_screen_ptr + offs; int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); - p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; - p[1] ^= o; p[0] ^= o; p[1] ^= o; - p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; + p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o; + p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _; + p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o; } else { unsigned char *p = (unsigned char *)g_screen_ptr + offs; int o = (up ? 0xe0 : 0xf0), _ = (up ? 0xf0 : 0xe0); - p[-pitch-1] = _; p[-pitch] = o; p[-pitch+1] = _; - p[-1] = o; p[0] = o; p[1] = o; - p[pitch-1] = _; p[pitch] = o; p[pitch+1] = _; + p[-pitch-1] = o; p[-pitch] = _; p[-pitch+1] = _; p[-pitch+2] = o; + p[-1] = _; p[0] = o; p[1] = o; p[2] = _; + p[pitch-1] = _; p[pitch] = o; p[pitch+1] = o; p[pitch+2] = _; + p[2*pitch-1]= o; p[2*pitch]= _; p[2*pitch+1]= _; p[2*pitch+2]= o; } } @@ -434,8 +439,15 @@ void pemu_finalize_frame(const char *fps, const char *notice) osd_text(osd_fps_x, osd_y, fps); if ((PicoIn.AHW & PAHW_MCD) && (emu_opt & EOPT_EN_CD_LEDS)) draw_cd_leds(); - if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) - if (pico_inp_mode) draw_pico_ptr(); + if (PicoIn.AHW & PAHW_PICO) { + int h = linecount, w = colcount; + u16 *pd = g_screen_ptr + firstline*g_screen_ppitch + firstcol; + + if (pico_inp_mode && is_16bit_mode()) + emu_pico_overlay(pd, w, h, g_screen_ppitch); + if (pico_inp_mode /*== 2 || overlay*/) + draw_pico_ptr(); + } } void plat_video_flip(void) diff --git a/platform/libpicofe b/platform/libpicofe index 82b485477..4563c1316 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 82b4854771302e23201de274eee2969fc28be8be +Subproject commit 4563c13167deb97851397789bf2fb95bb44cf1ed diff --git a/platform/linux/blit.c b/platform/linux/blit.c index ee2b6d0eb..e10aa6b7b 100644 --- a/platform/linux/blit.c +++ b/platform/linux/blit.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2006,2009 + * (C) irixxxx, 2022 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. diff --git a/platform/linux/emu.c b/platform/linux/emu.c index ba384ba40..5d65ad5ee 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2006-2010 + * (C) irixxxx, 2019-2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -92,14 +93,18 @@ static void draw_pico_ptr(void) int pitch = g_screen_ppitch; u16 *p = g_screen_ptr; int x = pico_pen_x, y = pico_pen_y; + // storyware pages are actually squished, 2:1 + int h = (pico_inp_mode == 1 ? 160 : out_h); + if (h < 224) y++; x = (x * out_w * ((1ULL<<32) / 320 + 1)) >> 32; - y = (y * out_h * ((1ULL<<32) / 224 + 1)) >> 32; + y = (y * h * ((1ULL<<32) / 224 + 1)) >> 32; p += (screen_y+y)*pitch + (screen_x+x); - p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; - p[-1] ^= o; p[0] ^= o; p[1] ^= o; - p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; + p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o; + p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _; + p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o; } /* render/screen buffer handling: @@ -194,6 +199,7 @@ void pemu_finalize_frame(const char *fps, const char *notice) u16 *ps = ghost_buf; int y, h = currentConfig.vscaling == EOPT_SCALE_SW ? 240:out_h; int w = currentConfig.scaling == EOPT_SCALE_SW ? 320:out_w; + if (currentConfig.ghosting == 1) for (y = 0; y < h; y++) { v_blend((u32 *)pd, (u32 *)ps, w/2, p_075_round); @@ -208,8 +214,17 @@ void pemu_finalize_frame(const char *fps, const char *notice) } } - if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) - if (pico_inp_mode) draw_pico_ptr(); + if (PicoIn.AHW & PAHW_PICO) { + int h = currentConfig.vscaling == EOPT_SCALE_SW ? 240:out_h; + int w = currentConfig.scaling == EOPT_SCALE_SW ? 320:out_w; + u16 *pd = screen_buffer(g_screen_ptr) + out_y*g_screen_ppitch + out_x; + + if (pico_inp_mode) + emu_pico_overlay(pd, w, h, g_screen_ppitch); + if (pico_inp_mode /*== 2 || overlay*/) + draw_pico_ptr(); + } + if (notice) emu_osd_text16(4, g_screen_height - 8, notice); if (currentConfig.EmuOpt & EOPT_SHOW_FPS) diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 32177ace8..20f9ca8f2 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -75,9 +75,9 @@ static struct in_default_bind in_evdev_defbinds[] = { KEY_4, IN_BINDTYPE_EMU, PEVB_SSLOT_NEXT }, { KEY_5, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, { KEY_6, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, - { KEY_7, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, - { KEY_8, IN_BINDTYPE_EMU, PEVB_PICO_SHPEN }, - { KEY_9, IN_BINDTYPE_EMU, PEVB_PICO_PPOSV }, + { KEY_7, IN_BINDTYPE_EMU, PEVB_PICO_STORY }, + { KEY_8, IN_BINDTYPE_EMU, PEVB_PICO_PAD }, + { KEY_9, IN_BINDTYPE_EMU, PEVB_PICO_PENST }, { 0, 0, 0 } }; @@ -143,20 +143,32 @@ static void draw_pico_ptr(void) int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); int x = pico_pen_x, y = pico_pen_y, pitch = g_screen_ppitch; unsigned short *p = (unsigned short *)g_screen_ptr; + // storyware pages are actually squished, 2:1 + int h = (pico_inp_mode == 1 ? 160 : saved_line_count); + if (h < 224) y++; - x = (x * saved_col_count * ((1ULL<<32) / 320 + 1)) >> 32; - y = (y * saved_line_count * ((1ULL<<32) / 224 + 1)) >> 32; + x = (x * saved_col_count * ((1ULL<<32) / 320 + 1)) >> 32; + y = (y * h * ((1ULL<<32) / 224 + 1)) >> 32; p += (saved_start_col+x) + (saved_start_line+y) * pitch; - p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; - p[-1] ^= o; p[0] ^= o; p[1] ^= o; - p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; + p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o; + p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _; + p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o; } void pemu_finalize_frame(const char *fps, const char *notice) { - if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) - if (pico_inp_mode) draw_pico_ptr(); + if (PicoIn.AHW & PAHW_PICO) { + int h = saved_line_count, w = saved_col_count; + u16 *pd = g_screen_ptr + saved_start_line*g_screen_ppitch + + saved_start_col; + + if (pico_inp_mode) + emu_pico_overlay(pd, w, h, g_screen_ppitch); + if (pico_inp_mode /*== 2 || overlay*/) + draw_pico_ptr(); + } 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)) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index b15c60363..35db97447 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -713,9 +713,12 @@ static void draw_pico_ptr(void) int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; int x = pico_pen_x, y = pico_pen_y, offs; int pitch = g_screen_ppitch; + // storyware pages are actually squished, 2:1 + int h = (pico_inp_mode == 1 ? 160 : out_h); + if (h < 224) y++; x = (x * out_w * ((1ULL<<32) / 320 + 1)) >> 32; - y = (y * out_h * ((1ULL<<32) / 224 + 1)) >> 32; + y = (y * h * ((1ULL<<32) / 224 + 1)) >> 32; offs = pitch * (out_y+y) + (out_x+x); @@ -723,16 +726,18 @@ static void draw_pico_ptr(void) unsigned short *p = (unsigned short *)g_screen_ptr + offs; int o = (up ? 0x0000 : 0x7fff), _ = (up ? 0x7fff : 0x0000); - p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; - p[1] ^= o; p[0] ^= o; p[1] ^= o; - p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; + p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o; + p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _; + p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o; } else { unsigned char *p = (unsigned char *)g_screen_ptr + offs + 8; int o = (up ? 0xe0 : 0xf0), _ = (up ? 0xf0 : 0xe0); - p[-pitch-1] = _; p[-pitch] = o; p[-pitch+1] = _; - p[-1] = o; p[0] = o; p[1] = o; - p[pitch-1] = _; p[pitch] = o; p[pitch+1] = _; + p[-pitch-1] = o; p[-pitch] = _; p[-pitch+1] = _; p[-pitch+2] = o; + p[-1] = _; p[0] = o; p[1] = o; p[2] = _; + p[pitch-1] = _; p[pitch] = o; p[pitch+1] = o; p[pitch+2] = _; + p[2*pitch-1]= o; p[2*pitch]= _; p[2*pitch+1]= _; p[2*pitch+2]= o; } } @@ -748,8 +753,15 @@ void pemu_finalize_frame(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; - if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) - if (pico_inp_mode) draw_pico_ptr(); + if (PicoIn.AHW & PAHW_PICO) { + int h = out_h, w = out_w; + u16 *pd = g_screen_ptr + out_y*g_screen_ppitch + out_x; + + if (pico_inp_mode && is_16bit_mode()) + emu_pico_overlay(pd, w, h, g_screen_ppitch); + if (pico_inp_mode /*== 2 || overlay*/) + draw_pico_ptr(); + } osd_buf_cnt = 0; if (notice) osd_text(4, notice); diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 624d02a97..948102bb0 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -373,26 +373,31 @@ static void draw_pico_ptr(void) int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; int x = pico_pen_x, y = pico_pen_y, offs; int pitch = g_screen_ppitch; + // storyware pages are actually squished, 2:1 + int h = (pico_inp_mode == 1 ? 160 : out_h); + if (h < 224) y++; x = (x * out_w * ((1ULL<<32) / 320 + 1)) >> 32; - y = (y * out_h * ((1ULL<<32) / 224 + 1)) >> 32; + y = (y * h * ((1ULL<<32) / 224 + 1)) >> 32; - offs = 512 * (out_y+y) + (out_x+x); + offs = pitch * (out_y+y) + (out_x+x); if (is_16bit_mode()) { unsigned short *p = (unsigned short *)g_screen_ptr + offs; int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); - p[-pitch-1] ^= _; p[-pitch] ^= o; p[-pitch+1] ^= _; - p[1] ^= o; p[0] ^= o; p[1] ^= o; - p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= _; + p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o; + p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _; + p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o; } else { unsigned char *p = (unsigned char *)g_screen_ptr + offs + 8; int o = (up ? 0xe0 : 0xf0), _ = (up ? 0xf0 : 0xe0); - p[-pitch-1] = _; p[-pitch] = o; p[-pitch+1] = _; - p[-1] = o; p[0] = o; p[1] = o; - p[pitch-1] = _; p[pitch] = o; p[pitch+1] = _; + p[-pitch-1] = o; p[-pitch] = _; p[-pitch+1] = _; p[-pitch+2] = o; + p[-1] = _; p[0] = o; p[1] = o; p[2] = _; + p[pitch-1] = _; p[pitch] = o; p[pitch+1] = o; p[pitch+2] = _; + p[2*pitch-1]= o; p[2*pitch]= _; p[2*pitch+1]= _; p[2*pitch+2]= o; } } @@ -697,8 +702,15 @@ void pemu_finalize_frame(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; - if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) - if (pico_inp_mode) draw_pico_ptr(); + if (PicoIn.AHW & PAHW_PICO) { + int h = out_h, w = out_w; + u16 *pd = g_screen_ptr + out_y*g_screen_ppitch + out_x; + + if (pico_inp_mode && is_16bit_mode()) + emu_pico_overlay(pd, w, h, g_screen_ppitch); + if (pico_inp_mode /*== 2 || overlay*/) + draw_pico_ptr(); + } osd_buf_cnt = 0; if (notice) From 5f9901e09806c5d5e2010fa81326b5b120b80432 Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 25 Mar 2024 18:49:19 +0100 Subject: [PATCH 63/66] libretro, add Pico pad overlay and storyware pages handling --- Makefile | 2 + Makefile.libretro | 1 + jni/Android.mk | 11 + .../libretro/libretro-common/file/file_path.c | 768 +++++----- .../libretro-common/file/file_path_io.c | 149 ++ .../libretro-common/formats/png/rpng.c | 1251 +++++++++++++++++ .../formats/png/rpng_internal.h | 49 + .../libretro-common/include/file/file_path.h | 332 +++-- .../libretro-common/include/filters.h | 103 ++ .../libretro-common/include/formats/image.h | 102 ++ .../libretro-common/include/formats/rpng.h | 64 + .../libretro-common/include/retro_math.h | 190 +++ .../include/streams/trans_stream.h | 106 ++ .../libretro-common/streams/trans_stream.c | 92 ++ .../streams/trans_stream_pipe.c | 111 ++ .../streams/trans_stream_zlib.c | 330 +++++ platform/libretro/libretro.c | 231 ++- 17 files changed, 3415 insertions(+), 477 deletions(-) create mode 100644 platform/libretro/libretro-common/file/file_path_io.c create mode 100644 platform/libretro/libretro-common/formats/png/rpng.c create mode 100644 platform/libretro/libretro-common/formats/png/rpng_internal.h create mode 100644 platform/libretro/libretro-common/include/filters.h create mode 100644 platform/libretro/libretro-common/include/formats/image.h create mode 100644 platform/libretro/libretro-common/include/formats/rpng.h create mode 100644 platform/libretro/libretro-common/include/retro_math.h create mode 100644 platform/libretro/libretro-common/include/streams/trans_stream.h create mode 100644 platform/libretro/libretro-common/streams/trans_stream.c create mode 100644 platform/libretro/libretro-common/streams/trans_stream_pipe.c create mode 100644 platform/libretro/libretro-common/streams/trans_stream_zlib.c diff --git a/Makefile b/Makefile index 3fe87cbe2..7b87043ee 100644 --- a/Makefile +++ b/Makefile @@ -72,8 +72,10 @@ CFLAGS += $(call chkCCflag, -fno-caller-saves -fno-guess-branch-probability -fno CFLAGS += $(call chkCCflag, -fno-tree-loop-if-convert -fipa-pta -fno-ipa-cp) endif else +ifneq ($(STATIC_LINKING), 1) CFLAGS += $(call chkCCflag, -flto) endif +endif # revision info from repository if this not a tagged release ifeq "$(shell git describe --tags --exact-match HEAD 2>/dev/null)" "" diff --git a/Makefile.libretro b/Makefile.libretro index d849be811..9a2e2ebb3 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -30,6 +30,7 @@ CFLAGS ?= CFLAGS += -I platform/libretro/libretro-common/include CFLAGS += -I platform/libretro/libretro-common/include/compat CFLAGS += -I platform/libretro/libretro-common/include/encodings +CFLAGS += -I platform/libretro/libretro-common/include/formats CFLAGS += -I platform/libretro/libretro-common/include/streams CFLAGS += -I platform/libretro/libretro-common/include/string CFLAGS += -I platform/libretro/libretro-common/include/vfs diff --git a/jni/Android.mk b/jni/Android.mk index f89e1324b..b4d0143cd 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -54,7 +54,18 @@ endif include $(COMMON_DIR)/common.mak SOURCES_C := $(LIBRETRO_DIR)/libretro.c \ + $(LIBRETRO_COMM_DIR)/formats/png/rpng.c \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream.c \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream_pipe.c \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream_zlib.c \ + $(LIBRETRO_COMM_DIR)/file/file_path_io.c \ + $(LIBRETRO_COMM_DIR)/file/file_path.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \ + $(LIBRETRO_COMM_DIR)/time/rtime.c \ + $(LIBRETRO_COMM_DIR)/string/stdstring.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ $(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ $(COMMON_DIR)/mp3.c \ $(COMMON_DIR)/mp3_sync.c \ $(COMMON_DIR)/mp3_dummy.c \ diff --git a/platform/libretro/libretro-common/file/file_path.c b/platform/libretro/libretro-common/file/file_path.c index 320c5a2da..c696ff045 100644 --- a/platform/libretro/libretro-common/file/file_path.c +++ b/platform/libretro/libretro-common/file/file_path.c @@ -24,13 +24,12 @@ #include #include #include -#include +#include #include #include #include -#include #include #include #include