From b043a80a702d567022d641634aef9e5a339ad4d1 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 11 May 2021 18:29:21 +0200 Subject: [PATCH] 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