From b043a80a702d567022d641634aef9e5a339ad4d1 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 11 May 2021 18:29:21 +0200 Subject: [PATCH 01/22] Backported last irixxxx's changes to my FunKey fork --- .gitmodules | 3 + Makefile | 3 +- Makefile.libretro | 25 +++- cpu/drc/emit_arm64.c | 2 +- cpu/drc/emit_ppc.c | 29 +++-- cpu/drc/emit_x86.c | 9 +- cpu/musashi/m68kcpu.h | 13 +- cpu/sh2/compiler.c | 114 ++++++++++++------ cpu/sh2/compiler.h | 2 +- pico/32x/32x.c | 20 +-- pico/32x/draw.c | 2 +- pico/32x/draw_arm.S | 69 ++++++++--- pico/32x/memory.c | 29 +++-- pico/cart.c | 16 +-- pico/cd/cdc.c | 14 +-- pico/cd/cdd.c | 3 + pico/cd/gfx.c | 2 +- pico/cd/mcd.c | 54 ++++++--- pico/cd/memory.c | 16 +-- pico/cd/pcm.c | 6 +- pico/m68kif_cyclone.s | 4 +- pico/patch.c | 10 +- pico/pico_cmn.c | 3 +- pico/pico_int.h | 3 +- pico/pico_port.h | 4 +- pico/sek.c | 40 +++--- pico/sound/sound.c | 6 +- platform/common/config_file.c | 2 +- platform/common/dr_libs | 1 + platform/common/host_dasm.c | 29 ++++- platform/common/menu_pico.c | 3 +- platform/common/mp3_drmp3.c | 65 ++++++++++ platform/common/plat_sdl.c | 2 +- platform/libretro/libretro.c | 26 +++- platform/linux/emu.c | 2 +- platform/linux/menu.c | 16 +++ platform/opendingux/data/default.gcw0.desktop | 2 +- .../opendingux/data/default.retrofw.desktop | 4 +- tools/release.sh | 14 +-- 39 files changed, 461 insertions(+), 206 deletions(-) create mode 160000 platform/common/dr_libs create mode 100644 platform/common/mp3_drmp3.c create mode 100644 platform/linux/menu.c diff --git a/.gitmodules b/.gitmodules index f38d3399..8717be74 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "platform/common/minimp3"] path = platform/common/minimp3 url = https://github.com/lieff/minimp3 +[submodule "platform/common/dr_libs"] + path = platform/common/dr_libs + url = https://github.com/mackron/dr_libs diff --git a/Makefile b/Makefile index 93e4e8de..ae9d5abd 100644 --- a/Makefile +++ b/Makefile @@ -245,7 +245,8 @@ OBJS += platform/common/mp3_helix.o else ifeq "$(HAVE_LIBAVCODEC)" "1" OBJS += platform/common/mp3_libavcodec.o else -OBJS += platform/common/mp3_minimp3.o +#OBJS += platform/common/mp3_minimp3.o +OBJS += platform/common/mp3_drmp3.o endif endif diff --git a/Makefile.libretro b/Makefile.libretro index 6a189970..9effd3c8 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -160,6 +160,9 @@ else ifeq ($(platform), ps3) CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS STATIC_LINKING = 1 NO_MMAP = 1 + # PS3 has memory mapped in a way not suitable for DRC + use_sh2drc = 0 + use_svpdrc = 0 # sncps3 else ifeq ($(platform), sncps3) @@ -170,6 +173,9 @@ else ifeq ($(platform), sncps3) CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS STATIC_LINKING = 1 NO_MMAP = 1 + # PS3 has memory mapped in a way not suitable for DRC + use_sh2drc = 0 + use_svpdrc = 0 # Lightweight PS3 Homebrew SDK else ifeq ($(platform), psl1ght) @@ -179,6 +185,9 @@ else ifeq ($(platform), psl1ght) CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS STATIC_LINKING = 1 NO_MMAP = 1 + # PS3 has memory mapped in a way not suitable for DRC + use_sh2drc = 0 + use_svpdrc = 0 # PSP else ifeq ($(platform), psp1) @@ -253,14 +262,18 @@ else ifeq ($(platform), ngc) 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_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST + STATIC_LINKING = 1 + NO_MMAP = 1 # Nintendo Wii 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 -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST + STATIC_LINKING = 1 + NO_MMAP = 1 # Nintendo Wii U else ifeq ($(platform), wiiu) @@ -268,8 +281,12 @@ else ifeq ($(platform), wiiu) CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - COMMONFLAGS += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -D__POWERPC__ -D__ppc__ -DMSB_FIRST -DWORDS_BIGENDIAN=1 -I./deps/include/ - COMMONFLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int + CFLAGS += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST + STATIC_LINKING = 1 + NO_MMAP = 1 + # Wii U has memory mapped in a way not suitable for DRC + use_sh2drc = 0 + use_svpdrc = 0 # Nintendo Switch (libtransistor) else ifeq ($(platform), switch) diff --git a/cpu/drc/emit_arm64.c b/cpu/drc/emit_arm64.c index 66452975..089cfdb2 100644 --- a/cpu/drc/emit_arm64.c +++ b/cpu/drc/emit_arm64.c @@ -1187,7 +1187,7 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode) #define host_instructions_updated(base, end, force) \ do { if (force) __builtin___clear_cache(base, end); } while (0) #define emith_update_cache() /**/ -#define emith_rw_offs_max() 0xff +#define emith_rw_offs_max() 0x1ff #define emith_uext_ptr(r) /**/ diff --git a/cpu/drc/emit_ppc.c b/cpu/drc/emit_ppc.c index e6c43cde..0b4f0649 100644 --- a/cpu/drc/emit_ppc.c +++ b/cpu/drc/emit_ppc.c @@ -362,6 +362,11 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; #define PPC_STB_IMM(rt, ra, offs16) \ PPC_OP_IMM(OP_STB,rt,ra,(u16)(offs16)) +#define PPC_STXU_IMM(rt, ra, offs16) \ + PPC_OP_IMM(OP__ST,rt,ra,((u16)(offs16)&~3)|OPS_STDU) +#define PPC_STWU_IMM(rt, ra, offs16) \ + PPC_OP_IMM(OP_STWU,rt,ra,(u16)(offs16)) + // load/store, indexed #define PPC_LDX_REG(rt, ra, rb) \ @@ -407,6 +412,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; #define PPC_LDP_REG PPC_LDX_REG #define PPC_STP_IMM PPC_STX_IMM #define PPC_STP_REG PPC_STX_REG +#define PPC_STPU_IMM PPC_STXU_IMM #define PPC_BFXP_IMM PPC_BFX_IMM #define emith_uext_ptr(r) EMIT(PPC_EXTUW_REG(r, r)) @@ -440,6 +446,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; #define PPC_LDP_REG PPC_LDW_REG #define PPC_STP_IMM PPC_STW_IMM #define PPC_STP_REG PPC_STW_REG +#define PPC_STPU_IMM PPC_STWU_IMM #define PPC_BFXP_IMM PPC_BFXW_IMM #define emith_uext_ptr(r) /**/ @@ -1552,10 +1559,11 @@ static int emith_cond_check(int cond) static NOINLINE void host_instructions_updated(void *base, void *end, int force) { int step = 32, lgstep = 5; - char *_base = base, *_end = end; - int count = (_end - _base + step-1) >> lgstep; + char *_base = (char *)((uptr)base & ~(step-1)); + int count = (((char *)end - _base) >> lgstep) + 1; if (count <= 0) count = 1; // make sure count is positive + base = _base; asm volatile( " mtctr %1;" @@ -1587,25 +1595,24 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force) #define emith_sh2_drc_entry() do { \ int _c, _z = PTR_SIZE; u32 _m = 0xffffc000; /* r14-r31 */ \ if (__builtin_parity(_m) == 1) _m |= 0x1; /* ABI align for SP is 16 */ \ - int _s = count_bits(_m) * _z, _o = 0; \ - for (_c = HOST_REGS-1; _m && _c >= 0; _m &= ~(1 << _c), _c--) \ + int _s = count_bits(_m) * _z, _o = STACK_EXTRA; \ + EMIT(PPC_STPU_IMM(SP, SP, -_s-STACK_EXTRA)); \ + EMIT(PPC_MFSP_REG(AT, LR)); \ + for (_c = 0; _m && _c < HOST_REGS; _m &= ~(1 << _c), _c++) \ if (_m & (1 << _c)) \ - { _o -= _z; if (_c) emith_write_r_r_offs_ptr(_c, SP, _o); } \ - EMIT(PPC_MFSP_REG(10, LR)); \ - emith_write_r_r_offs_ptr(10, SP, 2*PTR_SIZE); \ - emith_write_r_r_offs_ptr(SP, SP, -_s-STACK_EXTRA); /* XXX stdu */ \ - emith_add_r_r_ptr_imm(SP, SP, -_s-STACK_EXTRA); \ + { if (_c) emith_write_r_r_offs_ptr(_c, SP, _o); _o += _z; } \ + emith_write_r_r_offs_ptr(AT, SP, _o + _z); \ } while (0) #define emith_sh2_drc_exit() do { \ int _c, _z = PTR_SIZE; u32 _m = 0xffffc000; \ if (__builtin_parity(_m) == 1) _m |= 0x1; \ int _s = count_bits(_m) * _z, _o = STACK_EXTRA; \ + emith_read_r_r_offs_ptr(AT, SP, _o+_s + _z); \ + EMIT(PPC_MTSP_REG(AT, LR)); \ for (_c = 0; _m && _c < HOST_REGS; _m &= ~(1 << _c), _c++) \ if (_m & (1 << _c)) \ { if (_c) emith_read_r_r_offs_ptr(_c, SP, _o); _o += _z; } \ emith_add_r_r_ptr_imm(SP, SP, _s+STACK_EXTRA); \ - emith_read_r_r_offs_ptr(10, SP, 2*PTR_SIZE); \ - EMIT(PPC_MTSP_REG(10, LR)); \ emith_ret(); \ } while (0) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 47124498..94111e0f 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -383,12 +383,9 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common // _r_imm #define emith_move_r_imm(r, imm) do { \ - if (imm) { \ - EMIT_REX_IF(0, 0, r); \ - EMIT_OP(0xb8 + ((r)&7)); \ - EMIT(imm, u32); \ - } else \ - emith_eor_r_r(r, r); \ + EMIT_REX_IF(0, 0, r); \ + EMIT_OP(0xb8 + ((r)&7)); \ + EMIT(imm, u32); \ } while (0) #define emith_move_r_ptr_imm(r, imm) do { \ diff --git a/cpu/musashi/m68kcpu.h b/cpu/musashi/m68kcpu.h index a1dff7de..5eee2b21 100644 --- a/cpu/musashi/m68kcpu.h +++ b/cpu/musashi/m68kcpu.h @@ -27,14 +27,11 @@ #define M68KCPU__HEADER // notaz: something's missing this -#ifndef UINT64 -#define UINT64 unsigned long long -#endif -#ifndef UINT16 -#define UINT32 unsigned int -#define UINT16 unsigned short -#define UINT8 unsigned char -#endif +#include +typedef uint64_t UINT64; +typedef uint32_t UINT32; +typedef uint16_t UINT16; +typedef uint8_t UINT8; #include "m68k.h" #include diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 586175de..76ccf301 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -203,19 +203,35 @@ static char sh2dasm_buff[64]; (ulong)(sh2)->poll_addr, (sh2)->poll_cycles, (sh2)->poll_cnt); \ } -#if (DRC_DEBUG & (8|256|512|1024)) || defined(PDB) #if (DRC_DEBUG & (256|512|1024)) static SH2 csh2[2][8]; static FILE *trace[2]; static int topen[2]; #endif +#if (DRC_DEBUG & 8) +static u32 lastpc, lastcnt; +static void *lastblock; +#endif +#if (DRC_DEBUG & (8|256|512|1024)) || defined(PDB) static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr) { if (block != NULL) { - dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm', - sh2->pc, block, (signed int)sr >> 12); #if defined PDB + dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave?'s':'m', + sh2->pc, block, (signed int)sr >> 12); pdb_step(sh2, sh2->pc); +#elif (DRC_DEBUG & 8) + if (lastpc != sh2->pc) { + if (lastcnt) + dbg(8, "= %csh2 enter %08x %p (%d times), c=%d", sh2->is_slave?'s':'m', + lastpc, lastblock, lastcnt, (signed int)sr >> 12); + dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave?'s':'m', + sh2->pc, block, (signed int)sr >> 12); + lastpc = sh2->pc; + lastblock = block; + lastcnt = 0; + } else + lastcnt++; #elif (DRC_DEBUG & 256) { static SH2 fsh2; @@ -468,7 +484,7 @@ static void rcache_free_tmp(int hr); #include "../drc/emit_mips.c" #elif defined(__riscv__) || defined(__riscv) #include "../drc/emit_riscv.c" -#elif defined(__powerpc__) || defined(_M_PPC) +#elif defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC) #include "../drc/emit_ppc.c" #elif defined(__i386__) || defined(_M_X86) #include "../drc/emit_x86.c" @@ -1339,6 +1355,7 @@ static void rcache_add_vreg_alias(int x, sh2_reg_e r); static void rcache_remove_vreg_alias(int x, sh2_reg_e r); static void rcache_evict_vreg(int x); static void rcache_remap_vreg(int x); +static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode, int *hr); static void rcache_set_x16(int hr, int s16_, int u16_) { @@ -1444,7 +1461,6 @@ static int rcache_is_u16(int hr) } */ \ } -#if PROPAGATE_CONSTANTS static inline int gconst_alloc(sh2_reg_e r) { int i, n = -1; @@ -1481,7 +1497,6 @@ static void gconst_new(sh2_reg_e r, u32 val) if (guest_regs[r].vreg >= 0) rcache_remove_vreg_alias(guest_regs[r].vreg, r); } -#endif static int gconst_get(sh2_reg_e r, u32 *val) { @@ -2661,6 +2676,10 @@ static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, s32 *offs) } else { // known fixed host address la = split_address(la + ((a + *offs) & mask), omask, offs); + if (la == 0) { + la = *offs; + *offs = 0; + } hr = rcache_get_tmp(); emith_move_r_ptr_imm(hr, la); } @@ -3014,12 +3033,22 @@ static void emit_do_static_regs(int is_write, int tmpr) // divide operation replacement functions, called by compiled code. Only the // 32:16 cases and the 64:32 cases described in the SH2 prog man are replaced. -static uint32_t REGPARM(2) sh2_drc_divu32(uint32_t dv, uint32_t ds) +// This is surprisingly difficult since the SH2 division operation is generating +// the result in the dividend during the operation, leaving some remainder-like +// stuff in the bits unused for the result, and leaving the T and Q status bits +// in a state depending on the operands and the result. Q always reflects the +// last result bit generated (i.e. bit 0 of the result). For T: +// 32:16 T = top bit of the 16 bit remainder-like +// 64:32 T = resulting T of the DIV0U/S operation +// The remainder-like depends on outcome of the last generated result bit. + +static uint32_t REGPARM(3) sh2_drc_divu32(uint32_t dv, uint32_t *dt, uint32_t ds) { - if (ds && ds >= dv) { - // good case: no divide by 0, and no result overflow + if (ds > dv && (uint16_t)ds == 0) { + // good case: no overflow, divisor not 0, lower 16 bits 0 uint32_t quot = dv / (ds>>16), rem = dv - (quot * (ds>>16)); if (~quot&1) rem -= ds>>16; + *dt = (rem>>15) & 1; return (uint16_t)quot | ((2*rem + (quot>>31)) << 16); } else { // bad case: use the sh2 algo to get the right result @@ -3029,20 +3058,21 @@ static uint32_t REGPARM(2) sh2_drc_divu32(uint32_t dv, uint32_t ds) dv = (dv<<1) | t; t = v; v = dv; - if (q) dv += ds, q = dv < v; - else dv -= ds, q = !(dv < v); + if (q) dv += ds, q = dv < v; + else dv -= ds, q = dv > v; q ^= t, t = !q; } + *dt = dv>>31; return (dv<<1) | t; } } static uint32_t REGPARM(3) sh2_drc_divu64(uint32_t dh, uint32_t *dl, uint32_t ds) { - if (ds > 1 && ds >= dh) { - // good case: no divide by 0, and no result overflow + if (ds > dh) { + // good case: no overflow, divisor not 0 uint64_t dv = *dl | ((uint64_t)dh << 32); - uint32_t quot = dv / ds, rem = dv - (quot * ds); + uint32_t quot = dv / ds, rem = dv - ((uint64_t)quot * ds); if (~quot&1) rem -= ds; *dl = quot; return rem; @@ -3055,8 +3085,8 @@ static uint32_t REGPARM(3) sh2_drc_divu64(uint32_t dh, uint32_t *dl, uint32_t ds dv = (dv<<1) | t; t = v; v = dv; - if (q) dv += ((uint64_t)ds << 32), q = dv < v; - else dv -= ((uint64_t)ds << 32), q = !(dv < v); + if (q) dv += ((uint64_t)ds << 32), q = dv < v; + else dv -= ((uint64_t)ds << 32), q = dv > v; q ^= t, t = !q; } *dl = (dv<<1) | t; @@ -3064,16 +3094,17 @@ static uint32_t REGPARM(3) sh2_drc_divu64(uint32_t dh, uint32_t *dl, uint32_t ds } } -static uint32_t REGPARM(2) sh2_drc_divs32(int32_t dv, int32_t ds) +static uint32_t REGPARM(3) sh2_drc_divs32(int32_t dv, uint32_t *dt, int32_t ds) { uint32_t adv = abs(dv), ads = abs(ds)>>16; - if (ads > 1 && ads > adv>>16 && (int32_t)ads > 0 && !(uint16_t)ds) { - // good case: no divide by 0, and no result overflow + if (ads > adv>>16 && ds != 0x80000000 && (int16_t)ds == 0) { + // good case: no overflow, divisor not 0 and not MIN_INT, lower 16 bits 0 uint32_t quot = adv / ads, rem = adv - (quot * ads); int m1 = (rem ? dv^ds : ds) < 0; if (rem && dv < 0) rem = (quot&1 ? -rem : +ads-rem); else rem = (quot&1 ? +rem : -ads+rem); quot = ((dv^ds)<0 ? -quot : +quot) - m1; + *dt = (rem>>15) & 1; return (uint16_t)quot | ((2*rem + (quot>>31)) << 16); } else { // bad case: use the sh2 algo to get the right result @@ -3083,10 +3114,11 @@ static uint32_t REGPARM(2) sh2_drc_divs32(int32_t dv, int32_t ds) dv = (dv<<1) | t; t = v; v = dv; - if (m^q) dv += ds, q = (uint32_t)dv < v; - else dv -= ds, q = !((uint32_t)dv < v); + if (m^q) dv += ds, q = (uint32_t)dv < v; + else dv -= ds, q = (uint32_t)dv > v; q ^= m^t, t = !(m^q); } + *dt = (uint32_t)dv>>31; return (dv<<1) | t; } } @@ -3096,8 +3128,8 @@ static uint32_t REGPARM(3) sh2_drc_divs64(int32_t dh, uint32_t *dl, int32_t ds) int64_t _dv = *dl | ((int64_t)dh << 32); uint64_t adv = (_dv < 0 ? -_dv : _dv); // llabs isn't in older toolchains uint32_t ads = abs(ds); - if (ads > 1 && ads > adv>>32 && (int64_t)adv > 0) { - // good case: no divide by 0, and no result overflow + if (ads > adv>>32 && ds != 0x80000000) { + // good case: no overflow, divisor not 0 and not MIN_INT uint32_t quot = adv / ads, rem = adv - ((uint64_t)quot * ads); int m1 = (rem ? dh^ds : ds) < 0; if (rem && dh < 0) rem = (quot&1 ? -rem : +ads-rem); @@ -3110,12 +3142,12 @@ static uint32_t REGPARM(3) sh2_drc_divs64(int32_t dh, uint32_t *dl, int32_t ds) uint64_t dv = *dl | ((uint64_t)dh << 32); int m = (uint32_t)ds>>31, q = (uint64_t)dv>>63, t = m^q, s = 32; while (s--) { - int64_t v = (uint64_t)dv>>63; + uint64_t v = (uint64_t)dv>>63; dv = (dv<<1) | t; t = v; v = dv; - if (m^q) dv += ((uint64_t)ds << 32), q = dv < v; - else dv -= ((uint64_t)ds << 32), q = !(dv < v); + if (m^q) dv += ((uint64_t)ds << 32), q = dv < v; + else dv -= ((uint64_t)ds << 32), q = dv > v; q ^= m^t, t = !(m^q); } *dl = (dv<<1) | t; @@ -3921,8 +3953,10 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) #if DIV_OPTIMIZER if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) { // divide 32/16 + tmp = rcache_get_tmp_arg(1); + emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_get_reg_arg(0, div(opd).rn, NULL); - rcache_get_reg_arg(1, div(opd).rm, NULL); + rcache_get_reg_arg(2, div(opd).rm, NULL); rcache_invalidate_tmp(); emith_abicall(sh2_drc_divu32); tmp = rcache_get_tmp_ret(); @@ -3934,8 +3968,9 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_and_r_r_imm(tmp3, tmp2, 1); // Q = !Rn[0] emith_eor_r_r_imm(tmp3, tmp3, 1); emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); + emith_ctx_read(tmp3, offsetof(SH2, drc_tmp)); + emith_or_r_r_r(sr, sr, tmp3); // T rcache_free_tmp(tmp3); - emith_or_r_r_r_lsr(sr, sr, tmp2, 31); // T = Rn[31] skip_op = div(opd).div1 + div(opd).rotcl; } else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) { @@ -3960,7 +3995,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_eor_r_r_imm(tmp3, tmp3, 1); emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); rcache_free_tmp(tmp3); - emith_or_r_r_r_lsr(sr, sr, tmp4, 31); // T = Ro[31] skip_op = div(opd).div1 + div(opd).rotcl; } #endif @@ -4035,8 +4069,10 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) #if DIV_OPTIMIZER if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) { // divide 32/16 + tmp = rcache_get_tmp_arg(1); + emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_get_reg_arg(0, div(opd).rn, NULL); - tmp2 = rcache_get_reg_arg(1, div(opd).rm, NULL); + tmp2 = rcache_get_reg_arg(2, div(opd).rm, NULL); tmp3 = rcache_get_tmp(); emith_lsr(tmp3, tmp2, 31); emith_or_r_r_lsl(sr, tmp3, M_SHIFT); // M = Rm[31] @@ -4052,19 +4088,22 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_and_r_r_imm(tmp3, tmp3, 1); emith_eor_r_r_imm(tmp3, tmp3, 1); emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); // Q = !Rn[0]^M + emith_ctx_read(tmp3, offsetof(SH2, drc_tmp)); + emith_or_r_r_r(sr, sr, tmp3); // T rcache_free_tmp(tmp3); - emith_or_r_r_r_lsr(sr, sr, tmp2, 31); // T = Rn[31] skip_op = div(opd).div1 + div(opd).rotcl; } else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) { // divide 64/32 tmp4 = rcache_get_reg(div(opd).ro, RC_GR_READ, NULL); emith_ctx_write(tmp4, offsetof(SH2, drc_tmp)); - rcache_get_reg_arg(0, div(opd).rn, NULL); + tmp = rcache_get_reg_arg(0, div(opd).rn, NULL); tmp2 = rcache_get_reg_arg(2, div(opd).rm, NULL); tmp3 = rcache_get_tmp_arg(1); emith_lsr(tmp3, tmp2, 31); - emith_or_r_r_lsl(sr, tmp3, M_SHIFT); // M = Rm[31] + emith_or_r_r_lsl(sr, tmp3, M_SHIFT); // M = Rm[31] + emith_eor_r_r_lsr(tmp3, tmp, 31); + emith_or_r_r(sr, tmp3); // T = Rn[31]^M emith_add_r_r_ptr_imm(tmp3, CONTEXT_REG, offsetof(SH2, drc_tmp)); rcache_invalidate_tmp(); emith_abicall(sh2_drc_divs64); @@ -4081,7 +4120,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_eor_r_r_imm(tmp3, tmp3, 1); emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); // Q = !Ro[0]^M rcache_free_tmp(tmp3); - emith_or_r_r_r_lsr(sr, sr, tmp4, 31); // T = Ro[31] skip_op = div(opd).div1 + div(opd).rotcl; } else #endif @@ -5639,6 +5677,9 @@ int sh2_execute_drc(SH2 *sh2c, int cycles) // others are usual SH2 flags sh2c->sr &= 0x3f3; sh2c->sr |= cycles << 12; +#if (DRC_DEBUG & 8) + lastpc = lastcnt = 0; +#endif sh2c->state |= SH2_IN_DRC; sh2_drc_entry(sh2c); @@ -5648,6 +5689,11 @@ int sh2_execute_drc(SH2 *sh2c, int cycles) ret_cycles = (int32_t)sh2c->sr >> 12; if (ret_cycles > 0) dbg(1, "warning: drc returned with cycles: %d, pc %08x", ret_cycles, sh2c->pc); +#if (DRC_DEBUG & 8) + if (lastcnt) + dbg(8, "= %csh2 enter %08x %p (%d times), c=%d", sh2c->is_slave?'s':'m', + lastpc, lastblock, lastcnt, (signed int)sh2c->sr >> 12); +#endif sh2c->sr &= 0x3f3; return ret_cycles; diff --git a/cpu/sh2/compiler.h b/cpu/sh2/compiler.h index dda3b91d..8892b236 100644 --- a/cpu/sh2/compiler.h +++ b/cpu/sh2/compiler.h @@ -47,7 +47,7 @@ u16 scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc, #elif defined(__riscv__) || defined(__riscv) #define DRC_SR_REG "s11" #define DRC_REG_LL 0 // no ABI for (__ILP32__ && __riscv_xlen != 32) -#elif defined(__powerpc__) +#elif defined(__powerpc__) || defined(__ppc__) #define DRC_SR_REG "r28" #define DRC_REG_LL 0 // no ABI for __ILP32__ #elif defined(__i386__) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index bf3c9ec0..a34e8075 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -56,14 +56,14 @@ void p32x_update_irls(SH2 *active_sh2, unsigned int m68k_cycles) if (mrun) { p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, m68k_cycles); if (msh2.state & SH2_STATE_RUN) - sh2_end_run(&msh2, 1); + sh2_end_run(&msh2, 0); } srun = sh2_irl_irq(&ssh2, slvl, ssh2.state & SH2_STATE_RUN); if (srun) { p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, m68k_cycles); if (ssh2.state & SH2_STATE_RUN) - sh2_end_run(&ssh2, 1); + sh2_end_run(&ssh2, 0); } elprintf(EL_32X, "update_irls: m %d/%d, s %d/%d", mlvl, mrun, slvl, srun); @@ -142,9 +142,9 @@ void p32x_reset_sh2s(void) unsigned int vbr; // initial data - idl_src = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3d4)) & ~0xf0000000; - idl_dst = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3d8)) & ~0xf0000000; - idl_size= CPU_BE2(*(unsigned int *)(Pico.rom + 0x3dc)); + idl_src = CPU_BE2(*(u32 *)(Pico.rom + 0x3d4)) & ~0xf0000000; + idl_dst = CPU_BE2(*(u32 *)(Pico.rom + 0x3d8)) & ~0xf0000000; + idl_size= CPU_BE2(*(u32 *)(Pico.rom + 0x3dc)); if (idl_size > Pico.romsize || idl_src + idl_size > Pico.romsize || idl_size > 0x40000 || idl_dst + idl_size > 0x40000 || (idl_src & 3) || (idl_dst & 3)) { elprintf(EL_STATUS|EL_ANOMALY, "32x: invalid initial data ptrs: %06x -> %06x, %06x", @@ -154,11 +154,11 @@ void p32x_reset_sh2s(void) memcpy(Pico32xMem->sdram + idl_dst, Pico.rom + idl_src, idl_size); // VBR - vbr = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3e8)); + vbr = CPU_BE2(*(u32 *)(Pico.rom + 0x3e8)); sh2_set_vbr(0, vbr); // checksum and M_OK - Pico32x.regs[0x28 / 2] = *(unsigned short *)(Pico.rom + 0x18e); + Pico32x.regs[0x28 / 2] = *(u16 *)(Pico.rom + 0x18e); } // program will set M_OK } @@ -168,7 +168,7 @@ void p32x_reset_sh2s(void) unsigned int vbr; // GBR/VBR - vbr = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3ec)); + vbr = CPU_BE2(*(u32 *)(Pico.rom + 0x3ec)); sh2_set_gbr(1, 0x20004000); sh2_set_vbr(1, vbr); // program will set S_OK @@ -328,7 +328,7 @@ void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after) left_to_next = C_M68K_TO_SH2(sh2, (int)(event_time_next - now)); if (sh2_cycles_left(sh2) > left_to_next) { if (left_to_next < 1) - left_to_next = 1; + left_to_next = 0; sh2_end_run(sh2, left_to_next); } } @@ -421,7 +421,7 @@ void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target) left_to_event = C_M68K_TO_SH2(sh2, (int)(event_time_next - m68k_target)); if (sh2_cycles_left(sh2) > left_to_event) { if (left_to_event < 1) - left_to_event = 1; + left_to_event = 0; sh2_end_run(sh2, left_to_event); } } diff --git a/pico/32x/draw.c b/pico/32x/draw.c index f5638b96..cc98a692 100644 --- a/pico/32x/draw.c +++ b/pico/32x/draw.c @@ -10,7 +10,7 @@ // BGR555 to native conversion #if defined(USE_BGR555) -#define PXCONV(t) (t) +#define PXCONV(t) ((t)&(mr|mg|mb|mp)) #define PXPRIO 0x8000 // prio in MSB #elif defined(USE_BGR565) #define PXCONV(t) (((t)&mr) | (((t)&(mg|mb)) << 1) | (((t)&mp) >> 10)) diff --git a/pico/32x/draw_arm.S b/pico/32x/draw_arm.S index bf26f746..cdcb211a 100644 --- a/pico/32x/draw_arm.S +++ b/pico/32x/draw_arm.S @@ -101,10 +101,46 @@ mov r6, #320 add r5, r1, r12, lsl #1 @ p32x = dram + dram[l] + ldrh r7, [r5], #2 2: @ loop_inner: - ldrh r8, [r5], #2 + mov r8, r7 subs lr, r6, #1 blt 0b @ loop_outer + beq 7f @ single_pix + ldrh r7, [r5], #2 @ 32x pixel + cmp r7, r8 @ do RLE only if we have at least 2 px +@ ldreqh r7, [r5] +@ cmpeq r7, r8 + subeq lr, lr, #1 + beq 3f @ loop_innermost + +7: @ single_pix: + mov r6, lr + + eor r12,r8, r10 + tst r12, #0x8000 @ !((t ^ inv) & 0x8000) + addeq r11,r11,#1 + beq 8f @ single_pix_32x + + ldrb r12,[r11], #1 @ MD pixel + cmp r3, r12,lsl #26 @ MD has bg pixel? +.if \do_md + movne r12,r12,lsl #1 + ldrneh r12,[r9, r12] + strneh r12,[r0], #2 @ *dst++ = palmd[*pmd] +.else + addne r0, r0, #2 +.endif + bne 2b @ loop_inner + +8: @ single_pix_32x: + and r12,r8, #0x03e0 + mov r8, r8, lsl #11 + orr r8, r8, r8, lsr #(10+11) + orr r8, r8, r12,lsl #1 + bic r8, r8, #0x0020 @ kill prio bit + strh r8, [r0], #2 + b 2b @ loop_inner 3: @ loop_innermost: ldrh r7, [r5], #2 @ 32x pixel @@ -112,7 +148,6 @@ cmpge r7, r8 beq 3b @ loop_innermost - sub r5, r5, #2 add lr, lr, #1 sub lr, r6, lr sub r6, r6, lr @@ -121,10 +156,10 @@ tst r12, #0x8000 @ !((t ^ inv) & 0x8000) bne 5f @ draw_md - and r7 ,r8, #0x03e0 + and r12,r8, #0x03e0 mov r8, r8, lsl #11 orr r8, r8, r8, lsr #(10+11) - orr r8, r8, r7 ,lsl #1 + orr r8, r8, r12,lsl #1 bic r8, r8, #0x0020 @ kill prio bit add r11,r11,lr @@ -148,35 +183,35 @@ 5: @ draw_md: subs lr, lr, #1 - ldrgeb r7, [r11], #1 @ MD pixel + ldrgeb r12,[r11], #1 @ MD pixel blt 2b @ loop_inner - cmp r3, r7, lsl #26 @ MD has bg pixel? + cmp r3, r12,lsl #26 @ MD has bg pixel? .if \do_md - mov r7, r7, lsl #1 - ldrneh r7 ,[r9, r7] - strneh r7 ,[r0], #2 @ *dst++ = palmd[*pmd] + mov r12,r12,lsl #1 + ldrneh r12,[r9, r12] + strneh r12,[r0], #2 @ *dst++ = palmd[*pmd] .else addne r0, r0, #2 .endif bne 5b @ draw_md - and r7 ,r8, #0x03e0 + and r12,r8, #0x03e0 mov r8, r8, lsl #11 orr r8, r8, r8, lsr #(10+11) - orr r8, r8, r7 ,lsl #1 + orr r8, r8, r12,lsl #1 bic r8, r8, #0x0020 @ kill prio bit strh r8, [r0], #2 @ *dst++ = bgr2rgb(*p32x++) 6: @ draw_md_32x: subs lr, lr, #1 - ldrgeb r7, [r11], #1 @ MD pixel + ldrgeb r12,[r11], #1 @ MD pixel blt 2b @ loop_inner - cmp r3, r7, lsl #26 @ MD has bg pixel? + cmp r3, r12,lsl #26 @ MD has bg pixel? .if \do_md - mov r7, r7, lsl #1 - ldrneh r7 ,[r9, r7] @ *dst++ = palmd[*pmd] - moveq r7 ,r8 @ *dst++ = bgr2rgb(*p32x++) - strh r7 ,[r0], #2 + mov r12,r12,lsl #1 + ldrneh r12,[r9, r12] @ *dst++ = palmd[*pmd] + moveq r12,r8 @ *dst++ = bgr2rgb(*p32x++) + strh r12,[r0], #2 .else streqh r8, [r0] @ *dst++ = bgr2rgb(*p32x++) add r0, r0, #2 diff --git a/pico/32x/memory.c b/pico/32x/memory.c index fe9ae57d..8cd1c198 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -126,7 +126,7 @@ void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt) sh2->state, sh2->state | flags); sh2->state |= flags; - sh2_end_run(sh2, 1); + sh2_end_run(sh2, 0); pevt_log_sh2(sh2, EVT_POLL_START); #ifdef DRC_SH2 // mark this as an address used for polling if SDRAM @@ -324,7 +324,7 @@ static u32 sh2_comm_faker(u32 a) static int f = 0; if (a == 0x28 && !p32x_csum_faked) { p32x_csum_faked = 1; - return *(unsigned short *)(Pico.rom + 0x18e); + return *(u16 *)(Pico.rom + 0x18e); } if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0])) f = 0; @@ -855,7 +855,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) p32x_m68k_poll_event(P32XF_68KCPOLL); p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles); if (p32x_sh2_ready(sh2->other_sh2, cycles+8)) - sh2_end_run(sh2, 1); + sh2_end_run(sh2, 0); sh2_poll_write(a & ~1, r[a / 2], cycles, sh2); } return; @@ -948,7 +948,7 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) p32x_m68k_poll_event(P32XF_68KCPOLL); p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles); if (p32x_sh2_ready(sh2->other_sh2, cycles+8)) - sh2_end_run(sh2, 1); + sh2_end_run(sh2, 0); sh2_poll_write(a, d, cycles, sh2); } return; @@ -1583,7 +1583,7 @@ static void sh2_sdram_poll(u32 a, u32 d, SH2 *sh2) sh2_poll_write(a, d, cycles, sh2); p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_RPOLL, cycles); if (p32x_sh2_ready(sh2->other_sh2, cycles+8)) - sh2_end_run(sh2, 1); + sh2_end_run(sh2, 0); DRC_RESTORE_SR(sh2); } @@ -1690,16 +1690,21 @@ static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2) } #endif +static NOINLINE void REGPARM(3) sh2_write8_sdram_sync(u32 a, u32 d, SH2 *sh2) +{ + DRC_SAVE_SR(sh2); + sh2_end_run(sh2, 32); + DRC_RESTORE_SR(sh2); + sh2_write8_sdram(a, d, sh2); +} + static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2) { // xmen sync hack.. - if (a < 0x26000200) { - DRC_SAVE_SR(sh2); - sh2_end_run(sh2, 32); - DRC_RESTORE_SR(sh2); - } - - sh2_write8_sdram(a, d, sh2); + if ((a << 8) >> 17) // ((a & 0x00ffffff) < 0x200) + sh2_write8_sdram(a, d, sh2); + else + sh2_write8_sdram_sync(a, d, sh2); } // write16 diff --git a/pico/cart.c b/pico/cart.c index 81fc7fb0..1d17c713 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -187,7 +187,7 @@ zip_failed: else if (strcasecmp(ext, "cso") == 0) { cso_struct *cso = NULL, *tmp = NULL; - int size; + int i, size; f = fopen(path, "rb"); if (f == NULL) goto cso_failed; @@ -229,6 +229,8 @@ zip_failed: elprintf(EL_STATUS, "cso: premature EOF"); goto cso_failed; } + for (i = 0; i < size/4; i++) + cso->index[i] = CPU_LE4(cso->index[i]); // all ok cso->fpos_in = ftell(f); @@ -280,7 +282,7 @@ cso_failed: chd->file.file = chd; chd->file.type = PMT_CHD; // subchannel data is skipped, remove it from total size - chd->file.size = chd_get_header(cf)->logicalbytes / CD_FRAME_SIZE * CD_MAX_SECTOR_DATA; + chd->file.size = head->logicalbytes / CD_FRAME_SIZE * CD_MAX_SECTOR_DATA; strncpy(chd->file.ext, ext, sizeof(chd->file.ext) - 1); return &chd->file; @@ -359,7 +361,7 @@ static size_t _pm_read_chd(void *ptr, size_t bytes, pm_file *stream, int is_audi if (len > bytes) len = bytes; -#ifdef CPU_IS_LE +#if CPU_IS_LE if (is_audio) { // convert big endian audio samples u16 *dst = ptr, v; @@ -821,7 +823,7 @@ int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_ // This will hang the emu, but will prevent nasty crashes. // note: 4 bytes are padded to every ROM if (rom != NULL) - *(unsigned long *)(rom+romsize) = CPU_BE2(0x4EFAFFFE); + *(u32 *)(rom+romsize) = CPU_BE2(0x4EFAFFFE); Pico.rom=rom; Pico.romsize=romsize; @@ -1254,11 +1256,11 @@ static void PicoCartDetect(const char *carthw_cfg) int fill_sram = 0; memset(&Pico.sv, 0, sizeof(Pico.sv)); - if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A') + if (Pico.rom[MEM_BE2(0x1B0)] == 'R' && Pico.rom[MEM_BE2(0x1B1)] == 'A') { Pico.sv.start = rom_read32(0x1B4) & ~0xff000001; // align Pico.sv.end = (rom_read32(0x1B8) & ~0xff000000) | 1; - if (Pico.rom[0x1B2] & 0x40) + if (Pico.rom[MEM_BE2(0x1B3)] & 0x40) // EEPROM Pico.sv.flags |= SRF_EEPROM; Pico.sv.flags |= SRF_ENABLED; @@ -1309,7 +1311,7 @@ static void PicoCartDetect(const char *carthw_cfg) // Unusual region 'code' if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0) - *(int *) (Pico.rom + 0x1f0) = 0x20204520; + *(u32 *) (Pico.rom + 0x1f0) = CPU_LE4(0x20204520); } // vim:shiftwidth=2:expandtab diff --git a/pico/cd/cdc.c b/pico/cd/cdc.c index bf688f57..70914636 100644 --- a/pico/cd/cdc.c +++ b/pico/cd/cdc.c @@ -367,7 +367,7 @@ void cdc_dma_update(void) { /* update IRQ level */ elprintf(EL_INTS, "cdc DTE irq 5"); - SekInterruptS68k(5); + pcd_irq_s68k(5, 1); } } @@ -411,7 +411,7 @@ int cdc_decoder_update(uint8 header[4]) { /* update IRQ level */ elprintf(EL_INTS, "cdc DEC irq 5"); - SekInterruptS68k(5); + pcd_irq_s68k(5, 1); } } @@ -469,13 +469,13 @@ void cdc_reg_w(unsigned char data) { /* update IRQ level */ elprintf(EL_INTS, "cdc pending irq 5"); - SekInterruptS68k(5); + pcd_irq_s68k(5, 1); } } else // if (scd.pending & (1 << 5)) { /* clear pending level 5 interrupts */ - SekInterruptClearS68k(5); + pcd_irq_s68k(5, 0); } /* abort any data transfer if data output is disabled */ @@ -614,7 +614,7 @@ void cdc_reg_w(unsigned char data) if ((cdc.ifstat | BIT_DECI) || !(cdc.ifctrl & BIT_DECIEN)) { /* clear pending level 5 interrupt */ - SekInterruptClearS68k(5); + pcd_irq_s68k(5, 0); } #endif Pico_mcd->s68k_regs[0x04+1] = 0x08; @@ -774,7 +774,7 @@ unsigned char cdc_reg_r(void) if ((cdc.ifstat | BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN)) { /* clear pending level 5 interrupt */ - SekInterruptClearS68k(5); + pcd_irq_s68k(5, 0); } #endif @@ -826,7 +826,7 @@ unsigned short cdc_host_r(void) { /* update IRQ level */ elprintf(EL_INTS, "cdc DTE irq 5"); - SekInterruptS68k(5); + pcd_irq_s68k(5, 1); } } diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index fd78c357..00e12bad 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -444,6 +444,9 @@ int cdd_unload(void) { int i; + /* stop audio streaming */ + Pico_mcd->cdda_stream = NULL; + /* close CD tracks */ if (cdd.toc.tracks[0].fd) { diff --git a/pico/cd/gfx.c b/pico/cd/gfx.c index b7d9cf1c..0a231b7a 100644 --- a/pico/cd/gfx.c +++ b/pico/cd/gfx.c @@ -421,7 +421,7 @@ void gfx_update(unsigned int cycles) if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) { elprintf(EL_INTS|EL_CD, "s68k: gfx_cd irq 1"); - SekInterruptS68k(1); + pcd_irq_s68k(1, 1); } } else { diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 559fca7a..7554f8c6 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -124,9 +124,6 @@ static void SekRunS68k(unsigned int to) if ((cyc_do = SekCycleAimS68k - SekCycleCntS68k) <= 0) return; - if (SekShouldInterrupt()) - Pico_mcd->m.s68k_poll_a = 0; - pprof_start(s68k); SekCycleCntS68k += cyc_do; #if defined(EMU_C68K) @@ -177,7 +174,7 @@ static void pcd_cdc_event(unsigned int now) if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) { elprintf(EL_INTS|EL_CD, "s68k: cdd irq 4"); - SekInterruptS68k(4); + pcd_irq_s68k(4, 1); } } @@ -188,7 +185,7 @@ static void pcd_int3_timer_event(unsigned int now) { if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN3) { elprintf(EL_INTS|EL_CD, "s68k: timer irq 3"); - SekInterruptS68k(3); + pcd_irq_s68k(3, 1); } if (Pico_mcd->s68k_regs[0x31] != 0) @@ -280,6 +277,16 @@ static void pcd_run_events(unsigned int until) oldest, event_time_next); } +void pcd_irq_s68k(int irq, int state) +{ + if (state) { + SekInterruptS68k(irq); + SekSetStopS68k(0); + Pico_mcd->m.s68k_poll_a = 0; + } else + SekInterruptClearS68k(irq); +} + int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync) { #define now SekCycleCntS68k @@ -307,7 +314,11 @@ int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync) if (event_time_next && CYCLES_GT(target, event_time_next)) target = event_time_next; - SekRunS68k(target); + if (SekIsStoppedS68k()) + SekCycleCntS68k = SekCycleAimS68k = target; + else + SekRunS68k(target); + if (m68k_poll_sync && Pico_mcd->m.m68k_poll_cnt == 0) break; } @@ -324,20 +335,27 @@ static void SekSyncM68k(void); void pcd_run_cpus_normal(int m68k_cycles) { Pico.t.m68c_aim += m68k_cycles; - if (SekShouldInterrupt() || Pico_mcd->m.m68k_poll_cnt < 12) - Pico_mcd->m.m68k_poll_cnt = 0; - else if (Pico_mcd->m.m68k_poll_cnt >= 16) { - int s68k_left = pcd_sync_s68k(Pico.t.m68c_aim, 1); - if (s68k_left <= 0) { - elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x", - Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc); - Pico.t.m68c_cnt = Pico.t.m68c_aim; - return; - } - Pico.t.m68c_cnt = Pico.t.m68c_aim - (s68k_left * mcd_s68k_cycle_mult >> 16); - } while (CYCLES_GT(Pico.t.m68c_aim, Pico.t.m68c_cnt)) { + if (SekShouldInterrupt()) + Pico_mcd->m.m68k_poll_cnt = 0; + +#ifdef USE_POLL_DETECT + if (Pico_mcd->m.m68k_poll_cnt >= 16) { + // main CPU is polling, (wake and) run sub only + SekSetStopS68k(0); + pcd_sync_s68k(Pico.t.m68c_aim, 1); + + Pico.t.m68c_cnt = Pico.t.m68c_aim; + if (SekIsStoppedS68k()) { + // slave has stopped, wake master to avoid lockups + Pico_mcd->m.m68k_poll_cnt = 0; + } + elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x", + Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc); + } +#endif + SekRunM68kOnce(); if (Pico_mcd->m.need_sync) { Pico_mcd->m.need_sync = 0; diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 7cf9ffd5..558251c7 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -150,7 +150,7 @@ void m68k_reg_write8(u32 a, u32 d) if (d && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN2)) { elprintf(EL_INTS, "m68k: s68k irq 2"); pcd_sync_s68k(SekCyclesDone(), 0); - SekInterruptS68k(2); + pcd_irq_s68k(2, 1); } return; case 1: @@ -205,10 +205,10 @@ void m68k_reg_write8(u32 a, u32 d) goto write_comm; case 6: - Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer + Pico_mcd->bios[MEM_BE2(0x72)] = d; // simple hint vector changer return; case 7: - Pico_mcd->bios[0x72] = d; + Pico_mcd->bios[MEM_BE2(0x73)] = d; elprintf(EL_CDREGS, "hint vector set to %04x%04x", ((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]); return; @@ -277,7 +277,7 @@ u32 s68k_poll_detect(u32 a, u32 d) #define READ_FONT_DATA(basemask) \ { \ - unsigned int fnt = *(unsigned int *)(Pico_mcd->s68k_regs + 0x4c); \ + unsigned int fnt = CPU_LE4(*(u32 *)(Pico_mcd->s68k_regs + 0x4c)); \ unsigned int col0 = (fnt >> 8) & 0x0f, col1 = (fnt >> 12) & 0x0f; \ if (fnt & (basemask << 0)) d = col1 ; else d = col0; \ if (fnt & (basemask << 1)) d |= col1 << 4; else d |= col0 << 4; \ @@ -331,7 +331,7 @@ u32 s68k_reg_read16(u32 a) d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; - if (a >= 0x0e && a < 0x30) + if (a >= 0x0e && a < 0x20) return s68k_poll_detect(a, d); return d; @@ -425,7 +425,7 @@ void s68k_reg_write8(u32 a, u32 d) // XXX: emulate pending irq instead? if (Pico_mcd->s68k_regs[0x37] & 4) { elprintf(EL_INTS, "cdd export irq 4 (unmask)"); - SekInterruptS68k(4); + pcd_irq_s68k(4, 1); } } break; @@ -443,7 +443,7 @@ void s68k_reg_write8(u32 a, u32 d) if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) { elprintf(EL_INTS, "cdd export irq 4"); - SekInterruptS68k(4); + pcd_irq_s68k(4, 1); } } return; @@ -1094,7 +1094,7 @@ void pcd_state_loaded_mem(void) Pico_mcd->m.dmna_ret_2m &= 3; // restore hint vector - *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector; + *(u16 *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector; } #ifdef EMU_M68K diff --git a/pico/cd/pcm.c b/pico/cd/pcm.c index 27fb2ac9..b77196a4 100644 --- a/pico/cd/pcm.c +++ b/pico/cd/pcm.c @@ -88,7 +88,7 @@ void pcd_pcm_sync(unsigned int to) } addr = ch->addr; - inc = *(unsigned short *)&ch->regs[2]; + inc = ch->regs[2] + (ch->regs[3]<<8); mul_l = ((int)ch->regs[0] * (ch->regs[1] & 0xf)) >> (5+1); mul_r = ((int)ch->regs[0] * (ch->regs[1] >> 4)) >> (5+1); @@ -99,7 +99,7 @@ void pcd_pcm_sync(unsigned int to) // test for loop signal if (smp == 0xff) { - addr = *(unsigned short *)&ch->regs[4]; // loop_addr + addr = ch->regs[4] + (ch->regs[5]<<8); // loop_addr smp = Pico_mcd->pcm_ram[addr]; addr <<= PCM_STEP_SHIFT; if (smp == 0xff) @@ -120,7 +120,7 @@ end: Pico_mcd->pcm_mixpos += steps; } -void pcd_pcm_update(int *buf32, int length, int stereo) +void pcd_pcm_update(s32 *buf32, int length, int stereo) { int step, *pcm; int p = 0; diff --git a/pico/m68kif_cyclone.s b/pico/m68kif_cyclone.s index ec3087e5..6f2a9bcc 100644 --- a/pico/m68kif_cyclone.s +++ b/pico/m68kif_cyclone.s @@ -81,9 +81,9 @@ cyclone_fetch32: ldr r1, [r1, r2, lsl #2] bic r0, r0, #1 movs r1, r1, lsl #1 - ldrcch r0, [r1, r0]! + ldrcch r2, [r1, r0]! ldrcch r1, [r1, #2] - orrcc r0, r1, r0, lsl #16 + orrcc r0, r1, r2, lsl #16 bxcc lr stmfd sp!,{r0,r1,r2,lr} diff --git a/pico/patch.c b/pico/patch.c index 4b6b5472..b4c2d898 100644 --- a/pico/patch.c +++ b/pico/patch.c @@ -446,11 +446,11 @@ void PicoPatchPrepare(void) addr=PicoPatches[i].addr; addr &= ~1; if (addr < Pico.romsize) - PicoPatches[i].data_old = *(unsigned short *)(Pico.rom + addr); + PicoPatches[i].data_old = *(u16 *)(Pico.rom + addr); else { if(!(PicoIn.AHW & PAHW_SMS)) - PicoPatches[i].data_old = (unsigned short) m68k_read16(addr); + PicoPatches[i].data_old = (u16) m68k_read16(addr); else ;// wrong: PicoPatches[i].data_old = (unsigned char) PicoRead8_z80(addr); } @@ -473,7 +473,7 @@ void PicoPatchApply(void) if (PicoPatches[i].active) { if (!(PicoIn.AHW & PAHW_SMS)) - *(unsigned short *)(Pico.rom + addr) = PicoPatches[i].data; + *(u16 *)(Pico.rom + addr) = PicoPatches[i].data; else if (!PicoPatches[i].comp || PicoPatches[i].comp == *(char *)(Pico.rom + addr)) *(char *)(Pico.rom + addr) = (char) PicoPatches[i].data; } @@ -485,13 +485,13 @@ void PicoPatchApply(void) if (u == i) { if (!(PicoIn.AHW & PAHW_SMS)) - *(unsigned short *)(Pico.rom + addr) = PicoPatches[i].data_old; + *(u16 *)(Pico.rom + addr) = PicoPatches[i].data_old; else *(char *)(Pico.rom + addr) = (char) PicoPatches[i].data_old; } } // fprintf(stderr, "patched %i: %06x:%04x\n", PicoPatches[i].active, addr, - // *(unsigned short *)(Pico.rom + addr)); + // *(u16 *)(Pico.rom + addr)); } else { diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index c5d72278..d1ebe22b 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -67,7 +67,8 @@ static void do_hint(struct PicoVideo *pv) pv->pending_ints |= 0x10; if (pv->reg[0] & 0x10) { elprintf(EL_INTS, "hint: @ %06x [%u]", SekPc, SekCyclesDone()); - SekInterrupt(4); + if (SekIrqLevel < 4) + SekInterrupt(4); } } diff --git a/pico/pico_int.h b/pico/pico_int.h index cc3d2f44..c4044167 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -773,6 +773,7 @@ void pcd_event_schedule(unsigned int now, enum pcd_event event, int after); void pcd_event_schedule_s68k(enum pcd_event event, int after); void pcd_prepare_frame(void); unsigned int pcd_cycles_m68k_to_s68k(unsigned int c); +void pcd_irq_s68k(int irq, int state); int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync); void pcd_run_cpus(int m68k_cycles); void pcd_soft_reset(void); @@ -780,7 +781,7 @@ void pcd_state_loaded(void); // cd/pcm.c void pcd_pcm_sync(unsigned int to); -void pcd_pcm_update(int *buffer, int length, int stereo); +void pcd_pcm_update(s32 *buffer, int length, int stereo); void pcd_pcm_write(unsigned int a, unsigned int d); unsigned int pcd_pcm_read(unsigned int a); diff --git a/pico/pico_port.h b/pico/pico_port.h index a5f8a582..d2b78e05 100644 --- a/pico/pico_port.h +++ b/pico/pico_port.h @@ -57,7 +57,7 @@ #define MEM_LE2(a) (a) #define MEM_LE4(a) (a) // swapping -#define CPU_BE2(v) ((u32)((u64)(v)<<16)|((v)>>16)) +#define CPU_BE2(v) ((u32)((u64)(v)<<16)|((u32)(v)>>16)) #define CPU_BE4(v) (((u32)(v)>>24)|(((v)>>8)&0x00ff00)| \ (((v)<<8)&0xff0000)|(u32)((v)<<24)) #define CPU_LE2(v) (v) // swap of 2*u16 in u32 @@ -71,7 +71,7 @@ // swapping #define CPU_BE2(v) (v) #define CPU_BE4(v) (v) -#define CPU_LE2(v) ((u32)((u64)(v)<<16)|((v)>>16)) +#define CPU_LE2(v) ((u32)((u64)(v)<<16)|((u32)(v)>>16)) #define CPU_LE4(v) (((u32)(v)>>24)|(((v)>>8)&0x00ff00)| \ (((v)<<8)&0xff0000)|(u32)((v)<<24)) #endif diff --git a/pico/sek.c b/pico/sek.c index 6c340672..bd8f70f5 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -192,14 +192,14 @@ PICO_INTERNAL void SekSetRealTAS(int use_real) // XXX: rename PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub) { - unsigned int pc=0; + u32 pc=0; #if defined(EMU_C68K) struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k; memcpy(cpu,context->d,0x40); pc=context->pc-context->membase; - *(unsigned int *)(cpu+0x44)=CycloneGetSr(context); - *(unsigned int *)(cpu+0x48)=context->osp; + *(u32 *)(cpu+0x44)=CycloneGetSr(context); + *(u32 *)(cpu+0x48)=context->osp; cpu[0x4c] = context->irq; cpu[0x4d] = context->state_flags & 1; #elif defined(EMU_M68K) @@ -207,8 +207,8 @@ PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub) m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k); memcpy(cpu,m68ki_cpu_p->dar,0x40); pc=m68ki_cpu_p->pc; - *(unsigned int *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR); - *(unsigned int *)(cpu+0x48)=m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]; + *(u32 *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR); + *(u32 *)(cpu+0x48)=m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]; cpu[0x4c] = CPU_INT_LEVEL>>8; cpu[0x4d] = CPU_STOPPED; m68k_set_context(oldcontext); @@ -216,14 +216,14 @@ PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub) M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k; memcpy(cpu,context->dreg,0x40); pc=context->pc; - *(unsigned int *)(cpu+0x44)=context->sr; - *(unsigned int *)(cpu+0x48)=context->asp; + *(u32 *)(cpu+0x44)=context->sr; + *(u32 *)(cpu+0x48)=context->asp; cpu[0x4c] = context->interrupts[0]; cpu[0x4d] = (context->execinfo & FM68K_HALTED) ? 1 : 0; #endif - *(unsigned int *)(cpu+0x40) = pc; - *(unsigned int *)(cpu+0x50) = + *(u32 *)(cpu+0x40) = pc; + *(u32 *)(cpu+0x50) = is_sub ? SekCycleCntS68k : Pico.t.m68c_cnt; } @@ -231,11 +231,11 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) { #if defined(EMU_C68K) struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k; - CycloneSetSr(context, *(unsigned int *)(cpu+0x44)); - context->osp=*(unsigned int *)(cpu+0x48); + CycloneSetSr(context, *(u32 *)(cpu+0x44)); + context->osp=*(u32 *)(cpu+0x48); memcpy(context->d,cpu,0x40); context->membase = 0; - context->pc = *(unsigned int *)(cpu+0x40); + context->pc = *(u32 *)(cpu+0x40); CycloneUnpack(context, NULL); // rebase PC context->irq = cpu[0x4c]; context->state_flags = 0; @@ -244,27 +244,27 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) #elif defined(EMU_M68K) void *oldcontext = m68ki_cpu_p; m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k); - m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44)); + m68k_set_reg(M68K_REG_SR, *(u32 *)(cpu+0x44)); memcpy(m68ki_cpu_p->dar,cpu,0x40); - m68ki_cpu_p->pc=*(unsigned int *)(cpu+0x40); - m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]=*(unsigned int *)(cpu+0x48); + m68ki_cpu_p->pc=*(u32 *)(cpu+0x40); + m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]=*(u32 *)(cpu+0x48); CPU_INT_LEVEL = cpu[0x4c] << 8; CPU_STOPPED = cpu[0x4d]; m68k_set_context(oldcontext); #elif defined(EMU_F68K) M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k; memcpy(context->dreg,cpu,0x40); - context->pc =*(unsigned int *)(cpu+0x40); - context->sr =*(unsigned int *)(cpu+0x44); - context->asp=*(unsigned int *)(cpu+0x48); + context->pc =*(u32 *)(cpu+0x40); + context->sr =*(u32 *)(cpu+0x44); + context->asp=*(u32 *)(cpu+0x48); context->interrupts[0] = cpu[0x4c]; context->execinfo &= ~FM68K_HALTED; if (cpu[0x4d]&1) context->execinfo |= FM68K_HALTED; #endif if (is_sub) - SekCycleCntS68k = *(unsigned int *)(cpu+0x50); + SekCycleCntS68k = *(u32 *)(cpu+0x50); else - Pico.t.m68c_cnt = *(unsigned int *)(cpu+0x50); + Pico.t.m68c_cnt = *(u32 *)(cpu+0x50); } diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 806a597b..76a9be84 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -17,10 +17,10 @@ void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo; // master int buffer to mix to -static int PsndBuffer[2*(44100+100)/50]; +static s32 PsndBuffer[2*(44100+100)/50]; // cdda output buffer -short cdda_out_buffer[2*1152]; +s16 cdda_out_buffer[2*1152]; // sn76496 extern int *sn76496_regs; @@ -236,7 +236,7 @@ PICO_INTERNAL void PsndDoFM(int cyc_to) // Q16, number of samples since last call len = (cyc_to * Pico.snd.clkl_mult) - Pico.snd.fm_pos; - // don't do this too often (about once every canline) + // don't do this too often (about once every scanline) if (len >> 16 <= PicoIn.sndRate >> 10) return; diff --git a/platform/common/config_file.c b/platform/common/config_file.c index 59bbe122..8c80f7d5 100644 --- a/platform/common/config_file.c +++ b/platform/common/config_file.c @@ -280,7 +280,7 @@ static int custom_read(menu_entry *me, const char *var, const char *val) return 1; case MA_OPT_SOUND_ALPHA: - if (strcasecmp(var, "Filter strength (alpha)") != 0) return 0; + if (strcasecmp(var, "Filter strength") != 0) return 0; PicoIn.sndFilterAlpha = 0x10000 * atof(val); return 1; diff --git a/platform/common/dr_libs b/platform/common/dr_libs new file mode 160000 index 00000000..343aa923 --- /dev/null +++ b/platform/common/dr_libs @@ -0,0 +1 @@ +Subproject commit 343aa923439e59e7a9f7726f70edc77a4500bdec diff --git a/platform/common/host_dasm.c b/platform/common/host_dasm.c index 03a28946..fb7a4259 100644 --- a/platform/common/host_dasm.c +++ b/platform/common/host_dasm.c @@ -7,10 +7,10 @@ #include #include -#ifdef __mips__ +#if defined __mips__ #include "dismips.c" #define disasm dismips -#else +#elif defined __arm__ #include "disarm.c" #define disasm disarm #endif @@ -36,6 +36,7 @@ static const char *lookup_name(void *addr) return NULL; } +#ifdef disasm void host_dasm(void *addr, int len) { void *end = (char *)addr + len; @@ -65,6 +66,30 @@ void host_dasm(void *addr, int len) addr = (char *)addr + sizeof(long); } } +#else +void host_dasm(void *addr, int len) +{ + uint8_t *end = (uint8_t *)addr + len; + char buf[64]; + uint8_t *p = addr; + int i = 0, o = 0; + + o = snprintf(buf, sizeof(buf), "%p: ", p); + while (p < end) { + o += snprintf(buf+o, sizeof(buf)-o, "%02x ", *p++); + if (++i >= 16) { + buf[o] = '\0'; + printf("%s\n", buf); + o = snprintf(buf, sizeof(buf), "%p: ", p); + i = 0; + } + } + if (i) { + buf[o] = '\0'; + printf("%s\n", buf); + } +} +#endif void host_dasm_new_symbol_(void *addr, const char *name) { diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 23e3db06..fd0e56cc 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -84,8 +84,7 @@ static const char *men_dummy[] = { NULL }; #elif defined(PANDORA) #include #else -#define MENU_OPTIONS_GFX -#define MENU_OPTIONS_ADV +#include #endif diff --git a/platform/common/mp3_drmp3.c b/platform/common/mp3_drmp3.c new file mode 100644 index 00000000..54d3496d --- /dev/null +++ b/platform/common/mp3_drmp3.c @@ -0,0 +1,65 @@ +/* + * MP3 decoding using dr_mp3 + * (C) kub, 2020 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include + +#include +#define DR_MP3_IMPLEMENTATION +#include "dr_libs/dr_mp3.h" +#include "mp3.h" + +static drmp3dec mp3dec; +static unsigned char mp3_input_buffer[2 * 1024]; + +int mp3dec_start(FILE *f, int fpos_start) +{ + drmp3dec_init(&mp3dec); + return 0; +} + +int mp3dec_decode(FILE *f, int *file_pos, int file_len) +{ + drmp3dec_frame_info info; + unsigned char *readPtr; + int bytesLeft; + int offset; // mp3 frame offset from readPtr + int len; + int retry = 3; + + do + { + if (*file_pos >= file_len) + return 1; /* EOF, nothing to do */ + + fseek(f, *file_pos, SEEK_SET); + bytesLeft = fread(mp3_input_buffer, 1, sizeof(mp3_input_buffer), f); + + offset = mp3_find_sync_word(mp3_input_buffer, bytesLeft); + if (offset < 0) { + lprintf("find_sync_word (%i/%i) err %i\n", + *file_pos, file_len, offset); + *file_pos = file_len; + return 1; // EOF + } + *file_pos += offset; + readPtr = mp3_input_buffer + offset; + bytesLeft -= offset; + + len = drmp3dec_decode_frame(&mp3dec, readPtr, bytesLeft, cdda_out_buffer, &info); + if (len > 0) // retrieved decoded data + *file_pos += info.frame_bytes; + else if (info.frame_bytes > 0) // no output but input consumed? + *file_pos += 1; // try to skip frame + else if (offset == 0) // bad frame? + *file_pos += 1; // try resyncing + // else // truncated frame, try more data + } + while (len <= 0 && --retry > 0); + + return len <= 0; +} diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index 8d1ebf3e..03ec9823 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -1726,7 +1726,7 @@ void plat_video_loop_prepare(void) // take over any new vout settings XXX ask plat_sdl for scaling instead! plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 0); // switch over to scaled output if available - if (plat_sdl_overlay != NULL || plat_sdl_gl_active) { + if (plat_sdl_overlay != NULL || plat_sdl_gl_active || currentConfig.scaling != EOPT_SCALE_NONE) { g_screen_width = 320; g_screen_height = 240; g_screen_ppitch = g_screen_width; diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 25ae8437..0969017b 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -353,7 +353,7 @@ static void munmap(void *addr, size_t length) void* mmap(void *desired_addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off) { - return malloc(len); + return calloc(1, len); } void munmap(void *base_addr, size_t len) @@ -706,6 +706,8 @@ void lprintf(const char *fmt, ...) } /* libretro */ +bool libretro_supports_bitmasks = false; + void retro_set_environment(retro_environment_t cb) { #ifdef USE_LIBRETRO_VFS @@ -1638,6 +1640,7 @@ void retro_run(void) bool updated = false; int pad, i; static void *buff; + int16_t input; PicoIn.skipFrame = 0; @@ -1647,10 +1650,18 @@ void retro_run(void) input_poll_cb(); PicoIn.pad[0] = PicoIn.pad[1] = 0; - for (pad = 0; pad < 2; pad++) - for (i = 0; i < RETRO_PICO_MAP_LEN; i++) - if (input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, i)) - PicoIn.pad[pad] |= retro_pico_map[i]; + for (pad = 0; pad < 2; pad++) { + if (libretro_supports_bitmasks) { + input = input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); + for (i = 0; i < RETRO_PICO_MAP_LEN; i++) + if (input & (1 << i)) + PicoIn.pad[pad] |= retro_pico_map[i]; + } else { + for (i = 0; i < RETRO_PICO_MAP_LEN; i++) + if (input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, i)) + PicoIn.pad[pad] |= retro_pico_map[i]; + } + } if (PicoPatches) PicoPatchApply(); @@ -1785,6 +1796,9 @@ void retro_init(void) environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control); + if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL)) + libretro_supports_bitmasks = true; + #ifdef _3DS ctr_svchack_successful = ctr_svchack_init(); check_rosalina(); @@ -1853,4 +1867,6 @@ void retro_deinit(void) #endif vout_buf = NULL; PicoExit(); + + libretro_supports_bitmasks = false; } diff --git a/platform/linux/emu.c b/platform/linux/emu.c index 191af764..577243fa 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -32,7 +32,7 @@ void pemu_prep_defconfig(void) void pemu_validate_config(void) { -#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) && !defined(__riscv__) && !defined(__riscv) && !defined(__powerpc__) && !defined(__i386__) && !defined(__x86_64__) +#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) && !defined(__riscv__) && !defined(__riscv) && !defined(__powerpc__) && !defined(__ppc__) && !defined(__i386__) && !defined(__x86_64__) PicoIn.opt &= ~POPT_EN_DRC; #endif } diff --git a/platform/linux/menu.c b/platform/linux/menu.c new file mode 100644 index 00000000..b9bf4cee --- /dev/null +++ b/platform/linux/menu.c @@ -0,0 +1,16 @@ +#include "../libpicofe/gp2x/plat_gp2x.h" + +// ------------ gfx options menu ------------ + + +const char *men_scaling_opts[] = { "OFF", "ON", NULL }; + +#define MENU_OPTIONS_GFX \ + // mee_enum ("screen scaling", MA_OPT_SCALING, currentConfig.scaling, men_scaling_opts), \ + +#define MENU_OPTIONS_ADV + +void linux_menu_init(void) +{ +} + diff --git a/platform/opendingux/data/default.gcw0.desktop b/platform/opendingux/data/default.gcw0.desktop index 3e17a75e..bfdb4298 100644 --- a/platform/opendingux/data/default.gcw0.desktop +++ b/platform/opendingux/data/default.gcw0.desktop @@ -6,4 +6,4 @@ Exec=PicoDrive %f Icon=megadrive Terminal=false Categories=emulators; -MimeType=.md;.smd;.bin;.sms;.cue;.32x;.zip;.7z +MimeType=.md;.smd;.bin;.sms;.cue;.chd;.32x;.zip;.7z diff --git a/platform/opendingux/data/default.retrofw.desktop b/platform/opendingux/data/default.retrofw.desktop index 84a35894..97c977bc 100644 --- a/platform/opendingux/data/default.retrofw.desktop +++ b/platform/opendingux/data/default.retrofw.desktop @@ -3,10 +3,10 @@ Name=Picodrive Comment=A megadrive/genesis emulator Exec=PicoDrive %f Icon=megadrive -Categories=games; +Categories=emulators; X-OD-Manual= X-OD-Selector= -X-OD-Filter=.md,.smd,.bin,.sms,.cue,.32x,.zip,.7z +X-OD-Filter=.md,.smd,.bin,.sms,.cue,.chd,.32x,.zip,.7z Terminal=true Type=Application StartupNotify=true diff --git a/tools/release.sh b/tools/release.sh index 9388c710..a01904ea 100644 --- a/tools/release.sh +++ b/tools/release.sh @@ -15,7 +15,7 @@ # rg350: rg350-toolchain (+ mips-toolchain for newer gcc) # psp: pspdev -mkdir -p release +mkdir -p release-$1 trap "exit" ERR # GPH devices: gp2x, wiz, caanoo, with ubuntu arm gcc 4.7 @@ -23,18 +23,18 @@ trap "exit" ERR TC=$HOME/opt/open2x/gcc-4.1.1-glibc-2.3.6 CROSS_COMPILE=arm-linux-gnueabi- CFLAGS="-I$TC/arm-open2x-linux/include -I$HOME/src/gp2x/armroot/include -U_FORTIFY_SOURCE" LDFLAGS="-B$TC/lib/gcc/arm-open2x-linux/4.1.1 -B$TC/arm-open2x-linux/lib -L$TC/arm-open2x-linux/lib -L$HOME/src/gp2x/armroot/lib" ./configure --platform=gp2x make clean all make -C platform/gp2x rel VER=$1 -mv PicoDrive_$1.zip release/PicoDrive-gph_$1.zip +mv PicoDrive_$1.zip release-$1/PicoDrive-gph_$1.zip # dingux: dingoo a320, ritmix rzx-50, JZ4755 or older (mips32r1 w/o fpu) # NB works for legacy dingux and possibly opendingux before gcw0 TC=$HOME/opt/opendingux-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- CFLAGS="-I $TC/usr/include -I $TC/usr/include/SDL -Wno-unused-result -mabicalls" LDFLAGS="--sysroot $TC" ./configure --platform=dingux TC=$HOME/opt/opendingux-toolchain PATH=$TC/usr/bin:$PATH make clean all -mv PicoDrive-dge.zip release/PicoDrive-dge_$1.zip +mv PicoDrive-dge.zip release-$1/PicoDrive-dge_$1.zip # retrofw: rs-97 and similar, JZ4760 (mips32r1 with fpu) TC=$HOME/opt/mipsel-linux-uclibc PATH=$TC/bin:$PATH CROSS_COMPILE=mipsel-linux- CFLAGS="-I $TC/include -I $TC/include/SDL -Wno-unused-result" LDFLAGS="--sysroot $TC/mipsel-buildroot-linux-uclibc/sysroot" ./configure --platform=retrofw TC=$HOME/opt/mipsel-linux-uclibc PATH=$TC/bin:$PATH make clean all -mv PicoDrive.opk release/PicoDrive-retrofw_$1.opk +mv PicoDrive.opk release-$1/PicoDrive-retrofw_$1.opk # gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons, SDK toolchain #TC=$HOME/opt/gcw0-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL" LDFLAGS="--sysroot $TS" ./configure --platform=gcw0 @@ -43,7 +43,7 @@ mv PicoDrive.opk release/PicoDrive-retrofw_$1.opk # gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons, newer generic gcc TC=$HOME/opt/gcw0-toolchain PATH=$HOME/opt/mips-toolchain/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL -mabicalls" LDFLAGS="--sysroot $TS -Wl,--dynamic-linker=/lib/ld-uClibc.so.0" ./configure --platform=gcw0 PATH=$HOME/opt/mips-toolchain/usr/bin:$PATH make clean all -mv PicoDrive.opk release/PicoDrive-gcw0_$1.opk +mv PicoDrive.opk release-$1/PicoDrive-gcw0_$1.opk # rg350: JZ4770, SDK toolchain #TC=$HOME/opt/rg350-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL" LDFLAGS="--sysroot $TS" ./configure --platform=rg350 @@ -53,10 +53,10 @@ mv PicoDrive.opk release/PicoDrive-gcw0_$1.opk # NB this may or may not work on the newer opendingux beta TC=$HOME/opt/rg350-toolchain PATH=$HOME/opt/mips-toolchain/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL -mabicalls" LDFLAGS="--sysroot $TS -Wl,--dynamic-linker=/lib/ld-uClibc.so.0" ./configure --platform=opendingux PATH=$HOME/opt/mips-toolchain/usr/bin:$PATH make clean all -mv PicoDrive.opk release/PicoDrive-opendingux_$1.opk +mv PicoDrive.opk release-$1/PicoDrive-opendingux_$1.opk # psp (experimental), pspdev SDK toolchain TC=$HOME/opt/pspdev PATH=$TC/bin:$PATH CROSS_COMPILE=psp- CFLAGS="-I$TC/psp/sdk/include -D_POSIX_C_SOURCE=199506L" LDFLAGS="-L$TC/psp/sdk/lib" ./configure --platform=psp TC=$HOME/opt/pspdev PATH=$TC/bin:$PATH make clean all make -C platform/psp rel VER=$1 -mv PicoDrive_psp_$1.zip release/PicoDrive-psp_$1.zip +mv PicoDrive_psp_$1.zip release-$1/PicoDrive-psp_$1.zip From 18e8a645a7182e71a63e7da03ebb5dbba99226d7 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 12 May 2021 10:17:58 +0200 Subject: [PATCH 02/22] 32x, drc, fix saving SH2 SR in dma --- cpu/sh2/compiler.h | 5 +++-- cpu/sh2/sh2.h | 4 ++-- pico/32x/sh2soc.c | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cpu/sh2/compiler.h b/cpu/sh2/compiler.h index 8892b236..f0322743 100644 --- a/cpu/sh2/compiler.h +++ b/cpu/sh2/compiler.h @@ -70,12 +70,13 @@ extern void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2); #else #define DRC_DECLARE_SR register long _sh2_sr asm(DRC_SR_REG) #endif +// NB: save/load SR register only when DRC is executing and not in DMA access #define DRC_SAVE_SR(sh2) \ - if (likely(sh2->state & SH2_IN_DRC)) \ + if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \ sh2->sr = (s32)_sh2_sr // sh2_drc_save_sr(sh2) #define DRC_RESTORE_SR(sh2) \ - if (likely(sh2->state & SH2_IN_DRC)) \ + if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \ _sh2_sr = (s32)sh2->sr // sh2_drc_restore_sr(sh2) #else diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index c3ca1146..614e7de1 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -50,8 +50,8 @@ typedef struct SH2_ #define SH2_STATE_CPOLL (1 << 2) // polling comm regs #define SH2_STATE_VPOLL (1 << 3) // polling VDP #define SH2_STATE_RPOLL (1 << 4) // polling address in SDRAM -#define SH2_TIMER_RUN (1 << 7) // SOC WDT timer is running -#define SH2_IN_DRC (1 << 8) // DRC in use +#define SH2_TIMER_RUN (1 << 6) // SOC WDT timer is running +#define SH2_IN_DRC (1 << 7) // DRC in use unsigned int state; uint32_t poll_addr; int poll_cycles; diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index ae9474d2..f8bb4e79 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -480,10 +480,12 @@ void REGPARM(3) sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) if (!(dmac->dmaor & DMA_DME)) return; + DRC_SAVE_SR(sh2); if ((dmac->chan[0].chcr & (DMA_TE|DMA_DE)) == DMA_DE) dmac_trigger(sh2, &dmac->chan[0]); if ((dmac->chan[1].chcr & (DMA_TE|DMA_DE)) == DMA_DE) dmac_trigger(sh2, &dmac->chan[1]); + DRC_RESTORE_SR(sh2); break; } @@ -538,7 +540,9 @@ static void dreq1_do(SH2 *sh2, struct dma_chan *chan) if ((chan->dar & ~0xf) != 0x20004030) elprintf(EL_32XP|EL_ANOMALY, "dreq1: bad dar?: %08x\n", chan->dar); + sh2->state |= SH2_STATE_SLEEP; dmac_transfer_one(sh2, chan); + sh2->state &= ~SH2_STATE_SLEEP; if (chan->tcr == 0) dmac_transfer_complete(sh2, chan); } From 40e3810a93b36d2a57fe4fc733c9c2d056ef317c Mon Sep 17 00:00:00 2001 From: root Date: Fri, 14 May 2021 19:35:38 +0200 Subject: [PATCH 03/22] mcd, improve polling detection --- pico/cd/mcd.c | 16 ++++++++++------ pico/cd/memory.c | 13 ++++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 7554f8c6..732a4299 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -281,7 +281,8 @@ void pcd_irq_s68k(int irq, int state) { if (state) { SekInterruptS68k(irq); - SekSetStopS68k(0); + if (SekIsStoppedS68k()) + SekSetStopS68k(0); Pico_mcd->m.s68k_poll_a = 0; } else SekInterruptClearS68k(irq); @@ -342,21 +343,24 @@ void pcd_run_cpus_normal(int m68k_cycles) #ifdef USE_POLL_DETECT if (Pico_mcd->m.m68k_poll_cnt >= 16) { + int s68k_left; // main CPU is polling, (wake and) run sub only - SekSetStopS68k(0); - pcd_sync_s68k(Pico.t.m68c_aim, 1); + if (SekIsStoppedS68k()) + SekSetStopS68k(0); + s68k_left = pcd_sync_s68k(Pico.t.m68c_aim, 1); Pico.t.m68c_cnt = Pico.t.m68c_aim; + if (s68k_left > 0) + Pico.t.m68c_cnt -= ((long long)s68k_left * mcd_s68k_cycle_mult >> 16); if (SekIsStoppedS68k()) { // slave has stopped, wake master to avoid lockups Pico_mcd->m.m68k_poll_cnt = 0; } elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x", Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc); - } + } else #endif - - SekRunM68kOnce(); + SekRunM68kOnce(); if (Pico_mcd->m.need_sync) { Pico_mcd->m.need_sync = 0; pcd_sync_s68k(Pico.t.m68c_cnt, 0); diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 558251c7..a7b47b91 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -144,6 +144,8 @@ void m68k_reg_write8(u32 a, u32 d) u32 dold; a &= 0x3f; + Pico_mcd->m.m68k_poll_cnt = 0; + switch (a) { case 0: d &= 1; @@ -180,8 +182,7 @@ void m68k_reg_write8(u32 a, u32 d) return; case 2: elprintf(EL_CDREGS, "m68k: prg wp=%02x", d); - Pico_mcd->s68k_regs[2] = d; // really use s68k side register - return; + goto write_comm; case 3: dold = Pico_mcd->s68k_regs[3]; elprintf(EL_CDREG3, "m68k_regs w3: %02x @%06x", (u8)d, SekPc); @@ -331,7 +332,7 @@ u32 s68k_reg_read16(u32 a) d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; - if (a >= 0x0e && a < 0x20) + if (a >= 0x0e && a < 0x30) return s68k_poll_detect(a, d); return d; @@ -494,6 +495,8 @@ void s68k_reg_write16(u32 a, u32 d) { u8 *r = Pico_mcd->s68k_regs; + Pico_mcd->m.s68k_poll_cnt = 0; + if ((a & 0x1f0) == 0x20) goto write_comm; @@ -501,8 +504,8 @@ void s68k_reg_write16(u32 a, u32 d) case 0x0e: // special case, 2 byte writes would be handled differently // TODO: verify - r[0xf] = d; - return; + d = (u8)d | (r[0xe] << 8); + goto write_comm; case 0x58: // stamp data size r[0x59] = d & 7; return; From 86896ccefcf5523b192575dcb5ec786112829125 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 14 May 2021 23:17:20 +0200 Subject: [PATCH 04/22] mcd, improve polling detection --- pico/cd/mcd.c | 2 +- pico/cd/memory.c | 9 ++++++--- pico/pico_int.h | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 732a4299..602b6eb4 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -342,7 +342,7 @@ void pcd_run_cpus_normal(int m68k_cycles) Pico_mcd->m.m68k_poll_cnt = 0; #ifdef USE_POLL_DETECT - if (Pico_mcd->m.m68k_poll_cnt >= 16) { + if (Pico_mcd->m.m68k_poll_cnt >= 32) { int s68k_left; // main CPU is polling, (wake and) run sub only if (SekIsStoppedS68k()) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index a7b47b91..a47d6a37 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -63,19 +63,22 @@ static void remap_prg_window(u32 r1, u32 r3); static void remap_word_ram(u32 r3); // poller detection -#define POLL_LIMIT 16 +#define POLL_LIMIT 32 #define POLL_CYCLES 64 void m68k_comm_check(u32 a) { - pcd_sync_s68k(SekCyclesDone(), 0); + u32 cycles = SekCyclesDone(); + u32 clkdiff = cycles - Pico_mcd->m.m68k_poll_clk; + pcd_sync_s68k(cycles, 0); if (a >= 0x0e && !Pico_mcd->m.need_sync) { // there are cases when slave updates comm and only switches RAM // over after that (mcd1b), so there must be a resync.. SekEndRun(64); Pico_mcd->m.need_sync = 1; } - if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a) { + Pico_mcd->m.m68k_poll_clk = cycles; + if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a || clkdiff > POLL_CYCLES) { Pico_mcd->m.m68k_poll_a = a; Pico_mcd->m.m68k_poll_cnt = 0; SekNotPolling = 0; diff --git a/pico/pico_int.h b/pico/pico_int.h index c4044167..6a393fbf 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -491,7 +491,8 @@ struct mcd_misc unsigned char dmna_ret_2m; unsigned char need_sync; unsigned char pad3; - int pad4[9]; + unsigned int m68k_poll_clk; + int pad4[8]; }; typedef struct From 17ffa908b8fb7abf03a8337311865570b0501d58 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 May 2021 19:50:48 +0200 Subject: [PATCH 05/22] Added last irixxxx's changes --- .gitmodules | 2 +- cpu/fame/famec_opcodes.h | 6 +----- cpu/sh2/compiler.c | 13 +++++++------ cpu/sh2/mame/sh2pico.c | 12 +++++++----- pico/32x/memory.c | 10 +++++----- pico/cd/mcd.c | 2 +- pico/cd/memory.c | 6 ++++-- 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/.gitmodules b/.gitmodules index 8717be74..339a0944 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/FunKey-Project/picofe-irixxxx.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/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index e069e9ea..d43a563a 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -4614,7 +4614,7 @@ OPCODE(0x013C) src = 1 << (src & 7); FETCH_BYTE(res); flag_NotZ = res & src; -RET(8) +RET(10) } // BTST @@ -24027,11 +24027,7 @@ OPCODE(0x5048) dst = AREGu32((Opcode >> 0) & 7); res = dst + src; AREG((Opcode >> 0) & 7) = res; -#ifdef USE_CYCLONE_TIMING -RET(4) -#else RET(8) -#endif } // ADDQ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 76ccf301..1ddcb19a 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -3540,7 +3540,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) // if exiting a pinned loop pinned regs must be written back to ctx // since they are reloaded in the loop entry code emith_cmp_r_imm(sr, 0); - EMITH_JMP_START(DCOND_GT); + EMITH_JMP_START(DCOND_GE); rcache_save_pinned(); if (blx_target_count < ARRAY_SIZE(blx_targets)) { @@ -3564,13 +3564,13 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_cmp_r_imm(sr, 0); blx_targets[blx_target_count++] = (struct linkage) { .pc = pc, .ptr = tcache_ptr, .mask = 0x1 }; - emith_jump_cond_patchable(DCOND_LE, tcache_ptr); + emith_jump_cond_patchable(DCOND_LT, tcache_ptr); } else { // blx table full, must inline exit code tmp = rcache_get_tmp_arg(0); emith_cmp_r_imm(sr, 0); EMITH_SJMP_START(DCOND_GT); - emith_move_r_imm_c(DCOND_LE, tmp, pc); + emith_move_r_imm_c(DCOND_LT, tmp, pc); emith_jump_cond(DCOND_LE, sh2_drc_exit); EMITH_SJMP_END(DCOND_GT); rcache_free_tmp(tmp); @@ -5676,7 +5676,7 @@ int sh2_execute_drc(SH2 *sh2c, int cycles) // bit11 contains T saved for delay slot // others are usual SH2 flags sh2c->sr &= 0x3f3; - sh2c->sr |= cycles << 12; + sh2c->sr |= (cycles-1) << 12; #if (DRC_DEBUG & 8) lastpc = lastcnt = 0; #endif @@ -5687,7 +5687,7 @@ int sh2_execute_drc(SH2 *sh2c, int cycles) // TODO: irq cycles ret_cycles = (int32_t)sh2c->sr >> 12; - if (ret_cycles > 0) + if (ret_cycles >= 0) dbg(1, "warning: drc returned with cycles: %d, pc %08x", ret_cycles, sh2c->pc); #if (DRC_DEBUG & 8) if (lastcnt) @@ -5696,7 +5696,7 @@ int sh2_execute_drc(SH2 *sh2c, int cycles) #endif sh2c->sr &= 0x3f3; - return ret_cycles; + return ret_cycles+1; } static void block_stats(void) @@ -6223,6 +6223,7 @@ u16 scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc_out, break; case 1: // SLEEP 0000000000011011 opd->op = OP_SLEEP; + opd->cycles = 3; end_block = 1; break; case 2: // RTE 0000000000101011 diff --git a/cpu/sh2/mame/sh2pico.c b/cpu/sh2/mame/sh2pico.c index 380ca24f..f4ae85cb 100644 --- a/cpu/sh2/mame/sh2pico.c +++ b/cpu/sh2/mame/sh2pico.c @@ -167,14 +167,16 @@ int sh2_execute_interpreter(SH2 *sh2, int cycles) sh2->icount--; - if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f)) + if (sh2->test_irq && !sh2->delay) { int level = sh2->pending_level; - int vector = sh2->irq_callback(sh2, level); - sh2_do_irq(sh2, level, vector); + if (level > ((sh2->sr >> 4) & 0x0f)) + { + int vector = sh2->irq_callback(sh2, level); + sh2_do_irq(sh2, level, vector); + } sh2->test_irq = 0; } - } while (sh2->icount > 0 || sh2->delay); /* can't interrupt before delay */ @@ -221,7 +223,7 @@ int sh2_execute_interpreter(SH2 *sh2, int cycles) || pc_expect != sh2->pc) // branched { pc_expect = sh2->pc; - if (sh2->icount < 0) + if (sh2->icount <= 0) break; } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 8cd1c198..4cf683c6 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -511,7 +511,7 @@ static void p32x_reg_write8(u32 a, u32 d) case 0x2d: case 0x2e: case 0x2f: - if (REG8IN16(r, a) != d) { + if (REG8IN16(r, a) != (u8)d) { unsigned int cycles = SekCyclesDone(); if (CYCLES_GT(cycles - msh2.m68krcycles_done, 64)) @@ -608,7 +608,7 @@ static void p32x_reg_write16(u32 a, u32 d) case 0x2a/2: case 0x2c/2: case 0x2e/2: - if (r[a / 2] != d) { + if (r[a / 2] != (u16)d) { unsigned int cycles = SekCyclesDone(); if (CYCLES_GT(cycles - msh2.m68krcycles_done, 64)) @@ -823,7 +823,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) return; case 0x05: // H count d &= 0xff; - if (Pico32x.sh2_regs[4 / 2] != d) { + if (Pico32x.sh2_regs[4 / 2] != (u8)d) { unsigned int cycles = sh2_cycles_done_m68k(sh2); Pico32x.sh2_regs[4 / 2] = d; p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles); @@ -848,7 +848,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) case 0x2d: case 0x2e: case 0x2f: - if (REG8IN16(r, a) != d) { + if (REG8IN16(r, a) != (u8)d) { unsigned int cycles = sh2_cycles_done_m68k(sh2); REG8IN16(r, a) = d; @@ -941,7 +941,7 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) case 0x2a/2: case 0x2c/2: case 0x2e/2: - if (Pico32x.regs[a / 2] != d) { + if (Pico32x.regs[a / 2] != (u16)d) { unsigned int cycles = sh2_cycles_done_m68k(sh2); Pico32x.regs[a / 2] = d; diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 602b6eb4..732a4299 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -342,7 +342,7 @@ void pcd_run_cpus_normal(int m68k_cycles) Pico_mcd->m.m68k_poll_cnt = 0; #ifdef USE_POLL_DETECT - if (Pico_mcd->m.m68k_poll_cnt >= 32) { + if (Pico_mcd->m.m68k_poll_cnt >= 16) { int s68k_left; // main CPU is polling, (wake and) run sub only if (SekIsStoppedS68k()) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index a47d6a37..05ee3e13 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -63,7 +63,7 @@ static void remap_prg_window(u32 r1, u32 r3); static void remap_word_ram(u32 r3); // poller detection -#define POLL_LIMIT 32 +#define POLL_LIMIT 16 #define POLL_CYCLES 64 void m68k_comm_check(u32 a) @@ -78,13 +78,15 @@ void m68k_comm_check(u32 a) Pico_mcd->m.need_sync = 1; } Pico_mcd->m.m68k_poll_clk = cycles; - if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a || clkdiff > POLL_CYCLES) { + if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a || clkdiff > POLL_CYCLES || clkdiff <= 16) { Pico_mcd->m.m68k_poll_a = a; Pico_mcd->m.m68k_poll_cnt = 0; SekNotPolling = 0; return; } Pico_mcd->m.m68k_poll_cnt++; + if(Pico_mcd->m.m68k_poll_cnt == POLL_LIMIT) + SekEndRun(0); } #ifndef _ASM_CD_MEMORY_C From 850f55d7296737eca6e1fb32bcd82e8a74f8868c Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 May 2021 22:18:20 +0200 Subject: [PATCH 06/22] Updated cyclone core --- cpu/cyclone | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cyclone b/cpu/cyclone index 94a9d9a8..1f03ed6a 160000 --- a/cpu/cyclone +++ b/cpu/cyclone @@ -1 +1 @@ -Subproject commit 94a9d9a888e72cbfa4db12113cd113cf5e154f7f +Subproject commit 1f03ed6a49252bfb900c4d3932094308e1c5b375 From 902b8e557ade9c25e7b61b3838b51400dc1cb632 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 May 2021 22:59:57 +0200 Subject: [PATCH 07/22] Changed resync vid and audio every 2 minutes and 30s --- 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 d74e997f..cda1e3a6 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1759,7 +1759,7 @@ void emu_loop(void) // second changed? if (timestamp_x3 - timestamp_fps_x3 >= ms_to_ticks(1000) * 3) { -#define FUNKEY_RESYNCHRONIZE_AUDIO_SECS (5*60) +#define FUNKEY_RESYNCHRONIZE_AUDIO_SECS (150) #ifdef FUNKEY_RESYNCHRONIZE_AUDIO_SECS static unsigned int last_resync = 0, cur_sec=0; if(cur_sec++ - last_resync >= FUNKEY_RESYNCHRONIZE_AUDIO_SECS){ From 5579b6a600da3f46dc48c4c1f08a11c92b687ddd Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 May 2021 23:15:09 +0200 Subject: [PATCH 08/22] Test --- 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 cda1e3a6..d74e997f 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1759,7 +1759,7 @@ void emu_loop(void) // second changed? if (timestamp_x3 - timestamp_fps_x3 >= ms_to_ticks(1000) * 3) { -#define FUNKEY_RESYNCHRONIZE_AUDIO_SECS (150) +#define FUNKEY_RESYNCHRONIZE_AUDIO_SECS (5*60) #ifdef FUNKEY_RESYNCHRONIZE_AUDIO_SECS static unsigned int last_resync = 0, cur_sec=0; if(cur_sec++ - last_resync >= FUNKEY_RESYNCHRONIZE_AUDIO_SECS){ From 0bd016f580bf0401fe2d849499a4ede97a7027b6 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 May 2021 23:16:39 +0200 Subject: [PATCH 09/22] Restored previous commit --- 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 d74e997f..cda1e3a6 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1759,7 +1759,7 @@ void emu_loop(void) // second changed? if (timestamp_x3 - timestamp_fps_x3 >= ms_to_ticks(1000) * 3) { -#define FUNKEY_RESYNCHRONIZE_AUDIO_SECS (5*60) +#define FUNKEY_RESYNCHRONIZE_AUDIO_SECS (150) #ifdef FUNKEY_RESYNCHRONIZE_AUDIO_SECS static unsigned int last_resync = 0, cur_sec=0; if(cur_sec++ - last_resync >= FUNKEY_RESYNCHRONIZE_AUDIO_SECS){ From e9b9b9d81fdfcfeec62fb0b20e72e94344c5bc95 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 21 May 2021 21:32:45 +0200 Subject: [PATCH 10/22] Restored initial audio volume --- pico/sound/mix_arm.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pico/sound/mix_arm.S b/pico/sound/mix_arm.S index 60438988..9cee2ac1 100644 --- a/pico/sound/mix_arm.S +++ b/pico/sound/mix_arm.S @@ -156,7 +156,7 @@ m16_32_s2_no_unal2: @ limit @ reg=int_sample, r12=1, r8=tmp, kills flags .macro Limit reg - sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping +@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping add r8, r12, \reg, asr #15 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1 movne \reg, #0x8000 @@ -166,7 +166,7 @@ m16_32_s2_no_unal2: @ limit and shift up by 16 @ reg=int_sample, r12=1, r8=tmp, kills flags .macro Limitsh reg - sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping +@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping add r8, r12,\reg, asr #15 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1 moveq \reg, \reg, lsl #16 From 45e3128e13f56f62479533fae9f5550f7848b3bb Mon Sep 17 00:00:00 2001 From: root Date: Sat, 22 May 2021 17:25:00 +0200 Subject: [PATCH 11/22] Deactivated Lowpass and DC filters to fix audio level issue --- pico/sound/mix_arm.S | 100 +++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/pico/sound/mix_arm.S b/pico/sound/mix_arm.S index 9cee2ac1..24523a17 100644 --- a/pico/sound/mix_arm.S +++ b/pico/sound/mix_arm.S @@ -177,21 +177,21 @@ m16_32_s2_no_unal2: @ filter out DC offset @ in=int_sample (max 20 bit), y=filter memory, r8=tmp -.macro DCfilt in y - rsb r8, \y, \in, lsl #12 @ fixpoint 20.12 - add \y, \y, r8, asr #12 @ alpha = 1-1/4094 - sub \in, \in, \y, asr #12 -.endm +@.macro DCfilt in y +@ rsb r8, \y, \in, lsl #12 @ fixpoint 20.12 +@ add \y, \y, r8, asr #12 @ alpha = 1-1/4094 +@ sub \in, \in, \y, asr #12 +@.endm @ lowpass filter @ in=int_sample (max 20 bit), y=filter memory, r12=alpha(Q8), r8=tmp -.macro LPfilt in y +@.macro LPfilt in y @ asr r8, \y, #8 @ rsb r8, r8, \in, lsl #4 @ fixpoint 20.12 - sub r8, \in, \y, asr #12 @ fixpoint 20.12 - mla \y, r8, r12, \y - asr \in, \y, #12 -.endm +@ sub r8, \in, \y, asr #12 @ fixpoint 20.12 +@ mla \y, r8, r12, \y +@ asr \in, \y, #12 +@.endm @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only @@ -220,14 +220,14 @@ m32_16l_st_loop: add r6, r6, r12,asr #16 add r7, r7, r12,asr #16 ldr r12,[sp] - LPfilt r4, r3 - LPfilt r5, lr - LPfilt r6, r3 - LPfilt r7, lr - DCfilt r4, r10 - DCfilt r5, r11 - DCfilt r6, r10 - DCfilt r7, r11 +@ LPfilt r4, r3 +@ LPfilt r5, lr +@ LPfilt r6, r3 +@ LPfilt r7, lr +@ DCfilt r4, r10 +@ DCfilt r5, r11 +@ DCfilt r6, r10 +@ DCfilt r7, r11 mov r12,#1 Limitsh r4 Limitsh r5 @@ -248,10 +248,10 @@ m32_16l_st_end: add r4, r4, r6 add r5, r5, r6 ldr r12,[sp] - LPfilt r4, r3 - LPfilt r5, lr - DCfilt r4, r10 - DCfilt r5, r11 +@ LPfilt r4, r3 +@ LPfilt r5, lr +@ DCfilt r4, r10 +@ DCfilt r5, r11 mov r12,#1 Limitsh r4 Limitsh r5 @@ -286,8 +286,8 @@ mix_32_to_16_mono: sub r2, r2, #1 add r4, r4, r5 ldr r12,[sp] - LPfilt r4, r11 - DCfilt r4, r10 +@ LPfilt r4, r11 +@ DCfilt r4, r10 mov r12,#1 Limit r4 strh r4, [r0], #2 @@ -306,14 +306,14 @@ m32_16_mo_loop: mov r12,r12,lsl #16 add r6, r6, r12,asr #16 ldr r12,[sp] - LPfilt r4, r11 - LPfilt r5, r11 - LPfilt r6, r11 - LPfilt r7, r11 - DCfilt r4, r10 - DCfilt r5, r10 - DCfilt r6, r10 - DCfilt r7, r10 +@ LPfilt r4, r11 +@ LPfilt r5, r11 +@ LPfilt r6, r11 +@ LPfilt r7, r11 +@ DCfilt r4, r10 +@ DCfilt r5, r10 +@ DCfilt r6, r10 +@ DCfilt r7, r10 mov r12,#1 Limitsh r4 Limitsh r5 @@ -335,10 +335,10 @@ m32_16_mo_end: mov r6, r6, lsl #16 add r4, r4, r6, asr #16 ldr r12,[sp] - LPfilt r4, r11 - LPfilt r5, r11 - DCfilt r4, r10 - DCfilt r5, r10 +@ LPfilt r4, r11 +@ LPfilt r5, r11 +@ DCfilt r4, r10 +@ DCfilt r5, r10 mov r12,#1 Limitsh r4 Limitsh r5 @@ -352,8 +352,8 @@ m32_16_mo_no_unal2: ldr r4, [r1], #4 add r4, r4, r5 ldr r12,[sp] - LPfilt r4, r11 - DCfilt r4, r10 +@ LPfilt r4, r11 +@ DCfilt r4, r10 mov r12,#1 Limit r4 strh r4, [r0], #2 @@ -411,14 +411,14 @@ m32_16l_st_l_loop: mov r6, r6, asr r9 mov r7, r7, asr r9 ldr r12,[sp] - LPfilt r4, r3 - LPfilt r5, lr - LPfilt r6, r3 - LPfilt r7, lr - DCfilt r4, r10 - DCfilt r5, r11 - DCfilt r6, r10 - DCfilt r7, r11 +@ LPfilt r4, r3 +@ LPfilt r5, lr +@ LPfilt r6, r3 +@ LPfilt r7, lr +@ DCfilt r4, r10 +@ DCfilt r5, r11 +@ DCfilt r6, r10 +@ DCfilt r7, r11 mov r12,#1 Limitsh r4 Limitsh r5 @@ -441,10 +441,10 @@ m32_16l_st_l_end: mov r4, r4, asr r9 mov r5, r5, asr r9 ldr r12,[sp] - LPfilt r4, r3 - LPfilt r5, lr - DCfilt r4, r10 - DCfilt r5, r11 +@ LPfilt r4, r3 +@ LPfilt r5, lr +@ DCfilt r4, r10 +@ DCfilt r5, r11 mov r12,#1 Limitsh r4 Limitsh r5 From 6704bddae6f318625fcb410cb8ee6e3bd02e57dc Mon Sep 17 00:00:00 2001 From: root Date: Sat, 22 May 2021 19:40:01 +0200 Subject: [PATCH 12/22] Restored sound filters as disabling them caused too many side effects with some 32X games --- pico/sound/mix_arm.S | 104 +++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/pico/sound/mix_arm.S b/pico/sound/mix_arm.S index 24523a17..60438988 100644 --- a/pico/sound/mix_arm.S +++ b/pico/sound/mix_arm.S @@ -156,7 +156,7 @@ m16_32_s2_no_unal2: @ limit @ reg=int_sample, r12=1, r8=tmp, kills flags .macro Limit reg -@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping + sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping add r8, r12, \reg, asr #15 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1 movne \reg, #0x8000 @@ -166,7 +166,7 @@ m16_32_s2_no_unal2: @ limit and shift up by 16 @ reg=int_sample, r12=1, r8=tmp, kills flags .macro Limitsh reg -@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping + sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping add r8, r12,\reg, asr #15 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1 moveq \reg, \reg, lsl #16 @@ -177,21 +177,21 @@ m16_32_s2_no_unal2: @ filter out DC offset @ in=int_sample (max 20 bit), y=filter memory, r8=tmp -@.macro DCfilt in y -@ rsb r8, \y, \in, lsl #12 @ fixpoint 20.12 -@ add \y, \y, r8, asr #12 @ alpha = 1-1/4094 -@ sub \in, \in, \y, asr #12 -@.endm +.macro DCfilt in y + rsb r8, \y, \in, lsl #12 @ fixpoint 20.12 + add \y, \y, r8, asr #12 @ alpha = 1-1/4094 + sub \in, \in, \y, asr #12 +.endm @ lowpass filter @ in=int_sample (max 20 bit), y=filter memory, r12=alpha(Q8), r8=tmp -@.macro LPfilt in y +.macro LPfilt in y @ asr r8, \y, #8 @ rsb r8, r8, \in, lsl #4 @ fixpoint 20.12 -@ sub r8, \in, \y, asr #12 @ fixpoint 20.12 -@ mla \y, r8, r12, \y -@ asr \in, \y, #12 -@.endm + sub r8, \in, \y, asr #12 @ fixpoint 20.12 + mla \y, r8, r12, \y + asr \in, \y, #12 +.endm @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only @@ -220,14 +220,14 @@ m32_16l_st_loop: add r6, r6, r12,asr #16 add r7, r7, r12,asr #16 ldr r12,[sp] -@ LPfilt r4, r3 -@ LPfilt r5, lr -@ LPfilt r6, r3 -@ LPfilt r7, lr -@ DCfilt r4, r10 -@ DCfilt r5, r11 -@ DCfilt r6, r10 -@ DCfilt r7, r11 + LPfilt r4, r3 + LPfilt r5, lr + LPfilt r6, r3 + LPfilt r7, lr + DCfilt r4, r10 + DCfilt r5, r11 + DCfilt r6, r10 + DCfilt r7, r11 mov r12,#1 Limitsh r4 Limitsh r5 @@ -248,10 +248,10 @@ m32_16l_st_end: add r4, r4, r6 add r5, r5, r6 ldr r12,[sp] -@ LPfilt r4, r3 -@ LPfilt r5, lr -@ DCfilt r4, r10 -@ DCfilt r5, r11 + LPfilt r4, r3 + LPfilt r5, lr + DCfilt r4, r10 + DCfilt r5, r11 mov r12,#1 Limitsh r4 Limitsh r5 @@ -286,8 +286,8 @@ mix_32_to_16_mono: sub r2, r2, #1 add r4, r4, r5 ldr r12,[sp] -@ LPfilt r4, r11 -@ DCfilt r4, r10 + LPfilt r4, r11 + DCfilt r4, r10 mov r12,#1 Limit r4 strh r4, [r0], #2 @@ -306,14 +306,14 @@ m32_16_mo_loop: mov r12,r12,lsl #16 add r6, r6, r12,asr #16 ldr r12,[sp] -@ LPfilt r4, r11 -@ LPfilt r5, r11 -@ LPfilt r6, r11 -@ LPfilt r7, r11 -@ DCfilt r4, r10 -@ DCfilt r5, r10 -@ DCfilt r6, r10 -@ DCfilt r7, r10 + LPfilt r4, r11 + LPfilt r5, r11 + LPfilt r6, r11 + LPfilt r7, r11 + DCfilt r4, r10 + DCfilt r5, r10 + DCfilt r6, r10 + DCfilt r7, r10 mov r12,#1 Limitsh r4 Limitsh r5 @@ -335,10 +335,10 @@ m32_16_mo_end: mov r6, r6, lsl #16 add r4, r4, r6, asr #16 ldr r12,[sp] -@ LPfilt r4, r11 -@ LPfilt r5, r11 -@ DCfilt r4, r10 -@ DCfilt r5, r10 + LPfilt r4, r11 + LPfilt r5, r11 + DCfilt r4, r10 + DCfilt r5, r10 mov r12,#1 Limitsh r4 Limitsh r5 @@ -352,8 +352,8 @@ m32_16_mo_no_unal2: ldr r4, [r1], #4 add r4, r4, r5 ldr r12,[sp] -@ LPfilt r4, r11 -@ DCfilt r4, r10 + LPfilt r4, r11 + DCfilt r4, r10 mov r12,#1 Limit r4 strh r4, [r0], #2 @@ -411,14 +411,14 @@ m32_16l_st_l_loop: mov r6, r6, asr r9 mov r7, r7, asr r9 ldr r12,[sp] -@ LPfilt r4, r3 -@ LPfilt r5, lr -@ LPfilt r6, r3 -@ LPfilt r7, lr -@ DCfilt r4, r10 -@ DCfilt r5, r11 -@ DCfilt r6, r10 -@ DCfilt r7, r11 + LPfilt r4, r3 + LPfilt r5, lr + LPfilt r6, r3 + LPfilt r7, lr + DCfilt r4, r10 + DCfilt r5, r11 + DCfilt r6, r10 + DCfilt r7, r11 mov r12,#1 Limitsh r4 Limitsh r5 @@ -441,10 +441,10 @@ m32_16l_st_l_end: mov r4, r4, asr r9 mov r5, r5, asr r9 ldr r12,[sp] -@ LPfilt r4, r3 -@ LPfilt r5, lr -@ DCfilt r4, r10 -@ DCfilt r5, r11 + LPfilt r4, r3 + LPfilt r5, lr + DCfilt r4, r10 + DCfilt r5, r11 mov r12,#1 Limitsh r4 Limitsh r5 From afad78074279a6b15a69a0052eb5a6731da923dc Mon Sep 17 00:00:00 2001 From: root Date: Sat, 22 May 2021 19:44:38 +0200 Subject: [PATCH 13/22] Deactivated sound volume reduction (25%) --- pico/sound/mix_arm.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pico/sound/mix_arm.S b/pico/sound/mix_arm.S index 60438988..9aa05b28 100644 --- a/pico/sound/mix_arm.S +++ b/pico/sound/mix_arm.S @@ -156,7 +156,7 @@ m16_32_s2_no_unal2: @ limit @ reg=int_sample, r12=1, r8=tmp, kills flags .macro Limit reg - sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping +@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl to avoid clipping add r8, r12, \reg, asr #15 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1 movne \reg, #0x8000 @@ -166,7 +166,7 @@ m16_32_s2_no_unal2: @ limit and shift up by 16 @ reg=int_sample, r12=1, r8=tmp, kills flags .macro Limitsh reg - sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping +@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl to avoid clipping add r8, r12,\reg, asr #15 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1 moveq \reg, \reg, lsl #16 From 6339f601d4317694c80eb4e7e11b2977c8b2156f Mon Sep 17 00:00:00 2001 From: root Date: Sun, 23 May 2021 03:25:37 +0200 Subject: [PATCH 14/22] Deactivated "Sound filter" by default to increase sound volume --- platform/common/emu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index cda1e3a6..dfbb38df 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -688,8 +688,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/*?*/; - defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER| - POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | + defaultConfig.s_PicoOpt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX | POPT_EN_DRC|POPT_ACC_SPRITES | POPT_EN_32X|POPT_EN_PWM; From ebc054b27821c97fb45cce64cb27c6f1a5f417cb Mon Sep 17 00:00:00 2001 From: root Date: Thu, 27 May 2021 22:11:51 +0200 Subject: [PATCH 15/22] Last irixxxx's optimizations --- cpu/fame/famec_opcodes.h | 1 + cpu/musashi/m68k_in.c | 2 +- cpu/musashi/m68kcpu.c | 10 +-- cpu/musashi/m68kcpu.h | 2 + cpu/musashi/m68kmake.c | 3 + pico/misc.c | 176 --------------------------------------- pico/pico.c | 1 + pico/pico_int.h | 7 +- pico/videoport.c | 141 +++++++++++++++++++++++++++---- 9 files changed, 141 insertions(+), 202 deletions(-) diff --git a/cpu/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index d43a563a..ffb7c4ed 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -19318,6 +19318,7 @@ OPCODE(0x4E73) AREG(7) = ASP; ASP = res; } + CHECK_BRANCH_EXCEPTION(res) POST_IO ctx->execinfo &= ~(FM68K_EMULATE_GROUP_0|FM68K_EMULATE_TRACE|FM68K_DO_TRACE); CHECK_INT_TO_JUMP(20) diff --git a/cpu/musashi/m68k_in.c b/cpu/musashi/m68k_in.c index d1756a53..14c1347d 100644 --- a/cpu/musashi/m68k_in.c +++ b/cpu/musashi/m68k_in.c @@ -389,7 +389,7 @@ addi 32 . . 0000011010...... A+-DXWL... U U U U 20 20 4 4 addq 8 . d 0101...000000... .......... U U U U 4 4 2 2 addq 8 . . 0101...000...... A+-DXWL... U U U U 8 8 4 4 addq 16 . d 0101...001000... .......... U U U U 4 4 2 2 -addq 16 . a 0101...001001... .......... U U U U 4 4 2 2 +addq 16 . a 0101...001001... .......... U U U U 8 8 2 2 addq 16 . . 0101...001...... A+-DXWL... U U U U 8 8 4 4 addq 32 . d 0101...010000... .......... U U U U 8 8 2 2 addq 32 . a 0101...010001... .......... U U U U 8 8 2 2 diff --git a/cpu/musashi/m68kcpu.c b/cpu/musashi/m68kcpu.c index 38469f32..d729f2cf 100644 --- a/cpu/musashi/m68kcpu.c +++ b/cpu/musashi/m68kcpu.c @@ -43,7 +43,7 @@ extern void m68040_fpu_op1(void); /* ================================= DATA ================================= */ /* ======================================================================== */ -int m68ki_initial_cycles; +//int m68ki_initial_cycles; //int m68ki_remaining_cycles = 0; /* Number of clocks remaining */ uint m68ki_tracing = 0; uint m68ki_address_space; @@ -828,6 +828,10 @@ int m68k_execute(int num_cycles) m68ki_instruction_jump_table[REG_IR](); USE_CYCLES(CYC_INSTRUCTION[REG_IR]); // moving this up may cause a deadlock + /* ASG: update cycles */ + USE_CYCLES(CPU_INT_CYCLES); + CPU_INT_CYCLES = 0; + /* Trace m68k_exception, if necessary */ m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ @@ -839,10 +843,6 @@ int m68k_execute(int num_cycles) /* set previous PC to current PC for the next entry into the loop */ REG_PPC = REG_PC; - /* ASG: update cycles */ - USE_CYCLES(CPU_INT_CYCLES); - CPU_INT_CYCLES = 0; - /* return how many clocks we used */ return m68ki_initial_cycles - GET_CYCLES(); } diff --git a/cpu/musashi/m68kcpu.h b/cpu/musashi/m68kcpu.h index 5eee2b21..6ab0ba0b 100644 --- a/cpu/musashi/m68kcpu.h +++ b/cpu/musashi/m68kcpu.h @@ -916,6 +916,7 @@ typedef struct void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */ // notaz + sint cyc_initial_cycles; sint cyc_remaining_cycles; sint not_polling; } m68ki_cpu_core; @@ -923,6 +924,7 @@ typedef struct // notaz extern m68ki_cpu_core *m68ki_cpu_p; #define m68ki_cpu (*m68ki_cpu_p) +#define m68ki_initial_cycles m68ki_cpu_p->cyc_initial_cycles #define m68ki_remaining_cycles m68ki_cpu_p->cyc_remaining_cycles diff --git a/cpu/musashi/m68kmake.c b/cpu/musashi/m68kmake.c index a544a5c2..6dd57fca 100644 --- a/cpu/musashi/m68kmake.c +++ b/cpu/musashi/m68kmake.c @@ -641,6 +641,9 @@ int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type) strcmp(op->name, "suba") == 0)) return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2; + if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && op->size == 8 && strcmp(op->name, "btst") == 0) + return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2; + if(strcmp(op->name, "jmp") == 0) return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode]; if(strcmp(op->name, "jsr") == 0) diff --git a/pico/misc.c b/pico/misc.c index edf82b3a..9065476b 100644 --- a/pico/misc.c +++ b/pico/misc.c @@ -1,7 +1,6 @@ /* * rarely used EEPROM code * (C) notaz, 2006-2008 - * (C) kub, 2020 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -9,181 +8,6 @@ #include "pico_int.h" -// H-counter table for hvcounter reads in 40col mode, starting at HINT -const unsigned char hcounts_40[] = { -0xa5,0xa6,0xa7,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xae,0xaf,0xb0,0xb1,0xb2, -0xb3,0xb4,0xb5,0xb5,0xe4,0xe5,0xe6,0xe7,0xe8,0xe8,0xe9,0xea,0xea,0xeb,0xec,0xed, -0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3,0xf4,0xf4,0xf5,0xf6,0xf7,0xf7,0xf8, -0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0x00,0x01,0x02,0x03,0x04,0x04,0x05,0x06, -0x07,0x08,0x09,0x0a,0x0b,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x12,0x13,0x14, -0x15,0x16,0x17,0x18,0x19,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x20,0x21,0x22, -0x23,0x24,0x25,0x26,0x27,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2e,0x2f,0x30, -0x31,0x32,0x33,0x34,0x35,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3c,0x3d,0x3e, -0x3f,0x40,0x41,0x42,0x43,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4a,0x4b,0x4c, -0x4d,0x4e,0x4f,0x50,0x51,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x58,0x59,0x5a, -0x5b,0x5c,0x5d,0x5e,0x5f,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x66,0x67,0x68, -0x69,0x6a,0x6b,0x6c,0x6d,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x74,0x75,0x76, -0x77,0x78,0x79,0x7a,0x7b,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0x82,0x83,0x84, -0x85,0x86,0x87,0x88,0x89,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x90,0x91,0x92, -0x93,0x94,0x95,0x96,0x97,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9e,0x9f,0xa0, -0xa1,0xa2,0xa3,0xa4,0xa5,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xac,0xad,0xae, -}; - -// H-counter table for hvcounter reads in 32col mode, starting at HINT -const unsigned char hcounts_32[] = { -0x85,0x86,0x86,0x87,0x88,0x88,0x89,0x8a,0x8a,0x8b,0x8c,0x8d,0x8d,0x8e,0x8f,0x8f, -0x90,0x91,0x91,0x92,0x93,0xe9,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xed,0xee,0xef,0xf0, -0xf0,0xf1,0xf2,0xf2,0xf3,0xf4,0xf4,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xf9,0xfa,0xfb, -0xfb,0xfc,0xfd,0xfe,0xfe,0xff,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x05,0x06, -0x07,0x07,0x08,0x09,0x09,0x0a,0x0b,0x0c,0x0c,0x0d,0x0e,0x0e,0x0f,0x10,0x10,0x11, -0x12,0x13,0x13,0x14,0x15,0x15,0x16,0x17,0x17,0x18,0x19,0x1a,0x1a,0x1b,0x1c,0x1c, -0x1d,0x1e,0x1e,0x1f,0x20,0x21,0x21,0x22,0x23,0x23,0x24,0x25,0x25,0x26,0x27,0x28, -0x28,0x29,0x2a,0x2a,0x2b,0x2c,0x2c,0x2d,0x2e,0x2f,0x2f,0x30,0x31,0x31,0x32,0x33, -0x33,0x34,0x35,0x36,0x36,0x37,0x38,0x38,0x39,0x3a,0x3a,0x3b,0x3c,0x3d,0x3d,0x3e, -0x3f,0x3f,0x40,0x41,0x41,0x42,0x43,0x44,0x44,0x45,0x46,0x46,0x47,0x48,0x48,0x49, -0x4a,0x4b,0x4b,0x4c,0x4d,0x4d,0x4e,0x4f,0x4f,0x50,0x51,0x52,0x52,0x53,0x54,0x54, -0x55,0x56,0x56,0x57,0x58,0x59,0x59,0x5a,0x5b,0x5b,0x5c,0x5d,0x5d,0x5e,0x5f,0x60, -0x60,0x61,0x62,0x62,0x63,0x64,0x64,0x65,0x66,0x67,0x67,0x68,0x69,0x69,0x6a,0x6b, -0x6b,0x6c,0x6d,0x6e,0x6e,0x6f,0x70,0x70,0x71,0x72,0x72,0x73,0x74,0x75,0x75,0x76, -0x77,0x77,0x78,0x79,0x79,0x7a,0x7b,0x7c,0x7c,0x7d,0x7e,0x7e,0x7f,0x80,0x80,0x81, -0x82,0x83,0x83,0x84,0x85,0x85,0x86,0x87,0x87,0x88,0x89,0x8a,0x8a,0x8b,0x8c,0x8c, -}; - -// VDP transfer slots for blanked and active display in 32col and 40col mode. -// 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40 -// In blanked display, all slots but 5(h32) / 6(h40) are usable for transfers, -// in active display only 16(h32) / 18(h40) slots can be used. - -// NB the cyc2sl tables should cover 2 slot into the next scanline, in case the -// last insn in the old scanline is a 32 bit VDP access. That is currently not -// the case for active display. - -// XXX inactive tables by slot#=cycles*maxslot#/488. should be through hv tables -// VDP transfer slots in inactive (blanked) display 32col mode. -// refresh slots: 250, 26, 58, 90, 122 -> 32, 64, 96, 128, 160 -const unsigned char vdpcyc2sl_32_bl[] = { // 68k cycles/2 to slot # -// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 - 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, - 10, 11, 12, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21, - 21, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, - 32, 33, 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 42, - 43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 51, 51, 52, 53, 53, - 54, 55, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 63, 63, 64, - 65, 65, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 75, - 76, 76, 77, 78, 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 85, 86, - 87, 87, 88, 89, 89, 90, 91, 91, 92, 93, 93, 94, 95, 95, 96, 97, - 97, 98, 99,100,100,101,102,102,103,104,104,105,106,106,107,108, - 108,109,110,110,111,112,112,113,114,114,115,116,117,117,118,119, - 119,120,121,121,122,123,123,124,125,125,126,127,127,128,129,129, - 130,131,131,132,133,134,134,135,136,136,137,138,138,139,140,140, - 141,142,142,143,144,144,145,146,146,147,148,148,149,150,151,151, - 152,153,153,154,155,155,156,157,157,158,159,159,160,161,161,162, - 163,163,164,165,166,166,167,168,168,169,170,170,171,172,172,173, -}; -// VDP transfer slots in inactive (blanked) display 40col mode. -// refresh slots: 250, 26, 58, 90, 122, 154 -> 40, 72, 104, 136, 168, 200 -const unsigned char vdpcyc2sl_40_bl[] = { // 68k cycles/2 to slot # -// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 - 0, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12, - 13, 14, 15, 15, 16, 17, 18, 19, 20, 20, 21, 22, 23, 24, 25, 25, - 26, 27, 28, 29, 30, 30, 31, 32, 33, 34, 35, 35, 36, 37, 38, 39, - 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 51, 52, - 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 66, - 66, 67, 68, 69, 70, 71, 71, 72, 73, 74, 75, 76, 76, 77, 78, 79, - 80, 81, 81, 82, 83, 84, 85, 86, 86, 87, 88, 89, 90, 91, 91, 92, - 93, 94, 95, 96, 96, 97, 98, 99,100,101,102,102,103,104,105,106, - 107,107,108,109,110,111,112,112,113,114,115,116,117,117,118,119, - 120,121,122,122,123,124,125,126,127,127,128,129,130,131,132,132, - 133,134,135,136,137,137,138,139,140,141,142,142,143,144,145,146, - 147,147,148,149,150,151,152,153,153,154,155,156,157,158,158,159, - 160,161,162,163,163,164,165,166,167,168,168,169,170,171,172,173, - 173,174,175,176,177,178,178,179,180,181,182,183,183,184,185,186, - 187,188,188,189,190,191,192,193,193,194,195,196,197,198,198,199, - 200,201,202,203,204,204,205,206,207,208,209,209,210,211,212,213, -}; -// VDP transfer slots in active display 32col mode. Transfer slots (Hint=0): -// 11,25,40,48,56,72,80,88,104,112,120,136,144,152,167,168 -const unsigned char vdpcyc2sl_32[] = { // 68k cycles/2 to slot # -// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, -}; -// VDP transfer slots in active display 40col mode. Transfer slots (Hint=0): -// 21,47,55,63,79,87,95,111,119,127,143,151,159,175,183,191,206,207 -const unsigned char vdpcyc2sl_40[] = { // 68k cycles/2 to slot # -// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 96 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, // 128 - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, // 160 - 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, // 192 - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 224 - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, // 256 - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // 288 - 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, // 320 - 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, // 352 - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, // 384 - 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, // 416 - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, // 448 - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, // 480 -}; - -// NB the sl2cyc tables must cover all slots present in the cyc2sl tables. - -// XXX inactive tables by cyc=slot#*488/maxslot#. should be through hv tables -const unsigned short vdpsl2cyc_32_bl[] = { // slot # to 68k cycles/2 - 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23, - 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, 46, - 48, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, - 71, 73, 74, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 93, - 95, 96, 98, 99,100,102,103,105,106,108,109,111,112,114,115,117, - 118,120,121,122,124,125,127,128,130,131,133,134,136,137,139,140, - 142,143,145,146,147,149,150,152,153,155,156,158,159,161,162,164, - 165,167,168,170,171,172,174,175,177,178,180,181,183,184,186,187, - 189,190,192,193,195,196,197,199,200,202,203,205,206,208,209,211, - 212,214,215,217,218,220,221,222,224,225,227,228,230,231,233,234, - 236,237,239,240,242,243,244,246,247,249,250,252,253,255,256 -}; -const unsigned short vdpsl2cyc_40_bl[] = { // slot # to 68k cycles/2 - 0, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, - 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 38, - 39, 40, 41, 42, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 56, 57, - 58, 59, 60, 61, 63, 64, 65, 66, 67, 69, 70, 71, 72, 73, 75, 76, - 77, 78, 79, 81, 82, 83, 84, 85, 87, 88, 89, 90, 91, 93, 94, 95, - 96, 97, 99,100,101,102,103,105,106,107,108,109,111,112,113,114, - 115,117,118,119,120,121,122,124,125,126,127,128,130,131,132,133, - 134,136,137,138,139,140,142,143,144,145,146,148,149,150,151,152, - 154,155,156,157,158,160,161,162,163,164,166,167,168,169,170,172, - 173,174,175,176,178,179,180,181,182,183,185,186,187,188,189,191, - 192,193,194,195,197,198,199,200,201,203,204,205,206,207,209,210, - 211,212,213,215,216,217,218,219,221,222,223,224,225,227,228,229, - 230,231,233,234,235,236,237,239,240,241,242,243,244,246,247,248, - 249,250,252,253,254,255,257 -}; -const unsigned short vdpsl2cyc_32[] = { // slot # to 68k cycles/2 - 0, 16, 36, 56, 67, 79,102,113,125,148,159,171,194,205,217,239, - 240,260,280 -}; -const unsigned short vdpsl2cyc_40[] = { // slot # to 68k cycles/2 - 0, 24, 55, 64, 73, 92,101,110,129,138,147,166,175,184,203,212, - 221,239,240,268,299 -}; #ifndef _ASM_MISC_C PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count) diff --git a/pico/pico.c b/pico/pico.c index 577701ba..b5ac2641 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -40,6 +40,7 @@ void PicoInit(void) Pico32xInit(); PsndInit(); + PicoVideoInit(); PicoDrawInit(); PicoDraw2Init(); } diff --git a/pico/pico_int.h b/pico/pico_int.h index 6a393fbf..18e33418 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -102,16 +102,16 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #define SekSr m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR) #define SekSrS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_SR) #define SekSetStop(x) { \ - if(x) { SET_CYCLES(0); PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \ + if(x) { PicoCpuMM68k.cyc_remaining_cycles = 0; PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \ else PicoCpuMM68k.stopped=0; \ } #define SekSetStopS68k(x) { \ - if(x) { SET_CYCLES(0); PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \ + if(x) { PicoCpuMS68k.cyc_remaining_cycles = 0; PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \ else PicoCpuMS68k.stopped=0; \ } #define SekIsStoppedM68k() (PicoCpuMM68k.stopped==STOP_LEVEL_STOP) #define SekIsStoppedS68k() (PicoCpuMS68k.stopped==STOP_LEVEL_STOP) -#define SekShouldInterrupt() (CPU_INT_LEVEL > FLAG_INT_MASK) +#define SekShouldInterrupt() (PicoCpuMM68k.int_level > PicoCpuMM68k.int_mask) #define SekNotPolling PicoCpuMM68k.not_polling #define SekNotPollingS68k PicoCpuMS68k.not_polling @@ -878,6 +878,7 @@ void PicoVideoFIFOSync(int cycles); int PicoVideoFIFOHint(void); void PicoVideoFIFOMode(int active, int h40); int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags); +void PicoVideoInit(void); void PicoVideoSave(void); void PicoVideoLoad(void); void PicoVideoCacheSAT(void); diff --git a/pico/videoport.c b/pico/videoport.c index 33548cb8..cadf956f 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -2,7 +2,7 @@ * PicoDrive * (c) Copyright Dave, 2004 * (C) notaz, 2006-2009 - * (C) kub, 2020 + * (C) kub, 2020,2021 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -12,11 +12,118 @@ #define NEED_DMA_SOURCE #include "memory.h" -extern const unsigned char hcounts_32[], hcounts_40[]; -extern const unsigned char vdpcyc2sl_32_bl[], vdpcyc2sl_40_bl[]; -extern const unsigned char vdpcyc2sl_32[], vdpcyc2sl_40[]; -extern const unsigned short vdpsl2cyc_32_bl[], vdpsl2cyc_40_bl[]; -extern const unsigned short vdpsl2cyc_32[], vdpsl2cyc_40[]; + +enum { clkdiv = 2 }; // CPU clock granularity: one of 1,2,4,8 + +// VDP Slot timing, taken from http://gendev.spritesmind.net/ +// forum/viewtopic.php?f=22&t=851&sid=d5701a71396ee7f700c74fb7cd85cb09 +// Thank you very much for the great work, Nemesis! + +// 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40. + +// VDP has a slot counter running from 0x00 to 0xff every scanline, but it has +// a gap depending on the video mode. The slot in which a horizontal interrupt +// is generated also depends on the video mode. +enum { hint32 = 0x84, gapstart32 = 0x94, gapend32 = 0xe9 }; +enum { hint40 = 0xa4, gapstart40 = 0xb7, gapend40 = 0xe5 }; + +// number of slots in a scanline +#define slots32 (0x100-(gapend32-gapstart32)) // 171 +#define slots40 (0x100-(gapend40-gapstart40)) // 210 + +// In blanked display, all slots but the refresh slots are usable for transfers, +// in active display only 16(h32) / 18(h40) slots can be used. + +// dma and refresh slots for active display, 16 for H32 +static u8 dmaslots32[] = + { 145,243, 2,10,18, 34,42,50, 66,74,82, 98,106,114, 129,130 }; +static u8 refslots32[] = + { 250, 26, 58, 90, 122 }; +// dma and refresh slots for active display, 18 for H40 +static u8 dmaslots40[] = + { 232, 2,10,18, 34,42,50, 66,74,82, 98,106,114, 130,138,146, 161,162 }; +static u8 refslots40[] = + { 250, 26, 58, 90, 122, 154 }; + +// table sizes +enum { cycsz = 488/clkdiv }; +enum { sl32blsz=slots32-sizeof(refslots32)+1, sl32acsz=sizeof(dmaslots32)+1 }; +enum { sl40blsz=slots40-sizeof(refslots40)+1, sl40acsz=sizeof(dmaslots40)+1 }; + +// Tables must be considerably larger than one scanline, since 68k emulation +// isn't stopping in the middle of an operation. If the last op is a 32 bit +// VDP write 2 slots may need to be taken from the next scanline, which can be +// more than 100 CPU cycles. For safety just cover 2 scanlines. + +// table for mapping hvcounter reads +static u8 hcounts_32[2*cycsz], hcounts_40[2*cycsz]; +// tables mapping cycles to slots +static u16 vdpcyc2sl_32_bl[2*cycsz],vdpcyc2sl_40_bl[2*cycsz]; +static u16 vdpcyc2sl_32_ac[2*cycsz],vdpcyc2sl_40_ac[2*cycsz]; +// tables mapping slots to cycles +// NB the sl2cyc tables must cover all slots present in the cyc2sl tables. +static u16 vdpsl2cyc_32_bl[2*sl32blsz],vdpsl2cyc_40_bl[2*sl40blsz]; +static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz]; + + +// calculate timing tables for one mode (H32 or H40) +// NB tables aligned to HINT, since the main loop uses HINT as synchronization +#define INITTABLES(s) { \ + float factor = 488./slots##s; \ + int ax, bx, rx, ac, bc; \ + int i, n; \ + \ + /* calculate internal VDP slot numbers */ \ + for (i = 0; i < cycsz; i++) { \ + n = hint##s + i*clkdiv/factor; \ + if (n >= gapstart##s) n += gapend##s-gapstart##s; \ + hcounts_##s[i] = n % 256; \ + } \ + memcpy(hcounts_##s+cycsz, hcounts_##s, ARRAY_SIZE(hcounts_##s)-cycsz);\ + \ + ax = bx = ac = bc = rx = 0; \ + for (i = 0; i < cycsz; i++) { \ + n = hcounts_##s[i]; \ + if (i == 0 || n != hcounts_##s[i-1]) { \ + /* fill slt <=> cycle tables, active scanline */ \ + if (ax < ARRAY_SIZE(dmaslots##s) && dmaslots##s[ax] == n) { \ + vdpsl2cyc_##s##_ac[++ax]=i; \ + while (ac < i) vdpcyc2sl_##s##_ac[ac++] = ax-1; \ + } \ + /* fill slt <=> cycle tables, scanline off */ \ + if (rx >= ARRAY_SIZE(refslots##s) || refslots##s[rx] != n) { \ + vdpsl2cyc_##s##_bl[++bx]=i; \ + while (bc < i) vdpcyc2sl_##s##_bl[bc++] = bx-1; \ + } else \ + ++rx; \ + } \ + } \ + /* fill up cycle to slot mappings for last slot */ \ + while (ac < cycsz) \ + vdpcyc2sl_##s##_ac[ac] = ARRAY_SIZE(dmaslots##s), ac++; \ + while (bc < cycsz) \ + vdpcyc2sl_##s##_bl[bc] = slots##s-ARRAY_SIZE(refslots##s), bc++; \ + /* extend tables for 2nd scanline */ \ + i = ARRAY_SIZE(dmaslots##s); \ + while (ac < ARRAY_SIZE(vdpcyc2sl_##s##_ac)) \ + vdpcyc2sl_##s##_ac[ac] = vdpcyc2sl_##s##_ac[ac-cycsz]+i, ac++; \ + while (ax < ARRAY_SIZE(vdpsl2cyc_##s##_ac)-1) ax++, \ + vdpsl2cyc_##s##_ac[ax] = vdpsl2cyc_##s##_ac[ax-i]+cycsz;\ + i = slots##s - ARRAY_SIZE(refslots##s); \ + while (bc < ARRAY_SIZE(vdpcyc2sl_##s##_bl)) \ + vdpcyc2sl_##s##_bl[bc] = vdpcyc2sl_##s##_bl[bc-cycsz]+i, bc++; \ + while (bx < ARRAY_SIZE(vdpsl2cyc_##s##_bl)-1) bx++, \ + vdpsl2cyc_##s##_bl[bx] = vdpsl2cyc_##s##_bl[bx-i]+cycsz; \ +} + + +// initialize VDP timing tables +void PicoVideoInit(void) +{ + INITTABLES(32); + INITTABLES(40); +} + static int blankline; // display disabled for this line @@ -69,16 +176,17 @@ static struct VdpFIFO { // XXX this must go into save file! unsigned short fifo_slot; // last executed slot in current scanline unsigned short fifo_maxslot;// #slots in scanline - const unsigned char *fifo_cyc2sl; + const unsigned short *fifo_cyc2sl; const unsigned short *fifo_sl2cyc; } VdpFIFO; enum { FQ_BYTE = 1, FQ_BGDMA = 2, FQ_FGDMA = 4 }; // queue flags, NB: BYTE = 1! -// NB must limit cyc2sl to table size in case 68k overdraws its aim. That can -// happen if the last insn is a blocking acess to VDP, or for exceptions (e.g.irq) -#define Cyc2Sl(vf,lc) ((lc) < 256*2 ? vf->fifo_cyc2sl[(lc)>>1] : vf->fifo_cyc2sl[255]) -#define Sl2Cyc(vf,sl) (vf->fifo_sl2cyc[sl]*2) + +// NB should limit cyc2sl to table size in case 68k overdraws its aim. That can +// happen if the last op is a blocking acess to VDP, or for exceptions (e.g.irq) +#define Cyc2Sl(vf,lc) (vf->fifo_cyc2sl[(lc)/clkdiv]) +#define Sl2Cyc(vf,sl) (vf->fifo_sl2cyc[sl]*clkdiv) // do the FIFO math static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, int slots) @@ -263,7 +371,7 @@ int PicoVideoFIFOWrite(int count, int flags, unsigned sr_mask,unsigned sr_flags) // update FIFO state if it was empty if (!(pv->status & PVS_FIFORUN)) { - vf->fifo_slot = Cyc2Sl(vf, lc+9); // FIFO latency ~3 vdp slots + vf->fifo_slot = Cyc2Sl(vf, lc+5); // FIFO latency ~3 vdp slots pv->status |= PVS_FIFORUN; pv->fifo_cnt = count << (flags & FQ_BYTE); } @@ -300,10 +408,10 @@ int PicoVideoFIFOHint(void) // switch FIFO mode between active/inactive display void PicoVideoFIFOMode(int active, int h40) { - static const unsigned char *vdpcyc2sl[2][2] = - { {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl} , {vdpcyc2sl_32, vdpcyc2sl_40} }; + static const unsigned short *vdpcyc2sl[2][2] = + { {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl},{vdpcyc2sl_32_ac, vdpcyc2sl_40_ac} }; static const unsigned short *vdpsl2cyc[2][2] = - { {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl} , {vdpsl2cyc_32, vdpsl2cyc_40} }; + { {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl},{vdpsl2cyc_32_ac, vdpsl2cyc_40_ac} }; struct VdpFIFO *vf = &VdpFIFO; struct PicoVideo *pv = &Pico.video; @@ -316,11 +424,10 @@ void PicoVideoFIFOMode(int active, int h40) vf->fifo_cyc2sl = vdpcyc2sl[active][h40]; vf->fifo_sl2cyc = vdpsl2cyc[active][h40]; // recalculate FIFO slot for new mode - vf->fifo_slot = Cyc2Sl(vf, lc)-1; + vf->fifo_slot = Cyc2Sl(vf, lc); vf->fifo_maxslot = Cyc2Sl(vf, 488); } - // VDP memory rd/wr static __inline void AutoIncrement(void) From 4f993d5ffe5baefddc5cdd2aeca6c2484837bd37 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 30 May 2021 14:47:07 +0200 Subject: [PATCH 16/22] Activated YM2413 emulation for SMS by default --- platform/common/emu.c | 6 +++--- platform/common/minimp3 | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index dfbb38df..86a01324 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -687,8 +687,8 @@ 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/*?*/; - defaultConfig.s_PicoOpt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | + EOPT_GZIP_SAVES | 0x10/*?*/; + defaultConfig.s_PicoOpt = 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 | POPT_EN_DRC|POPT_ACC_SPRITES | POPT_EN_32X|POPT_EN_PWM; @@ -1687,7 +1687,7 @@ static void emu_loop_prep(void) void emu_loop(void) { int frames_done, frames_shown; /* actual frames for fps counter */ - int frame_nb = 0; + int frame_nb = 0; int target_frametime_x3; unsigned int timestamp_x3 = 0; unsigned int timestamp_aim_x3 = 0; diff --git a/platform/common/minimp3 b/platform/common/minimp3 index ef9e212f..b18d274b 160000 --- a/platform/common/minimp3 +++ b/platform/common/minimp3 @@ -1 +1 @@ -Subproject commit ef9e212fa29bb72d23558da21bb5694fd2d01768 +Subproject commit b18d274b998cd4406070ddc1f370f53392241af0 From a16b0ab9396eabf649688545d1c3ac724e8e5287 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 4 Jun 2021 18:47:21 +0200 Subject: [PATCH 17/22] Last updates from irixxxx + submodule update --- .gitmodules | 2 +- pico/cd/libchdr | 2 +- pico/cd/pcm.c | 10 +++++----- platform/common/emu.c | 2 +- platform/common/menu_pico.c | 7 ++++--- platform/common/menu_pico.h | 4 ++-- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.gitmodules b/.gitmodules index 339a0944..026e51cb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,7 +9,7 @@ url = https://github.com/digital-sound-antiques/emu2413.git [submodule "pico/cd/libchdr"] path = pico/cd/libchdr - url = https://github.com/irixxxx/libchdr-picodrive.git + url = https://github.com/rtissera/libchdr.git [submodule "platform/common/minimp3"] path = platform/common/minimp3 url = https://github.com/lieff/minimp3 diff --git a/pico/cd/libchdr b/pico/cd/libchdr index ff3175dd..00319cf3 160000 --- a/pico/cd/libchdr +++ b/pico/cd/libchdr @@ -1 +1 @@ -Subproject commit ff3175ddb040b1a967c665a28868b16bf5aa97dd +Subproject commit 00319cf31f034e4d468a49a60265c7c5b8305b70 diff --git a/pico/cd/pcm.c b/pico/cd/pcm.c index b77196a4..795ec3b7 100644 --- a/pico/cd/pcm.c +++ b/pico/cd/pcm.c @@ -89,10 +89,10 @@ void pcd_pcm_sync(unsigned int to) addr = ch->addr; inc = ch->regs[2] + (ch->regs[3]<<8); - mul_l = ((int)ch->regs[0] * (ch->regs[1] & 0xf)) >> (5+1); - mul_r = ((int)ch->regs[0] * (ch->regs[1] >> 4)) >> (5+1); + mul_l = (int)ch->regs[0] * (ch->regs[1] & 0xf); + mul_r = (int)ch->regs[0] * (ch->regs[1] >> 4); - for (s = 0; s < steps; s++, addr = (addr + inc) & 0x7FFFFFF) + for (s = 0; s < steps; s++, addr = (addr + inc) & 0x07FFFFFF) { smp = Pico_mcd->pcm_ram[addr >> PCM_STEP_SHIFT]; @@ -109,8 +109,8 @@ void pcd_pcm_sync(unsigned int to) if (smp & 0x80) smp = -(smp & 0x7f); - out[s*2 ] += smp * mul_l; // max 128 * 119 = 15232 - out[s*2+1] += smp * mul_r; + out[s*2 ] += (smp * mul_l) >> 5; // max 127 * 255 * 15 / 32 = 15180 + out[s*2+1] += (smp * mul_r) >> 5; } ch->addr = addr; } diff --git a/platform/common/emu.c b/platform/common/emu.c index 86a01324..35d662ed 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1533,7 +1533,7 @@ void quick_save_and_poweroff() printf("Save Instant Play file\n"); /* Send command to cancel any previously scheduled powerdown */ - fp = popen(SHELL_CMD_CANCEL_SCHED_POWERDOWN, "r"); + fp = popen(SHELL_CMD_POWERDOWN_HANDLE, "r"); if (fp == NULL) { /* Countdown is still ticking, so better do nothing diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 7d89f67d..6a63fed0 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -84,7 +84,8 @@ static const char *men_dummy[] = { NULL }; #elif defined(PANDORA) #include #else -#include +#define MENU_OPTIONS_GFX +#define MENU_OPTIONS_ADV #endif @@ -1020,8 +1021,8 @@ void run_menu_loop() if(menu_confirmation){ MENU_DEBUG_PRINTF("Powerdown - confirmed\n"); /// ----- Shell cmd ---- - execlp(SHELL_CMD_SHUTDOWN_FUNKEY, SHELL_CMD_SHUTDOWN_FUNKEY, NULL); - MENU_ERROR_PRINTF("Failed to run command %s\n", SHELL_CMD_SHUTDOWN_FUNKEY); + execlp(SHELL_CMD_POWERDOWN, SHELL_CMD_POWERDOWN, NULL); + MENU_ERROR_PRINTF("Failed to run command %s\n", SHELL_CMD_POWERDOWN); exit(0); } else{ diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index a86abe12..9883e74c 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -40,9 +40,9 @@ typedef enum {RESUME_OPTIONS} ENUM_RESUME_OPTIONS; #define SHELL_CMD_NOTIF_CLEAR "notif clear" #define SHELL_CMD_AUDIO_AMP_ON "audio_amp on" #define SHELL_CMD_AUDIO_AMP_OFF "audio_amp off" -#define SHELL_CMD_CANCEL_SCHED_POWERDOWN "cancel_sched_powerdown" +#define SHELL_CMD_POWERDOWN "powerdown" +#define SHELL_CMD_POWERDOWN_HANDLE "powerdown handle" #define SHELL_CMD_INSTANT_PLAY "instant_play" -#define SHELL_CMD_SHUTDOWN_FUNKEY "shutdown_funkey" #define SHELL_CMD_KEYMAP_DEFAULT "keymap default" #define SHELL_CMD_KEYMAP_RESUME "keymap resume" From 50046026c6dec8dd7e2ecf78d2f179098c130ed6 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 7 Jun 2021 20:10:31 +0200 Subject: [PATCH 18/22] sh2 drc, fix bugs in code block management --- cpu/sh2/compiler.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 1ddcb19a..ba7e740d 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -763,6 +763,7 @@ static void rm_from_hashlist(struct block_entry *be, int tcache_id) } +#if LINK_BRANCHES static void add_to_hashlist_unresolved(struct block_link *bl, int tcache_id) { u32 tcmask = HASH_TABLE_SIZE(tcache_id) - 1; @@ -805,7 +806,6 @@ static void rm_from_hashlist_unresolved(struct block_link *bl, int tcache_id) bl->next->prev = bl->prev; } -#if LINK_BRANCHES static void dr_block_link(struct block_entry *be, struct block_link *bl, int emit_jump) { dbg(2, "- %slink from %p to pc %08x entry %p", emit_jump ? "":"early ", @@ -1033,23 +1033,23 @@ static void dr_rm_block_entry(struct block_desc *bd, int tcache_id, u32 nolit, i return; } -#if LINK_BRANCHES // remove from hash table, make incoming links unresolved if (bd->active) { for (i = 0; i < bd->entry_count; i++) { rm_from_hashlist(&bd->entryp[i], tcache_id); +#if LINK_BRANCHES while ((bl = bd->entryp[i].links) != NULL) { dr_block_unlink(bl, 1); add_to_hashlist_unresolved(bl, tcache_id); } +#endif } dr_mark_memory(-1, bd, tcache_id, nolit); add_to_block_list(&inactive_blocks[tcache_id], bd); } bd->active = 0; -#endif if (free) { #if LINK_BRANCHES @@ -1069,7 +1069,6 @@ static void dr_rm_block_entry(struct block_desc *bd, int tcache_id, u32 nolit, i rm_from_block_lists(bd); bd->addr = bd->size = bd->addr_lit = bd->size_lit = 0; bd->entry_count = 0; - bd->entryp = NULL; } emith_update_cache(); } From a5613afc6b123bfbac507482dbbe5fa0f5574144 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 10 Jun 2021 20:08:58 +0200 Subject: [PATCH 19/22] sound, improve FM output on load/resume --- pico/sound/ym2612.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index 6b3e4bab..75d33de6 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -2185,6 +2185,7 @@ int YM2612PicoStateLoad2(int *tat, int *tbt) blk = ym2612.CH[c].block_fnum >> 11; ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7]; ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk); + refresh_fc_eg_chan( &ym2612.CH[c] ); } // chans 4,5,6 ptr = &ym2612.REGS[0x1b8]; @@ -2205,6 +2206,7 @@ int YM2612PicoStateLoad2(int *tat, int *tbt) blk = ym2612.CH[c].block_fnum >> 11; ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7]; ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk); + refresh_fc_eg_chan( &ym2612.CH[c] ); } for (c = 0; c < 3; c++) { From 142e78daa915183f335830a125613851ca67fdc2 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 10 Jun 2021 20:32:53 +0200 Subject: [PATCH 20/22] vdp, some finetuning, cleanup and 68k, fix idle loop detection crash on 64 bit platforms --- pico/sek.c | 2 +- pico/videoport.c | 73 ++++++++++++++++++++++++------------------------ 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/pico/sek.c b/pico/sek.c index bd8f70f5..ccbddb8e 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -398,7 +398,7 @@ int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx) // XXX: probably shouldn't patch RAM too v = m68k_read16_map[pc >> M68K_MEM_SHIFT]; - if (!(v & 0x80000000)) + if (~v & ~((uptr)-1LL >> 1)) // MSB clear? target = (u16 *)((v << 1) + pc); else { if (++idledet_bads > 128) diff --git a/pico/videoport.c b/pico/videoport.c index cadf956f..44a02fbb 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -19,13 +19,24 @@ enum { clkdiv = 2 }; // CPU clock granularity: one of 1,2,4,8 // forum/viewtopic.php?f=22&t=851&sid=d5701a71396ee7f700c74fb7cd85cb09 // Thank you very much for the great work, Nemesis! +// Slot clock is sysclock/20 for h32 and sysclock/16 for h40. +// One scanline is 63.7us/63.5us (h32/h40) long which is 488.6/487.4 68k cycles. +// Assume 488 for everything. // 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40. +enum { slcpu = 488 }; // VDP has a slot counter running from 0x00 to 0xff every scanline, but it has // a gap depending on the video mode. The slot in which a horizontal interrupt // is generated also depends on the video mode. -enum { hint32 = 0x84, gapstart32 = 0x94, gapend32 = 0xe9 }; -enum { hint40 = 0xa4, gapstart40 = 0xb7, gapend40 = 0xe5 }; +enum { hint32 = 0x85, gapstart32 = 0x94, gapend32 = 0xe9}; +enum { hint40 = 0xa5, gapstart40 = 0xb7, gapend40 = 0xe5}; + +// The horizontal sync period (HBLANK) is 30/37 slots (h32/h40): +// h32: 4 slots front porch (1.49us), 13 HSYNC (4.84us), 13 back porch (4.84us) +// h40: 5 slots front porch (1.49us), 16 HSYNC (4.77us), 16 back porch (4.77us) +// HBLANK starts in slot 0x93/0xb4, according to Nemesis' measurements. +enum { hboff32 = 0x93-hint32, hblen32 = 0xf8-(gapend32-gapstart32)-hint32};//30 +enum { hboff40 = 0xb4-hint40, hblen40 = 0xf8-(gapend40-gapstart40)-hint40};//37 // number of slots in a scanline #define slots32 (0x100-(gapend32-gapstart32)) // 171 @@ -46,16 +57,17 @@ static u8 refslots40[] = { 250, 26, 58, 90, 122, 154 }; // table sizes -enum { cycsz = 488/clkdiv }; +enum { cycsz = slcpu/clkdiv }; enum { sl32blsz=slots32-sizeof(refslots32)+1, sl32acsz=sizeof(dmaslots32)+1 }; enum { sl40blsz=slots40-sizeof(refslots40)+1, sl40acsz=sizeof(dmaslots40)+1 }; // Tables must be considerably larger than one scanline, since 68k emulation // isn't stopping in the middle of an operation. If the last op is a 32 bit -// VDP write 2 slots may need to be taken from the next scanline, which can be +// VDP access 2 slots may need to be taken from the next scanline, which can be // more than 100 CPU cycles. For safety just cover 2 scanlines. -// table for mapping hvcounter reads +// table for hvcounter mapping. check: Sonic 3D Blast bonus, Cannon Fodder, +// Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune static u8 hcounts_32[2*cycsz], hcounts_40[2*cycsz]; // tables mapping cycles to slots static u16 vdpcyc2sl_32_bl[2*cycsz],vdpcyc2sl_40_bl[2*cycsz]; @@ -69,7 +81,7 @@ static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz]; // calculate timing tables for one mode (H32 or H40) // NB tables aligned to HINT, since the main loop uses HINT as synchronization #define INITTABLES(s) { \ - float factor = 488./slots##s; \ + float factor = (float)slcpu/slots##s; \ int ax, bx, rx, ac, bc; \ int i, n; \ \ @@ -77,9 +89,8 @@ static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz]; for (i = 0; i < cycsz; i++) { \ n = hint##s + i*clkdiv/factor; \ if (n >= gapstart##s) n += gapend##s-gapstart##s; \ - hcounts_##s[i] = n % 256; \ + hcounts_##s[i] = n % 256; \ } \ - memcpy(hcounts_##s+cycsz, hcounts_##s, ARRAY_SIZE(hcounts_##s)-cycsz);\ \ ax = bx = ac = bc = rx = 0; \ for (i = 0; i < cycsz; i++) { \ @@ -103,12 +114,14 @@ static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz]; vdpcyc2sl_##s##_ac[ac] = ARRAY_SIZE(dmaslots##s), ac++; \ while (bc < cycsz) \ vdpcyc2sl_##s##_bl[bc] = slots##s-ARRAY_SIZE(refslots##s), bc++; \ + \ /* extend tables for 2nd scanline */ \ + memcpy(hcounts_##s+cycsz, hcounts_##s, ARRAY_SIZE(hcounts_##s)-cycsz);\ i = ARRAY_SIZE(dmaslots##s); \ while (ac < ARRAY_SIZE(vdpcyc2sl_##s##_ac)) \ vdpcyc2sl_##s##_ac[ac] = vdpcyc2sl_##s##_ac[ac-cycsz]+i, ac++; \ while (ax < ARRAY_SIZE(vdpsl2cyc_##s##_ac)-1) ax++, \ - vdpsl2cyc_##s##_ac[ax] = vdpsl2cyc_##s##_ac[ax-i]+cycsz;\ + vdpsl2cyc_##s##_ac[ax] = vdpsl2cyc_##s##_ac[ax-i]+cycsz; \ i = slots##s - ARRAY_SIZE(refslots##s); \ while (bc < ARRAY_SIZE(vdpcyc2sl_##s##_bl)) \ vdpcyc2sl_##s##_bl[bc] = vdpcyc2sl_##s##_bl[bc-cycsz]+i, bc++; \ @@ -198,7 +211,8 @@ static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, i if (l > cnt) l = cnt; if (!(vf->fifo_queue[vf->fifo_qx] & FQ_BGDMA)) - if ((vf->fifo_total -= ((cnt & b) + l) >> b) < 0) vf->fifo_total = 0; + vf->fifo_total -= ((cnt & b) + l) >> b; + if (vf->fifo_total < 0) vf->fifo_total = 0; cnt -= l; // if entry has been processed... @@ -371,7 +385,7 @@ int PicoVideoFIFOWrite(int count, int flags, unsigned sr_mask,unsigned sr_flags) // update FIFO state if it was empty if (!(pv->status & PVS_FIFORUN)) { - vf->fifo_slot = Cyc2Sl(vf, lc+5); // FIFO latency ~3 vdp slots + vf->fifo_slot = Cyc2Sl(vf, lc+7); // FIFO latency ~3 vdp slots pv->status |= PVS_FIFORUN; pv->fifo_cnt = count << (flags & FQ_BYTE); } @@ -829,8 +843,8 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) case 0x00: // Data port 0 or 2 // try avoiding the sync.. if (Pico.m.scanline < (pvid->reg[1]&0x08 ? 240 : 224) && (pvid->reg[1]&0x40) && - !(!pvid->pending && - ((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == (d & 0x7ff))) + !(!pvid->pending && ((pvid->command & 0xc00000f0) == 0x40000010 && + PicoMem.vsram[(pvid->addr>>1) & 0x3f] == (d & 0x7ff))) ) DrawSync(0); // XXX it's unclear when vscroll data is fetched from vsram? @@ -988,10 +1002,10 @@ update_irq: static u32 VideoSr(const struct PicoVideo *pv) { - unsigned int hp = pv->reg[12]&1 ? 15*488/210+1 : 15*488/171+1; // HBLANK start - unsigned int hl = pv->reg[12]&1 ? 37*488/210+1 : 28*488/171+1; // HBLANK len + unsigned int hp = pv->reg[12]&1 ? hboff40*488/slots40 : hboff32*488/slots32; + unsigned int hl = pv->reg[12]&1 ? hblen40*488/slots40 : hblen32*488/slots32; unsigned int c; - u32 d = pv->status; + u32 d = (u16)pv->status; c = SekCyclesDone() - Pico.t.m68c_line_start; if (c - hp < hl) @@ -1021,32 +1035,17 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) return d; } - // H-counter info (based on Generator): - // frame: - // | <- hblank? -> | - // start <416> hint <36> hdisplay <38> end // CPU cycles - // |---------...---------|------------|-------------| - // 0 B6 E4 FF // 40 cells - // 0 93 E8 FF // 32 cells - - // Gens (?) v-render - // start hint hdisplay <404> | - // |---------------------|--------------------------| - // E4 (hc[0x43]==0) 07 B1 // 40 - // E8 (hc[0x45]==0) 05 91 // 32 - - // check: Sonic 3D Blast bonus, Cannon Fodder, Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune if ((a&0x1c)==0x08) { unsigned int c; u32 d; - c = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME + c = SekCyclesDone() - Pico.t.m68c_line_start; if (Pico.video.reg[0]&2) d = Pico.video.hv_latch; else if (Pico.video.reg[12]&1) - d = hcounts_40[c/2] | (Pico.video.v_counter << 8); - else d = hcounts_32[c/2] | (Pico.video.v_counter << 8); + d = hcounts_40[c/clkdiv] | (Pico.video.v_counter << 8); + else d = hcounts_32[c/clkdiv] | (Pico.video.v_counter << 8); elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc); return d; @@ -1103,12 +1102,12 @@ unsigned char PicoVideoRead8HV_H(int is_from_z80) // FIXME: broken unsigned char PicoVideoRead8HV_L(int is_from_z80) { - u32 d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME + u32 d = SekCyclesDone() - Pico.t.m68c_line_start; if (Pico.video.reg[0]&2) d = Pico.video.hv_latch; else if (Pico.video.reg[12]&1) - d = hcounts_40[d/2]; - else d = hcounts_32[d/2]; + d = hcounts_40[d/clkdiv]; + else d = hcounts_32[d/clkdiv]; elprintf(EL_HVCNT, "hcounter: %02x [%u] @ %06x", d, SekCyclesDone(), SekPc); return d; } From fa5f425ee04579252562061d403e211021cc9775 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 11 Jun 2021 13:00:26 +0200 Subject: [PATCH 21/22] Updated dr_libs submodule --- platform/common/dr_libs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/common/dr_libs b/platform/common/dr_libs index 343aa923..b20f7512 160000 --- a/platform/common/dr_libs +++ b/platform/common/dr_libs @@ -1 +1 @@ -Subproject commit 343aa923439e59e7a9f7726f70edc77a4500bdec +Subproject commit b20f7512a69b732ab4082c05e01fc29d42333fae From 5986ec32c826c05374777b67e90487765b27344b Mon Sep 17 00:00:00 2001 From: root Date: Mon, 21 Jun 2021 08:42:45 +0200 Subject: [PATCH 22/22] 32x, optimize poll detection and sh2 drc, fix constant memory address access calculation --- cpu/sh2/compiler.c | 9 +++++---- pico/32x/memory.c | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index ba7e740d..08b2c80f 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -2612,8 +2612,8 @@ static uptr split_address(uptr la, uptr mask, s32 *offs) uptr sign = (mask>>1) + 1; // sign bit in offset *offs = (la & mask) | (la & sign ? ~mask : 0); // offset part, sign extended la = (la & ~mask) + ((la & sign) << 1); // base part, corrected for offs sign - if (~mask && la == ~mask && !(*offs & sign)) { // special case la=-1 & offs>0 - *offs = -*offs; + if (~mask && la == ~mask && *offs > 0) { // special case la=-1&~mask && offs>0 + *offs -= mask+1; la = 0; } return la; @@ -2676,8 +2676,9 @@ static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, s32 *offs) // known fixed host address la = split_address(la + ((a + *offs) & mask), omask, offs); if (la == 0) { - la = *offs; - *offs = 0; + // offset only. optimize for hosts having short indexed addressing + la = *offs & ~0x7f; // keep the lower bits for endianess handling + *offs &= 0x7f; } hr = rcache_get_tmp(); emith_move_r_ptr_imm(hr, la); diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 4cf683c6..5bac31b8 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -119,7 +119,7 @@ void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt) // reading 2 consecutive 16bit values is probably a 32bit access. detect this // by checking address (max 2 bytes away) and cycles (max 2 cycles later). // no polling if more than 20 cycles have passed since last detect call. - if (a - sh2->poll_addr <= 2 && CYCLES_GE(20, cycles_diff)) { + if (a - sh2->poll_addr <= 2 && CYCLES_GE(10, cycles_diff)) { if (CYCLES_GT(cycles_diff, 2) && ++sh2->poll_cnt >= maxcnt) { if (!(sh2->state & flags)) elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", @@ -736,7 +736,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[sh2->is_slave]; case 0x04/2: // H count (often as comm too) - p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 9); + p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 5); cycles = sh2_cycles_done_m68k(sh2); sh2s_sync_on_read(sh2, cycles); return sh2_poll_read(a, Pico32x.sh2_regs[4 / 2], cycles, sh2); @@ -770,7 +770,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) case 0x2a/2: case 0x2c/2: case 0x2e/2: - p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 9); + p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 5); cycles = sh2_cycles_done_m68k(sh2); sh2s_sync_on_read(sh2, cycles); return sh2_poll_read(a, r[a / 2], cycles, sh2); @@ -1457,7 +1457,7 @@ static u32 REGPARM(2) sh2_read8_cs0(u32 a, SH2 *sh2) if ((a & 0x3fff0) == 0x4100) { d = p32x_vdp_read16(a); - p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 9); + p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 7); goto out_16to8; } @@ -1520,7 +1520,7 @@ static u32 REGPARM(2) sh2_read16_cs0(u32 a, SH2 *sh2) if ((a & 0x3fff0) == 0x4100) { d = p32x_vdp_read16(a); - p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 9); + p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 7); goto out; }