diff --git a/Makefile b/Makefile index f0cd64ef..2620a704 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,9 @@ asm_mix ?= 1 else # if not arm use_fame ?= 1 use_cz80 ?= 1 +ifneq (,$(findstring 86,$(ARCH))) +use_sh2drc ?= 1 +endif endif -include Makefile.local @@ -66,7 +69,13 @@ endif ifeq ("$(PLATFORM)",$(filter "$(PLATFORM)","rpi1" "rpi2")) CFLAGS += -DHAVE_GLES -DRASPBERRY CFLAGS += -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads/ -I/opt/vc/include/interface/vmcs_host/linux/ -LDFLAGS += -ldl -lbcm_host -L/opt/vc/lib -lEGL -lGLESv2 +LDFLAGS += -ldl -lbcm_host -L/opt/vc/lib +# Stupid renaming occured in latest raspbian... +ifneq (,$(wildcard /opt/vc/lib/libbrcmGLESv2.so)) +LDFLAGS += -lbrcmEGL -lbrcmGLESv2 +else +LDFLAGS += -lEGL -lGLESv2 +endif OBJS += platform/linux/emu.o platform/linux/blit.o # FIXME OBJS += platform/common/plat_sdl.o OBJS += platform/libpicofe/plat_sdl.o platform/libpicofe/in_sdl.o @@ -221,8 +230,9 @@ pico/carthw_cfg.c: pico/carthw.cfg tools/make_carthw_c $< $@ # random deps -pico/carthw/svp/compiler.o : cpu/drc/emit_$(ARCH).c -cpu/sh2/compiler.o : cpu/drc/emit_$(ARCH).c +pico/carthw/svp/compiler.o : cpu/drc/emit_arm.c +cpu/sh2/compiler.o : cpu/drc/emit_arm.c +cpu/sh2/compiler.o : cpu/drc/emit_x86.c cpu/sh2/mame/sh2pico.o : cpu/sh2/mame/sh2.c pico/pico.o pico/cd/mcd.o pico/32x/32x.o : pico/pico_cmn.c pico/pico_int.h pico/memory.o pico/cd/memory.o pico/32x/memory.o : pico/pico_int.h pico/memory.h diff --git a/Makefile.libretro b/Makefile.libretro index f0d39857..0c360183 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -52,6 +52,7 @@ ifeq ($(platform), unix) SHARED := -shared DONT_COMPILE_IN_ZLIB = 1 CFLAGS += -DFAMEC_NO_GOTOS + use_sh2drc = 1 # Portable Linux else ifeq ($(platform), linux-portable) @@ -62,6 +63,7 @@ else ifeq ($(platform), linux-portable) LIBM := DONT_COMPILE_IN_ZLIB = 1 CFLAGS += -DFAMEC_NO_GOTOS + use_sh2drc = 1 # OS X else ifeq ($(platform), osx) diff --git a/README b/README index d9c10910..af1bbfcc 100644 --- a/README +++ b/README @@ -12,10 +12,3 @@ then taken over and expanded by notaz. PicoDrive was the first emulator ever to properly emulate Virtua Racing and it's SVP chip. - -How to compile on Raspbian Wheezy: - -export CC=gcc-4.8 -export CXX=g++-4.8 -./configure --platform=rpi2 -make diff --git a/cpu/drc/cmn.h b/cpu/drc/cmn.h index 8953edd1..39463566 100644 --- a/cpu/drc/cmn.h +++ b/cpu/drc/cmn.h @@ -1,7 +1,9 @@ typedef unsigned char u8; typedef signed char s8; typedef unsigned short u16; +typedef signed short s16; typedef unsigned int u32; +typedef signed int s32; #define DRC_TCACHE_SIZE (2*1024*1024) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 64face12..7b5566dd 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -6,6 +6,7 @@ * See COPYING file in the top-level directory. */ #define CONTEXT_REG 11 +#define RET_REG 0 // XXX: tcache_ptr type for SVP and SH2 compilers differs.. #define EMIT_PTR(ptr, x) \ @@ -243,6 +244,11 @@ #define EOP_MSR_IMM(ror2,imm) EOP_C_MSR_IMM(A_COND_AL,ror2,imm) #define EOP_MSR_REG(rm) EOP_C_MSR_REG(A_COND_AL,rm) +#define EOP_MOVW(rd,imm) \ + EMIT(0xe3000000 | ((rd)<<12) | ((imm)&0xfff) | (((imm)<<4)&0xf0000)) + +#define EOP_MOVT(rd,imm) \ + EMIT(0xe3400000 | ((rd)<<12) | (((imm)>>16)&0xfff) | (((imm)>>12)&0xf0000)) // XXX: AND, RSB, *C, will break if 1 insn is not enough static void emith_op_imm2(int cond, int s, int op, int rd, int rn, unsigned int imm) @@ -257,6 +263,19 @@ static void emith_op_imm2(int cond, int s, int op, int rd, int rn, unsigned int imm = ~imm; op = A_OP_MVN; } +#ifdef HAVE_ARMV7 + for (v = imm, ror2 = 0; v && !(v & 3); v >>= 2) + ror2--; + if (v >> 8) { + /* 2+ insns needed - prefer movw/movt */ + if (op == A_OP_MVN) + imm = ~imm; + EOP_MOVW(rd, imm); + if (imm & 0xffff0000) + EOP_MOVT(rd, imm); + return; + } +#endif break; case A_OP_EOR: @@ -351,6 +370,9 @@ static int emith_xbranch(int cond, void *target, int is_call) #define EMITH_NOTHING1(cond) \ (void)(cond) +#define EMITH_SJMP_DECL_() +#define EMITH_SJMP_START_(cond) EMITH_NOTHING1(cond) +#define EMITH_SJMP_END_(cond) EMITH_NOTHING1(cond) #define EMITH_SJMP_START(cond) EMITH_NOTHING1(cond) #define EMITH_SJMP_END(cond) EMITH_NOTHING1(cond) #define EMITH_SJMP3_START(cond) EMITH_NOTHING1(cond) @@ -360,6 +382,9 @@ static int emith_xbranch(int cond, void *target, int is_call) #define emith_move_r_r(d, s) \ EOP_MOV_REG_SIMPLE(d, s) +#define emith_move_r_r_ptr(d, s) \ + emith_move_r_r(d, s) + #define emith_mvn_r_r(d, s) \ EOP_MVN_REG(A_COND_AL,0,d,s,A_AM1_LSL,0) @@ -503,6 +528,9 @@ static int emith_xbranch(int cond, void *target, int is_call) #define emith_add_r_r_imm(d, s, imm) \ emith_op_imm2(A_COND_AL, 0, A_OP_ADD, d, s, imm) +#define emith_add_r_r_ptr_imm(d, s, imm) \ + emith_add_r_r_imm(d, s, imm) + #define emith_sub_r_r_imm(d, s, imm) \ emith_op_imm2(A_COND_AL, 0, A_OP_SUB, d, s, imm) @@ -593,6 +621,9 @@ static int emith_xbranch(int cond, void *target, int is_call) #define emith_ctx_read(r, offs) \ emith_read_r_r_offs(r, CONTEXT_REG, offs) +#define emith_ctx_read_ptr(r, offs) \ + emith_ctx_read(r, offs) + #define emith_ctx_write(r, offs) \ EOP_STR_IMM(r, CONTEXT_REG, offs) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 754c27fe..5362d9bd 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -16,6 +16,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define CONTEXT_REG xBP +#define RET_REG xAX #define ICOND_JO 0x00 #define ICOND_JNO 0x01 @@ -53,15 +54,15 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define EMIT_PTR(ptr, val, type) \ *(type *)(ptr) = val -#define EMIT(val, type) { \ +#define EMIT(val, type) do { \ EMIT_PTR(tcache_ptr, val, type); \ tcache_ptr += sizeof(type); \ -} +} while (0) -#define EMIT_OP(op) { \ +#define EMIT_OP(op) do { \ COUNT_OP; \ EMIT(op, u8); \ -} +} while (0) #define EMIT_MODRM(mod,r,rm) \ EMIT(((mod)<<6) | ((r)<<3) | (rm), u8) @@ -69,6 +70,9 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define EMIT_SIB(scale,index,base) \ EMIT(((scale)<<6) | ((index)<<3) | (base), u8) +#define EMIT_REX(w,r,x,b) \ + EMIT(0x40 | ((w)<<3) | ((r)<<2) | ((x)<<1) | (b), u8) + #define EMIT_OP_MODRM(op,mod,r,rm) do { \ EMIT_OP(op); \ EMIT_MODRM(mod, r, rm); \ @@ -90,6 +94,11 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_move_r_r(dst, src) \ EMIT_OP_MODRM(0x8b, 3, dst, src) +#define emith_move_r_r_ptr(dst, src) do { \ + EMIT_REX_FOR_PTR(); \ + EMIT_OP_MODRM(0x8b, 3, dst, src); \ +} while (0) + #define emith_add_r_r(d, s) \ EMIT_OP_MODRM(0x01, 3, s, d) @@ -118,34 +127,34 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; EMIT_OP_MODRM(0x39, 3, s, d) // fake teq - test equivalence - get_flags(d ^ s) -#define emith_teq_r_r(d, s) { \ +#define emith_teq_r_r(d, s) do { \ emith_push(d); \ emith_eor_r_r(d, s); \ emith_pop(d); \ -} +} while (0) -#define emith_mvn_r_r(d, s) { \ +#define emith_mvn_r_r(d, s) do { \ if (d != s) \ emith_move_r_r(d, s); \ EMIT_OP_MODRM(0xf7, 3, 2, d); /* NOT d */ \ -} +} while (0) -#define emith_negc_r_r(d, s) { \ +#define emith_negc_r_r(d, s) do { \ int tmp_ = rcache_get_tmp(); \ emith_move_r_imm(tmp_, 0); \ emith_sbc_r_r(tmp_, s); \ emith_move_r_r(d, tmp_); \ rcache_free_tmp(tmp_); \ -} +} while (0) -#define emith_neg_r_r(d, s) { \ +#define emith_neg_r_r(d, s) do { \ if (d != s) \ emith_move_r_r(d, s); \ EMIT_OP_MODRM(0xf7, 3, 3, d); /* NEG d */ \ -} +} while (0) // _r_r_r -#define emith_add_r_r_r(d, s1, s2) { \ +#define emith_add_r_r_r(d, s1, s2) do { \ if (d == s1) { \ emith_add_r_r(d, s2); \ } else if (d == s2) { \ @@ -154,9 +163,9 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_move_r_r(d, s1); \ emith_add_r_r(d, s2); \ } \ -} +} while (0) -#define emith_eor_r_r_r(d, s1, s2) { \ +#define emith_eor_r_r_r(d, s1, s2) do { \ if (d == s1) { \ emith_eor_r_r(d, s2); \ } else if (d == s2) { \ @@ -165,29 +174,29 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_move_r_r(d, s1); \ emith_eor_r_r(d, s2); \ } \ -} +} while (0) // _r_r_shift -#define emith_or_r_r_lsl(d, s, lslimm) { \ +#define emith_or_r_r_lsl(d, s, lslimm) do { \ int tmp_ = rcache_get_tmp(); \ emith_lsl(tmp_, s, lslimm); \ emith_or_r_r(d, tmp_); \ rcache_free_tmp(tmp_); \ -} +} while (0) // d != s -#define emith_eor_r_r_lsr(d, s, lsrimm) { \ +#define emith_eor_r_r_lsr(d, s, lsrimm) do { \ emith_push(s); \ emith_lsr(s, s, lsrimm); \ emith_eor_r_r(d, s); \ emith_pop(s); \ -} +} while (0) // _r_imm -#define emith_move_r_imm(r, imm) { \ +#define emith_move_r_imm(r, imm) do { \ EMIT_OP(0xb8 + (r)); \ EMIT(imm, u32); \ -} +} while (0) #define emith_move_r_imm_s8(r, imm) \ emith_move_r_imm(r, (u32)(signed int)(signed char)(imm)) @@ -212,7 +221,14 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_and_r_imm(r, imm) \ emith_arith_r_imm(4, r, imm) -#define emith_sub_r_imm(r, imm) \ +/* used for sub cycles after test, so retain flags with lea */ +#define emith_sub_r_imm(r, imm) do { \ + assert(r != xSP); \ + EMIT_OP_MODRM(0x8d, 2, r, r); \ + EMIT(-(s32)(imm), s32); \ +} while (0) + +#define emith_subf_r_imm(r, imm) \ emith_arith_r_imm(5, r, imm) #define emith_eor_r_imm(r, imm) \ @@ -231,20 +247,20 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_arith_r_imm(4, r, ~(imm)) // fake conditionals (using SJMP instead) -#define emith_move_r_imm_c(cond, r, imm) { \ +#define emith_move_r_imm_c(cond, r, imm) do { \ (void)(cond); \ emith_move_r_imm(r, imm); \ -} +} while (0) -#define emith_add_r_imm_c(cond, r, imm) { \ +#define emith_add_r_imm_c(cond, r, imm) do { \ (void)(cond); \ emith_add_r_imm(r, imm); \ -} +} while (0) -#define emith_sub_r_imm_c(cond, r, imm) { \ +#define emith_sub_r_imm_c(cond, r, imm) do { \ (void)(cond); \ emith_sub_r_imm(r, imm); \ -} +} while (0) #define emith_or_r_imm_c(cond, r, imm) \ emith_or_r_imm(r, imm) @@ -274,26 +290,40 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_ret_c(cond) \ emith_ret() -// _r_r_imm -#define emith_add_r_r_imm(d, s, imm) { \ - if (d != s) \ - emith_move_r_r(d, s); \ - emith_add_r_imm(d, imm); \ -} +// _r_r_imm - use lea +#define emith_add_r_r_imm(d, s, imm) do { \ + assert(s != xSP); \ + EMIT_OP_MODRM(0x8d, 2, d, s); /* lea */ \ + EMIT(imm, s32); \ +} while (0) -#define emith_and_r_r_imm(d, s, imm) { \ +#define emith_add_r_r_ptr_imm(d, s, imm) do { \ + if (s != xSP) { \ + EMIT_REX_FOR_PTR(); \ + EMIT_OP_MODRM(0x8d, 2, d, s); /* lea */ \ + } \ + else { \ + if (d != s) \ + emith_move_r_r_ptr(d, s); \ + EMIT_REX_FOR_PTR(); \ + EMIT_OP_MODRM(0x81, 3, 0, d); /* add */ \ + } \ + EMIT(imm, s32); \ +} while (0) + +#define emith_and_r_r_imm(d, s, imm) do { \ if (d != s) \ emith_move_r_r(d, s); \ emith_and_r_imm(d, imm); \ -} +} while (0) // shift -#define emith_shift(op, d, s, cnt) { \ +#define emith_shift(op, d, s, cnt) do { \ if (d != s) \ emith_move_r_r(d, s); \ EMIT_OP_MODRM(0xc1, 3, op, d); \ EMIT(cnt, u8); \ -} +} while (0) #define emith_lsl(d, s, cnt) \ emith_shift(4, d, s, cnt) @@ -320,10 +350,10 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_push(r) \ EMIT_OP(0x50 + (r)) -#define emith_push_imm(imm) { \ +#define emith_push_imm(imm) do { \ EMIT_OP(0x68); \ EMIT(imm, u32); \ -} +} while (0) #define emith_pop(r) \ EMIT_OP(0x58 + (r)) @@ -349,13 +379,14 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_asr(d, d, 32 - (bits)); \ } -#define emith_setc(r) { \ +#define emith_setc(r) do { \ + assert(is_abcdx(r)); \ EMIT_OP(0x0f); \ EMIT_OP_MODRM(0x92, 3, 0, r); /* SETC r */ \ -} +} while (0) // XXX: stupid mess -#define emith_mul_(op, dlo, dhi, s1, s2) { \ +#define emith_mul_(op, dlo, dhi, s1, s2) do { \ int rmr; \ if (dlo != xAX && dhi != xAX) \ emith_push(xAX); \ @@ -381,7 +412,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_pop(xDX); \ if (dlo != xAX && dhi != xAX) \ emith_pop(xAX); \ -} +} while (0) #define emith_mul_u64(dlo, dhi, s1, s2) \ emith_mul_(4, dlo, dhi, s1, s2) /* MUL */ @@ -393,20 +424,19 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_mul_(4, d, -1, s1, s2) // (dlo,dhi) += signed(s1) * signed(s2) -#define emith_mula_s64(dlo, dhi, s1, s2) { \ +#define emith_mula_s64(dlo, dhi, s1, s2) do { \ emith_push(dhi); \ emith_push(dlo); \ emith_mul_(5, dlo, dhi, s1, s2); \ EMIT_OP_MODRM(0x03, 0, dlo, 4); \ - EMIT_SIB(0, 4, 4); /* add dlo, [esp] */ \ + EMIT_SIB(0, 4, 4); /* add dlo, [xsp] */ \ EMIT_OP_MODRM(0x13, 1, dhi, 4); \ EMIT_SIB(0, 4, 4); \ - EMIT(4, u8); /* adc dhi, [esp+4] */ \ - emith_add_r_imm(xSP, 4*2); \ -} + EMIT(sizeof(void *), u8); /* adc dhi, [xsp+{4,8}] */ \ + emith_add_r_r_ptr_imm(xSP, xSP, sizeof(void *) * 2); \ +} while (0) // "flag" instructions are the same -#define emith_subf_r_imm emith_sub_r_imm #define emith_addf_r_r emith_add_r_r #define emith_subf_r_r emith_sub_r_r #define emith_adcf_r_r emith_adc_r_r @@ -464,19 +494,24 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; rcache_free_tmp(r_); \ } while (0) -#define emith_read16_r_r_offs(r, rs, offs) { \ +#define emith_read16_r_r_offs(r, rs, offs) do { \ EMIT(0x66, u8); /* operand override */ \ emith_read_r_r_offs(r, rs, offs); \ -} +} while (0) -#define emith_write16_r_r_offs(r, rs, offs) { \ +#define emith_write16_r_r_offs(r, rs, offs) do { \ EMIT(0x66, u8); \ emith_write_r_r_offs(r, rs, offs); \ -} +} while (0) #define emith_ctx_read(r, offs) \ emith_read_r_r_offs(r, CONTEXT_REG, offs) +#define emith_ctx_read_ptr(r, offs) do { \ + EMIT_REX_FOR_PTR(); \ + emith_deref_op(0x8b, r, CONTEXT_REG, offs); \ +} while (0) + #define emith_ctx_write(r, offs) \ emith_write_r_r_offs(r, CONTEXT_REG, offs) @@ -499,7 +534,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; } #define emith_jump(ptr) { \ - u32 disp = (u32)(ptr) - ((u32)tcache_ptr + 5); \ + u32 disp = (u8 *)(ptr) - ((u8 *)tcache_ptr + 5); \ EMIT_OP(0xe9); \ EMIT(disp, u32); \ } @@ -507,30 +542,30 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_jump_patchable(target) \ emith_jump(target) -#define emith_jump_cond(cond, ptr) { \ - u32 disp = (u32)(ptr) - ((u32)tcache_ptr + 6); \ +#define emith_jump_cond(cond, ptr) do { \ + u32 disp = (u8 *)(ptr) - ((u8 *)tcache_ptr + 6); \ EMIT(0x0f, u8); \ EMIT_OP(0x80 | (cond)); \ EMIT(disp, u32); \ -} +} while (0) #define emith_jump_cond_patchable(cond, target) \ emith_jump_cond(cond, target) #define emith_jump_patch(ptr, target) do { \ - u32 disp_ = (u32)(target) - ((u32)(ptr) + 4); \ + u32 disp_ = (u8 *)(target) - ((u8 *)(ptr) + 4); \ u32 offs_ = (*(u8 *)(ptr) == 0x0f) ? 2 : 1; \ EMIT_PTR((u8 *)(ptr) + offs_, disp_ - offs_, u32); \ } while (0) #define emith_jump_at(ptr, target) { \ - u32 disp_ = (u32)(target) - ((u32)(ptr) + 5); \ + u32 disp_ = (u8 *)(target) - ((u8 *)(ptr) + 5); \ EMIT_PTR(ptr, 0xe9, u8); \ EMIT_PTR((u8 *)(ptr) + 1, disp_, u32); \ } #define emith_call(ptr) { \ - u32 disp = (u32)(ptr) - ((u32)tcache_ptr + 5); \ + u32 disp = (u8 *)(ptr) - ((u8 *)tcache_ptr + 5); \ EMIT_OP(0xe8); \ EMIT(disp, u32); \ } @@ -541,10 +576,10 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_call_reg(r) \ EMIT_OP_MODRM(0xff, 3, 2, r) -#define emith_call_ctx(offs) { \ +#define emith_call_ctx(offs) do { \ EMIT_OP_MODRM(0xff, 2, 2, CONTEXT_REG); \ EMIT(offs, u32); \ -} +} while (0) #define emith_ret() \ EMIT_OP(0xc3) @@ -552,10 +587,10 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_jump_reg(r) \ EMIT_OP_MODRM(0xff, 3, 4, r) -#define emith_jump_ctx(offs) { \ +#define emith_jump_ctx(offs) do { \ EMIT_OP_MODRM(0xff, 2, 4, CONTEXT_REG); \ EMIT(offs, u32); \ -} +} while (0) #define emith_push_ret() @@ -584,6 +619,15 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; // "simple" jump (no more then a few insns) // ARM will use conditional instructions here +#define EMITH_SJMP_DECL_() \ + u8 *cond_ptr + +#define EMITH_SJMP_START_(cond) \ + JMP8_POS(cond_ptr) + +#define EMITH_SJMP_END_(cond) \ + JMP8_EMIT(cond, cond_ptr) + #define EMITH_SJMP_START EMITH_JMP_START #define EMITH_SJMP_END EMITH_JMP_END @@ -591,20 +635,55 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define EMITH_SJMP3_MID EMITH_JMP3_MID #define EMITH_SJMP3_END EMITH_JMP3_END -#define emith_pass_arg_r(arg, reg) { \ +#define emith_pass_arg_r(arg, reg) do { \ int rd = 7; \ host_arg2reg(rd, arg); \ - emith_move_r_r(rd, reg); \ -} + emith_move_r_r_ptr(rd, reg); \ +} while (0) -#define emith_pass_arg_imm(arg, imm) { \ +#define emith_pass_arg_imm(arg, imm) do { \ int rd = 7; \ host_arg2reg(rd, arg); \ emith_move_r_imm(rd, imm); \ -} +} while (0) #define host_instructions_updated(base, end) +#ifdef __x86_64__ + +#define PTR_SCALE 3 +#define NA_TMP_REG xCX // non-arg tmp from reg_temp[] + +#define EMIT_REX_FOR_PTR() \ + EMIT_REX(1,0,0,0) + +#define host_arg2reg(rd, arg) \ + switch (arg) { \ + case 0: rd = xDI; break; \ + case 1: rd = xSI; break; \ + case 2: rd = xDX; break; \ + } + +#define emith_sh2_drc_entry() { \ + emith_push(xBX); \ + emith_push(xBP); \ + emith_push(xSI); /* to align */ \ +} + +#define emith_sh2_drc_exit() { \ + emith_pop(xSI); \ + emith_pop(xBP); \ + emith_pop(xBX); \ + emith_ret(); \ +} + +#else + +#define PTR_SCALE 2 +#define NA_TMP_REG xBX // non-arg tmp from reg_temp[] + +#define EMIT_REX_FOR_PTR() + #define host_arg2reg(rd, arg) \ switch (arg) { \ case 0: rd = xAX; break; \ @@ -612,7 +691,6 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; case 2: rd = xCX; break; \ } -/* SH2 drc specific */ #define emith_sh2_drc_entry() { \ emith_push(xBX); \ emith_push(xBP); \ @@ -628,15 +706,33 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_ret(); \ } -// assumes EBX is free temporary +#endif + +#define emith_save_caller_regs(mask) do { \ + if ((mask) & (1 << xAX)) emith_push(xAX); \ + if ((mask) & (1 << xCX)) emith_push(xCX); \ + if ((mask) & (1 << xDX)) emith_push(xDX); \ + if ((mask) & (1 << xSI)) emith_push(xSI); \ + if ((mask) & (1 << xDI)) emith_push(xDI); \ +} while (0) + +#define emith_restore_caller_regs(mask) do { \ + if ((mask) & (1 << xDI)) emith_pop(xDI); \ + if ((mask) & (1 << xSI)) emith_pop(xSI); \ + if ((mask) & (1 << xDX)) emith_pop(xDX); \ + if ((mask) & (1 << xCX)) emith_pop(xCX); \ + if ((mask) & (1 << xAX)) emith_pop(xAX); \ +} while (0) + #define emith_sh2_wcall(a, tab) { \ int arg2_; \ host_arg2reg(arg2_, 2); \ - emith_lsr(xBX, a, SH2_WRITE_SHIFT); \ - EMIT_OP_MODRM(0x8b, 0, xBX, 4); \ - EMIT_SIB(2, xBX, tab); /* mov ebx, [tab + ebx * 4] */ \ - emith_move_r_r(arg2_, CONTEXT_REG); \ - emith_jump_reg(xBX); \ + emith_lsr(NA_TMP_REG, a, SH2_WRITE_SHIFT); \ + EMIT_REX_FOR_PTR(); \ + EMIT_OP_MODRM(0x8b, 0, NA_TMP_REG, 4); \ + EMIT_SIB(PTR_SCALE, NA_TMP_REG, tab); /* mov tmp, [tab + tmp * {4,8}] */ \ + emith_move_r_r_ptr(arg2_, CONTEXT_REG); \ + emith_jump_reg(NA_TMP_REG); \ } #define emith_sh2_dtbf_loop() { \ @@ -697,8 +793,8 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; JMP8_EMIT(ICOND_JE, jmp0); /* do_sub: */ \ emith_sub_r_r(rn, rm); \ JMP8_EMIT_NC(jmp1); /* done: */ \ - emith_setc(tmp_); \ - EMIT_OP_MODRM(0x31, 3, tmp_, sr); /* T = Q1 ^ Q2 */ \ + emith_adc_r_r(tmp_, tmp_); \ + emith_eor_r_r(sr, tmp_); \ rcache_free_tmp(tmp_); \ } diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 7bd9de0e..3b6b45af 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -29,6 +29,7 @@ #include #include "../../pico/pico_int.h" +#include "../../pico/arm_features.h" #include "sh2.h" #include "compiler.h" #include "../drc/cmn.h" @@ -47,10 +48,11 @@ #define MAX_LOCAL_BRANCHES 32 // debug stuff -// 1 - warnings/errors -// 2 - block info/smc -// 4 - asm -// 8 - runtime block entry log +// 01 - warnings/errors +// 02 - block info/smc +// 04 - asm +// 08 - runtime block entry log +// 10 - smc self-check // { #ifndef DRC_DEBUG #define DRC_DEBUG 0 @@ -324,6 +326,27 @@ static temp_reg_t reg_temp[] = { { xDX, }, }; +#elif defined(__x86_64__) +#include "../drc/emit_x86.c" + +static const int reg_map_g2h[] = { + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, xBX, + -1, -1, -1, -1, +}; + +// ax, cx, dx are usually temporaries by convention +static temp_reg_t reg_temp[] = { + { xAX, }, + { xCX, }, + { xDX, }, + { xSI, }, + { xDI, }, +}; + #else #error unsupported arch #endif @@ -419,7 +442,7 @@ static void add_to_block_list(struct block_list **blist, struct block_desc *bloc static void rm_from_block_list(struct block_list **blist, struct block_desc *block) { struct block_list *prev = NULL, *current = *blist; - for (; current != NULL; prev = current, current = current->next) { + for (; current != NULL; current = current->next) { if (current->block == block) { if (prev == NULL) *blist = current->next; @@ -428,6 +451,7 @@ static void rm_from_block_list(struct block_list **blist, struct block_desc *blo free(current); return; } + prev = current; } dbg(1, "can't rm block %p (%08x-%08x)", block, block->addr, block->addr + block->size); @@ -514,6 +538,29 @@ missing: dbg(1, "rm_from_hashlist: be %p %08x missing?", be, be->pc); } +static void unregister_links(struct block_entry *be, int tcache_id) +{ + struct block_link *bl_unresolved = unresolved_links[tcache_id]; + struct block_link *bl, *bl_next; + + for (bl = be->links; bl != NULL; ) { + bl_next = bl->next; + bl->next = bl_unresolved; + bl_unresolved = bl; + bl = bl_next; + } + be->links = NULL; + unresolved_links[tcache_id] = bl_unresolved; +} + +// unlike sh2_smc_rm_block, the block stays and can still be accessed +// by other already directly linked blocks, just not preferred +static void kill_block_entry(struct block_entry *be, int tcache_id) +{ + rm_from_hashlist(be, tcache_id); + unregister_links(be, tcache_id); +} + static struct block_desc *dr_add_block(u32 addr, u16 size_lit, u16 size_nolit, int is_slave, int *blk_id) { @@ -524,8 +571,10 @@ static struct block_desc *dr_add_block(u32 addr, u16 size_lit, // do a lookup to get tcache_id and override check be = dr_get_entry(addr, is_slave, &tcache_id); - if (be != NULL) - dbg(1, "block override for %08x", addr); + if (be != NULL) { + dbg(1, "block override for %08x, was %p", addr, be->tcache_ptr); + kill_block_entry(be, tcache_id); + } bcount = &block_counts[tcache_id]; if (*bcount >= block_max_counts[tcache_id]) { @@ -891,13 +940,12 @@ do_alloc: return tr->hreg; } -static int rcache_get_arg_id(int arg) +static int rcache_get_hr_id(int hr) { - int i, r = 0; - host_arg2reg(r, arg); + int i; for (i = 0; i < ARRAY_SIZE(reg_temp); i++) - if (reg_temp[i].hreg == r) + if (reg_temp[i].hreg == hr) break; if (i == ARRAY_SIZE(reg_temp)) // can't happen @@ -910,7 +958,7 @@ static int rcache_get_arg_id(int arg) gconst_check_evict(reg_temp[i].greg); } else if (reg_temp[i].type == HR_TEMP) { - printf("arg %d reg %d already used, aborting\n", arg, r); + printf("host reg %d already used, aborting\n", hr); exit(1); } @@ -920,6 +968,13 @@ static int rcache_get_arg_id(int arg) return i; } +static int rcache_get_arg_id(int arg) +{ + int r = 0; + host_arg2reg(r, arg); + return rcache_get_hr_id(r); +} + // get a reg to be used as function arg static int rcache_get_tmp_arg(int arg) { @@ -929,6 +984,15 @@ static int rcache_get_tmp_arg(int arg) return reg_temp[id].hreg; } +// ... as return value after a call +static int rcache_get_tmp_ret(void) +{ + int id = rcache_get_hr_id(RET_REG); + reg_temp[id].type = HR_TEMP; + + return reg_temp[id].hreg; +} + // same but caches a reg. RC_GR_READ only. static int rcache_get_reg_arg(int arg, sh2_reg_e r) { @@ -1076,8 +1140,8 @@ static int emit_get_rbase_and_offs(u32 a, u32 *offs) // XXX: could use some related reg hr = rcache_get_tmp(); - emith_ctx_read(hr, poffs); - emith_add_r_imm(hr, a & mask & ~0xff); + emith_ctx_read_ptr(hr, poffs); + emith_add_r_r_ptr_imm(hr, hr, a & mask & ~0xff); *offs = a & 0xff; // XXX: ARM oriented.. return hr; } @@ -1126,7 +1190,7 @@ static int emit_memhandler_read_(int size, int ram_check) emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4); arg1 = rcache_get_tmp_arg(1); - emith_move_r_r(arg1, CONTEXT_REG); + emith_move_r_r_ptr(arg1, CONTEXT_REG); #if 0 // can't do this because of unmapped reads // ndef PDB_NET @@ -1180,8 +1244,7 @@ static int emit_memhandler_read_(int size, int ram_check) if (reg_map_g2h[SHR_SR] != -1) emith_ctx_read(reg_map_g2h[SHR_SR], SHR_SR * 4); - // assuming arg0 and retval reg matches - return rcache_get_tmp_arg(0); + return rcache_get_tmp_ret(); } static int emit_memhandler_read(int size) @@ -1251,7 +1314,7 @@ static void emit_memhandler_write(int size) emith_call(sh2_drc_write16); break; case 2: // 32 - emith_move_r_r(ctxr, CONTEXT_REG); + emith_move_r_r_ptr(ctxr, CONTEXT_REG); emith_call(sh2_drc_write32); break; } @@ -1323,26 +1386,23 @@ static void emit_do_static_regs(int is_write, int tmpr) } } +/* just after lookup function, jump to address returned */ static void emit_block_entry(void) { - int arg0; - - host_arg2reg(arg0, 0); - #if (DRC_DEBUG & 8) || defined(PDB) int arg1, arg2; host_arg2reg(arg1, 1); host_arg2reg(arg2, 2); emit_do_static_regs(1, arg2); - emith_move_r_r(arg1, CONTEXT_REG); + emith_move_r_r_ptr(arg1, CONTEXT_REG); emith_move_r_r(arg2, rcache_get_reg(SHR_SR, RC_GR_READ)); emith_call(sh2_drc_log_entry); rcache_invalidate(); #endif - emith_tst_r_r(arg0, arg0); + emith_tst_r_r(RET_REG, RET_REG); EMITH_SJMP_START(DCOND_EQ); - emith_jump_reg_c(DCOND_NE, arg0); + emith_jump_reg_c(DCOND_NE, RET_REG); EMITH_SJMP_END(DCOND_EQ); } @@ -1480,13 +1540,22 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) // make block entry v = block->entry_count; - if (v < ARRAY_SIZE(block->entryp)) { + if (v < ARRAY_SIZE(block->entryp)) + { + struct block_entry *be_old; + block->entryp[v].pc = pc; block->entryp[v].tcache_ptr = tcache_ptr; block->entryp[v].links = NULL; #if (DRC_DEBUG & 2) block->entryp[v].block = block; #endif + be_old = dr_get_entry(pc, sh2->is_slave, &tcache_id); + if (be_old != NULL) { + dbg(1, "entry override for %08x, was %p", pc, be_old->tcache_ptr); + kill_block_entry(be_old, tcache_id); + } + add_to_hashlist(&block->entryp[v], tcache_id); block->entry_count++; @@ -1514,6 +1583,22 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emit_move_r_imm32(SHR_PC, pc); rcache_clean(); +#if (DRC_DEBUG & 0x10) + rcache_get_reg_arg(0, SHR_PC); + tmp = emit_memhandler_read(2); + tmp2 = rcache_get_tmp(); + tmp3 = rcache_get_tmp(); + emith_move_r_imm(tmp2, FETCH32(pc)); + emith_move_r_imm(tmp3, 0); + emith_cmp_r_r(tmp, tmp2); + EMITH_SJMP_START(DCOND_EQ); + emith_read_r_r_offs_c(DCOND_NE, tmp3, tmp3, 0); // crash + EMITH_SJMP_END(DCOND_EQ); + rcache_free_tmp(tmp); + rcache_free_tmp(tmp2); + rcache_free_tmp(tmp3); +#endif + // check cycles sr = rcache_get_reg(SHR_SR, RC_GR_READ); emith_cmp_r_imm(sr, 0); @@ -2650,14 +2735,18 @@ end_op: struct op_data *opd_b = (op_flags[i] & OF_DELAY_OP) ? &ops[i-1] : opd; u32 target_pc = opd_b->imm; - int cond = -1; + int cond = -1, ncond = -1; void *target = NULL; + EMITH_SJMP_DECL_(); sr = rcache_get_reg(SHR_SR, RC_GR_RMW); FLUSH_CYCLES(sr); + rcache_clean(); - if (opd_b->op != OP_BRANCH) + if (opd_b->op != OP_BRANCH) { cond = (opd_b->op == OP_BRANCH_CF) ? DCOND_EQ : DCOND_NE; + ncond = (opd_b->op == OP_BRANCH_CF) ? DCOND_NE : DCOND_EQ; + } if (cond != -1) { int ctaken = (op_flags[i] & OF_DELAY_OP) ? 1 : 2; @@ -2666,9 +2755,9 @@ end_op: else emith_tst_r_imm(sr, T); + EMITH_SJMP_START_(ncond); emith_sub_r_imm_c(cond, sr, ctaken<<12); } - rcache_clean(); #if LINK_BRANCHES if (find_in_array(branch_target_pc, branch_target_count, target_pc) >= 0) @@ -2697,8 +2786,10 @@ end_op: return NULL; } - if (cond != -1) + if (cond != -1) { emith_jump_cond_patchable(cond, target); + EMITH_SJMP_END_(ncond); + } else { emith_jump_patchable(target); rcache_invalidate(); @@ -2853,18 +2944,18 @@ static void sh2_generate_utils(void) rcache_invalidate(); emith_ctx_read(arg0, SHR_PC * 4); emith_ctx_read(arg1, offsetof(SH2, is_slave)); - emith_add_r_r_imm(arg2, CONTEXT_REG, offsetof(SH2, drc_tmp)); + emith_add_r_r_ptr_imm(arg2, CONTEXT_REG, offsetof(SH2, drc_tmp)); emith_call(dr_lookup_block); emit_block_entry(); // lookup failed, call sh2_translate() - emith_move_r_r(arg0, CONTEXT_REG); + emith_move_r_r_ptr(arg0, CONTEXT_REG); emith_ctx_read(arg1, offsetof(SH2, drc_tmp)); // tcache_id emith_call(sh2_translate); emit_block_entry(); // sh2_translate() failed, flush cache and retry emith_ctx_read(arg0, offsetof(SH2, drc_tmp)); emith_call(flush_tcache); - emith_move_r_r(arg0, CONTEXT_REG); + emith_move_r_r_ptr(arg0, CONTEXT_REG); emith_ctx_read(arg1, offsetof(SH2, drc_tmp)); emith_call(sh2_translate); emit_block_entry(); @@ -2891,13 +2982,13 @@ static void sh2_generate_utils(void) emith_add_r_imm(tmp, 4); tmp = rcache_get_reg_arg(1, SHR_SR); emith_clear_msb(tmp, tmp, 22); - emith_move_r_r(arg2, CONTEXT_REG); + emith_move_r_r_ptr(arg2, CONTEXT_REG); emith_call(p32x_sh2_write32); // XXX: use sh2_drc_write32? rcache_invalidate(); // push PC rcache_get_reg_arg(0, SHR_SP); emith_ctx_read(arg1, SHR_PC * 4); - emith_move_r_r(arg2, CONTEXT_REG); + emith_move_r_r_ptr(arg2, CONTEXT_REG); emith_call(p32x_sh2_write32); rcache_invalidate(); // update I, cycles, do callback @@ -2907,16 +2998,16 @@ static void sh2_generate_utils(void) emith_or_r_r_lsl(sr, arg1, I_SHIFT); emith_sub_r_imm(sr, 13 << 12); // at least 13 cycles rcache_flush(); - emith_move_r_r(arg0, CONTEXT_REG); + emith_move_r_r_ptr(arg0, CONTEXT_REG); emith_call_ctx(offsetof(SH2, irq_callback)); // vector = sh2->irq_callback(sh2, level); // obtain new PC - emith_lsl(arg0, arg0, 2); + emith_lsl(arg0, RET_REG, 2); emith_ctx_read(arg1, SHR_VBR * 4); emith_add_r_r(arg0, arg1); - emit_memhandler_read(2); - emith_ctx_write(arg0, SHR_PC * 4); -#ifdef __i386__ - emith_add_r_imm(xSP, 4); // fix stack + tmp = emit_memhandler_read(2); + emith_ctx_write(tmp, SHR_PC * 4); +#if defined(__i386__) || defined(__x86_64__) + emith_add_r_r_ptr_imm(xSP, xSP, sizeof(void *)); // fix stack #endif emith_jump(sh2_drc_dispatcher); rcache_invalidate(); @@ -2924,19 +3015,19 @@ static void sh2_generate_utils(void) // sh2_drc_entry(SH2 *sh2) sh2_drc_entry = (void *)tcache_ptr; emith_sh2_drc_entry(); - emith_move_r_r(CONTEXT_REG, arg0); // move ctx, arg0 + emith_move_r_r_ptr(CONTEXT_REG, arg0); // move ctx, arg0 emit_do_static_regs(0, arg2); emith_call(sh2_drc_test_irq); emith_jump(sh2_drc_dispatcher); // sh2_drc_write8(u32 a, u32 d) sh2_drc_write8 = (void *)tcache_ptr; - emith_ctx_read(arg2, offsetof(SH2, write8_tab)); + emith_ctx_read_ptr(arg2, offsetof(SH2, write8_tab)); emith_sh2_wcall(arg0, arg2); // sh2_drc_write16(u32 a, u32 d) sh2_drc_write16 = (void *)tcache_ptr; - emith_ctx_read(arg2, offsetof(SH2, write16_tab)); + emith_ctx_read_ptr(arg2, offsetof(SH2, write16_tab)); emith_sh2_wcall(arg0, arg2); #ifdef PDB_NET @@ -2962,7 +3053,7 @@ static void sh2_generate_utils(void) emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1])); \ emith_adc_r_imm(arg2, 0x01000000); \ emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \ - emith_move_r_r(arg2, CONTEXT_REG); \ + emith_move_r_r_ptr(arg2, CONTEXT_REG); \ emith_jump(func); \ func = tmp; \ } @@ -2992,13 +3083,12 @@ static void sh2_generate_utils(void) #endif } -static void sh2_smc_rm_block_entry(struct block_desc *bd, int tcache_id, u32 ram_mask) +static void sh2_smc_rm_block(struct block_desc *bd, int tcache_id, u32 ram_mask) { - struct block_link *bl, *bl_next, *bl_unresolved; u32 i, addr, end_addr; void *tmp; - dbg(2, " killing entry %08x-%08x-%08x, blkid %d,%d", + dbg(2, " killing block %08x-%08x-%08x, blkid %d,%d", bd->addr, bd->addr + bd->size_nolit, bd->addr + bd->size, tcache_id, bd - block_tables[tcache_id]); if (bd->addr == 0 || bd->entry_count == 0) { @@ -3015,7 +3105,6 @@ static void sh2_smc_rm_block_entry(struct block_desc *bd, int tcache_id, u32 ram } tmp = tcache_ptr; - bl_unresolved = unresolved_links[tcache_id]; // remove from hash table, make incoming links unresolved // XXX: maybe patch branches w/flush instead? @@ -3031,42 +3120,49 @@ static void sh2_smc_rm_block_entry(struct block_desc *bd, int tcache_id, u32 ram host_instructions_updated(bd->entryp[i].tcache_ptr, tcache_ptr); - for (bl = bd->entryp[i].links; bl != NULL; ) { - bl_next = bl->next; - bl->next = bl_unresolved; - bl_unresolved = bl; - bl = bl_next; - } + unregister_links(&bd->entryp[i], tcache_id); } tcache_ptr = tmp; - unresolved_links[tcache_id] = bl_unresolved; bd->addr = bd->size = bd->size_nolit = 0; bd->entry_count = 0; } -static void sh2_smc_rm_block(u32 a, u16 *drc_ram_blk, int tcache_id, u32 shift, u32 mask) +/* +04205:243: == msh2 block #0,200 060017a8-060017f0 -> 0x27cb9c + 060017a8 d11c MOV.L @($70,PC),R1 ; @$0600181c + +04230:261: msh2 xsh w32 [260017a8] d225e304 +04230:261: msh2 smc check @260017a8 +04239:226: = ssh2 enter 060017a8 0x27cb9c, c=173 +*/ +static void sh2_smc_rm_blocks(u32 a, u16 *drc_ram_blk, int tcache_id, u32 shift, u32 mask) { struct block_list **blist = NULL, *entry; - u32 from = ~0, to = 0, end_addr, taddr, i; struct block_desc *block; + u32 start_addr, end_addr, taddr, i; + u32 from = ~0, to = 0; + + // ignore cache-through + a &= ~0x20000000; blist = &inval_lookup[tcache_id][(a & mask) / INVAL_PAGE_SIZE]; entry = *blist; while (entry != NULL) { block = entry->block; - end_addr = block->addr + block->size; - if (block->addr <= a && a < end_addr) { + start_addr = block->addr & ~0x20000000; + end_addr = start_addr + block->size; + if (start_addr <= a && a < end_addr) { // get addr range that includes all removed blocks - if (from > block->addr) - from = block->addr; + if (from > start_addr) + from = start_addr; if (to < end_addr) to = end_addr; - sh2_smc_rm_block_entry(block, tcache_id, mask); - if (a >= block->addr + block->size_nolit) + if (a >= start_addr + block->size_nolit) literal_disabled_frames = 3; + sh2_smc_rm_block(block, tcache_id, mask); // entry lost, restart search entry = *blist; @@ -3088,12 +3184,13 @@ static void sh2_smc_rm_block(u32 a, u16 *drc_ram_blk, int tcache_id, u32 shift, for (; entry != NULL; entry = entry->next) { block = entry->block; - if (block->addr > a) { - if (to > block->addr) - to = block->addr; + start_addr = block->addr & ~0x20000000; + if (start_addr > a) { + if (to > start_addr) + to = start_addr; } else { - end_addr = block->addr + block->size; + end_addr = start_addr + block->size; if (from < end_addr) from = end_addr; } @@ -3110,13 +3207,13 @@ static void sh2_smc_rm_block(u32 a, u16 *drc_ram_blk, int tcache_id, u32 shift, void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid) { dbg(2, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a); - sh2_smc_rm_block(a, Pico32xMem->drcblk_ram, 0, SH2_DRCBLK_RAM_SHIFT, 0x3ffff); + sh2_smc_rm_blocks(a, Pico32xMem->drcblk_ram, 0, SH2_DRCBLK_RAM_SHIFT, 0x3ffff); } void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid) { dbg(2, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a); - sh2_smc_rm_block(a, Pico32xMem->drcblk_da[cpuid], + sh2_smc_rm_blocks(a, Pico32xMem->drcblk_da[cpuid], 1 + cpuid, SH2_DRCBLK_DA_SHIFT, 0xfff); } diff --git a/cpu/sh2/mame/sh2dasm.c b/cpu/sh2/mame/sh2dasm.c index 21a32e68..3fa25e92 100644 --- a/cpu/sh2/mame/sh2dasm.c +++ b/cpu/sh2/mame/sh2dasm.c @@ -610,6 +610,7 @@ unsigned DasmSH2(char *buffer, unsigned pc, UINT16 opcode) case 14: flags = op1110(buffer,pc,opcode); break; default: flags = op1111(buffer,pc,opcode); break; } + (void)flags; return 0;//2 | flags | DASMFLAG_SUPPORTED; } diff --git a/cpu/sh2/sh2.c b/cpu/sh2/sh2.c index 23b8fc0a..403c4c70 100644 --- a/cpu/sh2/sh2.c +++ b/cpu/sh2/sh2.c @@ -237,7 +237,7 @@ static void dump_regs(SH2 *sh2) printf("%csh2 SR: %03x PR: %08x\n", csh2, sh2->sr, sh2->pr); } -void do_sh2_cmp(SH2 *current) +void REGPARM(1) do_sh2_cmp(SH2 *current) { static int current_slave; static u32 current_val; @@ -251,6 +251,13 @@ void do_sh2_cmp(SH2 *current) int cycles; int i, ret; +#if 0 + sr = current->sr; + current->sr &= 0x3f3; + do_sh2_trace(current, (signed int)sr >> 12); + current->sr = sr; + return; +#endif sh2ref[1].is_slave = 1; while (1) { diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index e945354d..407270f1 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -118,7 +118,7 @@ void REGPARM(3) p32x_sh2_write32(unsigned int a, unsigned int d, SH2 *sh2); // debug #ifdef DRC_CMP void do_sh2_trace(SH2 *current, int cycles); -void do_sh2_cmp(SH2 *current); +void REGPARM(1) do_sh2_cmp(SH2 *current); #endif #endif /* __SH2_H__ */ diff --git a/pico/32x/32x.c b/pico/32x/32x.c index c10e1486..9bfbefac 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -422,6 +422,9 @@ void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target) } } +#define STEP_LS 24 +#define STEP_N 440 + #define sync_sh2s_normal p32x_sync_sh2s //#define sync_sh2s_lockstep p32x_sync_sh2s @@ -451,6 +454,8 @@ void sync_sh2s_normal(unsigned int m68k_target) target = m68k_target; if (event_time_next && CYCLES_GT(target, event_time_next)) target = event_time_next; + if (CYCLES_GT(target, now + STEP_N)) + target = now + STEP_N; while (CYCLES_GT(target, now)) { @@ -502,9 +507,10 @@ void sync_sh2s_normal(unsigned int m68k_target) if (CYCLES_GT(m68k_target, ssh2.m68krcycles_done)) ssh2.m68krcycles_done = m68k_target; } -} -#define STEP_68K 24 + // everyone is in sync now + Pico32x.comm_dirty = 0; +} void sync_sh2s_lockstep(unsigned int m68k_target) { @@ -515,7 +521,7 @@ void sync_sh2s_lockstep(unsigned int m68k_target) mcycles = ssh2.m68krcycles_done; while (mcycles < m68k_target) { - mcycles += STEP_68K; + mcycles += STEP_LS; sync_sh2s_normal(mcycles); } } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 399c8bd1..706d820e 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -191,12 +191,10 @@ static u32 p32x_reg_read16(u32 a) int comreg = 1 << (a & 0x0f) / 2; if (cycles - msh2.m68krcycles_done > 244 - || (Pico32x.comm_dirty_68k & comreg)) + || (Pico32x.comm_dirty & comreg)) p32x_sync_sh2s(cycles); - if (Pico32x.comm_dirty_sh2 & comreg) - Pico32x.comm_dirty_sh2 &= ~comreg; - else if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) { + if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) { SekSetStop(1); SekEndRun(16); } @@ -388,14 +386,13 @@ static void p32x_reg_write8(u32 a, u32 d) if (REG8IN16(r, a) == d) return; - comreg = 1 << (a & 0x0f) / 2; - if (Pico32x.comm_dirty_68k & comreg) - p32x_sync_sh2s(cycles); + p32x_sync_sh2s(cycles); REG8IN16(r, a) = d; p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles); p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles); - Pico32x.comm_dirty_68k |= comreg; + comreg = 1 << (a & 0x0f) / 2; + Pico32x.comm_dirty |= comreg; if (cycles - (int)msh2.m68krcycles_done > 120) p32x_sync_sh2s(cycles); @@ -451,20 +448,13 @@ static void p32x_reg_write16(u32 a, u32 d) int cycles = SekCyclesDone(); int comreg; - if (r[a / 2] == d) - return; - - comreg = 1 << (a & 0x0f) / 2; - if (Pico32x.comm_dirty_68k & comreg) - p32x_sync_sh2s(cycles); + p32x_sync_sh2s(cycles); r[a / 2] = d; p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles); p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles); - Pico32x.comm_dirty_68k |= comreg; - - if (cycles - (int)msh2.m68krcycles_done > 120) - p32x_sync_sh2s(cycles); + comreg = 1 << (a & 0x0f) / 2; + Pico32x.comm_dirty |= comreg; return; } // PWM @@ -601,11 +591,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) // comm port if ((a & 0x30) == 0x20) { - int comreg = 1 << (a & 0x0f) / 2; - if (Pico32x.comm_dirty_68k & comreg) - Pico32x.comm_dirty_68k &= ~comreg; - else - sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); + sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); sh2s_sync_on_read(sh2); return r[a / 2]; } @@ -708,7 +694,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, sh2_cycles_done_m68k(sh2)); comreg = 1 << (a & 0x0f) / 2; - Pico32x.comm_dirty_sh2 |= comreg; + Pico32x.comm_dirty |= comreg; return; } @@ -733,7 +719,7 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, sh2_cycles_done_m68k(sh2)); comreg = 1 << (a & 0x0f) / 2; - Pico32x.comm_dirty_sh2 |= comreg; + Pico32x.comm_dirty |= comreg; return; } // PWM @@ -1658,23 +1644,37 @@ static void get_bios(void) Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom)); } else { + static const u16 andb[] = { 0x0239, 0x00fe, 0x00a1, 0x5107 }; + static const u16 p_d4[] = { + 0x48e7, 0x8040, // movem.l d0/a1, -(sp) + 0x227c, 0x00a1, 0x30f1, // movea.l #0xa130f1, a1 + 0x7007, // moveq.l #7, d0 + 0x12d8, //0: move.b (a0)+, (a1)+ + 0x5289, // addq.l #1, a1 + 0x51c8, 0xfffa, // dbra d0, 0b + 0x0239, 0x00fe, 0x00a1, // and.b #0xfe, (0xa15107).l + 0x5107, + 0x4cdf, 0x0201 // movem.l (sp)+, d0/a1 + }; + // generate 68k ROM ps = (u16 *)Pico32xMem->m68k_rom; pl = (u32 *)ps; for (i = 1; i < 0xc0/4; i++) pl[i] = HWSWAP(0x880200 + (i - 1) * 6); + pl[0x70/4] = 0; // fill with nops for (i = 0xc0/2; i < 0x100/2; i++) ps[i] = 0x4e71; -#if 0 - ps[0xc0/2] = 0x46fc; - ps[0xc2/2] = 0x2700; // move #0x2700,sr - ps[0xfe/2] = 0x60fe; // jump to self -#else + // c0: don't need to care about RV - not emulated + ps[0xc8/2] = 0x1280; // move.b d0, (a1) + memcpy(ps + 0xca/2, andb, sizeof(andb)); // and.b #0xfe, (a15107) + ps[0xd2/2] = 0x4e75; // rts + // d4: + memcpy(ps + 0xd4/2, p_d4, sizeof(p_d4)); ps[0xfe/2] = 0x4e75; // rts -#endif } // fill remaining m68k_rom page with game ROM memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom), diff --git a/pico/cart.c b/pico/cart.c index 3148f36d..58a9a68f 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -391,8 +391,8 @@ int pm_seek(pm_file *stream, long offset, int whence) offset = pos; } - if (PicoMessage != NULL && offset > 4 * 1024 * 1024) - PicoMessage("Decompressing data..."); + if (PicoIn.osdMessage != NULL && offset > 4 * 1024 * 1024) + PicoIn.osdMessage("Decompressing data..."); while (offset > 0) { char buf[16 * 1024]; diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index 501d09e8..35edaa80 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -1297,8 +1297,8 @@ void cdd_process(void) set_reg16(0x3e, 0x0000); set_reg16(0x40, 0x000f); - if (PicoMCDcloseTray) - PicoMCDcloseTray(); + if (PicoIn.mcdTrayClose) + PicoIn.mcdTrayClose(); return; } @@ -1316,8 +1316,8 @@ void cdd_process(void) set_reg16(0x3e, 0x0000); set_reg16(0x40, ~CD_OPEN & 0x0f); - if (PicoMCDopenTray) - PicoMCDopenTray(); + if (PicoIn.mcdTrayOpen) + PicoIn.mcdTrayOpen(); return; } diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 51d9d403..5e3629a3 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -15,9 +15,6 @@ static unsigned int mcd_m68k_cycle_mult; static unsigned int mcd_m68k_cycle_base; static unsigned int mcd_s68k_cycle_base; -void (*PicoMCDopenTray)(void) = NULL; -void (*PicoMCDcloseTray)(void) = NULL; - PICO_INTERNAL void PicoInitMCD(void) { diff --git a/pico/debug.c b/pico/debug.c index d4fb575a..50cbaf38 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -387,14 +387,14 @@ void PDebugZ80Frame(void) if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) PicoSyncZ80(Pico.t.m68c_cnt + line_sample * 488); - if (PsndOut) + if (PicoIn.sndOut) PsndGetSamples(line_sample); if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) { PicoSyncZ80(Pico.t.m68c_cnt + 224 * 488); z80_int(); } - if (PsndOut) + if (PicoIn.sndOut) PsndGetSamples(224); // sync z80 @@ -402,7 +402,7 @@ void PDebugZ80Frame(void) Pico.t.m68c_cnt += Pico.m.pal ? 151809 : 127671; // cycles adjusted for converter PicoSyncZ80(Pico.t.m68c_cnt); } - if (PsndOut && ym2612.dacen && PsndDacLine < lines) + if (PicoIn.sndOut && ym2612.dacen && Pico.snd.dac_line < lines) PsndDoDAC(lines - 1); PsndDoPSG(lines - 1); diff --git a/pico/memory.c b/pico/memory.c index b49956e3..c633c89b 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -389,7 +389,7 @@ static int get_scanline(int is_from_z80); static void psg_write_68k(u32 d) { // look for volume write and update if needed - if ((d & 0x90) == 0x90 && PsndPsgLine < Pico.m.scanline) + if ((d & 0x90) == 0x90 && Pico.snd.psg_line < Pico.m.scanline) PsndDoPSG(Pico.m.scanline); SN76496Write(d); @@ -399,7 +399,7 @@ static void psg_write_z80(u32 d) { if ((d & 0x90) == 0x90) { int scanline = get_scanline(1); - if (PsndPsgLine < scanline) + if (Pico.snd.psg_line < scanline) PsndDoPSG(scanline); } @@ -895,41 +895,41 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) int xcycles = z80_cycles << 8; /* check for overflows */ - if ((mode_old & 4) && xcycles > timer_a_next_oflow) + if ((mode_old & 4) && xcycles > Pico.t.timer_a_next_oflow) ym2612.OPN.ST.status |= 1; - if ((mode_old & 8) && xcycles > timer_b_next_oflow) + if ((mode_old & 8) && xcycles > Pico.t.timer_b_next_oflow) ym2612.OPN.ST.status |= 2; /* update timer a */ if (mode_old & 1) - while (xcycles > timer_a_next_oflow) - timer_a_next_oflow += timer_a_step; + while (xcycles > Pico.t.timer_a_next_oflow) + Pico.t.timer_a_next_oflow += Pico.t.timer_a_step; if ((mode_old ^ mode_new) & 1) // turning on/off { if (mode_old & 1) - timer_a_next_oflow = TIMER_NO_OFLOW; + Pico.t.timer_a_next_oflow = TIMER_NO_OFLOW; else - timer_a_next_oflow = xcycles + timer_a_step; + Pico.t.timer_a_next_oflow = xcycles + Pico.t.timer_a_step; } if (mode_new & 1) - elprintf(EL_YMTIMER, "timer a upd to %i @ %i", timer_a_next_oflow>>8, z80_cycles); + elprintf(EL_YMTIMER, "timer a upd to %i @ %i", Pico.t.timer_a_next_oflow>>8, z80_cycles); /* update timer b */ if (mode_old & 2) - while (xcycles > timer_b_next_oflow) - timer_b_next_oflow += timer_b_step; + while (xcycles > Pico.t.timer_b_next_oflow) + Pico.t.timer_b_next_oflow += Pico.t.timer_b_step; if ((mode_old ^ mode_new) & 2) { if (mode_old & 2) - timer_b_next_oflow = TIMER_NO_OFLOW; + Pico.t.timer_b_next_oflow = TIMER_NO_OFLOW; else - timer_b_next_oflow = xcycles + timer_b_step; + Pico.t.timer_b_next_oflow = xcycles + Pico.t.timer_b_step; } if (mode_new & 2) - elprintf(EL_YMTIMER, "timer b upd to %i @ %i", timer_b_next_oflow>>8, z80_cycles); + elprintf(EL_YMTIMER, "timer b upd to %i @ %i", Pico.t.timer_b_next_oflow>>8, z80_cycles); } // ym2612 DAC and timer I/O handlers for z80 @@ -941,7 +941,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) if (a == 1 && ym2612.OPN.ST.address == 0x2a) /* DAC data */ { int scanline = get_scanline(is_from_z80); - //elprintf(EL_STATUS, "%03i -> %03i dac w %08x z80 %i", PsndDacLine, scanline, d, is_from_z80); + //elprintf(EL_STATUS, "%03i -> %03i dac w %08x z80 %i", Pico.snd.dac_line, scanline, d, is_from_z80); ym2612.dacout = ((int)d - 0x80) << 6; if (ym2612.dacen) PsndDoDAC(scanline); @@ -977,13 +977,13 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) ym2612.OPN.ST.TA = TAnew; //ym2612.OPN.ST.TAC = (1024-TAnew)*18; //ym2612.OPN.ST.TAT = 0; - timer_a_step = TIMER_A_TICK_ZCYCLES * (1024 - TAnew); + Pico.t.timer_a_step = TIMER_A_TICK_ZCYCLES * (1024 - TAnew); if (ym2612.OPN.ST.mode & 1) { // this is not right, should really be done on overflow only int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); - timer_a_next_oflow = (cycles << 8) + timer_a_step; + Pico.t.timer_a_next_oflow = (cycles << 8) + Pico.t.timer_a_step; } - elprintf(EL_YMTIMER, "timer a set to %i, %i", 1024 - TAnew, timer_a_next_oflow>>8); + elprintf(EL_YMTIMER, "timer a set to %i, %i", 1024 - TAnew, Pico.t.timer_a_next_oflow>>8); } return 0; } @@ -993,12 +993,12 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) ym2612.OPN.ST.TB = d; //ym2612.OPN.ST.TBC = (256-d) * 288; //ym2612.OPN.ST.TBT = 0; - timer_b_step = TIMER_B_TICK_ZCYCLES * (256 - d); // 262800 + Pico.t.timer_b_step = TIMER_B_TICK_ZCYCLES * (256 - d); // 262800 if (ym2612.OPN.ST.mode & 2) { int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); - timer_b_next_oflow = (cycles << 8) + timer_b_step; + Pico.t.timer_b_next_oflow = (cycles << 8) + Pico.t.timer_b_step; } - elprintf(EL_YMTIMER, "timer b set to %i, %i", 256 - d, timer_b_next_oflow>>8); + elprintf(EL_YMTIMER, "timer b set to %i, %i", 256 - d, Pico.t.timer_b_next_oflow>>8); } return 0; case 0x27: { /* mode, timer control */ @@ -1029,7 +1029,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) int scanline = get_scanline(is_from_z80); if (ym2612.dacen != (d & 0x80)) { ym2612.dacen = d & 0x80; - PsndDacLine = scanline; + Pico.snd.dac_line = scanline; } #ifdef __GP2X__ if (PicoIn.opt & POPT_EXT_FM) YM2612Write_940(a, d, scanline); @@ -1065,9 +1065,9 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) #define ym2612_read_local() \ - if (xcycles >= timer_a_next_oflow) \ + if (xcycles >= Pico.t.timer_a_next_oflow) \ ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 1; \ - if (xcycles >= timer_b_next_oflow) \ + if (xcycles >= Pico.t.timer_b_next_oflow) \ ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 2 static u32 ym2612_read_local_z80(void) @@ -1076,8 +1076,9 @@ static u32 ym2612_read_local_z80(void) ym2612_read_local(); - elprintf(EL_YMTIMER, "timer z80 read %i, sched %i, %i @ %i|%i", ym2612.OPN.ST.status, - timer_a_next_oflow>>8, timer_b_next_oflow>>8, xcycles >> 8, (xcycles >> 8) / 228); + elprintf(EL_YMTIMER, "timer z80 read %i, sched %i, %i @ %i|%i", + ym2612.OPN.ST.status, Pico.t.timer_a_next_oflow >> 8, + Pico.t.timer_b_next_oflow >> 8, xcycles >> 8, (xcycles >> 8) / 228); return ym2612.OPN.ST.status; } @@ -1087,8 +1088,9 @@ static u32 ym2612_read_local_68k(void) ym2612_read_local(); - elprintf(EL_YMTIMER, "timer 68k read %i, sched %i, %i @ %i|%i", ym2612.OPN.ST.status, - timer_a_next_oflow>>8, timer_b_next_oflow>>8, xcycles >> 8, (xcycles >> 8) / 228); + elprintf(EL_YMTIMER, "timer 68k read %i, sched %i, %i @ %i|%i", + ym2612.OPN.ST.status, Pico.t.timer_a_next_oflow >> 8, + Pico.t.timer_b_next_oflow >> 8, xcycles >> 8, (xcycles >> 8) / 228); return ym2612.OPN.ST.status; } @@ -1098,10 +1100,12 @@ void ym2612_pack_state(void) int tac, tat = 0, tbc, tbt = 0; tac = 1024 - ym2612.OPN.ST.TA; tbc = 256 - ym2612.OPN.ST.TB; - if (timer_a_next_oflow != TIMER_NO_OFLOW) - tat = (int)((double)(timer_a_step - timer_a_next_oflow) / (double)timer_a_step * tac * 65536); - if (timer_b_next_oflow != TIMER_NO_OFLOW) - tbt = (int)((double)(timer_b_step - timer_b_next_oflow) / (double)timer_b_step * tbc * 65536); + if (Pico.t.timer_a_next_oflow != TIMER_NO_OFLOW) + tat = (int)((double)(Pico.t.timer_a_step - Pico.t.timer_a_next_oflow) + / (double)Pico.t.timer_a_step * tac * 65536); + if (Pico.t.timer_b_next_oflow != TIMER_NO_OFLOW) + tbt = (int)((double)(Pico.t.timer_b_step - Pico.t.timer_b_next_oflow) + / (double)Pico.t.timer_b_step * tbc * 65536); elprintf(EL_YMTIMER, "save: timer a %i/%i", tat >> 16, tac); elprintf(EL_YMTIMER, "save: timer b %i/%i", tbt >> 16, tbc); @@ -1154,15 +1158,15 @@ void ym2612_unpack_state(void) tac = (1024 - ym2612.OPN.ST.TA) << 16; tbc = (256 - ym2612.OPN.ST.TB) << 16; if (ym2612.OPN.ST.mode & 1) - timer_a_next_oflow = (int)((double)(tac - tat) / (double)tac * timer_a_step); + Pico.t.timer_a_next_oflow = (int)((double)(tac - tat) / (double)tac * Pico.t.timer_a_step); else - timer_a_next_oflow = TIMER_NO_OFLOW; + Pico.t.timer_a_next_oflow = TIMER_NO_OFLOW; if (ym2612.OPN.ST.mode & 2) - timer_b_next_oflow = (int)((double)(tbc - tbt) / (double)tbc * timer_b_step); + Pico.t.timer_b_next_oflow = (int)((double)(tbc - tbt) / (double)tbc * Pico.t.timer_b_step); else - timer_b_next_oflow = TIMER_NO_OFLOW; - elprintf(EL_YMTIMER, "load: %i/%i, timer_a_next_oflow %i", tat>>16, tac>>16, timer_a_next_oflow >> 8); - elprintf(EL_YMTIMER, "load: %i/%i, timer_b_next_oflow %i", tbt>>16, tbc>>16, timer_b_next_oflow >> 8); + Pico.t.timer_b_next_oflow = TIMER_NO_OFLOW; + elprintf(EL_YMTIMER, "load: %i/%i, timer_a_next_oflow %i", tat>>16, tac>>16, Pico.t.timer_a_next_oflow >> 8); + elprintf(EL_YMTIMER, "load: %i/%i, timer_b_next_oflow %i", tbt>>16, tbc>>16, Pico.t.timer_b_next_oflow >> 8); } #if defined(NO_32X) && defined(_ASM_MEMORY_C) diff --git a/pico/pico.c b/pico/pico.c index 76c5fe92..f6b43cd6 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -14,7 +14,6 @@ struct Pico Pico; struct PicoMem PicoMem; PicoInterface PicoIn; -void (*PicoWriteSound)(int len) = NULL; // called at the best time to send sound buffer (PsndOut) to hardware void (*PicoResetHook)(void) = NULL; void (*PicoLineHook)(void) = NULL; @@ -344,6 +343,4 @@ void PicoGetInternal(pint_t which, pint_ret_t *r) } } -// callback to output message from emu -void (*PicoMessage)(const char *msg)=NULL; - +// vim:ts=2:sw=2:expandtab diff --git a/pico/pico.h b/pico/pico.h index 2d63d184..f22ef606 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -97,6 +97,15 @@ typedef struct unsigned short quirks; // game-specific quirks: PQUIRK_* unsigned short overclockM68k; // overclock the emulated 68k, in % + + int sndRate; // rate in Hz + short *sndOut; // PCM output buffer + void (*writeSound)(int len); // write .sndOut callback, called once per frame + + void (*osdMessage)(const char *msg); // output OSD message from emu, optional + + void (*mcdTrayOpen)(void); + void (*mcdTrayClose)(void); } PicoInterface; extern PicoInterface PicoIn; @@ -108,18 +117,12 @@ int PicoReset(void); void PicoLoopPrepare(void); void PicoFrame(void); void PicoFrameDrawOnly(void); -extern void (*PicoWriteSound)(int bytes); // called once per frame at the best time to send sound buffer (PsndOut) to hardware -extern void (*PicoMessage)(const char *msg); // callback to output text message from emu typedef enum { PI_ROM, PI_ISPAL, PI_IS40_CELL, PI_IS240_LINES } pint_t; typedef union { int vint; void *vptr; } pint_ret_t; void PicoGetInternal(pint_t which, pint_ret_t *ret); struct PicoEState; -// cd/mcd.c -extern void (*PicoMCDopenTray)(void); -extern void (*PicoMCDcloseTray)(void); - // pico.c #define XPCM_BUFFER_SIZE (320+160) typedef struct @@ -230,8 +233,6 @@ void Pico32xSetClocks(int msh2_hz, int ssh2_hz); #define PICO_SSH2_HZ ((int)(7670442.0 * 2.4)) // sound.c -extern int PsndRate,PsndLen; -extern short *PsndOut; extern void (*PsndMix_32_to_16l)(short *dest, int *src, int count); void PsndRerate(int preserve_state); diff --git a/pico/pico/xpcm.c b/pico/pico/xpcm.c index 0109dcf9..ee204464 100644 --- a/pico/pico/xpcm.c +++ b/pico/pico/xpcm.c @@ -50,7 +50,7 @@ PICO_INTERNAL void PicoPicoPCMReset(void) PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate) { - stepsamples = (PsndRate<<10)/xpcm_rate; + stepsamples = (PicoIn.sndRate<<10)/xpcm_rate; } #define XSHIFT 6 diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index fc12a767..95b6b103 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -153,7 +153,7 @@ static int PicoFrameHints(void) } // get samples from sound chips - if ((y == 224 || y == line_sample) && PsndOut) + if ((y == 224 || y == line_sample) && PicoIn.sndOut) { cycles = SekCyclesDone(); @@ -241,7 +241,7 @@ static int PicoFrameHints(void) #endif // get samples from sound chips - if (y == 224 && PsndOut) + if (y == 224 && PicoIn.sndOut) PsndGetSamples(y); // Run scanline: @@ -324,9 +324,9 @@ static int PicoFrameHints(void) cycles = SekCyclesDone(); if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) PicoSyncZ80(cycles); - if (PsndOut && ym2612.dacen && PsndDacLine < lines) + if (PicoIn.sndOut && ym2612.dacen && Pico.snd.dac_line < lines) PsndDoDAC(lines - 1); - if (PsndOut && PsndPsgLine < lines) + if (PicoIn.sndOut && Pico.snd.psg_line < lines) PsndDoPSG(lines - 1); #ifdef PICO_CD diff --git a/pico/pico_int.h b/pico/pico_int.h index fa7979cc..0b50e4b9 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -409,6 +409,19 @@ struct PicoTiming unsigned int z80c_cnt; // z80 cycles done (this frame) unsigned int z80c_aim; int z80_scanline; + + int timer_a_next_oflow, timer_a_step; // in z80 cycles + int timer_b_next_oflow, timer_b_step; +}; + +struct PicoSound +{ + short len; // number of mono samples + short len_use; // adjusted + int len_e_add; // for non-int samples/frame + int len_e_cnt; + short dac_line; + short psg_line; }; // run tools/mkoffsets pico/pico_int_o32.h if you change these @@ -419,6 +432,7 @@ struct Pico struct PicoMisc m; struct PicoTiming t; struct PicoCartSave sv; + struct PicoSound snd; struct PicoEState est; struct PicoMS ms; @@ -568,8 +582,8 @@ struct Pico32x unsigned int dmac0_fifo_ptr; unsigned short vdp_fbcr_fake; unsigned short pad2; - unsigned char comm_dirty_68k; - unsigned char comm_dirty_sh2; + unsigned char comm_dirty; + unsigned char pad3; // was comm_dirty_sh2 unsigned char pwm_irq_cnt; unsigned char pad1; unsigned short pwm_p[2]; // pwm pos in fifo @@ -781,10 +795,6 @@ void SekInterruptClearS68k(int irq); // sound/sound.c extern short cdda_out_buffer[2*1152]; -extern int PsndLen_exc_cnt; -extern int PsndLen_exc_add; -extern int timer_a_next_oflow, timer_a_step; // in z80 cycles -extern int timer_b_next_oflow, timer_b_step; void cdda_start_play(int lba_base, int lba_offset, int lb_len); @@ -799,16 +809,16 @@ void ym2612_unpack_state(void); #define TIMER_B_TICK_ZCYCLES 262800 // 275251 broken, see Dai Makaimura #define timers_cycle() \ - if (timer_a_next_oflow > 0 && timer_a_next_oflow < TIMER_NO_OFLOW) \ - timer_a_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \ - if (timer_b_next_oflow > 0 && timer_b_next_oflow < TIMER_NO_OFLOW) \ - timer_b_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \ + if (Pico.t.timer_a_next_oflow > 0 && Pico.t.timer_a_next_oflow < TIMER_NO_OFLOW) \ + Pico.t.timer_a_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \ + if (Pico.t.timer_b_next_oflow > 0 && Pico.t.timer_b_next_oflow < TIMER_NO_OFLOW) \ + Pico.t.timer_b_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \ ym2612_sync_timers(0, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); #define timers_reset() \ - timer_a_next_oflow = timer_b_next_oflow = TIMER_NO_OFLOW; \ - timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \ - timer_b_step = TIMER_B_TICK_ZCYCLES * 256; + Pico.t.timer_a_next_oflow = Pico.t.timer_b_next_oflow = TIMER_NO_OFLOW; \ + Pico.t.timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \ + Pico.t.timer_b_step = TIMER_B_TICK_ZCYCLES * 256; // videoport.c @@ -850,7 +860,6 @@ PICO_INTERNAL void PsndDoPSG(int line_to); PICO_INTERNAL void PsndClear(void); PICO_INTERNAL void PsndGetSamples(int y); PICO_INTERNAL void PsndGetSamplesMS(void); -extern int PsndDacLine, PsndPsgLine; // sms.c #ifndef NO_SMS @@ -974,7 +983,7 @@ static __inline int isspace_(int c) // emulation event logging #ifndef EL_LOGMASK # ifdef __x86_64__ // HACK -# define EL_LOGMASK (EL_STATUS|EL_IDLE|EL_ANOMALY) +# define EL_LOGMASK (EL_STATUS|EL_ANOMALY) # else # define EL_LOGMASK (EL_STATUS) # endif diff --git a/pico/pico_int_o32.h b/pico/pico_int_o32.h index ca3004f3..25c64f43 100644 --- a/pico/pico_int_o32.h +++ b/pico/pico_int_o32.h @@ -6,13 +6,13 @@ #define OFS_Pico_m_hardware 0x0047 #define OFS_Pico_m_z80_reset 0x004f #define OFS_Pico_m_sram_reg 0x0049 -#define OFS_Pico_sv 0x007c -#define OFS_Pico_sv_data 0x007c -#define OFS_Pico_sv_start 0x0080 -#define OFS_Pico_sv_end 0x0084 -#define OFS_Pico_sv_flags 0x0088 -#define OFS_Pico_rom 0x031c -#define OFS_Pico_romsize 0x0320 +#define OFS_Pico_sv 0x008c +#define OFS_Pico_sv_data 0x008c +#define OFS_Pico_sv_start 0x0090 +#define OFS_Pico_sv_end 0x0094 +#define OFS_Pico_sv_flags 0x0098 +#define OFS_Pico_rom 0x033c +#define OFS_Pico_romsize 0x0340 #define OFS_EST_DrawScanline 0x00 #define OFS_EST_rendstatus 0x04 #define OFS_EST_DrawLineDest 0x08 diff --git a/pico/sms.c b/pico/sms.c index 748c3265..ac81c2b2 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -8,10 +8,8 @@ /* * TODO: * - start in a state as if BIOS ran - * - remaining status flags (OVR/COL) * - RAM support in mapper * - region support - * - SN76496 DAC-like usage * - H counter */ #include "pico_int.h" @@ -133,8 +131,9 @@ static void z80_sms_out(unsigned short a, unsigned char d) case 0x40: case 0x41: - if (PicoIn.opt & POPT_EN_PSG) - SN76496Write(d); + if ((d & 0x90) == 0x90 && Pico.snd.psg_line < Pico.m.scanline) + PsndDoPSG(Pico.m.scanline); + SN76496Write(d); break; case 0x80: @@ -300,12 +299,16 @@ void PicoFrameMS(void) } } + // 224 because of how it's done for MD... + if (y == 224 && PicoIn.sndOut) + PsndGetSamplesMS(); + cycles_aim += cycles_line; cycles_done += z80_run((cycles_aim - cycles_done) >> 8) << 8; } - if (PsndOut) - PsndGetSamplesMS(); + if (PicoIn.sndOut && Pico.snd.psg_line < lines) + PsndDoPSG(lines - 1); } void PicoFrameDrawOnlyMS(void) @@ -319,3 +322,4 @@ void PicoFrameDrawOnlyMS(void) PicoLineMode4(y); } +// vim:ts=2:sw=2:expandtab diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 56ffe3f8..fc71b741 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -25,31 +25,20 @@ static unsigned short dac_info[312+4]; // pos in sample buffer // cdda output buffer short cdda_out_buffer[2*1152]; -// for Pico -int PsndRate=0; -int PsndLen=0; // number of mono samples, multiply by 2 for stereo -int PsndLen_exc_add=0; // this is for non-integer sample counts per line, eg. 22050/60 -int PsndLen_exc_cnt=0; -int PsndDacLine, PsndPsgLine; -short *PsndOut=NULL; // PCM data buffer -static int PsndLen_use; - -// timers -int timer_a_next_oflow, timer_a_step; // in z80 cycles -int timer_b_next_oflow, timer_b_step; - // sn76496 extern int *sn76496_regs; static void dac_recalculate(void) { - int i, dac_cnt, pos, len, lines = Pico.m.pal ? 313 : 262, mid = Pico.m.pal ? 68 : 93; + int lines = Pico.m.pal ? 313 : 262; + int mid = Pico.m.pal ? 68 : 93; + int i, dac_cnt, pos, len; - if (PsndLen <= lines) + if (Pico.snd.len <= lines) { // shrinking algo - dac_cnt = -PsndLen; + dac_cnt = -Pico.snd.len; len=1; pos=0; dac_info[225] = 1; @@ -60,14 +49,14 @@ static void dac_recalculate(void) pos++; dac_cnt += lines; } - dac_cnt -= PsndLen; + dac_cnt -= Pico.snd.len; dac_info[i] = pos; } } else { // stretching - dac_cnt = PsndLen; + dac_cnt = Pico.snd.len; pos=0; for(i = 225; i != 224; i++) { @@ -78,11 +67,11 @@ static void dac_recalculate(void) len++; } if (i == mid) // midpoint - while(pos+len < PsndLen/2) { + while(pos+len < Pico.snd.len/2) { dac_cnt -= lines; len++; } - dac_cnt += PsndLen; + dac_cnt += Pico.snd.len; pos += len; dac_info[i] = pos; } @@ -112,7 +101,7 @@ void PsndRerate(int preserve_state) ym2612_pack_state(); memcpy(state, YM2612GetRegs(), 0x204); } - YM2612Init(Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7, PsndRate); + YM2612Init(Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7, PicoIn.sndRate); if (preserve_state) { // feed it back it's own registers, just like after loading state memcpy(YM2612GetRegs(), state, 0x204); @@ -120,16 +109,16 @@ void PsndRerate(int preserve_state) } if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state - SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PsndRate); + SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate); if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state if (state) free(state); - // calculate PsndLen - PsndLen=PsndRate / target_fps; - PsndLen_exc_add=((PsndRate - PsndLen*target_fps)<<16) / target_fps; - PsndLen_exc_cnt=0; + // calculate Pico.snd.len + Pico.snd.len = PicoIn.sndRate / target_fps; + Pico.snd.len_e_add = ((PicoIn.sndRate - Pico.snd.len * target_fps) << 16) / target_fps; + Pico.snd.len_e_cnt = 0; // recalculate dac info dac_recalculate(); @@ -137,7 +126,7 @@ void PsndRerate(int preserve_state) // clear all buffers memset32(PsndBuffer, 0, sizeof(PsndBuffer)/4); memset(cdda_out_buffer, 0, sizeof(cdda_out_buffer)); - if (PsndOut) + if (PicoIn.sndOut) PsndClear(); // set mixer @@ -150,24 +139,24 @@ void PsndRerate(int preserve_state) PICO_INTERNAL void PsndStartFrame(void) { - // compensate for float part of PsndLen - PsndLen_use = PsndLen; - PsndLen_exc_cnt += PsndLen_exc_add; - if (PsndLen_exc_cnt >= 0x10000) { - PsndLen_exc_cnt -= 0x10000; - PsndLen_use++; + // compensate for float part of Pico.snd.len + Pico.snd.len_use = Pico.snd.len; + Pico.snd.len_e_cnt += Pico.snd.len_e_add; + if (Pico.snd.len_e_cnt >= 0x10000) { + Pico.snd.len_e_cnt -= 0x10000; + Pico.snd.len_use++; } - PsndDacLine = PsndPsgLine = 0; + Pico.snd.dac_line = Pico.snd.psg_line = 0; Pico.m.status &= ~1; - dac_info[224] = PsndLen_use; + dac_info[224] = Pico.snd.len_use; } PICO_INTERNAL void PsndDoDAC(int line_to) { int pos, pos1, len; int dout = ym2612.dacout; - int line_from = PsndDacLine; + int line_from = Pico.snd.dac_line; if (line_to >= 313) line_to = 312; @@ -178,23 +167,23 @@ PICO_INTERNAL void PsndDoDAC(int line_to) if (len <= 0) return; - PsndDacLine = line_to + 1; + Pico.snd.dac_line = line_to + 1; - if (!PsndOut) + if (!PicoIn.sndOut) return; if (PicoIn.opt & POPT_EN_STEREO) { - short *d = PsndOut + pos*2; + short *d = PicoIn.sndOut + pos*2; for (; len > 0; len--, d+=2) *d += dout; } else { - short *d = PsndOut + pos; + short *d = PicoIn.sndOut + pos; for (; len > 0; len--, d++) *d += dout; } } PICO_INTERNAL void PsndDoPSG(int line_to) { - int line_from = PsndPsgLine; + int line_from = Pico.snd.psg_line; int pos, pos1, len; int stereo = 0; @@ -209,16 +198,16 @@ PICO_INTERNAL void PsndDoPSG(int line_to) if (len <= 0) return; - PsndPsgLine = line_to + 1; + Pico.snd.psg_line = line_to + 1; - if (!PsndOut || !(PicoIn.opt & POPT_EN_PSG)) + if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_PSG)) return; if (PicoIn.opt & POPT_EN_STEREO) { stereo = 1; pos <<= 1; } - SN76496Update(PsndOut + pos, len, stereo); + SN76496Update(PicoIn.sndOut + pos, len, stereo); } // cdda @@ -227,8 +216,8 @@ static void cdda_raw_update(int *buffer, int length) int ret, cdda_bytes, mult = 1; cdda_bytes = length*4; - if (PsndRate <= 22050 + 100) mult = 2; - if (PsndRate < 22050 - 100) mult = 4; + if (PicoIn.sndRate <= 22050 + 100) mult = 2; + if (PicoIn.sndRate < 22050 - 100) mult = 4; cdda_bytes *= mult; ret = pm_read(cdda_out_buffer, cdda_bytes, Pico_mcd->cdda_stream); @@ -270,12 +259,12 @@ void cdda_start_play(int lba_base, int lba_offset, int lb_len) PICO_INTERNAL void PsndClear(void) { - int len = PsndLen; - if (PsndLen_exc_add) len++; + int len = Pico.snd.len; + if (Pico.snd.len_e_add) len++; if (PicoIn.opt & POPT_EN_STEREO) - memset32((int *) PsndOut, 0, len); // assume PsndOut to be aligned + memset32((int *) PicoIn.sndOut, 0, len); // assume PicoIn.sndOut to be aligned else { - short *out = PsndOut; + short *out = PicoIn.sndOut; if ((long)out & 2) { *out++ = 0; len--; } memset32((int *) out, 0, len/2); if (len & 1) out[len-1] = 0; @@ -294,7 +283,7 @@ static int PsndRender(int offset, int length) pprof_start(sound); if (PicoIn.AHW & PAHW_PICO) { - PicoPicoPCMUpdate(PsndOut+offset, length, stereo); + PicoPicoPCMUpdate(PicoIn.sndOut+offset, length, stereo); return length; } @@ -330,7 +319,7 @@ static int PsndRender(int offset, int length) p32x_pwm_update(buf32, length, stereo); // convert + limit to normal 16bit output - PsndMix_32_to_16l(PsndOut+offset, buf32, length); + PsndMix_32_to_16l(PicoIn.sndOut+offset, buf32, length); pprof_end(sound); @@ -342,51 +331,50 @@ PICO_INTERNAL void PsndGetSamples(int y) { static int curr_pos = 0; - if (ym2612.dacen && PsndDacLine < y) + if (ym2612.dacen && Pico.snd.dac_line < y) PsndDoDAC(y - 1); PsndDoPSG(y - 1); if (y == 224) { if (Pico.m.status & 2) - curr_pos += PsndRender(curr_pos, PsndLen-PsndLen/2); - else curr_pos = PsndRender(0, PsndLen_use); + curr_pos += PsndRender(curr_pos, Pico.snd.len-Pico.snd.len/2); + else curr_pos = PsndRender(0, Pico.snd.len_use); if (Pico.m.status & 1) Pico.m.status |= 2; else Pico.m.status &= ~2; - if (PicoWriteSound) - PicoWriteSound(curr_pos * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2)); + if (PicoIn.writeSound) + PicoIn.writeSound(curr_pos * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2)); // clear sound buffer PsndClear(); - PsndDacLine = 224; + Pico.snd.dac_line = 224; dac_info[224] = 0; } else if (Pico.m.status & 3) { Pico.m.status |= 2; Pico.m.status &= ~1; - curr_pos = PsndRender(0, PsndLen/2); + curr_pos = PsndRender(0, Pico.snd.len/2); } } PICO_INTERNAL void PsndGetSamplesMS(void) { - int stereo = (PicoIn.opt & 8) >> 3; - int length = PsndLen_use; + int length = Pico.snd.len_use; - // PSG - if (PicoIn.opt & POPT_EN_PSG) - SN76496Update(PsndOut, length, stereo); + PsndDoPSG(223); // upmix to "stereo" if needed - if (stereo) { + if (PicoIn.opt & POPT_EN_STEREO) { int i, *p; - for (i = length, p = (void *)PsndOut; i > 0; i--, p++) + for (i = length, p = (void *)PicoIn.sndOut; i > 0; i--, p++) *p |= *p << 16; } - if (PicoWriteSound != NULL) - PicoWriteSound(length * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2)); + if (PicoIn.writeSound != NULL) + PicoIn.writeSound(length * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2)); PsndClear(); + + dac_info[224] = 0; } // vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/state.c b/pico/state.c index 100f4237..5092ddcb 100644 --- a/pico/state.c +++ b/pico/state.c @@ -227,6 +227,9 @@ static int state_save(void *file) areaWrite(&ver, 1, 4, file); if (!(PicoIn.AHW & PAHW_SMS)) { + // the patches can cause incompatible saves with no-idle + SekFinishIdleDet(); + memset(buff, 0, sizeof(buff)); SekPackCpu(buff, 0); CHECKED_WRITE_BUFF(CHUNK_M68K, buff); @@ -235,6 +238,9 @@ static int state_save(void *file) CHECKED_WRITE_BUFF(CHUNK_IOPORTS, PicoMem.ioports); ym2612_pack_state(); CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs); + + if (!(PicoIn.opt & POPT_DIS_IDLE_DET)) + SekInitIdleDet(); } else { CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms); diff --git a/platform/common/config_file.c b/platform/common/config_file.c index 2d1186d7..1b5c5172 100644 --- a/platform/common/config_file.c +++ b/platform/common/config_file.c @@ -259,9 +259,9 @@ static int custom_read(menu_entry *me, const char *var, const char *val) case MA_OPT_SOUND_QUALITY: if (strcasecmp(var, "Sound Quality") != 0) return 0; - PsndRate = strtoul(val, &tmp, 10); - if (PsndRate < 8000 || PsndRate > 44100) - PsndRate = 22050; + PicoIn.sndRate = strtoul(val, &tmp, 10); + if (PicoIn.sndRate < 8000 || PicoIn.sndRate > 44100) + PicoIn.sndRate = 22050; if (*tmp == 'H' || *tmp == 'h') tmp++; if (*tmp == 'Z' || *tmp == 'z') tmp++; while (*tmp == ' ') tmp++; diff --git a/platform/common/emu.c b/platform/common/emu.c index 407ed599..b4db4c67 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -604,7 +604,7 @@ void emu_set_defconfig(void) { memcpy(¤tConfig, &defaultConfig, sizeof(currentConfig)); PicoIn.opt = currentConfig.s_PicoOpt; - PsndRate = currentConfig.s_PsndRate; + PicoIn.sndRate = currentConfig.s_PsndRate; PicoIn.regionOverride = currentConfig.s_PicoRegion; PicoIn.autoRgnOrder = currentConfig.s_PicoAutoRgnOrder; } @@ -958,10 +958,10 @@ void emu_set_fastforward(int set_on) static int set_Frameskip, set_EmuOpt, is_on = 0; if (set_on && !is_on) { - set_PsndOut = PsndOut; + set_PsndOut = PicoIn.sndOut; set_Frameskip = currentConfig.Frameskip; set_EmuOpt = currentConfig.EmuOpt; - PsndOut = NULL; + PicoIn.sndOut = NULL; currentConfig.Frameskip = 8; currentConfig.EmuOpt &= ~4; currentConfig.EmuOpt |= 0x40000; @@ -969,7 +969,7 @@ void emu_set_fastforward(int set_on) emu_status_msg("FAST FORWARD"); } else if (!set_on && is_on) { - PsndOut = set_PsndOut; + PicoIn.sndOut = set_PsndOut; currentConfig.Frameskip = set_Frameskip; currentConfig.EmuOpt = set_EmuOpt; PsndRerate(1); @@ -1253,9 +1253,9 @@ void emu_init(void) config_readlrom(path); PicoInit(); - PicoMessage = plat_status_msg_busy_next; - PicoMCDopenTray = emu_tray_open; - PicoMCDcloseTray = emu_tray_close; + PicoIn.osdMessage = plat_status_msg_busy_next; + PicoIn.mcdTrayOpen = emu_tray_open; + PicoIn.mcdTrayClose = emu_tray_close; sndout_init(); } @@ -1285,12 +1285,12 @@ void emu_finish(void) static void snd_write_nonblocking(int len) { - sndout_write_nb(PsndOut, len); + sndout_write_nb(PicoIn.sndOut, len); } void emu_sound_start(void) { - PsndOut = NULL; + PicoIn.sndOut = NULL; if (currentConfig.EmuOpt & EOPT_EN_SOUND) { @@ -1299,12 +1299,12 @@ void emu_sound_start(void) PsndRerate(Pico.m.frame_count ? 1 : 0); printf("starting audio: %i len: %i stereo: %i, pal: %i\n", - PsndRate, PsndLen, is_stereo, Pico.m.pal); - sndout_start(PsndRate, is_stereo); - PicoWriteSound = snd_write_nonblocking; + PicoIn.sndRate, Pico.snd.len, is_stereo, Pico.m.pal); + sndout_start(PicoIn.sndRate, is_stereo); + PicoIn.writeSound = snd_write_nonblocking; plat_update_volume(0, 0); memset(sndBuffer, 0, sizeof(sndBuffer)); - PsndOut = sndBuffer; + PicoIn.sndOut = sndBuffer; } } diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 1d73d4a7..969fc8e2 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -610,7 +610,7 @@ static int mh_opt_misc(int id, int keys) { switch (id) { case MA_OPT_SOUND_QUALITY: - PsndRate = sndrate_prevnext(PsndRate, keys & PBTN_RIGHT); + PicoIn.sndRate = sndrate_prevnext(PicoIn.sndRate, keys & PBTN_RIGHT); break; case MA_OPT_REGION: region_prevnext(keys & PBTN_RIGHT); @@ -674,7 +674,7 @@ static const char *mgn_opt_sound(int id, int *offs) const char *str2; *offs = -8; str2 = (PicoIn.opt & POPT_EN_STEREO) ? "stereo" : "mono"; - sprintf(static_buff, "%5iHz %s", PsndRate, str2); + sprintf(static_buff, "%5iHz %s", PicoIn.sndRate, str2); return static_buff; } @@ -892,7 +892,7 @@ static void debug_menu_loop(void) if (inp & PBTN_UP) pv->debug_p ^= PVD_KILL_S_HI; if (inp & PBTN_MA2) pv->debug_p ^= PVD_KILL_32X; if (inp & PBTN_MOK) { - PsndOut = NULL; // just in case + PicoIn.sndOut = NULL; // just in case PicoIn.skipFrame = 1; PicoFrame(); PicoIn.skipFrame = 0; diff --git a/platform/common/mp3.c b/platform/common/mp3.c index 6c823ad4..c84962cc 100644 --- a/platform/common/mp3.c +++ b/platform/common/mp3.c @@ -167,11 +167,11 @@ void mp3_update(int *buffer, int length, int stereo) return; length_mp3 = length; - if (PsndRate <= 11025 + 100) { + if (PicoIn.sndRate <= 11025 + 100) { mix_samples = mix_16h_to_32_s2; length_mp3 <<= 2; shr = 2; } - else if (PsndRate <= 22050 + 100) { + else if (PicoIn.sndRate <= 22050 + 100) { mix_samples = mix_16h_to_32_s1; length_mp3 <<= 1; shr = 1; } diff --git a/platform/gizmondo/emu.c b/platform/gizmondo/emu.c index 96a49cf5..86c473c2 100644 --- a/platform/gizmondo/emu.c +++ b/platform/gizmondo/emu.c @@ -266,12 +266,12 @@ static void stdbg(const char *fmt, ...) static void updateSound(int len) { snd_all_samples += len / 2; - PsndOut += len / 2; - if (PsndOut - snd_cbuff >= snd_cbuf_samples) + PicoIn.sndOut += len / 2; + if (PicoIn.sndOut - snd_cbuff >= snd_cbuf_samples) { - //if (PsndOut - snd_cbuff != snd_cbuf_samples) - // stdbg("snd diff is %i, not %i", PsndOut - snd_cbuff, snd_cbuf_samples); - PsndOut = snd_cbuff; + //if (PicoIn.sndOut - snd_cbuff != snd_cbuf_samples) + // stdbg("snd diff is %i, not %i", PicoIn.sndOut - snd_cbuff, snd_cbuf_samples); + PicoIn.sndOut = snd_cbuff; } } @@ -317,7 +317,7 @@ static void RunEvents(unsigned int which) { int do_it = 1; - if (PsndOut != NULL) + if (PicoIn.sndOut != NULL) FrameworkAudio_SetPause(1); if (giz_screen == NULL) giz_screen = fb_lock(1); @@ -344,7 +344,7 @@ static void RunEvents(unsigned int which) Sleep(0); } - if (PsndOut != NULL) + if (PicoIn.sndOut != NULL) FrameworkAudio_SetPause(0); reset_timing = 1; } @@ -401,7 +401,7 @@ static void updateKeys(void) events = (allActions[0] | allActions[1]) >> 16; // volume is treated in special way and triggered every frame - if ((events & 0x6000) && PsndOut != NULL) + if ((events & 0x6000) && PicoIn.sndOut != NULL) { int vol = currentConfig.volume; if (events & 0x2000) { @@ -469,19 +469,19 @@ void pemu_loop(void) if (PicoIn.AHW & PAHW_MCD) PicoCDBufferInit(); // prepare sound stuff - PsndOut = NULL; + PicoIn.sndOut = NULL; if (currentConfig.EmuOpt & 4) { int ret, snd_excess_add, stereo; - if (PsndRate != PsndRate_old || (PicoIn.opt&0x0b) != (PicoOpt_old&0x0b) || Pico.m.pal != pal_old) { + if (PicoIn.sndRate != PsndRate_old || (PicoIn.opt&0x0b) != (PicoOpt_old&0x0b) || Pico.m.pal != pal_old) { PsndRerate(Pico.m.frame_count ? 1 : 0); } stereo=(PicoIn.opt&8)>>3; - snd_excess_add = ((PsndRate - PsndLen*target_fps)<<16) / target_fps; - snd_cbuf_samples = (PsndRate< 22050) co = 11; + if (PicoIn.sndRate == 22050) co = 10; + if (PicoIn.sndRate > 22050) co = 11; if (PicoIn.opt&8) shift++; if (audio_skew < 0) { adj = -((-audio_skew) >> shift); @@ -600,7 +600,7 @@ void pemu_loop(void) for (i = 0; i < currentConfig.Frameskip; i++) { updateKeys(); SkipFrame(); frames_done++; - if (PsndOut) { // do framelimitting if sound is enabled + if (PicoIn.sndOut) { // do framelimitting if sound is enabled int tval_diff; tval = GetTickCount(); tval_diff = (int)(tval - tval_thissec) << 8; @@ -660,7 +660,7 @@ void pemu_loop(void) if (currentConfig.Frameskip < 0 && tval_diff - lim_time >= (300<<8)) // slowdown detection reset_timing = 1; - else if (PsndOut != NULL || currentConfig.Frameskip < 0) + else if (PicoIn.sndOut != NULL || currentConfig.Frameskip < 0) { // sleep if we are still too fast if (tval_diff < lim_time) @@ -676,8 +676,8 @@ void pemu_loop(void) if (PicoIn.AHW & PAHW_MCD) PicoCDBufferFree(); - if (PsndOut != NULL) { - PsndOut = snd_cbuff = NULL; + if (PicoIn.sndOut != NULL) { + PicoIn.sndOut = snd_cbuff = NULL; FrameworkAudio_Close(); } diff --git a/platform/gizmondo/menu.c b/platform/gizmondo/menu.c index 232701ad..51f032f0 100644 --- a/platform/gizmondo/menu.c +++ b/platform/gizmondo/menu.c @@ -1046,7 +1046,7 @@ static void menu_opt_cust_draw(const menu_entry *entry, int x, int y, void *para break; case MA_OPT_SOUND_QUALITY: str = (PicoIn.opt&0x08)?"stereo":"mono"; - text_out16(x, y, "Sound Quality: %5iHz %s", PsndRate, str); + text_out16(x, y, "Sound Quality: %5iHz %s", PicoIn.sndRate, str); break; case MA_OPT_REGION: text_out16(x, y, "Region: %s", me_region_name(PicoIn.regionOverride, PicoIn.autoRgnOrder)); @@ -1174,18 +1174,18 @@ static int menu_loop_options(void) } break; case MA_OPT_SOUND_QUALITY: - if ((inp & PBTN_RIGHT) && PsndRate == 44100 && + if ((inp & PBTN_RIGHT) && PicoIn.sndRate == 44100 && !(PicoIn.opt&0x08)) { - PsndRate = 11025; + PicoIn.sndRate = 11025; PicoIn.opt |= 8; - } else if ((inp & PBTN_LEFT) && PsndRate == 11025 && + } else if ((inp & PBTN_LEFT) && PicoIn.sndRate == 11025 && (PicoIn.opt&0x08) && !(PicoIn.AHW&1)) { - PsndRate = 44100; + PicoIn.sndRate = 44100; PicoIn.opt &= ~8; } else - PsndRate = sndrate_prevnext(PsndRate, inp & PBTN_RIGHT); + PicoIn.sndRate = sndrate_prevnext(PicoIn.sndRate, inp & PBTN_RIGHT); break; case MA_OPT_REGION: region_prevnext(inp & PBTN_RIGHT); diff --git a/platform/gp2x/940ctl.c b/platform/gp2x/940ctl.c index 99c25d64..c270bfee 100644 --- a/platform/gp2x/940ctl.c +++ b/platform/gp2x/940ctl.c @@ -402,9 +402,9 @@ int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty) writebuff_ptr = 0; /* predict sample counter for next frame */ - if (PsndLen_exc_add) { - length = PsndLen; - if (PsndLen_exc_cnt + PsndLen_exc_add >= 0x10000) length++; + if (Pico.snd.len_e_add) { + length = Pico.snd.len; + if (Pico.snd.len_e_cnt + Pico.snd.len_e_add >= 0x10000) length++; } /* give 940 ym job */ @@ -463,11 +463,11 @@ int mp3dec_start(FILE *f, int fpos_start) if (loaded_mp3 != f) { - if (PicoMessage != NULL) + if (PicoIn.osdMessage != NULL) { fseek(f, 0, SEEK_END); if (ftell(f) > 2*1024*1024) - PicoMessage("Loading MP3..."); + PicoIn.osdMessage("Loading MP3..."); } fseek(f, 0, SEEK_SET); fread(mp3_mem, 1, MP3_SIZE_MAX, f); diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 3b3a234b..7e9a132f 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -692,7 +692,7 @@ void pemu_sound_start(void) { soc = soc_detect(); if (soc == SOCID_POLLUX) { - PsndRate = pollux_get_real_snd_rate(PsndRate); + PicoIn.sndRate = pollux_get_real_snd_rate(PicoIn.sndRate); PsndRerate(Pico.m.frame_count ? 1 : 0); } @@ -707,10 +707,10 @@ void pemu_sound_stop(void) int i; /* get back from Pollux pain */ - PsndRate += 1000; + PicoIn.sndRate += 1000; for (i = 0; i < ARRAY_SIZE(sound_rates); i++) { - if (PsndRate >= sound_rates[i]) { - PsndRate = sound_rates[i]; + if (PicoIn.sndRate >= sound_rates[i]) { + PicoIn.sndRate = sound_rates[i]; break; } } diff --git a/platform/libpicofe b/platform/libpicofe index f287890d..21082d0b 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit f287890d65ad36ca75bb71d05745693ae78b1490 +Subproject commit 21082d0b2b9910727770674cef9b68b9e97a3155 diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 99f0f3b5..2bdd07d2 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -1088,9 +1088,9 @@ bool retro_load_game(const struct retro_game_info *info) PicoLoopPrepare(); - PicoWriteSound = snd_write; + PicoIn.writeSound = snd_write; memset(sndBuffer, 0, sizeof(sndBuffer)); - PsndOut = sndBuffer; + PicoIn.sndOut = sndBuffer; PsndRerate(0); return true; @@ -1193,7 +1193,7 @@ static const unsigned short retro_pico_map[] = { static void snd_write(int len) { - audio_batch_cb(PsndOut, len / 4); + audio_batch_cb(PicoIn.sndOut, len / 4); } static enum input_device input_name_to_val(const char *name) @@ -1375,7 +1375,7 @@ void retro_init(void) #endif PicoIn.opt |= POPT_EN_DRC; #endif - PsndRate = 44100; + PicoIn.sndRate = 44100; PicoIn.autoRgnOrder = 0x184; // US, EU, JP vout_width = 320; @@ -1390,9 +1390,9 @@ void retro_init(void) PicoDrawSetOutFormat(PDF_RGB555, 0); PicoDrawSetOutBuf(vout_buf, vout_width * 2); - //PicoMessage = plat_status_msg_busy_next; - PicoMCDopenTray = disk_tray_open; - PicoMCDcloseTray = disk_tray_close; + //PicoIn.osdMessage = plat_status_msg_busy_next; + PicoIn.mcdTrayOpen = disk_tray_open; + PicoIn.mcdTrayClose = disk_tray_close; update_variables(); } diff --git a/platform/linux/emu.c b/platform/linux/emu.c index ddde8dab..c470a771 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -29,7 +29,7 @@ void pemu_prep_defconfig(void) void pemu_validate_config(void) { -#ifndef __arm__ +#if !defined(__arm__) && !defined(__i386__) && !defined(__x86_64__) PicoIn.opt &= ~POPT_EN_DRC; #endif } diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 8f77f395..0656f581 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -571,32 +571,32 @@ void pemu_sound_start(void) samples_made = samples_done = 0; - if (PsndRate != PsndRate_old || (PicoIn.opt&0x0b) != (PicoOpt_old&0x0b) || Pico.m.pal != pal_old) { + if (PicoIn.sndRate != PsndRate_old || (PicoIn.opt&0x0b) != (PicoOpt_old&0x0b) || Pico.m.pal != pal_old) { PsndRerate(Pico.m.frame_count ? 1 : 0); } stereo=(PicoIn.opt&8)>>3; samples_block = Pico.m.pal ? SOUND_BLOCK_SIZE_PAL : SOUND_BLOCK_SIZE_NTSC; - if (PsndRate <= 22050) samples_block /= 2; + if (PicoIn.sndRate <= 22050) samples_block /= 2; sndBuffer_endptr = &sndBuffer[samples_block*SOUND_BLOCK_COUNT]; lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", - PsndRate, PsndLen, stereo, Pico.m.pal, samples_block); + PicoIn.sndRate, Pico.snd.len, stereo, Pico.m.pal, samples_block); // while (sceAudioOutput2GetRestSample() > 0) psp_msleep(100); // sceAudio_5C37C0AE(); - ret = sceAudio_38553111(samples_block/2, PsndRate, 2); // seems to not need that stupid 64byte alignment + ret = sceAudio_38553111(samples_block/2, PicoIn.sndRate, 2); // seems to not need that stupid 64byte alignment if (ret < 0) { lprintf("sceAudio_38553111() failed: %i\n", ret); emu_status_msg("sound init failed (%i), snd disabled", ret); currentConfig.EmuOpt &= ~EOPT_EN_SOUND; } else { - PicoWriteSound = writeSound; + PicoIn.writeSound = writeSound; memset32((int *)(void *)sndBuffer, 0, sizeof(sndBuffer)/4); snd_playptr = sndBuffer_endptr - samples_block; samples_made = samples_block; // send 1 empty block first.. - PsndOut = sndBuffer; - PsndRate_old = PsndRate; + PicoIn.sndOut = sndBuffer; + PsndRate_old = PicoIn.sndRate; PicoOpt_old = PicoIn.opt; pal_old = Pico.m.pal; } @@ -641,16 +641,16 @@ static void writeSound(int len) { int ret; - PsndOut += len / 2; - /*if (PsndOut > sndBuffer_endptr) { - memcpy32((int *)(void *)sndBuffer, (int *)endptr, (PsndOut - endptr + 1) / 2); - PsndOut = &sndBuffer[PsndOut - endptr]; + PicoIn.sndOut += len / 2; + /*if (PicoIn.sndOut > sndBuffer_endptr) { + memcpy32((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) / 2); + PicoIn.sndOut = &sndBuffer[PicoIn.sndOut - endptr]; lprintf("mov\n"); } else*/ - if (PsndOut > sndBuffer_endptr) lprintf("snd oflow %i!\n", PsndOut - sndBuffer_endptr); - if (PsndOut >= sndBuffer_endptr) - PsndOut = sndBuffer; + if (PicoIn.sndOut > sndBuffer_endptr) lprintf("snd oflow %i!\n", PicoIn.sndOut - sndBuffer_endptr); + if (PicoIn.sndOut >= sndBuffer_endptr) + PicoIn.sndOut = sndBuffer; // signal the snd thread samples_made += len / 2; @@ -873,7 +873,7 @@ void pemu_loop(void) } // prepare sound stuff - PsndOut = NULL; + PicoIn.sndOut = NULL; if (currentConfig.EmuOpt & EOPT_EN_SOUND) { pemu_sound_start(); @@ -1021,9 +1021,9 @@ void pemu_loop(void) if (PicoIn.AHW & PAHW_MCD) PicoCDBufferFree(); - if (PsndOut != NULL) { + if (PicoIn.sndOut != NULL) { pemu_sound_stop(); - PsndOut = NULL; + PicoIn.sndOut = NULL; } // save SRAM diff --git a/platform/psp/menu.c b/platform/psp/menu.c index de63d345..ab022f97 100644 --- a/platform/psp/menu.c +++ b/platform/psp/menu.c @@ -1227,7 +1227,7 @@ static void menu_opt_cust_draw(const menu_entry *entry, int x, int y, void *para break; case MA_OPT_SOUND_QUALITY: str = (PicoIn.opt&0x08)?"stereo":"mono"; - text_out16(x, y, "Sound Quality: %5iHz %s", PsndRate, str); + text_out16(x, y, "Sound Quality: %5iHz %s", PicoIn.sndRate, str); break; case MA_OPT_REGION: text_out16(x, y, "Region: %s", me_region_name(PicoIn.regionOverride, PicoIn.autoRgnOrder)); @@ -1353,7 +1353,7 @@ static int menu_loop_options(void) } break; case MA_OPT_SOUND_QUALITY: - PsndRate = sndrate_prevnext(PsndRate, inp & PBTN_RIGHT); + PicoIn.sndRate = sndrate_prevnext(PicoIn.sndRate, inp & PBTN_RIGHT); break; case MA_OPT_REGION: region_prevnext(inp & PBTN_RIGHT); diff --git a/platform/psp/mp3.c b/platform/psp/mp3.c index 4ea3bdd7..18624399 100644 --- a/platform/psp/mp3.c +++ b/platform/psp/mp3.c @@ -403,8 +403,8 @@ void mp3_update(int *buffer, int length, int stereo) if (mp3_handle < 0 || mp3_src_pos >= mp3_src_size) return; length_mp3 = length; - if (PsndRate == 22050) length_mp3 <<= 1; // mp3s are locked to 44100Hz stereo - else if (PsndRate == 11025) length_mp3 <<= 2; // so make length 44100ish + if (PicoIn.sndRate == 22050) length_mp3 <<= 1; // mp3s are locked to 44100Hz stereo + else if (PicoIn.sndRate == 11025) length_mp3 <<= 2; // so make length 44100ish /* do we have to wait? */ if (mp3_job_started && mp3_samples_ready < length_mp3) @@ -420,8 +420,8 @@ void mp3_update(int *buffer, int length, int stereo) { int shr = 0; void (*mix_samples)(int *dest_buf, short *mp3_buf, int count) = mix_16h_to_32; - if (PsndRate == 22050) { mix_samples = mix_16h_to_32_s1; shr = 1; } - else if (PsndRate == 11025) { mix_samples = mix_16h_to_32_s2; shr = 2; } + if (PicoIn.sndRate == 22050) { mix_samples = mix_16h_to_32_s1; shr = 1; } + else if (PicoIn.sndRate == 11025) { mix_samples = mix_16h_to_32_s2; shr = 2; } if (1152 - mp3_buffer_offs >= length_mp3) { mix_samples(buffer, mp3_mix_buffer[mp3_play_bufsel] + mp3_buffer_offs*2, length<<1); diff --git a/platform/win32/plat.c b/platform/win32/plat.c index a9cceb79..8abb0626 100644 --- a/platform/win32/plat.c +++ b/platform/win32/plat.c @@ -131,7 +131,7 @@ void pemu_sound_start(void) { int ret; - PsndOut = NULL; + PicoIn.sndOut = NULL; currentConfig.EmuOpt &= ~EOPT_EXT_FRMLIMIT; // prepare sound stuff @@ -139,14 +139,14 @@ void pemu_sound_start(void) { PsndRerate(0); - ret = DSoundInit(FrameWnd, PsndRate, (PicoIn.opt & POPT_EN_STEREO) ? 1 : 0, PsndLen); + ret = DSoundInit(FrameWnd, PicoIn.sndRate, (PicoIn.opt & POPT_EN_STEREO) ? 1 : 0, Pico.snd.len); if (ret != 0) { lprintf("dsound init failed\n"); return; } - PsndOut = (void *)sndbuff; - PicoWriteSound = update_sound; + PicoIn.sndOut = (void *)sndbuff; + PicoIn.writeSound = update_sound; currentConfig.EmuOpt |= EOPT_EXT_FRMLIMIT; } } diff --git a/tools/mkoffsets.c b/tools/mkoffsets.c index 297a1969..7e57383a 100644 --- a/tools/mkoffsets.c +++ b/tools/mkoffsets.c @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) DUMP_EST(f, Pico); DUMP_EST(f, PicoMem_vram); DUMP_EST(f, PicoMem_cram); - DUMP_EST(f, PicoIn.opt); + DUMP_EST(f, PicoOpt); DUMP_EST(f, Draw2FB); DUMP_EST(f, HighPal); DUMP_PMEM(f, vram);