From 12da51c27a8d1c1205d8f0f01bbc4814c46e79ce Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 10 Aug 2013 17:57:54 +0300 Subject: [PATCH 01/41] some new cpu debug code --- Makefile | 3 +- cpu/cyclone | 2 +- cpu/cyclone_config.h | 2 +- cpu/sh2/sh2.c | 57 +++++++----------- pico/debug.c | 33 ++++++++++- pico/debug.h | 20 +++++++ pico/m68kif_cyclone.s | 8 ++- pico/pico.c | 2 +- pico/pico_cmn.c | 1 + pico/pico_int.h | 19 ++++-- pico/sek.c | 118 +++++++++++++++++++++++++++++++++++++ platform/common/common.mak | 13 ++-- 12 files changed, 224 insertions(+), 54 deletions(-) diff --git a/Makefile b/Makefile index db145a5b..e6e3b2fc 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,8 @@ CFLAGS += -O2 -DNDEBUG endif #CFLAGS += -DEVT_LOG #CFLAGS += -DDRC_CMP -#drc_debug = 4 +#cpu_cmp = 1 +#drc_debug = 3 #profile = 1 diff --git a/cpu/cyclone b/cpu/cyclone index 194104e3..1f9661c5 160000 --- a/cpu/cyclone +++ b/cpu/cyclone @@ -1 +1 @@ -Subproject commit 194104e334f7c26015b99c862486a73be0d80162 +Subproject commit 1f9661c5a2919ba91c0f4b89985e0712871e5762 diff --git a/cpu/cyclone_config.h b/cpu/cyclone_config.h index af9ab5e7..7f9690d0 100644 --- a/cpu/cyclone_config.h +++ b/cpu/cyclone_config.h @@ -19,7 +19,7 @@ #define MEMHANDLERS_NEED_CYCLES 1 #define MEMHANDLERS_CHANGE_PC 0 #define MEMHANDLERS_CHANGE_FLAGS 0 -#define MEMHANDLERS_CHANGE_CYCLES 0 +#define MEMHANDLERS_CHANGE_CYCLES 1 #define MEMHANDLERS_DIRECT_PREFIX "cyclone_" diff --git a/cpu/sh2/sh2.c b/cpu/sh2/sh2.c index 847035a5..7b83cf21 100644 --- a/cpu/sh2/sh2.c +++ b/cpu/sh2/sh2.c @@ -136,15 +136,6 @@ void sh2_unpack(SH2 *sh2, const unsigned char *buff) static SH2 sh2ref[2]; static unsigned int mem_val; -static FILE *f; - -enum ctl_byte { - CTL_MASTERSLAVE = 0x80, - CTL_EA = 0x82, - CTL_EAVAL = 0x83, - CTL_M68KPC = 0x84, - CTL_CYCLES = 0x85, -}; static unsigned int local_read32(SH2 *sh2, u32 a) { @@ -176,12 +167,6 @@ static unsigned int local_read32(SH2 *sh2, u32 a) return 0; } -static void write_uint(unsigned char ctl, unsigned int v) -{ - fwrite(&ctl, 1, 1, f); - fwrite(&v, sizeof(v), 1, f); -} - void do_sh2_trace(SH2 *current, int cycles) { static int current_slave = -1; @@ -193,39 +178,36 @@ void do_sh2_trace(SH2 *current, int cycles) u32 val; int i; - if (f == NULL) - f = fopen("tracelog", "wb"); - if (SekPc != current_m68k_pc) { current_m68k_pc = SekPc; - write_uint(CTL_M68KPC, current_m68k_pc); + tl_write_uint(CTL_M68KPC, current_m68k_pc); } if (current->is_slave != current_slave) { current_slave = current->is_slave; v = CTL_MASTERSLAVE | current->is_slave; - fwrite(&v, 1, 1, f); + tl_write(&v, sizeof(v)); } for (i = 0; i < offsetof(SH2, read8_map) / 4; i++) { if (i == 17) // ppc continue; if (regs_a[i] != regs_o[i]) { - write_uint(i, regs_a[i]); + tl_write_uint(CTL_SH2_R + i, regs_a[i]); regs_o[i] = regs_a[i]; } } if (current->ea != sh2o->ea) { - write_uint(CTL_EA, current->ea); + tl_write_uint(CTL_EA, current->ea); sh2o->ea = current->ea; } val = local_read32(current, current->ea); if (mem_val != val) { - write_uint(CTL_EAVAL, val); + tl_write_uint(CTL_EAVAL, val); mem_val = val; } - write_uint(CTL_CYCLES, cycles); + tl_write_uint(CTL_CYCLES, cycles); } static const char *regnames[] = { @@ -264,17 +246,14 @@ void do_sh2_cmp(SH2 *current) int cycles; int i, ret; - if (f == NULL) { - f = fopen("tracelog", "rb"); - sh2ref[1].is_slave = 1; - } + sh2ref[1].is_slave = 1; while (1) { - ret = fread(&code, 1, 1, f); + ret = tl_read(&code, 1); if (ret <= 0) break; if (code == CTL_CYCLES) { - fread(&cycles_o, 1, 4, f); + tl_read(&cycles_o, 4); break; } @@ -284,23 +263,27 @@ void do_sh2_cmp(SH2 *current) current_slave = code & 1; break; case CTL_EA: - fread(&sh2o->ea, 4, 1, f); + tl_read_uint(&sh2o->ea); break; case CTL_EAVAL: - fread(¤t_val, 4, 1, f); + tl_read_uint(¤t_val); break; case CTL_M68KPC: - fread(&val, 4, 1, f); + tl_read_uint(&val); if (SekPc != val) { printf("m68k: %08x %08x\n", SekPc, val); bad = 1; } break; default: - if (code < offsetof(SH2, read8_map) / 4) - fread(regs_o + code, 4, 1, f); - else { - printf("invalid code: %02x\n", code); + if (CTL_SH2_R <= code && code < CTL_SH2_R + + offsetof(SH2, read8_map) / 4) + { + tl_read_uint(regs_o + code - CTL_SH2_R); + } + else + { + printf("wrong code: %02x\n", code); goto end; } break; diff --git a/pico/debug.c b/pico/debug.c index 03451201..9cb93b26 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -40,7 +40,7 @@ char *PDebugMain(void) sprintf(dstrp, "mode set 4: %02x\n", (r=reg[0xC])); MVP; sprintf(dstrp, "interlace: %i%i, cells: %i, shadow: %i\n", bit(r,2), bit(r,1), (r&0x80) ? 40 : 32, bit(r,3)); MVP; sprintf(dstrp, "scroll size: w: %i, h: %i SRAM: %i; eeprom: %i (%i)\n", reg[0x10]&3, (reg[0x10]&0x30)>>4, - !!(SRam.flags & SRF_ENABLED), !!(SRam.flags & SRF_EEPROM), SRam.eeprom_type); MVP; + !!(SRam.flags & SRF_ENABLED), !!(SRam.flags & SRF_EEPROM), SRam.eeprom_type); MVP; sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", SRam.start, SRam.end, Pico.m.sram_reg); MVP; sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP; sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDoneT()); MVP; @@ -535,4 +535,35 @@ void pevt_dump(void) } #endif +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) +static FILE *tl_f; + +void tl_write(const void *ptr, size_t size) +{ + if (tl_f == NULL) + tl_f = fopen("tracelog", "wb"); + + fwrite(ptr, 1, size, tl_f); +} + +void tl_write_uint(unsigned char ctl, unsigned int v) +{ + tl_write(&ctl, sizeof(ctl)); + tl_write(&v, sizeof(v)); +} + +int tl_read(void *ptr, size_t size) +{ + if (tl_f == NULL) + tl_f = fopen("tracelog", "rb"); + + return fread(ptr, 1, size, tl_f); +} + +int tl_read_uint(void *ptr) +{ + return tl_read(ptr, 4); +} +#endif + // vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/debug.h b/pico/debug.h index 53dc6680..fcfdc079 100644 --- a/pico/debug.h +++ b/pico/debug.h @@ -9,3 +9,23 @@ void PDebugDumpMem(void); void PDebugZ80Frame(void); void PDebugCPUStep(void); +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) +enum ctl_byte { + CTL_68K_SLAVE = 0x02, + CTL_68K_PC = 0x04, + CTL_68K_SR = 0x05, + CTL_68K_CYCLES = 0x06, + CTL_68K_R = 0x10, // .. 0x20 + CTL_MASTERSLAVE = 0x80, + CTL_EA = 0x82, + CTL_EAVAL = 0x83, + CTL_M68KPC = 0x84, + CTL_CYCLES = 0x85, + CTL_SH2_R = 0x90, // .. 0xa8 +}; + +void tl_write(const void *ptr, size_t size); +void tl_write_uint(unsigned char ctl, unsigned int v); +int tl_read(void *ptr, size_t size); +int tl_read_uint(void *ptr); +#endif diff --git a/pico/m68kif_cyclone.s b/pico/m68kif_cyclone.s index f8b6927c..a0a508cd 100644 --- a/pico/m68kif_cyclone.s +++ b/pico/m68kif_cyclone.s @@ -24,16 +24,18 @@ cyclone_checkpc: ldr r1, [r7, #0x60] @ membase sub r0, r0, r1 - bic r0, r0, #0xff000000 - bics r0, r0, #1 + and r3, r0, #0xff000000 + bic r0, r0, #1 + bics r2, r0, #0xff000000 beq crashed ldr r1, [r7, #0x6c] @ read16 map - mov r2, r0, lsr #M68K_MEM_SHIFT + mov r2, r2, lsr #M68K_MEM_SHIFT ldr r1, [r1, r2, lsl #2] movs r1, r1, lsl #1 bcs crashed + sub r1, r1, r3 str r1, [r7, #0x60] @ membase add r0, r0, r1 bx lr diff --git a/pico/pico.c b/pico/pico.c index 80ffb90e..747c6266 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -146,7 +146,7 @@ int PicoReset(void) if (Pico.romsize <= 0) return 1; -#ifdef DRC_CMP +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) PicoOpt |= POPT_DIS_VDP_FIFO|POPT_DIS_IDLE_DET; #endif diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 9099c855..3383b131 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -50,6 +50,7 @@ static __inline void SekRunM68k(int cyc) #endif out: + SekTrace(0); pevt_log_m68k_o(EVT_RUN_END); pprof_end(m68k); } diff --git a/pico/pico_int.h b/pico/pico_int.h index 339d1bf1..9fcc6d4b 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -46,8 +46,10 @@ extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k; #define SekEndTimesliceS68k(after) PicoCpuCS68k.cycles=after #define SekPc (PicoCpuCM68k.pc-PicoCpuCM68k.membase) #define SekPcS68k (PicoCpuCS68k.pc-PicoCpuCS68k.membase) -#define SekDar(x) (x < 8 ? PicoCpuCM68k.d[x] : PicoCpuCM68k.a[x - 8]) +#define SekDar(x) (x < 8 ? PicoCpuCM68k.d[x] : PicoCpuCM68k.a[x - 8]) +#define SekDarS68k(x) (x < 8 ? PicoCpuCS68k.d[x] : PicoCpuCS68k.a[x - 8]) #define SekSr CycloneGetSr(&PicoCpuCM68k) +#define SekSrS68k CycloneGetSr(&PicoCpuCS68k) #define SekSetStop(x) { PicoCpuCM68k.state_flags&=~1; if (x) { PicoCpuCM68k.state_flags|=1; PicoCpuCM68k.cycles=0; } } #define SekSetStopS68k(x) { PicoCpuCS68k.state_flags&=~1; if (x) { PicoCpuCS68k.state_flags|=1; PicoCpuCS68k.cycles=0; } } #define SekIsStoppedM68k() (PicoCpuCM68k.state_flags&1) @@ -74,8 +76,10 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; #define SekEndTimesliceS68k(after) PicoCpuFS68k.io_cycle_counter=after #define SekPc fm68k_get_pc(&PicoCpuFM68k) #define SekPcS68k fm68k_get_pc(&PicoCpuFS68k) -#define SekDar(x) (x < 8 ? PicoCpuFM68k.dreg[x].D : PicoCpuFM68k.areg[x - 8].D) +#define SekDar(x) (x < 8 ? PicoCpuFM68k.dreg[x].D : PicoCpuFM68k.areg[x - 8].D) +#define SekDarS68k(x) (x < 8 ? PicoCpuFS68k.dreg[x].D : PicoCpuFS68k.areg[x - 8].D) #define SekSr PicoCpuFM68k.sr +#define SekSrS68k PicoCpuFS68k.sr #define SekSetStop(x) { \ PicoCpuFM68k.execinfo &= ~FM68K_HALTED; \ if (x) { PicoCpuFM68k.execinfo |= FM68K_HALTED; PicoCpuFM68k.io_cycle_counter = 0; } \ @@ -109,8 +113,10 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #define SekEndTimesliceS68k(after) PicoCpuMS68k.cyc_remaining_cycles=after #define SekPc m68k_get_reg(&PicoCpuMM68k, M68K_REG_PC) #define SekPcS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_PC) -#define SekDar(x) PicoCpuMM68k.dar[x] -#define SekSr m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR) +#define SekDar(x) PicoCpuMM68k.dar[x] +#define SekDarS68k(x) PicoCpuMS68k.dar[x] +#define SekSr m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR) +#define SekSrS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_SR) #define SekSetStop(x) { \ if(x) { SET_CYCLES(0); PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \ else PicoCpuMM68k.stopped=0; \ @@ -633,6 +639,11 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub); void SekStepM68k(void); void SekInitIdleDet(void); void SekFinishIdleDet(void); +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) +void SekTrace(int is_s68k); +#else +#define SekTrace(x) +#endif // cd/sek.c PICO_INTERNAL void SekInitS68k(void); diff --git a/pico/sek.c b/pico/sek.c index 85bfd287..2fe77cbb 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -420,6 +420,122 @@ void SekFinishIdleDet(void) } +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) +#include "debug.h" + +struct ref_68k { + u32 dar[16]; + u32 pc; + u32 sr; + u32 cycles; + u32 pc_prev; +}; +struct ref_68k ref_68ks[2]; +static int current_68k; + +void SekTrace(int is_s68k) +{ + struct ref_68k *x68k = &ref_68ks[is_s68k]; + u32 pc = is_s68k ? SekPcS68k : SekPc; + u32 sr = is_s68k ? SekSrS68k : SekSr; + u32 cycles = is_s68k ? SekCycleCntS68k : SekCycleCnt; + u32 r; + u8 cmd; +#ifdef CPU_CMP_W + int i; + + if (is_s68k != current_68k) { + current_68k = is_s68k; + cmd = CTL_68K_SLAVE | current_68k; + tl_write(&cmd, sizeof(cmd)); + } + if (pc != x68k->pc) { + x68k->pc = pc; + tl_write_uint(CTL_68K_PC, x68k->pc); + } + if (sr != x68k->sr) { + x68k->sr = sr; + tl_write_uint(CTL_68K_SR, x68k->sr); + } + for (i = 0; i < 16; i++) { + r = is_s68k ? SekDarS68k(i) : SekDar(i); + if (r != x68k->dar[i]) { + x68k->dar[i] = r; + tl_write_uint(CTL_68K_R + i, r); + } + } + tl_write_uint(CTL_68K_CYCLES, cycles); +#else + int i, bad = 0; + + while (1) + { + int ret = tl_read(&cmd, sizeof(cmd)); + if (ret == 0) { + elprintf(EL_STATUS, "EOF"); + exit(1); + } + switch (cmd) { + case CTL_68K_SLAVE: + case CTL_68K_SLAVE + 1: + current_68k = cmd & 1; + break; + case CTL_68K_PC: + tl_read_uint(&x68k->pc); + break; + case CTL_68K_SR: + tl_read_uint(&x68k->sr); + break; + case CTL_68K_CYCLES: + tl_read_uint(&x68k->cycles); + goto breakloop; + default: + if (CTL_68K_R <= cmd && cmd < CTL_68K_R + 0x10) + tl_read_uint(&x68k->dar[cmd - CTL_68K_R]); + else + elprintf(EL_STATUS, "invalid cmd: %02x", cmd); + } + } + +breakloop: + if (is_s68k != current_68k) { + printf("bad 68k: %d %d\n", is_s68k, current_68k); + bad = 1; + } + if (cycles != x68k->cycles) { + printf("bad cycles: %u %u\n", cycles, x68k->cycles); + bad = 1; + } + if ((pc ^ x68k->pc) & 0xffffff) { + printf("bad PC: %08x %08x\n", pc, x68k->pc); + bad = 1; + } + if (sr != x68k->sr) { + printf("bad SR: %03x %03x\n", sr, x68k->sr); + bad = 1; + } + for (i = 0; i < 16; i++) { + r = is_s68k ? SekDarS68k(i) : SekDar(i); + if (r != x68k->dar[i]) { + printf("bad %c%d: %08x %08x\n", i < 8 ? 'D' : 'A', i & 7, + r, x68k->dar[i]); + bad = 1; + } + } + if (bad) { + for (i = 0; i < 8; i++) + printf("D%d: %08x A%d: %08x\n", i, x68k->dar[i], + i, x68k->dar[i + 8]); + printf("PC: %08x, %08x\n", x68k->pc, x68k->pc_prev); + + PDebugDumpMem(); + exit(1); + } + x68k->pc_prev = x68k->pc; +#endif +} +#endif // CPU_CMP_* + #if defined(EMU_M68K) && M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER static unsigned char op_flags[0x400000/2] = { 0, }; static int atexit_set = 0; @@ -447,3 +563,5 @@ void instruction_hook(void) op_flags[REG_PC/2] = 1; } #endif + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/platform/common/common.mak b/platform/common/common.mak index 17e540fb..a365abc6 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -30,6 +30,13 @@ SRCS_COMMON += $(R)cpu/debug.c LDFLAGS += -lreadline endif endif +ifeq "$(cpu_cmp)" "1" +ifdef cpu_cmp_w +DEFINES += CPU_CMP_W +else +DEFINES += CPU_CMP_R +endif # cpu_cmp_w +endif ifeq "$(pprof)" "1" DEFINES += PPROF SRCS_COMMON += $(R)platform/linux/pprof.c @@ -157,10 +164,6 @@ SRCS_COMMON += $(R)cpu/sh2/mame/sh2dasm.c SRCS_COMMON += $(R)platform/libpicofe/linux/host_dasm.c LDFLAGS += -lbfd -lopcodes -liberty endif -ifeq "$(drc_debug_interp)" "1" -DEFINES += DRC_DEBUG_INTERP -use_sh2mame = 1 -endif endif # use_sh2drc # ifeq "$(use_sh2mame)" "1" @@ -183,7 +186,7 @@ $(FR)cpu/cyclone/Cyclone.h: $(FR)cpu/cyclone/Cyclone.s: @echo building Cyclone... - @make -C $(R)cpu/cyclone/ CONFIG_FILE='\"../cyclone_config.h\"' + @make -C $(R)cpu/cyclone/ CONFIG_FILE=../cyclone_config.h $(FR)cpu/musashi/m68kops.c: @make -C $(R)cpu/musashi From 3e5b912cf8820efc2c74e8f639a1c29cd4f68b75 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 10 Aug 2013 17:58:23 +0300 Subject: [PATCH 02/41] minor 68k timing tuning --- cpu/fame/famec.c | 1 + pico/32x/memory.c | 2 +- pico/pico_cmn.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cpu/fame/famec.c b/cpu/fame/famec.c index 616027c2..1aba794f 100644 --- a/cpu/fame/famec.c +++ b/cpu/fame/famec.c @@ -929,6 +929,7 @@ famec_Exec: u32 line; m68kcontext.io_cycle_counter = cycles_needed; cycles_needed = 0; + if (m68kcontext.io_cycle_counter <= 0) goto famec_End; line=interrupt_chk__(); if (line>0) { diff --git a/pico/32x/memory.c b/pico/32x/memory.c index fd6ff45e..11b0462c 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -198,7 +198,7 @@ static u32 p32x_reg_read16(u32 a) Pico32x.comm_dirty_sh2 &= ~comreg; else if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) { SekSetStop(1); - SekEndTimeslice(16); + SekEndRun(16); } dr2 = SekDar(2); goto out; diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 3383b131..2b558c1e 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -46,7 +46,7 @@ static __inline void SekRunM68k(int cyc) #elif defined(EMU_M68K) SekCycleCnt+=m68k_execute(cyc_do); #elif defined(EMU_F68K) - SekCycleCnt+=fm68k_emulate(cyc_do+1, 0, 0); + SekCycleCnt+=fm68k_emulate(cyc_do, 0, 0); #endif out: From f3d1e1e63ff0d7fb61ce7b0fa5c328b039f110e0 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 10 Aug 2013 19:45:35 +0300 Subject: [PATCH 03/41] bump libpicofe --- platform/libpicofe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/libpicofe b/platform/libpicofe index cab91943..c54d04fd 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit cab9194354b6340b4bf0c5154fecc4018a4f2a33 +Subproject commit c54d04fd84f59c60c6ecdbd2502fbda5de735b4b From cd0ace2832b2088e5a973a50ebbab6e57c56b91f Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 10 Aug 2013 19:46:27 +0300 Subject: [PATCH 04/41] fix incomplete init --- cpu/sh2/sh2.c | 7 ++++++- pico/32x/32x.c | 5 ++--- pico/32x/sh2soc.c | 6 ++++++ pico/pico_int.h | 1 + 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/cpu/sh2/sh2.c b/cpu/sh2/sh2.c index 7b83cf21..23b8fc0a 100644 --- a/cpu/sh2/sh2.c +++ b/cpu/sh2/sh2.c @@ -17,10 +17,15 @@ int sh2_init(SH2 *sh2, int is_slave, SH2 *other_sh2) { int ret = 0; + unsigned int mult_m68k_to_sh2 = sh2->mult_m68k_to_sh2; + unsigned int mult_sh2_to_m68k = sh2->mult_sh2_to_m68k; - memset(sh2, 0, offsetof(SH2, mult_m68k_to_sh2)); + memset(sh2, 0, sizeof(*sh2)); sh2->is_slave = is_slave; sh2->other_sh2 = other_sh2; + sh2->mult_m68k_to_sh2 = mult_m68k_to_sh2; + sh2->mult_sh2_to_m68k = mult_sh2_to_m68k; + pdb_register_cpu(sh2, PDBCT_SH2, is_slave ? "ssh2" : "msh2"); #ifdef DRC_SH2 ret = sh2_drc_init(sh2); diff --git a/pico/32x/32x.c b/pico/32x/32x.c index d0110c13..dd4d0ed2 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -85,9 +85,6 @@ void Pico32xStartup(void) if (!Pico.m.pal) Pico32x.vdp_regs[0] |= P32XV_nPAL; - PREG8(msh2.peri_regs, 4) = - PREG8(ssh2.peri_regs, 4) = 0x84; // SCI SSR - rendstatus_old = -1; emu_32x_startup(); @@ -100,6 +97,8 @@ void p32x_reset_sh2s(void) sh2_reset(&msh2); sh2_reset(&ssh2); + sh2_peripheral_reset(&msh2); + sh2_peripheral_reset(&ssh2); // if we don't have BIOS set, perform it's work here. // MSH2 diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index bdd07a04..8b971535 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -207,6 +207,12 @@ void p32x_timers_do(unsigned int m68k_slice) } } +void sh2_peripheral_reset(SH2 *sh2) +{ + memset(sh2->peri_regs, 0, sizeof(sh2->peri_regs)); // ? + PREG8(sh2->peri_regs, 4) = 0x84; // SCI SSR +} + // ------------------------------------------------------------------ // SH2 internal peripheral memhandlers // we keep them in little endian format diff --git a/pico/pico_int.h b/pico/pico_int.h index 9fcc6d4b..34b2881c 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -804,6 +804,7 @@ void p32x_dreq0_trigger(void); void p32x_dreq1_trigger(void); void p32x_timers_recalc(void); void p32x_timers_do(unsigned int m68k_slice); +void sh2_peripheral_reset(SH2 *sh2); unsigned int sh2_peripheral_read8(unsigned int a, SH2 *sh2); unsigned int sh2_peripheral_read16(unsigned int a, SH2 *sh2); unsigned int sh2_peripheral_read32(unsigned int a, SH2 *sh2); From 4a1fb1832381958386c1dc91a8a5422af386441d Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 11 Aug 2013 01:32:19 +0300 Subject: [PATCH 05/41] 32x: handle FEN quirk Metal Head relies on it? --- pico/32x/32x.c | 6 +++--- pico/32x/memory.c | 29 ++++++++++++++++++++++------- pico/pico_int.h | 3 ++- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index dd4d0ed2..0a72ddb7 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -155,7 +155,7 @@ void PicoPower32x(void) memset(&Pico32x, 0, sizeof(Pico32x)); Pico32x.regs[0] = P32XS_REN|P32XS_nRES; // verified - Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_HBLK|P32XV_PEN; + Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_PEN; Pico32x.sh2_regs[0] = P32XS2_ADEN; } @@ -322,8 +322,8 @@ static inline void run_sh2(SH2 *sh2, int m68k_cycles) pevt_log_sh2_o(sh2, EVT_RUN_START); sh2->state |= SH2_STATE_RUN; cycles = C_M68K_TO_SH2(*sh2, m68k_cycles); - elprintf(EL_32X, "%csh2 +run %u %d", - sh2->is_slave?'s':'m', sh2->m68krcycles_done, cycles); + elprintf(EL_32X, "%csh2 +run %u %d @%08x", + sh2->is_slave?'s':'m', sh2->m68krcycles_done, cycles, sh2->pc); done = sh2_execute(sh2, cycles); diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 11b0462c..0e19d691 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -93,12 +93,12 @@ void p32x_m68k_poll_event(u32 flags) m68k_poll.addr = m68k_poll.cnt = 0; } -static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags) +static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags, int maxcnt) { int cycles_left = sh2_cycles_left(sh2); if (a == sh2->poll_addr && sh2->poll_cycles - cycles_left <= 10) { - if (sh2->poll_cnt++ > 3) { + if (sh2->poll_cnt++ > maxcnt) { if (!(sh2->state & flags)) elprintf(EL_32X, "%csh2 state: %02x->%02x", sh2->is_slave?'s':'m', sh2->state, sh2->state | flags); @@ -321,6 +321,8 @@ static void p32x_reg_write16(u32 a, u32 d) if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN) r[6 / 2] |= P32XS_FULL; } + else + elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!"); break; } @@ -363,9 +365,22 @@ static void p32x_reg_write16(u32 a, u32 d) // VDP regs static u32 p32x_vdp_read16(u32 a) { + u32 d; a &= 0x0e; - return Pico32x.vdp_regs[a / 2]; + d = Pico32x.vdp_regs[a / 2]; + if (a == 0x0a) { + // tested: FEN seems to be randomly pulsing on hcnt 0x80-0xf0, + // most often at 0xb1-0xb5, even during vblank, + // what's the deal with that? + // we'll just fake it along with hblank for now + Pico32x.vdp_fbcr_fake++; + if (Pico32x.vdp_fbcr_fake & 4) + d |= P32XV_HBLK; + if ((Pico32x.vdp_fbcr_fake & 7) == 0) + d |= P32XV_nFEN; + } + return d; } static void p32x_vdp_write8(u32 a, u32 d) @@ -442,7 +457,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[sh2->is_slave]; case 0x04: // H count (often as comm too) - sh2_poll_detect(sh2, a, SH2_STATE_CPOLL); + sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); sh2s_sync_on_read(sh2); return Pico32x.sh2_regs[4 / 2]; case 0x10: // DREQ len @@ -458,7 +473,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) if (Pico32x.comm_dirty_68k & comreg) Pico32x.comm_dirty_68k &= ~comreg; else - sh2_poll_detect(sh2, a, SH2_STATE_CPOLL); + sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); sh2s_sync_on_read(sh2); return r[a / 2]; } @@ -917,7 +932,7 @@ static u32 sh2_read8_cs0(u32 a, SH2 *sh2) if ((a & 0x3ff00) == 0x4100) { d = p32x_vdp_read16(a); - sh2_poll_detect(sh2, a, SH2_STATE_VPOLL); + sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7); goto out_16to8; } @@ -971,7 +986,7 @@ static u32 sh2_read16_cs0(u32 a, SH2 *sh2) if ((a & 0x3ff00) == 0x4100) { d = p32x_vdp_read16(a); - sh2_poll_detect(sh2, a, SH2_STATE_VPOLL); + sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7); goto out; } diff --git a/pico/pico_int.h b/pico/pico_int.h index 34b2881c..53c6f4e7 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -512,7 +512,8 @@ struct Pico32x unsigned int sh2irqs; // common irqs unsigned short dmac_fifo[DMAC_FIFO_LEN]; unsigned int dmac0_fifo_ptr; - unsigned int pad; + unsigned short vdp_fbcr_fake; + unsigned short pad; unsigned char comm_dirty_68k; unsigned char comm_dirty_sh2; unsigned char pwm_irq_cnt; From 7eaa381224c5b50b90f39938be2e298a322b6f9f Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 11 Aug 2013 20:28:47 +0300 Subject: [PATCH 06/41] 32x: m68k memory handler improvemets did some hw tests today.. --- pico/32x/memory.c | 235 ++++++++++++++++++++++++++++++++++++---------- pico/32x/sh2soc.c | 15 ++- pico/pico_int.h | 6 +- 3 files changed, 196 insertions(+), 60 deletions(-) diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 0e19d691..f9374c47 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -9,17 +9,17 @@ * a15100 F....... R.....EA F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm * a15102 ........ ......SM ? 4002 // intS intM * a15104 ........ ......10 ........ hhhhhhhh 4004 // bk1 bk0 Hint - * a15106 F....... .....SDR UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb] + * a15106 ........ F....SDR UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb] * a15108 (32bit DREQ src) 4008 * a1510c (32bit DREQ dst) 400c * a15110 llllllll llllll00 4010 // DREQ Len * a15112 (16bit FIFO reg) 4012 - * a15114 ? (16bit VRES clr) 4014 - * a15116 ? (16bit Vint clr) 4016 - * a15118 ? (16bit Hint clr) 4018 - * a1511a ........ .......C (16bit CMD clr) 401a // Cm - * a1511c ? (16bit PWM clr) 401c - * a1511e ? ? 401e + * a15114 0 (16bit VRES clr) 4014 + * a15116 0 (16bit Vint clr) 4016 + * a15118 0 (16bit Hint clr) 4018 + * a1511a .......? .......C (16bit CMD clr) 401a // TV Cm + * a1511c 0 (16bit PWM clr) 401c + * a1511e 0 ? 401e * a15120 (16 bytes comm) 2020 * a15130 (PWM) 2030 * @@ -49,6 +49,9 @@ struct Pico32xMem *Pico32xMem; static void bank_switch(int b); +// addressing byte in 16bit reg +#define REG8IN16(ptr, offs) ((u8 *)ptr)[(offs) ^ 1] + // poll detection #define POLL_THRESHOLD 3 @@ -219,6 +222,32 @@ out: return Pico32x.regs[a / 2]; } +static void dreq0_write(u16 *r, u32 d) +{ + if (!(r[6 / 2] & P32XS_68S)) { + elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?"); + return; // ignored - tested + } + if (Pico32x.dmac0_fifo_ptr < DMAC_FIFO_LEN) { + Pico32x.dmac_fifo[Pico32x.dmac0_fifo_ptr++] = d; + if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN) + r[6 / 2] |= P32XS_FULL; + // tested: len register decrements and 68S clears + // even if SH2s/DMAC aren't active.. + r[0x10 / 2]--; + if (r[0x10 / 2] == 0) + r[6 / 2] &= ~P32XS_68S; + + if ((Pico32x.dmac0_fifo_ptr & 3) == 0) { + p32x_sync_sh2s(SekCyclesDoneT()); + p32x_dreq0_trigger(); + } + } + else + elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!"); +} + +// writable bits tested static void p32x_reg_write8(u32 a, u32 d) { u16 *r = Pico32x.regs; @@ -228,15 +257,18 @@ static void p32x_reg_write8(u32 a, u32 d) m68k_poll.cnt = 0; switch (a) { - case 0: // adapter ctl - r[0] = (r[0] & ~P32XS_FM) | ((d << 8) & P32XS_FM); + case 0x00: // adapter ctl: FM writable + REG8IN16(r, 0x00) = d & 0x80; return; - case 1: // adapter ctl, RES bit writeable + case 0x01: // adapter ctl: RES and ADEN writable if ((d ^ r[0]) & d & P32XS_nRES) p32x_reset_sh2s(); - r[0] = (r[0] & ~P32XS_nRES) | (d & P32XS_nRES); + REG8IN16(r, 0x01) &= ~(P32XS_nRES|P32XS_ADEN); + REG8IN16(r, 0x01) |= d & (P32XS_nRES|P32XS_ADEN); return; - case 3: // irq ctl + case 0x02: // ignored, always 0 + return; + case 0x03: // irq ctl if ((d & 1) != !!(Pico32x.sh2irqi[0] & P32XI_CMD)) { p32x_sync_sh2s(SekCyclesDoneT()); if (d & 1) @@ -254,34 +286,124 @@ static void p32x_reg_write8(u32 a, u32 d) p32x_update_irls(NULL, SekCyclesDoneT2()); } return; - case 5: // bank - d &= 7; - if (r[4 / 2] != d) { - r[4 / 2] = d; + case 0x04: // ignored, always 0 + return; + case 0x05: // bank + d &= 3; + if (r[0x04 / 2] != d) { + r[0x04 / 2] = d; bank_switch(d); } return; - case 7: // DREQ ctl - r[6 / 2] = (r[6 / 2] & P32XS_FULL) | (d & (P32XS_68S|P32XS_DMA|P32XS_RV)); + case 0x06: // ignored, always 0 + return; + case 0x07: // DREQ ctl + REG8IN16(r, 0x07) &= ~(P32XS_68S|P32XS_DMA|P32XS_RV); + if (!(d & P32XS_68S)) { + Pico32x.dmac0_fifo_ptr = 0; + REG8IN16(r, 0x07) &= ~P32XS_FULL; + } + REG8IN16(r, 0x07) |= d & (P32XS_68S|P32XS_DMA|P32XS_RV); + return; + case 0x08: // ignored, always 0 + return; + case 0x09: // DREQ src + REG8IN16(r, 0x09) = d; + return; + case 0x0a: + REG8IN16(r, 0x0a) = d; + return; + case 0x0b: + REG8IN16(r, 0x0b) = d & 0xfe; + return; + case 0x0c: // ignored, always 0 + return; + case 0x0d: // DREQ dest + case 0x0e: + case 0x0f: + case 0x10: // DREQ len + REG8IN16(r, a) = d; + return; + case 0x11: + REG8IN16(r, a) = d & 0xfc; + return; + // DREQ FIFO - writes to odd addr go to fifo + // do writes to even work? Reads return 0 + case 0x12: + REG8IN16(r, a) = d; + return; + case 0x13: + d = (REG8IN16(r, 0x12) << 8) | (d & 0xff); + REG8IN16(r, 0x12) = 0; + dreq0_write(r, d); + return; + case 0x14: // ignored, always 0 + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + return; + case 0x1a: // what's this? + elprintf(EL_32X|EL_ANOMALY, "mystery w8 %02x %02x", a, d); + REG8IN16(r, a) = d & 0x01; return; case 0x1b: // TV - r[0x1a / 2] = d; + REG8IN16(r, a) = d & 0x01; + return; + case 0x1c: // ignored, always 0 + case 0x1d: + case 0x1e: + case 0x1f: + case 0x30: + return; + case 0x31: // PWM control + REG8IN16(r, a) &= ~0x0f; + REG8IN16(r, a) |= d & 0x0f; + goto pwm_write; + case 0x32: // PWM cycle + REG8IN16(r, a) = d & 0x0f; + goto pwm_write; + case 0x33: + REG8IN16(r, a) = d; + goto pwm_write; + // PWM pulse regs.. Only writes to odd address send a value + // to FIFO; reads are 0 (except status bits) + case 0x34: + case 0x36: + case 0x38: + REG8IN16(r, a) = d; + return; + case 0x35: + case 0x37: + case 0x39: + d = (REG8IN16(r, a) << 8) | (d & 0xff); + REG8IN16(r, a) = 0; + goto pwm_write; + case 0x3a: // ignored, always 0 + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + return; + pwm_write: + p32x_pwm_write16(a & ~1, r[a / 2], NULL, SekCyclesDoneT()); return; } if ((a & 0x30) == 0x20) { - u8 *r8 = (u8 *)r; int cycles = SekCyclesDoneT(); int comreg; - if (r8[a ^ 1] == d) + if (REG8IN16(r, a) == d) return; comreg = 1 << (a & 0x0f) / 2; if (Pico32x.comm_dirty_68k & comreg) p32x_sync_sh2s(cycles); - r8[a ^ 1] = d; + 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; @@ -304,35 +426,34 @@ static void p32x_reg_write16(u32 a, u32 d) case 0x00: // adapter ctl if ((d ^ r[0]) & d & P32XS_nRES) p32x_reset_sh2s(); - r[0] = (r[0] & ~(P32XS_FM|P32XS_nRES)) | (d & (P32XS_FM|P32XS_nRES)); + r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN); + r[0] |= d & (P32XS_FM|P32XS_nRES|P32XS_ADEN); + return; + case 0x08: // DREQ src + r[a / 2] = d & 0xff; + return; + case 0x0a: + r[a / 2] = d & ~1; + return; + case 0x0c: // DREQ dest + r[a / 2] = d & 0xff; + return; + case 0x0e: + r[a / 2] = d; return; case 0x10: // DREQ len r[a / 2] = d & ~3; return; case 0x12: // FIFO reg - if (!(r[6 / 2] & P32XS_68S)) { - elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?"); - return; - } - if (Pico32x.dmac0_fifo_ptr < DMAC_FIFO_LEN) { - Pico32x.dmac_fifo[Pico32x.dmac0_fifo_ptr++] = d; - if ((Pico32x.dmac0_fifo_ptr & 3) == 0) - p32x_dreq0_trigger(); - if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN) - r[6 / 2] |= P32XS_FULL; - } - else - elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!"); - break; + dreq0_write(r, d); + return; + case 0x1a: // TV + mystery bit + r[a / 2] = d & 0x0101; + return; } - // DREQ src, dst - if ((a & 0x38) == 0x08) { - r[a / 2] = d; - return; - } // comm port - else if ((a & 0x30) == 0x20) { + if ((a & 0x30) == 0x20) { int cycles = SekCyclesDoneT(); int comreg; @@ -460,13 +581,30 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); sh2s_sync_on_read(sh2); return Pico32x.sh2_regs[4 / 2]; + case 0x06: + return (r[a / 2] & ~P32XS_FULL) | 0x4000; + case 0x08: // DREQ src + case 0x0a: + case 0x0c: // DREQ dst + case 0x0e: case 0x10: // DREQ len return r[a / 2]; + case 0x12: // DREQ FIFO - does this work on hw? + if (Pico32x.dmac0_fifo_ptr > 0) { + Pico32x.dmac0_fifo_ptr--; + r[a / 2] = Pico32x.dmac_fifo[0]; + memmove(&Pico32x.dmac_fifo[0], &Pico32x.dmac_fifo[1], + Pico32x.dmac0_fifo_ptr * 2); + } + return r[a / 2]; + case 0x14: + case 0x16: + case 0x18: + case 0x1a: + case 0x1c: + return 0; // ? } - // DREQ src, dst - if ((a & 0x38) == 0x08) - return r[a / 2]; // comm port if ((a & 0x30) == 0x20) { int comreg = 1 << (a & 0x0f) / 2; @@ -477,10 +615,11 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) sh2s_sync_on_read(sh2); return r[a / 2]; } - if ((a & 0x30) == 0x30) { + if ((a & 0x30) == 0x30) return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2)); - } + elprintf_sh2(sh2, EL_32X|EL_ANOMALY, + "unhandled sysreg r16 [%06x] @%06x", a, SekPc); return 0; } diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index 8b971535..2d5a6dce 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -360,13 +360,13 @@ void sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) /* 32X specific */ static void dreq0_do(SH2 *sh2, struct dma_chan *chan) { - unsigned short *dreqlen = &Pico32x.regs[0x10 / 2]; + unsigned short dreqlen = Pico32x.regs[0x10 / 2]; int i; // debug/sanity checks - if (chan->tcr != *dreqlen) - elprintf(EL_32XP|EL_ANOMALY, "dreq0: tcr0 and len differ: %d != %d", - chan->tcr, *dreqlen); + if (chan->tcr < dreqlen || chan->tcr > dreqlen + 4) + elprintf(EL_32XP|EL_ANOMALY, "dreq0: tcr0/len inconsistent: %d/%d", + chan->tcr, dreqlen); // note: DACK is not connected, single addr mode should not be used if ((chan->chcr & 0x3f08) != 0x0400) elprintf(EL_32XP|EL_ANOMALY, "dreq0: bad control: %04x", chan->chcr); @@ -377,12 +377,11 @@ static void dreq0_do(SH2 *sh2, struct dma_chan *chan) sh2->state |= SH2_STATE_SLEEP; for (i = 0; i < Pico32x.dmac0_fifo_ptr && chan->tcr > 0; i++) { - elprintf(EL_32XP, "dmaw [%08x] %04x, left %d", - chan->dar, Pico32x.dmac_fifo[i], *dreqlen); + elprintf(EL_32XP, "dreq0 [%08x] %04x, dreq_len %d", + chan->dar, Pico32x.dmac_fifo[i], dreqlen); p32x_sh2_write16(chan->dar, Pico32x.dmac_fifo[i], sh2); chan->dar += 2; chan->tcr--; - (*dreqlen)--; } if (Pico32x.dmac0_fifo_ptr != i) @@ -391,8 +390,6 @@ static void dreq0_do(SH2 *sh2, struct dma_chan *chan) Pico32x.dmac0_fifo_ptr -= i; Pico32x.regs[6 / 2] &= ~P32XS_FULL; - if (*dreqlen == 0) - Pico32x.regs[6 / 2] &= ~P32XS_68S; // transfer complete if (chan->tcr == 0) dmac_transfer_complete(sh2, chan); else diff --git a/pico/pico_int.h b/pico/pico_int.h index 53c6f4e7..d6365799 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -489,8 +489,7 @@ typedef struct // peripheral reg access #define PREG8(regs,offs) ((unsigned char *)regs)[offs ^ 3] -// real one is 4*2, but we use more because we don't lockstep -#define DMAC_FIFO_LEN (4*4) +#define DMAC_FIFO_LEN (4*2) #define PWM_BUFF_LEN 1024 // in one channel samples #define SH2_DRCBLK_RAM_SHIFT 1 @@ -511,9 +510,10 @@ struct Pico32x unsigned char sh2irqi[2]; // individual unsigned int sh2irqs; // common irqs unsigned short dmac_fifo[DMAC_FIFO_LEN]; + unsigned int pad[4]; unsigned int dmac0_fifo_ptr; unsigned short vdp_fbcr_fake; - unsigned short pad; + unsigned short pad2; unsigned char comm_dirty_68k; unsigned char comm_dirty_sh2; unsigned char pwm_irq_cnt; From 61801d5bc85c82afc5548fc25fc890bb56f4e763 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 11 Aug 2013 20:30:02 +0300 Subject: [PATCH 07/41] 32x: implement more sh2 peripherals --- pico/32x/32x.c | 1 + pico/32x/sh2soc.c | 122 ++++++++++++++++++++++++++++++++++------------ pico/pico.c | 2 +- 3 files changed, 92 insertions(+), 33 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 0a72ddb7..f29f3275 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -173,6 +173,7 @@ void PicoUnload32x(void) void PicoReset32x(void) { if (PicoAHW & PAHW_32X) { + msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDoneT(); Pico32x.sh2irqs |= P32XI_VRES; p32x_update_irls(NULL, SekCyclesDoneT2()); p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, 0); diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index 2d5a6dce..3802aa92 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -142,7 +142,7 @@ static void dmac_trigger(SH2 *sh2, struct dma_chan *chan) // DREQ0 is only sent after first 4 words are written. // we do multiple of 4 words to avoid messing up alignment - if (chan->sar == 0x20004012) { + if ((chan->sar & ~0x20000000) == 0x00004012) { if (Pico32x.dmac0_fifo_ptr && (Pico32x.dmac0_fifo_ptr & 3) == 0) { elprintf(EL_32XP, "68k -> sh2 DMA"); p32x_dreq0_trigger(); @@ -210,7 +210,11 @@ void p32x_timers_do(unsigned int m68k_slice) void sh2_peripheral_reset(SH2 *sh2) { memset(sh2->peri_regs, 0, sizeof(sh2->peri_regs)); // ? - PREG8(sh2->peri_regs, 4) = 0x84; // SCI SSR + PREG8(sh2->peri_regs, 0x001) = 0xff; // SCI BRR + PREG8(sh2->peri_regs, 0x003) = 0xff; // SCI TDR + PREG8(sh2->peri_regs, 0x004) = 0x84; // SCI SSR + PREG8(sh2->peri_regs, 0x011) = 0x01; // TIER + PREG8(sh2->peri_regs, 0x017) = 0xe0; // TOCR } // ------------------------------------------------------------------ @@ -225,8 +229,8 @@ u32 sh2_peripheral_read8(u32 a, SH2 *sh2) a &= 0x1ff; d = PREG8(r, a); - elprintf(EL_32XP, "%csh2 peri r8 [%08x] %02x @%06x", - sh2->is_slave ? 's' : 'm', a | ~0x1ff, d, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32XP, "peri r8 [%08x] %02x @%06x", + a | ~0x1ff, d, sh2_pc(sh2)); return d; } @@ -238,8 +242,8 @@ u32 sh2_peripheral_read16(u32 a, SH2 *sh2) a &= 0x1ff; d = r[(a / 2) ^ 1]; - elprintf(EL_32XP, "%csh2 peri r16 [%08x] %04x @%06x", - sh2->is_slave ? 's' : 'm', a | ~0x1ff, d, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32XP, "peri r16 [%08x] %04x @%06x", + a | ~0x1ff, d, sh2_pc(sh2)); return d; } @@ -249,40 +253,90 @@ u32 sh2_peripheral_read32(u32 a, SH2 *sh2) a &= 0x1fc; d = sh2->peri_regs[a / 4]; - elprintf(EL_32XP, "%csh2 peri r32 [%08x] %08x @%06x", - sh2->is_slave ? 's' : 'm', a | ~0x1ff, d, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32XP, "peri r32 [%08x] %08x @%06x", + a | ~0x1ff, d, sh2_pc(sh2)); return d; } +static void sci_trigger(SH2 *sh2, u8 *r) +{ + u8 *oregs; + + if (!(PREG8(r, 2) & 0x20)) + return; // transmitter not enabled + if ((PREG8(r, 4) & 0x80)) // TDRE - TransmitDataR Empty + return; + + oregs = (u8 *)sh2->other_sh2->peri_regs; + if (!(PREG8(oregs, 2) & 0x10)) + return; // receiver not enabled + + PREG8(oregs, 5) = PREG8(r, 3); // other.RDR = this.TDR + PREG8(r, 4) |= 0x80; // TDRE - TDR empty + PREG8(oregs, 4) |= 0x40; // RDRF - RDR Full + + // might need to delay these a bit.. + if (PREG8(r, 2) & 0x80) { // TIE - tx irq enabled + int level = PREG8(oregs, 0x60) >> 4; + int vector = PREG8(oregs, 0x64) & 0x7f; + elprintf(EL_32XP, "SCI tx irq (%d, %d)", + level, vector); + sh2_internal_irq(sh2, level, vector); + } + // TODO: TEIE + if (PREG8(oregs, 2) & 0x40) { // RIE - rx irq enabled + int level = PREG8(oregs, 0x60) >> 4; + int vector = PREG8(oregs, 0x63) & 0x7f; + elprintf(EL_32XP, "SCI rx irq (%d, %d)", + level, vector); + sh2_internal_irq(sh2->other_sh2, level, vector); + } +} + void REGPARM(3) sh2_peripheral_write8(u32 a, u32 d, SH2 *sh2) { u8 *r = (void *)sh2->peri_regs; + u8 old; + elprintf(EL_32XP, "%csh2 peri w8 [%08x] %02x @%06x", sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2)); a &= 0x1ff; - PREG8(r, a) = d; + old = PREG8(r, a); - // X-men SCI hack - if ((a == 2 && (d & 0x20)) || // transmiter enabled - (a == 4 && !(d & 0x80))) { // valid data in TDR - void *oregs = sh2->other_sh2->peri_regs; - if ((PREG8(oregs, 2) & 0x50) == 0x50) { // receiver + irq enabled - int level = PREG8(oregs, 0x60) >> 4; - int vector = PREG8(oregs, 0x63) & 0x7f; - elprintf(EL_32XP, "%csh2 SCI recv irq (%d, %d)", - (sh2->is_slave ^ 1) ? 's' : 'm', level, vector); - sh2_internal_irq(sh2->other_sh2, level, vector); - return; + switch (a) { + case 0x002: // SCR - serial control + if (!(PREG8(r, a) & 0x20) && (d & 0x20)) { // TE being set + PREG8(r, a) = d; + sci_trigger(sh2, r); } + break; + case 0x003: // TDR - transmit data + break; + case 0x004: // SSR - serial status + d = (old & (d | 0x06)) | (d & 1); + PREG8(r, a) = d; + sci_trigger(sh2, r); + return; + case 0x005: // RDR - receive data + break; + case 0x010: // TIER + if (d & 0x8e) + elprintf(EL_32XP|EL_ANOMALY, "TIER: %02x", d); + d = (d & 0x8e) | 1; + break; + case 0x017: // TOCR + d |= 0xe0; + break; } + PREG8(r, a) = d; } void REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, SH2 *sh2) { u16 *r = (void *)sh2->peri_regs; - elprintf(EL_32XP, "%csh2 peri w16 [%08x] %04x @%06x", - sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32XP, "peri w16 [%08x] %04x @%06x", + a, d, sh2_pc(sh2)); a &= 0x1ff; @@ -303,17 +357,20 @@ void REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, SH2 *sh2) void sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) { u32 *r = sh2->peri_regs; - elprintf(EL_32XP, "%csh2 peri w32 [%08x] %08x @%06x", - sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2)); + u32 old; + + elprintf_sh2(sh2, EL_32XP, "peri w32 [%08x] %08x @%06x", + a, d, sh2_pc(sh2)); a &= 0x1fc; + old = r[a / 4]; r[a / 4] = d; switch (a) { // division unit (TODO: verify): case 0x104: // DVDNT: divident L, starts divide - elprintf(EL_32XP, "%csh2 divide %08x / %08x", - sh2->is_slave ? 's' : 'm', d, r[0x100 / 4]); + elprintf_sh2(sh2, EL_32XP, "divide %08x / %08x", + d, r[0x100 / 4]); if (r[0x100 / 4]) { signed int divisor = r[0x100 / 4]; r[0x118 / 4] = r[0x110 / 4] = (signed int)d % divisor; @@ -323,8 +380,8 @@ void sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ? break; case 0x114: - elprintf(EL_32XP, "%csh2 divide %08x%08x / %08x @%08x", - sh2->is_slave ? 's' : 'm', r[0x110 / 4], d, r[0x100 / 4], sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32XP, "divide %08x%08x / %08x @%08x", + r[0x110 / 4], d, r[0x100 / 4], sh2_pc(sh2)); if (r[0x100 / 4]) { signed long long divident = (signed long long)r[0x110 / 4] << 32 | d; signed int divisor = r[0x100 / 4]; @@ -334,8 +391,7 @@ void sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) r[0x11c / 4] = r[0x114 / 4] = divident; divident >>= 31; if ((unsigned long long)divident + 1 > 1) { - //elprintf(EL_32XP, "%csh2 divide overflow! @%08x", - // sh2->is_slave ? 's' : 'm', sh2_pc(sh2)); + //elprintf_sh2(sh2, EL_32XP, "divide overflow! @%08x", sh2_pc(sh2)); r[0x11c / 4] = r[0x114 / 4] = divident > 0 ? 0x7fffffff : 0x80000000; // overflow } } @@ -347,6 +403,8 @@ void sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) // perhaps starting a DMA? if (a == 0x1b0 || a == 0x18c || a == 0x19c) { struct dmac *dmac = (void *)&sh2->peri_regs[0x180 / 4]; + if (a == 0x1b0 && !((old ^ d) & d & DMA_DME)) + return; if (!(dmac->dmaor & DMA_DME)) return; @@ -370,8 +428,8 @@ static void dreq0_do(SH2 *sh2, struct dma_chan *chan) // note: DACK is not connected, single addr mode should not be used if ((chan->chcr & 0x3f08) != 0x0400) elprintf(EL_32XP|EL_ANOMALY, "dreq0: bad control: %04x", chan->chcr); - if (chan->sar != 0x20004012) - elprintf(EL_32XP|EL_ANOMALY, "dreq0: bad sar?: %08x\n", chan->sar); + if ((chan->sar & ~0x20000000) != 0x00004012) + elprintf(EL_32XP|EL_ANOMALY, "dreq0: bad sar?: %08x", chan->sar); // HACK: assume bus is busy and SH2 is halted sh2->state |= SH2_STATE_SLEEP; diff --git a/pico/pico.c b/pico/pico.c index 747c6266..7c7a93e7 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -165,7 +165,7 @@ int PicoReset(void) SekReset(); // s68k doesn't have the TAS quirk, so we just globally set normal TAS handler in MCD mode (used by Batman games). SekSetRealTAS(PicoAHW & PAHW_MCD); - SekCycleCntT=0; + SekCycleCntT = SekCycleCnt = SekCycleAim = 0; if (PicoAHW & PAHW_MCD) // needed for MCD to reset properly, probably some bug hides behind this.. From 8a847c12e6a82869b7ff6f1742f53e0da1ad2db6 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 11 Aug 2013 23:49:01 +0300 Subject: [PATCH 08/41] 32x: some timing hacks.. --- pico/32x/memory.c | 18 ++++++++++++++++-- pico/pico_int.h | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pico/32x/memory.c b/pico/32x/memory.c index f9374c47..c6f3a316 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -32,7 +32,7 @@ * sys reg 0004000-00040ff 1 1 * vdp reg 0004100-00041ff 5 5 * vdp pal 0004200-00043ff 5 5 - * rom 2000000-23fffff 6-15 + * cart 2000000-23fffff 6-15 * dram/fb 4000000-401ffff 5-12 1-3 * fb ovr 4020000-403ffff * sdram 6000000-603ffff 12 2 (cycles) @@ -1063,6 +1063,8 @@ static u32 sh2_read8_cs0(u32 a, SH2 *sh2) { u32 d = 0; + sh2_burn_cycles(sh2, 1*2); + // 0x3ff00 is veridied if ((a & 0x3ff00) == 0x4000) { d = p32x_sh2reg_read16(a, sh2); @@ -1116,6 +1118,8 @@ static u32 sh2_read16_cs0(u32 a, SH2 *sh2) { u32 d = 0; + sh2_burn_cycles(sh2, 1*2); + if ((a & 0x3ff00) == 0x4000) { d = p32x_sh2reg_read16(a, sh2); if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM @@ -1206,6 +1210,15 @@ static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2) Pico32xMem->sdram[a1 ^ 1] = d; } +static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2) +{ + // xmen sync hack.. + if (a < 0x26000200) + sh2_end_run(sh2, 32); + + sh2_write8_sdram(a, d, sh2); +} + static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2) { u32 a1 = a & 0xfff; @@ -1609,7 +1622,8 @@ void PicoMemSetup32x(void) // CS3 - SDRAM sh2_read8_map[0x06/2].addr = sh2_read8_map[0x26/2].addr = sh2_read16_map[0x06/2].addr = sh2_read16_map[0x26/2].addr = MAP_MEMORY(Pico32xMem->sdram); - sh2_write8_map[0x06/2] = sh2_write8_map[0x26/2] = sh2_write8_sdram; + sh2_write8_map[0x06/2] = sh2_write8_sdram; + sh2_write8_map[0x26/2] = sh2_write8_sdram_wt; sh2_write16_map[0x06/2] = sh2_write16_map[0x26/2] = sh2_write16_sdram; sh2_read8_map[0x06/2].mask = sh2_read8_map[0x26/2].mask = sh2_read16_map[0x06/2].mask = sh2_read16_map[0x26/2].mask = 0x03ffff; diff --git a/pico/pico_int.h b/pico/pico_int.h index d6365799..2a793e5e 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -251,6 +251,7 @@ extern SH2 sh2s[2]; } \ } while (0) # define sh2_cycles_left(sh2) (sh2)->icount +# define sh2_burn_cycles(sh2, n) (sh2)->icount -= n # define sh2_pc(sh2) (sh2)->ppc #else # define sh2_end_run(sh2, after_) do { \ @@ -262,6 +263,7 @@ extern SH2 sh2s[2]; } \ } while (0) # define sh2_cycles_left(sh2) ((signed int)(sh2)->sr >> 12) +# define sh2_burn_cycles(sh2, n) (sh2)->sr -= ((n) << 12) # define sh2_pc(sh2) (sh2)->pc #endif From f8675e282e7aa72bc6ab0edbb1dada4395d1c44c Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 12 Aug 2013 00:24:19 +0300 Subject: [PATCH 09/41] 32x: simplify logging a bit --- cpu/sh2/compiler.c | 4 ++-- pico/32x/32x.c | 20 ++++++++++---------- pico/32x/memory.c | 38 +++++++++++++++++++------------------- pico/32x/sh2soc.c | 12 ++++++------ pico/pico_int.h | 3 +++ 5 files changed, 40 insertions(+), 37 deletions(-) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 015a0986..103f286f 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -1552,8 +1552,8 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) if (delay_dep_bk & BITMASK1(SHR_PC)) { if (opd->op != OP_LOAD_POOL && opd->op != OP_MOVA) { // can only be those 2 really.. - elprintf(EL_ANOMALY, "%csh2 drc: illegal slot insn %04x @ %08x?", - sh2->is_slave ? 's' : 'm', op, pc - 2); + elprintf_sh2(sh2, EL_ANOMALY, + "drc: illegal slot insn %04x @ %08x?", op, pc - 2); } if (opd->imm != 0) ; // addr already resolved somehow diff --git a/pico/32x/32x.c b/pico/32x/32x.c index f29f3275..f4611876 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -17,12 +17,12 @@ SH2 sh2s[2]; static int REGPARM(2) sh2_irq_cb(SH2 *sh2, int level) { if (sh2->pending_irl > sh2->pending_int_irq) { - elprintf(EL_32X, "%csh2 ack/irl %d @ %08x", - sh2->is_slave ? 's' : 'm', level, sh2->pc); + elprintf_sh2(sh2, EL_32X, "ack/irl %d @ %08x", + level, sh2_pc(sh2)); return 64 + sh2->pending_irl / 2; } else { - elprintf(EL_32X, "%csh2 ack/int %d/%d @ %08x", - sh2->is_slave ? 's' : 'm', level, sh2->pending_int_vector, sh2->pc); + elprintf_sh2(sh2, EL_32X, "ack/int %d/%d @ %08x", + level, sh2->pending_int_vector, sh2_pc(sh2)); sh2->pending_int_irq = 0; // auto-clear sh2->pending_level = sh2->pending_irl; return sh2->pending_int_vector; @@ -323,16 +323,16 @@ static inline void run_sh2(SH2 *sh2, int m68k_cycles) pevt_log_sh2_o(sh2, EVT_RUN_START); sh2->state |= SH2_STATE_RUN; cycles = C_M68K_TO_SH2(*sh2, m68k_cycles); - elprintf(EL_32X, "%csh2 +run %u %d @%08x", - sh2->is_slave?'s':'m', sh2->m68krcycles_done, cycles, sh2->pc); + elprintf_sh2(sh2, EL_32X, "+run %u %d @%08x", + sh2->m68krcycles_done, cycles, sh2->pc); done = sh2_execute(sh2, cycles); sh2->m68krcycles_done += C_SH2_TO_M68K(*sh2, done); sh2->state &= ~SH2_STATE_RUN; pevt_log_sh2_o(sh2, EVT_RUN_END); - elprintf(EL_32X, "%csh2 -run %u %d", - sh2->is_slave?'s':'m', sh2->m68krcycles_done, done); + elprintf_sh2(sh2, EL_32X, "-run %u %d", + sh2->m68krcycles_done, done); } // sync other sh2 to this one @@ -355,8 +355,8 @@ void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target) return; } - elprintf(EL_32X, "%csh2 sync to %u %d", - osh2->is_slave?'s':'m', m68k_target, m68k_cycles); + elprintf_sh2(osh2, EL_32X, "sync to %u %d", + m68k_target, m68k_cycles); run_sh2(osh2, m68k_cycles); diff --git a/pico/32x/memory.c b/pico/32x/memory.c index c6f3a316..c40a3fdd 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -103,7 +103,7 @@ static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags, int maxcnt) if (a == sh2->poll_addr && sh2->poll_cycles - cycles_left <= 10) { if (sh2->poll_cnt++ > maxcnt) { if (!(sh2->state & flags)) - elprintf(EL_32X, "%csh2 state: %02x->%02x", sh2->is_slave?'s':'m', + elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state, sh2->state | flags); sh2->state |= flags; @@ -121,8 +121,8 @@ static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags, int maxcnt) void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles) { if (sh2->state & flags) { - elprintf(EL_32X, "%csh2 state: %02x->%02x", sh2->is_slave?'s':'m', - sh2->state, sh2->state & ~flags); + elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state, + sh2->state & ~flags); if (sh2->m68krcycles_done < m68k_cycles) sh2->m68krcycles_done = m68k_cycles; @@ -1054,8 +1054,8 @@ static void bank_switch(int b) // read8 static u32 sh2_read8_unmapped(u32 a, SH2 *sh2) { - elprintf(EL_UIO, "%csh2 unmapped r8 [%08x] %02x @%06x", - sh2->is_slave ? 's' : 'm', a, 0, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "unmapped r8 [%08x] %02x @%06x", + a, 0, sh2_pc(sh2)); return 0; } @@ -1096,8 +1096,8 @@ out_16to8: else d >>= 8; - elprintf(EL_32X, "%csh2 r8 [%08x] %02x @%06x", - sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "r8 [%08x] %02x @%06x", + a, d, sh2_pc(sh2)); return d; } @@ -1109,8 +1109,8 @@ static u32 sh2_read8_da(u32 a, SH2 *sh2) // read16 static u32 sh2_read16_unmapped(u32 a, SH2 *sh2) { - elprintf(EL_UIO, "%csh2 unmapped r16 [%08x] %04x @%06x", - sh2->is_slave ? 's' : 'm', a, 0, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "unmapped r16 [%08x] %04x @%06x", + a, 0, sh2_pc(sh2)); return 0; } @@ -1146,8 +1146,8 @@ static u32 sh2_read16_cs0(u32 a, SH2 *sh2) return sh2_read16_unmapped(a, sh2); out: - elprintf(EL_32X, "%csh2 r16 [%08x] %04x @%06x", - sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "r16 [%08x] %04x @%06x", + a, d, sh2_pc(sh2)); return d; } @@ -1164,14 +1164,14 @@ static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2) // write8 static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2) { - elprintf(EL_UIO, "%csh2 unmapped w8 [%08x] %02x @%06x", - sh2->is_slave ? 's' : 'm', a, d & 0xff, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "unmapped w8 [%08x] %02x @%06x", + a, d & 0xff, sh2_pc(sh2)); } static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2) { - elprintf(EL_32X, "%csh2 w8 [%08x] %02x @%06x", - sh2->is_slave ? 's' : 'm', a, d & 0xff, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "w8 [%08x] %02x @%06x", + a, d & 0xff, sh2_pc(sh2)); if (Pico32x.regs[0] & P32XS_FM) { if ((a & 0x3ff00) == 0x4100) { @@ -1234,15 +1234,15 @@ static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2) // write16 static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2) { - elprintf(EL_UIO, "%csh2 unmapped w16 [%08x] %04x @%06x", - sh2->is_slave ? 's' : 'm', a, d & 0xffff, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "unmapped w16 [%08x] %04x @%06x", + a, d & 0xffff, sh2_pc(sh2)); } static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2) { if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM - elprintf(EL_32X, "%csh2 w16 [%08x] %04x @%06x", - sh2->is_slave ? 's' : 'm', a, d & 0xffff, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32X, "w16 [%08x] %04x @%06x", + a, d & 0xffff, sh2_pc(sh2)); if (Pico32x.regs[0] & P32XS_FM) { if ((a & 0x3ff00) == 0x4100) { diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index 3802aa92..bdf349f2 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -128,7 +128,7 @@ static void dmac_transfer_one(SH2 *sh2, struct dma_chan *chan) // DMA trigger by SH2 register write static void dmac_trigger(SH2 *sh2, struct dma_chan *chan) { - elprintf(EL_32XP, "sh2 DMA %08x->%08x, cnt %d, chcr %04x @%06x", + elprintf_sh2(sh2, EL_32XP, "DMA %08x->%08x, cnt %d, chcr %04x @%06x", chan->sar, chan->dar, chan->tcr, chan->chcr, sh2->pc); chan->tcr &= 0xffffff; @@ -279,7 +279,7 @@ static void sci_trigger(SH2 *sh2, u8 *r) if (PREG8(r, 2) & 0x80) { // TIE - tx irq enabled int level = PREG8(oregs, 0x60) >> 4; int vector = PREG8(oregs, 0x64) & 0x7f; - elprintf(EL_32XP, "SCI tx irq (%d, %d)", + elprintf_sh2(sh2, EL_32XP, "SCI tx irq (%d, %d)", level, vector); sh2_internal_irq(sh2, level, vector); } @@ -287,7 +287,7 @@ static void sci_trigger(SH2 *sh2, u8 *r) if (PREG8(oregs, 2) & 0x40) { // RIE - rx irq enabled int level = PREG8(oregs, 0x60) >> 4; int vector = PREG8(oregs, 0x63) & 0x7f; - elprintf(EL_32XP, "SCI rx irq (%d, %d)", + elprintf_sh2(sh2->other_sh2, EL_32XP, "SCI rx irq (%d, %d)", level, vector); sh2_internal_irq(sh2->other_sh2, level, vector); } @@ -298,8 +298,8 @@ void REGPARM(3) sh2_peripheral_write8(u32 a, u32 d, SH2 *sh2) u8 *r = (void *)sh2->peri_regs; u8 old; - elprintf(EL_32XP, "%csh2 peri w8 [%08x] %02x @%06x", - sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2)); + elprintf_sh2(sh2, EL_32XP, "peri w8 [%08x] %02x @%06x", + a, d, sh2_pc(sh2)); a &= 0x1ff; old = PREG8(r, a); @@ -435,7 +435,7 @@ static void dreq0_do(SH2 *sh2, struct dma_chan *chan) sh2->state |= SH2_STATE_SLEEP; for (i = 0; i < Pico32x.dmac0_fifo_ptr && chan->tcr > 0; i++) { - elprintf(EL_32XP, "dreq0 [%08x] %04x, dreq_len %d", + elprintf_sh2(sh2, EL_32XP, "dreq0 [%08x] %04x, dreq_len %d", chan->dar, Pico32x.dmac_fifo[i], dreqlen); p32x_sh2_write16(chan->dar, Pico32x.dmac_fifo[i], sh2); chan->dar += 2; diff --git a/pico/pico_int.h b/pico/pico_int.h index 2a793e5e..bba13c95 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -283,6 +283,9 @@ extern SH2 sh2s[2]; #define sh2_set_vbr(c, v) \ { if (c) ssh2.vbr = v; else msh2.vbr = v; } +#define elprintf_sh2(sh2, w, f, ...) \ + elprintf(w,"%csh2 "f,(sh2)->is_slave?'s':'m',##__VA_ARGS__) + // --------------------------------------------------------- // main oscillator clock which controls timing From 001f73a0d62cfaba80738c48b5deea27ab85dfc7 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 12 Aug 2013 00:47:25 +0300 Subject: [PATCH 10/41] 32x: drc: emulate illegal insn The X-Men proto debugger makes it worth it --- cpu/sh2/compiler.c | 47 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 103f286f..106fab50 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -1228,7 +1228,7 @@ static int emit_memhandler_read_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int siz return hr2; } -static void emit_memhandler_write(int size, u32 pc) +static void emit_memhandler_write(int size) { int ctxr; host_arg2reg(ctxr, 2); @@ -1718,7 +1718,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) tmp2 = rcache_get_reg_arg(0, SHR_R0); tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ); emith_add_r_r(tmp2, tmp3); - emit_memhandler_write(op & 3, pc); + emit_memhandler_write(op & 3); goto end_op; case 0x07: // MUL.L Rm,Rn 0000nnnnmmmm0111 @@ -1837,7 +1837,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) tmp2 = rcache_get_reg_arg(1, GET_Rm()); if (op & 0x0f) emith_add_r_imm(tmp, (op & 0x0f) * 4); - emit_memhandler_write(2, pc); + emit_memhandler_write(2); goto end_op; case 0x02: @@ -1849,7 +1849,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) rcache_clean(); rcache_get_reg_arg(0, GET_Rn()); rcache_get_reg_arg(1, GET_Rm()); - emit_memhandler_write(op & 3, pc); + emit_memhandler_write(op & 3); goto end_op; case 0x04: // MOV.B Rm,@-Rn 0010nnnnmmmm0100 case 0x05: // MOV.W Rm,@-Rn 0010nnnnmmmm0101 @@ -1859,7 +1859,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_sub_r_imm(tmp, (1 << (op & 3))); rcache_clean(); rcache_get_reg_arg(0, GET_Rn()); - emit_memhandler_write(op & 3, pc); + emit_memhandler_write(op & 3); goto end_op; case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111 sr = rcache_get_reg(SHR_SR, RC_GR_RMW); @@ -2168,7 +2168,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) tmp3 = rcache_get_reg_arg(1, tmp); if (tmp == SHR_SR) emith_clear_msb(tmp3, tmp3, 22); // reserved bits defined by ISA as 0 - emit_memhandler_write(2, pc); + emit_memhandler_write(2); goto end_op; case 0x04: case 0x05: @@ -2308,7 +2308,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_move_r_r(tmp2, tmp); rcache_free_tmp(tmp); rcache_get_reg_arg(0, GET_Rn()); - emit_memhandler_write(0, pc); + emit_memhandler_write(0); break; default: goto default_; @@ -2468,7 +2468,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) tmp3 = (op & 0x100) >> 8; if (op & 0x0f) emith_add_r_imm(tmp, (op & 0x0f) << tmp3); - emit_memhandler_write(tmp3, pc); + emit_memhandler_write(tmp3); goto end_op; case 0x0400: // MOV.B @(disp,Rm),R0 10000100mmmmdddd case 0x0500: // MOV.W @(disp,Rm),R0 10000101mmmmdddd @@ -2501,7 +2501,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) tmp2 = rcache_get_reg_arg(1, SHR_R0); tmp3 = (op & 0x300) >> 8; emith_add_r_imm(tmp, (op & 0xff) << tmp3); - emit_memhandler_write(tmp3, pc); + emit_memhandler_write(tmp3); goto end_op; case 0x0400: // MOV.B @(disp,GBR),R0 11000100dddddddd case 0x0500: // MOV.W @(disp,GBR),R0 11000101dddddddd @@ -2517,12 +2517,12 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emith_add_r_imm(tmp, 4); tmp = rcache_get_reg_arg(1, SHR_SR); emith_clear_msb(tmp, tmp, 22); - emit_memhandler_write(2, pc); + emit_memhandler_write(2); // push PC rcache_get_reg_arg(0, SHR_SP); tmp = rcache_get_tmp_arg(1); emith_move_r_imm(tmp, pc); - emit_memhandler_write(2, pc); + emit_memhandler_write(2); // obtain new PC emit_memhandler_read_rr(SHR_PC, SHR_VBR, (op & 0xff) * 4, 2); // indirect jump -> back to dispatcher @@ -2574,7 +2574,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) tmp3 = rcache_get_reg_arg(0, SHR_GBR); tmp4 = rcache_get_reg(SHR_R0, RC_GR_READ); emith_add_r_r(tmp3, tmp4); - emit_memhandler_write(0, pc); + emit_memhandler_write(0); goto end_op; } goto default_; @@ -2587,8 +2587,27 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) default: default_: - elprintf(EL_ANOMALY, "%csh2 drc: unhandled op %04x @ %08x", - sh2->is_slave ? 's' : 'm', op, pc - 2); + elprintf_sh2(sh2, EL_ANOMALY, + "drc: illegal op %04x @ %08x", op, pc - 2); + + tmp = rcache_get_reg(SHR_SP, RC_GR_RMW); + emith_sub_r_imm(tmp, 4*2); + // push SR + tmp = rcache_get_reg_arg(0, SHR_SP); + emith_add_r_imm(tmp, 4); + tmp = rcache_get_reg_arg(1, SHR_SR); + emith_clear_msb(tmp, tmp, 22); + emit_memhandler_write(2); + // push PC + rcache_get_reg_arg(0, SHR_SP); + tmp = rcache_get_tmp_arg(1); + emith_move_r_imm(tmp, pc - 2); + emit_memhandler_write(2); + // obtain new PC + emit_memhandler_read_rr(SHR_PC, SHR_VBR, 4 * 4, 2); + // indirect jump -> back to dispatcher + rcache_flush(); + emith_jump(sh2_drc_dispatcher); break; } From b011c2af397e6fa9a9763a130d971915d2362d46 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 12 Aug 2013 01:50:03 +0300 Subject: [PATCH 11/41] pandora: use quad buffering so that ff doesn't tear also fix frame counter overflowing fb --- platform/common/emu.c | 6 ++---- platform/pandora/plat.c | 10 +++++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index 4098bd25..1573d128 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1370,10 +1370,8 @@ void emu_loop(void) sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2); printf("%s\n", fpsbuff); #else - if (currentConfig.EmuOpt & EOPT_SHOW_FPS) { - sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done); - if (fpsbuff[5] == 0) { fpsbuff[5] = fpsbuff[6] = ' '; fpsbuff[7] = 0; } - } + if (currentConfig.EmuOpt & EOPT_SHOW_FPS) + sprintf(fpsbuff, "%02i/%02i ", frames_shown, frames_done); #endif frames_shown = frames_done = 0; timestamp_fps += ms_to_ticks(1000); diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index a9fa9920..306f2c36 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -73,6 +73,7 @@ static struct in_default_bind in_evdev_defbinds[] = { KEY_S, IN_BINDTYPE_PLAYER12, GBTN_B }, { KEY_D, IN_BINDTYPE_PLAYER12, GBTN_C }, { KEY_ENTER, IN_BINDTYPE_PLAYER12, GBTN_START }, + { KEY_F, IN_BINDTYPE_EMU, PEVB_FF }, { KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU }, { KEY_SPACE, IN_BINDTYPE_EMU, PEVB_MENU }, /* Pandora */ @@ -104,10 +105,13 @@ static void osd_text(int x, int y, const char *text) int i, h; len++; + if (x + len > g_screen_width) + len = g_screen_width - x; + for (h = 0; h < 8; h++) { unsigned short *p; p = (unsigned short *)g_screen_ptr + x + g_screen_width*(y + h); - for (i = len; i; i--, p++) + for (i = len; i > 0; i--, p++) *p = (*p>>2) & 0x39e7; } emu_text_out16(x, y, text); @@ -348,7 +352,7 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols) pnd_setup_layer(1, g_layer_x, g_layer_y, g_layer_w, g_layer_h); vout_fbdev_clear(layer_fb); - vout_fbdev_resize(layer_fb, fb_w, fb_h, 16, fb_left, fb_right, fb_top, fb_bottom, 3); + vout_fbdev_resize(layer_fb, fb_w, fb_h, 16, fb_left, fb_right, fb_top, fb_bottom, 4); plat_video_flip(); PicoDrawSetOutFormat(PDF_RGB555, 0); @@ -447,7 +451,7 @@ void plat_init(void) g_menuscreen_ptr = vout_fbdev_flip(main_fb); w = 320; h = 240; - layer_fb = vout_fbdev_init(layer_fb_name, &w, &h, 16, 3); + layer_fb = vout_fbdev_init(layer_fb_name, &w, &h, 16, 4); if (layer_fb == NULL) { fprintf(stderr, "couldn't init fb: %s\n", layer_fb_name); goto fail0; From 5ac99d9adf88799fd2de3ec787409ed1f2255168 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 14 Aug 2013 03:36:36 +0300 Subject: [PATCH 12/41] 32x: add preliminary hint emulation --- pico/32x/32x.c | 31 +++++++++++++++++++++++++++++++ pico/32x/memory.c | 6 +++--- pico/pico_int.h | 2 ++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index f4611876..0d56b982 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -228,6 +228,25 @@ static void p32x_start_blank(void) p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0); } +void p32x_schedule_hint(SH2 *sh2, int m68k_cycles) +{ + // rather rough, 32x hint is useless in practice + int after; + + if (!((Pico32x.sh2irq_mask[0] | Pico32x.sh2irq_mask[1]) & 4)) + return; // nobody cares + // note: when Pico.m.scanline is 224, SH2s might + // still be at scanline 93 (or so) + if (!(Pico32x.sh2_regs[0] & 0x80) && Pico.m.scanline > 224) + return; + + after = (Pico32x.sh2_regs[4 / 2] + 1) * 488; + if (sh2 != NULL) + p32x_event_schedule_sh2(sh2, P32X_EVENT_HINT, after); + else + p32x_event_schedule(m68k_cycles, P32X_EVENT_HINT, after); +} + // compare cycles, handling overflows // check if a > b #define CYCLES_GT(a, b) \ @@ -244,6 +263,13 @@ static void fillend_event(unsigned int now) p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, now); } +static void hint_event(unsigned int now) +{ + Pico32x.sh2irqs |= P32XI_HINT; + p32x_update_irls(NULL, now); + p32x_schedule_hint(NULL, now); +} + typedef void (event_cb)(unsigned int now); unsigned int event_times[P32X_EVENT_COUNT]; @@ -251,6 +277,7 @@ static unsigned int event_time_next; static event_cb *event_cbs[] = { [P32X_EVENT_PWM] = p32x_pwm_irq_event, [P32X_EVENT_FILLEND] = fillend_event, + [P32X_EVENT_HINT] = hint_event, }; // schedule event at some time 'after', in m68k clocks @@ -481,10 +508,14 @@ void sync_sh2s_lockstep(unsigned int m68k_target) void PicoFrame32x(void) { + Pico.m.scanline = 0; + Pico32x.vdp_regs[0x0a/2] &= ~P32XV_VBLK; // get out of vblank if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0) // no forced blanking Pico32x.vdp_regs[0x0a/2] &= ~P32XV_PEN; // no palette access + if (!(Pico32x.sh2_regs[0] & 0x80)) + p32x_schedule_hint(NULL, SekCyclesDoneT2()); p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, 0); p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0); diff --git a/pico/32x/memory.c b/pico/32x/memory.c index c40a3fdd..5d882e37 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -635,13 +635,13 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) Pico32x.regs[0] |= (d << 8) & P32XS_FM; return; case 1: // HEN/irq masks - if ((d ^ Pico32x.sh2_regs[0]) & 0x80) - elprintf(EL_ANOMALY|EL_32X, "HEN"); - Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x8f; + Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f; Pico32x.sh2_regs[0] &= ~0x80; Pico32x.sh2_regs[0] |= d & 0x80; if (d & 1) p32x_pwm_schedule_sh2(sh2); + if (d & 4) + p32x_schedule_hint(sh2, 0); p32x_update_irls(sh2, 0); return; case 5: // H count diff --git a/pico/pico_int.h b/pico/pico_int.h index bba13c95..aa8e4971 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -749,6 +749,7 @@ extern struct Pico32x Pico32x; enum p32x_event { P32X_EVENT_PWM, P32X_EVENT_FILLEND, + P32X_EVENT_HINT, P32X_EVENT_COUNT, }; extern unsigned int event_times[P32X_EVENT_COUNT]; @@ -766,6 +767,7 @@ void p32x_update_irls(SH2 *active_sh2, int m68k_cycles); void p32x_reset_sh2s(void); void p32x_event_schedule(unsigned int now, enum p32x_event event, int after); void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after); +void p32x_schedule_hint(SH2 *sh2, int m68k_cycles); // 32x/memory.c struct Pico32xMem *Pico32xMem; From 1ac97cbbf29855dc91901ff87e59369ea6ba0958 Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 15 Aug 2013 02:12:52 +0300 Subject: [PATCH 13/41] 32x: avoid unnecessary logging --- pico/32x/sh2soc.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index bdf349f2..daa48da2 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -150,6 +150,10 @@ static void dmac_trigger(SH2 *sh2, struct dma_chan *chan) return; } + // DREQ1 + if ((chan->dar & 0xc7fffff0) == 0x00004030) + return; + elprintf(EL_32XP|EL_ANOMALY, "unhandled DMA: " "%08x->%08x, cnt %d, chcr %04x @%06x", chan->sar, chan->dar, chan->tcr, chan->chcr, sh2->pc); @@ -497,8 +501,19 @@ void p32x_dreq1_trigger(void) hit = 1; } - if (!hit) - elprintf(EL_32XP|EL_ANOMALY, "dreq1: nobody cared"); + // debug +#if (EL_LOGMASK & (EL_32XP|EL_ANOMALY)) + { + static int miss_count; + if (!hit) { + if (++miss_count == 4) + elprintf(EL_32XP|EL_ANOMALY, "dreq1: nobody cared"); + } + else + miss_count = 0; + } +#endif + (void)hit; } // vim:shiftwidth=2:ts=2:expandtab From 8ad1d2adf2feb934a687025402ceed4689337fac Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 15 Aug 2013 21:51:27 +0300 Subject: [PATCH 14/41] 32x: improve pwm a bit more --- pico/32x/pwm.c | 54 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index abe745e2..6fe7954c 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -11,6 +11,7 @@ static int pwm_cycles; static int pwm_mult; static int pwm_ptr; static int pwm_irq_reload; +static int pwm_doing_fifo; void p32x_pwm_ctl_changed(void) { @@ -49,21 +50,15 @@ static void do_pwm_irq(SH2 *sh2, unsigned int m68k_cycles) static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles, int sh2_cycles_diff) { - int do_irq = 0; - - if (pwm_cycles == 0) + if (pwm_cycles == 0 || pwm_doing_fifo) return; elprintf(EL_PWM, "pwm: %u: consume %d/%d, %d,%d ptr %d", m68k_cycles, sh2_cycles_diff, sh2_cycles_diff / pwm_cycles, Pico32x.pwm_p[0], Pico32x.pwm_p[1], pwm_ptr); - if (sh2_cycles_diff >= pwm_cycles * 17) { - // silence/skip - Pico32x.pwm_cycle_p = m68k_cycles * 3; - Pico32x.pwm_p[0] = Pico32x.pwm_p[1] = 0; - return; - } + // this is for recursion from dreq1 writes + pwm_doing_fifo = 1; while (sh2_cycles_diff >= pwm_cycles) { struct Pico32xMem *mem = Pico32xMem; @@ -91,15 +86,11 @@ static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles, if (--Pico32x.pwm_irq_cnt == 0) { Pico32x.pwm_irq_cnt = pwm_irq_reload; - // irq also does dreq1, so call it after cycle update - do_irq = 1; - break; + do_pwm_irq(sh2, m68k_cycles); } } Pico32x.pwm_cycle_p = m68k_cycles * 3 - sh2_cycles_diff; - - if (do_irq) - do_pwm_irq(sh2, m68k_cycles); + pwm_doing_fifo = 0; } static int p32x_pwm_schedule_(SH2 *sh2, unsigned int m68k_now) @@ -234,16 +225,29 @@ void p32x_pwm_update(int *buf32, int length, int stereo) int p = 0; int xmd; - xmd = Pico32x.regs[0x30 / 2] & 0x0f; - if ((xmd != 0x05 && xmd != 0x0a) || pwm_ptr <= 16) - goto out; + consume_fifo(NULL, SekCyclesDoneT2()); - step = (pwm_ptr << 16) / length; // FIXME: division.. + xmd = Pico32x.regs[0x30 / 2] & 0x0f; + if (xmd == 0 || xmd == 0x06 || xmd == 0x09 || xmd == 0x0f) + goto out; // invalid? + + step = (pwm_ptr << 16) / length; pwmb = Pico32xMem->pwm; if (stereo) { - if (xmd == 0x0a) { + if (xmd == 0x05) { + // normal + while (length-- > 0) { + *buf32++ += pwmb[0]; + *buf32++ += pwmb[1]; + + p += step; + pwmb += (p >> 16) * 2; + p &= 0xffff; + } + } + else if (xmd == 0x0a) { // channel swap while (length-- > 0) { *buf32++ += pwmb[1]; @@ -255,18 +259,24 @@ void p32x_pwm_update(int *buf32, int length, int stereo) } } else { + // mono - LMD, RMD specify dst + if (xmd & 0x06) // src is R + pwmb++; + if (xmd & 0x0c) // dst is R + buf32++; while (length-- > 0) { - *buf32++ += pwmb[0]; - *buf32++ += pwmb[1]; + *buf32 += *pwmb; p += step; pwmb += (p >> 16) * 2; p &= 0xffff; + buf32 += 2; } } } else { + // mostly unused while (length-- > 0) { *buf32++ += pwmb[0]; From 0219d379de3e8168a94dc4a5f220af04039868fd Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 16 Aug 2013 00:46:25 +0300 Subject: [PATCH 15/41] fixes for idle and other stuff --- Makefile | 2 +- cpu/cyclone | 2 +- cpu/fame/famec_opcodes.h | 6 ++---- cpu/sh2/compiler.c | 1 + pico/pico_int.h | 2 +- pico/sek.c | 27 ++++++++++++++++++++------- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index e6e3b2fc..e923091c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ endif #CFLAGS += -DEVT_LOG #CFLAGS += -DDRC_CMP #cpu_cmp = 1 -#drc_debug = 3 +#drc_debug = 7 #profile = 1 diff --git a/cpu/cyclone b/cpu/cyclone index 1f9661c5..7ddcd35c 160000 --- a/cpu/cyclone +++ b/cpu/cyclone @@ -1 +1 @@ -Subproject commit 1f9661c5a2919ba91c0f4b89985e0712871e5762 +Subproject commit 7ddcd35c8b2a8248257bd89ef989095639c29c08 diff --git a/cpu/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index 76918994..5e09a928 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -40012,20 +40012,18 @@ RET(8) } +extern int SekIsIdleReady(void); extern int SekIsIdleCode(unsigned short *dst, int bytes); extern int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx); OPCODE(idle_detector_bcc8) { - extern int idledet_start_frame; - extern char Pico[]; int frame_count, cond_true, bytes, ret, newop; u16 *dest_pc; dest_pc = PC + (((s8)(Opcode & 0xFE)) >> 1); - frame_count = *(int *)(Pico+0x22208+0x1c); // Pico.m.frame_count - if (frame_count < idledet_start_frame) + if (!SekIsIdleReady()) goto end; bytes = 0 - (s8)(Opcode & 0xFE) - 2; diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 106fab50..4d7adb3c 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -3126,6 +3126,7 @@ int sh2_execute(SH2 *sh2c, int cycles) if (ret_cycles > 0) dbg(1, "warning: drc returned with cycles: %d", ret_cycles); + sh2c->sr &= 0x3f3; return sh2c->cycles_timeslice - ret_cycles; } diff --git a/pico/pico_int.h b/pico/pico_int.h index aa8e4971..bb8fde75 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -353,7 +353,7 @@ struct Pico unsigned short vsram[0x40]; // 0x22180 unsigned char *rom; // 0x22200 - unsigned int romsize; // 0x22204 + unsigned int romsize; // 0x22204 (on 32bits) struct PicoMisc m; struct PicoVideo video; diff --git a/pico/sek.c b/pico/sek.c index 2fe77cbb..5a7b7076 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -268,7 +268,7 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) static unsigned short **idledet_ptrs = NULL; static int idledet_count = 0, idledet_bads = 0; -int idledet_start_frame = 0; +static int idledet_start_frame = 0; #if 0 #define IDLE_STATS 1 @@ -312,6 +312,11 @@ void SekInitIdleDet(void) #endif } +int SekIsIdleReady(void) +{ + return (Pico.m.frame_count >= idledet_start_frame); +} + int SekIsIdleCode(unsigned short *dst, int bytes) { // printf("SekIsIdleCode %04x %i\n", *dst, bytes); @@ -322,11 +327,16 @@ int SekIsIdleCode(unsigned short *dst, int bytes) return 1; break; case 4: - if ( (*dst & 0xfff8) == 0x4a10 || // tst.b ($aX) // there should be no need to wait - (*dst & 0xfff8) == 0x4a28 || // tst.b ($xxxx,a0) // for byte change anywhere - (*dst & 0xff3f) == 0x4a38 || // tst.x ($xxxx.w); tas ($xxxx.w) - (*dst & 0xc1ff) == 0x0038 || // move.x ($xxxx.w), dX - (*dst & 0xf13f) == 0xb038) // cmp.x ($xxxx.w), dX + if ( (*dst & 0xff3f) == 0x4a38 || // tst.x ($xxxx.w); tas ($xxxx.w) + (*dst & 0xc1ff) == 0x0038 || // move.x ($xxxx.w), dX + (*dst & 0xf13f) == 0xb038) // cmp.x ($xxxx.w), dX + return 1; + if (PicoAHW & (PAHW_MCD|PAHW_32X)) + break; + // with no addons, there should be no need to wait + // for byte change anywhere + if ( (*dst & 0xfff8) == 0x4a10 || // tst.b ($aX) + (*dst & 0xfff8) == 0x4a28) // tst.b ($xxxx,a0) return 1; break; case 6: @@ -348,7 +358,9 @@ int SekIsIdleCode(unsigned short *dst, int bytes) return 1; break; case 12: - if ((*dst & 0xf1f8) == 0x3010 && // move.w (aX), dX + if (PicoAHW & (PAHW_MCD|PAHW_32X)) + break; + if ( (*dst & 0xf1f8) == 0x3010 && // move.w (aX), dX (dst[1]&0xf100) == 0x0000 && // arithmetic (dst[3]&0xf100) == 0x0000) // arithmetic return 1; @@ -372,6 +384,7 @@ int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx) is_main68k = ctx == &PicoCpuFM68k; #endif pc &= ~0xff000000; + if (!(newop&0x200)) elprintf(EL_IDLE, "idle: patch %06x %04x %04x %c %c #%i", pc, oldop, newop, (newop&0x200)?'n':'y', is_main68k?'m':'s', idledet_count); From 6b5feebabcf3fe4d136639a14f308005106f5dbf Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 16 Aug 2013 02:11:31 +0300 Subject: [PATCH 16/41] 32x: fix bg color tests --- pico/32x/draw.c | 6 +++--- pico/32x/draw_arm.s | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/pico/32x/draw.c b/pico/32x/draw.c index 33947e6b..66f67a7e 100644 --- a/pico/32x/draw.c +++ b/pico/32x/draw.c @@ -43,7 +43,7 @@ static void convert_pal555(int invert_prio) \ for (i = 320; i > 0; i--, pd++, p32x++, pmd++) { \ unsigned short t = *p32x; \ - if (*pmd != mdbg && !((t ^ inv) & 0x8000)) { \ + if ((*pmd & 0x3f) != mdbg && !((t ^ inv) & 0x8000)) { \ pmd_draw_code; \ continue; \ } \ @@ -59,7 +59,7 @@ static void convert_pal555(int invert_prio) int i; \ for (i = 320; i > 0; i--, pd++, p32x++, pmd++) { \ t = pal[*(unsigned char *)((long)p32x ^ 1)]; \ - if ((t & 0x20) || *pmd == mdbg) \ + if ((t & 0x20) || (*pmd & 0x3f) == mdbg) \ *pd = t; \ else \ pmd_draw_code; \ @@ -74,7 +74,7 @@ static void convert_pal555(int invert_prio) for (i = 320; i > 0; p32x++) { \ t = pal[*p32x & 0xff]; \ for (len = (*p32x >> 8) + 1; len > 0 && i > 0; len--, i--, pd++, pmd++) { \ - if (*pmd == mdbg || (t & 0x20)) \ + if ((*pmd & 0x3f) == mdbg || (t & 0x20)) \ *pd = t; \ else \ pmd_draw_code; \ diff --git a/pico/32x/draw_arm.s b/pico/32x/draw_arm.s index ad50ff3d..ba66fbf1 100644 --- a/pico/32x/draw_arm.s +++ b/pico/32x/draw_arm.s @@ -77,6 +77,7 @@ Pico32xNativePal: ldr r9, =HighPal @ palmd and r4, r2, #0xff mov r5, #328 + lsl r3, #26 @ mdbg << 26 mla r11,r4,r5,r11 @ r11 = pmd = PicoDraw2FB + offs*328: md data tst r10,#P32XV_PRI moveq r10,#0 @@ -107,7 +108,7 @@ Pico32xNativePal: subs r6, r6, #1 blt 0b @ loop_outer ldrh r8, [r5], #2 @ 32x pixel - cmp r7, r3 @ MD has bg pixel? + cmp r3, r7, lsl #26 @ MD has bg pixel? beq 3f @ draw32x eor r12,r8, r10 ands r12,r12,#0x8000 @ !((t ^ inv) & 0x8000) @@ -145,6 +146,7 @@ Pico32xNativePal: ldr r9, =HighPal @ palmd and r4, r2, #0xff mov r5, #328 + lsl r3, #26 @ mdbg << 26 mla r11,r4,r5,r11 @ r11 = pmd = PicoDraw2FB + offs*328: md data call_scan_prep \call_scan @@ -191,14 +193,14 @@ Pico32xNativePal: tst r12,#0x20 ldrneb r12,[r11,#-2] @ MD pixel 0 eor lr, r8, #0x20 - cmpne r12,r3 @ MD has bg pixel? + cmpne r3, r12, lsl #26 @ MD has bg pixel? .if \do_md mov r12,r12,lsl #1 ldrneh r7, [r9, r12] @ t = palmd[pmd[0]] tst lr, #0x20 ldrneb lr, [r11,#-1] @ MD pixel 1 strh r7, [r0], #2 - cmpne lr, r3 @ MD has bg pixel? + cmpne r3, lr, lsl #26 @ MD has bg pixel? mov lr, lr, lsl #1 ldrneh r8, [r9, lr] @ t = palmd[pmd[1]] strh r8, [r0], #2 @@ -207,7 +209,7 @@ Pico32xNativePal: tst lr, #0x20 ldrneb lr, [r11,#-1] @ MD pixel 1 add r0, r0, #4 - cmpne lr, r3 @ MD has bg pixel? + cmpne r3, lr, lsl #26 @ MD has bg pixel? streqh r8, [r0, #-2] .endif b 2b @ loop_inner @@ -265,12 +267,12 @@ Pico32xNativePal: 9: @ bg_mode: ldrb r12,[r11],#1 @ MD pixel ldrb lr, [r11],#1 - cmp r12,r3 @ MD has bg pixel? + cmp r3, lr, lsl #26 @ MD has bg pixel? .if \do_md mov r12,r12,lsl #1 ldrneh r12,[r9, r12] @ t = palmd[*pmd] moveq r12,r7 - cmp lr, r3 + cmp r3, lr, lsl #26 mov lr, lr, lsl #1 ldrneh lr, [r9, lr] moveq lr, r7 @@ -278,7 +280,7 @@ Pico32xNativePal: strh lr, [r0], #2 .else streqh r7, [r0] - cmp lr, r3 + cmp r3, lr, lsl #26 streqh r7, [r0, #2] add r0, r0, #4 .endif @@ -302,6 +304,7 @@ Pico32xNativePal: ldr r9, =HighPal @ palmd and r4, r2, #0xff mov r5, #328 + lsl r3, #26 @ mdbg << 26 mla r11,r4,r5,r11 @ r11 = pmd = PicoDraw2FB + offs*328: md data call_scan_prep \call_scan @@ -335,7 +338,7 @@ Pico32xNativePal: ldrb r7, [r11], #1 @ MD pixel subs r6, r6, #1 blt 0b @ loop_outer - cmp r7, r3 @ MD has bg pixel? + cmp r3, r7, lsl #26 @ MD has bg pixel? mov r7, r7, lsl #1 tstne lr, #0x20 .if \do_md From be7867d8756f15956447d3275382a77a71922feb Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 16 Aug 2013 02:42:56 +0300 Subject: [PATCH 17/41] draw: fix mistake from 9c9cda8c3 --- pico/draw.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pico/draw.c b/pico/draw.c index ede11f5d..f2a8c9ce 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1505,15 +1505,9 @@ void PicoDrawSync(int to, int blank_last_line) for (line = DrawScanline; line < to; line++) { - if (line >= 224) break; PicoLine(line, offs, sh, bgc); } - if (line >= 224) { - DrawScanline = 240; - return; - } - // last line if (line <= to) { From 531a8f38839713938a441f9287724e5e72c492c3 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 17 Aug 2013 03:04:15 +0300 Subject: [PATCH 18/41] improve input handling --- pico/memory.c | 132 +++++++++++++++++++++++++----------- pico/memory_arm.s | 56 ++------------- pico/pico.c | 3 + pico/pico.h | 10 ++- pico/pico_cmn.c | 15 ++-- pico/pico_int.h | 1 - platform/common/emu.c | 10 ++- platform/common/emu.h | 2 + platform/common/menu_pico.c | 9 ++- platform/common/menu_pico.h | 3 +- platform/libretro.c | 36 +++++++++- platform/win32/plat.c | 1 - 12 files changed, 170 insertions(+), 108 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index 88d43f0e..664fd72a 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -186,62 +186,119 @@ void cyclone_crashed(u32 pc, struct Cyclone *context) // ----------------------------------------------------------------- // memmap helpers -#ifndef _ASM_MEMORY_C -static -#endif -int PadRead(int i) +static u32 read_pad_3btn(int i, u32 out_bits) { - int pad,value,data_reg; - pad=~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU - data_reg=Pico.ioports[i+1]; + u32 pad = ~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU + u32 value; - // orr the bits, which are set as output - value = data_reg&(Pico.ioports[i+4]|0x80); + if (out_bits & 0x40) // TH + value = pad & 0x3f; // ?1CB RLDU + else + value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU - if (PicoOpt & POPT_6BTN_PAD) - { - int phase = Pico.m.padTHPhase[i]; - - if(phase == 2 && !(data_reg&0x40)) { // TH - value|=(pad&0xc0)>>2; // ?0SA 0000 - return value; - } else if(phase == 3) { - if(data_reg&0x40) - value|=(pad&0x30)|((pad>>8)&0xf); // ?1CB MXYZ - else - value|=((pad&0xc0)>>2)|0x0f; // ?0SA 1111 - return value; - } - } - - if(data_reg&0x40) // TH - value|=(pad&0x3f); // ?1CB RLDU - else value|=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU - - return value; // will mirror later + value |= out_bits & 0x40; + return value; } -#ifndef _ASM_MEMORY_C +static u32 read_pad_6btn(int i, u32 out_bits) +{ + u32 pad = ~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU + int phase = Pico.m.padTHPhase[i]; + u32 value; -static u32 io_ports_read(u32 a) + if (phase == 2 && !(out_bits & 0x40)) { + value = (pad & 0xc0) >> 2; // ?0SA 0000 + goto out; + } + else if(phase == 3) { + if (out_bits & 0x40) + return (pad & 0x30) | ((pad >> 8) & 0xf); // ?1CB MXYZ + else + return ((pad & 0xc0) >> 2) | 0x0f; // ?0SA 1111 + goto out; + } + + if (out_bits & 0x40) // TH + value = pad & 0x3f; // ?1CB RLDU + else + value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU + +out: + value |= out_bits & 0x40; + return value; +} + +static u32 read_nothing(int i, u32 out_bits) +{ + return 0xff; +} + +typedef u32 (port_read_func)(int index, u32 out_bits); + +static port_read_func *port_readers[3] = { + read_pad_3btn, + read_pad_3btn, + read_nothing +}; + +static NOINLINE u32 port_read(int i) +{ + u32 data_reg = Pico.ioports[i + 1]; + u32 ctrl_reg = Pico.ioports[i + 4] | 0x80; + u32 in, out; + + out = data_reg & ctrl_reg; + out |= 0x7f & ~ctrl_reg; // pull-ups + + in = port_readers[i](i, out); + + return (in & ~ctrl_reg) | (data_reg & ctrl_reg); +} + +void PicoSetInputDevice(int port, enum input_device device) +{ + port_read_func *func; + + if (port < 0 || port > 2) + return; + + switch (device) { + case PICO_INPUT_PAD_3BTN: + func = read_pad_3btn; + break; + + case PICO_INPUT_PAD_6BTN: + func = read_pad_6btn; + break; + + default: + func = read_nothing; + break; + } + + port_readers[port] = func; +} + +NOINLINE u32 io_ports_read(u32 a) { u32 d; a = (a>>1) & 0xf; switch (a) { case 0: d = Pico.m.hardware; break; // Hardware value (Version register) - case 1: d = PadRead(0); break; - case 2: d = PadRead(1); break; + case 1: d = port_read(0); break; + case 2: d = port_read(1); break; + case 3: d = port_read(2); break; default: d = Pico.ioports[a]; break; // IO ports can be used as RAM } return d; } -static void NOINLINE io_ports_write(u32 a, u32 d) +NOINLINE void io_ports_write(u32 a, u32 d) { a = (a>>1) & 0xf; // 6 button gamepad: if TH went from 0 to 1, gamepad changes state - if (1 <= a && a <= 2 && (PicoOpt & POPT_6BTN_PAD)) + if (1 <= a && a <= 2) { Pico.m.padDelay[a - 1] = 0; if (!(Pico.ioports[a] & 0x40) && (d & 0x40)) @@ -252,8 +309,6 @@ static void NOINLINE io_ports_write(u32 a, u32 d) Pico.ioports[a] = d; } -#endif // _ASM_MEMORY_C - void NOINLINE ctl_write_z80busreq(u32 d) { d&=1; d^=1; @@ -1177,3 +1232,4 @@ static void z80_mem_setup(void) #endif } +// vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/memory_arm.s b/pico/memory_arm.s index be2fa995..f6d7f79d 100644 --- a/pico/memory_arm.s +++ b/pico/memory_arm.s @@ -9,7 +9,6 @@ .equ SRR_MAPPED, (1 << 0) .equ SRR_READONLY, (1 << 1) .equ SRF_EEPROM, (1 << 1) -.equ POPT_6BTN_PAD, (1 << 5) .equ POPT_EN_32X, (1 << 20) .text @@ -67,24 +66,7 @@ m_read8_eeprom: PicoRead8_io: @ u32 a, u32 d bic r2, r0, #0x001f @ most commonly we get i/o port read, cmp r2, #0xa10000 @ so check for it first - bne m_read8_not_io - -m_read8_misc_io: - ands r0, r0, #0x1e - beq m_read8_misc_hwreg - cmp r0, #4 - movlt r0, #0 - moveq r0, #1 - ble PadRead - ldr r3, =(Pico+0x22000) - mov r0, r0, lsr #1 @ other IO ports (Pico.ioports[a]) - ldrb r0, [r3, r0] - bx lr - -m_read8_misc_hwreg: - ldr r3, =(Pico+0x22200) - ldrb r0, [r3, #0x0f] @ Pico.m.hardware - bx lr + beq io_ports_read m_read8_not_io: and r2, r0, #0xfc00 @@ -161,7 +143,7 @@ PicoRead16_io: @ u32 a, u32 d cmp r2, #0xa10000 @ so check for it first bne m_read16_not_io stmfd sp!,{lr} - bl m_read8_misc_io @ same as read8 + bl io_ports_read @ same as read8 orr r0, r0, r0, lsl #8 @ only has bytes mirrored ldmfd sp!,{pc} @@ -201,37 +183,7 @@ PicoWrite8_io: @ u32 a, u32 d bic r2, r0, #0x1e @ most commonly we get i/o port write, eor r2, r2, #0xa10000 @ so check for it first eors r2, r2, #1 - bne m_write8_not_io - -m_write8_io: - ldr r2, =PicoOpt - and r0, r0, #0x1e - ldr r2, [r2] - ldr r3, =(Pico+0x22000) @ Pico.ioports - tst r2, #POPT_6BTN_PAD - beq m_write8_io_done - cmp r0, #2 - cmpne r0, #4 - bne m_write8_io_done @ not likely to happen - add r2, r3, #0x200 @ Pico+0x22200 - mov r12,#0 - cmp r0, #2 - streqb r12,[r2,#0x18] - strneb r12,[r2,#0x19] @ Pico.m.padDelay[i] = 0 - tst r1, #0x40 @ TH - beq m_write8_io_done - ldrb r12,[r3, r0, lsr #1] - tst r12,#0x40 - bne m_write8_io_done - cmp r0, #2 - ldreqb r12,[r2,#0x0a] - ldrneb r12,[r2,#0x0b] @ Pico.m.padTHPhase - add r12,r12,#1 - streqb r12,[r2,#0x0a] - strneb r12,[r2,#0x0b] @ Pico.m.padTHPhase -m_write8_io_done: - strb r1, [r3, r0, lsr #1] - bx lr + beq io_ports_write m_write8_not_io: tst r0, #1 @@ -270,7 +222,7 @@ m_write8_not_sreg: PicoWrite16_io: @ u32 a, u32 d bic r2, r0, #0x1f @ most commonly we get i/o port write, cmp r2, #0xa10000 @ so check for it first - beq m_write8_io + beq io_ports_write m_write16_not_io: and r2, r0, #0xff00 diff --git a/pico/pico.c b/pico/pico.c index 7c7a93e7..859935e7 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -70,6 +70,9 @@ void PicoPower(void) Pico.video.pending_ints=0; z80_reset(); + // my MD1 VA6 console has this in IO + Pico.ioports[1] = Pico.ioports[2] = Pico.ioports[3] = 0xff; + // default VDP register values (based on Fusion) Pico.video.reg[0] = Pico.video.reg[1] = 0x04; Pico.video.reg[0xc] = 0x81; diff --git a/pico/pico.h b/pico/pico.h index 0422dfd9..c0aa6da9 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -52,7 +52,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s; #define POPT_EN_Z80 (1<< 2) #define POPT_EN_STEREO (1<< 3) #define POPT_ALT_RENDERER (1<< 4) // 00 00x0 -#define POPT_6BTN_PAD (1<< 5) +// unused (1<< 5) // unused (1<< 6) #define POPT_ACC_SPRITES (1<< 7) #define POPT_DIS_32C_BORDER (1<< 8) // 00 0x00 @@ -248,6 +248,14 @@ int PicoCdCheck(const char *fname_in, int *pregion); extern unsigned char media_id_header[0x100]; +// memory.c +enum input_device { + PICO_INPUT_NOTHING, + PICO_INPUT_PAD_3BTN, + PICO_INPUT_PAD_6BTN, +}; +void PicoSetInputDevice(int port, enum input_device device); + #ifdef __cplusplus } // End of extern "C" #endif diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 2b558c1e..f4e20d21 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -14,11 +14,10 @@ #define CYCLES_S68K_ASD 241 // pad delay (for 6 button pads) -#define PAD_DELAY \ - if (PicoOpt&POPT_6BTN_PAD) { \ - if(Pico.m.padDelay[0]++ > 25) Pico.m.padTHPhase[0]=0; \ - if(Pico.m.padDelay[1]++ > 25) Pico.m.padTHPhase[1]=0; \ - } +#define PAD_DELAY() { \ + if(Pico.m.padDelay[0]++ > 25) Pico.m.padTHPhase[0]=0; \ + if(Pico.m.padDelay[1]++ > 25) Pico.m.padTHPhase[1]=0; \ +} // CPUS_RUN #ifndef CPUS_RUN @@ -114,7 +113,7 @@ static int PicoFrameHints(void) Pico.video.status|=0x200; } - PAD_DELAY + PAD_DELAY(); #ifdef PICO_CD check_cd_dma(); #endif @@ -187,7 +186,7 @@ static int PicoFrameHints(void) Pico.video.status|=0x200; memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt)); - PAD_DELAY + PAD_DELAY(); #ifdef PICO_CD check_cd_dma(); #endif @@ -257,7 +256,7 @@ static int PicoFrameHints(void) pv->v_counter = (pv->v_counter << 1) | 1; pv->v_counter &= 0xff; - PAD_DELAY + PAD_DELAY(); #ifdef PICO_CD check_cd_dma(); #endif diff --git a/pico/pico_int.h b/pico/pico_int.h index bb8fde75..8a760c60 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -598,7 +598,6 @@ unsigned int PicoRead8_io(unsigned int a); unsigned int PicoRead16_io(unsigned int a); void PicoWrite8_io(unsigned int a, unsigned int d); void PicoWrite16_io(unsigned int a, unsigned int d); -void p32x_dreq1_trigger(void); // pico/memory.c PICO_INTERNAL void PicoMemSetupPico(void); diff --git a/platform/common/emu.c b/platform/common/emu.c index 1573d128..5807c1bb 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -455,9 +455,11 @@ int emu_reload_rom(const char *rom_fname_in) // additional movie stuff if (movie_data) { - if (movie_data[0x14] == '6') - PicoOpt |= POPT_6BTN_PAD; // 6 button pad - else PicoOpt &= ~POPT_6BTN_PAD; + enum input_device indev = (movie_data[0x14] == '6') ? + PICO_INPUT_PAD_6BTN : PICO_INPUT_PAD_3BTN; + PicoSetInputDevice(0, indev); + PicoSetInputDevice(1, indev); + PicoOpt |= POPT_DIS_VDP_FIFO; // no VDP fifo timing if (movie_data[0xF] >= 'A') { if (movie_data[0x16] & 0x80) { @@ -550,6 +552,8 @@ void emu_prep_defconfig(void) defaultConfig.s_PicoCDBuffers = 0; defaultConfig.confirm_save = EOPT_CONFIRM_SAVE; defaultConfig.Frameskip = -1; // auto + defaultConfig.input_dev0 = PICO_INPUT_PAD_3BTN; + defaultConfig.input_dev1 = PICO_INPUT_PAD_3BTN; defaultConfig.volume = 50; defaultConfig.gamma = 100; defaultConfig.scaling = 0; diff --git a/platform/common/emu.h b/platform/common/emu.h index 836d7d4b..5138754d 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -57,6 +57,8 @@ typedef struct _currentConfig_t { int s_PicoAutoRgnOrder; int s_PicoCDBuffers; int Frameskip; + int input_dev0; + int input_dev1; int confirm_save; int CPUclock; int volume; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 0745352e..4e9e5948 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -355,12 +355,15 @@ static const char *mgn_dev_name(int id, int *offs) static int mh_saveloadcfg(int id, int keys); static const char *mgn_saveloadcfg(int id, int *offs); +const char *indev_names[] = { "none", "3 button pad", "6 button pad", NULL }; + static menu_entry e_menu_keyconfig[] = { mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap), mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap), mee_handler_id("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap), - mee_onoff ("6 button pad", MA_OPT_6BUTTON_PAD, PicoOpt, POPT_6BTN_PAD), + mee_enum ("Input device 1", MA_OPT_INPUT_DEV0, currentConfig.input_dev0, indev_names), + mee_enum ("Input device 2", MA_OPT_INPUT_DEV1, currentConfig.input_dev1, indev_names), mee_range ("Turbo rate", MA_CTRL_TURBO_RATE, currentConfig.turbo_rate, 1, 30), mee_range ("Analog deadzone", MA_CTRL_DEADZONE, currentConfig.analog_deadzone, 1, 99), mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg), @@ -383,6 +386,10 @@ static int menu_loop_keyconfig(int id, int keys) me_enable(e_menu_keyconfig, MA_OPT_SAVECFG_GAME, PicoGameLoaded); me_loop(e_menu_keyconfig, &sel); + + PicoSetInputDevice(0, currentConfig.input_dev0); + PicoSetInputDevice(1, currentConfig.input_dev1); + return 0; } diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index c609e836..9558ff54 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -24,7 +24,8 @@ typedef enum MA_OPT_ENABLE_SOUND, MA_OPT_SOUND_QUALITY, MA_OPT_ARM940_SOUND, - MA_OPT_6BUTTON_PAD, + MA_OPT_INPUT_DEV0, + MA_OPT_INPUT_DEV1, MA_OPT_REGION, MA_OPT_SRAM_STATES, MA_OPT_CONFIRM_STATES, diff --git a/platform/libretro.c b/platform/libretro.c index d46cc4a2..3ae89740 100644 --- a/platform/libretro.c +++ b/platform/libretro.c @@ -183,6 +183,8 @@ void retro_set_environment(retro_environment_t cb) { static const struct retro_variable vars[] = { //{ "region", "Region; Auto|NTSC|PAL" }, + { "picodrive_input1", "Input device 1; 3 button pad|6 button pad|None" }, + { "picodrive_input2", "Input device 2; 3 button pad|6 button pad|None" }, { NULL, NULL }, }; @@ -545,7 +547,7 @@ bool retro_load_game(const struct retro_game_info *info) enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { - lprintf("RGB565 suppot required, sorry\n"); + lprintf("RGB565 support required, sorry\n"); return false; } @@ -660,13 +662,41 @@ static void snd_write(int len) audio_batch_cb(PsndOut, len / 4); } +static enum input_device input_name_to_val(const char *name) +{ + if (strcmp(name, "3 button pad") == 0) + return PICO_INPUT_PAD_3BTN; + if (strcmp(name, "6 button pad") == 0) + return PICO_INPUT_PAD_6BTN; + if (strcmp(name, "None") == 0) + return PICO_INPUT_NOTHING; + + lprintf("invalid picodrive_input: '%s'\n", name); + return PICO_INPUT_PAD_3BTN; +} + +static void update_variables(void) +{ + struct retro_variable var; + + var.value = NULL; + var.key = "picodrive_input1"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + PicoSetInputDevice(0, input_name_to_val(var.value)); + + var.value = NULL; + var.key = "picodrive_input2"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + PicoSetInputDevice(1, input_name_to_val(var.value)); +} + void retro_run(void) { bool updated = false; int pad, i; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) - ; //update_variables(true); + update_variables(); input_poll_cb(); @@ -720,6 +750,8 @@ void retro_init(void) //PicoMessage = plat_status_msg_busy_next; PicoMCDopenTray = disk_tray_open; PicoMCDcloseTray = disk_tray_close; + + update_variables(); } void retro_deinit(void) diff --git a/platform/win32/plat.c b/platform/win32/plat.c index aa3a7f21..e8f53898 100644 --- a/platform/win32/plat.c +++ b/platform/win32/plat.c @@ -64,7 +64,6 @@ int plat_wait_event(int *fds_hnds, int count, int timeout_ms) void pemu_prep_defconfig(void) { memset(&defaultConfig, 0, sizeof(defaultConfig)); - defaultConfig.s_PicoOpt|= POPT_6BTN_PAD; // for xmen proto defaultConfig.s_PicoCDBuffers = 0; defaultConfig.Frameskip = 0; } From 9e1fa0a6cf997b9e4ad38a532d6a9628253fefa7 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 17 Aug 2013 22:46:07 +0300 Subject: [PATCH 19/41] 32x: improve interrupt handling ..hopefully.. --- pico/32x/32x.c | 40 ++++++++++++++++++++++++++------- pico/32x/memory.c | 57 ++++++++++++++++++++++++++--------------------- pico/32x/pwm.c | 11 +++++---- pico/pico_int.h | 3 +++ 4 files changed, 74 insertions(+), 37 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 0d56b982..0eb2974f 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -39,13 +39,13 @@ void p32x_update_irls(SH2 *active_sh2, int m68k_cycles) m68k_cycles = sh2_cycles_done_m68k(active_sh2); // msh2 - irqs = (Pico32x.sh2irqs | Pico32x.sh2irqi[0]) & ((Pico32x.sh2irq_mask[0] << 3) | P32XI_VRES); + irqs = Pico32x.sh2irqs | Pico32x.sh2irqi[0]; while ((irqs >>= 1)) mlvl++; mlvl *= 2; // ssh2 - irqs = (Pico32x.sh2irqs | Pico32x.sh2irqi[1]) & ((Pico32x.sh2irq_mask[1] << 3) | P32XI_VRES); + irqs = Pico32x.sh2irqs | Pico32x.sh2irqi[1]; while ((irqs >>= 1)) slvl++; slvl *= 2; @@ -67,6 +67,33 @@ void p32x_update_irls(SH2 *active_sh2, int m68k_cycles) elprintf(EL_32X, "update_irls: m %d/%d, s %d/%d", mlvl, mrun, slvl, srun); } +// the mask register is inconsistent, CMD is supposed to be a mask, +// while others are actually irq trigger enables? +// TODO: test on hw.. +void p32x_trigger_irq(SH2 *sh2, int m68k_cycles, unsigned int mask) +{ + Pico32x.sh2irqs |= mask & P32XI_VRES; + Pico32x.sh2irqi[0] |= mask & (Pico32x.sh2irq_mask[0] << 3); + Pico32x.sh2irqi[1] |= mask & (Pico32x.sh2irq_mask[1] << 3); + + p32x_update_irls(sh2, m68k_cycles); +} + +void p32x_update_cmd_irq(SH2 *sh2, int m68k_cycles) +{ + if ((Pico32x.sh2irq_mask[0] & 2) && (Pico32x.regs[2 / 2] & 1)) + Pico32x.sh2irqi[0] |= P32XI_CMD; + else + Pico32x.sh2irqi[0] &= ~P32XI_CMD; + + if ((Pico32x.sh2irq_mask[1] & 2) && (Pico32x.regs[2 / 2] & 2)) + Pico32x.sh2irqi[1] |= P32XI_CMD; + else + Pico32x.sh2irqi[1] &= ~P32XI_CMD; + + p32x_update_irls(sh2, m68k_cycles); +} + void Pico32xStartup(void) { elprintf(EL_STATUS|EL_32X, "32X startup"); @@ -174,8 +201,7 @@ void PicoReset32x(void) { if (PicoAHW & PAHW_32X) { msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDoneT(); - Pico32x.sh2irqs |= P32XI_VRES; - p32x_update_irls(NULL, SekCyclesDoneT2()); + p32x_trigger_irq(NULL, SekCyclesDoneT2(), P32XI_VRES); p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, 0); p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, 0); p32x_pwm_ctl_changed(); @@ -222,8 +248,7 @@ static void p32x_start_blank(void) Pico32xSwapDRAM(Pico32x.pending_fb ^ 1); } - Pico32x.sh2irqs |= P32XI_VINT; - p32x_update_irls(NULL, SekCyclesDoneT2()); + p32x_trigger_irq(NULL, SekCyclesDoneT2(), P32XI_VINT); p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, 0); p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0); } @@ -265,8 +290,7 @@ static void fillend_event(unsigned int now) static void hint_event(unsigned int now) { - Pico32x.sh2irqs |= P32XI_HINT; - p32x_update_irls(NULL, now); + p32x_trigger_irq(NULL, now, P32XI_HINT); p32x_schedule_hint(NULL, now); } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 5d882e37..a6c977b6 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -212,7 +212,7 @@ static u32 p32x_reg_read16(u32 a) unsigned int cycles = SekCyclesDoneT(); if (cycles - msh2.m68krcycles_done > 64) p32x_sync_sh2s(cycles); - return ((Pico32x.sh2irqi[0] & P32XI_CMD) >> 4) | ((Pico32x.sh2irqi[1] & P32XI_CMD) >> 3); + goto out; } if ((a & 0x30) == 0x30) @@ -269,21 +269,11 @@ static void p32x_reg_write8(u32 a, u32 d) case 0x02: // ignored, always 0 return; case 0x03: // irq ctl - if ((d & 1) != !!(Pico32x.sh2irqi[0] & P32XI_CMD)) { - p32x_sync_sh2s(SekCyclesDoneT()); - if (d & 1) - Pico32x.sh2irqi[0] |= P32XI_CMD; - else - Pico32x.sh2irqi[0] &= ~P32XI_CMD; - p32x_update_irls(NULL, SekCyclesDoneT2()); - } - if (!!(d & 2) != !!(Pico32x.sh2irqi[1] & P32XI_CMD)) { - p32x_sync_sh2s(SekCyclesDoneT()); - if (d & 2) - Pico32x.sh2irqi[1] |= P32XI_CMD; - else - Pico32x.sh2irqi[1] &= ~P32XI_CMD; - p32x_update_irls(NULL, SekCyclesDoneT2()); + if ((d ^ r[0x02 / 2]) & 3) { + int cycles = SekCyclesDoneT(); + p32x_sync_sh2s(cycles); + r[0x02 / 2] = d & 3; + p32x_update_cmd_irq(NULL, cycles); } return; case 0x04: // ignored, always 0 @@ -625,8 +615,9 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) { - a &= 0xff; + u32 old; + a &= 0xff; sh2->poll_addr = 0; switch (a) { @@ -635,14 +626,20 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) Pico32x.regs[0] |= (d << 8) & P32XS_FM; return; case 1: // HEN/irq masks + old = Pico32x.sh2irq_mask[sh2->is_slave]; + if ((d ^ old) & 1) + p32x_pwm_sync_to_sh2(sh2); + Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f; Pico32x.sh2_regs[0] &= ~0x80; Pico32x.sh2_regs[0] |= d & 0x80; - if (d & 1) + + if ((d ^ old) & 1) p32x_pwm_schedule_sh2(sh2); - if (d & 4) + if ((old ^ d) & 2) + p32x_update_cmd_irq(sh2, 0); + if ((old ^ d) & 4) p32x_schedule_hint(sh2, 0); - p32x_update_irls(sh2, 0); return; case 5: // H count d &= 0xff; @@ -702,12 +699,22 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) Pico32x.regs[0] &= ~P32XS_FM; Pico32x.regs[0] |= d & P32XS_FM; break; - case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls; - case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls; - case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls; - case 0x1a: Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_CMD; goto irls; + case 0x14: + Pico32x.sh2irqs &= ~P32XI_VRES; + goto irls; + case 0x16: + Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT; + goto irls; + case 0x18: + Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT; + goto irls; + case 0x1a: + Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave); + p32x_update_cmd_irq(sh2, 0); + return; case 0x1c: - Pico32x.sh2irqs &= ~P32XI_PWM; + p32x_pwm_sync_to_sh2(sh2); + Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM; p32x_pwm_schedule_sh2(sh2); goto irls; } diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 6fe7954c..97edb9e7 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -31,8 +31,7 @@ void p32x_pwm_ctl_changed(void) static void do_pwm_irq(SH2 *sh2, unsigned int m68k_cycles) { - Pico32x.sh2irqs |= P32XI_PWM; - p32x_update_irls(sh2, m68k_cycles); + p32x_trigger_irq(sh2, m68k_cycles, P32XI_PWM); if (Pico32x.regs[0x30 / 2] & P32XP_RTP) { p32x_event_schedule(m68k_cycles, P32X_EVENT_PWM, pwm_cycles / 3 + 1); @@ -105,8 +104,6 @@ static int p32x_pwm_schedule_(SH2 *sh2, unsigned int m68k_now) if (cycles_diff_sh2 >= pwm_cycles) consume_fifo_do(sh2, m68k_now, cycles_diff_sh2); - if (Pico32x.sh2irqs & P32XI_PWM) - return 0; // previous not acked if (!((Pico32x.sh2irq_mask[0] | Pico32x.sh2irq_mask[1]) & 1)) return 0; // masked by everyone @@ -129,6 +126,12 @@ void p32x_pwm_schedule_sh2(SH2 *sh2) p32x_event_schedule_sh2(sh2, P32X_EVENT_PWM, after); } +void p32x_pwm_sync_to_sh2(SH2 *sh2) +{ + int m68k_cycles = sh2_cycles_done_m68k(sh2); + consume_fifo(sh2, m68k_cycles); +} + void p32x_pwm_irq_event(unsigned int m68k_now) { p32x_pwm_schedule(m68k_now); diff --git a/pico/pico_int.h b/pico/pico_int.h index 8a760c60..e71245a8 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -763,6 +763,8 @@ void Pico32xStateLoaded(int is_early); void p32x_sync_sh2s(unsigned int m68k_target); void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target); void p32x_update_irls(SH2 *active_sh2, int m68k_cycles); +void p32x_trigger_irq(SH2 *sh2, int m68k_cycles, unsigned int mask); +void p32x_update_cmd_irq(SH2 *sh2, int m68k_cycles); void p32x_reset_sh2s(void); void p32x_event_schedule(unsigned int now, enum p32x_event event, int after); void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after); @@ -803,6 +805,7 @@ void p32x_pwm_update(int *buf32, int length, int stereo); void p32x_pwm_ctl_changed(void); void p32x_pwm_schedule(unsigned int m68k_now); void p32x_pwm_schedule_sh2(SH2 *sh2); +void p32x_pwm_sync_to_sh2(SH2 *sh2); void p32x_pwm_irq_event(unsigned int m68k_now); void p32x_pwm_state_loaded(void); From 77e58d93fe3fd60f3b0adc4b7364713db714c904 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 17 Aug 2013 22:47:08 +0300 Subject: [PATCH 20/41] 32x: more memhandler improvements --- pico/32x/memory.c | 154 +++++++++++++++++++++++++++++++++++++++++----- pico/memory.h | 5 ++ 2 files changed, 144 insertions(+), 15 deletions(-) diff --git a/pico/32x/memory.c b/pico/32x/memory.c index a6c977b6..eabc1b62 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -350,12 +350,15 @@ static void p32x_reg_write8(u32 a, u32 d) case 0x31: // PWM control REG8IN16(r, a) &= ~0x0f; REG8IN16(r, a) |= d & 0x0f; + d = r[0x30 / 2]; goto pwm_write; case 0x32: // PWM cycle REG8IN16(r, a) = d & 0x0f; + d = r[0x32 / 2]; goto pwm_write; case 0x33: REG8IN16(r, a) = d; + d = r[0x32 / 2]; goto pwm_write; // PWM pulse regs.. Only writes to odd address send a value // to FIFO; reads are 0 (except status bits) @@ -367,8 +370,8 @@ static void p32x_reg_write8(u32 a, u32 d) case 0x35: case 0x37: case 0x39: - d = (REG8IN16(r, a) << 8) | (d & 0xff); - REG8IN16(r, a) = 0; + d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff); + REG8IN16(r, a ^ 1) = 0; goto pwm_write; case 0x3a: // ignored, always 0 case 0x3b: @@ -378,7 +381,7 @@ static void p32x_reg_write8(u32 a, u32 d) case 0x3f: return; pwm_write: - p32x_pwm_write16(a & ~1, r[a / 2], NULL, SekCyclesDoneT()); + p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDoneT()); return; } @@ -440,6 +443,11 @@ static void p32x_reg_write16(u32 a, u32 d) case 0x1a: // TV + mystery bit r[a / 2] = d & 0x0101; return; + case 0x30: // PWM control + d = (r[a / 2] & ~0x0f) | (d & 0x0f); + r[a / 2] = d; + p32x_pwm_write16(a, d, NULL, SekCyclesDoneT()); + return; } // comm port @@ -609,23 +617,24 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2)); elprintf_sh2(sh2, EL_32X|EL_ANOMALY, - "unhandled sysreg r16 [%06x] @%06x", a, SekPc); + "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2)); return 0; } static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) { + u16 *r = Pico32x.regs; u32 old; a &= 0xff; sh2->poll_addr = 0; switch (a) { - case 0: // FM - Pico32x.regs[0] &= ~P32XS_FM; - Pico32x.regs[0] |= (d << 8) & P32XS_FM; + case 0x00: // FM + r[0] &= ~P32XS_FM; + r[0] |= (d << 8) & P32XS_FM; return; - case 1: // HEN/irq masks + case 0x01: // HEN/irq masks old = Pico32x.sh2irq_mask[sh2->is_slave]; if ((d ^ old) & 1) p32x_pwm_sync_to_sh2(sh2); @@ -641,7 +650,9 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) if ((old ^ d) & 4) p32x_schedule_hint(sh2, 0); return; - case 5: // H count + case 0x04: // ignored? + return; + case 0x05: // H count d &= 0xff; if (Pico32x.sh2_regs[4 / 2] != d) { Pico32x.sh2_regs[4 / 2] = d; @@ -650,15 +661,53 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) sh2_end_run(sh2, 4); } return; + case 0x30: + REG8IN16(r, a) = d & 0x0f; + d = r[0x30 / 2]; + goto pwm_write; + case 0x31: // PWM control + REG8IN16(r, a) = d & 0x8f; + d = r[0x30 / 2]; + goto pwm_write; + case 0x32: // PWM cycle + REG8IN16(r, a) = d & 0x0f; + d = r[0x32 / 2]; + goto pwm_write; + case 0x33: + REG8IN16(r, a) = d; + d = r[0x32 / 2]; + goto pwm_write; + // PWM pulse regs.. Only writes to odd address send a value + // to FIFO; reads are 0 (except status bits) + case 0x34: + case 0x36: + case 0x38: + REG8IN16(r, a) = d; + return; + case 0x35: + case 0x37: + case 0x39: + d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff); + REG8IN16(r, a ^ 1) = 0; + goto pwm_write; + case 0x3a: // ignored, always 0? + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + return; + pwm_write: + p32x_pwm_write16(a & ~1, d, sh2, 0); + return; } if ((a & 0x30) == 0x20) { - u8 *r8 = (u8 *)Pico32x.regs; int comreg; - if (r8[a ^ 1] == d) + if (REG8IN16(r, a) == d) return; - r8[a ^ 1] = d; + REG8IN16(r, a) = d; p32x_m68k_poll_event(P32XF_68KCPOLL); p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, sh2_cycles_done_m68k(sh2)); @@ -666,6 +715,9 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) Pico32x.comm_dirty_sh2 |= comreg; return; } + + elprintf(EL_32X|EL_ANOMALY, + "unhandled sysreg w8 [%02x] %02x @%08x", a, d, sh2_pc(sh2)); } static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) @@ -816,6 +868,8 @@ static void PicoWrite8_32x_on(u32 a, u32 d) if ((a & 0xfc00) != 0x5000) { PicoWrite8_io(a, d); + if (a == 0xa130f1) + bank_switch(Pico32x.regs[4 / 2]); return; } @@ -849,6 +903,8 @@ static void PicoWrite16_32x_on(u32 a, u32 d) if ((a & 0xfc00) != 0x5000) { PicoWrite16_io(a, d); + if (a == 0xa130f0) + bank_switch(Pico32x.regs[4 / 2]); return; } @@ -1014,7 +1070,8 @@ static void PicoWrite8_hint(u32 a, u32 d) return; } - elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", + a, d & 0xff, SekPc); } static void PicoWrite16_hint(u32 a, u32 d) @@ -1024,7 +1081,64 @@ static void PicoWrite16_hint(u32 a, u32 d) return; } - elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", + a, d & 0xffff, SekPc); +} + +// normally not writable, but somebody could make a RAM cart +static void PicoWrite8_cart(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + + a &= 0xfffff; + m68k_write8(a, d); +} + +static void PicoWrite16_cart(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + + a &= 0xfffff; + m68k_write16(a, d); +} + +// same with bank, but save ram is sometimes here +static u32 PicoRead8_bank(u32 a) +{ + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + return m68k_read8(a); +} + +static u32 PicoRead16_bank(u32 a) +{ + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + return m68k_read16(a); +} + +static void PicoWrite8_bank(u32 a, u32 d) +{ + if (!(Pico.m.sram_reg & SRR_MAPPED)) + elprintf(EL_UIO, "m68k w8 [%06x] %02x @%06x", + a, d & 0xff, SekPc); + + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + m68k_write8(a, d); +} + +static void PicoWrite16_bank(u32 a, u32 d) +{ + if (!(Pico.m.sram_reg & SRR_MAPPED)) + elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", + a, d & 0xffff, SekPc); + + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + m68k_write16(a, d); +} + +static void bank_map_handler(void) +{ + cpu68k_map_set(m68k_read8_map, 0x900000, 0x9fffff, PicoRead8_bank, 1); + cpu68k_map_set(m68k_read16_map, 0x900000, 0x9fffff, PicoRead16_bank, 1); } static void bank_switch(int b) @@ -1032,8 +1146,14 @@ static void bank_switch(int b) unsigned int rs, bank; bank = b << 20; + if ((Pico.m.sram_reg & SRR_MAPPED) && bank == SRam.start) { + bank_map_handler(); + return; + } + if (bank >= Pico.romsize) { elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank); + bank_map_handler(); return; } @@ -1358,7 +1478,7 @@ u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2) return (pd[0] << 16) | pd[1]; } - if (offs == 0x1f) + if (offs == SH2MAP_ADDR2OFFS_R(0xffffc000)) return sh2_peripheral_read32(a, sh2); handler = (sh2_read_handler *)(p << 1); @@ -1579,6 +1699,8 @@ void PicoMemSetup32x(void) rs = 0x80000; cpu68k_map_set(m68k_read8_map, 0x880000, 0x880000 + rs - 1, Pico.rom, 0); cpu68k_map_set(m68k_read16_map, 0x880000, 0x880000 + rs - 1, Pico.rom, 0); + cpu68k_map_set(m68k_write8_map, 0x880000, 0x880000 + rs - 1, PicoWrite8_cart, 1); + cpu68k_map_set(m68k_write16_map, 0x880000, 0x880000 + rs - 1, PicoWrite16_cart, 1); #ifdef EMU_F68K // setup FAME fetchmap PicoCpuFM68k.Fetch[0] = (unsigned long)Pico32xMem->m68k_rom; @@ -1588,6 +1710,8 @@ void PicoMemSetup32x(void) // 32X ROM (banked) bank_switch(0); + cpu68k_map_set(m68k_write8_map, 0x900000, 0x9fffff, PicoWrite8_bank, 1); + cpu68k_map_set(m68k_write16_map, 0x900000, 0x9fffff, PicoWrite16_bank, 1); // SYS regs cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_32x_on, 1); diff --git a/pico/memory.h b/pico/memory.h index 1fd7fc15..44213714 100644 --- a/pico/memory.h +++ b/pico/memory.h @@ -26,6 +26,11 @@ extern uptr s68k_write16_map[0x1000000 >> M68K_MEM_SHIFT]; typedef u32 (cpu68k_read_f)(u32 a); typedef void (cpu68k_write_f)(u32 a, u32 d); +extern u32 m68k_read8(u32 a); +extern u32 m68k_read16(u32 a); +extern void m68k_write8(u32 a, u8 d); +extern void m68k_write16(u32 a, u16 d); + // z80 #define Z80_MEM_SHIFT 13 extern uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT]; From 419973a6d6cb92f96a60f1d5ccda0beb8b28b15d Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 18 Aug 2013 02:43:52 +0300 Subject: [PATCH 21/41] 32x: some hacks.. --- pico/32x/32x.c | 2 ++ pico/32x/memory.c | 22 +++++++++++++++++++++- pico/pico_int.h | 5 +++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 0eb2974f..ab522e41 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -523,6 +523,8 @@ void sync_sh2s_lockstep(unsigned int m68k_target) #define CPUS_RUN(m68k_cycles,s68k_cycles) do { \ SekRunM68k(m68k_cycles); \ + if (Pico32x.emu_flags & P32XF_Z80_32X_IO) \ + PicoSyncZ80(SekCycleCnt); \ if (Pico32x.emu_flags & (P32XF_68KCPOLL|P32XF_68KVPOLL)) \ p32x_sync_sh2s(SekCyclesDoneT2()); \ } while (0) diff --git a/pico/32x/memory.c b/pico/32x/memory.c index eabc1b62..08e48e86 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -195,8 +195,10 @@ static u32 p32x_reg_read16(u32 a) m68k_poll.cnt = 0; dr2 = SekDar(2); - if (cycles - msh2.m68krcycles_done > 500) + if (cycles - msh2.m68krcycles_done > 244 + || (Pico32x.comm_dirty_68k & 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)) { @@ -1523,6 +1525,21 @@ void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2) // ----------------------------------------------------------------- +static void z80_md_bank_write_32x(unsigned int a, unsigned char d) +{ + unsigned int addr68k; + + addr68k = Pico.m.z80_bank68k << 15; + addr68k += a & 0x7fff; + if ((addr68k & 0xfff000) == 0xa15000) + Pico32x.emu_flags |= P32XF_Z80_32X_IO; + + elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, d); + m68k_write8(addr68k, d); +} + +// ----------------------------------------------------------------- + static const u16 msh2_code[] = { // trap instructions 0xaffe, // bra @@ -1779,6 +1796,9 @@ void PicoMemSetup32x(void) sh2_drc_mem_setup(&msh2); sh2_drc_mem_setup(&ssh2); + + // z80 hack + z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write_32x, 1); } void Pico32xMemStateLoaded(void) diff --git a/pico/pico_int.h b/pico/pico_int.h index e71245a8..a4f446b4 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -482,8 +482,9 @@ typedef struct #define P32XP_FULL (1<<15) // PWM pulse #define P32XP_EMPTY (1<<14) -#define P32XF_68KCPOLL (1 << 0) -#define P32XF_68KVPOLL (1 << 1) +#define P32XF_68KCPOLL (1 << 0) +#define P32XF_68KVPOLL (1 << 1) +#define P32XF_Z80_32X_IO (1 << 7) // z80 does 32x io #define P32XI_VRES (1 << 14/2) // IRL/2 #define P32XI_VINT (1 << 12/2) From 8ce9c3a782e47ed355a12789859e5359c4a81e77 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 18 Aug 2013 19:32:56 +0300 Subject: [PATCH 22/41] 32x: pwm pop reduction hacks --- pico/32x/pwm.c | 57 ++++++++++++++++++++++++++++++++++--------------- pico/pico_int.h | 3 ++- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 97edb9e7..6f9cd07e 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -12,6 +12,7 @@ static int pwm_mult; static int pwm_ptr; static int pwm_irq_reload; static int pwm_doing_fifo; +static int pwm_silent; void p32x_pwm_ctl_changed(void) { @@ -20,7 +21,12 @@ void p32x_pwm_ctl_changed(void) cycles = (cycles - 1) & 0x0fff; pwm_cycles = cycles; - pwm_mult = 0x10000 / cycles; + + // supposedly we should stop FIFO when xMd is 0, + // but mars test disagrees + pwm_mult = 0; + if ((control & 0x0f) != 0) + pwm_mult = 0x10000 / cycles; pwm_irq_reload = (control & 0x0f00) >> 8; pwm_irq_reload = ((pwm_irq_reload - 1) & 0x0f) + 1; @@ -40,6 +46,15 @@ static void do_pwm_irq(SH2 *sh2, unsigned int m68k_cycles) } } +static int convert_sample(unsigned int v) +{ + if (v == 0) + return 0; + if (v > pwm_cycles) + v = pwm_cycles; + return ((int)v - pwm_cycles / 2) * pwm_mult; +} + #define consume_fifo(sh2, m68k_cycles) { \ int cycles_diff = ((m68k_cycles) * 3) - Pico32x.pwm_cycle_p; \ if (cycles_diff >= pwm_cycles) \ @@ -49,6 +64,11 @@ static void do_pwm_irq(SH2 *sh2, unsigned int m68k_cycles) static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles, int sh2_cycles_diff) { + struct Pico32xMem *mem = Pico32xMem; + unsigned short *fifo_l = mem->pwm_fifo[0]; + unsigned short *fifo_r = mem->pwm_fifo[1]; + int sum = 0; + if (pwm_cycles == 0 || pwm_doing_fifo) return; @@ -59,30 +79,29 @@ static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles, // this is for recursion from dreq1 writes pwm_doing_fifo = 1; - while (sh2_cycles_diff >= pwm_cycles) { - struct Pico32xMem *mem = Pico32xMem; - short *fifo_l = mem->pwm_fifo[0]; - short *fifo_r = mem->pwm_fifo[1]; - + for (; sh2_cycles_diff >= pwm_cycles; sh2_cycles_diff -= pwm_cycles) + { if (Pico32x.pwm_p[0] > 0) { fifo_l[0] = fifo_l[1]; fifo_l[1] = fifo_l[2]; fifo_l[2] = fifo_l[3]; Pico32x.pwm_p[0]--; + mem->pwm_current[0] = convert_sample(fifo_l[0]); + sum += mem->pwm_current[0]; } if (Pico32x.pwm_p[1] > 0) { fifo_r[0] = fifo_r[1]; fifo_r[1] = fifo_r[2]; fifo_r[2] = fifo_r[3]; Pico32x.pwm_p[1]--; + mem->pwm_current[1] = convert_sample(fifo_r[0]); + sum += mem->pwm_current[1]; } - mem->pwm[pwm_ptr * 2 ] = fifo_l[0]; - mem->pwm[pwm_ptr * 2 + 1] = fifo_r[0]; + mem->pwm[pwm_ptr * 2 ] = mem->pwm_current[0]; + mem->pwm[pwm_ptr * 2 + 1] = mem->pwm_current[1]; pwm_ptr = (pwm_ptr + 1) & (PWM_BUFF_LEN - 1); - sh2_cycles_diff -= pwm_cycles; - if (--Pico32x.pwm_irq_cnt == 0) { Pico32x.pwm_irq_cnt = pwm_irq_reload; do_pwm_irq(sh2, m68k_cycles); @@ -90,6 +109,8 @@ static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles, } Pico32x.pwm_cycle_p = m68k_cycles * 3 - sh2_cycles_diff; pwm_doing_fifo = 0; + if (sum != 0) + pwm_silent = 0; } static int p32x_pwm_schedule_(SH2 *sh2, unsigned int m68k_now) @@ -182,8 +203,9 @@ void p32x_pwm_write16(unsigned int a, unsigned int d, a &= 0x0e; if (a == 0) { // control - // supposedly we should stop FIFO when xMd is 0, - // but mars test disagrees + // avoiding pops.. + if ((Pico32x.regs[0x30 / 2] & 0x0f) == 0) + Pico32xMem->pwm_fifo[0][0] = Pico32xMem->pwm_fifo[1][0] = 0; Pico32x.regs[0x30 / 2] = d; p32x_pwm_ctl_changed(); Pico32x.pwm_irq_cnt = pwm_irq_reload; // ? @@ -194,12 +216,9 @@ void p32x_pwm_write16(unsigned int a, unsigned int d, } else if (a <= 8) { d = (d - 1) & 0x0fff; - if (d > pwm_cycles) - d = pwm_cycles; - d = (d - pwm_cycles / 2) * pwm_mult; if (a == 4 || a == 8) { // L ch or MONO - short *fifo = Pico32xMem->pwm_fifo[0]; + unsigned short *fifo = Pico32xMem->pwm_fifo[0]; if (Pico32x.pwm_p[0] < 3) Pico32x.pwm_p[0]++; else { @@ -209,7 +228,7 @@ void p32x_pwm_write16(unsigned int a, unsigned int d, fifo[Pico32x.pwm_p[0]] = d; } if (a == 6 || a == 8) { // R ch or MONO - short *fifo = Pico32xMem->pwm_fifo[1]; + unsigned short *fifo = Pico32xMem->pwm_fifo[1]; if (Pico32x.pwm_p[1] < 3) Pico32x.pwm_p[1]++; else { @@ -233,6 +252,8 @@ void p32x_pwm_update(int *buf32, int length, int stereo) xmd = Pico32x.regs[0x30 / 2] & 0x0f; if (xmd == 0 || xmd == 0x06 || xmd == 0x09 || xmd == 0x0f) goto out; // invalid? + if (pwm_silent) + return; step = (pwm_ptr << 16) / length; pwmb = Pico32xMem->pwm; @@ -294,6 +315,8 @@ void p32x_pwm_update(int *buf32, int length, int stereo) out: pwm_ptr = 0; + pwm_silent = Pico32xMem->pwm_current[0] == 0 + && Pico32xMem->pwm_current[1] == 0; } void p32x_pwm_state_loaded(void) diff --git a/pico/pico_int.h b/pico/pico_int.h index a4f446b4..6b062b6a 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -548,7 +548,8 @@ struct Pico32xMem unsigned short pal[0x100]; unsigned short pal_native[0x100]; // converted to native (for renderer) signed short pwm[2*PWM_BUFF_LEN]; // PWM buffer for current frame - signed short pwm_fifo[2][4]; // [0] - current, others - fifo entries + signed short pwm_current[2]; // current converted samples + unsigned short pwm_fifo[2][4]; // [0] - current raw, others - fifo entries }; // area.c From eb35ce1506c38b63fede2490078b34a19f5baeb0 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 19 Aug 2013 03:02:36 +0300 Subject: [PATCH 23/41] 32x: some mapping corrections --- cpu/sh2/compiler.c | 3 ++- pico/32x/memory.c | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 4d7adb3c..0b59920b 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -3308,7 +3308,8 @@ static void *dr_get_pc_base(u32 pc, int is_slave) } else if ((pc & 0xc6000000) == 0x02000000) { // ROM - ret = Pico.rom; + if ((pc & 0x3fffff) < Pico.romsize) + ret = Pico.rom; mask = 0x3fffff; } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 08e48e86..3b12cbbd 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -571,7 +571,7 @@ static void p32x_vdp_write16(u32 a, u32 d, SH2 *sh2) static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) { u16 *r = Pico32x.regs; - a &= 0xfe; // ? + a &= 0x3e; switch (a) { case 0x00: // adapter/irq ctl @@ -628,7 +628,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) u16 *r = Pico32x.regs; u32 old; - a &= 0xff; + a &= 0x3f; sh2->poll_addr = 0; switch (a) { @@ -724,7 +724,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) { - a &= 0xfe; + a &= 0x3e; sh2->poll_addr = 0; @@ -1194,13 +1194,13 @@ static u32 sh2_read8_cs0(u32 a, SH2 *sh2) sh2_burn_cycles(sh2, 1*2); - // 0x3ff00 is veridied - if ((a & 0x3ff00) == 0x4000) { + // 0x3ffc0 is veridied + if ((a & 0x3ffc0) == 0x4000) { d = p32x_sh2reg_read16(a, sh2); goto out_16to8; } - if ((a & 0x3ff00) == 0x4100) { + if ((a & 0x3fff0) == 0x4100) { d = p32x_vdp_read16(a); sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7); goto out_16to8; @@ -1249,14 +1249,14 @@ static u32 sh2_read16_cs0(u32 a, SH2 *sh2) sh2_burn_cycles(sh2, 1*2); - if ((a & 0x3ff00) == 0x4000) { + if ((a & 0x3ffc0) == 0x4000) { d = p32x_sh2reg_read16(a, sh2); if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM return d; goto out; } - if ((a & 0x3ff00) == 0x4100) { + if ((a & 0x3fff0) == 0x4100) { d = p32x_vdp_read16(a); sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7); goto out; @@ -1303,14 +1303,14 @@ static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2) a, d & 0xff, sh2_pc(sh2)); if (Pico32x.regs[0] & P32XS_FM) { - if ((a & 0x3ff00) == 0x4100) { + if ((a & 0x3fff0) == 0x4100) { sh2->poll_addr = 0; p32x_vdp_write8(a, d); return; } } - if ((a & 0x3ff00) == 0x4000) { + if ((a & 0x3ffc0) == 0x4000) { p32x_sh2reg_write8(a, d, sh2); return; } @@ -1374,7 +1374,7 @@ static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2) a, d & 0xffff, sh2_pc(sh2)); if (Pico32x.regs[0] & P32XS_FM) { - if ((a & 0x3ff00) == 0x4100) { + if ((a & 0x3fff0) == 0x4100) { sh2->poll_addr = 0; p32x_vdp_write16(a, d, sh2); return; @@ -1387,7 +1387,7 @@ static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2) } } - if ((a & 0x3ff00) == 0x4000) { + if ((a & 0x3ffc0) == 0x4000) { p32x_sh2reg_write16(a, d, sh2); return; } From a76fad41291b7be0b42554353d6775dcdff065e0 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 20 Aug 2013 00:54:03 +0300 Subject: [PATCH 24/41] 32x: add 6btn quirk --- pico/cart.c | 5 +++++ pico/carthw.cfg | 13 +++++++++---- pico/carthw_cfg.c | 10 ++++++---- pico/media.c | 4 ++++ pico/pico.c | 1 + pico/pico.h | 4 ++++ platform/common/emu.c | 4 ++++ 7 files changed, 33 insertions(+), 8 deletions(-) diff --git a/pico/cart.c b/pico/cart.c index db742a8b..6a835b63 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -643,6 +643,8 @@ static int rom_strcmp(int rom_offset, const char *s1) { int i, len = strlen(s1); const char *s_rom = (const char *)Pico.rom; + if (rom_offset + len > Pico.romsize) + return 0; for (i = 0; i < len; i++) if (s1[i] != s_rom[(i + rom_offset) ^ 1]) return 1; @@ -897,10 +899,13 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) SRam.flags &= ~SRF_EEPROM; else if (strcmp(p, "filled_sram") == 0) *fill_sram = 1; + else if (strcmp(p, "force_6btn") == 0) + PicoQuirks |= PQUIRK_FORCE_6BTN; else { elprintf(EL_STATUS, "carthw:%d: unsupported prop: %s", line, p); goto bad_nomsg; } + elprintf(EL_STATUS, "game prop: %s", p); continue; } else if (is_expr("eeprom_type", &p)) { diff --git a/pico/carthw.cfg b/pico/carthw.cfg index ac918bfc..d61161c6 100644 --- a/pico/carthw.cfg +++ b/pico/carthw.cfg @@ -8,6 +8,7 @@ # no_sram - don't emulate sram/EEPROM even if ROM headers tell it's there # no_eeprom - save storage is not EEPROM, even if ROM headers tell it is # filled_sram - save storage needs to be initialized with FFh instead of 00h +# force_6btn - game only supports 6 button pad (32X X-men proto) # # mappers (hw = ...): # ssf2_mapper - used in Super Street Fighter2 @@ -60,6 +61,12 @@ prop = filled_sram check_str = 0x150, "MICRO MACHINES II" prop = filled_sram +# X-Men proto +[X-Men (prototype)] +check_str = 0x150, "32X SAMPLE PROGRAM" +check_str = 0x32b74c, "Bishop Level" +prop = force_6btn + # The SSF2 mapper [Super Street Fighter II - The New Challengers (U)] check_str = 0x150, "SUPER STREET FIGHTER2 The New Challengers" @@ -68,11 +75,9 @@ prop = no_sram # The Pier Solar mapper, custom eeprom location [Pier Solar and the Great Architects] -check_str = 0x150, "PIER SOLAR™&THE GREAT ARCHITECTS© WaterMelon™" +check_str = 0x150, "PIER" +check_str = 0x610, "Respect" hw = piersolar_mapper -sram_range = 0xa13009,0xa1300b -eeprom_type = 3 -eeprom_lines = 2,1,0 # detect *_in_1 based on first game and if it's larger than it should be, # as some dumps look like to be incomplete. diff --git a/pico/carthw_cfg.c b/pico/carthw_cfg.c index 14aec3e8..0974fa02 100644 --- a/pico/carthw_cfg.c +++ b/pico/carthw_cfg.c @@ -22,15 +22,17 @@ static const char builtin_carthw_cfg[] = "check_str=0x150,\"MICRO MACHINES II\"\n" "prop=filled_sram\n" "[]\n" + "check_str=0x150,\"32X SAMPLE PROGRAM\"\n" + "check_str=0x32b74c,\"Bishop Level\"\n" + "prop=force_6btn\n" + "[]\n" "check_str=0x150,\"SUPER STREET FIGHTER2 The New Challengers\"\n" "hw=ssf2_mapper\n" "prop=no_sram\n" "[]\n" - "check_str=0x150,\"PIER SOLAR\x99&THE GREAT ARCHITECTS\xa9 WaterMelon\x99\"\n" + "check_str=0x150,\"PIER\"\n" + "check_str=0x610,\"Respect\"\n" "hw=piersolar_mapper\n" - "sram_range=0xa13009,0xa1300b\n" - "eeprom_type=3\n" - "eeprom_lines=2,1,0\n" "[]\n" "check_str=0x120,\"FLICKY\"\n" "check_size_gt=0x020000\n" diff --git a/pico/media.c b/pico/media.c index ade8dedf..c03846d8 100644 --- a/pico/media.c +++ b/pico/media.c @@ -212,6 +212,7 @@ enum media_type_e PicoLoadMedia(const char *filename, Stop_CD(); PicoCartUnload(); PicoAHW = 0; + PicoQuirks = 0; if (media_type == PM_CD) { @@ -296,6 +297,9 @@ enum media_type_e PicoLoadMedia(const char *filename, } } + if (PicoQuirks & PQUIRK_FORCE_6BTN) + PicoSetInputDevice(0, PICO_INPUT_PAD_6BTN); + out: if (rom_data) free(rom_data); diff --git a/pico/pico.c b/pico/pico.c index 859935e7..bbc514fe 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -16,6 +16,7 @@ int PicoSkipFrame; // skip rendering frame? int PicoPad[2]; // Joypads, format is MXYZ SACB RLDU int PicoPadInt[2]; // internal copy int PicoAHW; // active addon hardware: PAHW_* +int PicoQuirks; // game-specific quirks int PicoRegionOverride; // override the region detection 0: Auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe int PicoAutoRgnOrder; diff --git a/pico/pico.h b/pico/pico.h index c0aa6da9..e1bcf03d 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -77,6 +77,10 @@ extern int PicoOpt; // bitfield #define PAHW_PICO (1<<3) #define PAHW_SMS (1<<4) extern int PicoAHW; // Pico active hw + +#define PQUIRK_FORCE_6BTN (1<<0) +extern int PicoQuirks; + extern int PicoSkipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff extern int PicoRegionOverride; // override the region detection 0: auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe extern int PicoAutoRgnOrder; // packed priority list of regions, for example 0x148 means this detection order: EUR, USA, JAP diff --git a/platform/common/emu.c b/platform/common/emu.c index 5807c1bb..c2f41090 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -444,6 +444,10 @@ int emu_reload_rom(const char *rom_fname_in) break; } + // make quirks visible in UI + if (PicoQuirks & PQUIRK_FORCE_6BTN) + currentConfig.input_dev0 = PICO_INPUT_PAD_6BTN; + menu_romload_end(); menu_romload_started = 0; From 895d15121be3762c7007a3afe24c5d78bbdc8be7 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 20 Aug 2013 03:20:37 +0300 Subject: [PATCH 25/41] deal with some strict aliasing issues --- Makefile | 10 ++++++++++ cpu/sh2/compiler.c | 9 ++++++--- pico/32x/memory.c | 20 ++++++++++---------- pico/cd/pico.c | 2 +- pico/pico_int.h | 11 +++++++++-- pico/state.c | 3 ++- 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index e923091c..ec9f08c6 100644 --- a/Makefile +++ b/Makefile @@ -151,6 +151,16 @@ tools/textfilter: tools/textfilter.c .s.o: $(CC) $(CFLAGS) -c $< -o $@ +# special flags - perhaps fix this someday instead? +pico/draw.o: CFLAGS += -fno-strict-aliasing +pico/draw2.o: CFLAGS += -fno-strict-aliasing +pico/mode4.o: CFLAGS += -fno-strict-aliasing +pico/cd/memory.o: CFLAGS += -fno-strict-aliasing +pico/cd/cd_file.o: CFLAGS += -fno-strict-aliasing +pico/cd/pcm.o: CFLAGS += -fno-strict-aliasing +pico/cd/LC89510.o: CFLAGS += -fno-strict-aliasing +pico/cd/gfx_cd.o: CFLAGS += -fno-strict-aliasing + # random deps pico/carthw/svp/compiler.o : cpu/drc/emit_$(ARCH).c cpu/sh2/compiler.o : cpu/drc/emit_$(ARCH).c diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 0b59920b..76df2204 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -1110,8 +1110,11 @@ static void emit_or_t_if_eq(int srr) // reg cache must be clean before call static int emit_memhandler_read_(int size, int ram_check) { - int arg0, arg1; + int arg1; +#if 0 + int arg0; host_arg2reg(arg0, 0); +#endif rcache_clean(); @@ -3179,7 +3182,7 @@ void sh2_drc_flush_all(void) void sh2_drc_mem_setup(SH2 *sh2) { // fill the convenience pointers - sh2->p_bios = sh2->is_slave ? Pico32xMem->sh2_rom_s : Pico32xMem->sh2_rom_m; + sh2->p_bios = sh2->is_slave ? Pico32xMem->sh2_rom_s.w : Pico32xMem->sh2_rom_m.w; sh2->p_da = sh2->data_array; sh2->p_sdram = Pico32xMem->sdram; sh2->p_rom = Pico.rom; @@ -3293,7 +3296,7 @@ static void *dr_get_pc_base(u32 pc, int is_slave) if ((pc & ~0x7ff) == 0) { // BIOS - ret = is_slave ? Pico32xMem->sh2_rom_s : Pico32xMem->sh2_rom_m; + ret = is_slave ? Pico32xMem->sh2_rom_s.w : Pico32xMem->sh2_rom_m.w; mask = 0x7ff; } else if ((pc & 0xfffff000) == 0xc0000000) { diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 3b12cbbd..5be4da45 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -1208,9 +1208,9 @@ static u32 sh2_read8_cs0(u32 a, SH2 *sh2) // TODO: mirroring? if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m)) - return Pico32xMem->sh2_rom_m[a ^ 1]; + return Pico32xMem->sh2_rom_m.b[a ^ 1]; if (sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_s)) - return Pico32xMem->sh2_rom_s[a ^ 1]; + return Pico32xMem->sh2_rom_s.b[a ^ 1]; if ((a & 0x3fe00) == 0x4200) { d = Pico32xMem->pal[(a & 0x1ff) / 2]; @@ -1263,9 +1263,9 @@ static u32 sh2_read16_cs0(u32 a, SH2 *sh2) } if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m)) - return *(u16 *)(Pico32xMem->sh2_rom_m + a); + return Pico32xMem->sh2_rom_m.w[a / 2]; if (sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_s)) - return *(u16 *)(Pico32xMem->sh2_rom_s + a); + return Pico32xMem->sh2_rom_s.w[a / 2]; if ((a & 0x3fe00) == 0x4200) { d = Pico32xMem->pal[(a & 0x1ff) / 2]; @@ -1619,17 +1619,17 @@ static void get_bios(void) // MSH2 if (p32x_bios_m != NULL) { elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS"); - Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m)); + Byteswap(&Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m)); } else { - pl = (u32 *)Pico32xMem->sh2_rom_m; + pl = (u32 *)&Pico32xMem->sh2_rom_m; // fill exception vector table to our trap address for (i = 0; i < 128; i++) pl[i] = HWSWAP(0x200); // startup code - memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code)); + memcpy(&Pico32xMem->sh2_rom_m.b[0x200], msh2_code, sizeof(msh2_code)); // reset SP pl[1] = pl[3] = HWSWAP(0x6040000); @@ -1640,17 +1640,17 @@ static void get_bios(void) // SSH2 if (p32x_bios_s != NULL) { elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS"); - Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s)); + Byteswap(&Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s)); } else { - pl = (u32 *)Pico32xMem->sh2_rom_s; + pl = (u32 *)&Pico32xMem->sh2_rom_s; // fill exception vector table to our trap address for (i = 0; i < 128; i++) pl[i] = HWSWAP(0x200); // startup code - memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code)); + memcpy(&Pico32xMem->sh2_rom_s.b[0x200], ssh2_code, sizeof(ssh2_code)); // reset SP pl[1] = pl[3] = HWSWAP(0x603f800); diff --git a/pico/cd/pico.c b/pico/cd/pico.c index 7549d542..2b652957 100644 --- a/pico/cd/pico.c +++ b/pico/cd/pico.c @@ -43,7 +43,7 @@ PICO_INTERNAL int PicoResetMCD(void) memset(&Pico_mcd->pcm, 0, sizeof(Pico_mcd->pcm)); memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m)); - *(unsigned int *)(Pico_mcd->bios + 0x70) = 0xffffffff; // reset hint vector (simplest way to implement reg6) + memset(Pico_mcd->bios + 0x70, 0xff, 4); // reset hint vector (simplest way to implement reg6) Pico_mcd->m.state_flags |= 1; // s68k reset pending Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode with m68k access after reset diff --git a/pico/pico_int.h b/pico/pico_int.h index 6b062b6a..6e4917b3 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -441,6 +441,7 @@ typedef struct unsigned char pcm_ram[0x10000]; unsigned char pcm_ram_b[0x10][0x1000]; }; + // FIXME: should be short unsigned char s68k_regs[0x200]; // 110000: GA, not CPU regs unsigned char bram[0x2000]; // 110200: 8K struct mcd_misc m; // 112200: misc @@ -543,8 +544,14 @@ struct Pico32xMem #ifdef DRC_SH2 unsigned short drcblk_da[2][1 << (12 - SH2_DRCBLK_DA_SHIFT)]; #endif - unsigned char sh2_rom_m[0x800]; - unsigned char sh2_rom_s[0x400]; + union { + unsigned char b[0x800]; + unsigned short w[0x800/2]; + } sh2_rom_m; + union { + unsigned char b[0x400]; + unsigned short w[0x400/2]; + } sh2_rom_s; unsigned short pal[0x100]; unsigned short pal_native[0x100]; // converted to native (for renderer) signed short pwm[2*PWM_BUFF_LEN]; // PWM buffer for current frame diff --git a/pico/state.c b/pico/state.c index de2d8ab6..6c113810 100644 --- a/pico/state.c +++ b/pico/state.c @@ -290,7 +290,8 @@ static int state_save(void *file) SekPackCpu(buff, 1); if (Pico_mcd->s68k_regs[3] & 4) // 1M mode? wram_1M_to_2M(Pico_mcd->word_ram2M); - Pico_mcd->m.hint_vector = *(unsigned short *)(Pico_mcd->bios + 0x72); + memcpy(&Pico_mcd->m.hint_vector, Pico_mcd->bios + 0x72, + sizeof(Pico_mcd->m.hint_vector)); CHECKED_WRITE_BUFF(CHUNK_S68K, buff); CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram); From 8b78786e0f68a1e0e4331dc5f02eac468c99df11 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 20 Aug 2013 04:06:24 +0300 Subject: [PATCH 26/41] distinguish VR SVP from 32X version --- pico/carthw.cfg | 2 ++ pico/carthw_cfg.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pico/carthw.cfg b/pico/carthw.cfg index d61161c6..72d4a9a1 100644 --- a/pico/carthw.cfg +++ b/pico/carthw.cfg @@ -33,10 +33,12 @@ [Virtua Racing - SVP] check_str = 0x150, "Virtua Racing" +check_str = 0x810, "OHMP" hw = svp [Virtua Racing - SVP] check_str = 0x150, "VIRTUA RACING" +check_str = 0x810, "OHMP" hw = svp [Pico] diff --git a/pico/carthw_cfg.c b/pico/carthw_cfg.c index 0974fa02..91ddec74 100644 --- a/pico/carthw_cfg.c +++ b/pico/carthw_cfg.c @@ -2,9 +2,11 @@ static const char builtin_carthw_cfg[] = "[]\n" "check_str=0x150,\"Virtua Racing\"\n" + "check_str=0x810,\"OHMP\"\n" "hw=svp\n" "[]\n" "check_str=0x150,\"VIRTUA RACING\"\n" + "check_str=0x810,\"OHMP\"\n" "hw=svp\n" "[]\n" "check_str=0x100,\"SEGA PICO\"\n" From 75a30842c4f9e7e95a199361b9348c9f9dede0e6 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 23 Aug 2013 03:09:53 +0300 Subject: [PATCH 27/41] revive GP2X build, update --- Makefile | 20 +- Makefile.libretro | 6 - configure | 63 ++-- platform/common/emu.c | 2 +- platform/common/emu.h | 2 - platform/common/menu_pico.c | 84 ++++- platform/common/menu_pico.h | 2 - platform/common/mp3.c | 26 +- platform/common/mp3.h | 2 +- platform/common/mp3_dummy.c | 2 +- platform/common/mp3_helix.c | 2 +- platform/common/mp3_libavcodec.c | 2 +- platform/gp2x/940ctl.c | 175 ++++------ platform/gp2x/Makefile | 106 ------ platform/gp2x/code940/940shared.h | 3 +- platform/gp2x/emu.c | 160 ++------- platform/gp2x/in_gp2x.c | 311 ----------------- platform/gp2x/in_gp2x.h | 17 - platform/gp2x/menu.c | 79 +---- platform/gp2x/plat.c | 180 +++++----- platform/gp2x/plat.h | 25 ++ platform/gp2x/plat_gp2x.h | 29 -- platform/gp2x/pollux_set.c | 388 --------------------- platform/gp2x/pollux_set.h | 10 - platform/gp2x/soc.c | 101 ------ platform/gp2x/soc.h | 38 --- platform/gp2x/soc_dummy.c | 95 ------ platform/gp2x/soc_mmsp2.c | 550 ------------------------------ platform/gp2x/soc_mmsp2.h | 9 - platform/gp2x/soc_pollux.c | 439 ------------------------ platform/gp2x/soc_pollux.h | 2 - platform/gp2x/vid_mmsp2.c | 174 ++++++++++ platform/gp2x/vid_pollux.c | 232 +++++++++++++ platform/libpicofe | 2 +- platform/pandora/menu.c | 11 +- 35 files changed, 757 insertions(+), 2592 deletions(-) delete mode 100644 platform/gp2x/in_gp2x.c delete mode 100644 platform/gp2x/in_gp2x.h create mode 100644 platform/gp2x/plat.h delete mode 100644 platform/gp2x/plat_gp2x.h delete mode 100644 platform/gp2x/pollux_set.c delete mode 100644 platform/gp2x/pollux_set.h delete mode 100644 platform/gp2x/soc.c delete mode 100644 platform/gp2x/soc.h delete mode 100644 platform/gp2x/soc_dummy.c delete mode 100644 platform/gp2x/soc_mmsp2.c delete mode 100644 platform/gp2x/soc_mmsp2.h delete mode 100644 platform/gp2x/soc_pollux.c delete mode 100644 platform/gp2x/soc_pollux.h create mode 100644 platform/gp2x/vid_mmsp2.c create mode 100644 platform/gp2x/vid_pollux.c diff --git a/Makefile b/Makefile index ec9f08c6..439a66fd 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,23 @@ OBJS += platform/libpicofe/linux/xenv.o OBJS += platform/libpicofe/pandora/plat.o USE_FRONTEND = 1 endif +ifeq "$(PLATFORM)" "gp2x" +OBJS += platform/common/arm_utils.o +OBJS += platform/libpicofe/gp2x/in_gp2x.o +OBJS += platform/libpicofe/gp2x/soc.o +OBJS += platform/libpicofe/gp2x/soc_mmsp2.o +OBJS += platform/libpicofe/gp2x/soc_pollux.o +OBJS += platform/libpicofe/gp2x/plat.o +OBJS += platform/libpicofe/gp2x/pollux_set.o +OBJS += platform/gp2x/940ctl.o +OBJS += platform/gp2x/plat.o +OBJS += platform/gp2x/emu.o +OBJS += platform/gp2x/vid_mmsp2.o +OBJS += platform/gp2x/vid_pollux.o +OBJS += platform/gp2x/warm.o +USE_FRONTEND = 1 +PLATFORM_MP3 = 1 +endif ifeq "$(PLATFORM)" "libretro" OBJS += platform/libretro.o endif @@ -111,7 +128,8 @@ endif endif # USE_FRONTEND OBJS += platform/common/mp3.o -ifeq "$(HAVE_LIBAVCODEC)" "1" +ifeq "$(PLATFORM_MP3)" "1" +else ifeq "$(HAVE_LIBAVCODEC)" "1" OBJS += platform/common/mp3_libavcodec.o else OBJS += platform/common/mp3_dummy.o diff --git a/Makefile.libretro b/Makefile.libretro index bc677352..141277c8 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -47,8 +47,6 @@ else ifeq ($(platform), ios) CFLAGS += -DIOS ARCH := arm - HAVE_NEON = 0 - USE_DYNAREC = 0 use_cyclone = 0 use_fame = 1 @@ -101,9 +99,7 @@ else ifeq ($(platform), qnx) ASFLAGS += -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp ARCH = arm - HAVE_NEON = 1 ARM_ASM = 1 - USE_DYNAREC = 1 else ifneq (,$(findstring armv,$(platform))) TARGET := $(TARGET_NAME)_libretro.so SHARED := -shared -Wl,--no-undefined @@ -118,7 +114,6 @@ endif ifneq (,$(findstring neon,$(platform))) CFLAGS += -mfpu=neon ASFLAGS += -mfpu=neon - HAVE_NEON = 1 endif ifneq (,$(findstring softfloat,$(platform))) CFLAGS += -mfloat-abi=softfp @@ -131,7 +126,6 @@ ifneq (,$(findstring armasm,$(platform))) ARM_ASM = 1 endif ARCH = arm - USE_DYNAREC = 1 else TARGET := $(TARGET_NAME)_retro.dll CC = gcc diff --git a/configure b/configure index 9af719f4..097a2764 100755 --- a/configure +++ b/configure @@ -2,9 +2,9 @@ # some elements originated from qemu configure set -e -TMPC="/tmp/pcsx-conf-${RANDOM}-$$-${RANDOM}.c" -TMPO="/tmp/pcsx-conf-${RANDOM}-$$-${RANDOM}.o" -TMPB="/tmp/pcsx-conf-${RANDOM}-$$-${RANDOM}" +TMPC="/tmp/picodrive-conf-${RANDOM}-$$-${RANDOM}.c" +TMPO="/tmp/picodrive-conf-${RANDOM}-$$-${RANDOM}.o" +TMPB="/tmp/picodrive-conf-${RANDOM}-$$-${RANDOM}" trap "rm -f $TMPC $TMPO $TMPB" EXIT INT QUIT TERM rm -f config.log @@ -17,7 +17,7 @@ compile_object() compile_binary() { - c="$CC $CFLAGS $TMPC -o $TMPB $LDFLAGS $MAIN_LDLIBS $@" + c="$CC $CFLAGS $TMPC -o $TMPB $LDFLAGS $@" echo $c >> config.log $c >> config.log 2>&1 } @@ -31,7 +31,7 @@ check_define() # setting options to "yes" or "no" will make that choice default, # "" means "autodetect". -platform_list="generic pandora" +platform_list="generic pandora gp2x" platform="generic" sound_driver_list="oss alsa sdl" sound_drivers="" @@ -40,12 +40,12 @@ have_armv6="" have_armv7="" have_arm_neon="" have_libavcodec="" -enable_dynarec="yes" need_sdl="no" need_xlib="no" # these are for known platforms optimize_cortexa8="no" optimize_arm926ej="no" +optimize_arm920="no" # hardcoded stuff CC="${CC-${CROSS_COMPILE}gcc}" @@ -72,6 +72,16 @@ set_platform() optimize_cortexa8="yes" have_arm_neon="yes" ;; + gp2x) + sound_drivers="oss" + optimize_arm920="yes" + CFLAGS="$CFLAGS -D__GP2X__" + if [ "$CROSS_COMPILE" = "arm-linux-" ]; then + # still using static, dynamic linking slows Wiz 1-10% + # also libm on F100 is not compatible + MAIN_LDLIBS="$MAIN_LDLIBS -static" + fi + ;; *) fail "unsupported platform: $platform" ;; @@ -87,12 +97,6 @@ for opt do ;; --sound-drivers=*) sound_drivers="$optarg" ;; - --enable-neon) have_arm_neon="yes" - ;; - --disable-neon) have_arm_neon="no" - ;; - --disable-dynarec) enable_dynarec="no" - ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -105,10 +109,6 @@ if [ "$show_help" = "yes" ]; then echo " available: $platform_list" echo " --sound-drivers=LIST sound output drivers [guessed]" echo " available: $sound_driver_list" - echo " --enable-neon" - echo " --disable-neon enable/disable ARM NEON optimizations [guessed]" - echo " --disable-dynarec disable dynamic recompiler" - echo " (dynarec is only available and enabled on ARM)" echo "influential environment variables:" echo " CROSS_COMPILE CC CXX AS CFLAGS ASFLAGS LDFLAGS LDLIBS" exit 1 @@ -158,6 +158,10 @@ arm*) CFLAGS="$CFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s" ASFLAGS="$ASFLAGS -mcpu=arm926ej-s -mfloat-abi=softfp" fi + if [ "$optimize_arm920" = "yes" ]; then + CFLAGS="$CFLAGS -mcpu=arm920t -mtune=arm920t" + ASFLAGS="$ASFLAGS -mcpu=arm920t -mfloat-abi=soft" + fi if [ "x$have_arm_neon" = "x" ]; then # detect NEON from user-supplied cflags to enable asm code @@ -202,7 +206,7 @@ arm*) fi # warn about common mistakes - if [ "$have_armv5" != "yes" ]; then + if [ "$platform" != "gp2x" -a "$have_armv5" != "yes" ]; then if ! echo "$CFLAGS" | grep -q -- '-mcpu=\|-march='; then echo "Warning: compiling for ARMv4, is that really what you want?" echo "You probably should specify -mcpu= or -march= like this:" @@ -216,8 +220,6 @@ arm*) fi ;; *) - # dynarec only available on ARM - enable_dynarec="no" ;; esac @@ -243,7 +245,8 @@ check_libpng() #include void main() { png_init_io(0, 0); } EOF - compile_binary +# compile_binary + compile_object } check_oss() @@ -315,7 +318,7 @@ else fi if echo $sound_drivers | grep -q "\"; then MAIN_LDLIBS="-lasound $MAIN_LDLIBS" - check_alsa || fail "please install libasound2-dev" + check_alsa -lasound || fail "please install libasound2-dev" fi fi @@ -324,7 +327,7 @@ if [ "$need_sdl" = "yes" ]; then fail "sdl-config is missing; please install libsdl (libsdl1.2-dev)" CFLAGS="$CFLAGS `sdl-config --cflags`" MAIN_LDLIBS="`sdl-config --libs` $MAIN_LDLIBS" - check_sdl || fail "please install libsdl (libsdl1.2-dev)" + check_sdl `sdl-config --libs` || fail "please install libsdl (libsdl1.2-dev)" fi cat > $TMPC < $config_mak printf "# Configured with:" >> $config_mak @@ -372,11 +372,14 @@ echo "SOUND_DRIVERS = $sound_drivers" >> $config_mak if [ "$have_libavcodec" = "yes" ]; then echo "HAVE_LIBAVCODEC = 1" >> $config_mak fi -if [ "$have_arm_neon" = "yes" ]; then - echo "HAVE_NEON = 1" >> $config_mak -fi -if [ "$enable_dynarec" = "yes" ]; then - echo "USE_DYNAREC = 1" >> $config_mak + +# GP2X toolchains are too old for UAL asm, +# so add this here to not litter main Makefile +if [ "$platform" = "g1p2x" ]; then + echo >> $config_mak + echo "%.o: %.S" >> $config_mak + echo " $(CC) $(CFLAGS) -E -c $^ -o /tmp/$(notdir $@).s" >> $config_mak + echo " $(AS) $(ASFLAGS) /tmp/$(notdir $@).s -o $@" >> $config_mak fi # use pandora's skin (for now) diff --git a/platform/common/emu.c b/platform/common/emu.c index c2f41090..ee216fe2 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -545,7 +545,7 @@ static void make_config_cfg(char *cfg_buff_512) void emu_prep_defconfig(void) { memset(&defaultConfig, 0, sizeof(defaultConfig)); - defaultConfig.EmuOpt = 0x9d | EOPT_RAM_TIMINGS|EOPT_EN_CD_LEDS; + defaultConfig.EmuOpt = 0x9d | EOPT_EN_CD_LEDS; defaultConfig.s_PicoOpt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX | POPT_EN_SVP_DRC|POPT_ACC_SPRITES | diff --git a/platform/common/emu.h b/platform/common/emu.h index 5138754d..4a4b4394 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -21,10 +21,8 @@ extern int g_screen_height; #define EOPT_SHOW_FPS (1<<1) #define EOPT_EN_SOUND (1<<2) #define EOPT_GZIP_SAVES (1<<3) -#define EOPT_MMUHACK (1<<4) #define EOPT_NO_AUTOSVCFG (1<<5) #define EOPT_16BPP (1<<7) // depreceted for .renderer -#define EOPT_RAM_TIMINGS (1<<8) #define EOPT_EN_CD_LEDS (1<<10) #define EOPT_A_SN_GAMMA (1<<12) #define EOPT_VSYNC (1<<13) diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 4e9e5948..14274905 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -7,6 +7,7 @@ */ #include #include +#include #include "emu.h" #include "menu_pico.h" @@ -66,7 +67,6 @@ static const char *men_dummy[] = { NULL }; #else #define MENU_OPTIONS_GFX #define MENU_OPTIONS_ADV -#define menu_main_plat_draw NULL #endif static void make_bg(int no_scale) @@ -524,6 +524,8 @@ static menu_entry e_menu_adv_options[] = mee_onoff ("Don't save last used ROM", MA_OPT2_NO_LAST_ROM, currentConfig.EmuOpt, EOPT_NO_AUTOSVCFG), mee_onoff ("Disable idle loop patching",MA_OPT2_NO_IDLE_LOOPS,PicoOpt, POPT_DIS_IDLE_DET), mee_onoff ("Disable frame limiter", MA_OPT2_NO_FRAME_LIMIT,currentConfig.EmuOpt, EOPT_NO_FRMLIMIT), + mee_onoff ("Enable dynarecs", MA_OPT2_SVP_DYNAREC, PicoOpt, POPT_EN_SVP_DRC), + mee_onoff ("Status line in main menu", MA_OPT2_STATUS_LINE, currentConfig.EmuOpt, EOPT_SHOW_RTC), MENU_OPTIONS_ADV mee_end, }; @@ -537,14 +539,20 @@ static int menu_loop_adv_options(int id, int keys) // ------------ gfx options menu ------------ -static const char h_gamma[] = "Gamma/brightness adjustment (default 100)"; +static const char h_gamma[] = "Gamma/brightness adjustment (default 1.00)"; + +static const char *mgn_aopt_gamma(int id, int *offs) +{ + sprintf(static_buff, "%i.%02i", currentConfig.gamma / 100, currentConfig.gamma % 100); + return static_buff; +} static menu_entry e_menu_gfx_options[] = { mee_enum ("Video output mode", MA_OPT_VOUT_MODE, plat_target.vout_method, men_dummy), mee_enum ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names), mee_enum ("Filter", MA_OPT3_FILTERING, currentConfig.filter, men_dummy), - mee_range_h("Gamma adjustment", MA_OPT3_GAMMA, currentConfig.gamma, 1, 200, h_gamma), + mee_range_cust_h("Gamma correction", MA_OPT2_GAMMA, currentConfig.gamma, 1, 300, mgn_aopt_gamma, h_gamma), MENU_OPTIONS_GFX mee_end, }; @@ -753,10 +761,7 @@ static menu_entry e_menu_options[] = static int menu_loop_options(int id, int keys) { static int sel = 0; - int i; - i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS); - e_menu_options[i].enabled = e_menu_options[i].name[0] ? 1 : 0; me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, PicoGameLoaded); me_enable(e_menu_options, MA_OPT_LOADCFG, config_slot != config_slot_current); @@ -941,6 +946,56 @@ static const char credits[] = " Lordus, Exophase, Rokas,\n" " Nemesis, Tasco Deluxe"; +static void menu_main_draw_status(void) +{ + static time_t last_bat_read = 0; + static int last_bat_val = -1; + unsigned short *bp = g_screen_ptr; + int bat_h = me_mfont_h * 2 / 3; + int i, u, w, wfill, batt_val; + struct tm *tmp; + time_t ltime; + char time_s[16]; + + if (!(currentConfig.EmuOpt & EOPT_SHOW_RTC)) + return; + + ltime = time(NULL); + tmp = gmtime(<ime); + strftime(time_s, sizeof(time_s), "%H:%M", tmp); + + text_out16(g_screen_width - me_mfont_w * 6, me_mfont_h + 2, time_s); + + if (ltime - last_bat_read > 10) { + last_bat_read = ltime; + last_bat_val = batt_val = plat_target_bat_capacity_get(); + } + else + batt_val = last_bat_val; + + if (batt_val < 0 || batt_val > 100) + return; + + /* battery info */ + bp += (me_mfont_h * 2 + 2) * g_screen_width + g_screen_width - me_mfont_w * 3 - 3; + for (i = 0; i < me_mfont_w * 2; i++) + bp[i] = menu_text_color; + for (i = 0; i < me_mfont_w * 2; i++) + bp[i + g_screen_width * bat_h] = menu_text_color; + for (i = 0; i <= bat_h; i++) + bp[i * g_screen_width] = + bp[i * g_screen_width + me_mfont_w * 2] = menu_text_color; + for (i = 2; i < bat_h - 1; i++) + bp[i * g_screen_width - 1] = + bp[i * g_screen_width - 2] = menu_text_color; + + w = me_mfont_w * 2 - 1; + wfill = batt_val * w / 100; + for (u = 1; u < bat_h; u++) + for (i = 0; i < wfill; i++) + bp[(w - i) + g_screen_width * u] = menu_text_color; +} + static int main_menu_handler(int id, int keys) { const char *ret_name; @@ -1029,7 +1084,7 @@ void menu_loop(void) menu_enter(PicoGameLoaded); in_set_config_int(0, IN_CFG_BLOCKING, 1); - me_loop_d(e_menu_main, &sel, NULL, menu_main_plat_draw); + me_loop_d(e_menu_main, &sel, NULL, menu_main_draw_status); if (PicoGameLoaded) { if (engineState == PGS_Menu) @@ -1163,6 +1218,12 @@ void menu_init(void) menu_init_base(); + i = 0; +#if defined(_SVP_DRC) || defined(DRC_SH2) + i = 1; +#endif + me_enable(e_menu_adv_options, MA_OPT2_SVP_DYNAREC, i); + i = me_id2offset(e_menu_gfx_options, MA_OPT_VOUT_MODE); e_menu_gfx_options[i].data = plat_target.vout_methods; me_enable(e_menu_gfx_options, MA_OPT_VOUT_MODE, @@ -1173,6 +1234,13 @@ void menu_init(void) me_enable(e_menu_gfx_options, MA_OPT3_FILTERING, plat_target.hwfilters != NULL); - me_enable(e_menu_gfx_options, MA_OPT3_GAMMA, + me_enable(e_menu_gfx_options, MA_OPT2_GAMMA, plat_target.gamma_set != NULL); + + i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS); + e_menu_options[i].enabled = 0; + if (plat_target.cpu_clock_set != NULL) { + e_menu_options[i].name = "CPU clock"; + e_menu_options[i].enabled = 1; + } } diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index 9558ff54..583a77cf 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -51,7 +51,6 @@ typedef enum MA_OPT2_GZIP_STATES, MA_OPT2_NO_LAST_ROM, MA_OPT2_RAMTIMINGS, /* gp2x */ - MA_OPT2_SQUIDGEHACK, /* gp2x */ MA_OPT2_STATUS_LINE, /* psp */ MA_OPT2_NO_FRAME_LIMIT, /* psp */ MA_OPT2_SVP_DYNAREC, @@ -66,7 +65,6 @@ typedef enum MA_OPT3_PRES_FULLSCR, MA_OPT3_FILTERING, MA_OPT3_VSYNC, - MA_OPT3_GAMMA, MA_OPT3_BLACKLVL, MA_OPT3_LAYER_X, MA_OPT3_LAYER_Y, diff --git a/platform/common/mp3.c b/platform/common/mp3.c index 9b347e89..ad3d70e5 100644 --- a/platform/common/mp3.c +++ b/platform/common/mp3.c @@ -103,7 +103,7 @@ out: return retval; } -void mp3_start_play(void *f_, int pos) +void mp3_start_play(void *f_, int pos1024) { unsigned char buf[2048]; FILE *f = f_; @@ -117,13 +117,6 @@ void mp3_start_play(void *f_, int pos) if (!(PicoOpt & POPT_EN_MCD_CDDA) || f == NULL) // cdda disabled or no file? return; - ret = mp3dec_start(); - if (ret != 0) - return; - - decoder_active = 1; - - mp3_current_file = f; fseek(f, 0, SEEK_END); mp3_file_len = ftell(f); @@ -144,12 +137,20 @@ void mp3_start_play(void *f_, int pos) } // seek.. - if (pos) { + if (pos1024 != 0) { unsigned long long pos64 = mp3_file_len - mp3_file_pos; - pos64 *= pos; + pos64 *= pos1024; mp3_file_pos += pos64 >> 10; } + ret = mp3dec_start(f, mp3_file_pos); + if (ret != 0) { + return; + } + + mp3_current_file = f; + decoder_active = 1; + mp3dec_decode(mp3_current_file, &mp3_file_pos, mp3_file_len); } @@ -182,8 +183,9 @@ void mp3_update(int *buffer, int length, int stereo) } else { int ret, left = 1152 - cdda_out_pos; - mix_samples(buffer, cdda_out_buffer + cdda_out_pos * 2, - (left >> shr) * 2); + if (left > 0) + mix_samples(buffer, cdda_out_buffer + cdda_out_pos * 2, + (left >> shr) * 2); ret = mp3dec_decode(mp3_current_file, &mp3_file_pos, mp3_file_len); diff --git a/platform/common/mp3.h b/platform/common/mp3.h index 26c4a3ce..eb66db88 100644 --- a/platform/common/mp3.h +++ b/platform/common/mp3.h @@ -6,7 +6,7 @@ int mp3_find_sync_word(const unsigned char *buf, int size); /* decoder */ -int mp3dec_start(void); +int mp3dec_start(FILE *f, int fpos_start); int mp3dec_decode(FILE *f, int *file_pos, int file_len); extern unsigned short mpeg1_l3_bitrates[16]; diff --git a/platform/common/mp3_dummy.c b/platform/common/mp3_dummy.c index 7d0ef9ee..0e6a8136 100644 --- a/platform/common/mp3_dummy.c +++ b/platform/common/mp3_dummy.c @@ -9,7 +9,7 @@ #include #include "mp3.h" -int mp3dec_start(void) +int mp3dec_start(FILE *f, int fpos_start) { return -1; } diff --git a/platform/common/mp3_helix.c b/platform/common/mp3_helix.c index 62e91897..b2785298 100644 --- a/platform/common/mp3_helix.c +++ b/platform/common/mp3_helix.c @@ -84,7 +84,7 @@ int mp3dec_decode(FILE *f, int *file_pos, int file_len) return 0; } -int mp3dec_start(void) +int mp3dec_start(FILE *f, int fpos_start) { // must re-init decoder for new track if (mp3dec) diff --git a/platform/common/mp3_libavcodec.c b/platform/common/mp3_libavcodec.c index 3c93dfba..2d3c799c 100644 --- a/platform/common/mp3_libavcodec.c +++ b/platform/common/mp3_libavcodec.c @@ -91,7 +91,7 @@ int mp3dec_decode(FILE *f, int *file_pos, int file_len) return 0; } -int mp3dec_start(void) +int mp3dec_start(FILE *f, int fpos_start) { void (*avcodec_register_all)(void); AVCodec *(*avcodec_find_decoder)(enum CodecID id); diff --git a/platform/gp2x/940ctl.c b/platform/gp2x/940ctl.c index 88477f8e..d3769570 100644 --- a/platform/gp2x/940ctl.c +++ b/platform/gp2x/940ctl.c @@ -15,17 +15,19 @@ #include #include -#include "code940/940shared.h" -#include "soc_mmsp2.h" -#include "soc.h" +#include "../libpicofe/input.h" +#include "../libpicofe/gp2x/soc_mmsp2.h" +#include "../libpicofe/gp2x/soc.h" #include "../common/mp3.h" #include "../common/arm_utils.h" -#include "../common/menu.h" +#include "../common/menu_pico.h" #include "../common/emu.h" -#include "../common/input.h" #include "../../pico/pico_int.h" #include "../../pico/sound/ym2612.h" #include "../../pico/sound/mix.h" +#include "code940/940shared.h" +#include "plat.h" +#include "940ctl.h" static unsigned char *shared_mem = 0; static _940_data_t *shared_data = 0; @@ -122,14 +124,14 @@ int YM2612Write_940(unsigned int a, unsigned int v, int scanline) #define CHECK_BUSY(job) \ - (gp2x_memregs[0x3b46>>1] & (1<<(job-1))) + (memregs[0x3b46>>1] & (1<<(job-1))) static void wait_busy_940(int job) { int i; job--; - for (i = 0; (gp2x_memregs[0x3b46>>1] & (1<>1] & (1<vstarts[i]); printf(")\n"); - printf("irq pending flags: DUALCPU %04x, SRCPND %08lx (see 26), INTPND %08lx\n", - gp2x_memregs[0x3b46>>1], gp2x_memregl[0x4500>>2], gp2x_memregl[0x4510>>2]); + printf("irq pending flags: DUALCPU %04x, SRCPND %08x (see 26), INTPND %08x\n", + memregs[0x3b46>>1], memregl[0x4500>>2], memregl[0x4510>>2]); printf("last lr: %08x, lastjob: %i\n", shared_ctl->last_lr, shared_ctl->lastjob); printf("trying to interrupt..\n"); - gp2x_memregs[0x3B3E>>1] = 0xffff; - for (i = 0; gp2x_memregs[0x3b46>>1] && i < 0x10000; i++) + memregs[0x3B3E>>1] = 0xffff; + for (i = 0; memregs[0x3b46>>1] && i < 0x10000; i++) spend_cycles(8*1024); printf("i = 0x%x\n", i); - printf("irq pending flags: DUALCPU %04x, SRCPND %08lx (see 26), INTPND %08lx\n", - gp2x_memregs[0x3b46>>1], gp2x_memregl[0x4500>>2], gp2x_memregl[0x4510>>2]); + printf("irq pending flags: DUALCPU %04x, SRCPND %08x (see 26), INTPND %08x\n", + memregs[0x3b46>>1], memregl[0x4500>>2], memregl[0x4510>>2]); printf("last lr: %08x, lastjob: %i\n", shared_ctl->last_lr, shared_ctl->lastjob); - me_update_msg("940 crashed, too much overclock?"); + menu_update_msg("940 crashed, too much overclock?"); engineState = PGS_Menu; crashed_940 = 1; } @@ -165,9 +167,9 @@ static void add_job_940(int job) // generate interrupt for this job job--; - gp2x_memregs[(0x3B20+job*2)>>1] = 1; + memregs[(0x3B20+job*2)>>1] = 1; -// printf("added %i, pending %04x\n", job+1, gp2x_memregs[0x3b46>>1]); +// printf("added %i, pending %04x\n", job+1, memregs[0x3b46>>1]); } @@ -288,11 +290,11 @@ void YM2612Init_940(int baseclock, int rate) reset940(1, 2); pause940(1); - gp2x_memregs[0x3B40>>1] = 0; // disable DUALCPU interrupts for 920 - gp2x_memregs[0x3B42>>1] = 1; // enable DUALCPU interrupts for 940 + memregs[0x3B40>>1] = 0; // disable DUALCPU interrupts for 920 + memregs[0x3B42>>1] = 1; // enable DUALCPU interrupts for 940 - gp2x_memregl[0x4504>>2] = 0; // make sure no FIQs will be generated - gp2x_memregl[0x4508>>2] = ~(1<<26); // unmask DUALCPU ints in the undocumented 940's interrupt controller + memregl[0x4504>>2] = 0; // make sure no FIQs will be generated + memregl[0x4508>>2] = ~(1<<26); // unmask DUALCPU ints in the undocumented 940's interrupt controller if (crashed_940) @@ -310,7 +312,7 @@ void YM2612Init_940(int baseclock, int rate) text_out16(10, 100, "failed to open required file:"); text_out16(10, 110, CODE940_FILE); gp2x_video_flip2(); - in_menu_wait(PBTN_MOK|PBTN_MBACK, 100); + in_menu_wait(PBTN_MOK|PBTN_MBACK, NULL, 100); printf("failed to open %s\n", binpath); exit(1); } @@ -335,11 +337,11 @@ void YM2612Init_940(int baseclock, int rate) internal_reset(); - loaded_mp3 = 0; + loaded_mp3 = NULL; - gp2x_memregs[0x3B46>>1] = 0xffff; // clear pending DUALCPU interrupts for 940 - gp2x_memregl[0x4500>>2] = 0xffffffff; // clear pending IRQs in SRCPND - gp2x_memregl[0x4510>>2] = 0xffffffff; // clear pending IRQs in INTPND + memregs[0x3B46>>1] = 0xffff; // clear pending DUALCPU interrupts for 940 + memregl[0x4500>>2] = 0xffffffff; // clear pending IRQs in SRCPND + memregl[0x4510>>2] = 0xffffffff; // clear pending IRQs in INTPND /* start the 940 */ reset940(0, 2); @@ -410,85 +412,45 @@ int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty) /***********************************************************/ -static int mp3_samples_ready = 0, mp3_buffer_offs = 0; -static int mp3_play_bufsel = 0, mp3_job_started = 0; +// FIXME: double buffering no longer used.. -void mp3_update(int *buffer, int length, int stereo) +int mp3dec_decode(FILE *f, int *file_pos, int file_len) { - int length_mp3; - if (!(PicoOpt & POPT_EXT_FM)) { - mp3_update_local(buffer, length, stereo); - return; + //mp3_update_local(buffer, length, stereo); + return 0; } // check if playback was started, track not ended - if (loaded_mp3 == NULL || shared_ctl->mp3_offs >= shared_ctl->mp3_len) - 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 (loaded_mp3 == NULL || shared_ctl->mp3_offs >= shared_ctl->mp3_len) { + *file_pos = file_len; + return 1; + } /* do we have to wait? */ - if (mp3_job_started && mp3_samples_ready < length_mp3) { - if (CHECK_BUSY(JOB940_MP3DECODE)) wait_busy_940(JOB940_MP3DECODE); - mp3_job_started = 0; - mp3_samples_ready += 1152; - } + if (CHECK_BUSY(JOB940_MP3DECODE)) + wait_busy_940(JOB940_MP3DECODE); - /* mix mp3 data, only stereo */ - if (mp3_samples_ready >= length_mp3) - { - 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; } + memcpy(cdda_out_buffer, + shared_data->mp3_buffer[shared_ctl->mp3_buffsel], + sizeof(cdda_out_buffer)); - if (1152 - mp3_buffer_offs >= length_mp3) { - mix_samples(buffer, shared_data->mp3_buffer[mp3_play_bufsel] + mp3_buffer_offs*2, length<<1); + *file_pos = shared_ctl->mp3_offs; - mp3_buffer_offs += length_mp3; - } else { - // collect samples from both buffers.. - int left = 1152 - mp3_buffer_offs; - if (mp3_play_bufsel == 0) - { - mix_samples(buffer, shared_data->mp3_buffer[0] + mp3_buffer_offs*2, length<<1); - mp3_buffer_offs = length_mp3 - left; - mp3_play_bufsel = 1; - } else { - mix_samples(buffer, shared_data->mp3_buffer[1] + mp3_buffer_offs*2, (left>>shr)<<1); - mp3_buffer_offs = length_mp3 - left; - mix_samples(buffer + ((left>>shr)<<1), - shared_data->mp3_buffer[0], (mp3_buffer_offs>>shr)<<1); - mp3_play_bufsel = 0; - } - } - mp3_samples_ready -= length_mp3; - } - - // ask to decode more if we already can - if (!mp3_job_started) - { - mp3_job_started = 1; - shared_ctl->mp3_buffsel ^= 1; + if (shared_ctl->mp3_offs < shared_ctl->mp3_len) { + // ask to decode more + //shared_ctl->mp3_buffsel ^= 1; add_job_940(JOB940_MP3DECODE); } + + return 0; } - -void mp3_start_play(void *f_, int pos) // pos is 0-1023 +int mp3dec_start(FILE *f, int fpos_start) { - int byte_offs = 0; - FILE *f = f_; - - if (!(PicoOpt & POPT_EN_MCD_CDDA) || f == NULL) - return; - if (!(PicoOpt & POPT_EXT_FM)) { - mp3_start_play_local(f, pos); - return; + //mp3_start_play_local(f, pos); + return -1; } if (loaded_mp3 != f) @@ -501,34 +463,31 @@ void mp3_start_play(void *f_, int pos) // pos is 0-1023 } fseek(f, 0, SEEK_SET); fread(mp3_mem, 1, MP3_SIZE_MAX, f); - if (!feof(f)) printf("Warning: mp3 was too large, not all data loaded.\n"); + if (!feof(f)) + printf("Warning: mp3 was too large, not all data loaded.\n"); shared_ctl->mp3_len = ftell(f); loaded_mp3 = f; - if (PicoOpt & POPT_EXT_FM) { - // as we are going to change 940's cacheable area, we must invalidate it's cache.. - if (CHECK_BUSY(JOB940_MP3DECODE)) wait_busy_940(JOB940_MP3DECODE); - add_job_940(JOB940_INVALIDATE_DCACHE); - } + // as we are going to change 940's cacheable area, + // we must invalidate it's cache.. + if (CHECK_BUSY(JOB940_MP3DECODE)) + wait_busy_940(JOB940_MP3DECODE); + add_job_940(JOB940_INVALIDATE_DCACHE); reset_timing = 1; } - // seek.. - if (pos) { - byte_offs = (shared_ctl->mp3_len << 6) >> 10; - byte_offs *= pos; - byte_offs >>= 6; - } - printf(" mp3 pos1024: %i, byte_offs %i/%i\n", pos, byte_offs, shared_ctl->mp3_len); - - shared_ctl->mp3_offs = byte_offs; - - // reset buffer pointers and stuff.. - mp3_samples_ready = mp3_buffer_offs = mp3_play_bufsel = 0; - mp3_job_started = 0; - shared_ctl->mp3_buffsel = 1; // will change to 0 on first decode + shared_ctl->mp3_offs = fpos_start; + shared_ctl->mp3_buffsel = 0; add_job_940(JOB940_MP3RESET); - if (CHECK_BUSY(JOB940_MP3RESET)) wait_busy_940(JOB940_MP3RESET); + if (CHECK_BUSY(JOB940_MP3RESET)) + wait_busy_940(JOB940_MP3RESET); + + // because we decode ahea, need to start now + if (shared_ctl->mp3_offs < shared_ctl->mp3_len) { + add_job_940(JOB940_MP3DECODE); + } + + return 0; } diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index 030bab67..a3786c76 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -1,111 +1,6 @@ -CROSS ?= arm-linux- - -# settings -use_cyclone = 1 -#use_musashi = 1 -use_drz80 = 1 -use_sh2drc = 1 -#use_sh2mame = 1 - -asm_memory = 1 -asm_render = 1 -asm_ym2612 = 1 -asm_misc = 1 -asm_cdpico = 1 -asm_cdmemory = 1 -asm_32xdraw = 1 -#profile = 1 -#drc_debug = 3 - --include Makefile.local - -ifeq "$(debug_cyclone)" "1" -use_cyclone = 1 -use_musashi = 1 -endif -ifeq "$(use_musashi)" "1" -# due to CPU stop flag acces -asm_cdpico = 0 -asm_cdmemory = 0 -endif - -ARCH = arm -DEFINES += ARM __GP2X__ IN_GP2X IN_EVDEV # BENCHMARK -CFLAGS += -Wall -Winline -I../.. -I. -ifeq ($(DEBUG),) -CFLAGS += -O3 -fomit-frame-pointer -fstrict-aliasing -ffast-math -endif -CFLAGS += -mcpu=arm920t -mtune=arm920t -ASFLAGS = -mcpu=arm920t -mfloat-abi=soft -LDFLAGS += -lm -lpng - -CC = $(CROSS)gcc -STRIP = $(CROSS)strip -AS = $(CROSS)as -LD = $(CROSS)ld -OBJCOPY = $(CROSS)objcopy - -# frontend -OBJS += plat.o warm.o pollux_set.o soc.o soc_mmsp2.o soc_pollux.o soc_dummy.o emu.o in_gp2x.o -# 940 core control -OBJS += 940ctl.o - -# ARM stuff -OBJS += pico/carthw/svp/compiler.o pico/carthw/svp/stub_arm.o -OBJS += pico/sound/mix_arm.o - -# common -OBJS += platform/common/emu.o platform/common/menu_pico.o platform/common/fonts.o platform/common/config.o \ - platform/common/arm_utils.o platform/common/arm_linux.o platform/common/readpng.o \ - platform/common/mp3_helix.o platform/common/input.o platform/common/main.o platform/common/mp3.o \ - platform/linux/sndout_oss.o platform/linux/plat.o platform/linux/in_evdev.o - -# unzip -OBJS += unzip/unzip.o unzip/unzip_stream.o -# zlib -OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \ - zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o - -vpath %.c = ../.. -vpath %.s = ../.. -vpath %.S = ../.. - -DIRS += platform/gp2x platform/linux zlib unzip - - -all: mkdirs PicoDrive - -include ../common/common.mak -include ../common/common_arm.mak -include ../common/revision.mak - -CFLAGS += $(addprefix -D,$(DEFINES)) - -# partial linking helps profiled builds due to section merging -PicoDrive.o : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a - $(LD) -r -o $@ $^ - -# still using static, dynamic linking slows Wiz 1-10% -# also libm on F100 is not compatible -PicoDrive : PicoDrive.o - @echo ">>>" $@ - $(CC) -static -o $@ $(CFLAGS) $^ $(LDFLAGS) -Wl,-Map=$@.map -ifeq ($(DEBUG),) - $(STRIP) $@ -endif - -up: PicoDrive - @cp -v PicoDrive /mnt/gp2x/mnt/sd/emus/PicoDrive/ - -clean: tidy - $(RM) PicoDrive -tidy: - $(RM) $(OBJS) - readme.txt: ../../tools/textfilter ../base_readme.txt ../../tools/textfilter ../base_readme.txt $@ GP2X -# ----------- release ----------- VER ?= $(shell head -n 1 version.h | sed 's/.*"\(.*\)\.\(.*\)".*/\1\2/g') CODE940 = code940/pico940_v3.bin @@ -125,4 +20,3 @@ rel: PicoDrive PicoDrive.gpe $(CODE940) readme.txt ../game_def.cfg \ $(CODE940): make -C code940/ - diff --git a/platform/gp2x/code940/940shared.h b/platform/gp2x/code940/940shared.h index 57972600..6f12a32f 100644 --- a/platform/gp2x/code940/940shared.h +++ b/platform/gp2x/code940/940shared.h @@ -1,5 +1,4 @@ #include "../../../pico/sound/ym2612.h" -#include "../../common/helix/pub/mp3dec.h" // max 16 jobs, lower num means higher prio enum _940_job_t { @@ -20,7 +19,7 @@ enum _940_job_t { typedef struct { YM2612 ym2612; /* current state of the emulated YM2612 */ - HMP3Decoder mp3dec; /* mp3 decoder's handle */ + void *mp3dec; /* mp3 decoder's handle */ int ym_buffer[44100/50*2]; /* this is where the YM2612 samples will be mixed to */ short mp3_buffer[2][1152*2]; /* buffers for mp3 decoder's output */ } _940_data_t; diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 825ab5bb..7db89c29 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -15,18 +15,17 @@ #include #include -#include "plat_gp2x.h" -#include "soc.h" -#include "soc_pollux.h" -#include "../common/plat.h" -#include "../common/menu.h" +#include "../libpicofe/gp2x/plat_gp2x.h" +#include "../libpicofe/gp2x/soc.h" +#include "../libpicofe/input.h" +#include "../libpicofe/plat.h" +#include "../libpicofe/gp2x/soc_pollux.h" +#include "../common/menu_pico.h" #include "../common/arm_utils.h" -#include "../common/fonts.h" #include "../common/emu.h" -#include "../common/config.h" -#include "../common/input.h" -#include "../linux/sndout_oss.h" -#include "version.h" +#include "../common/config_file.h" +#include "../common/version.h" +#include "plat.h" #include #include @@ -40,9 +39,8 @@ #endif -extern int crashed_940; +//extern int crashed_940; -static short __attribute__((aligned(4))) sndBuffer[2*(44100+100)/50]; static int osd_fps_x, osd_y, doing_bg_frame; const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast", NULL }; const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL }; @@ -51,8 +49,6 @@ enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; static int (*emu_scan_begin)(unsigned int num) = NULL; static int (*emu_scan_end)(unsigned int num) = NULL; -extern void *gp2x_screens[4]; - void pemu_prep_defconfig(void) { @@ -670,8 +666,8 @@ static void RunEventsPico(unsigned int events) void plat_update_volume(int has_changed, int is_up) { static int prev_frame = 0, wait_frames = 0; - int vol = currentConfig.volume; int need_low_volume = 0; + int vol = currentConfig.volume; gp2x_soc_t soc; soc = soc_detect(); @@ -683,14 +679,9 @@ void plat_update_volume(int has_changed, int is_up) if (need_low_volume && vol < 5 && prev_frame == Pico.m.frame_count - 1 && wait_frames < 12) wait_frames++; else { - if (is_up) { - if (vol < 99) vol++; - } else { - if (vol > 0) vol--; - } wait_frames = 0; - sndout_oss_setvol(vol, vol); - currentConfig.volume = vol; + plat_target_step_volume(¤tConfig.volume, is_up ? 1 : -1); + vol = currentConfig.volume; } emu_status_msg("VOL: %02i", vol); prev_frame = Pico.m.frame_count; @@ -708,17 +699,13 @@ void plat_update_volume(int has_changed, int is_up) } } -static void oss_write_nonblocking(int len) -{ - // sndout_oss_can_write() is not reliable, only use with no_frmlimit - if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len)) - return; - - sndout_oss_write_nb(PsndOut, len); -} - void pemu_sound_start(void) { + emu_sound_start(); + + plat_target_step_volume(¤tConfig.volume, 0); + +#if 0 static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; PsndOut = NULL; @@ -754,6 +741,7 @@ void pemu_sound_start(void) PicoOpt_old = PicoOpt; pal_old = Pico.m.pal; } +#endif } static const int sound_rates[] = { 44100, 32000, 22050, 16000, 11025, 8000 }; @@ -772,11 +760,6 @@ void pemu_sound_stop(void) } } -void pemu_sound_wait(void) -{ - // don't need to do anything, writes will block by themselves -} - void pemu_forced_frame(int no_scale, int do_emu) { doing_bg_frame = 1; @@ -794,110 +777,23 @@ void plat_debug_cat(char *str) { } -#if 0 -static void tga_dump(void) +void plat_video_loop_prepare(void) { -#define BYTE unsigned char -#define WORD unsigned short - struct - { - BYTE IDLength; /* 00h Size of Image ID field */ - BYTE ColorMapType; /* 01h Color map type */ - BYTE ImageType; /* 02h Image type code */ - WORD CMapStart; /* 03h Color map origin */ - WORD CMapLength; /* 05h Color map length */ - BYTE CMapDepth; /* 07h Depth of color map entries */ - WORD XOffset; /* 08h X origin of image */ - WORD YOffset; /* 0Ah Y origin of image */ - WORD Width; /* 0Ch Width of image */ - WORD Height; /* 0Eh Height of image */ - BYTE PixelDepth; /* 10h Image pixel size */ - BYTE ImageDescriptor; /* 11h Image descriptor byte */ - } __attribute__((packed)) TGAHEAD; - static unsigned short oldscr[320*240]; - FILE *f; char name[128]; int i; - - memset(&TGAHEAD, 0, sizeof(TGAHEAD)); - TGAHEAD.ImageType = 2; - TGAHEAD.Width = 320; - TGAHEAD.Height = 240; - TGAHEAD.PixelDepth = 16; - TGAHEAD.ImageDescriptor = 2<<4; // image starts at top-left - -#define CONV(X) (((X>>1)&0x7fe0)|(X&0x1f)) // 555? - - for (i = 0; i < 320*240; i++) - if(oldscr[i] != CONV(((unsigned short *)g_screen_ptr)[i])) break; - if (i < 320*240) - { - for (i = 0; i < 320*240; i++) - oldscr[i] = CONV(((unsigned short *)g_screen_ptr)[i]); - sprintf(name, "%05i.tga", Pico.m.frame_count); - f = fopen(name, "wb"); - if (!f) { printf("!f\n"); exit(1); } - fwrite(&TGAHEAD, 1, sizeof(TGAHEAD), f); - fwrite(oldscr, 1, 320*240*2, f); - fclose(f); - } -} -#endif - -void pemu_loop_prep(void) -{ - static int gp2x_old_clock = -1, EmuOpt_old = 0, pal_old = 0; - static int gp2x_old_gamma = 100; - gp2x_soc_t soc; - - soc = soc_detect(); - - if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_RAM_TIMINGS) { - if (currentConfig.EmuOpt & EOPT_RAM_TIMINGS) - set_ram_timings(); - else - unset_ram_timings(); - } - - if (gp2x_old_clock < 0) - gp2x_old_clock = default_cpu_clock; - if (gp2x_old_clock != currentConfig.CPUclock && gp2x_set_cpuclk != NULL) { - printf("changing clock to %i...", currentConfig.CPUclock); fflush(stdout); - gp2x_set_cpuclk(currentConfig.CPUclock); - gp2x_old_clock = currentConfig.CPUclock; - printf(" done\n"); - } - - if (gp2x_old_gamma != currentConfig.gamma || ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_A_SN_GAMMA)) { - set_lcd_gamma(currentConfig.gamma, !!(currentConfig.EmuOpt & EOPT_A_SN_GAMMA)); - gp2x_old_gamma = currentConfig.gamma; - printf("updated gamma to %i, A_SN's curve: %i\n", currentConfig.gamma, !!(currentConfig.EmuOpt&0x1000)); - } - - if (((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_VSYNC) || Pico.m.pal != pal_old) { - if ((currentConfig.EmuOpt & EOPT_VSYNC) || soc == SOCID_POLLUX) - set_lcd_custom_rate(Pico.m.pal); - else if (EmuOpt_old & EOPT_VSYNC) - unset_lcd_custom_rate(); - } - - if (gp2x_dev_id == GP2X_DEV_CAANOO) - in_set_config_int(in_name_to_id("evdev:pollux-analog"), IN_CFG_ABS_DEAD_ZONE, - currentConfig.analog_deadzone); - - if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_MMUHACK) - gp2x_make_fb_bufferable(currentConfig.EmuOpt & EOPT_MMUHACK); - - EmuOpt_old = currentConfig.EmuOpt; - pal_old = Pico.m.pal; - // make sure we are in correct mode change_renderer(0); vid_reset_mode(); +} + +void pemu_loop_prep(void) +{ + if (gp2x_dev_id == GP2X_DEV_CAANOO) + in_set_config_int(in_name_to_id("evdev:pollux-analog"), + IN_CFG_ABS_DEAD_ZONE, + currentConfig.analog_deadzone); // dirty buffers better go now than during gameplay sync(); sleep(0); - - pemu_sound_start(); } void pemu_loop_end(void) diff --git a/platform/gp2x/in_gp2x.c b/platform/gp2x/in_gp2x.c deleted file mode 100644 index 196f1218..00000000 --- a/platform/gp2x/in_gp2x.c +++ /dev/null @@ -1,311 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "../common/input.h" -#include "in_gp2x.h" - -#define IN_GP2X_PREFIX "gp2x:" -#define IN_GP2X_NBUTTONS 32 - -/* note: in_gp2x hadles combos (if 2 btns have the same bind, - * both must be pressed for action to happen) */ -static int in_gp2x_combo_keys = 0; -static int in_gp2x_combo_acts = 0; -static int gpiodev = -1; /* Wiz only */ - -static int (*in_gp2x_get_bits)(void); - -static const char *in_gp2x_keys[IN_GP2X_NBUTTONS] = { - [0 ... IN_GP2X_NBUTTONS-1] = NULL, - [GP2X_BTN_UP] = "Up", [GP2X_BTN_LEFT] = "Left", - [GP2X_BTN_DOWN] = "Down", [GP2X_BTN_RIGHT] = "Right", - [GP2X_BTN_START] = "Start", [GP2X_BTN_SELECT] = "Select", - [GP2X_BTN_L] = "L", [GP2X_BTN_R] = "R", - [GP2X_BTN_A] = "A", [GP2X_BTN_B] = "B", - [GP2X_BTN_X] = "X", [GP2X_BTN_Y] = "Y", - [GP2X_BTN_VOL_DOWN] = "VOL DOWN", - [GP2X_BTN_VOL_UP] = "VOL UP", - [GP2X_BTN_PUSH] = "PUSH" -}; - - -static int in_gp2x_get_mmsp2_bits(void) -{ - extern volatile unsigned short *gp2x_memregs; - int value; - value = gp2x_memregs[0x1198>>1] & 0xff; // GPIO M - if (value == 0xFD) value = 0xFA; - if (value == 0xF7) value = 0xEB; - if (value == 0xDF) value = 0xAF; - if (value == 0x7F) value = 0xBE; - value |= gp2x_memregs[0x1184>>1] & 0xFF00; // GPIO C - value |= gp2x_memregs[0x1186>>1] << 16; // GPIO D - value = ~value & 0x08c0ff55; - - return value; -} - -static int in_gp2x_get_wiz_bits(void) -{ - int r, value = 0; - r = read(gpiodev, &value, 4); - if (value & 0x02) - value |= 0x05; - if (value & 0x08) - value |= 0x14; - if (value & 0x20) - value |= 0x50; - if (value & 0x80) - value |= 0x41; - - /* convert to GP2X style */ - value &= 0x7ff55; - if (value & (1 << 16)) - value |= 1 << GP2X_BTN_VOL_UP; - if (value & (1 << 17)) - value |= 1 << GP2X_BTN_VOL_DOWN; - if (value & (1 << 18)) - value |= 1 << GP2X_BTN_PUSH; - value &= ~0x70000; - - return value; -} - -#ifdef FAKE_IN_GP2X -volatile unsigned short *gp2x_memregs; -int gp2x_dev_id = -1; - -static int in_gp2x_get_fake_bits(void) -{ - extern int current_keys; - return current_keys; -} -#endif - -static void in_gp2x_probe(void) -{ - switch (gp2x_dev_id) - { - case GP2X_DEV_GP2X: - in_gp2x_get_bits = in_gp2x_get_mmsp2_bits; - break; - case GP2X_DEV_WIZ: - gpiodev = open("/dev/GPIO", O_RDONLY); - if (gpiodev < 0) { - perror("in_gp2x: couldn't open /dev/GPIO"); - return; - } - in_gp2x_get_bits = in_gp2x_get_wiz_bits; - break; - // we'll use evdev for Caanoo - default: -#ifdef FAKE_IN_GP2X - in_gp2x_get_bits = in_gp2x_get_fake_bits; - break; -#endif - return; - } - - in_register(IN_GP2X_PREFIX "GP2X pad", -1, NULL, - IN_GP2X_NBUTTONS, in_gp2x_keys, 1); -} - -static void in_gp2x_free(void *drv_data) -{ - if (gpiodev >= 0) { - close(gpiodev); - gpiodev = -1; - } -} - -static const char * const * -in_gp2x_get_key_names(int *count) -{ - *count = IN_GP2X_NBUTTONS; - return in_gp2x_keys; -} - -/* ORs result with pressed buttons */ -static int in_gp2x_update(void *drv_data, const int *binds, int *result) -{ - int type_start = 0; - int i, t, keys; - - keys = in_gp2x_get_bits(); - - if (keys & in_gp2x_combo_keys) { - result[IN_BINDTYPE_EMU] = in_combos_do(keys, binds, GP2X_BTN_PUSH, - in_gp2x_combo_keys, in_gp2x_combo_acts); - type_start = IN_BINDTYPE_PLAYER12; - } - - for (i = 0; keys; i++, keys >>= 1) { - if (!(keys & 1)) - continue; - - for (t = type_start; t < IN_BINDTYPE_COUNT; t++) - result[t] |= binds[IN_BIND_OFFS(i, t)]; - } - - return 0; -} - -int in_gp2x_update_keycode(void *data, int *is_down) -{ - static int old_val = 0; - int val, diff, i; - - val = in_gp2x_get_bits(); - diff = val ^ old_val; - if (diff == 0) - return -1; - - /* take one bit only */ - for (i = 0; i < sizeof(diff)*8; i++) - if (diff & (1< kc */ - keycode = -keycode; - for (i = 0; i < KEY_PBTN_MAP_SIZE; i++) - if (key_pbtn_map[i].pbtn == keycode) - return key_pbtn_map[i].key; - } - else - { - for (i = 0; i < KEY_PBTN_MAP_SIZE; i++) - if (key_pbtn_map[i].key == keycode) - return key_pbtn_map[i].pbtn; - } - - return 0; -} - -#if 0 // TODO: move to pico -static const struct { - short code; - char btype; - char bit; -} in_gp2x_defbinds[] = -{ - /* MXYZ SACB RLDU */ - { BTN_UP, IN_BINDTYPE_PLAYER12, 0 }, - { BTN_DOWN, IN_BINDTYPE_PLAYER12, 1 }, - { BTN_LEFT, IN_BINDTYPE_PLAYER12, 2 }, - { BTN_RIGHT, IN_BINDTYPE_PLAYER12, 3 }, - { BTN_X, IN_BINDTYPE_PLAYER12, 4 }, /* B */ - { BTN_B, IN_BINDTYPE_PLAYER12, 5 }, /* C */ - { BTN_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */ - { BTN_START, IN_BINDTYPE_PLAYER12, 7 }, - { BTN_SELECT, IN_BINDTYPE_EMU, PEVB_MENU }, -// { BTN_Y, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, - { BTN_L, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, - { BTN_R, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, - { BTN_VOL_UP, IN_BINDTYPE_EMU, PEVB_VOL_UP }, - { BTN_VOL_DOWN, IN_BINDTYPE_EMU, PEVB_VOL_DOWN }, - { 0, 0, 0 }, -}; -#endif - -/* remove binds of missing keys, count remaining ones */ -static int in_gp2x_clean_binds(void *drv_data, int *binds, int *def_binds) -{ - int i, count = 0; -// int eb, have_vol = 0, have_menu = 0; - - for (i = 0; i < IN_GP2X_NBUTTONS; i++) { - int t, offs; - for (t = 0; t < IN_BINDTYPE_COUNT; t++) { - offs = IN_BIND_OFFS(i, t); - if (in_gp2x_keys[i] == NULL) - binds[offs] = def_binds[offs] = 0; - if (binds[offs]) - count++; - } -#if 0 - eb = binds[IN_BIND_OFFS(i, IN_BINDTYPE_EMU)]; - if (eb & (PEV_VOL_DOWN|PEV_VOL_UP)) - have_vol = 1; - if (eb & PEV_MENU) - have_menu = 1; -#endif - } - - // TODO: move to pico -#if 0 - /* autobind some important keys, if they are unbound */ - if (!have_vol && binds[GP2X_BTN_VOL_UP] == 0 && binds[GP2X_BTN_VOL_DOWN] == 0) { - binds[IN_BIND_OFFS(GP2X_BTN_VOL_UP, IN_BINDTYPE_EMU)] = PEV_VOL_UP; - binds[IN_BIND_OFFS(GP2X_BTN_VOL_DOWN, IN_BINDTYPE_EMU)] = PEV_VOL_DOWN; - count += 2; - } - - if (!have_menu) { - binds[IN_BIND_OFFS(GP2X_BTN_SELECT, IN_BINDTYPE_EMU)] = PEV_MENU; - count++; - } -#endif - - in_combos_find(binds, GP2X_BTN_PUSH, &in_gp2x_combo_keys, &in_gp2x_combo_acts); - - return count; -} - -static const in_drv_t in_gp2x_drv = { - .prefix = IN_GP2X_PREFIX, - .probe = in_gp2x_probe, - .free = in_gp2x_free, - .get_key_names = in_gp2x_get_key_names, - .clean_binds = in_gp2x_clean_binds, - .update = in_gp2x_update, - .update_keycode = in_gp2x_update_keycode, - .menu_translate = in_gp2x_menu_translate, -}; - -void in_gp2x_init(const struct in_default_bind *defbinds) -{ - if (gp2x_dev_id == GP2X_DEV_WIZ) - in_gp2x_keys[GP2X_BTN_START] = "MENU"; - - in_gp2x_combo_keys = in_gp2x_combo_acts = 0; - - in_register_driver(&in_gp2x_drv, defbinds); -} - diff --git a/platform/gp2x/in_gp2x.h b/platform/gp2x/in_gp2x.h deleted file mode 100644 index 035cdedc..00000000 --- a/platform/gp2x/in_gp2x.h +++ /dev/null @@ -1,17 +0,0 @@ - -struct in_default_bind; - -void in_gp2x_init(const struct in_default_bind *defbinds); - -enum { GP2X_BTN_UP = 0, GP2X_BTN_LEFT = 2, GP2X_BTN_DOWN = 4, GP2X_BTN_RIGHT = 6, - GP2X_BTN_START = 8, GP2X_BTN_SELECT = 9, GP2X_BTN_L = 10, GP2X_BTN_R = 11, - GP2X_BTN_A = 12, GP2X_BTN_B = 13, GP2X_BTN_X = 14, GP2X_BTN_Y = 15, - GP2X_BTN_VOL_UP = 23, GP2X_BTN_VOL_DOWN = 22, GP2X_BTN_PUSH = 27 }; - -/* FIXME */ -#ifndef GP2X_DEV_GP2X -extern int gp2x_dev_id; -#define GP2X_DEV_GP2X 1 -#define GP2X_DEV_WIZ 2 -#define GP2X_DEV_CAANOO 3 -#endif diff --git a/platform/gp2x/menu.c b/platform/gp2x/menu.c index eabd74ea..7d7ac93d 100644 --- a/platform/gp2x/menu.c +++ b/platform/gp2x/menu.c @@ -1,65 +1,7 @@ -#include -#include "soc.h" -#include "plat_gp2x.h" - -static void menu_main_plat_draw(void) -{ - static time_t last_bat_read = 0; - static int last_bat_val = -1; - unsigned short *bp = g_screen_ptr; - int bat_h = me_mfont_h * 2 / 3; - int i, u, w, wfill, batt_val; - struct tm *tmp; - time_t ltime; - char time_s[16]; - - if (!(currentConfig.EmuOpt & EOPT_SHOW_RTC)) - return; - - ltime = time(NULL); - tmp = gmtime(<ime); - strftime(time_s, sizeof(time_s), "%H:%M", tmp); - - text_out16(g_screen_width - me_mfont_w * 6, me_mfont_h + 2, time_s); - - if (ltime - last_bat_read > 10) { - last_bat_read = ltime; - last_bat_val = batt_val = gp2x_read_battery(); - } - else - batt_val = last_bat_val; - - if (batt_val < 0 || batt_val > 100) - return; - - /* battery info */ - bp += (me_mfont_h * 2 + 2) * g_screen_width + g_screen_width - me_mfont_w * 3 - 3; - for (i = 0; i < me_mfont_w * 2; i++) - bp[i] = menu_text_color; - for (i = 0; i < me_mfont_w * 2; i++) - bp[i + g_screen_width * bat_h] = menu_text_color; - for (i = 0; i <= bat_h; i++) - bp[i * g_screen_width] = - bp[i * g_screen_width + me_mfont_w * 2] = menu_text_color; - for (i = 2; i < bat_h - 1; i++) - bp[i * g_screen_width - 1] = - bp[i * g_screen_width - 2] = menu_text_color; - - w = me_mfont_w * 2 - 1; - wfill = batt_val * w / 100; - for (u = 1; u < bat_h; u++) - for (i = 0; i < wfill; i++) - bp[(w - i) + g_screen_width * u] = menu_text_color; -} +#include "../libpicofe/gp2x/plat_gp2x.h" // ------------ gfx options menu ------------ -static const char *mgn_aopt_gamma(int id, int *offs) -{ - sprintf(static_buff, "%i.%02i", currentConfig.gamma / 100, currentConfig.gamma % 100); - return static_buff; -} - const char *men_scaling_opts[] = { "OFF", "software", "hardware", NULL }; @@ -67,16 +9,11 @@ const char *men_scaling_opts[] = { "OFF", "software", "hardware", NULL }; mee_enum ("Horizontal scaling", MA_OPT_SCALING, currentConfig.scaling, men_scaling_opts), \ mee_enum ("Vertical scaling", MA_OPT_VSCALING, currentConfig.vscaling, men_scaling_opts), \ mee_onoff ("Tearing Fix", MA_OPT_TEARING_FIX, currentConfig.EmuOpt, EOPT_WIZ_TEAR_FIX), \ - mee_range_cust("Gamma correction", MA_OPT2_GAMMA, currentConfig.gamma, 1, 300, mgn_aopt_gamma), \ - mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, EOPT_A_SN_GAMMA), \ + /*mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, EOPT_A_SN_GAMMA),*/ \ mee_onoff ("Vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC), #define MENU_OPTIONS_ADV \ mee_onoff ("Use second CPU for sound", MA_OPT_ARM940_SOUND, PicoOpt, POPT_EXT_FM), \ - mee_onoff ("RAM overclock", MA_OPT2_RAMTIMINGS, currentConfig.EmuOpt, EOPT_RAM_TIMINGS), \ - mee_onoff ("MMU hack", MA_OPT2_SQUIDGEHACK, currentConfig.EmuOpt, EOPT_MMUHACK), \ - mee_onoff ("SVP dynarec", MA_OPT2_SVP_DYNAREC, PicoOpt, POPT_EN_SVP_DRC), \ - mee_onoff ("Status line in main menu", MA_OPT2_STATUS_LINE, currentConfig.EmuOpt, EOPT_SHOW_RTC), static menu_entry e_menu_adv_options[]; @@ -86,12 +23,6 @@ static menu_entry e_menu_keyconfig[]; void gp2x_menu_init(void) { - static menu_entry *cpu_clk_ent; - int i; - - i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS); - cpu_clk_ent = &e_menu_options[i]; - /* disable by default.. */ me_enable(e_menu_adv_options, MA_OPT_ARM940_SOUND, 0); me_enable(e_menu_gfx_options, MA_OPT_TEARING_FIX, 0); @@ -103,22 +34,16 @@ void gp2x_menu_init(void) me_enable(e_menu_adv_options, MA_OPT_ARM940_SOUND, 1); me_enable(e_menu_gfx_options, MA_OPT2_GAMMA, 1); me_enable(e_menu_gfx_options, MA_OPT2_A_SN_GAMMA, 1); - cpu_clk_ent->name = "GP2X CPU clocks"; break; case GP2X_DEV_WIZ: me_enable(e_menu_gfx_options, MA_OPT_TEARING_FIX, 1); - cpu_clk_ent->name = "Wiz/Caanoo CPU clock"; break; case GP2X_DEV_CAANOO: - cpu_clk_ent->name = "Wiz/Caanoo CPU clock"; break; default: break; } - if (gp2x_set_cpuclk == NULL) - cpu_clk_ent->name = ""; - if (gp2x_dev_id != GP2X_DEV_GP2X) men_scaling_opts[2] = NULL; /* leave only off and sw */ diff --git a/platform/gp2x/plat.c b/platform/gp2x/plat.c index 2a3b0794..503e1496 100644 --- a/platform/gp2x/plat.c +++ b/platform/gp2x/plat.c @@ -1,69 +1,76 @@ #include #include #include +#include -#include "plat_gp2x.h" -#include "soc.h" -#include "warm.h" -#include "../common/plat.h" -#include "../common/readpng.h" -#include "../common/menu.h" #include "../common/emu.h" -#include "../common/input.h" -#include "../linux/sndout_oss.h" +#include "../common/menu_pico.h" +#include "../common/input_pico.h" +#include "../libpicofe/input.h" +#include "../libpicofe/plat.h" +#include "../libpicofe/linux/in_evdev.h" +#include "../libpicofe/gp2x/soc.h" +#include "../libpicofe/gp2x/plat_gp2x.h" +#include "../libpicofe/gp2x/in_gp2x.h" +#include "940ctl.h" +#include "warm.h" +#include "plat.h" #include /* GP2X local */ -int default_cpu_clock; -int gp2x_dev_id; int gp2x_current_bpp; void *gp2x_screens[4]; -#include +void (*gp2x_video_flip)(void); +void (*gp2x_video_flip2)(void); +void (*gp2x_video_changemode_ll)(int bpp); +void (*gp2x_video_setpalette)(int *pal, int len); +void (*gp2x_video_RGB_setscaling)(int ln_offs, int W, int H); +void (*gp2x_video_wait_vsync)(void); -static const char * const caanoo_keys[KEY_MAX + 1] = { - [0 ... KEY_MAX] = NULL, - [KEY_UP] = "Up", - [KEY_LEFT] = "Left", - [KEY_RIGHT] = "Right", - [KEY_DOWN] = "Down", - [BTN_TRIGGER] = "A", - [BTN_THUMB] = "X", - [BTN_THUMB2] = "B", - [BTN_TOP] = "Y", - [BTN_TOP2] = "L", - [BTN_PINKIE] = "R", - [BTN_BASE] = "Home", - [BTN_BASE2] = "Lock", - [BTN_BASE3] = "I", - [BTN_BASE4] = "II", - [BTN_BASE5] = "Push", -}; - -struct in_default_bind in_evdev_defbinds[] = +static struct in_default_bind in_evdev_defbinds[] = { /* MXYZ SACB RLDU */ - { KEY_UP, IN_BINDTYPE_PLAYER12, 0 }, - { KEY_DOWN, IN_BINDTYPE_PLAYER12, 1 }, - { KEY_LEFT, IN_BINDTYPE_PLAYER12, 2 }, - { KEY_RIGHT, IN_BINDTYPE_PLAYER12, 3 }, - { KEY_S, IN_BINDTYPE_PLAYER12, 4 }, /* B */ - { KEY_D, IN_BINDTYPE_PLAYER12, 5 }, /* C */ - { KEY_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */ - { KEY_ENTER, IN_BINDTYPE_PLAYER12, 7 }, + { KEY_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, + { KEY_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN }, + { KEY_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT }, + { KEY_RIGHT, IN_BINDTYPE_PLAYER12, GBTN_RIGHT }, + { KEY_A, IN_BINDTYPE_PLAYER12, GBTN_A }, + { KEY_S, IN_BINDTYPE_PLAYER12, GBTN_B }, + { KEY_D, IN_BINDTYPE_PLAYER12, GBTN_C }, + { KEY_ENTER, IN_BINDTYPE_PLAYER12, GBTN_START }, { KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU }, /* Caanoo */ - { BTN_THUMB, IN_BINDTYPE_PLAYER12, 4 }, /* B */ - { BTN_THUMB2, IN_BINDTYPE_PLAYER12, 5 }, /* C */ - { BTN_TRIGGER, IN_BINDTYPE_PLAYER12, 6 }, /* A */ - { BTN_BASE3, IN_BINDTYPE_PLAYER12, 7 }, + { BTN_TRIGGER, IN_BINDTYPE_PLAYER12, GBTN_A }, + { BTN_THUMB, IN_BINDTYPE_PLAYER12, GBTN_B }, + { BTN_THUMB2, IN_BINDTYPE_PLAYER12, GBTN_C }, + { BTN_BASE3, IN_BINDTYPE_PLAYER12, GBTN_START }, { BTN_TOP2, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, { BTN_PINKIE, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, { BTN_BASE, IN_BINDTYPE_EMU, PEVB_MENU }, { 0, 0, 0 } }; +static struct in_default_bind in_gp2x_defbinds[] = +{ + { GP2X_BTN_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, + { GP2X_BTN_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN }, + { GP2X_BTN_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT }, + { GP2X_BTN_RIGHT, IN_BINDTYPE_PLAYER12, GBTN_RIGHT }, + { GP2X_BTN_A, IN_BINDTYPE_PLAYER12, GBTN_A }, + { GP2X_BTN_X, IN_BINDTYPE_PLAYER12, GBTN_B }, + { GP2X_BTN_B, IN_BINDTYPE_PLAYER12, GBTN_C }, + { GP2X_BTN_START, IN_BINDTYPE_PLAYER12, GBTN_START }, + { GP2X_BTN_Y, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, + { GP2X_BTN_L, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, + { GP2X_BTN_R, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, + { GP2X_BTN_VOL_DOWN, IN_BINDTYPE_EMU, PEVB_VOL_DOWN }, + { GP2X_BTN_VOL_UP, IN_BINDTYPE_EMU, PEVB_VOL_UP }, + { GP2X_BTN_SELECT, IN_BINDTYPE_EMU, PEVB_MENU }, + { 0, 0, 0 } +}; + void gp2x_video_changemode(int bpp) { gp2x_video_changemode_ll(bpp); @@ -126,6 +133,7 @@ void plat_video_menu_enter(int is_rom_loaded) // switch to 16bpp gp2x_video_changemode_ll(16); gp2x_video_RGB_setscaling(0, 320, 240); +printf("menu_enter\n"); } void plat_video_menu_begin(void) @@ -138,36 +146,12 @@ void plat_video_menu_end(void) gp2x_video_flip2(); } +void plat_video_menu_leave(void) +{ +} + void plat_early_init(void) { - gp2x_soc_t soc; - FILE *f; - - soc = soc_detect(); - switch (soc) - { - case SOCID_MMSP2: - default_cpu_clock = 200; - gp2x_dev_id = GP2X_DEV_GP2X; - break; - case SOCID_POLLUX: - default_cpu_clock = 533; - f = fopen("/dev/accel", "rb"); - if (f) { - printf("detected Caanoo\n"); - gp2x_dev_id = GP2X_DEV_CAANOO; - fclose(f); - } - else { - printf("detected Wiz\n"); - gp2x_dev_id = GP2X_DEV_WIZ; - } - break; - default: - printf("could not recognize SoC, running in dummy mode.\n"); - break; - } - // just use gettimeofday until plat_init() gp2x_get_ticks_ms = plat_get_ticks_ms_good; gp2x_get_ticks_us = plat_get_ticks_us_good; @@ -175,55 +159,49 @@ void plat_early_init(void) void plat_init(void) { - gp2x_soc_t soc; + warm_init(); - soc = soc_detect(); - switch (soc) - { - case SOCID_MMSP2: - mmsp2_init(); + switch (gp2x_dev_id) { + case GP2X_DEV_GP2X: + sharedmem940_init(); + vid_mmsp2_init(); break; - case SOCID_POLLUX: - pollux_init(); - break; - default: - dummy_init(); + case GP2X_DEV_WIZ: + case GP2X_DEV_CAANOO: + vid_pollux_init(); break; } - warm_init(); - + g_menuscreen_w = 320; + g_menuscreen_h = 240; gp2x_memset_all_buffers(0, 0, 320*240*2); + gp2x_make_fb_bufferable(1); + // use buffer2 for menubg to save mem (using only buffers 0, 1 in menu) g_menubg_ptr = gp2x_screens[2]; - if (gp2x_dev_id == GP2X_DEV_CAANOO) - in_set_config(in_name_to_id("evdev:pollux-analog"), IN_CFG_KEY_NAMES, - caanoo_keys, sizeof(caanoo_keys)); - flip_after_sync = 1; gp2x_menu_init(); + + in_evdev_init(in_evdev_defbinds); + in_gp2x_init(in_gp2x_defbinds); + in_probe(); + plat_target_setup_input(); } void plat_finish(void) { - gp2x_soc_t soc; - warm_finish(); - soc = soc_detect(); - switch (soc) - { - case SOCID_MMSP2: - mmsp2_finish(); + switch (gp2x_dev_id) { + case GP2X_DEV_GP2X: + sharedmem940_finish(); + vid_mmsp2_finish(); break; - case SOCID_POLLUX: - pollux_finish(); - break; - default: - dummy_finish(); + case GP2X_DEV_WIZ: + case GP2X_DEV_CAANOO: + vid_pollux_finish(); break; } } - diff --git a/platform/gp2x/plat.h b/platform/gp2x/plat.h new file mode 100644 index 00000000..d46c4303 --- /dev/null +++ b/platform/gp2x/plat.h @@ -0,0 +1,25 @@ +extern void *gp2x_screens[4]; +extern int gp2x_current_bpp; + +/* SoC specific functions */ +extern void (*gp2x_video_flip)(void); +extern void (*gp2x_video_flip2)(void); +/* negative bpp means rotated mode (for Wiz) */ +extern void (*gp2x_video_changemode_ll)(int bpp); +extern void (*gp2x_video_setpalette)(int *pal, int len); +extern void (*gp2x_video_RGB_setscaling)(int ln_offs, int W, int H); +extern void (*gp2x_video_wait_vsync)(void); + +/* ??? */ +void gp2x_video_changemode(int bpp); +void gp2x_memcpy_all_buffers(void *data, int offset, int len); +void gp2x_memset_all_buffers(int offset, int byte, int len); + +/* vid_*.c */ +void vid_mmsp2_init(void); +void vid_mmsp2_finish(void); + +void vid_pollux_init(); +void vid_pollux_finish(); + +void gp2x_menu_init(void); diff --git a/platform/gp2x/plat_gp2x.h b/platform/gp2x/plat_gp2x.h deleted file mode 100644 index c77e061f..00000000 --- a/platform/gp2x/plat_gp2x.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __GP2X_H__ -#define __GP2X_H__ - -extern int default_cpu_clock; - -/* video */ -void gp2x_video_changemode(int bpp); -void gp2x_memcpy_all_buffers(void *data, int offset, int len); -void gp2x_memset_all_buffers(int offset, int byte, int len); -void gp2x_make_fb_bufferable(int yes); - -/* input */ -int gp2x_touchpad_read(int *x, int *y); - -/* misc */ -enum { - GP2X_DEV_GP2X = 1, - GP2X_DEV_WIZ, - GP2X_DEV_CAANOO, -}; -extern int gp2x_dev_id; -extern int gp2x_current_bpp; - -unsigned int plat_get_ticks_ms_good(void); -unsigned int plat_get_ticks_us_good(void); - -void gp2x_menu_init(void); - -#endif diff --git a/platform/gp2x/pollux_set.c b/platform/gp2x/pollux_set.c deleted file mode 100644 index 9781c828..00000000 --- a/platform/gp2x/pollux_set.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * quick tool to set various timings for Wiz - * - * Copyright (c) Gražvydas "notaz" Ignotas, 2009 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the organization nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * HTOTAL: X VTOTAL: 341 - * HSWIDTH: 1 VSWIDTH: 0 - * HASTART: 37 VASTART: 17 - * HAEND: 277 VAEND: 337 - * - * 120Hz - * pcd 8, 447: + 594us - * pcd 9, 397: + 36us - * pcd 10, 357: - 523us - * pcd 11, 325: +1153us - * - * 'lcd_timings=397,1,37,277,341,0,17,337;dpc_clkdiv0=9' - * 'ram_timings=2,9,4,1,1,1,1' - */ - -#include -#include -#include -#include "pollux_set.h" - -/* parse stuff */ -static int parse_lcd_timings(const char *str, void *data) -{ - int *lcd_timings = data; - const char *p = str; - int ret, c; - ret = sscanf(str, "%d,%d,%d,%d,%d,%d,%d,%d", - &lcd_timings[0], &lcd_timings[1], &lcd_timings[2], &lcd_timings[3], - &lcd_timings[4], &lcd_timings[5], &lcd_timings[6], &lcd_timings[7]); - if (ret != 8) - return -1; - /* skip seven commas */ - for (c = 0; c < 7 && *p != 0; p++) - if (*p == ',') - c++; - if (c != 7) - return -1; - /* skip last number */ - while ('0' <= *p && *p <= '9') - p++; - - return p - str; -} - -static int parse_ram_timings(const char *str, void *data) -{ - int *ram_timings = data; - const char *p = str; - int ret, c; - float cas; - - ret = sscanf(p, "%f,%d,%d,%d,%d,%d,%d", - &cas, &ram_timings[1], &ram_timings[2], &ram_timings[3], - &ram_timings[4], &ram_timings[5], &ram_timings[6]); - if (ret != 7) - return -1; - if (cas == 2) - ram_timings[0] = 1; - else if (cas == 2.5) - ram_timings[0] = 2; - else if (cas == 3) - ram_timings[0] = 3; - else - return -1; - for (c = 0; c < 6 && *p != 0; p++) - if (*p == ',') - c++; - if (c != 6) - return -1; - while ('0' <= *p && *p <= '9') - p++; - - return p - str; -} - -static int parse_decimal(const char *str, void *data) -{ - char *ep; - - *(int *)data = strtoul(str, &ep, 10); - if (ep == str) - return -1; - - return ep - str; -} - -/* validate and apply stuff */ -static int apply_lcd_timings(volatile unsigned short *memregs, void *data) -{ - int *lcd_timings = data; - int i; - - for (i = 0; i < 8; i++) { - if (lcd_timings[i] & ~0xffff) { - fprintf(stderr, "pollux_set: invalid lcd timing %d: %d\n", i, lcd_timings[i]); - return -1; - } - } - - for (i = 0; i < 8; i++) - memregs[(0x307c>>1) + i] = lcd_timings[i]; - - return 0; -} - -static const struct { - signed char adj; /* how to adjust value passed by user */ - signed short min; /* range of */ - signed short max; /* allowed values (inclusive) */ -} -ram_ranges[] = { - { 0, 1, 3 }, /* cas (cl) */ - { -2, 0, 15 }, /* trc */ - { -2, 0, 15 }, /* tras */ - { 0, 0, 15 }, /* twr */ - { 0, 0, 15 }, /* tmrd */ - { 0, 0, 15 }, /* trp */ - { 0, 0, 15 }, /* trcd */ -}; - -static int apply_ram_timings(volatile unsigned short *memregs, void *data) -{ - int *ram_timings = data; - int i, val; - - for (i = 0; i < 7; i++) - { - ram_timings[i] += ram_ranges[i].adj; - if (ram_timings[i] < ram_ranges[i].min || ram_timings[i] > ram_ranges[i].max) { - fprintf(stderr, "pollux_set: invalid RAM timing %d\n", i); - return -1; - } - } - - val = memregs[0x14802>>1] & 0x0f00; - val |= (ram_timings[4] << 12) | (ram_timings[5] << 4) | ram_timings[6]; - memregs[0x14802>>1] = val; - - val = memregs[0x14804>>1] & 0x4000; - val |= (ram_timings[0] << 12) | (ram_timings[1] << 8) | - (ram_timings[2] << 4) | ram_timings[3]; - val |= 0x8000; - memregs[0x14804>>1] = val; - - for (i = 0; i < 0x100000 && (memregs[0x14804>>1] & 0x8000); i++) - ; - - return 0; -} - -static int apply_dpc_clkdiv0(volatile unsigned short *memregs, void *data) -{ - int pcd = *(int *)data; - int tmp; - - if ((pcd - 1) & ~0x3f) { - fprintf(stderr, "pollux_set: invalid lcd clkdiv0: %d\n", pcd); - return -1; - } - - pcd = (pcd - 1) & 0x3f; - tmp = memregs[0x31c4>>1]; - memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4); - - return 0; -} - -static int apply_cpuclk(volatile unsigned short *memregs, void *data) -{ - volatile unsigned int *memregl = (volatile void *)memregs; - int mhz = *(int *)data; - int adiv, mdiv, pdiv, sdiv = 0; - int i, vf000, vf004; - - // m = MDIV, p = PDIV, s = SDIV - #define SYS_CLK_FREQ 27 - pdiv = 9; - mdiv = (mhz * pdiv) / SYS_CLK_FREQ; - if (mdiv & ~0x3ff) - return -1; - vf004 = (pdiv<<18) | (mdiv<<8) | sdiv; - - // attempt to keep AHB the divider close to 250, but not higher - for (adiv = 1; mhz / adiv > 250; adiv++) - ; - - vf000 = memregl[0xf000>>2]; - vf000 = (vf000 & ~0x3c0) | ((adiv - 1) << 6); - memregl[0xf000>>2] = vf000; - memregl[0xf004>>2] = vf004; - memregl[0xf07c>>2] |= 0x8000; - for (i = 0; (memregl[0xf07c>>2] & 0x8000) && i < 0x100000; i++) - ; - - printf("clock set to %dMHz, AHB set to %dMHz\n", mhz, mhz / adiv); - return 0; -} - -static int lcd_timings[8]; -static int ram_timings[7]; -static int dpc_clkdiv0; -static int cpuclk; - -static const char lcd_t_help[] = "htotal,hswidth,hastart,haend,vtotal,vswidth,vastart,vaend"; -static const char ram_t_help[] = "CAS,tRC,tRAS,tWR,tMRD,tRP,tRCD"; - -static const struct { - const char *name; - const char *help; - int (*parse)(const char *str, void *data); - int (*apply)(volatile unsigned short *memregs, void *data); - void *data; -} -all_params[] = { - { "lcd_timings", lcd_t_help, parse_lcd_timings, apply_lcd_timings, lcd_timings }, - { "ram_timings", ram_t_help, parse_ram_timings, apply_ram_timings, ram_timings }, - { "dpc_clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 }, - { "clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 }, /* alias */ - { "cpuclk", "MHZ", parse_decimal, apply_cpuclk, &cpuclk }, -}; -#define ALL_PARAM_COUNT (sizeof(all_params) / sizeof(all_params[0])) - -/* - * set timings based on preformated string - * returns 0 on success. - */ -int pollux_set(volatile unsigned short *memregs, const char *str) -{ - int parsed_params[ALL_PARAM_COUNT]; - int applied_params[ALL_PARAM_COUNT]; - int applied_something = 0; - const char *p, *po; - int i, ret; - - if (str == NULL) - return -1; - - memset(parsed_params, 0, sizeof(parsed_params)); - memset(applied_params, 0, sizeof(applied_params)); - - p = str; - while (1) - { -again: - while (*p == ';' || *p == ' ') - p++; - if (*p == 0) - break; - - for (i = 0; i < ALL_PARAM_COUNT; i++) - { - int param_len = strlen(all_params[i].name); - if (strncmp(p, all_params[i].name, param_len) == 0 && p[param_len] == '=') - { - p += param_len + 1; - ret = all_params[i].parse(p, all_params[i].data); - if (ret < 0) { - fprintf(stderr, "pollux_set parser: error at %-10s\n", p); - fprintf(stderr, " valid format is: <%s>\n", all_params[i].help); - return -1; - } - parsed_params[i] = 1; - p += ret; - goto again; - } - } - - /* Unknown param. Attempt to be forward compatible and ignore it. */ - for (po = p; *p != 0 && *p != ';'; p++) - ; - - fprintf(stderr, "unhandled param: "); - fwrite(po, 1, p - po, stderr); - fprintf(stderr, "\n"); - } - - /* validate and apply */ - for (i = 0; i < ALL_PARAM_COUNT; i++) - { - if (!parsed_params[i]) - continue; - - ret = all_params[i].apply(memregs, all_params[i].data); - if (ret < 0) { - fprintf(stderr, "pollux_set: failed to apply %s (bad value?)\n", - all_params[i].name); - continue; - } - - applied_something = 1; - applied_params[i] = 1; - } - - if (applied_something) - { - int c; - printf("applied: "); - for (i = c = 0; i < ALL_PARAM_COUNT; i++) - { - if (!applied_params[i]) - continue; - if (c != 0) - printf(", "); - printf("%s", all_params[i].name); - c++; - } - printf("\n"); - } - - return 0; -} - -#ifdef BINARY -#include -#include -#include -#include -#include - -static void usage(const char *binary) -{ - int i; - printf("usage:\n%s \n" - "set_str:\n", binary); - for (i = 0; i < ALL_PARAM_COUNT; i++) - printf(" %s=<%s>\n", all_params[i].name, all_params[i].help); -} - -int main(int argc, char *argv[]) -{ - volatile unsigned short *memregs; - int ret, memdev; - - if (argc != 2) { - usage(argv[0]); - return 1; - } - - memdev = open("/dev/mem", O_RDWR); - if (memdev == -1) - { - perror("open(/dev/mem) failed"); - return 1; - } - - memregs = mmap(0, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); - if (memregs == MAP_FAILED) - { - perror("mmap(memregs) failed"); - close(memdev); - return 1; - } - - ret = pollux_set(memregs, argv[1]); - - munmap((void *)memregs, 0x20000); - close(memdev); - - return ret; -} -#endif diff --git a/platform/gp2x/pollux_set.h b/platform/gp2x/pollux_set.h deleted file mode 100644 index 64bb2202..00000000 --- a/platform/gp2x/pollux_set.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifdef __cplusplus -extern "C" -{ -#endif - -int pollux_set(volatile unsigned short *memregs, const char *str); - -#ifdef __cplusplus -} -#endif diff --git a/platform/gp2x/soc.c b/platform/gp2x/soc.c deleted file mode 100644 index 43ebd85c..00000000 --- a/platform/gp2x/soc.c +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "soc.h" - -void (*gp2x_video_flip)(void); -void (*gp2x_video_flip2)(void); -void (*gp2x_video_changemode_ll)(int bpp); -void (*gp2x_video_setpalette)(int *pal, int len); -void (*gp2x_video_RGB_setscaling)(int ln_offs, int W, int H); -void (*gp2x_video_wait_vsync)(void); - -void (*gp2x_set_cpuclk)(unsigned int mhz); - -void (*set_lcd_custom_rate)(int is_pal); -void (*unset_lcd_custom_rate)(void); -void (*set_lcd_gamma)(int g100, int A_SNs_curve); - -void (*set_ram_timings)(void); -void (*unset_ram_timings)(void); -int (*gp2x_read_battery)(void); - -unsigned int (*gp2x_get_ticks_ms)(void); -unsigned int (*gp2x_get_ticks_us)(void); - - -gp2x_soc_t soc_detect(void) -{ - volatile unsigned short *memregs; - volatile unsigned int *memregl; - static gp2x_soc_t ret = -2; - int pollux_chipname[0x30/4 + 1]; - char *pollux_chipname_c = (char *)pollux_chipname; - int memdev; - int i; - - if ((int)ret != -2) - /* already detected */ - return ret; - - memdev = open("/dev/mem", O_RDONLY); - if (memdev == -1) - { - perror("open(/dev/mem)"); - ret = -1; - return -1; - } - - memregs = mmap(0, 0x20000, PROT_READ, MAP_SHARED, memdev, 0xc0000000); - if (memregs == MAP_FAILED) - { - perror("mmap(memregs)"); - close(memdev); - ret = -1; - return -1; - } - memregl = (volatile void *)memregs; - - if (memregs[0x1836>>1] == 0x2330) - { - printf("looks like this is MMSP2\n"); - ret = SOCID_MMSP2; - goto out; - } - - /* perform word reads. Byte reads might also work, - * but we don't want to play with that. */ - for (i = 0; i < 0x30; i += 4) - { - pollux_chipname[i >> 2] = memregl[(0x1f810 + i) >> 2]; - } - pollux_chipname_c[0x30] = 0; - - for (i = 0; i < 0x30; i++) - { - unsigned char c = pollux_chipname_c[i]; - if (c < 0x20 || c > 0x7f) - goto not_pollux_like; - } - - printf("found pollux-like id: \"%s\"\n", pollux_chipname_c); - - if (strncmp(pollux_chipname_c, "MAGICEYES-LEAPFROG-LF1000", 25) || - strncmp(pollux_chipname_c, "MAGICEYES-POLLUX", 16)) - { - ret = SOCID_POLLUX; - goto out; - } - -not_pollux_like: -out: - munmap((void *)memregs, 0x20000); - close(memdev); - return ret; -} - diff --git a/platform/gp2x/soc.h b/platform/gp2x/soc.h deleted file mode 100644 index 96861480..00000000 --- a/platform/gp2x/soc.h +++ /dev/null @@ -1,38 +0,0 @@ -typedef enum { - SOCID_MMSP2 = 1, - SOCID_POLLUX, -} gp2x_soc_t; - -gp2x_soc_t soc_detect(void); - -void mmsp2_init(void); -void mmsp2_finish(void); - -void pollux_init(void); -void pollux_finish(void); - -void dummy_init(void); -void dummy_finish(void); - -/* SoC specific functions */ -extern void (*gp2x_video_flip)(void); -extern void (*gp2x_video_flip2)(void); -/* negative bpp means rotated mode (for Wiz) */ -extern void (*gp2x_video_changemode_ll)(int bpp); -extern void (*gp2x_video_setpalette)(int *pal, int len); -extern void (*gp2x_video_RGB_setscaling)(int ln_offs, int W, int H); -extern void (*gp2x_video_wait_vsync)(void); - -extern void (*gp2x_set_cpuclk)(unsigned int mhz); - -extern void (*set_lcd_custom_rate)(int is_pal); -extern void (*unset_lcd_custom_rate)(void); -extern void (*set_lcd_gamma)(int g100, int A_SNs_curve); - -extern void (*set_ram_timings)(void); -extern void (*unset_ram_timings)(void); -extern int (*gp2x_read_battery)(void); - -/* gettimeofday is not suitable for Wiz, at least fw 1.1 or lower */ -extern unsigned int (*gp2x_get_ticks_ms)(void); -extern unsigned int (*gp2x_get_ticks_us)(void); diff --git a/platform/gp2x/soc_dummy.c b/platform/gp2x/soc_dummy.c deleted file mode 100644 index 99910825..00000000 --- a/platform/gp2x/soc_dummy.c +++ /dev/null @@ -1,95 +0,0 @@ -/* dummy code for qemu testing, etc */ -#include - -#include "soc.h" -#include "../common/emu.h" - -extern void *gp2x_screens[4]; - -extern unsigned int plat_get_ticks_ms_good(void); -extern unsigned int plat_get_ticks_us_good(void); - -/* video stuff */ -static void gp2x_video_flip_(void) -{ -} - -/* doulblebuffered flip */ -static void gp2x_video_flip2_(void) -{ -} - -static void gp2x_video_changemode_ll_(int bpp) -{ -} - -static void gp2x_video_setpalette_(int *pal, int len) -{ -} - -static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H) -{ -} - -static void gp2x_video_wait_vsync_(void) -{ -} - -/* RAM timings */ -static void set_ram_timings_(void) -{ -} - -static void unset_ram_timings_(void) -{ -} - -/* LCD refresh */ -static void set_lcd_custom_rate_(int is_pal) -{ -} - -static void unset_lcd_custom_rate_(void) -{ -} - -static void set_lcd_gamma_(int g100, int A_SNs_curve) -{ -} - -static int gp2x_read_battery_(void) -{ - return 0; -} - -void dummy_init(void) -{ - int i; - g_screen_ptr = malloc(320 * 240 * 2); - for (i = 0; i < array_size(gp2x_screens); i++) - gp2x_screens[i] = g_screen_ptr; - - gp2x_video_flip = gp2x_video_flip_; - gp2x_video_flip2 = gp2x_video_flip2_; - gp2x_video_changemode_ll = gp2x_video_changemode_ll_; - gp2x_video_setpalette = gp2x_video_setpalette_; - gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_; - gp2x_video_wait_vsync = gp2x_video_wait_vsync_; - - set_lcd_custom_rate = set_lcd_custom_rate_; - unset_lcd_custom_rate = unset_lcd_custom_rate_; - set_lcd_gamma = set_lcd_gamma_; - - set_ram_timings = set_ram_timings_; - unset_ram_timings = unset_ram_timings_; - gp2x_read_battery = gp2x_read_battery_; - - gp2x_get_ticks_ms = plat_get_ticks_ms_good; - gp2x_get_ticks_us = plat_get_ticks_us_good; -} - -void dummy_finish(void) -{ - free(gp2x_screens[0]); -} - diff --git a/platform/gp2x/soc_mmsp2.c b/platform/gp2x/soc_mmsp2.c deleted file mode 100644 index 9ef1e9b8..00000000 --- a/platform/gp2x/soc_mmsp2.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * PicoDrive - * (C) notaz, 2006-2009 - * - * This work is licensed under the terms of MAME license. - * See COPYING file in the top-level directory. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "soc.h" -#include "soc_mmsp2.h" -#include "plat_gp2x.h" -#include "../common/emu.h" -#include "../common/plat.h" -#include "../common/arm_utils.h" -#include "940ctl.h" - -volatile unsigned short *gp2x_memregs; -volatile unsigned long *gp2x_memregl; -extern void *gp2x_screens[4]; -static int screensel = 0; - -int memdev = -1; /* used by code940 */ -static int touchdev = -1; -static int touchcal[7] = { 6203, 0, -1501397, 0, -4200, 16132680, 65536 }; - -#define FRAMEBUFF_SIZE 0x30000 -#define FRAMEBUFF_WHOLESIZE (FRAMEBUFF_SIZE*4) // 320*240*2 + some more -#define FRAMEBUFF_ADDR0 (0x4000000 - FRAMEBUFF_WHOLESIZE) -#define FRAMEBUFF_ADDR1 (FRAMEBUFF_ADDR0 + FRAMEBUFF_SIZE) -#define FRAMEBUFF_ADDR2 (FRAMEBUFF_ADDR1 + FRAMEBUFF_SIZE) -#define FRAMEBUFF_ADDR3 (FRAMEBUFF_ADDR2 + FRAMEBUFF_SIZE) - -static const int gp2x_screenaddrs[4] = { FRAMEBUFF_ADDR0, FRAMEBUFF_ADDR1, FRAMEBUFF_ADDR2, FRAMEBUFF_ADDR3 }; -static int gp2x_screenaddrs_use[4]; - -static char gamma_was_changed = 0; -static char cpuclk_was_changed = 0; -static unsigned short gp2x_screenaddr_old[4]; -static unsigned short memtimex_old[2]; -static unsigned short reg0910; - -/* video stuff */ -static void gp2x_video_flip_(void) -{ - unsigned short lsw = (unsigned short) gp2x_screenaddrs_use[screensel&3]; - unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&3] >> 16); - - gp2x_memregs[0x2910>>1] = msw; - gp2x_memregs[0x2914>>1] = msw; - gp2x_memregs[0x290E>>1] = lsw; - gp2x_memregs[0x2912>>1] = lsw; - - // jump to other buffer: - g_screen_ptr = gp2x_screens[++screensel&3]; -} - -/* doulblebuffered flip */ -static void gp2x_video_flip2_(void) -{ - unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&1] >> 16); - - gp2x_memregs[0x2910>>1] = msw; - gp2x_memregs[0x2914>>1] = msw; - gp2x_memregs[0x290E>>1] = 0; - gp2x_memregs[0x2912>>1] = 0; - - // jump to other buffer: - g_screen_ptr = gp2x_screens[++screensel&1]; -} - -static void gp2x_video_changemode_ll_(int bpp) -{ - gp2x_memregs[0x28DA>>1] = (((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/ - gp2x_memregs[0x290C>>1] = 320*((bpp+1)/8); /*line width in bytes*/ -} - -static void gp2x_video_setpalette_(int *pal, int len) -{ - unsigned short *g = (unsigned short *)pal; - volatile unsigned short *memreg = &gp2x_memregs[0x295A>>1]; - - gp2x_memregs[0x2958>>1] = 0; - - len *= 2; - while (len--) - *memreg = *g++; -} - -static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H) -{ - float escalaw, escalah; - int bpp = (gp2x_memregs[0x28DA>>1]>>9)&0x3; - unsigned short scalw; - - // set offset - gp2x_screenaddrs_use[0] = gp2x_screenaddrs[0] + ln_offs * 320 * bpp; - gp2x_screenaddrs_use[1] = gp2x_screenaddrs[1] + ln_offs * 320 * bpp; - gp2x_screenaddrs_use[2] = gp2x_screenaddrs[2] + ln_offs * 320 * bpp; - gp2x_screenaddrs_use[3] = gp2x_screenaddrs[3] + ln_offs * 320 * bpp; - - escalaw = 1024.0; // RGB Horiz LCD - escalah = 320.0; // RGB Vert LCD - - if (gp2x_memregs[0x2800>>1]&0x100) //TV-Out - { - escalaw=489.0; // RGB Horiz TV (PAL, NTSC) - if (gp2x_memregs[0x2818>>1] == 287) //PAL - escalah=274.0; // RGB Vert TV PAL - else if (gp2x_memregs[0x2818>>1] == 239) //NTSC - escalah=331.0; // RGB Vert TV NTSC - } - - // scale horizontal - scalw = (unsigned short)((float)escalaw *(W/320.0)); - /* if there is no horizontal scaling, vertical doesn't work. - * Here is a nasty wrokaround... */ - if (H != 240 && W == 320) scalw--; - gp2x_memregs[0x2906>>1]=scalw; - // scale vertical - gp2x_memregl[0x2908>>2]=(unsigned long)((float)escalah *bpp *(H/240.0)); -} - -static void gp2x_video_wait_vsync_(void) -{ - unsigned short v = gp2x_memregs[0x1182>>1]; - while (!((v ^ gp2x_memregs[0x1182>>1]) & 0x10)) - spend_cycles(1024); -} - -/* 940 */ -void pause940(int yes) -{ - if (yes) - gp2x_memregs[0x0904>>1] &= 0xFFFE; - else - gp2x_memregs[0x0904>>1] |= 1; -} - -void reset940(int yes, int bank) -{ - gp2x_memregs[0x3B48>>1] = ((yes&1) << 7) | (bank & 0x03); -} - -/* - * CPU clock - * Fout = (m * Fin) / (p * 2^s) - * m = MDIV+8, p = PDIV+2, s = SDIV - * - * m = (Fout * p * 2^s) / Fin - */ - -#define SYS_CLK_FREQ 7372800 - -static void gp2x_set_cpuclk_(unsigned int mhz) -{ - unsigned int mdiv, pdiv, sdiv = 0; - unsigned int v; - int i; - - pdiv = 3; - mdiv = (mhz * pdiv * 1000000) / SYS_CLK_FREQ; - if (mdiv & ~0xff) { - fprintf(stderr, "invalid cpuclk MHz: %u\n", mhz); - return; - } - v = ((mdiv-8)<<8) | ((pdiv-2)<<2) | sdiv; - gp2x_memregs[0x910>>1] = v; - - for (i = 0; i < 10000; i++) - if (!(gp2x_memregs[0x902>>1] & 1)) - break; - - cpuclk_was_changed = 1; -} - -/* RAM timings */ -#define TIMING_CHECK(t, adj, mask) \ - t += adj; \ - if (t & ~mask) \ - goto bad - -static void set_ram_timing_vals(int tCAS, int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD) -{ - int i; - TIMING_CHECK(tCAS, -2, 0x1); - TIMING_CHECK(tRC, -1, 0xf); - TIMING_CHECK(tRAS, -1, 0xf); - TIMING_CHECK(tWR, -1, 0xf); - TIMING_CHECK(tMRD, -1, 0xf); - TIMING_CHECK(tRFC, -1, 0xf); - TIMING_CHECK(tRP, -1, 0xf); - TIMING_CHECK(tRCD, -1, 0xf); - - /* get spend_cycles() into cache */ - spend_cycles(1); - - gp2x_memregs[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF); - gp2x_memregs[0x3804>>1] = 0x8000 | ((tCAS & 1) << 12) | ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF); - - /* be sure we don't access the mem while it's being reprogrammed */ - spend_cycles(128*1024); - for (i = 0; i < 8*1024; i++) - if (!(gp2x_memregs[0x3804>>1] & 0x8000)) - break; - - printf("RAM timings set.\n"); - return; -bad: - fprintf(stderr, "RAM timings invalid.\n"); -} - -static void set_ram_timings_(void) -{ - /* craigix: --cas 2 --trc 6 --tras 4 --twr 1 --tmrd 1 --trfc 1 --trp 2 --trcd 2 */ - set_ram_timing_vals(2, 6, 4, 1, 1, 1, 2, 2); -} - -static void unset_ram_timings_(void) -{ - gp2x_memregs[0x3802>>1] = memtimex_old[0]; - gp2x_memregs[0x3804>>1] = memtimex_old[1] | 0x8000; - printf("RAM timings reset to startup values.\n"); -} - -/* LCD refresh */ -typedef struct -{ - unsigned short reg, valmask, val; -} -reg_setting; - -/* 120.00 97/0/2/7|25/ 7/ 7/11/37 */ -static const reg_setting lcd_rate_120[] = -{ - { 0x0914, 0xffff, (97<<8)|(0<<2)|2 }, /* UPLLSETVREG */ - { 0x0924, 0xff00, (2<<14)|(7<<8) }, /* DISPCSETREG */ - { 0x281A, 0x00ff, 25 }, /* .HSWID(T2) */ - { 0x281C, 0x00ff, 7 }, /* .HSSTR(T8) */ - { 0x281E, 0x00ff, 7 }, /* .HSEND(T7) */ - { 0x2822, 0x01ff, 11 }, /* .VSEND (T9) */ - { 0x2826, 0x0ff0, 37<<4 }, /* .DESTR(T3) */ - { 0, 0, 0 } -}; - -/* 100.00 96/0/2/7|29/25/53/15/37 */ -static const reg_setting lcd_rate_100[] = -{ - { 0x0914, 0xffff, (96<<8)|(0<<2)|2 }, /* UPLLSETVREG */ - { 0x0924, 0xff00, (2<<14)|(7<<8) }, /* DISPCSETREG */ - { 0x281A, 0x00ff, 29 }, /* .HSWID(T2) */ - { 0x281C, 0x00ff, 25 }, /* .HSSTR(T8) */ - { 0x281E, 0x00ff, 53 }, /* .HSEND(T7) */ - { 0x2822, 0x01ff, 15 }, /* .VSEND (T9) */ - { 0x2826, 0x0ff0, 37<<4 }, /* .DESTR(T3) */ - { 0, 0, 0 } -}; - -static reg_setting lcd_rate_defaults[] = -{ - { 0x0914, 0xffff, 0 }, - { 0x0924, 0xff00, 0 }, - { 0x281A, 0x00ff, 0 }, - { 0x281C, 0x00ff, 0 }, - { 0x281E, 0x00ff, 0 }, - { 0x2822, 0x01ff, 0 }, - { 0x2826, 0x0ff0, 0 }, - { 0, 0, 0 } -}; - -static void get_reg_setting(reg_setting *set) -{ - for (; set->reg; set++) - { - unsigned short val = gp2x_memregs[set->reg >> 1]; - val &= set->valmask; - set->val = val; - } -} - -static void set_reg_setting(const reg_setting *set) -{ - for (; set->reg; set++) - { - unsigned short val = gp2x_memregs[set->reg >> 1]; - val &= ~set->valmask; - val |= set->val; - gp2x_memregs[set->reg >> 1] = val; - } -} - -static void set_lcd_custom_rate_(int is_pal) -{ - if (gp2x_memregs[0x2800>>1] & 0x100) // tv-out - return; - - printf("setting custom LCD refresh (%d Hz)... ", is_pal ? 100 : 120); - fflush(stdout); - - set_reg_setting(is_pal ? lcd_rate_100 : lcd_rate_120); - printf("done.\n"); -} - -static void unset_lcd_custom_rate_(void) -{ - printf("reset to prev LCD refresh.\n"); - set_reg_setting(lcd_rate_defaults); -} - -static void set_lcd_gamma_(int g100, int A_SNs_curve) -{ - float gamma = (float) g100 / 100; - int i; - gamma = 1 / gamma; - - /* enable gamma */ - gp2x_memregs[0x2880>>1] &= ~(1<<12); - - gp2x_memregs[0x295C>>1] = 0; - for (i = 0; i < 256; i++) - { - unsigned char g; - unsigned short s; - const unsigned short grey50=143, grey75=177, grey25=97; - double blah; - - if (A_SNs_curve) - { - // The next formula is all about gaussian interpolation - blah = (( -128 * exp(-powf((float) i/64.0f + 2.0f , 2.0f))) + - ( -64 * exp(-powf((float) i/64.0f + 1.0f , 2.0f))) + - (grey25 * exp(-powf((float) i/64.0f - 1.0f , 2.0f))) + - (grey50 * exp(-powf((float) i/64.0f - 2.0f , 2.0f))) + - (grey75 * exp(-powf((float) i/64.0f - 3.0f , 2.0f))) + - ( 256 * exp(-powf((float) i/64.0f - 4.0f , 2.0f))) + - ( 320 * exp(-powf((float) i/64.0f - 5.0f , 2.0f))) + - ( 384 * exp(-powf((float) i/64.0f - 6.0f , 2.0f)))) / 1.772637; - blah += 0.5; - } - else - { - blah = i; - } - - g = (unsigned char)(255.0 * pow(blah/255.0, gamma)); - //printf("%d : %d\n", i, g); - s = (g<<8) | g; - gp2x_memregs[0x295E>>1]= s; - gp2x_memregs[0x295E>>1]= g; - } - - gamma_was_changed = 1; -} - -static int gp2x_read_battery_(void) -{ - return -1; /* TODO? */ -} - -/* these are not quite MMSP2 related, - * more to GP2X F100/F200 consoles themselves. */ -typedef struct ucb1x00_ts_event -{ - unsigned short pressure; - unsigned short x; - unsigned short y; - unsigned short pad; - struct timeval stamp; -} UCB1X00_TS_EVENT; - -int gp2x_touchpad_read(int *x, int *y) -{ - UCB1X00_TS_EVENT event; - static int zero_seen = 0; - int retval; - - if (touchdev < 0) return -1; - - retval = read(touchdev, &event, sizeof(event)); - if (retval <= 0) { - perror("touch read failed"); - return -1; - } - // this is to ignore the messed-up 4.1.x driver - if (event.pressure == 0) zero_seen = 1; - - if (x) *x = (event.x * touchcal[0] + touchcal[2]) >> 16; - if (y) *y = (event.y * touchcal[4] + touchcal[5]) >> 16; - // printf("read %i %i %i\n", event.pressure, *x, *y); - - return zero_seen ? event.pressure : 0; -} - -static void proc_set(const char *path, const char *val) -{ - FILE *f; - char tmp[16]; - - f = fopen(path, "w"); - if (f == NULL) { - printf("failed to open: %s\n", path); - return; - } - - fprintf(f, "0\n"); - fclose(f); - - printf("\"%s\" is set to: ", path); - f = fopen(path, "r"); - if (f == NULL) { - printf("(open failed)\n"); - return; - } - - fgets(tmp, sizeof(tmp), f); - printf("%s", tmp); - fclose(f); -} - - -void mmsp2_init(void) -{ - int i; - - memdev = open("/dev/mem", O_RDWR); - if (memdev == -1) - { - perror("open(\"/dev/mem\")"); - exit(1); - } - - gp2x_memregs = mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); - if (gp2x_memregs == MAP_FAILED) - { - perror("mmap(memregs)"); - exit(1); - } - gp2x_memregl = (unsigned long *) gp2x_memregs; - - gp2x_memregs[0x2880>>1] &= ~0x383; // disable cursor, subpict, osd, video layers - - gp2x_screens[0] = mmap(0, FRAMEBUFF_WHOLESIZE, PROT_WRITE, MAP_SHARED, - memdev, gp2x_screenaddrs[0]); - if (gp2x_screens[0] == MAP_FAILED) - { - perror("mmap(g_screen_ptr)"); - exit(1); - } - printf("framebuffers:\n"); - printf(" %08x -> %p\n", gp2x_screenaddrs[0], gp2x_screens[0]); - for (i = 1; i < 4; i++) - { - gp2x_screens[i] = (char *) gp2x_screens[i - 1] + FRAMEBUFF_SIZE; - printf(" %08x -> %p\n", gp2x_screenaddrs[i], gp2x_screens[i]); - } - - g_screen_ptr = gp2x_screens[0]; - screensel = 0; - - gp2x_screenaddr_old[0] = gp2x_memregs[0x290E>>1]; - gp2x_screenaddr_old[1] = gp2x_memregs[0x2910>>1]; - gp2x_screenaddr_old[2] = gp2x_memregs[0x2912>>1]; - gp2x_screenaddr_old[3] = gp2x_memregs[0x2914>>1]; - - memcpy(gp2x_screenaddrs_use, gp2x_screenaddrs, sizeof(gp2x_screenaddrs)); - - /* save startup values: LCD refresh */ - get_reg_setting(lcd_rate_defaults); - - /* CPU and RAM timings */ - reg0910 = gp2x_memregs[0x0910>>1]; - memtimex_old[0] = gp2x_memregs[0x3802>>1]; - memtimex_old[1] = gp2x_memregs[0x3804>>1]; - - /* touchscreen */ - touchdev = open("/dev/touchscreen/wm97xx", O_RDONLY); - if (touchdev >= 0) { - FILE *pcf = fopen("/etc/pointercal", "r"); - if (pcf) { - fscanf(pcf, "%d %d %d %d %d %d %d", &touchcal[0], &touchcal[1], - &touchcal[2], &touchcal[3], &touchcal[4], &touchcal[5], &touchcal[6]); - fclose(pcf); - } - printf("found touchscreen/wm97xx\n"); - } - - /* disable Linux read-ahead */ - proc_set("/proc/sys/vm/max-readahead", "0\n"); - proc_set("/proc/sys/vm/min-readahead", "0\n"); - - /* code940 portion */ - sharedmem940_init(); - - gp2x_video_flip = gp2x_video_flip_; - gp2x_video_flip2 = gp2x_video_flip2_; - gp2x_video_changemode_ll = gp2x_video_changemode_ll_; - gp2x_video_setpalette = gp2x_video_setpalette_; - gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_; - gp2x_video_wait_vsync = gp2x_video_wait_vsync_; - - gp2x_set_cpuclk = gp2x_set_cpuclk_; - - set_lcd_custom_rate = set_lcd_custom_rate_; - unset_lcd_custom_rate = unset_lcd_custom_rate_; - set_lcd_gamma = set_lcd_gamma_; - - set_ram_timings = set_ram_timings_; - unset_ram_timings = unset_ram_timings_; - gp2x_read_battery = gp2x_read_battery_; - - gp2x_get_ticks_ms = plat_get_ticks_ms_good; - gp2x_get_ticks_us = plat_get_ticks_us_good; -} - -void mmsp2_finish(void) -{ - reset940(1, 3); - pause940(1); - sharedmem940_finish(); - - gp2x_video_RGB_setscaling_(0, 320, 240); - gp2x_video_changemode_ll_(16); - - gp2x_memregs[0x290E>>1] = gp2x_screenaddr_old[0]; - gp2x_memregs[0x2910>>1] = gp2x_screenaddr_old[1]; - gp2x_memregs[0x2912>>1] = gp2x_screenaddr_old[2]; - gp2x_memregs[0x2914>>1] = gp2x_screenaddr_old[3]; - - unset_lcd_custom_rate_(); - if (gamma_was_changed) - set_lcd_gamma_(100, 0); - unset_ram_timings_(); - if (cpuclk_was_changed) - gp2x_memregs[0x910>>1] = reg0910; - - munmap(gp2x_screens[0], FRAMEBUFF_WHOLESIZE); - munmap((void *)gp2x_memregs, 0x10000); - close(memdev); - if (touchdev >= 0) - close(touchdev); -} - diff --git a/platform/gp2x/soc_mmsp2.h b/platform/gp2x/soc_mmsp2.h deleted file mode 100644 index 493bf9f6..00000000 --- a/platform/gp2x/soc_mmsp2.h +++ /dev/null @@ -1,9 +0,0 @@ - -extern int memdev; -extern volatile unsigned short *gp2x_memregs; -extern volatile unsigned long *gp2x_memregl; - -/* 940 core */ -void pause940(int yes); -void reset940(int yes, int bank); - diff --git a/platform/gp2x/soc_pollux.c b/platform/gp2x/soc_pollux.c deleted file mode 100644 index dd7e66d1..00000000 --- a/platform/gp2x/soc_pollux.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * PicoDrive - * (C) notaz, 2009,2010 - * - * This work is licensed under the terms of MAME license. - * See COPYING file in the top-level directory. - */ -/* - * - * 00000000-029fffff linux (42MB) - * 02a00000-02dfffff fb (4MB, 153600B really used) - * 02e00000-02ffffff sound dma (2MB) - * 03000000-03ffffff MPEGDEC (?, 16MB) - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "soc.h" -#include "plat_gp2x.h" -#include "../common/emu.h" -#include "../common/plat.h" -#include "../common/arm_utils.h" -#include "pollux_set.h" - -static volatile unsigned short *memregs; -static volatile unsigned int *memregl; -static int memdev = -1; -static int battdev = -1; - -extern void *gp2x_screens[4]; - -#define fb_buf_count 4 -static unsigned int fb_paddr[fb_buf_count]; -static int fb_work_buf; -static int fbdev = -1; - -static char cpuclk_was_changed = 0; -static unsigned short memtimex_old[2]; -static unsigned int pllsetreg0_old; -static unsigned int timer_drift; // count per real second -static int last_pal_setting = 0; - - -/* misc */ -static void pollux_set_fromenv(const char *env_var) -{ - const char *set_string; - set_string = getenv(env_var); - if (set_string) - pollux_set(memregs, set_string); - else - printf("env var %s not defined.\n", env_var); -} - -/* video stuff */ -static void pollux_video_flip(int buf_count) -{ - memregl[0x406C>>2] = fb_paddr[fb_work_buf]; - memregl[0x4058>>2] |= 0x10; - fb_work_buf++; - if (fb_work_buf >= buf_count) - fb_work_buf = 0; - g_screen_ptr = gp2x_screens[fb_work_buf]; -} - -static void gp2x_video_flip_(void) -{ - pollux_video_flip(fb_buf_count); -} - -/* doulblebuffered flip */ -static void gp2x_video_flip2_(void) -{ - pollux_video_flip(2); -} - -static void gp2x_video_changemode_ll_(int bpp) -{ - static int prev_bpp = 0; - int code = 0, bytes = 2; - int rot_cmd[2] = { 0, 0 }; - unsigned int r; - char buff[32]; - int ret; - - if (bpp == prev_bpp) - return; - prev_bpp = bpp; - - printf("changemode: %dbpp rot=%d\n", abs(bpp), bpp < 0); - - /* negative bpp means rotated mode */ - rot_cmd[0] = (bpp < 0) ? 6 : 5; - ret = ioctl(fbdev, _IOW('D', 90, int[2]), rot_cmd); - if (ret < 0) - perror("rot ioctl failed"); - memregl[0x4004>>2] = (bpp < 0) ? 0x013f00ef : 0x00ef013f; - memregl[0x4000>>2] |= 1 << 3; - - /* the above ioctl resets LCD timings, so set them here */ - snprintf(buff, sizeof(buff), "POLLUX_LCD_TIMINGS_%s", last_pal_setting ? "PAL" : "NTSC"); - pollux_set_fromenv(buff); - - switch (abs(bpp)) - { - case 8: - code = 0x443a; - bytes = 1; - break; - - case 15: - case 16: - code = 0x4432; - bytes = 2; - break; - - default: - printf("unhandled bpp request: %d\n", abs(bpp)); - return; - } - - memregl[0x405c>>2] = bytes; - memregl[0x4060>>2] = bytes * (bpp < 0 ? 240 : 320); - - r = memregl[0x4058>>2]; - r = (r & 0xffff) | (code << 16) | 0x10; - memregl[0x4058>>2] = r; -} - -static void gp2x_video_setpalette_(int *pal, int len) -{ - /* pollux palette is 16bpp only.. */ - int i; - for (i = 0; i < len; i++) - { - int c = pal[i]; - c = ((c >> 8) & 0xf800) | ((c >> 5) & 0x07c0) | ((c >> 3) & 0x001f); - memregl[0x4070>>2] = (i << 24) | c; - } -} - -static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H) -{ - /* maybe a job for 3d hardware? */ -} - -static void gp2x_video_wait_vsync_(void) -{ - while (!(memregl[0x308c>>2] & (1 << 10))) - spend_cycles(128); - memregl[0x308c>>2] |= 1 << 10; -} - -/* CPU clock */ -static void gp2x_set_cpuclk_(unsigned int mhz) -{ - char buff[24]; - snprintf(buff, sizeof(buff), "cpuclk=%u", mhz); - pollux_set(memregs, buff); - - cpuclk_was_changed = 1; -} - -/* RAM timings */ -static void set_ram_timings_(void) -{ - pollux_set_fromenv("POLLUX_RAM_TIMINGS"); -} - -static void unset_ram_timings_(void) -{ - int i; - - memregs[0x14802>>1] = memtimex_old[0]; - memregs[0x14804>>1] = memtimex_old[1] | 0x8000; - - for (i = 0; i < 0x100000; i++) - if (!(memregs[0x14804>>1] & 0x8000)) - break; - - printf("RAM timings reset to startup values.\n"); -} - -/* LCD refresh */ -static void set_lcd_custom_rate_(int is_pal) -{ - /* just remember PAL/NTSC. We always set timings in _changemode_ll() */ - last_pal_setting = is_pal; -} - -static void unset_lcd_custom_rate_(void) -{ -} - -static void set_lcd_gamma_(int g100, int A_SNs_curve) -{ - /* hm, the LCD possibly can do it (but not POLLUX) */ -} - -static int gp2x_read_battery_(void) -{ - unsigned short magic_val = 0; - - if (battdev < 0) - return -1; - if (read(battdev, &magic_val, sizeof(magic_val)) != sizeof(magic_val)) - return -1; - switch (magic_val) { - default: - case 1: return 100; - case 2: return 66; - case 3: return 40; - case 4: return 0; - } -} - -#define TIMER_BASE3 0x1980 -#define TIMER_REG(x) memregl[(TIMER_BASE3 + x) >> 2] - -static unsigned int gp2x_get_ticks_us_(void) -{ - TIMER_REG(0x08) = 0x4b; /* run timer, latch value */ - return TIMER_REG(0); -} - -static unsigned int gp2x_get_ticks_ms_(void) -{ - /* approximate /= 1000 */ - unsigned long long v64; - v64 = (unsigned long long)gp2x_get_ticks_us_() * 4294968; - return v64 >> 32; -} - -static void timer_cleanup(void) -{ - TIMER_REG(0x40) = 0x0c; /* be sure clocks are on */ - TIMER_REG(0x08) = 0x23; /* stop the timer, clear irq in case it's pending */ - TIMER_REG(0x00) = 0; /* clear counter */ - TIMER_REG(0x40) = 0; /* clocks off */ - TIMER_REG(0x44) = 0; /* dividers back to default */ -} - -/* note: both PLLs are programmed the same way, - * the databook incorrectly states that PLL1 differs */ -static int decode_pll(unsigned int reg) -{ - long long v; - int p, m, s; - - p = (reg >> 18) & 0x3f; - m = (reg >> 8) & 0x3ff; - s = reg & 0xff; - - if (p == 0) - p = 1; - - v = 27000000; // master clock - v = v * m / (p << s); - return v; -} - -int pollux_get_real_snd_rate(int req_rate) -{ - int clk0_src, clk1_src, rate, div; - - clk0_src = (memregl[0xdbc4>>2] >> 1) & 7; - clk1_src = (memregl[0xdbc8>>2] >> 1) & 7; - if (clk0_src > 1 || clk1_src != 7) { - fprintf(stderr, "get_real_snd_rate: bad clk sources: %d %d\n", clk0_src, clk1_src); - return req_rate; - } - - rate = decode_pll(clk0_src ? memregl[0xf008>>2] : memregl[0xf004>>2]); - - // apply divisors - div = ((memregl[0xdbc4>>2] >> 4) & 0x3f) + 1; - rate /= div; - div = ((memregl[0xdbc8>>2] >> 4) & 0x3f) + 1; - rate /= div; - rate /= 64; - - //printf("rate %d\n", rate); - rate -= rate * timer_drift / 1000000; - printf("adjusted rate: %d\n", rate); - - if (rate < 8000-1000 || rate > 44100+1000) { - fprintf(stderr, "get_real_snd_rate: got bad rate: %d\n", rate); - return req_rate; - } - - return rate; -} - -void pollux_init(void) -{ - struct fb_fix_screeninfo fbfix; - int i, ret, rate, timer_div; - - memdev = open("/dev/mem", O_RDWR); - if (memdev == -1) { - perror("open(/dev/mem) failed"); - exit(1); - } - - memregs = mmap(0, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); - if (memregs == MAP_FAILED) { - perror("mmap(memregs) failed"); - exit(1); - } - memregl = (volatile void *)memregs; - - fbdev = open("/dev/fb0", O_RDWR); - if (fbdev < 0) { - perror("can't open fbdev"); - exit(1); - } - - ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix); - if (ret == -1) { - perror("ioctl(fbdev) failed"); - exit(1); - } - - printf("framebuffer: \"%s\" @ %08lx\n", fbfix.id, fbfix.smem_start); - fb_paddr[0] = fbfix.smem_start; - - gp2x_screens[0] = mmap(0, 320*240*2*fb_buf_count, PROT_READ|PROT_WRITE, - MAP_SHARED, memdev, fb_paddr[0]); - if (gp2x_screens[0] == MAP_FAILED) - { - perror("mmap(gp2x_screens) failed"); - exit(1); - } - memset(gp2x_screens[0], 0, 320*240*2*fb_buf_count); - - printf(" %p -> %08x\n", gp2x_screens[0], fb_paddr[0]); - for (i = 1; i < fb_buf_count; i++) - { - fb_paddr[i] = fb_paddr[i-1] + 320*240*2; - gp2x_screens[i] = (char *)gp2x_screens[i-1] + 320*240*2; - printf(" %p -> %08x\n", gp2x_screens[i], fb_paddr[i]); - } - fb_work_buf = 0; - g_screen_ptr = gp2x_screens[0]; - - battdev = open("/dev/pollux_batt", O_RDONLY); - if (battdev < 0) - perror("Warning: could't open pollux_batt"); - - /* find what PLL1 runs at, for the timer */ - rate = decode_pll(memregl[0xf008>>2]); - printf("PLL1 @ %dHz\n", rate); - - /* setup timer */ - timer_div = (rate + 500000) / 1000000; - if (1 <= timer_div && timer_div <= 256) { - timer_drift = (rate - (timer_div * 1000000)) / timer_div; - - if (TIMER_REG(0x08) & 8) { - fprintf(stderr, "warning: timer in use, overriding!\n"); - timer_cleanup(); - } - - TIMER_REG(0x44) = ((timer_div - 1) << 4) | 2; /* using PLL1, divide by it's rate */ - TIMER_REG(0x40) = 0x0c; /* clocks on */ - TIMER_REG(0x08) = 0x6b; /* run timer, clear irq, latch value */ - - gp2x_get_ticks_ms = gp2x_get_ticks_ms_; - gp2x_get_ticks_us = gp2x_get_ticks_us_; - } - else { - fprintf(stderr, "warning: could not make use of timer\n"); - - // those functions are actually not good at all on Wiz kernel - gp2x_get_ticks_ms = plat_get_ticks_ms_good; - gp2x_get_ticks_us = plat_get_ticks_us_good; - } - - pllsetreg0_old = memregl[0xf004>>2]; - memtimex_old[0] = memregs[0x14802>>1]; - memtimex_old[1] = memregs[0x14804>>1]; - - gp2x_video_flip = gp2x_video_flip_; - gp2x_video_flip2 = gp2x_video_flip2_; - gp2x_video_changemode_ll = gp2x_video_changemode_ll_; - gp2x_video_setpalette = gp2x_video_setpalette_; - gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_; - gp2x_video_wait_vsync = gp2x_video_wait_vsync_; - - /* some firmwares have sys clk on PLL0, we can't adjust CPU clock - * by reprogramming the PLL0 then, as it overclocks system bus */ - if ((memregl[0xf000>>2] & 0x03000030) == 0x01000000) - gp2x_set_cpuclk = gp2x_set_cpuclk_; - else { - fprintf(stderr, "unexpected PLL config (%08x), overclocking disabled\n", - memregl[0xf000>>2]); - gp2x_set_cpuclk = NULL; - } - - set_lcd_custom_rate = set_lcd_custom_rate_; - unset_lcd_custom_rate = unset_lcd_custom_rate_; - set_lcd_gamma = set_lcd_gamma_; - - set_ram_timings = set_ram_timings_; - unset_ram_timings = unset_ram_timings_; - gp2x_read_battery = gp2x_read_battery_; -} - -void pollux_finish(void) -{ - /* switch to default fb mem, turn portrait off */ - memregl[0x406C>>2] = fb_paddr[0]; - memregl[0x4058>>2] |= 0x10; - close(fbdev); - - gp2x_video_changemode_ll_(16); - unset_ram_timings_(); - if (cpuclk_was_changed) { - memregl[0xf004>>2] = pllsetreg0_old; - memregl[0xf07c>>2] |= 0x8000; - } - timer_cleanup(); - - munmap((void *)memregs, 0x20000); - close(memdev); - if (battdev >= 0) - close(battdev); -} - diff --git a/platform/gp2x/soc_pollux.h b/platform/gp2x/soc_pollux.h deleted file mode 100644 index f26e594b..00000000 --- a/platform/gp2x/soc_pollux.h +++ /dev/null @@ -1,2 +0,0 @@ - -int pollux_get_real_snd_rate(int req_rate); diff --git a/platform/gp2x/vid_mmsp2.c b/platform/gp2x/vid_mmsp2.c new file mode 100644 index 00000000..ea294867 --- /dev/null +++ b/platform/gp2x/vid_mmsp2.c @@ -0,0 +1,174 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2006-2009,2013 + * + * This work is licensed under the terms of any of these licenses + * (at your option): + * - GNU GPL, version 2 or later. + * - GNU LGPL, version 2.1 or later. + * - MAME license. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include +#include +#include + +#include "../libpicofe/gp2x/plat_gp2x.h" +#include "../libpicofe/gp2x/soc.h" +#include "../common/arm_utils.h" +#include "../common/emu.h" +#include "plat.h" + +#define FRAMEBUFF_SIZE 0x30000 +#define FRAMEBUFF_WHOLESIZE (FRAMEBUFF_SIZE*4) // 320*240*2 + some more +#define FRAMEBUFF_ADDR0 (0x4000000 - FRAMEBUFF_WHOLESIZE) +#define FRAMEBUFF_ADDR1 (FRAMEBUFF_ADDR0 + FRAMEBUFF_SIZE) +#define FRAMEBUFF_ADDR2 (FRAMEBUFF_ADDR1 + FRAMEBUFF_SIZE) +#define FRAMEBUFF_ADDR3 (FRAMEBUFF_ADDR2 + FRAMEBUFF_SIZE) + +static const int gp2x_screenaddrs[4] = { FRAMEBUFF_ADDR0, FRAMEBUFF_ADDR1, FRAMEBUFF_ADDR2, FRAMEBUFF_ADDR3 }; +static int gp2x_screenaddrs_use[4]; + +static unsigned short gp2x_screenaddr_old[4]; +static int screensel; + +static void gp2x_video_flip_(void) +{ + unsigned short lsw = (unsigned short) gp2x_screenaddrs_use[screensel&3]; + unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&3] >> 16); + + memregs[0x2910>>1] = msw; + memregs[0x2914>>1] = msw; + memregs[0x290E>>1] = lsw; + memregs[0x2912>>1] = lsw; + + // jump to other buffer: + g_screen_ptr = gp2x_screens[++screensel&3]; +} + +/* doulblebuffered flip */ +static void gp2x_video_flip2_(void) +{ + unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&1] >> 16); + + memregs[0x2910>>1] = msw; + memregs[0x2914>>1] = msw; + memregs[0x290E>>1] = 0; + memregs[0x2912>>1] = 0; + + // jump to other buffer: + g_screen_ptr = gp2x_screens[++screensel&1]; +} + +static void gp2x_video_changemode_ll_(int bpp) +{ +printf("changemode %d\n", bpp); + memregs[0x28DA>>1] = (((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/ + memregs[0x290C>>1] = 320*((bpp+1)/8); /*line width in bytes*/ +} + +static void gp2x_video_setpalette_(int *pal, int len) +{ + unsigned short *g = (unsigned short *)pal; + volatile unsigned short *memreg = &memregs[0x295A>>1]; + + memregs[0x2958>>1] = 0; + + len *= 2; + while (len--) + *memreg = *g++; +} + +static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H) +{ + float escalaw, escalah; + int bpp = (memregs[0x28DA>>1]>>9)&0x3; + unsigned short scalw; + + // set offset + gp2x_screenaddrs_use[0] = gp2x_screenaddrs[0] + ln_offs * 320 * bpp; + gp2x_screenaddrs_use[1] = gp2x_screenaddrs[1] + ln_offs * 320 * bpp; + gp2x_screenaddrs_use[2] = gp2x_screenaddrs[2] + ln_offs * 320 * bpp; + gp2x_screenaddrs_use[3] = gp2x_screenaddrs[3] + ln_offs * 320 * bpp; + + escalaw = 1024.0; // RGB Horiz LCD + escalah = 320.0; // RGB Vert LCD + + if (memregs[0x2800>>1]&0x100) //TV-Out + { + escalaw=489.0; // RGB Horiz TV (PAL, NTSC) + if (memregs[0x2818>>1] == 287) //PAL + escalah=274.0; // RGB Vert TV PAL + else if (memregs[0x2818>>1] == 239) //NTSC + escalah=331.0; // RGB Vert TV NTSC + } + + // scale horizontal + scalw = (unsigned short)((float)escalaw *(W/320.0)); + /* if there is no horizontal scaling, vertical doesn't work. + * Here is a nasty wrokaround... */ + if (H != 240 && W == 320) scalw--; + memregs[0x2906>>1]=scalw; + // scale vertical + memregl[0x2908>>2]=(unsigned long)((float)escalah *bpp *(H/240.0)); +} + +static void gp2x_video_wait_vsync_(void) +{ + unsigned short v = memregs[0x1182>>1]; + while (!((v ^ memregs[0x1182>>1]) & 0x10)) + spend_cycles(1024); +} + + +void vid_mmsp2_init(void) +{ + int i; + + gp2x_screens[0] = mmap(0, FRAMEBUFF_WHOLESIZE, PROT_WRITE, MAP_SHARED, + memdev, gp2x_screenaddrs[0]); + if (gp2x_screens[0] == MAP_FAILED) + { + perror("mmap(g_screen_ptr)"); + exit(1); + } + printf("framebuffers:\n"); + printf(" %08x -> %p\n", gp2x_screenaddrs[0], gp2x_screens[0]); + for (i = 1; i < 4; i++) + { + gp2x_screens[i] = (char *) gp2x_screens[i - 1] + FRAMEBUFF_SIZE; + printf(" %08x -> %p\n", gp2x_screenaddrs[i], gp2x_screens[i]); + } + + g_screen_ptr = gp2x_screens[0]; + screensel = 0; + + gp2x_screenaddr_old[0] = memregs[0x290E>>1]; + gp2x_screenaddr_old[1] = memregs[0x2910>>1]; + gp2x_screenaddr_old[2] = memregs[0x2912>>1]; + gp2x_screenaddr_old[3] = memregs[0x2914>>1]; + + memcpy(gp2x_screenaddrs_use, gp2x_screenaddrs, sizeof(gp2x_screenaddrs)); + + gp2x_video_flip = gp2x_video_flip_; + gp2x_video_flip2 = gp2x_video_flip2_; + gp2x_video_changemode_ll = gp2x_video_changemode_ll_; + gp2x_video_setpalette = gp2x_video_setpalette_; + gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_; + gp2x_video_wait_vsync = gp2x_video_wait_vsync_; +} + +void vid_mmsp2_finish(void) +{ + gp2x_video_RGB_setscaling_(0, 320, 240); + gp2x_video_changemode_ll_(16); + + memregs[0x290E>>1] = gp2x_screenaddr_old[0]; + memregs[0x2910>>1] = gp2x_screenaddr_old[1]; + memregs[0x2912>>1] = gp2x_screenaddr_old[2]; + memregs[0x2914>>1] = gp2x_screenaddr_old[3]; + + munmap(gp2x_screens[0], FRAMEBUFF_WHOLESIZE); +} diff --git a/platform/gp2x/vid_pollux.c b/platform/gp2x/vid_pollux.c new file mode 100644 index 00000000..308eb001 --- /dev/null +++ b/platform/gp2x/vid_pollux.c @@ -0,0 +1,232 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2009,2013 + * + * This work is licensed under the terms of any of these licenses + * (at your option): + * - GNU GPL, version 2 or later. + * - GNU LGPL, version 2.1 or later. + * - MAME license. + * See the COPYING file in the top-level directory. + * + * + * 00000000-029fffff linux (42MB) + * 02a00000-02dfffff fb (4MB, 153600B really used) + * 02e00000-02ffffff sound dma (2MB) + * 03000000-03ffffff MPEGDEC (?, 16MB) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libpicofe/gp2x/soc.h" +#include "../libpicofe/gp2x/plat_gp2x.h" +#include "../libpicofe/gp2x/pollux_set.h" +#include "../common/emu.h" +#include "../common/arm_utils.h" +#include "plat.h" + +#define fb_buf_count 4 +static unsigned int fb_paddr[fb_buf_count]; +static int fb_work_buf; +static int fbdev = -1; + +static unsigned short memtimex_old[2]; +static int last_pal_setting = 0; + + +/* misc */ +static void pollux_set_fromenv(const char *env_var) +{ + const char *set_string; + set_string = getenv(env_var); + if (set_string) + pollux_set(memregs, set_string); + else + printf("env var %s not defined.\n", env_var); +} + +/* video stuff */ +static void pollux_video_flip(int buf_count) +{ + memregl[0x406C>>2] = fb_paddr[fb_work_buf]; + memregl[0x4058>>2] |= 0x10; + fb_work_buf++; + if (fb_work_buf >= buf_count) + fb_work_buf = 0; + g_screen_ptr = gp2x_screens[fb_work_buf]; +} + +static void gp2x_video_flip_(void) +{ + pollux_video_flip(fb_buf_count); +} + +/* doulblebuffered flip */ +static void gp2x_video_flip2_(void) +{ + pollux_video_flip(2); +} + +static void gp2x_video_changemode_ll_(int bpp) +{ + static int prev_bpp = 0; + int code = 0, bytes = 2; + int rot_cmd[2] = { 0, 0 }; + unsigned int r; + char buff[32]; + int ret; + + if (bpp == prev_bpp) + return; + prev_bpp = bpp; + + printf("changemode: %dbpp rot=%d\n", abs(bpp), bpp < 0); + + /* negative bpp means rotated mode */ + rot_cmd[0] = (bpp < 0) ? 6 : 5; + ret = ioctl(fbdev, _IOW('D', 90, int[2]), rot_cmd); + if (ret < 0) + perror("rot ioctl failed"); + memregl[0x4004>>2] = (bpp < 0) ? 0x013f00ef : 0x00ef013f; + memregl[0x4000>>2] |= 1 << 3; + + /* the above ioctl resets LCD timings, so set them here */ + snprintf(buff, sizeof(buff), "POLLUX_LCD_TIMINGS_%s", last_pal_setting ? "PAL" : "NTSC"); + pollux_set_fromenv(buff); + + switch (abs(bpp)) + { + case 8: + code = 0x443a; + bytes = 1; + break; + + case 15: + case 16: + code = 0x4432; + bytes = 2; + break; + + default: + printf("unhandled bpp request: %d\n", abs(bpp)); + return; + } + + memregl[0x405c>>2] = bytes; + memregl[0x4060>>2] = bytes * (bpp < 0 ? 240 : 320); + + r = memregl[0x4058>>2]; + r = (r & 0xffff) | (code << 16) | 0x10; + memregl[0x4058>>2] = r; +} + +static void gp2x_video_setpalette_(int *pal, int len) +{ + /* pollux palette is 16bpp only.. */ + int i; + for (i = 0; i < len; i++) + { + int c = pal[i]; + c = ((c >> 8) & 0xf800) | ((c >> 5) & 0x07c0) | ((c >> 3) & 0x001f); + memregl[0x4070>>2] = (i << 24) | c; + } +} + +static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H) +{ + /* maybe a job for 3d hardware? */ +} + +static void gp2x_video_wait_vsync_(void) +{ + while (!(memregl[0x308c>>2] & (1 << 10))) + spend_cycles(128); + memregl[0x308c>>2] |= 1 << 10; +} + +/* RAM timings */ +static void set_ram_timings_(void) +{ + pollux_set_fromenv("POLLUX_RAM_TIMINGS"); +} + +static void unset_ram_timings_(void) +{ + int i; + + memregs[0x14802>>1] = memtimex_old[0]; + memregs[0x14804>>1] = memtimex_old[1] | 0x8000; + + for (i = 0; i < 0x100000; i++) + if (!(memregs[0x14804>>1] & 0x8000)) + break; + + printf("RAM timings reset to startup values.\n"); +} + +void vid_pollux_init(void) +{ + struct fb_fix_screeninfo fbfix; + int i, ret; + + fbdev = open("/dev/fb0", O_RDWR); + if (fbdev < 0) { + perror("can't open fbdev"); + exit(1); + } + + ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix); + if (ret == -1) { + perror("ioctl(fbdev) failed"); + exit(1); + } + + printf("framebuffer: \"%s\" @ %08lx\n", fbfix.id, fbfix.smem_start); + fb_paddr[0] = fbfix.smem_start; + + gp2x_screens[0] = mmap(0, 320*240*2*fb_buf_count, PROT_READ|PROT_WRITE, + MAP_SHARED, memdev, fb_paddr[0]); + if (gp2x_screens[0] == MAP_FAILED) + { + perror("mmap(gp2x_screens) failed"); + exit(1); + } + memset(gp2x_screens[0], 0, 320*240*2*fb_buf_count); + + printf(" %p -> %08x\n", gp2x_screens[0], fb_paddr[0]); + for (i = 1; i < fb_buf_count; i++) + { + fb_paddr[i] = fb_paddr[i-1] + 320*240*2; + gp2x_screens[i] = (char *)gp2x_screens[i-1] + 320*240*2; + printf(" %p -> %08x\n", gp2x_screens[i], fb_paddr[i]); + } + fb_work_buf = 0; + g_screen_ptr = gp2x_screens[0]; + + set_ram_timings_(); + + gp2x_video_flip = gp2x_video_flip_; + gp2x_video_flip2 = gp2x_video_flip2_; + gp2x_video_changemode_ll = gp2x_video_changemode_ll_; + gp2x_video_setpalette = gp2x_video_setpalette_; + gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_; + gp2x_video_wait_vsync = gp2x_video_wait_vsync_; +} + +void vid_pollux_finish(void) +{ + munmap(gp2x_screens[0], 320*240*2 * fb_buf_count); + close(fbdev); + fbdev = -1; + + unset_ram_timings_(); +} diff --git a/platform/libpicofe b/platform/libpicofe index c54d04fd..7ceadd99 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit c54d04fd84f59c60c6ecdbd2502fbda5de735b4b +Subproject commit 7ceadd9993ea84078e9d74d79215419e06496f90 diff --git a/platform/pandora/menu.c b/platform/pandora/menu.c index f591ec14..9f451feb 100644 --- a/platform/pandora/menu.c +++ b/platform/pandora/menu.c @@ -67,11 +67,7 @@ static int menu_loop_cscaler(int id, int keys) mee_range_hide("layer_w", MA_OPT3_LAYER_W, g_layer_cw, 160, 800), \ mee_range_hide("layer_h", MA_OPT3_LAYER_H, g_layer_ch, 60, 480), \ -#define MENU_OPTIONS_ADV \ - mee_onoff ("SVP dynarec", MA_OPT2_SVP_DYNAREC, PicoOpt, POPT_EN_SVP_DRC), \ - mee_onoff ("Status line in main menu", MA_OPT2_STATUS_LINE, currentConfig.EmuOpt, EOPT_SHOW_RTC), - -#define menu_main_plat_draw NULL +#define MENU_OPTIONS_ADV static menu_entry e_menu_gfx_options[]; static menu_entry e_menu_options[]; @@ -79,11 +75,6 @@ static menu_entry e_menu_keyconfig[]; void pnd_menu_init(void) { - int i; - - i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS); - e_menu_options[i].name = "Max CPU clock"; - me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0); } From ae214f1c37e5b02b6413040649a40f8ba3874e1b Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 26 Aug 2013 00:32:31 +0300 Subject: [PATCH 28/41] new timing for main and cd --- pico/32x/32x.c | 64 +++++----- pico/32x/memory.c | 20 +-- pico/32x/pwm.c | 8 +- pico/32x/sh2soc.c | 2 +- pico/cd/LC89510.c | 19 ++- pico/cd/gfx_cd.c | 172 ++++++++------------------ pico/cd/gfx_cd.h | 2 - pico/cd/memory.c | 40 ++++-- pico/cd/pico.c | 302 +++++++++++++++++++++++++++++----------------- pico/cd/sek.c | 4 +- pico/debug.c | 2 +- pico/eeprom.c | 10 +- pico/memory.c | 24 ++-- pico/pico.c | 16 +-- pico/pico_cmn.c | 102 +++++++--------- pico/pico_int.h | 139 ++++++++++----------- pico/sek.c | 13 +- pico/state.c | 36 ++++-- pico/videoport.c | 6 +- 19 files changed, 507 insertions(+), 474 deletions(-) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index ab522e41..54250f18 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -166,7 +166,7 @@ void p32x_reset_sh2s(void) // program will set S_OK } - msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDoneT(); + msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDone(); } void Pico32xInit(void) @@ -200,8 +200,8 @@ void PicoUnload32x(void) void PicoReset32x(void) { if (PicoAHW & PAHW_32X) { - msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDoneT(); - p32x_trigger_irq(NULL, SekCyclesDoneT2(), P32XI_VRES); + msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDone(); + p32x_trigger_irq(NULL, SekCyclesDone(), P32XI_VRES); p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, 0); p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, 0); p32x_pwm_ctl_changed(); @@ -248,7 +248,7 @@ static void p32x_start_blank(void) Pico32xSwapDRAM(Pico32x.pending_fb ^ 1); } - p32x_trigger_irq(NULL, SekCyclesDoneT2(), P32XI_VINT); + p32x_trigger_irq(NULL, SekCyclesDone(), P32XI_VINT); p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, 0); p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0); } @@ -272,14 +272,6 @@ void p32x_schedule_hint(SH2 *sh2, int m68k_cycles) p32x_event_schedule(m68k_cycles, P32X_EVENT_HINT, after); } -// compare cycles, handling overflows -// check if a > b -#define CYCLES_GT(a, b) \ - ((int)((a) - (b)) > 0) -// check if a >= b -#define CYCLES_GE(a, b) \ - ((int)((a) - (b)) >= 0) - /* events */ static void fillend_event(unsigned int now) { @@ -296,9 +288,10 @@ static void hint_event(unsigned int now) typedef void (event_cb)(unsigned int now); -unsigned int event_times[P32X_EVENT_COUNT]; +/* times are in m68k (7.6MHz) cycles */ +unsigned int p32x_event_times[P32X_EVENT_COUNT]; static unsigned int event_time_next; -static event_cb *event_cbs[] = { +static event_cb *p32x_event_cbs[P32X_EVENT_COUNT] = { [P32X_EVENT_PWM] = p32x_pwm_irq_event, [P32X_EVENT_FILLEND] = fillend_event, [P32X_EVENT_HINT] = hint_event, @@ -311,8 +304,8 @@ void p32x_event_schedule(unsigned int now, enum p32x_event event, int after) when = (now + after) | 1; - elprintf(EL_32X, "new event #%u %u->%u", event, now, when); - event_times[event] = when; + elprintf(EL_32X, "32x: new event #%u %u->%u", event, now, when); + p32x_event_times[event] = when; if (event_time_next == 0 || CYCLES_GT(event_time_next, when)) event_time_next = when; @@ -329,7 +322,7 @@ void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after) sh2_end_run(sh2, left_to_next); } -static void run_events(unsigned int until) +static void p32x_run_events(unsigned int until) { int oldest, oldest_diff, time; int i, diff; @@ -338,8 +331,8 @@ static void run_events(unsigned int until) oldest = -1, oldest_diff = 0x7fffffff; for (i = 0; i < P32X_EVENT_COUNT; i++) { - if (event_times[i]) { - diff = event_times[i] - until; + if (p32x_event_times[i]) { + diff = p32x_event_times[i] - until; if (diff < oldest_diff) { oldest_diff = diff; oldest = i; @@ -348,13 +341,13 @@ static void run_events(unsigned int until) } if (oldest_diff <= 0) { - time = event_times[oldest]; - event_times[oldest] = 0; - elprintf(EL_32X, "run event #%d %u", oldest, time); - event_cbs[oldest](time); + time = p32x_event_times[oldest]; + p32x_event_times[oldest] = 0; + elprintf(EL_32X, "32x: run event #%d %u", oldest, time); + p32x_event_cbs[oldest](time); } else if (oldest_diff < 0x7fffffff) { - event_time_next = event_times[oldest]; + event_time_next = p32x_event_times[oldest]; break; } else { @@ -364,7 +357,8 @@ static void run_events(unsigned int until) } if (oldest != -1) - elprintf(EL_32X, "next event #%d at %u", oldest, event_time_next); + elprintf(EL_32X, "32x: next event #%d at %u", + oldest, event_time_next); } static inline void run_sh2(SH2 *sh2, int m68k_cycles) @@ -447,7 +441,7 @@ void sync_sh2s_normal(unsigned int m68k_target) while (CYCLES_GT(m68k_target, now)) { if (event_time_next && CYCLES_GE(now, event_time_next)) - run_events(now); + p32x_run_events(now); target = m68k_target; if (event_time_next && CYCLES_GT(target, event_time_next)) @@ -521,12 +515,13 @@ void sync_sh2s_lockstep(unsigned int m68k_target) } } -#define CPUS_RUN(m68k_cycles,s68k_cycles) do { \ +#define CPUS_RUN(m68k_cycles) do { \ SekRunM68k(m68k_cycles); \ - if (Pico32x.emu_flags & P32XF_Z80_32X_IO) \ - PicoSyncZ80(SekCycleCnt); \ + if ((Pico32x.emu_flags & P32XF_Z80_32X_IO) && Pico.m.z80Run \ + && !Pico.m.z80_reset && (PicoOpt & POPT_EN_Z80)) \ + PicoSyncZ80(SekCyclesDone()); \ if (Pico32x.emu_flags & (P32XF_68KCPOLL|P32XF_68KVPOLL)) \ - p32x_sync_sh2s(SekCyclesDoneT2()); \ + p32x_sync_sh2s(SekCyclesDone()); \ } while (0) #define PICO_32X @@ -541,7 +536,7 @@ void PicoFrame32x(void) Pico32x.vdp_regs[0x0a/2] &= ~P32XV_PEN; // no palette access if (!(Pico32x.sh2_regs[0] & 0x80)) - p32x_schedule_hint(NULL, SekCyclesDoneT2()); + p32x_schedule_hint(NULL, SekCyclesDone()); p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, 0); p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0); @@ -576,11 +571,10 @@ void Pico32xStateLoaded(int is_early) return; } - SekCycleCnt = 0; - sh2s[0].m68krcycles_done = sh2s[1].m68krcycles_done = SekCycleCntT; - p32x_update_irls(NULL, SekCycleCntT); + sh2s[0].m68krcycles_done = sh2s[1].m68krcycles_done = SekCyclesDone(); + p32x_update_irls(NULL, SekCyclesDone()); p32x_pwm_state_loaded(); - run_events(SekCycleCntT); + p32x_run_events(SekCyclesDone()); } // vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 5be4da45..fd902dd2 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -187,7 +187,7 @@ static u32 p32x_reg_read16(u32 a) #else if ((a & 0x30) == 0x20) { static u32 dr2 = 0; - unsigned int cycles = SekCyclesDoneT(); + unsigned int cycles = SekCyclesDone(); int comreg = 1 << (a & 0x0f) / 2; // evil X-Men proto polls in a dbra loop and expects it to expire.. @@ -211,14 +211,14 @@ static u32 p32x_reg_read16(u32 a) #endif if (a == 2) { // INTM, INTS - unsigned int cycles = SekCyclesDoneT(); + unsigned int cycles = SekCyclesDone(); if (cycles - msh2.m68krcycles_done > 64) p32x_sync_sh2s(cycles); goto out; } if ((a & 0x30) == 0x30) - return p32x_pwm_read16(a, NULL, SekCyclesDoneT()); + return p32x_pwm_read16(a, NULL, SekCyclesDone()); out: return Pico32x.regs[a / 2]; @@ -241,7 +241,7 @@ static void dreq0_write(u16 *r, u32 d) r[6 / 2] &= ~P32XS_68S; if ((Pico32x.dmac0_fifo_ptr & 3) == 0) { - p32x_sync_sh2s(SekCyclesDoneT()); + p32x_sync_sh2s(SekCyclesDone()); p32x_dreq0_trigger(); } } @@ -272,7 +272,7 @@ static void p32x_reg_write8(u32 a, u32 d) return; case 0x03: // irq ctl if ((d ^ r[0x02 / 2]) & 3) { - int cycles = SekCyclesDoneT(); + int cycles = SekCyclesDone(); p32x_sync_sh2s(cycles); r[0x02 / 2] = d & 3; p32x_update_cmd_irq(NULL, cycles); @@ -383,12 +383,12 @@ static void p32x_reg_write8(u32 a, u32 d) case 0x3f: return; pwm_write: - p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDoneT()); + p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDone()); return; } if ((a & 0x30) == 0x20) { - int cycles = SekCyclesDoneT(); + int cycles = SekCyclesDone(); int comreg; if (REG8IN16(r, a) == d) @@ -448,13 +448,13 @@ static void p32x_reg_write16(u32 a, u32 d) case 0x30: // PWM control d = (r[a / 2] & ~0x0f) | (d & 0x0f); r[a / 2] = d; - p32x_pwm_write16(a, d, NULL, SekCyclesDoneT()); + p32x_pwm_write16(a, d, NULL, SekCyclesDone()); return; } // comm port if ((a & 0x30) == 0x20) { - int cycles = SekCyclesDoneT(); + int cycles = SekCyclesDone(); int comreg; if (r[a / 2] == d) @@ -475,7 +475,7 @@ static void p32x_reg_write16(u32 a, u32 d) } // PWM else if ((a & 0x30) == 0x30) { - p32x_pwm_write16(a, d, NULL, SekCyclesDoneT()); + p32x_pwm_write16(a, d, NULL, SekCyclesDone()); return; } diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 6f9cd07e..1aba914f 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -247,7 +247,7 @@ void p32x_pwm_update(int *buf32, int length, int stereo) int p = 0; int xmd; - consume_fifo(NULL, SekCyclesDoneT2()); + consume_fifo(NULL, SekCyclesDone()); xmd = Pico32x.regs[0x30 / 2] & 0x0f; if (xmd == 0 || xmd == 0x06 || xmd == 0x09 || xmd == 0x0f) @@ -326,11 +326,11 @@ void p32x_pwm_state_loaded(void) p32x_pwm_ctl_changed(); // for old savestates - cycles_diff_sh2 = SekCycleCntT * 3 - Pico32x.pwm_cycle_p; + cycles_diff_sh2 = SekCycleCnt * 3 - Pico32x.pwm_cycle_p; if (cycles_diff_sh2 >= pwm_cycles || cycles_diff_sh2 < 0) { Pico32x.pwm_irq_cnt = pwm_irq_reload; - Pico32x.pwm_cycle_p = SekCycleCntT * 3; - p32x_pwm_schedule(SekCycleCntT); + Pico32x.pwm_cycle_p = SekCycleCnt * 3; + p32x_pwm_schedule(SekCycleCnt); } } diff --git a/pico/32x/sh2soc.c b/pico/32x/sh2soc.c index daa48da2..04d33748 100644 --- a/pico/32x/sh2soc.c +++ b/pico/32x/sh2soc.c @@ -73,7 +73,7 @@ static void dmac_transfer_complete(SH2 *sh2, struct dma_chan *chan) { chan->chcr |= DMA_TE; // DMA has ended normally - p32x_sh2_poll_event(sh2, SH2_STATE_SLEEP, SekCyclesDoneT()); + p32x_sh2_poll_event(sh2, SH2_STATE_SLEEP, SekCyclesDone()); if (chan->chcr & DMA_IE) dmac_te_irq(sh2, chan); } diff --git a/pico/cd/LC89510.c b/pico/cd/LC89510.c index 8a42ee5a..74894760 100644 --- a/pico/cd/LC89510.c +++ b/pico/cd/LC89510.c @@ -68,7 +68,7 @@ PICO_INTERNAL void Update_CDC_TRansfer(int which) unsigned short *dest; unsigned char *src; - if (Pico_mcd->cdc.DBC.N <= (CDC_DMA_SPEED * 2)) + if (1) //Pico_mcd->cdc.DBC.N <= (CDC_DMA_SPEED * 2)) { length = (Pico_mcd->cdc.DBC.N + 1) >> 1; Pico_mcd->scd.Status_CDC &= ~0x08; // Last transfer @@ -80,7 +80,7 @@ PICO_INTERNAL void Update_CDC_TRansfer(int which) { Pico_mcd->cdc.IFSTAT &= ~0x40; - if (Pico_mcd->s68k_regs[0x33] & (1<<5)) + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN5) { elprintf(EL_INTS, "cdc DTE irq 5"); SekInterruptS68k(5); @@ -430,6 +430,19 @@ PICO_INTERNAL void CDC_Write_Reg(unsigned char Data) cdprintf("************** Starting Data Transfer ***********"); cdprintf("RS0 = %.4X DAC = %.4X DBC = %.4X DMA adr = %.4X\n\n", Pico_mcd->s68k_regs[4]<<8, Pico_mcd->cdc.DAC.N, Pico_mcd->cdc.DBC.N, (Pico_mcd->s68k_regs[0xA]<<8) | Pico_mcd->s68k_regs[0xB]); + + // tmp + { + int ddx = Pico_mcd->s68k_regs[4] & 7; + if (ddx < 2) break; // invalid + if (ddx < 4) { + Pico_mcd->s68k_regs[4] |= 0x40; // Data set ready in host port + break; + } + if (ddx == 6) break; // invalid + + pcd_event_schedule_s68k(PCD_EVENT_DMA, Pico_mcd->cdc.DBC.N / 2); + } } break; @@ -504,7 +517,7 @@ PICO_INTERNAL void CDD_Export_Status(void) Pico_mcd->s68k_regs[0x37] &= 3; // CDD.Control - if (Pico_mcd->s68k_regs[0x33] & (1<<4)) + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) { elprintf(EL_INTS, "cdd export irq 4"); SekInterruptS68k(4); diff --git a/pico/cd/gfx_cd.c b/pico/cd/gfx_cd.c index 0623a27e..96d44f20 100644 --- a/pico/cd/gfx_cd.c +++ b/pico/cd/gfx_cd.c @@ -12,33 +12,21 @@ #define _rot_comp Pico_mcd->rot_comp -static const int Table_Rot_Time[] = -{ - 0x00054000, 0x00048000, 0x00040000, 0x00036000, //; 008-032 ; briefing - sprite - 0x0002E000, 0x00028000, 0x00024000, 0x00022000, //; 036-064 ; arbre souvent - 0x00021000, 0x00020000, 0x0001E000, 0x0001B800, //; 068-096 ; map thunderstrike - 0x00019800, 0x00017A00, 0x00015C00, 0x00013E00, //; 100-128 ; logo défoncé - - 0x00012000, 0x00011800, 0x00011000, 0x00010800, //; 132-160 ; briefing - map - 0x00010000, 0x0000F800, 0x0000F000, 0x0000E800, //; 164-192 - 0x0000E000, 0x0000D800, 0x0000D000, 0x0000C800, //; 196-224 - 0x0000C000, 0x0000B800, 0x0000B000, 0x0000A800, //; 228-256 ; batman visage - - 0x0000A000, 0x00009F00, 0x00009E00, 0x00009D00, //; 260-288 - 0x00009C00, 0x00009B00, 0x00009A00, 0x00009900, //; 292-320 - 0x00009800, 0x00009700, 0x00009600, 0x00009500, //; 324-352 - 0x00009400, 0x00009300, 0x00009200, 0x00009100, //; 356-384 - - 0x00009000, 0x00008F00, 0x00008E00, 0x00008D00, //; 388-416 - 0x00008C00, 0x00008B00, 0x00008A00, 0x00008900, //; 420-448 - 0x00008800, 0x00008700, 0x00008600, 0x00008500, //; 452-476 - 0x00008400, 0x00008300, 0x00008200, 0x00008100, //; 480-512 -}; - +static void gfx_do_line(unsigned int func, unsigned short *stamp_base, + unsigned int H_Dot); static void gfx_cd_start(void) { - int upd_len; + int w, h; + + w = _rot_comp.Reg_62; + h = _rot_comp.Reg_64; + if (w == 0 || h == 0) { + elprintf(EL_CD|EL_ANOMALY, "gfx_cd_start with %ux%u", w, h); + _rot_comp.Reg_64 = 0; + // irq? + return; + } // _rot_comp.XD_Mul = ((_rot_comp.Reg_5C & 0x1f) + 1) * 4; // unused _rot_comp.Function = (_rot_comp.Reg_58 & 7) | (Pico_mcd->s68k_regs[3] & 0x18); // Jmp_Adr @@ -46,12 +34,10 @@ static void gfx_cd_start(void) _rot_comp.YD = (_rot_comp.Reg_60 >> 3) & 7; _rot_comp.Vector_Adr = (_rot_comp.Reg_66 & 0xfffe) << 2; - upd_len = (_rot_comp.Reg_62 >> 3) & 0x3f; - upd_len = Table_Rot_Time[upd_len]; - _rot_comp.Draw_Speed = _rot_comp.Float_Part = upd_len; - _rot_comp.Reg_58 |= 0x8000; // Stamp_Size, we start a new GFX operation + pcd_event_schedule_s68k(PCD_EVENT_GFX, 5 * w * h); + switch (_rot_comp.Reg_58 & 6) // Scr_16? { case 0: // ? @@ -68,25 +54,46 @@ static void gfx_cd_start(void) break; } - dprintf("gfx_cd_start, stamp_map_addr=%06x", _rot_comp.Stamp_Map_Adr); - - gfx_cd_update(); -} - - -static void gfx_completed(void) -{ - _rot_comp.Reg_58 &= 0x7fff; // Stamp_Size - _rot_comp.Reg_64 = 0; - if (Pico_mcd->s68k_regs[0x33] & (1<<1)) + if (PicoOpt & POPT_EN_MCD_GFX) { - elprintf(EL_INTS, "gfx_cd irq 1"); - SekInterruptS68k(1); + unsigned int func = _rot_comp.Function; + unsigned short *stamp_base = (unsigned short *) (Pico_mcd->word_ram2M + _rot_comp.Stamp_Map_Adr); + + while (h--) + gfx_do_line(func, stamp_base, w); } } -static void gfx_do(unsigned int func, unsigned short *stamp_base, unsigned int H_Dot) +PICO_INTERNAL_ASM unsigned int gfx_cd_read(unsigned int a) +{ + unsigned int d = 0; + + switch (a) { + case 0x58: d = _rot_comp.Reg_58; break; + case 0x5A: d = _rot_comp.Reg_5A; break; + case 0x5C: d = _rot_comp.Reg_5C; break; + case 0x5E: d = _rot_comp.Reg_5E; break; + case 0x60: d = _rot_comp.Reg_60; break; + case 0x62: d = _rot_comp.Reg_62; break; + case 0x64: + d = _rot_comp.Reg_64; + if (_rot_comp.Reg_64 > 1) + // fudge.. + _rot_comp.Reg_64--; + break; + case 0x66: break; + default: dprintf("gfx_cd_read FIXME: unexpected address: %02x", a); break; + } + + dprintf("gfx_cd_read(%02x) = %04x", a, d); + + return d; + +} + +static void gfx_do_line(unsigned int func, unsigned short *stamp_base, + unsigned int H_Dot) { unsigned int eax, ebx, ecx, edx, esi, edi, pixel; unsigned int XD, Buffer_Adr; @@ -291,88 +298,13 @@ Next_Pixel: } -PICO_INTERNAL void gfx_cd_update(void) -{ - int V_Dot = _rot_comp.Reg_64 & 0xff; - int jobs; - - dprintf("gfx_cd_update, Reg_64 = %04x", _rot_comp.Reg_64); - - if (!V_Dot) - { - gfx_completed(); - return; - } - - jobs = _rot_comp.Float_Part >> 16; - - if (!jobs) - { - _rot_comp.Float_Part += _rot_comp.Draw_Speed; - return; - } - - _rot_comp.Float_Part &= 0xffff; - _rot_comp.Float_Part += _rot_comp.Draw_Speed; - - if (PicoOpt & POPT_EN_MCD_GFX) - { - unsigned int func = _rot_comp.Function; - unsigned int H_Dot = _rot_comp.Reg_62 & 0x1ff; - unsigned short *stamp_base = (unsigned short *) (Pico_mcd->word_ram2M + _rot_comp.Stamp_Map_Adr); - - while (jobs--) - { - gfx_do(func, stamp_base, H_Dot); // jmp [Jmp_Adr]: - - V_Dot--; // dec byte [V_Dot] - if (V_Dot == 0) - { - // GFX_Completed: - gfx_completed(); - return; - } - } - } - else - { - if (jobs >= V_Dot) - { - gfx_completed(); - return; - } - V_Dot -= jobs; - } - - _rot_comp.Reg_64 = V_Dot; -} - - -PICO_INTERNAL_ASM unsigned int gfx_cd_read(unsigned int a) -{ - unsigned int d = 0; - - switch (a) { - case 0x58: d = _rot_comp.Reg_58; break; - case 0x5A: d = _rot_comp.Reg_5A; break; - case 0x5C: d = _rot_comp.Reg_5C; break; - case 0x5E: d = _rot_comp.Reg_5E; break; - case 0x60: d = _rot_comp.Reg_60; break; - case 0x62: d = _rot_comp.Reg_62; break; - case 0x64: d = _rot_comp.Reg_64; break; - case 0x66: break; - default: dprintf("gfx_cd_read FIXME: unexpected address: %02x", a); break; - } - - dprintf("gfx_cd_read(%02x) = %04x", a, d); - - return d; -} - PICO_INTERNAL_ASM void gfx_cd_write16(unsigned int a, unsigned int d) { dprintf("gfx_cd_write16(%x, %04x)", a, d); + if (_rot_comp.Reg_58 & 0x8000) + elprintf(EL_CD|EL_ANOMALY, "cd: busy gfx reg write %02x %04x", a, d); + switch (a) { case 0x58: // .Reg_Stamp_Size _rot_comp.Reg_58 = d & 7; diff --git a/pico/cd/gfx_cd.h b/pico/cd/gfx_cd.h index 9a0c797e..a80b2ec4 100644 --- a/pico/cd/gfx_cd.h +++ b/pico/cd/gfx_cd.h @@ -24,8 +24,6 @@ typedef struct } Rot_Comp; -PICO_INTERNAL void gfx_cd_update(void); - PICO_INTERNAL_ASM unsigned int gfx_cd_read(unsigned int a); PICO_INTERNAL_ASM void gfx_cd_write16(unsigned int a, unsigned int d); diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 95c78f92..2c6eadc5 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -99,8 +99,11 @@ static u32 m68k_reg_read16(u32 a) case 0xA: elprintf(EL_UIO, "m68k FIXME: reserved read"); goto end; - case 0xC: - d = Pico_mcd->m.timer_stopwatch >> 16; + case 0xC: // 384 cycle stopwatch timer + // ugh.. + d = pcd_cycles_m68k_to_s68k(SekCyclesDone()); + d = (d - Pico_mcd->m.stopwatch_base_c) / 384; + d &= 0x0fff; elprintf(EL_CDREGS, "m68k stopwatch timer read (%04x)", d); goto end; } @@ -273,7 +276,9 @@ u32 s68k_reg_read16(u32 a) case 8: return Read_CDC_Host(1); // Gens returns 0 here on byte reads case 0xC: - d = Pico_mcd->m.timer_stopwatch >> 16; + d = SekCyclesDoneS68k() - Pico_mcd->m.stopwatch_base_c; + d /= 384; + d &= 0x0fff; elprintf(EL_CDREGS, "s68k stopwatch timer read (%04x)", d); return d; case 0x30: @@ -363,21 +368,29 @@ void s68k_reg_write8(u32 a, u32 d) elprintf(EL_CDREGS, "s68k set CDC dma addr"); break; case 0xc: - case 0xd: - elprintf(EL_CDREGS, "s68k set stopwatch timer"); - Pico_mcd->m.timer_stopwatch = 0; + case 0xd: // 384 cycle stopwatch timer + elprintf(EL_CDREGS|EL_CD, "s68k clear stopwatch (%x)", d); + // does this also reset internal 384 cycle counter? + Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k(); return; case 0xe: Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair return; - case 0x31: - elprintf(EL_CDREGS, "s68k set int3 timer: %02x", d); - Pico_mcd->m.timer_int3 = (d & 0xff) << 16; + case 0x31: // 384 cycle int3 timer + d &= 0xff; + elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d); + Pico_mcd->s68k_regs[a] = (u8) d; + if (d) // d or d+1?? + pcd_event_schedule_s68k(PCD_EVENT_TIMER3, d * 384); + else + pcd_event_schedule(0, PCD_EVENT_TIMER3, 0); break; case 0x33: // IRQ mask - elprintf(EL_CDREGS, "s68k irq mask: %02x", d); - if ((d&(1<<4)) && (Pico_mcd->s68k_regs[0x37]&4) && !(Pico_mcd->s68k_regs[0x33]&(1<<4))) { - CDD_Export_Status(); + elprintf(EL_CDREGS|EL_CD, "s68k irq mask: %02x", d); + d &= 0x7e; + if ((d ^ Pico_mcd->s68k_regs[0x33]) & d & PCDS_IEN4) { + if (Pico_mcd->s68k_regs[0x37] & 4) + CDD_Export_Status(); } break; case 0x34: // fader @@ -978,7 +991,7 @@ static void remap_word_ram(int r3) #endif } -void PicoMemStateLoaded(void) +void pcd_state_loaded_mem(void) { int r3 = Pico_mcd->s68k_regs[3]; @@ -1147,3 +1160,4 @@ static void m68k_mem_setup_cd(void) } #endif // EMU_M68K +// vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/cd/pico.c b/pico/cd/pico.c index 2b652957..0b6b943c 100644 --- a/pico/cd/pico.c +++ b/pico/cd/pico.c @@ -1,6 +1,6 @@ /* * PicoDrive - * (C) notaz, 2007 + * (C) notaz, 2007,2013 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -10,7 +10,8 @@ #include "../sound/ym2612.h" extern unsigned char formatted_bram[4*0x10]; -extern unsigned int s68k_poll_adclk; + +static unsigned int m68k_cycle_mult; void (*PicoMCDopenTray)(void) = NULL; void (*PicoMCDcloseTray)(void) = NULL; @@ -65,149 +66,191 @@ PICO_INTERNAL int PicoResetMCD(void) } SRam.start = SRam.end = 0; // unused + pcd_event_schedule(0, PCD_EVENT_CDC, 12500000/75); + return 0; } -static __inline void SekRunS68k(int cyc) +static __inline void SekRunS68k(unsigned int to) { int cyc_do; - SekCycleAimS68k+=cyc; - if ((cyc_do=SekCycleAimS68k-SekCycleCntS68k) <= 0) return; -#if defined(EMU_CORE_DEBUG) - SekCycleCntS68k+=CM_compareRun(cyc_do, 1); -#elif defined(EMU_C68K) - PicoCpuCS68k.cycles=cyc_do; + + SekCycleAimS68k = to; + if ((cyc_do = SekCycleAimS68k - SekCycleCntS68k) <= 0) + return; + + SekCycleCntS68k += cyc_do; +#if defined(EMU_C68K) + PicoCpuCS68k.cycles = cyc_do; CycloneRun(&PicoCpuCS68k); - SekCycleCntS68k+=cyc_do-PicoCpuCS68k.cycles; + SekCycleCntS68k -= PicoCpuCS68k.cycles; #elif defined(EMU_M68K) m68k_set_context(&PicoCpuMS68k); - SekCycleCntS68k+=m68k_execute(cyc_do); + SekCycleCntS68k += m68k_execute(cyc_do) - cyc_do; m68k_set_context(&PicoCpuMM68k); #elif defined(EMU_F68K) - g_m68kcontext=&PicoCpuFS68k; - SekCycleCntS68k+=fm68k_emulate(cyc_do, 0, 0); - g_m68kcontext=&PicoCpuFM68k; + g_m68kcontext = &PicoCpuFS68k; + SekCycleCntS68k += fm68k_emulate(cyc_do, 0, 0) - cyc_do; + g_m68kcontext = &PicoCpuFM68k; #endif } -#define PS_STEP_M68K ((488<<16)/20) // ~24 -//#define PS_STEP_S68K 13 -#if defined(_ASM_CD_PICO_C) -extern void SekRunPS(int cyc_m68k, int cyc_s68k); -#elif defined(EMU_F68K) -static __inline void SekRunPS(int cyc_m68k, int cyc_s68k) +unsigned int pcd_cycles_m68k_to_s68k(unsigned int c) { - SekCycleAim+=cyc_m68k; - SekCycleAimS68k+=cyc_s68k; - fm68k_emulate(0, 1, 0); + return (long long)c * m68k_cycle_mult >> 16; } -#else -static __inline void SekRunPS(int cyc_m68k, int cyc_s68k) + +/* events */ +static void pcd_cdc_event(unsigned int now) { - int cycn, cycn_s68k, cyc_do; - SekCycleAim+=cyc_m68k; - SekCycleAimS68k+=cyc_s68k; + // 75Hz CDC update + Check_CD_Command(); + pcd_event_schedule(now, PCD_EVENT_CDC, 12500000/75); +} -// fprintf(stderr, "=== start %3i/%3i [%3i/%3i] {%05i.%i} ===\n", cyc_m68k, cyc_s68k, -// SekCycleAim-SekCycleCnt, SekCycleAimS68k-SekCycleCntS68k, Pico.m.frame_count, Pico.m.scanline); +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); + } - /* loop 488 downto 0 in steps of PS_STEP */ - for (cycn = (488<<16)-PS_STEP_M68K; cycn >= 0; cycn -= PS_STEP_M68K) - { - cycn_s68k = (cycn + cycn/2 + cycn/8) >> 16; - if ((cyc_do = SekCycleAim-SekCycleCnt-(cycn>>16)) > 0) { -#if defined(EMU_C68K) - PicoCpuCM68k.cycles = cyc_do; - CycloneRun(&PicoCpuCM68k); - SekCycleCnt += cyc_do - PicoCpuCM68k.cycles; -#elif defined(EMU_M68K) - m68k_set_context(&PicoCpuMM68k); - SekCycleCnt += m68k_execute(cyc_do); -#elif defined(EMU_F68K) - g_m68kcontext = &PicoCpuFM68k; - SekCycleCnt += fm68k_emulate(cyc_do, 0, 0); -#endif - } - if ((cyc_do = SekCycleAimS68k-SekCycleCntS68k-cycn_s68k) > 0) { -#if defined(EMU_C68K) - PicoCpuCS68k.cycles = cyc_do; - CycloneRun(&PicoCpuCS68k); - SekCycleCntS68k += cyc_do - PicoCpuCS68k.cycles; -#elif defined(EMU_M68K) - m68k_set_context(&PicoCpuMS68k); - SekCycleCntS68k += m68k_execute(cyc_do); -#elif defined(EMU_F68K) - g_m68kcontext = &PicoCpuFS68k; - SekCycleCntS68k += fm68k_emulate(cyc_do, 0, 0); -#endif + if (Pico_mcd->s68k_regs[0x31] != 0) + pcd_event_schedule(now, PCD_EVENT_TIMER3, + Pico_mcd->s68k_regs[0x31] * 384); +} + +static void pcd_gfx_event(unsigned int now) +{ + // update gfx chip + if (Pico_mcd->rot_comp.Reg_58 & 0x8000) { + Pico_mcd->rot_comp.Reg_58 &= 0x7fff; + Pico_mcd->rot_comp.Reg_64 = 0; + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) { + elprintf(EL_INTS |EL_CD, "s68k: gfx_cd irq 1"); + SekInterruptS68k(1); } } } -#endif - -static __inline void check_cd_dma(void) +static void pcd_dma_event(unsigned int now) { - int ddx; - - if (!(Pico_mcd->scd.Status_CDC & 0x08)) return; - - ddx = Pico_mcd->s68k_regs[4] & 7; - if (ddx < 2) return; // invalid - if (ddx < 4) { - Pico_mcd->s68k_regs[4] |= 0x40; // Data set ready in host port - return; - } - if (ddx == 6) return; // invalid - - Update_CDC_TRansfer(ddx); // now go and do the actual transfer + int ddx = Pico_mcd->s68k_regs[4] & 7; + Update_CDC_TRansfer(ddx); } -static __inline void update_chips(void) +typedef void (event_cb)(unsigned int now); + +/* times are in s68k (12.5MHz) cycles */ +unsigned int pcd_event_times[PCD_EVENT_COUNT]; +static unsigned int event_time_next; +static event_cb *pcd_event_cbs[PCD_EVENT_COUNT] = { + [PCD_EVENT_CDC] = pcd_cdc_event, + [PCD_EVENT_TIMER3] = pcd_int3_timer_event, + [PCD_EVENT_GFX] = pcd_gfx_event, + [PCD_EVENT_DMA] = pcd_dma_event, +}; + +void pcd_event_schedule(unsigned int now, enum pcd_event event, int after) { - int counter_timer, int3_set; - int counter75hz_lim = Pico.m.pal ? 2080 : 2096; + unsigned int when; - // 75Hz CDC update - if ((Pico_mcd->m.counter75hz+=10) >= counter75hz_lim) { - Pico_mcd->m.counter75hz -= counter75hz_lim; - Check_CD_Command(); - } + when = now + after; + if (when == 0) { + // event cancelled + pcd_event_times[event] = 0; + return; + } - // update timers - counter_timer = Pico.m.pal ? 0x21630 : 0x2121c; // 136752 : 135708; - Pico_mcd->m.timer_stopwatch += counter_timer; - if ((int3_set = Pico_mcd->s68k_regs[0x31])) { - Pico_mcd->m.timer_int3 -= counter_timer; - if (Pico_mcd->m.timer_int3 < 0) { - if (Pico_mcd->s68k_regs[0x33] & (1<<3)) { - elprintf(EL_INTS, "s68k: timer irq 3"); - SekInterruptS68k(3); - Pico_mcd->m.timer_int3 += int3_set << 16; - } - // is this really what happens if irq3 is masked out? - Pico_mcd->m.timer_int3 &= 0xffffff; - } - } + when |= 1; - // update gfx chip - if (Pico_mcd->rot_comp.Reg_58 & 0x8000) - gfx_cd_update(); + elprintf(EL_CD, "cd: new event #%u %u->%u", event, now, when); + pcd_event_times[event] = when; + + if (event_time_next == 0 || CYCLES_GT(event_time_next, when)) + event_time_next = when; } +void pcd_event_schedule_s68k(enum pcd_event event, int after) +{ + if (SekCyclesLeftS68k > after) + SekEndRunS68k(after); + + pcd_event_schedule(SekCyclesDoneS68k(), event, after); +} + +static void pcd_run_events(unsigned int until) +{ + int oldest, oldest_diff, time; + int i, diff; + + while (1) { + oldest = -1, oldest_diff = 0x7fffffff; + + for (i = 0; i < PCD_EVENT_COUNT; i++) { + if (pcd_event_times[i]) { + diff = pcd_event_times[i] - until; + if (diff < oldest_diff) { + oldest_diff = diff; + oldest = i; + } + } + } + + if (oldest_diff <= 0) { + time = pcd_event_times[oldest]; + pcd_event_times[oldest] = 0; + elprintf(EL_CD, "cd: run event #%d %u", oldest, time); + pcd_event_cbs[oldest](time); + } + else if (oldest_diff < 0x7fffffff) { + event_time_next = pcd_event_times[oldest]; + break; + } + else { + event_time_next = 0; + break; + } + } + + if (oldest != -1) + elprintf(EL_CD, "cd: next event #%d at %u", + oldest, event_time_next); +} + +static void pcd_sync_s68k(unsigned int m68k_target) +{ + #define now SekCycleCntS68k + unsigned int s68k_target = + (unsigned long long)m68k_target * m68k_cycle_mult >> 16; + unsigned int target; + + elprintf(EL_CD, "s68k sync to %u/%u", m68k_target, s68k_target); + + if ((Pico_mcd->m.busreq & 3) != 1) { /* busreq/reset */ + SekCycleCntS68k = SekCycleAimS68k = s68k_target; + pcd_run_events(m68k_target); + return; + } + + while (CYCLES_GT(s68k_target, now)) { + if (event_time_next && CYCLES_GE(now, event_time_next)) + pcd_run_events(now); + + target = s68k_target; + if (event_time_next && CYCLES_GT(target, event_time_next)) + target = event_time_next; + + SekRunS68k(target); + } + #undef now +} #define PICO_CD -#define CPUS_RUN(m68k_cycles,s68k_cycles) \ -{ \ - if ((PicoOpt&POPT_EN_MCD_PSYNC) && (Pico_mcd->m.busreq&3) == 1) { \ - SekRunPS(m68k_cycles, s68k_cycles); /* "better/perfect sync" */ \ - } else { \ - SekRunM68k(m68k_cycles); \ - if ((Pico_mcd->m.busreq&3) == 1) /* no busreq/no reset */ \ - SekRunS68k(s68k_cycles); \ - } \ -} +#define CPUS_RUN(m68k_cycles) \ + SekRunM68k(m68k_cycles) + #include "../pico_cmn.c" @@ -216,7 +259,44 @@ PICO_INTERNAL void PicoFrameMCD(void) if (!(PicoOpt&POPT_ALT_RENDERER)) PicoFrameStart(); + // ~1.63 for NTSC, ~1.645 for PAL + if (Pico.m.pal) + m68k_cycle_mult = ((12500000ull << 16) / (50*312*488)); + else + m68k_cycle_mult = ((12500000ull << 16) / (60*262*488)) + 1; + PicoFrameHints(); } +void pcd_state_loaded(void) +{ + unsigned int cycles; + int diff; + pcd_state_loaded_mem(); + + // old savestates.. + cycles = pcd_cycles_m68k_to_s68k(SekCycleAim); + diff = cycles - SekCycleAimS68k; + if (diff < -1000 || diff > 1000) { + SekCycleCntS68k = SekCycleAimS68k = cycles; + } + if (pcd_event_times[PCD_EVENT_CDC] == 0) { + pcd_event_schedule(SekCycleAimS68k, PCD_EVENT_CDC, 12500000/75); + + if (Pico_mcd->s68k_regs[0x31]) + pcd_event_schedule(SekCycleAimS68k, PCD_EVENT_TIMER3, + Pico_mcd->s68k_regs[0x31] * 384); + + if (Pico_mcd->rot_comp.Reg_58 & 0x8000) { + Pico_mcd->rot_comp.Reg_58 &= 0x7fff; + Pico_mcd->rot_comp.Reg_64 = 0; + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) + SekInterruptS68k(1); + } + if (Pico_mcd->scd.Status_CDC & 0x08) + Update_CDC_TRansfer(Pico_mcd->s68k_regs[4] & 7); + } +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/cd/sek.c b/pico/cd/sek.c index 96e63351..8d838628 100644 --- a/pico/cd/sek.c +++ b/pico/cd/sek.c @@ -9,8 +9,8 @@ #include "../pico_int.h" -int SekCycleCntS68k=0; // cycles done in this frame -int SekCycleAimS68k=0; // cycle aim +unsigned int SekCycleCntS68k; +unsigned int SekCycleAimS68k; /* context */ diff --git a/pico/debug.c b/pico/debug.c index 9cb93b26..26b63936 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -43,7 +43,7 @@ char *PDebugMain(void) !!(SRam.flags & SRF_ENABLED), !!(SRam.flags & SRF_EEPROM), SRam.eeprom_type); MVP; sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", SRam.start, SRam.end, Pico.m.sram_reg); MVP; sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP; - sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDoneT()); MVP; + sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDone()); MVP; sprintf(dstrp, "M68k: PC: %06x, SR: %04x, irql: %i\n", SekPc, SekSr, SekIrqLevel); MVP; #if defined(EMU_C68K) sprintf(dstrp - 1, ", st_flg: %x\n", PicoCpuCM68k.state_flags); MVP; diff --git a/pico/eeprom.c b/pico/eeprom.c index 916622a3..16f6c05c 100644 --- a/pico/eeprom.c +++ b/pico/eeprom.c @@ -21,7 +21,7 @@ static void EEPROM_write_do(unsigned int d) // ???? ??la (l=SCL, a=SDA) unsigned int scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave; elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1, - (d&2)>>1, d&1, SekCyclesDoneT() - last_write); + (d&2)>>1, d&1, SekCyclesDone() - last_write); saddr &= 0x1fff; if(sreg & d & 2) { @@ -142,17 +142,17 @@ static void EEPROM_upd_pending(unsigned int d) void EEPROM_write16(unsigned int d) { // this diff must be at most 16 for NBA Jam to work - if (SekCyclesDoneT() - last_write < 16) { + if (SekCyclesDone() - last_write < 16) { // just update pending state elprintf(EL_EEPROM, "eeprom: skip because cycles=%i", - SekCyclesDoneT() - last_write); + SekCyclesDone() - last_write); EEPROM_upd_pending(d); } else { int srs = Pico.m.eeprom_status; EEPROM_write_do(srs >> 6); // execute pending EEPROM_upd_pending(d); if ((srs ^ Pico.m.eeprom_status) & 0xc0) // update time only if SDA/SCL changed - last_write = SekCyclesDoneT(); + last_write = SekCyclesDone(); } } @@ -172,7 +172,7 @@ unsigned int EEPROM_read(void) EEPROM_write_do(Pico.m.eeprom_status>>6); sreg = Pico.m.eeprom_status; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave; - interval = SekCyclesDoneT() - last_write; + interval = SekCyclesDone() - last_write; d = (sreg>>6)&1; // use SDA as "open bus" // NBA Jam is nasty enough to read raising the SCL and starting the new cycle. diff --git a/pico/memory.c b/pico/memory.c index 664fd72a..24e5f21e 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -309,6 +309,13 @@ NOINLINE void io_ports_write(u32 a, u32 d) Pico.ioports[a] = d; } +// lame.. +static int z80_cycles_from_68k(void) +{ + return z80_cycle_aim + + cycles_68k_to_z80(SekCyclesDone() - last_z80_sync); +} + void NOINLINE ctl_write_z80busreq(u32 d) { d&=1; d^=1; @@ -317,14 +324,13 @@ void NOINLINE ctl_write_z80busreq(u32 d) { if (d) { - z80_cycle_cnt = cycles_68k_to_z80(SekCyclesDone()); + z80_cycle_cnt = z80_cycles_from_68k(); } else { - z80stopCycle = SekCyclesDone(); if ((PicoOpt&POPT_EN_Z80) && !Pico.m.z80_reset) { pprof_start(m68k); - PicoSyncZ80(z80stopCycle); + PicoSyncZ80(SekCyclesDone()); pprof_end_sub(m68k); } } @@ -350,7 +356,7 @@ void NOINLINE ctl_write_z80reset(u32 d) } else { - z80_cycle_cnt = cycles_68k_to_z80(SekCyclesDone()); + z80_cycle_cnt = z80_cycles_from_68k(); z80_reset(); } Pico.m.z80_reset = d; @@ -486,7 +492,7 @@ static void PicoWrite8_z80(u32 a, u32 d) } if ((a & 0x4000) == 0x0000) { // z80 RAM - SekCyclesBurn(2); // hack + SekCyclesBurnRun(2); // FIXME hack Pico.zram[a & 0x1fff] = (u8)d; return; } @@ -940,7 +946,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) 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() : cycles_68k_to_z80(SekCyclesDone()); + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); timer_a_next_oflow = (cycles << 8) + timer_a_step; } elprintf(EL_YMTIMER, "timer a set to %i, %i", 1024 - TAnew, timer_a_next_oflow>>8); @@ -955,7 +961,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) //ym2612.OPN.ST.TBT = 0; timer_b_step = TIMER_B_TICK_ZCYCLES * (256 - d); // 262800 if (ym2612.OPN.ST.mode & 2) { - int cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); timer_b_next_oflow = (cycles << 8) + timer_b_step; } elprintf(EL_YMTIMER, "timer b set to %i, %i", 256 - d, timer_b_next_oflow>>8); @@ -963,7 +969,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) return 0; case 0x27: { /* mode, timer control */ int old_mode = ym2612.OPN.ST.mode; - int cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); ym2612.OPN.ST.mode = d; elprintf(EL_YMTIMER, "st mode %02x", d); @@ -1041,7 +1047,7 @@ static u32 ym2612_read_local_z80(void) static u32 ym2612_read_local_68k(void) { - int xcycles = cycles_68k_to_z80(SekCyclesDone()) << 8; + int xcycles = z80_cycles_from_68k() << 8; ym2612_read_local(); diff --git a/pico/pico.c b/pico/pico.c index bbc514fe..bd4621b3 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -169,7 +169,7 @@ int PicoReset(void) SekReset(); // s68k doesn't have the TAS quirk, so we just globally set normal TAS handler in MCD mode (used by Batman games). SekSetRealTAS(PicoAHW & PAHW_MCD); - SekCycleCntT = SekCycleCnt = SekCycleAim = 0; + SekCycleCnt = SekCycleAim = 0; if (PicoAHW & PAHW_MCD) // needed for MCD to reset properly, probably some bug hides behind this.. @@ -278,23 +278,25 @@ PICO_INTERNAL int CheckDMA(void) #include "pico_cmn.c" -int z80stopCycle; -int z80_cycle_cnt; /* 'done' z80 cycles before z80_run() */ +unsigned int last_z80_sync; /* in 68k cycles */ +int z80_cycle_cnt; int z80_cycle_aim; int z80_scanline; int z80_scanline_cycles; /* cycles done until z80_scanline */ /* sync z80 to 68k */ -PICO_INTERNAL void PicoSyncZ80(int m68k_cycles_done) +PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done) { int cnt; - z80_cycle_aim = cycles_68k_to_z80(m68k_cycles_done); + z80_cycle_aim += cycles_68k_to_z80(m68k_cycles_done - last_z80_sync); cnt = z80_cycle_aim - z80_cycle_cnt; + last_z80_sync = m68k_cycles_done; pprof_start(z80); - elprintf(EL_BUSREQ, "z80 sync %i (%i|%i -> %i|%i)", cnt, z80_cycle_cnt, z80_cycle_cnt / 228, - z80_cycle_aim, z80_cycle_aim / 228); + elprintf(EL_BUSREQ, "z80 sync %i (%u|%u -> %u|%u)", cnt, + z80_cycle_cnt, z80_cycle_cnt / 288, + z80_cycle_aim, z80_cycle_aim / 288); if (cnt > 0) z80_cycle_cnt += z80_run(cnt); diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index f4e20d21..98dfa936 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -9,9 +9,6 @@ #define CYCLES_M68K_LINE 488 // suitable for both PAL/NTSC #define CYCLES_M68K_VINT_LAG 68 #define CYCLES_M68K_ASD 148 -#define CYCLES_S68K_LINE 795 -#define CYCLES_S68K_VINT_LAG 111 -#define CYCLES_S68K_ASD 241 // pad delay (for 6 button pads) #define PAD_DELAY() { \ @@ -21,7 +18,7 @@ // CPUS_RUN #ifndef CPUS_RUN -#define CPUS_RUN(m68k_cycles,s68k_cycles) \ +#define CPUS_RUN(m68k_cycles) \ SekRunM68k(m68k_cycles) #endif @@ -31,24 +28,23 @@ static __inline void SekRunM68k(int cyc) pprof_start(m68k); pevt_log_m68k_o(EVT_RUN_START); - SekCycleAim+=cyc; - if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) - goto out; + SekCycleAim += cyc; + while ((cyc_do = SekCycleAim - SekCycleCnt) > 0) { + SekCycleCnt += cyc_do; -#if defined(EMU_CORE_DEBUG) - // this means we do run-compare - SekCycleCnt+=CM_compareRun(cyc_do, 0); -#elif defined(EMU_C68K) - PicoCpuCM68k.cycles=cyc_do; - CycloneRun(&PicoCpuCM68k); - SekCycleCnt+=cyc_do-PicoCpuCM68k.cycles; +#if defined(EMU_C68K) + PicoCpuCM68k.cycles = cyc_do; + CycloneRun(&PicoCpuCM68k); + SekCycleCnt -= PicoCpuCM68k.cycles; #elif defined(EMU_M68K) - SekCycleCnt+=m68k_execute(cyc_do); + SekCycleCnt += m68k_execute(cyc_do) - cyc_do; #elif defined(EMU_F68K) - SekCycleCnt+=fm68k_emulate(cyc_do, 0, 0); + SekCycleCnt += fm68k_emulate(cyc_do, 0, 0) - cyc_do; #endif + } + + SekCyclesLeft = 0; -out: SekTrace(0); pevt_log_m68k_o(EVT_RUN_END); pprof_end(m68k); @@ -58,6 +54,7 @@ static int PicoFrameHints(void) { struct PicoVideo *pv=&Pico.video; int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap; + unsigned int cycles; int hint; // Hint counter pevt_log_m68k_o(EVT_FRAME_START); @@ -81,11 +78,7 @@ static int PicoFrameHints(void) line_sample = 93; } - SekCyclesReset(); z80_resetCycles(); -#ifdef PICO_CD - SekCyclesResetS68k(); -#endif PsndDacLine = 0; emustatus &= ~1; @@ -95,7 +88,7 @@ static int PicoFrameHints(void) //dprintf("-hint: %i", hint); // This is to make active scan longer (needed for Double Dragon 2, mainly) - CPUS_RUN(CYCLES_M68K_ASD, CYCLES_S68K_ASD); + CPUS_RUN(CYCLES_M68K_ASD); for (y = 0; y < lines_vis; y++) { @@ -114,9 +107,6 @@ static int PicoFrameHints(void) } PAD_DELAY(); -#ifdef PICO_CD - check_cd_dma(); -#endif // H-Interrupts: if (--hint < 0) // y <= lines_vis: Comix Zone, Golden Axe @@ -124,7 +114,7 @@ static int PicoFrameHints(void) hint=pv->reg[10]; // Reload H-Int counter pv->pending_ints|=0x10; if (pv->reg[0]&0x10) { - elprintf(EL_INTS, "hint: @ %06x [%i]", SekPc, SekCycleCnt); + elprintf(EL_INTS, "hint: @ %06x [%i]", SekPc, SekCyclesDone()); SekInterrupt(4); } } @@ -145,25 +135,26 @@ static int PicoFrameHints(void) // get samples from sound chips if ((y == 224 || y == line_sample) && PsndOut) { + cycles = SekCyclesDone(); + if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) - PicoSyncZ80(SekCycleCnt); + PicoSyncZ80(cycles); if (ym2612.dacen && PsndDacLine <= y) PsndDoDAC(y); +#ifdef PICO_CD + pcd_sync_s68k(cycles); +#endif #ifdef PICO_32X - p32x_sync_sh2s(SekCyclesDoneT2()); + p32x_sync_sh2s(cycles); #endif PsndGetSamples(y); } // Run scanline: if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); - CPUS_RUN(CYCLES_M68K_LINE, CYCLES_S68K_LINE); + CPUS_RUN(CYCLES_M68K_LINE); -#ifdef PICO_CD - update_chips(); -#else if (PicoLineHook) PicoLineHook(); -#endif pevt_log_m68k_o(EVT_NEXT_LINE); } @@ -187,16 +178,13 @@ static int PicoFrameHints(void) memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt)); PAD_DELAY(); -#ifdef PICO_CD - check_cd_dma(); -#endif // Last H-Int: if (--hint < 0) { hint=pv->reg[10]; // Reload H-Int counter pv->pending_ints|=0x10; - //printf("rhint: %i @ %06x [%i|%i]\n", hint, SekPc, y, SekCycleCnt); + //printf("rhint: %i @ %06x [%i|%i]\n", hint, SekPc, y, SekCyclesDone()); if (pv->reg[0]&0x10) SekInterrupt(4); } @@ -207,20 +195,25 @@ static int PicoFrameHints(void) // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga) // also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants) // also delay between last H-int and V-int (Golden Axe 3) - CPUS_RUN(CYCLES_M68K_VINT_LAG, CYCLES_S68K_VINT_LAG); + CPUS_RUN(CYCLES_M68K_VINT_LAG); if (pv->reg[1]&0x20) { - elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCycleCnt); + elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCyclesDone()); SekInterrupt(6); } + + cycles = SekCyclesDone(); if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) { - PicoSyncZ80(SekCycleCnt); + PicoSyncZ80(cycles); elprintf(EL_INTS, "zint"); z80_int(); } +#ifdef PICO_CD + pcd_sync_s68k(cycles); +#endif #ifdef PICO_32X - p32x_sync_sh2s(SekCyclesDoneT2()); + p32x_sync_sh2s(cycles); p32x_start_blank(); #endif @@ -234,14 +227,9 @@ static int PicoFrameHints(void) // Run scanline: if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); - CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG - CYCLES_M68K_ASD, - CYCLES_S68K_LINE - CYCLES_S68K_VINT_LAG - CYCLES_S68K_ASD); + CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG - CYCLES_M68K_ASD); -#ifdef PICO_CD - update_chips(); -#else if (PicoLineHook) PicoLineHook(); -#endif pevt_log_m68k_o(EVT_NEXT_LINE); lines = scanlines_total; @@ -257,30 +245,27 @@ static int PicoFrameHints(void) pv->v_counter &= 0xff; PAD_DELAY(); -#ifdef PICO_CD - check_cd_dma(); -#endif // Run scanline: if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); - CPUS_RUN(CYCLES_M68K_LINE, CYCLES_S68K_LINE); + CPUS_RUN(CYCLES_M68K_LINE); -#ifdef PICO_CD - update_chips(); -#else if (PicoLineHook) PicoLineHook(); -#endif pevt_log_m68k_o(EVT_NEXT_LINE); } - // sync z80 + // sync cpus + cycles = SekCyclesDone(); if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) - PicoSyncZ80(Pico.m.pal ? 151809 : 127671); // cycles adjusted for converter + PicoSyncZ80(cycles); if (PsndOut && ym2612.dacen && PsndDacLine <= lines-1) PsndDoDAC(lines-1); +#ifdef PICO_CD + pcd_sync_s68k(cycles); +#endif #ifdef PICO_32X - p32x_sync_sh2s(SekCyclesDoneT2()); + p32x_sync_sh2s(cycles); #endif timers_cycle(); @@ -290,3 +275,4 @@ static int PicoFrameHints(void) #undef PAD_DELAY #undef CPUS_RUN +// vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/pico_int.h b/pico/pico_int.h index 6e4917b3..ef49295f 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -37,13 +37,8 @@ extern "C" { #ifdef EMU_C68K #include "../cpu/cyclone/Cyclone.h" extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k; -#define SekCyclesLeftNoMCD PicoCpuCM68k.cycles // cycles left for this run -#define SekCyclesLeft \ - (((PicoAHW&1) && (PicoOpt & POPT_EN_MCD_PSYNC)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD) -#define SekCyclesLeftS68k \ - ((PicoOpt & POPT_EN_MCD_PSYNC) ? (SekCycleAimS68k-SekCycleCntS68k) : PicoCpuCS68k.cycles) -#define SekEndTimeslice(after) PicoCpuCM68k.cycles=after -#define SekEndTimesliceS68k(after) PicoCpuCS68k.cycles=after +#define SekCyclesLeft PicoCpuCM68k.cycles // cycles left for this run +#define SekCyclesLeftS68k PicoCpuCS68k.cycles #define SekPc (PicoCpuCM68k.pc-PicoCpuCM68k.membase) #define SekPcS68k (PicoCpuCS68k.pc-PicoCpuCS68k.membase) #define SekDar(x) (x < 8 ? PicoCpuCM68k.d[x] : PicoCpuCM68k.a[x - 8]) @@ -59,21 +54,13 @@ extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k; #define SekInterrupt(i) PicoCpuCM68k.irq=i #define SekIrqLevel PicoCpuCM68k.irq -#ifdef EMU_M68K -#define EMU_CORE_DEBUG -#endif #endif #ifdef EMU_F68K #include "../cpu/fame/fame.h" extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; -#define SekCyclesLeftNoMCD PicoCpuFM68k.io_cycle_counter -#define SekCyclesLeft \ - (((PicoAHW&1) && (PicoOpt & POPT_EN_MCD_PSYNC)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD) -#define SekCyclesLeftS68k \ - ((PicoOpt & POPT_EN_MCD_PSYNC) ? (SekCycleAimS68k-SekCycleCntS68k) : PicoCpuFS68k.io_cycle_counter) -#define SekEndTimeslice(after) PicoCpuFM68k.io_cycle_counter=after -#define SekEndTimesliceS68k(after) PicoCpuFS68k.io_cycle_counter=after +#define SekCyclesLeft PicoCpuFM68k.io_cycle_counter +#define SekCyclesLeftS68k PicoCpuFS68k.io_cycle_counter #define SekPc fm68k_get_pc(&PicoCpuFM68k) #define SekPcS68k fm68k_get_pc(&PicoCpuFS68k) #define SekDar(x) (x < 8 ? PicoCpuFM68k.dreg[x].D : PicoCpuFM68k.areg[x - 8].D) @@ -95,22 +82,14 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; #define SekInterrupt(irq) PicoCpuFM68k.interrupts[0]=irq #define SekIrqLevel PicoCpuFM68k.interrupts[0] -#ifdef EMU_M68K -#define EMU_CORE_DEBUG -#endif #endif #ifdef EMU_M68K #include "../cpu/musashi/m68kcpu.h" extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #ifndef SekCyclesLeft -#define SekCyclesLeftNoMCD PicoCpuMM68k.cyc_remaining_cycles -#define SekCyclesLeft \ - (((PicoAHW&1) && (PicoOpt & POPT_EN_MCD_PSYNC)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD) -#define SekCyclesLeftS68k \ - ((PicoOpt & POPT_EN_MCD_PSYNC) ? (SekCycleAimS68k-SekCycleCntS68k) : PicoCpuMS68k.cyc_remaining_cycles) -#define SekEndTimeslice(after) SET_CYCLES(after) -#define SekEndTimesliceS68k(after) PicoCpuMS68k.cyc_remaining_cycles=after +#define SekCyclesLeft PicoCpuMM68k.cyc_remaining_cycles +#define SekCyclesLeftS68k PicoCpuMS68k.cyc_remaining_cycles #define SekPc m68k_get_reg(&PicoCpuMM68k, M68K_REG_PC) #define SekPcS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_PC) #define SekDar(x) PicoCpuMM68k.dar[x] @@ -140,52 +119,46 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #endif #endif // EMU_M68K -extern int SekCycleCnt; // cycles done in this frame -extern int SekCycleAim; // cycle aim -extern unsigned int SekCycleCntT; // total cycle counter, updated once per frame +// while running, cnt represents target of current timeslice +// while not in SekRun(), it's actual cycles done +// (but always use SekCyclesDone() if you need current position) +// cnt may change if timeslice is ended prematurely or extended, +// so we use SekCycleAim for the actual target +extern unsigned int SekCycleCnt; +extern unsigned int SekCycleAim; -#define SekCyclesReset() { \ - SekCycleCntT+=SekCycleAim; \ - SekCycleCnt-=SekCycleAim; \ - SekCycleAim=0; \ -} -#define SekCyclesBurn(c) SekCycleCnt+=c -#define SekCyclesDone() (SekCycleAim-SekCyclesLeft) // number of cycles done in this frame (can be checked anywhere) -#define SekCyclesDoneT() (SekCycleCntT+SekCyclesDone()) // total nuber of cycles done for this rom -#define SekCyclesDoneT2() (SekCycleCntT + SekCycleCnt) // same as above but not from memhandlers +// number of cycles done (can be checked anywhere) +#define SekCyclesDone() (SekCycleCnt - SekCyclesLeft) +// burn cycles while not in SekRun() and while in +#define SekCyclesBurn(c) SekCycleCnt += c +#define SekCyclesBurnRun(c) SekCyclesLeft -= c + +// note: sometimes may extend timeslice to delay an irq #define SekEndRun(after) { \ - SekCycleCnt -= SekCyclesLeft - (after); \ - if (SekCycleCnt < 0) SekCycleCnt = 0; \ - SekEndTimeslice(after); \ + SekCycleCnt -= SekCyclesLeft - (after); \ + SekCyclesLeft = after; \ } +extern unsigned int SekCycleCntS68k; +extern unsigned int SekCycleAimS68k; + #define SekEndRunS68k(after) { \ - SekCycleCntS68k -= SekCyclesLeftS68k - (after); \ - if (SekCycleCntS68k < 0) SekCycleCntS68k = 0; \ - SekEndTimesliceS68k(after); \ + if (SekCyclesLeftS68k > (after)) { \ + SekCycleCntS68k -= SekCyclesLeftS68k - (after); \ + SekCyclesLeftS68k = after; \ + } \ } -extern int SekCycleCntS68k; -extern int SekCycleAimS68k; +#define SekCyclesDoneS68k() (SekCycleCntS68k - SekCyclesLeftS68k) -#define SekCyclesResetS68k() { \ - SekCycleCntS68k-=SekCycleAimS68k; \ - SekCycleAimS68k=0; \ -} -#define SekCyclesDoneS68k() (SekCycleAimS68k-SekCyclesLeftS68k) - -#ifdef EMU_CORE_DEBUG -extern int dbg_irq_level; -#undef SekEndTimeslice -#undef SekCyclesBurn -#undef SekEndRun -#undef SekInterrupt -#define SekEndTimeslice(c) -#define SekCyclesBurn(c) c -#define SekEndRun(c) -#define SekInterrupt(irq) dbg_irq_level=irq -#endif +// compare cycles, handling overflows +// check if a > b +#define CYCLES_GT(a, b) \ + ((int)((a) - (b)) > 0) +// check if a >= b +#define CYCLES_GE(a, b) \ + ((int)((a) - (b)) >= 0) // ----------------------- Z80 CPU ----------------------- @@ -221,13 +194,14 @@ extern struct DrZ80 drZ80; #define Z80_STATE_SIZE 0x60 -extern int z80stopCycle; /* in 68k cycles */ +extern unsigned int last_z80_sync; extern int z80_cycle_cnt; /* 'done' z80 cycles before z80_run() */ extern int z80_cycle_aim; extern int z80_scanline; extern int z80_scanline_cycles; /* cycles done until z80_scanline */ #define z80_resetCycles() \ + last_z80_sync = SekCyclesDone(); \ z80_cycle_cnt = z80_cycle_aim = z80_scanline = z80_scanline_cycles = 0; #define z80_cyclesDone() \ @@ -410,14 +384,12 @@ struct mcd_misc unsigned char busreq; unsigned char s68k_pend_ints; unsigned int state_flags; // 04: emu state: reset_pending - unsigned int counter75hz; - unsigned int pad0; - int timer_int3; // 10 - unsigned int timer_stopwatch; + unsigned int stopwatch_base_c; + unsigned int pad[3]; unsigned char bcram_reg; // 18: battery-backed RAM cart register unsigned char pad2; unsigned short pad3; - int pad[9]; + int pad4[9]; }; typedef struct @@ -613,7 +585,7 @@ PICO_INTERNAL void PicoMemSetupPico(void); // cd/memory.c PICO_INTERNAL void PicoMemSetupCD(void); -void PicoMemStateLoaded(void); +void pcd_state_loaded_mem(void); // pico.c extern struct Pico Pico; @@ -625,15 +597,35 @@ extern void (*PicoResetHook)(void); extern void (*PicoLineHook)(void); PICO_INTERNAL int CheckDMA(void); PICO_INTERNAL void PicoDetectRegion(void); -PICO_INTERNAL void PicoSyncZ80(int m68k_cycles_done); +PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done); // cd/pico.c +#define PCDS_IEN1 (1<<1) +#define PCDS_IEN2 (1<<2) +#define PCDS_IEN3 (1<<3) +#define PCDS_IEN4 (1<<4) +#define PCDS_IEN5 (1<<5) +#define PCDS_IEN6 (1<<6) + PICO_INTERNAL void PicoInitMCD(void); PICO_INTERNAL void PicoExitMCD(void); PICO_INTERNAL void PicoPowerMCD(void); PICO_INTERNAL int PicoResetMCD(void); PICO_INTERNAL void PicoFrameMCD(void); +enum pcd_event { + PCD_EVENT_CDC, + PCD_EVENT_TIMER3, + PCD_EVENT_GFX, + PCD_EVENT_DMA, + PCD_EVENT_COUNT, +}; +extern unsigned int pcd_event_times[PCD_EVENT_COUNT]; +void pcd_event_schedule(unsigned int now, enum pcd_event event, int after); +void pcd_event_schedule_s68k(enum pcd_event event, int after); +unsigned int pcd_cycles_m68k_to_s68k(unsigned int c); +void pcd_state_loaded(void); + // pico/pico.c PICO_INTERNAL void PicoInitPico(void); PICO_INTERNAL void PicoReratePico(void); @@ -760,7 +752,7 @@ enum p32x_event { P32X_EVENT_HINT, P32X_EVENT_COUNT, }; -extern unsigned int event_times[P32X_EVENT_COUNT]; +extern unsigned int p32x_event_times[P32X_EVENT_COUNT]; void Pico32xInit(void); void PicoPower32x(void); @@ -884,6 +876,7 @@ static __inline int isspace_(int c) #define EL_32X 0x00080000 #define EL_PWM 0x00100000 /* 32X PWM stuff (LOTS of output) */ #define EL_32XP 0x00200000 /* 32X peripherals */ +#define EL_CD 0x00400000 /* MCD */ #define EL_STATUS 0x40000000 /* status messages */ #define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */ diff --git a/pico/sek.c b/pico/sek.c index 5a7b7076..8dd77292 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -11,9 +11,8 @@ #include "memory.h" -int SekCycleCnt=0; // cycles done in this frame -int SekCycleAim=0; // cycle aim -unsigned int SekCycleCntT=0; +unsigned int SekCycleCnt; +unsigned int SekCycleAim; /* context */ @@ -220,7 +219,8 @@ PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub) #endif *(unsigned int *)(cpu+0x40) = pc; - *(unsigned int *)(cpu+0x50) = SekCycleCntT; + *(unsigned int *)(cpu+0x50) = + is_sub ? SekCycleCntS68k : SekCycleCnt; } PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) @@ -257,7 +257,10 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) context->execinfo &= ~FM68K_HALTED; if (cpu[0x4d]&1) context->execinfo |= FM68K_HALTED; #endif - SekCycleCntT = *(unsigned int *)(cpu+0x50); + if (is_sub) + SekCycleCntS68k = *(unsigned int *)(cpu+0x50); + else + SekCycleCnt = *(unsigned int *)(cpu+0x50); } diff --git a/pico/state.c b/pico/state.c index 6c113810..a3695970 100644 --- a/pico/state.c +++ b/pico/state.c @@ -173,9 +173,11 @@ typedef enum { CHUNK_32X_EVT, CHUNK_32X_FIRST = CHUNK_MSH2, CHUNK_32X_LAST = CHUNK_32X_EVT, + // add new stuff here + CHUNK_CD_EVT = 50, // CHUNK_DEFAULT_COUNT, - CHUNK_CARTHW_ = CHUNK_CARTHW, // defined in PicoInt + CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt) } chunk_name_e; static const char * const chunk_names[] = { @@ -305,6 +307,9 @@ static int state_save(void *file) CHECKED_WRITE_BUFF(CHUNK_SCD, Pico_mcd->scd); CHECKED_WRITE_BUFF(CHUNK_RC, Pico_mcd->rot_comp); CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m); + memset(buff, 0, 0x40); + memcpy(buff, pcd_event_times, sizeof(pcd_event_times)); + CHECKED_WRITE(CHUNK_CD_EVT, 0x40, buff); if (Pico_mcd->s68k_regs[3] & 4) // convert back wram_2M_to_1M(Pico_mcd->word_ram2M); @@ -336,7 +341,7 @@ static int state_save(void *file) CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal); memset(buff, 0, 0x40); - memcpy(buff, event_times, sizeof(event_times)); + memcpy(buff, p32x_event_times, sizeof(p32x_event_times)); CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff); } #endif @@ -403,6 +408,9 @@ static int state_load(void *file) R_ERROR_RETURN("bad header"); CHECKED_READ(4, &ver); + memset(pcd_event_times, 0, sizeof(pcd_event_times)); + memset(p32x_event_times, 0, sizeof(p32x_event_times)); + while (!areaEof(file)) { CHECKED_READ(1, &chunk); @@ -459,6 +467,11 @@ static int state_load(void *file) case CHUNK_RC: CHECKED_READ_BUFF(Pico_mcd->rot_comp); break; case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break; + case CHUNK_CD_EVT: + CHECKED_READ_BUFF(buff); + memcpy(pcd_event_times, buff, sizeof(pcd_event_times)); + break; + // 32x stuff #ifndef NO_32X case CHUNK_MSH2: @@ -485,7 +498,7 @@ static int state_load(void *file) case CHUNK_32X_EVT: CHECKED_READ_BUFF(buff); - memcpy(event_times, buff, sizeof(event_times)); + memcpy(p32x_event_times, buff, sizeof(p32x_event_times)); break; #endif default: @@ -510,14 +523,6 @@ readend: if (PicoAHW & PAHW_SMS) PicoStateLoadedMS(); - if (PicoAHW & PAHW_MCD) - { - PicoMemStateLoaded(); - - if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1)) - cdda_start_play(); - } - if (PicoAHW & PAHW_32X) Pico32xStateLoaded(1); @@ -530,8 +535,17 @@ readend: z80_unpack(buff_z80); // due to dep from 68k cycles.. + SekCycleAim = SekCycleCnt; if (PicoAHW & PAHW_32X) Pico32xStateLoaded(0); + if (PicoAHW & PAHW_MCD) + { + SekCycleAimS68k = SekCycleCntS68k; + pcd_state_loaded(); + + if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1)) + cdda_start_play(); + } return 0; } diff --git a/pico/videoport.c b/pico/videoport.c index b78c3585..ec68e7f6 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -93,8 +93,7 @@ static void DmaSlow(int len) SekCyclesDone(), SekPc); Pico.m.dma_xfers += len; - if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_PSYNC)) SekCyclesBurn(CheckDMA()); - else SekEndTimeslice(SekCyclesLeftNoMCD - CheckDMA()); + SekCyclesBurnRun(CheckDMA()); if ((source&0xe00000)==0xe00000) { // Ram pd=(u16 *)(Pico.ram+(source&0xfffe)); @@ -362,8 +361,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) pvid->lwrite_cnt++; if (pvid->lwrite_cnt >= 4) pvid->status|=0x100; // FIFO full if (pvid->lwrite_cnt > 4) { - SekCyclesBurn(32); // penalty // 488/12-8 - if (SekCycleCnt>=SekCycleAim) SekEndRun(0); + SekCyclesBurnRun(32); // penalty // 488/12-8 } elprintf(EL_ASVDP, "VDP data write: %04x [%06x] {%i} #%i @ %06x", d, Pico.video.addr, Pico.video.type, pvid->lwrite_cnt, SekPc); From 95049eea1c93ae4ed044c0cbb51b3c19442e0e2b Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 26 Aug 2013 02:18:37 +0300 Subject: [PATCH 29/41] famec: make reentrant --- cpu/fame/fame.h | 14 ++++++++++++++ cpu/fame/famec.c | 28 +++++++++++++--------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/cpu/fame/fame.h b/cpu/fame/fame.h index f05acc79..d5349246 100644 --- a/cpu/fame/fame.h +++ b/cpu/fame/fame.h @@ -122,6 +122,20 @@ typedef struct unsigned short execinfo; // PD extension int io_cycle_counter; // cycles left + + unsigned int Opcode; + signed int cycles_needed; + unsigned short *PC; + unsigned long BasePC; + unsigned int flag_C; + unsigned int flag_V; + unsigned int flag_NotZ; + unsigned int flag_N; + unsigned int flag_X; + unsigned int flag_T; + unsigned int flag_S; + unsigned int flag_I; + unsigned long Fetch[M68K_FETCHBANK1]; } M68K_CONTEXT; diff --git a/cpu/fame/famec.c b/cpu/fame/famec.c index 1aba794f..68915260 100644 --- a/cpu/fame/famec.c +++ b/cpu/fame/famec.c @@ -24,7 +24,7 @@ #define FAMEC_CHECK_BRANCHES #define FAMEC_EXTRA_INLINE // #define FAMEC_DEBUG -#define FAMEC_NO_GOTOS +// #define FAMEC_NO_GOTOS #define FAMEC_ADR_BITS 24 // #define FAMEC_FETCHBITS 8 #define FAMEC_DATABITS 8 @@ -528,22 +528,20 @@ M68K_CONTEXT *g_m68kcontext; #define m68kcontext (*g_m68kcontext) #ifdef FAMEC_NO_GOTOS -static u32 Opcode; -static s32 cycles_needed; -static u16 *PC; -static uptr BasePC; -static u32 flag_C; -static u32 flag_V; -static u32 flag_NotZ; -static u32 flag_N; -static u32 flag_X; +#define Opcode m68kcontext.Opcode +#define cycles_needed m68kcontext.cycles_needed +#define PC m68kcontext.PC +#define BasePC m68kcontext.BasePC +#define flag_C m68kcontext.flag_C +#define flag_V m68kcontext.flag_V +#define flag_NotZ m68kcontext.flag_NotZ +#define flag_N m68kcontext.flag_N +#define flag_X m68kcontext.flag_X #endif -#ifdef FAMEC_EMULATE_TRACE -static u32 flag_T; -#endif -static u32 flag_S; -static u32 flag_I; +#define flag_T m68kcontext.flag_T +#define flag_S m68kcontext.flag_S +#define flag_I m68kcontext.flag_I static u32 initialised = 0; From add51c49ecdda53f59bd4c01d4b2e03817002a71 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 26 Aug 2013 03:44:53 +0300 Subject: [PATCH 30/41] fix yet another portability issue --- pico/memory.c | 10 +++++----- pico/memory.h | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index 24e5f21e..4f38e5e2 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -49,7 +49,7 @@ static void xmap_set(uptr *map, int shift, int start_addr, int end_addr, for (i = start_addr >> shift; i <= end_addr >> shift; i++) { map[i] = addr >> 1; if (is_func) - map[i] |= (uptr)1 << (sizeof(addr) * 8 - 1); + map[i] |= MAP_FLAG; } } @@ -126,19 +126,19 @@ void m68k_map_unmap(int start_addr, int end_addr) addr = (uptr)m68k_unmapped_read8; for (i = start_addr >> shift; i <= end_addr >> shift; i++) - m68k_read8_map[i] = (addr >> 1) | (1 << 31); + m68k_read8_map[i] = (addr >> 1) | MAP_FLAG; addr = (uptr)m68k_unmapped_read16; for (i = start_addr >> shift; i <= end_addr >> shift; i++) - m68k_read16_map[i] = (addr >> 1) | (1 << 31); + m68k_read16_map[i] = (addr >> 1) | MAP_FLAG; addr = (uptr)m68k_unmapped_write8; for (i = start_addr >> shift; i <= end_addr >> shift; i++) - m68k_write8_map[i] = (addr >> 1) | (1 << 31); + m68k_write8_map[i] = (addr >> 1) | MAP_FLAG; addr = (uptr)m68k_unmapped_write16; for (i = start_addr >> shift; i <= end_addr >> shift; i++) - m68k_write16_map[i] = (addr >> 1) | (1 << 31); + m68k_write16_map[i] = (addr >> 1) | MAP_FLAG; } MAKE_68K_READ8(m68k_read8, m68k_read8_map) diff --git a/pico/memory.h b/pico/memory.h index 44213714..afca0826 100644 --- a/pico/memory.h +++ b/pico/memory.h @@ -45,7 +45,8 @@ void cpu68k_map_set(uptr *map, int start_addr, int end_addr, void cpu68k_map_all_ram(int start_addr, int end_addr, void *ptr, int is_sub); void m68k_map_unmap(int start_addr, int end_addr); -#define map_flag_set(x) ((x) & ((uptr)1 << (sizeof(uptr) * 8 - 1))) +#define MAP_FLAG ((uptr)1 << (sizeof(uptr) * 8 - 1)) +#define map_flag_set(x) ((x) & MAP_FLAG) #define MAKE_68K_READ8(name, map) \ u32 name(u32 a) \ From bc3c13d3291c1f7093f89d086b7082169f3c6077 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 26 Aug 2013 03:46:27 +0300 Subject: [PATCH 31/41] cd sync improvements --- pico/cd/memory.c | 63 ++++++++++++++++++++++++++++++++++---------- pico/cd/memory_arm.s | 3 +++ pico/cd/pico.c | 4 +-- pico/debug.c | 3 --- pico/pico_int.h | 14 +++++++--- 5 files changed, 65 insertions(+), 22 deletions(-) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 2c6eadc5..743568ec 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -73,6 +73,26 @@ static void remap_word_ram(int r3); #define POLL_CYCLES 124 unsigned int s68k_poll_adclk, s68k_poll_cnt; +void m68k_comm_check(u32 a) +{ + pcd_sync_s68k(SekCyclesDone()); + /*if (Pico_mcd->m.m68k_comm_dirty & (1 << a/2)) { + Pico_mcd->m.m68k_comm_dirty &= ~(1 << a/2); + Pico_mcd->m.m68k_poll_a = Pico_mcd->m.m68k_poll_cnt = 0; + return; + } + if (a != Pico_mcd->m.m68k_poll_a) { + Pico_mcd->m.m68k_poll_a = a; + Pico_mcd->m.m68k_poll_cnt = 0; + return; + } + if (++Pico_mcd->m.m68k_poll_cnt > 5) + SekCyclesBurnRun(122); + + elprintf(EL_CDPOLL, "m68k poll [%02x] %d %u", a, + Pico_mcd->m.m68k_poll_cnt, SekCyclesDone());*/ +} + #ifndef _ASM_CD_MEMORY_C static u32 m68k_reg_read16(u32 a) { @@ -84,6 +104,7 @@ static u32 m68k_reg_read16(u32 a) d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens goto end; case 2: + m68k_comm_check(a); d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7); elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc); goto end; @@ -110,6 +131,7 @@ static u32 m68k_reg_read16(u32 a) if (a < 0x30) { // comm flag/cmd/status (0xE-0x2F) + m68k_comm_check(a); d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; goto end; } @@ -130,6 +152,8 @@ void m68k_reg_write8(u32 a, u32 d) u32 dold; a &= 0x3f; + Pico_mcd->m.m68k_poll_a = 0; + switch (a) { case 0: d &= 1; @@ -137,18 +161,24 @@ void m68k_reg_write8(u32 a, u32 d) return; case 1: d &= 3; - if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset - if ( (Pico_mcd->m.busreq&1) != (d&1)) elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1)); - if ( (Pico_mcd->m.busreq&2) != (d&2)) elprintf(EL_INTSW, "m68k: s68k brq %i", (d&2)>>1); - if ((Pico_mcd->m.state_flags&1) && (d&3)==1) { - SekResetS68k(); // S68k comes out of RESET or BRQ state - Pico_mcd->m.state_flags&=~1; - elprintf(EL_CDREGS, "m68k: resetting s68k, cycles=%i", SekCyclesLeft); + elprintf(EL_CDREGS, "d m.busreq %u %u", d, Pico_mcd->m.busreq); + if (d == Pico_mcd->m.busreq) + return; + pcd_sync_s68k(SekCyclesDone()); + + if ((Pico_mcd->m.busreq ^ d) & 1) { + elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1)); + if (!(d & 1)) + d |= 2; // verified: reset also gives bus + else { + elprintf(EL_CDREGS, "m68k: resetting s68k"); + SekResetS68k(); + } } - if (!(d & 1)) - d |= 2; // verified: reset also gives bus - if ((d ^ Pico_mcd->m.busreq) & 2) + if ((Pico_mcd->m.busreq ^ d) & 2) { + elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1); remap_prg_window(); + } Pico_mcd->m.busreq = d; return; case 2: @@ -193,8 +223,10 @@ void m68k_reg_write8(u32 a, u32 d) case 0xf: d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case) case 0xe: - //dprintf("m68k: comm flag: %02x", d); - Pico_mcd->s68k_regs[0xe] = d; + if (d != Pico_mcd->s68k_regs[0xe]) { + pcd_sync_s68k(SekCyclesDone()); + Pico_mcd->s68k_regs[0xe] = d; + } #ifdef USE_POLL_DETECT if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) { SekSetStopS68k(0); s68k_poll_adclk = 0; @@ -374,8 +406,8 @@ void s68k_reg_write8(u32 a, u32 d) Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k(); return; case 0xe: - Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair - return; + d = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair + break; case 0x31: // 384 cycle int3 timer d &= 0xff; elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d); @@ -418,6 +450,9 @@ void s68k_reg_write8(u32 a, u32 d) return; } + if (a < 0x30) + Pico_mcd->m.m68k_comm_dirty |= (1 << a/2); + Pico_mcd->s68k_regs[a] = (u8) d; } diff --git a/pico/cd/memory_arm.s b/pico/cd/memory_arm.s index b9bbaec8..598bcd7d 100644 --- a/pico/cd/memory_arm.s +++ b/pico/cd/memory_arm.s @@ -216,6 +216,9 @@ m_m68k_read8_r0d: mov r0, r0, lsr #16 bx lr m_m68k_read8_hi: + push {r0,r1,lr} + bl m68k_comm_check + pop {r0,r1,lr} cmp r0, #0x30 movge r0, #0 bxeq lr diff --git a/pico/cd/pico.c b/pico/cd/pico.c index 0b6b943c..eabd2ea9 100644 --- a/pico/cd/pico.c +++ b/pico/cd/pico.c @@ -45,7 +45,7 @@ PICO_INTERNAL int PicoResetMCD(void) memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m)); memset(Pico_mcd->bios + 0x70, 0xff, 4); // reset hint vector (simplest way to implement reg6) - Pico_mcd->m.state_flags |= 1; // s68k reset pending + Pico_mcd->m.state_flags = 0; Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode with m68k access after reset Reset_CD(); @@ -219,7 +219,7 @@ static void pcd_run_events(unsigned int until) oldest, event_time_next); } -static void pcd_sync_s68k(unsigned int m68k_target) +void pcd_sync_s68k(unsigned int m68k_target) { #define now SekCycleCntS68k unsigned int s68k_target = diff --git a/pico/debug.c b/pico/debug.c index 26b63936..959331f8 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -45,9 +45,6 @@ char *PDebugMain(void) sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP; sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDone()); MVP; sprintf(dstrp, "M68k: PC: %06x, SR: %04x, irql: %i\n", SekPc, SekSr, SekIrqLevel); MVP; -#if defined(EMU_C68K) - sprintf(dstrp - 1, ", st_flg: %x\n", PicoCpuCM68k.state_flags); MVP; -#endif for (r = 0; r < 8; r++) { sprintf(dstrp, "d%i=%08x, a%i=%08x\n", r, SekDar(r), r, SekDar(r+8)); MVP; } diff --git a/pico/pico_int.h b/pico/pico_int.h index ef49295f..c23705b6 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -132,7 +132,11 @@ extern unsigned int SekCycleAim; // burn cycles while not in SekRun() and while in #define SekCyclesBurn(c) SekCycleCnt += c -#define SekCyclesBurnRun(c) SekCyclesLeft -= c +#define SekCyclesBurnRun(c) { \ + SekCyclesLeft -= c; \ + if (SekCyclesLeft < 0) \ + SekCyclesLeft = 0; \ +} // note: sometimes may extend timeslice to delay an irq #define SekEndRun(after) { \ @@ -383,9 +387,12 @@ struct mcd_misc unsigned short hint_vector; unsigned char busreq; unsigned char s68k_pend_ints; - unsigned int state_flags; // 04: emu state: reset_pending + unsigned int state_flags; // 04 unsigned int stopwatch_base_c; - unsigned int pad[3]; + unsigned int m68k_comm_dirty; + unsigned short m68k_poll_a; + unsigned short m68k_poll_cnt; + unsigned int pad; unsigned char bcram_reg; // 18: battery-backed RAM cart register unsigned char pad2; unsigned short pad3; @@ -624,6 +631,7 @@ extern unsigned int pcd_event_times[PCD_EVENT_COUNT]; void pcd_event_schedule(unsigned int now, enum pcd_event event, int after); void pcd_event_schedule_s68k(enum pcd_event event, int after); unsigned int pcd_cycles_m68k_to_s68k(unsigned int c); +void pcd_sync_s68k(unsigned int m68k_target); void pcd_state_loaded(void); // pico/pico.c From 08769494e89920b5987f10c9d15e33e4e0110930 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 27 Aug 2013 03:39:38 +0300 Subject: [PATCH 32/41] cd sync improvements, part2 --- pico/cd/memory.c | 178 ++++++++++++++++++++----------------------- pico/cd/memory_arm.s | 75 +++++++----------- pico/cd/pico.c | 32 +++++++- pico/pico_cmn.c | 16 ++-- pico/pico_int.h | 17 +++-- pico/videoport.c | 2 +- 6 files changed, 159 insertions(+), 161 deletions(-) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 743568ec..82e6d6dd 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -65,32 +65,23 @@ void PicoWriteS68k16_dec_m1b1(u32 a, u32 d); void PicoWriteS68k16_dec_m2b1(u32 a, u32 d); #endif -static void remap_prg_window(void); +static void remap_prg_window(int r3); static void remap_word_ram(int r3); // poller detection #define POLL_LIMIT 16 #define POLL_CYCLES 124 -unsigned int s68k_poll_adclk, s68k_poll_cnt; -void m68k_comm_check(u32 a) +u32 m68k_comm_check(u32 a, u32 d) { - pcd_sync_s68k(SekCyclesDone()); - /*if (Pico_mcd->m.m68k_comm_dirty & (1 << a/2)) { - Pico_mcd->m.m68k_comm_dirty &= ~(1 << a/2); - Pico_mcd->m.m68k_poll_a = Pico_mcd->m.m68k_poll_cnt = 0; - return; - } + pcd_sync_s68k(SekCyclesDone(), 0); if (a != Pico_mcd->m.m68k_poll_a) { Pico_mcd->m.m68k_poll_a = a; Pico_mcd->m.m68k_poll_cnt = 0; - return; + return d; } - if (++Pico_mcd->m.m68k_poll_cnt > 5) - SekCyclesBurnRun(122); - - elprintf(EL_CDPOLL, "m68k poll [%02x] %d %u", a, - Pico_mcd->m.m68k_poll_cnt, SekCyclesDone());*/ + Pico_mcd->m.m68k_poll_cnt++; + return d; } #ifndef _ASM_CD_MEMORY_C @@ -104,10 +95,9 @@ static u32 m68k_reg_read16(u32 a) d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens goto end; case 2: - m68k_comm_check(a); d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7); elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc); - goto end; + goto end_comm; case 4: d = Pico_mcd->s68k_regs[4]<<8; goto end; @@ -131,16 +121,17 @@ static u32 m68k_reg_read16(u32 a) if (a < 0x30) { // comm flag/cmd/status (0xE-0x2F) - m68k_comm_check(a); d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; - goto end; + goto end_comm; } elprintf(EL_UIO, "m68k_regs FIXME invalid read @ %02x", a); end: - return d; + +end_comm: + return m68k_comm_check(a, d); } #endif @@ -152,19 +143,24 @@ void m68k_reg_write8(u32 a, u32 d) u32 dold; a &= 0x3f; - Pico_mcd->m.m68k_poll_a = 0; + Pico_mcd->m.m68k_poll_a = + Pico_mcd->m.m68k_poll_cnt = 0; switch (a) { case 0: d &= 1; - if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { elprintf(EL_INTS, "m68k: s68k irq 2"); SekInterruptS68k(2); } + if (d && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN2)) { + elprintf(EL_INTS, "m68k: s68k irq 2"); + pcd_sync_s68k(SekCyclesDone(), 0); + SekInterruptS68k(2); + } return; case 1: d &= 3; elprintf(EL_CDREGS, "d m.busreq %u %u", d, Pico_mcd->m.busreq); if (d == Pico_mcd->m.busreq) return; - pcd_sync_s68k(SekCyclesDone()); + pcd_sync_s68k(SekCyclesDone(), 0); if ((Pico_mcd->m.busreq ^ d) & 1) { elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1)); @@ -177,7 +173,7 @@ void m68k_reg_write8(u32 a, u32 d) } if ((Pico_mcd->m.busreq ^ d) & 2) { elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1); - remap_prg_window(); + remap_prg_window(Pico_mcd->s68k_regs[3]); } Pico_mcd->m.busreq = d; return; @@ -194,24 +190,19 @@ void m68k_reg_write8(u32 a, u32 d) if (dold & 4) { // 1M mode d ^= 2; // writing 0 to DMNA actually sets it, 1 does nothing } else { - if ((d ^ dold) & d & 2) { // DMNA is being set + if ((d ^ dold) & d & 2) { // DMNA is being set dold &= ~1; // return word RAM to s68k /* Silpheed hack: bset(w3), r3, btst, bne, r3 */ SekEndRun(20+16+10+12+16); } } - Pico_mcd->s68k_regs[3] = (d & 0xc2) | (dold & 0x1f); + d = (d & 0xc2) | (dold & 0x1f); if ((d ^ dold) & 0xc0) { - elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3)); - remap_prg_window(); + elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i", + (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3)); + remap_prg_window(d); } -#ifdef USE_POLL_DETECT - if ((s68k_poll_adclk&0xfe) == 2 && s68k_poll_cnt > POLL_LIMIT) { - SekSetStopS68k(0); s68k_poll_adclk = 0; - elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a); - } -#endif - return; + goto write_comm; case 6: Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer return; @@ -220,34 +211,30 @@ void m68k_reg_write8(u32 a, u32 d) elprintf(EL_CDREGS, "hint vector set to %04x%04x", ((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]); return; - case 0xf: + case 0x0f: d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case) - case 0xe: - if (d != Pico_mcd->s68k_regs[0xe]) { - pcd_sync_s68k(SekCyclesDone()); - Pico_mcd->s68k_regs[0xe] = d; - } -#ifdef USE_POLL_DETECT - if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) { - SekSetStopS68k(0); s68k_poll_adclk = 0; - elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a); - } -#endif - return; + a = 0x0e; + case 0x0e: + goto write_comm; } - if ((a&0xf0) == 0x10) { - Pico_mcd->s68k_regs[a] = d; -#ifdef USE_POLL_DETECT - if ((a&0xfe) == (s68k_poll_adclk&0xfe) && s68k_poll_cnt > POLL_LIMIT) { - SekSetStopS68k(0); s68k_poll_adclk = 0; - elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a); - } -#endif - return; - } + if ((a&0xf0) == 0x10) + goto write_comm; elprintf(EL_UIO, "m68k FIXME: invalid write? [%02x] %02x", a, d); + return; + +write_comm: + if (d == Pico_mcd->s68k_regs[a]) + return; + + Pico_mcd->s68k_regs[a] = d; + pcd_sync_s68k(SekCyclesDone(), 0); + if (Pico_mcd->m.s68k_poll_a == a && Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) { + SekSetStopS68k(0); + Pico_mcd->m.s68k_poll_a = 0; + elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a); + } } #ifndef _ASM_CD_MEMORY_C @@ -256,24 +243,26 @@ static u32 s68k_poll_detect(u32 a, u32 d) { #ifdef USE_POLL_DETECT - // needed mostly for Cyclone, which doesn't always check it's cycle counter - if (SekIsStoppedS68k()) return d; - // polling detection - if (a == (s68k_poll_adclk&0xff)) { - unsigned int clkdiff = SekCyclesDoneS68k() - (s68k_poll_adclk>>8); + u32 cycles, cnt = 0; + if (SekIsStoppedS68k()) + return d; + + cycles = SekCyclesDoneS68k(); + if (a == Pico_mcd->m.s68k_poll_a) { + u32 clkdiff = cycles - Pico_mcd->m.s68k_poll_clk; if (clkdiff <= POLL_CYCLES) { - s68k_poll_cnt++; - //printf("-- diff: %u, cnt = %i\n", clkdiff, s68k_poll_cnt); - if (s68k_poll_cnt > POLL_LIMIT) { + cnt = Pico_mcd->m.s68k_poll_cnt + 1; + //printf("-- diff: %u, cnt = %i\n", clkdiff, cnt); + if (Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) { SekSetStopS68k(1); - elprintf(EL_CDPOLL, "s68k poll detected @ %06x, a=%02x", SekPcS68k, a); + elprintf(EL_CDPOLL, "s68k poll detected @ %06x, a=%02x", + SekPcS68k, a); } - s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a; - return d; } } - s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a; - s68k_poll_cnt = 0; + Pico_mcd->m.s68k_poll_a = a; + Pico_mcd->m.s68k_poll_clk = cycles; + Pico_mcd->m.s68k_poll_cnt = cnt; #endif return d; } @@ -384,7 +373,7 @@ void s68k_reg_write8(u32 a, u32 d) if (d & 1) d &= ~2; // DMNA clears } - break; + goto write_comm; } case 4: elprintf(EL_CDREGS, "s68k CDC dest: %x", d&7); @@ -405,9 +394,12 @@ void s68k_reg_write8(u32 a, u32 d) // does this also reset internal 384 cycle counter? Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k(); return; - case 0xe: + case 0x0e: + d &= 0xff; d = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair - break; + a = 0x0f; + case 0x0f: + goto write_comm; case 0x31: // 384 cycle int3 timer d &= 0xff; elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d); @@ -444,16 +436,23 @@ void s68k_reg_write8(u32 a, u32 d) return; } + if ((a&0x1f0) == 0x20) + goto write_comm; + if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42)) { elprintf(EL_UIO, "s68k FIXME: invalid write @ %02x?", a); return; } - if (a < 0x30) - Pico_mcd->m.m68k_comm_dirty |= (1 << a/2); - Pico_mcd->s68k_regs[a] = (u8) d; + return; + +write_comm: + Pico_mcd->s68k_regs[a] = (u8) d; + if (Pico_mcd->m.m68k_poll_cnt) + SekEndRunS68k(0); + Pico_mcd->m.m68k_poll_cnt = 0; } // ----------------------------------------------------------------- @@ -611,20 +610,10 @@ static void PicoWriteM68k16_io(u32 a, u32 d) { if ((a & 0xff00) == 0x2000) { // a12000 - a120ff elprintf(EL_CDREGS, "m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc); -/* TODO FIXME? - if (a == 0xe) { // special case, 2 byte writes would be handled differently - Pico_mcd->s68k_regs[0xe] = d >> 8; -#ifdef USE_POLL_DETECT - if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) { - SekSetStopS68k(0); s68k_poll_adclk = 0; - elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a); - } -#endif - return; - } -*/ + m68k_reg_write8(a, d >> 8); - m68k_reg_write8(a + 1, d & 0xff); + if ((a & 0x3e) != 0x0e) // special case + m68k_reg_write8(a + 1, d & 0xff); return; } @@ -965,11 +954,11 @@ static const void *s68k_dec_write16[2][4] = { // ----------------------------------------------------------------- -static void remap_prg_window(void) +static void remap_prg_window(int r3) { // PRG RAM if (Pico_mcd->m.busreq & 2) { - void *bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3] >> 6]; + void *bank = Pico_mcd->prg_ram_b[r3 >> 6]; cpu68k_map_all_ram(0x020000, 0x03ffff, bank, 0); } else { @@ -1034,7 +1023,7 @@ void pcd_state_loaded_mem(void) if (r3 & 4) // 1M mode? wram_2M_to_1M(Pico_mcd->word_ram2M); remap_word_ram(r3); - remap_prg_window(); + remap_prg_window(r3); // restore hint vector *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector; @@ -1144,9 +1133,6 @@ PICO_INTERNAL void PicoMemSetupCD(void) #ifdef EMU_M68K m68k_mem_setup_cd(); #endif - - // m68k_poll_addr = m68k_poll_cnt = 0; - s68k_poll_adclk = s68k_poll_cnt = 0; } diff --git a/pico/cd/memory_arm.s b/pico/cd/memory_arm.s index 598bcd7d..2fc74ca0 100644 --- a/pico/cd/memory_arm.s +++ b/pico/cd/memory_arm.s @@ -53,7 +53,6 @@ .extern m68k_reg_write8 .extern s68k_reg_read16 .extern s68k_reg_write8 -.extern s68k_poll_adclk .extern s68k_poll_detect .extern gfx_cd_read .extern gfx_cd_write16 @@ -62,6 +61,7 @@ .extern PicoRead16_io .extern PicoWrite8_io .extern PicoWrite16_io +.extern m68k_comm_check @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -174,17 +174,16 @@ m_m68k_read8_r02: add r1, r1, #0x110000 ldrb r0, [r1, #2] bx lr -m_m68k_read8_r03: - add r1, r1, #0x110000 - ldrb r0, [r1, #3] - add r1, r1, #0x002200 - ldr r1, [r1, #4] - and r0, r0, #0xc7 - tst r1, #2 @ DMNA pending? - bxeq lr - bic r0, r0, #1 - orr r0, r0, #2 - bx lr +m_m68k_read8_r03: @ FIXME: sync with C + add r2, r1, #0x110000 + ldrb r1, [r2, #3] + add r2, r2, #0x002200 + ldr r2, [r2, #4] + and r1, r1, #0xc7 + tst r2, #2 @ DMNA pending? + bicne r1, r1, #1 + orrne r1, r1, #2 + b m68k_comm_check m_m68k_read8_r04: add r1, r1, #0x110000 ldrb r0, [r1, #4] @@ -216,15 +215,12 @@ m_m68k_read8_r0d: mov r0, r0, lsr #16 bx lr m_m68k_read8_hi: - push {r0,r1,lr} - bl m68k_comm_check - pop {r0,r1,lr} cmp r0, #0x30 movge r0, #0 bxeq lr add r1, r1, #0x110000 - ldrb r0, [r1, r0] - bx lr + ldrb r1, [r1, r0] + b m68k_comm_check @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -273,19 +269,18 @@ m_m68k_read16_r00: and r0, r0, #0x04000000 @ we need irq2 mask state orr r0, r1, r0, lsr #11 bx lr -m_m68k_read16_r02: - add r1, r1, #0x110000 - ldrb r0, [r1, #2] - ldrb r2, [r1, #3] - add r1, r1, #0x002200 - ldr r1, [r1, #4] +m_m68k_read16_r02: @ FIXME: out of sync from C + add r3, r1, #0x110000 + ldrb r1, [r3, #2] + ldrb r2, [r3, #3] + add r3, r3, #0x002200 + ldr r3, [r3, #4] and r2, r2, #0xc7 - orr r0, r2, r0, lsl #8 - tst r1, #2 @ DMNA pending? - bxeq lr - bic r0, r0, #1 - orr r0, r0, #2 - bx lr + orr r1, r2, r1, lsl #8 + tst r3, #2 @ DMNA pending? + bicne r1, r1, #1 + orrne r1, r1, #2 + b m68k_comm_check m_m68k_read16_r04: add r1, r1, #0x110000 ldrb r0, [r1, #4] @@ -309,10 +304,10 @@ m_m68k_read16_hi: ldrlth r1, [r1, r0] movge r0, #0 bxge lr - mov r0, r1, lsr #8 + mov r2, r1, lsr #8 and r1, r1, #0xff - orr r0, r0, r1, lsl #8 - bx lr + orr r1, r2, r1, lsl #8 + b m68k_comm_check @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -380,22 +375,8 @@ m_m68k_write16_regs: b m68k_reg_write8 m_m68k_write16_regs_spec: @ special case - ldr r2, =(Pico+0x22200) - ldr r3, =s68k_poll_adclk - mov r0, #0x110000 - ldr r2, [r2] - add r0, r0, #0x00000e mov r1, r1, lsr #8 - strb r1, [r2, r0] @ if (a == 0xe) s68k_regs[0x0e] = d >> 8; - ldr r2, [r3] - mov r1, #0 - and r2, r2, #0xfe - cmp r2, #0x0e - bxne lr - ldr r0, =PicoCpuCS68k - str r1, [r0, #0x58] @ push s68k out of stopped state - str r1, [r3] - bx lr + b m68k_reg_write8 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ diff --git a/pico/cd/pico.c b/pico/cd/pico.c index eabd2ea9..539d157e 100644 --- a/pico/cd/pico.c +++ b/pico/cd/pico.c @@ -219,19 +219,20 @@ static void pcd_run_events(unsigned int until) oldest, event_time_next); } -void pcd_sync_s68k(unsigned int m68k_target) +int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync) { #define now SekCycleCntS68k unsigned int s68k_target = (unsigned long long)m68k_target * m68k_cycle_mult >> 16; unsigned int target; - elprintf(EL_CD, "s68k sync to %u/%u", m68k_target, s68k_target); + elprintf(EL_CD, "s68k sync to %u, %u->%u", + m68k_target, now, s68k_target); if ((Pico_mcd->m.busreq & 3) != 1) { /* busreq/reset */ SekCycleCntS68k = SekCycleAimS68k = s68k_target; pcd_run_events(m68k_target); - return; + return 0; } while (CYCLES_GT(s68k_target, now)) { @@ -243,13 +244,36 @@ void pcd_sync_s68k(unsigned int m68k_target) target = event_time_next; SekRunS68k(target); + if (m68k_poll_sync && Pico_mcd->m.m68k_poll_cnt == 0) + break; } + + return s68k_target - now; #undef now } +static void SekSyncM68k(void); + +static void pcd_run_cpus(int m68k_cycles) +{ + SekCycleAim += m68k_cycles; + if (Pico_mcd->m.m68k_poll_cnt >= 16 && !SekShouldInterrupt()) { + int s68k_left = pcd_sync_s68k(SekCycleAim, 1); + if (s68k_left <= 0) { + elprintf(EL_CDPOLL, "m68k poll [%02x] %d @%06x", + Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc); + SekCycleCnt = SekCycleAim; + return; + } + SekCycleCnt = SekCycleAim - (s68k_left * 40220 >> 16); + } + + SekSyncM68k(); +} + #define PICO_CD #define CPUS_RUN(m68k_cycles) \ - SekRunM68k(m68k_cycles) + pcd_run_cpus(m68k_cycles) #include "../pico_cmn.c" diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 98dfa936..bdf48cfa 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -22,13 +22,13 @@ SekRunM68k(m68k_cycles) #endif -static __inline void SekRunM68k(int cyc) +// sync m68k to SekCycleAim +static void SekSyncM68k(void) { int cyc_do; pprof_start(m68k); pevt_log_m68k_o(EVT_RUN_START); - SekCycleAim += cyc; while ((cyc_do = SekCycleAim - SekCycleCnt) > 0) { SekCycleCnt += cyc_do; @@ -50,6 +50,12 @@ static __inline void SekRunM68k(int cyc) pprof_end(m68k); } +static inline void SekRunM68k(int cyc) +{ + SekCycleAim += cyc; + SekSyncM68k(); +} + static int PicoFrameHints(void) { struct PicoVideo *pv=&Pico.video; @@ -142,7 +148,7 @@ static int PicoFrameHints(void) if (ym2612.dacen && PsndDacLine <= y) PsndDoDAC(y); #ifdef PICO_CD - pcd_sync_s68k(cycles); + pcd_sync_s68k(cycles, 0); #endif #ifdef PICO_32X p32x_sync_sh2s(cycles); @@ -210,7 +216,7 @@ static int PicoFrameHints(void) } #ifdef PICO_CD - pcd_sync_s68k(cycles); + pcd_sync_s68k(cycles, 0); #endif #ifdef PICO_32X p32x_sync_sh2s(cycles); @@ -262,7 +268,7 @@ static int PicoFrameHints(void) PsndDoDAC(lines-1); #ifdef PICO_CD - pcd_sync_s68k(cycles); + pcd_sync_s68k(cycles, 0); #endif #ifdef PICO_32X p32x_sync_sh2s(cycles); diff --git a/pico/pico_int.h b/pico/pico_int.h index c23705b6..9b597d81 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -49,7 +49,7 @@ extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k; #define SekSetStopS68k(x) { PicoCpuCS68k.state_flags&=~1; if (x) { PicoCpuCS68k.state_flags|=1; PicoCpuCS68k.cycles=0; } } #define SekIsStoppedM68k() (PicoCpuCM68k.state_flags&1) #define SekIsStoppedS68k() (PicoCpuCS68k.state_flags&1) -#define SekShouldInterrupt (PicoCpuCM68k.irq > (PicoCpuCM68k.srh&7)) +#define SekShouldInterrupt() (PicoCpuCM68k.irq > (PicoCpuCM68k.srh&7)) #define SekInterrupt(i) PicoCpuCM68k.irq=i #define SekIrqLevel PicoCpuCM68k.irq @@ -77,7 +77,7 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; } #define SekIsStoppedM68k() (PicoCpuFM68k.execinfo&FM68K_HALTED) #define SekIsStoppedS68k() (PicoCpuFS68k.execinfo&FM68K_HALTED) -#define SekShouldInterrupt fm68k_would_interrupt() +#define SekShouldInterrupt() fm68k_would_interrupt() #define SekInterrupt(irq) PicoCpuFM68k.interrupts[0]=irq #define SekIrqLevel PicoCpuFM68k.interrupts[0] @@ -106,7 +106,7 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; } #define SekIsStoppedM68k() (PicoCpuMM68k.stopped==STOP_LEVEL_STOP) #define SekIsStoppedS68k() (PicoCpuMS68k.stopped==STOP_LEVEL_STOP) -#define SekShouldInterrupt (CPU_INT_LEVEL > FLAG_INT_MASK) +#define SekShouldInterrupt() (CPU_INT_LEVEL > FLAG_INT_MASK) #define SekInterrupt(irq) { \ void *oldcontext = m68ki_cpu_p; \ @@ -389,10 +389,11 @@ struct mcd_misc unsigned char s68k_pend_ints; unsigned int state_flags; // 04 unsigned int stopwatch_base_c; - unsigned int m68k_comm_dirty; unsigned short m68k_poll_a; unsigned short m68k_poll_cnt; - unsigned int pad; + unsigned short s68k_poll_a; + unsigned short s68k_poll_cnt; + unsigned int s68k_poll_clk; unsigned char bcram_reg; // 18: battery-backed RAM cart register unsigned char pad2; unsigned short pad3; @@ -631,7 +632,7 @@ extern unsigned int pcd_event_times[PCD_EVENT_COUNT]; void pcd_event_schedule(unsigned int now, enum pcd_event event, int after); void pcd_event_schedule_s68k(enum pcd_event event, int after); unsigned int pcd_cycles_m68k_to_s68k(unsigned int c); -void pcd_sync_s68k(unsigned int m68k_target); +int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync); void pcd_state_loaded(void); // pico/pico.c @@ -935,9 +936,9 @@ void pevt_log(unsigned int cycles, enum evt_cpu c, enum evt e); void pevt_dump(void); #define pevt_log_m68k(e) \ - pevt_log(SekCyclesDoneT(), EVT_M68K, e) + pevt_log(SekCyclesDone(), EVT_M68K, e) #define pevt_log_m68k_o(e) \ - pevt_log(SekCyclesDoneT2(), EVT_M68K, e) + pevt_log(SekCyclesDone(), EVT_M68K, e) #define pevt_log_sh2(sh2, e) \ pevt_log(sh2_cycles_done_m68k(sh2), EVT_MSH2 + (sh2)->is_slave, e) #define pevt_log_sh2_o(sh2, e) \ diff --git a/pico/videoport.c b/pico/videoport.c index ec68e7f6..42f55c82 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -423,7 +423,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) update_irq: #ifndef EMU_CORE_DEBUG // update IRQ level - if (!SekShouldInterrupt) // hack + if (!SekShouldInterrupt()) // hack { int lines, pints, irq=0; lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); From 89dbbf2b2fe885c9f443178c1f1350567e92160b Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 28 Aug 2013 02:21:57 +0300 Subject: [PATCH 33/41] rename cd/pico.c -> cd/mcd.c --- Makefile | 2 +- pico/cd/{pico.c => mcd.c} | 0 pico/cd/{pico_arm.s => mcd_arm.s} | 0 pico/pico.h | 2 +- pico/pico_cmn.c | 4 ++-- pico/pico_int.h | 2 +- platform/common/common.mak | 8 +++++--- 7 files changed, 10 insertions(+), 8 deletions(-) rename pico/cd/{pico.c => mcd.c} (100%) rename pico/cd/{pico_arm.s => mcd_arm.s} (100%) diff --git a/Makefile b/Makefile index 439a66fd..d094104c 100644 --- a/Makefile +++ b/Makefile @@ -183,7 +183,7 @@ pico/cd/gfx_cd.o: CFLAGS += -fno-strict-aliasing pico/carthw/svp/compiler.o : cpu/drc/emit_$(ARCH).c cpu/sh2/compiler.o : cpu/drc/emit_$(ARCH).c cpu/sh2/mame/sh2pico.o : cpu/sh2/mame/sh2.c -pico/pico.o pico/cd/pico.o pico/32x/32x.o : pico/pico_cmn.c pico/pico_int.h +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/pico_int.h pico/memory.h cpu/fame/famec.o: cpu/fame/famec.c cpu/fame/famec_opcodes.h diff --git a/pico/cd/pico.c b/pico/cd/mcd.c similarity index 100% rename from pico/cd/pico.c rename to pico/cd/mcd.c diff --git a/pico/cd/pico_arm.s b/pico/cd/mcd_arm.s similarity index 100% rename from pico/cd/pico_arm.s rename to pico/cd/mcd_arm.s diff --git a/pico/pico.h b/pico/pico.h index e1bcf03d..43217dcc 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -99,7 +99,7 @@ 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); -// cd/Pico.c +// cd/mcd.c extern void (*PicoMCDopenTray)(void); extern void (*PicoMCDcloseTray)(void); extern int PicoCDBuffers; diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index bdf48cfa..af696e57 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -1,6 +1,6 @@ /* - * common code for pico.c and cd/pico.c - * (C) notaz, 2007-2009 + * common code for base/cd/32x + * (C) notaz, 2007-2009,2013 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. diff --git a/pico/pico_int.h b/pico/pico_int.h index 9b597d81..be56abd0 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -607,7 +607,7 @@ PICO_INTERNAL int CheckDMA(void); PICO_INTERNAL void PicoDetectRegion(void); PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done); -// cd/pico.c +// cd/mcd.c #define PCDS_IEN1 (1<<1) #define PCDS_IEN2 (1<<2) #define PCDS_IEN3 (1<<3) diff --git a/platform/common/common.mak b/platform/common/common.mak index a365abc6..da5a52e4 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -63,7 +63,7 @@ SRCS_COMMON += $(R)pico/cd/misc_arm.s endif ifeq "$(asm_cdpico)" "1" DEFINES += _ASM_CD_PICO_C -SRCS_COMMON += $(R)pico/cd/pico_arm.s +SRCS_COMMON += $(R)pico/cd/mcd_arm.s endif ifeq "$(asm_cdmemory)" "1" DEFINES += _ASM_CD_MEMORY_C @@ -92,7 +92,7 @@ else DEFINES += NO_SMS endif # CD -SRCS_COMMON += $(R)pico/cd/pico.c $(R)pico/cd/memory.c $(R)pico/cd/sek.c \ +SRCS_COMMON += $(R)pico/cd/mcd.c $(R)pico/cd/memory.c $(R)pico/cd/sek.c \ $(R)pico/cd/LC89510.c $(R)pico/cd/cd_sys.c $(R)pico/cd/cd_file.c \ $(R)pico/cd/cue.c $(R)pico/cd/gfx_cd.c $(R)pico/cd/misc.c \ $(R)pico/cd/pcm.c $(R)pico/cd/buffering.c @@ -184,10 +184,12 @@ $(FR)cpu/cyclone/Cyclone.h: @echo "Cyclone submodule is missing, please run 'git submodule update --init'" @false -$(FR)cpu/cyclone/Cyclone.s: +$(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/cyclone_config.h @echo building Cyclone... @make -C $(R)cpu/cyclone/ CONFIG_FILE=../cyclone_config.h +$(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/cyclone/*.cpp $(FR)cpu/cyclone/*.h + $(FR)cpu/musashi/m68kops.c: @make -C $(R)cpu/musashi From ba6e8bfd4b707aab042e47bc3e2a14f70be01075 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 28 Aug 2013 03:07:33 +0300 Subject: [PATCH 34/41] cd: clean up dmna handling, stuff --- pico/cd/mcd.c | 17 +++++++++-- pico/cd/memory.c | 73 +++++++++++++++++++++++++----------------------- pico/pico_int.h | 2 +- 3 files changed, 54 insertions(+), 38 deletions(-) diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 539d157e..82ae1bc6 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -252,15 +252,18 @@ int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync) #undef now } +#define pcd_run_cpus_normal pcd_run_cpus +//#define pcd_run_cpus_lockstep pcd_run_cpus + static void SekSyncM68k(void); -static void pcd_run_cpus(int m68k_cycles) +static inline void pcd_run_cpus_normal(int m68k_cycles) { SekCycleAim += m68k_cycles; if (Pico_mcd->m.m68k_poll_cnt >= 16 && !SekShouldInterrupt()) { int s68k_left = pcd_sync_s68k(SekCycleAim, 1); if (s68k_left <= 0) { - elprintf(EL_CDPOLL, "m68k poll [%02x] %d @%06x", + elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x", Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc); SekCycleCnt = SekCycleAim; return; @@ -271,6 +274,16 @@ static void pcd_run_cpus(int m68k_cycles) SekSyncM68k(); } +static inline void pcd_run_cpus_lockstep(int m68k_cycles) +{ + unsigned int target = SekCycleAim + m68k_cycles; + do { + SekCycleAim += 8; + SekSyncM68k(); + pcd_sync_s68k(SekCycleAim, 0); + } while (CYCLES_GT(target, SekCycleAim)); +} + #define PICO_CD #define CPUS_RUN(m68k_cycles) \ pcd_run_cpus(m68k_cycles) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 82e6d6dd..f8ffaeb0 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -184,24 +184,24 @@ void m68k_reg_write8(u32 a, u32 d) case 3: dold = Pico_mcd->s68k_regs[3]; elprintf(EL_CDREG3, "m68k_regs w3: %02x @%06x", (u8)d, SekPc); - //if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2); - //if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") : - // ((d&2) ? "word ram to s68k" : "word ram to m68k")); - if (dold & 4) { // 1M mode - d ^= 2; // writing 0 to DMNA actually sets it, 1 does nothing - } else { - if ((d ^ dold) & d & 2) { // DMNA is being set - dold &= ~1; // return word RAM to s68k - /* Silpheed hack: bset(w3), r3, btst, bne, r3 */ - SekEndRun(20+16+10+12+16); - } - } - d = (d & 0xc2) | (dold & 0x1f); if ((d ^ dold) & 0xc0) { elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3)); remap_prg_window(d); } + + // 2M mode state is tracked regardless of current mode + if (d & 2) { + Pico_mcd->m.dmna_ret_2m |= 2; + Pico_mcd->m.dmna_ret_2m &= ~1; + } + if (dold & 4) { // 1M mode + d ^= 2; // 0 sets DMNA, 1 does nothing + d = (d & 0xc2) | (dold & 0x1f); + } + else + d = (d & 0xc0) | (dold & 0x1c) | Pico_mcd->m.dmna_ret_2m; + goto write_comm; case 6: Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer @@ -343,35 +343,34 @@ void s68k_reg_write8(u32 a, u32 d) elprintf(EL_CDREG3, "s68k_regs w3: %02x @%06x", (u8)d, SekPcS68k); d &= 0x1d; d |= dold & 0xc2; + + // 2M mode state + if (d & 1) { + Pico_mcd->m.dmna_ret_2m |= 1; + Pico_mcd->m.dmna_ret_2m &= ~2; // DMNA clears + } + if (d & 4) { - if ((d ^ dold) & 0x1d) { - d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit - remap_word_ram(d); - } if (!(dold & 4)) { elprintf(EL_CDREG3, "wram mode 2M->1M"); wram_2M_to_1M(Pico_mcd->word_ram2M); } + + if ((d ^ dold) & 0x1d) + remap_word_ram(d); + + if ((d ^ dold) & 0x05) + d &= ~2; // clear DMNA - swap complete } else { if (dold & 4) { elprintf(EL_CDREG3, "wram mode 1M->2M"); - if (!(d&1)) { // it didn't set the ret bit, which means it doesn't want to give WRAM to m68k - d &= ~3; - d |= (dold&1) ? 2 : 1; // then give it to the one which had bank0 in 1M mode - } wram_1M_to_2M(Pico_mcd->word_ram2M); remap_word_ram(d); } - // s68k can only set RET, writing 0 has no effect - else if ((dold ^ d) & d & 1) { // RET being set - SekEndRunS68k(20+16+10+12+16); // see DMNA case - } else - d |= dold & 1; - if (d & 1) - d &= ~2; // DMNA clears + d = (d & ~3) | Pico_mcd->m.dmna_ret_2m; } goto write_comm; } @@ -806,20 +805,22 @@ static u32 PicoReadS68k8_pr(u32 a) // regs if ((a & 0xfe00) == 0x8000) { a &= 0x1ff; - elprintf(EL_CDREGS, "s68k_regs r8: [%02x] @ %06x", a, SekPcS68k); if (a >= 0x0e && a < 0x30) { d = Pico_mcd->s68k_regs[a]; s68k_poll_detect(a, d); - elprintf(EL_CDREGS, "ret = %02x", (u8)d); - return d; + goto regs_done; } else if (a >= 0x58 && a < 0x68) d = gfx_cd_read(a & ~1); else d = s68k_reg_read16(a & ~1); if (!(a & 1)) d >>= 8; - elprintf(EL_CDREGS, "ret = %02x", (u8)d); - return d & 0xff; + +regs_done: + d &= 0xff; + elprintf(EL_CDREGS, "s68k_regs r8: [%02x] %02x @ %06x", + a, d, SekPcS68k); + return d; } // PCM @@ -847,11 +848,12 @@ static u32 PicoReadS68k16_pr(u32 a) // regs if ((a & 0xfe00) == 0x8000) { a &= 0x1fe; - elprintf(EL_CDREGS, "s68k_regs r16: [%02x] @ %06x", a, SekPcS68k); if (0x58 <= a && a < 0x68) d = gfx_cd_read(a); else d = s68k_reg_read16(a); - elprintf(EL_CDREGS, "ret = %04x", d); + + elprintf(EL_CDREGS, "s68k_regs r16: [%02x] %04x @ %06x", + a, d, SekPcS68k); return d; } @@ -1024,6 +1026,7 @@ void pcd_state_loaded_mem(void) wram_2M_to_1M(Pico_mcd->word_ram2M); remap_word_ram(r3); remap_prg_window(r3); + Pico_mcd->m.dmna_ret_2m &= 3; // restore hint vector *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector; diff --git a/pico/pico_int.h b/pico/pico_int.h index be56abd0..2053ac60 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -395,7 +395,7 @@ struct mcd_misc unsigned short s68k_poll_cnt; unsigned int s68k_poll_clk; unsigned char bcram_reg; // 18: battery-backed RAM cart register - unsigned char pad2; + unsigned char dmna_ret_2m; unsigned short pad3; int pad4[9]; }; From 59991f1117c8d71f452a0f17584138c73c4fd65d Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 29 Aug 2013 00:42:38 +0300 Subject: [PATCH 35/41] cd: some fixes --- pico/cd/cd_sys.c | 4 ++++ pico/cd/memory.c | 13 +++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pico/cd/cd_sys.c b/pico/cd/cd_sys.c index 06cf3f83..6b92d568 100644 --- a/pico/cd/cd_sys.c +++ b/pico/cd/cd_sys.c @@ -471,6 +471,10 @@ PICO_INTERNAL int Play_CDD_c3(void) if (delay < 0) delay = -delay; delay >>= 12; + // based on genplys GX + if (delay < 13) + delay = 13; + Pico_mcd->scd.Cur_LBA = new_lba; CDC_Update_Header(); diff --git a/pico/cd/memory.c b/pico/cd/memory.c index f8ffaeb0..1d669a29 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -212,7 +212,6 @@ void m68k_reg_write8(u32 a, u32 d) ((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]); return; case 0x0f: - d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case) a = 0x0e; case 0x0e: goto write_comm; @@ -394,8 +393,6 @@ void s68k_reg_write8(u32 a, u32 d) Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k(); return; case 0x0e: - d &= 0xff; - d = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair a = 0x0f; case 0x0f: goto write_comm; @@ -646,17 +643,17 @@ static void s68k_unmapped_write16(u32 a, u32 d) elprintf(EL_UIO, "s68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); } -// PRG RAM protected range (000000 - 00ff00)? +// PRG RAM protected range (000000 - 01fdff)? // XXX verify: ff00 or 1fe00 max? static void PicoWriteS68k8_prgwp(u32 a, u32 d) { - if (a >= (Pico_mcd->s68k_regs[2] << 8)) + if (a >= (Pico_mcd->s68k_regs[2] << 9)) Pico_mcd->prg_ram[a ^ 1] = d; } static void PicoWriteS68k16_prgwp(u32 a, u32 d) { - if (a >= (Pico_mcd->s68k_regs[2] << 8)) + if (a >= (Pico_mcd->s68k_regs[2] << 9)) *(u16 *)(Pico_mcd->prg_ram + a) = d; } @@ -1067,8 +1064,8 @@ PICO_INTERNAL void PicoMemSetupCD(void) cpu68k_map_set(s68k_read16_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0); cpu68k_map_set(s68k_write8_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0); cpu68k_map_set(s68k_write16_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0); - cpu68k_map_set(s68k_write8_map, 0x000000, 0x00ffff, PicoWriteS68k8_prgwp, 1); - cpu68k_map_set(s68k_write16_map, 0x000000, 0x00ffff, PicoWriteS68k16_prgwp, 1); + cpu68k_map_set(s68k_write8_map, 0x000000, 0x01ffff, PicoWriteS68k8_prgwp, 1); + cpu68k_map_set(s68k_write16_map, 0x000000, 0x01ffff, PicoWriteS68k16_prgwp, 1); // BRAM cpu68k_map_set(s68k_read8_map, 0xfe0000, 0xfeffff, PicoReadS68k8_bram, 1); From 4fb435550b3f51abbfc8bb9ff25e0c110c7d7fa2 Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 29 Aug 2013 03:43:56 +0300 Subject: [PATCH 36/41] cd: fix busreq and reset --- pico/cd/mcd.c | 23 ++++++++++++++--------- pico/cd/memory.c | 49 ++++++++++++++++++++++++++---------------------- pico/pico.c | 4 ---- pico/pico_int.h | 4 +++- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 82ae1bc6..8b807d30 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -35,19 +35,24 @@ PICO_INTERNAL void PicoPowerMCD(void) memset(Pico_mcd->word_ram2M, 0, sizeof(Pico_mcd->word_ram2M)); memset(Pico_mcd->pcm_ram, 0, sizeof(Pico_mcd->pcm_ram)); memset(Pico_mcd->bram, 0, sizeof(Pico_mcd->bram)); - memcpy(Pico_mcd->bram + sizeof(Pico_mcd->bram) - fmt_size, formatted_bram, fmt_size); -} - -PICO_INTERNAL int PicoResetMCD(void) -{ + memcpy(Pico_mcd->bram + sizeof(Pico_mcd->bram) - fmt_size, + formatted_bram, fmt_size); memset(Pico_mcd->s68k_regs, 0, sizeof(Pico_mcd->s68k_regs)); memset(&Pico_mcd->pcm, 0, sizeof(Pico_mcd->pcm)); memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m)); - memset(Pico_mcd->bios + 0x70, 0xff, 4); // reset hint vector (simplest way to implement reg6) - Pico_mcd->m.state_flags = 0; - Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode with m68k access after reset + // cold reset state (tested) + Pico_mcd->m.state_flags = PCD_ST_S68K_RST; + Pico_mcd->m.busreq = 2; // busreq on, s68k in reset + Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode, m68k access + Pico_mcd->s68k_regs[6] = 0xff; + Pico_mcd->s68k_regs[7] = 0xff; + memset(Pico_mcd->bios + 0x70, 0xff, 4); +} +PICO_INTERNAL int PicoResetMCD(void) +{ + // ?? Reset_CD(); LC89510_Reset(); gfx_cd_reset(); @@ -229,7 +234,7 @@ int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync) elprintf(EL_CD, "s68k sync to %u, %u->%u", m68k_target, now, s68k_target); - if ((Pico_mcd->m.busreq & 3) != 1) { /* busreq/reset */ + if (Pico_mcd->m.busreq != 1) { /* busreq/reset */ SekCycleCntS68k = SekCycleAimS68k = s68k_target; pcd_run_events(m68k_target); return 0; diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 1d669a29..1064b91c 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -65,8 +65,8 @@ void PicoWriteS68k16_dec_m1b1(u32 a, u32 d); void PicoWriteS68k16_dec_m2b1(u32 a, u32 d); #endif -static void remap_prg_window(int r3); -static void remap_word_ram(int r3); +static void remap_prg_window(u32 r1, u32 r3); +static void remap_word_ram(u32 r3); // poller detection #define POLL_LIMIT 16 @@ -87,12 +87,14 @@ u32 m68k_comm_check(u32 a, u32 d) #ifndef _ASM_CD_MEMORY_C static u32 m68k_reg_read16(u32 a) { - u32 d=0; + u32 d = 0; a &= 0x3e; switch (a) { case 0: - d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens + // here IFL2 is always 0, just like in Gens + d = ((Pico_mcd->s68k_regs[0x33] << 13) & 0x8000) + | Pico_mcd->m.busreq; goto end; case 2: d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7); @@ -157,23 +159,26 @@ void m68k_reg_write8(u32 a, u32 d) return; case 1: d &= 3; - elprintf(EL_CDREGS, "d m.busreq %u %u", d, Pico_mcd->m.busreq); - if (d == Pico_mcd->m.busreq) + dold = Pico_mcd->m.busreq; + if (!(d & 1)) + d |= 2; // verified: can't release bus on reset + if (dold == d) return; + pcd_sync_s68k(SekCyclesDone(), 0); - if ((Pico_mcd->m.busreq ^ d) & 1) { + if ((dold ^ d) & 1) elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1)); - if (!(d & 1)) - d |= 2; // verified: reset also gives bus - else { - elprintf(EL_CDREGS, "m68k: resetting s68k"); - SekResetS68k(); - } + if (!(d & 1)) + Pico_mcd->m.state_flags |= PCD_ST_S68K_RST; + else if (d == 1 && (Pico_mcd->m.state_flags & PCD_ST_S68K_RST)) { + Pico_mcd->m.state_flags &= ~PCD_ST_S68K_RST; + elprintf(EL_CDREGS, "m68k: resetting s68k"); + SekResetS68k(); } - if ((Pico_mcd->m.busreq ^ d) & 2) { + if ((dold ^ d) & 2) { elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1); - remap_prg_window(Pico_mcd->s68k_regs[3]); + remap_prg_window(d, Pico_mcd->s68k_regs[3]); } Pico_mcd->m.busreq = d; return; @@ -187,7 +192,7 @@ void m68k_reg_write8(u32 a, u32 d) if ((d ^ dold) & 0xc0) { elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3)); - remap_prg_window(d); + remap_prg_window(Pico_mcd->m.busreq, d); } // 2M mode state is tracked regardless of current mode @@ -953,11 +958,11 @@ static const void *s68k_dec_write16[2][4] = { // ----------------------------------------------------------------- -static void remap_prg_window(int r3) +static void remap_prg_window(u32 r1, u32 r3) { // PRG RAM - if (Pico_mcd->m.busreq & 2) { - void *bank = Pico_mcd->prg_ram_b[r3 >> 6]; + if (r1 & 2) { + void *bank = Pico_mcd->prg_ram_b[(r3 >> 6) & 3]; cpu68k_map_all_ram(0x020000, 0x03ffff, bank, 0); } else { @@ -965,7 +970,7 @@ static void remap_prg_window(int r3) } } -static void remap_word_ram(int r3) +static void remap_word_ram(u32 r3) { void *bank; @@ -1016,13 +1021,13 @@ static void remap_word_ram(int r3) void pcd_state_loaded_mem(void) { - int r3 = Pico_mcd->s68k_regs[3]; + u32 r3 = Pico_mcd->s68k_regs[3]; /* after load events */ if (r3 & 4) // 1M mode? wram_2M_to_1M(Pico_mcd->word_ram2M); remap_word_ram(r3); - remap_prg_window(r3); + remap_prg_window(Pico_mcd->m.busreq, r3); Pico_mcd->m.dmna_ret_2m &= 3; // restore hint vector diff --git a/pico/pico.c b/pico/pico.c index bd4621b3..696743f6 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -171,10 +171,6 @@ int PicoReset(void) SekSetRealTAS(PicoAHW & PAHW_MCD); SekCycleCnt = SekCycleAim = 0; - if (PicoAHW & PAHW_MCD) - // needed for MCD to reset properly, probably some bug hides behind this.. - memset(Pico.ioports,0,sizeof(Pico.ioports)); - Pico.m.dirtyPal = 1; Pico.m.z80_bank68k = 0; diff --git a/pico/pico_int.h b/pico/pico_int.h index 2053ac60..690c233c 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -382,10 +382,12 @@ struct mcd_pcm } ch[8]; }; +#define PCD_ST_S68K_RST 1 + struct mcd_misc { unsigned short hint_vector; - unsigned char busreq; + unsigned char busreq; // not s68k_regs[1] unsigned char s68k_pend_ints; unsigned int state_flags; // 04 unsigned int stopwatch_base_c; From cfae1ae17956a94d7deae336ce6b9571b3f825f1 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 30 Aug 2013 01:35:47 +0300 Subject: [PATCH 37/41] fix array-out-of-bounds issue --- pico/state.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pico/state.c b/pico/state.c index a3695970..f9a7f839 100644 --- a/pico/state.c +++ b/pico/state.c @@ -180,7 +180,7 @@ typedef enum { CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt) } chunk_name_e; -static const char * const chunk_names[] = { +static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = { "INVALID!", "M68K state", "RAM", @@ -237,7 +237,7 @@ static int write_chunk(chunk_name_e name, int len, void *data, void *file) } #define CHECKED_WRITE(name,len,data) { \ - if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT) { \ + if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \ strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \ PicoStateProgressCB(sbuff); \ } \ @@ -245,7 +245,7 @@ static int write_chunk(chunk_name_e name, int len, void *data, void *file) } #define CHECKED_WRITE_BUFF(name,buff) { \ - if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT) { \ + if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \ strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \ PicoStateProgressCB(sbuff); \ } \ From b59172e3d428eb6848e6874861804c79bbc9d1ec Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 30 Aug 2013 03:54:48 +0300 Subject: [PATCH 38/41] frontend: new sync code should fix video drift/desync on pandora --- platform/common/config_file.c | 5 -- platform/common/emu.c | 158 ++++++++++++++++------------------ platform/common/emu.h | 2 +- platform/common/main.c | 1 - platform/common/menu_pico.c | 5 +- 5 files changed, 77 insertions(+), 94 deletions(-) diff --git a/platform/common/config_file.c b/platform/common/config_file.c index f058fbd8..f8f7fdf1 100644 --- a/platform/common/config_file.c +++ b/platform/common/config_file.c @@ -308,11 +308,6 @@ static int custom_read(menu_entry *me, const char *var, const char *val) return 0; return 1; - case MA_OPT2_GAMMA: - if (strcasecmp(var, "Gamma correction") != 0) return 0; - currentConfig.gamma = (int) (atof(val) * 100.0); - return 1; - case MA_CDOPT_READAHEAD: if (strcasecmp(var, "ReadAhead buffer") != 0) return 0; PicoCDBuffers = atoi(val) / 2; diff --git a/platform/common/emu.c b/platform/common/emu.c index ee216fe2..8bc83af4 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -43,7 +43,7 @@ void *g_screen_ptr; int g_screen_width = 320; int g_screen_height = 240; -char *PicoConfigFile = "config.cfg"; +const char *PicoConfigFile = "config2.cfg"; currentConfig_t currentConfig, defaultConfig; int state_slot = 0; int config_slot = 0, config_slot_current = 0; @@ -1276,31 +1276,26 @@ static void emu_loop_prep(void) filter_old = currentConfig.filter; } +printf("-- gamma %d\n", currentConfig.gamma); plat_target_gamma_set(currentConfig.gamma, 0); pemu_loop_prep(); } -static void skip_frame(int do_audio) -{ - PicoSkipFrame = do_audio ? 1 : 2; - PicoFrame(); - PicoSkipFrame = 0; -} - /* our tick here is 1 us right now */ #define ms_to_ticks(x) (unsigned int)(x * 1000) #define get_ticks() plat_get_ticks_us() void emu_loop(void) { - int pframes_done; /* "period" frames, used for sync */ int frames_done, frames_shown; /* actual frames for fps counter */ - int target_fps, target_frametime; - unsigned int timestamp_base = 0, timestamp_fps; + int target_frametime_x3; + unsigned int timestamp_x3 = 0; + unsigned int timestamp_aim_x3 = 0; + unsigned int timestamp_fps_x3 = 0; char *notice_msg = NULL; char fpsbuff[24]; - int i; + int fskip_cnt = 0; fpsbuff[0] = 0; @@ -1315,45 +1310,47 @@ void emu_loop(void) pemu_sound_start(); /* number of ticks per frame */ - if (Pico.m.pal) { - target_fps = 50; - target_frametime = ms_to_ticks(1000) / 50; - } else { - target_fps = 60; - target_frametime = ms_to_ticks(1000) / 60 + 1; - } + if (Pico.m.pal) + target_frametime_x3 = 3 * ms_to_ticks(1000) / 50; + else + target_frametime_x3 = 3 * ms_to_ticks(1000) / 60; - timestamp_fps = get_ticks(); reset_timing = 1; - - frames_done = frames_shown = pframes_done = 0; - - plat_video_wait_vsync(); + frames_done = frames_shown = 0; /* loop with resync every 1 sec. */ while (engineState == PGS_Running) { - unsigned int timestamp; - int diff, diff_lim; + int skip = 0; + int diff; pprof_start(main); - timestamp = get_ticks(); if (reset_timing) { reset_timing = 0; - timestamp_base = timestamp; - pframes_done = 0; + plat_video_wait_vsync(); + timestamp_aim_x3 = get_ticks() * 3; + timestamp_fps_x3 = timestamp_aim_x3; + fskip_cnt = 0; } + else if (currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) { + timestamp_aim_x3 = get_ticks() * 3; + } + + timestamp_x3 = get_ticks() * 3; // show notice_msg message? if (notice_msg_time != 0) { static int noticeMsgSum; - if (timestamp - ms_to_ticks(notice_msg_time) > ms_to_ticks(STATUS_MSG_TIMEOUT)) { + if (timestamp_x3 - ms_to_ticks(notice_msg_time) * 3 + > ms_to_ticks(STATUS_MSG_TIMEOUT) * 3) + { notice_msg_time = 0; plat_status_msg_clear(); notice_msg = NULL; - } else { + } + else { int sum = noticeMsg[0] + noticeMsg[1] + noticeMsg[2]; if (sum != noticeMsgSum) { plat_status_msg_clear(); @@ -1364,7 +1361,7 @@ void emu_loop(void) } // second changed? - if (timestamp - timestamp_fps >= ms_to_ticks(1000)) + if (timestamp_x3 - timestamp_fps_x3 >= ms_to_ticks(1000) * 3) { #ifdef BENCHMARK static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; @@ -1382,86 +1379,79 @@ void emu_loop(void) sprintf(fpsbuff, "%02i/%02i ", frames_shown, frames_done); #endif frames_shown = frames_done = 0; - timestamp_fps += ms_to_ticks(1000); + timestamp_fps_x3 += ms_to_ticks(1000) * 3; } #ifdef PFRAMES sprintf(fpsbuff, "%i", Pico.m.frame_count); #endif - if (timestamp - timestamp_base >= ms_to_ticks(1000)) + diff = timestamp_aim_x3 - timestamp_x3; + + if (currentConfig.Frameskip >= 0) // frameskip enabled (or 0) { - if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && currentConfig.Frameskip >= 0) - pframes_done = 0; - else - pframes_done -= target_fps; - if (pframes_done < -2) { - /* don't drag more than 2 frames behind */ - pframes_done = -2; - timestamp_base = timestamp - 2 * target_frametime; + if (fskip_cnt < currentConfig.Frameskip) { + fskip_cnt++; + skip = 1; } - else - timestamp_base += ms_to_ticks(1000); - } - - diff = timestamp - timestamp_base; - diff_lim = (pframes_done + 1) * target_frametime; - - if (currentConfig.Frameskip >= 0) // frameskip enabled - { - for (i = 0; i < currentConfig.Frameskip; i++) { - emu_update_input(); - skip_frame(1); - pframes_done++; frames_done++; - diff_lim += target_frametime; - - if (!(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) { - timestamp = get_ticks(); - diff = timestamp - timestamp_base; - if (!reset_timing && diff < diff_lim) // we are too fast - plat_wait_till_us(timestamp_base + diff_lim); - } + else { + fskip_cnt = 0; } } - else if (diff > diff_lim) + else if (diff < -target_frametime_x3) { /* no time left for this frame - skip */ /* limit auto frameskip to 8 */ - if (frames_done / 8 <= frames_shown) { - emu_update_input(); - skip_frame(diff < diff_lim + target_frametime * 16); - pframes_done++; frames_done++; - continue; - } + if (frames_done / 8 <= frames_shown) + skip = 1; + } + + // don't go in debt too much + while (diff < -target_frametime_x3 * 3) { + timestamp_aim_x3 += target_frametime_x3; + diff = timestamp_aim_x3 - timestamp_x3; } emu_update_input(); - PicoFrame(); - pemu_finalize_frame(fpsbuff, notice_msg); + if (skip) { + int do_audio = diff > -target_frametime_x3 * 2; + PicoSkipFrame = do_audio ? 1 : 2; + PicoFrame(); + PicoSkipFrame = 0; + } + else { + PicoFrame(); + pemu_finalize_frame(fpsbuff, notice_msg); + frames_shown++; + } + frames_done++; + timestamp_aim_x3 += target_frametime_x3; - if (!flip_after_sync) + if (!skip && !flip_after_sync) plat_video_flip(); /* frame limiter */ - if (!reset_timing && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) + if (!skip && !reset_timing + && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) { - timestamp = get_ticks(); - diff = timestamp - timestamp_base; + unsigned int timestamp = get_ticks(); + diff = timestamp_aim_x3 - timestamp * 3; // sleep or vsync if we are still too fast - if (diff < diff_lim) - { + if (diff > target_frametime_x3 && (currentConfig.EmuOpt & EOPT_VSYNC)) { // we are too fast - plat_wait_till_us(timestamp_base + diff_lim - target_frametime / 4); - if (currentConfig.EmuOpt & EOPT_VSYNC) - plat_video_wait_vsync(); + plat_video_wait_vsync(); + timestamp = get_ticks(); + diff = timestamp * 3 - timestamp_aim_x3; + } + if (diff > target_frametime_x3) { + // still too fast + plat_wait_till_us(timestamp + (diff - target_frametime_x3) / 3); } } - if (flip_after_sync) + if (!skip && flip_after_sync) plat_video_flip(); - pframes_done++; frames_done++; frames_shown++; - pprof_end(main); } diff --git a/platform/common/emu.h b/platform/common/emu.h index 4a4b4394..93787c77 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -77,7 +77,7 @@ typedef struct _currentConfig_t { } currentConfig_t; extern currentConfig_t currentConfig, defaultConfig; -extern char *PicoConfigFile; +extern const char *PicoConfigFile; extern int state_slot; extern int config_slot, config_slot_current; extern unsigned char *movie_data; diff --git a/platform/common/main.c b/platform/common/main.c index e8f92b9e..52676676 100644 --- a/platform/common/main.c +++ b/platform/common/main.c @@ -19,7 +19,6 @@ #include -extern char *PicoConfigFile; static int load_state_slot = -1; char **g_argv; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 14274905..8e723ff6 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -927,7 +927,7 @@ static void debug_menu_loop(void) // ------------ main menu ------------ static const char credits[] = - "PicoDrive v" VERSION " (c) notaz, 2006-2011\n\n\n" + "PicoDrive v" VERSION " (c) notaz, 2006-2013\n\n\n" "Credits:\n" "fDave: Cyclone 68000 core,\n" " base code of PicoDrive\n" @@ -935,7 +935,6 @@ static const char credits[] = "MAME devs: YM2612 and SN76496 cores\n" "Inder, ketchupgun: graphics\n" #ifdef __GP2X__ - "rlyeh and others: minimal SDK\n" "Squidge: mmuhack\n" "Dzz: ARM940 sample\n" #endif @@ -944,7 +943,7 @@ static const char credits[] = " Charles MacDonald, Haze,\n" " Stephane Dallongeville,\n" " Lordus, Exophase, Rokas,\n" - " Nemesis, Tasco Deluxe"; + " Eke, Nemesis, Tasco Deluxe"; static void menu_main_draw_status(void) { From c7074ddb0258ab03b9329bef9930c28ba46ae6da Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 31 Aug 2013 00:58:56 +0300 Subject: [PATCH 39/41] frontend: save autoload --- platform/common/emu.c | 48 ++++++++++++++++++++++++++++++------- platform/common/emu.h | 2 +- platform/common/menu_pico.c | 3 ++- platform/common/menu_pico.h | 1 + platform/libpicofe | 2 +- platform/pandora/plat.c | 15 ++++++++---- 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index 8bc83af4..ebc7c773 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -490,6 +490,30 @@ int emu_reload_rom(const char *rom_fname_in) if (currentConfig.EmuOpt & EOPT_EN_SRAM) emu_save_load_game(1, 1); + // state autoload? + if (g_autostateld_opt) { + int time, newest = 0, newest_slot = -1; + int slot; + + for (slot = 0; slot < 10; slot++) { + if (emu_check_save_file(slot, &time)) { + if (time > newest) { + newest = time; + newest_slot = slot; + } + } + } + + if (newest_slot >= 0) { + lprintf("autoload slot %d\n", newest_slot); + state_slot = newest_slot; + emu_save_load_game(1, 0); + } + else { + lprintf("no save to autoload.\n"); + } + } + retval = 1; out: if (menu_romload_started) @@ -736,19 +760,25 @@ void update_movie(void) } } -static int try_ropen_file(const char *fname) +static int try_ropen_file(const char *fname, int *time) { + struct stat st; FILE *f; f = fopen(fname, "rb"); if (f) { + if (time != NULL) { + *time = 0; + if (fstat(fileno(f), &st) == 0) + *time = (int)st.st_mtime; + } fclose(f); return 1; } return 0; } -char *emu_get_save_fname(int load, int is_sram, int slot) +char *emu_get_save_fname(int load, int is_sram, int slot, int *time) { char *saveFname = static_buff; char ext[16]; @@ -761,11 +791,11 @@ char *emu_get_save_fname(int load, int is_sram, int slot) if (!load) return saveFname; - if (try_ropen_file(saveFname)) + if (try_ropen_file(saveFname, time)) return saveFname; romfname_ext(saveFname, sizeof(static_buff), NULL, ext); - if (try_ropen_file(saveFname)) + if (try_ropen_file(saveFname, time)) return saveFname; } else @@ -783,11 +813,11 @@ char *emu_get_save_fname(int load, int is_sram, int slot) } else { romfname_ext(saveFname, sizeof(static_buff), "mds" PATH_SEP, ext); - if (try_ropen_file(saveFname)) + if (try_ropen_file(saveFname, time)) return saveFname; romfname_ext(saveFname, sizeof(static_buff), NULL, ext); - if (try_ropen_file(saveFname)) + if (try_ropen_file(saveFname, time)) return saveFname; // try the other ext @@ -797,7 +827,7 @@ char *emu_get_save_fname(int load, int is_sram, int slot) strcat(ext, ext_othr); romfname_ext(saveFname, sizeof(static_buff), "mds"PATH_SEP, ext); - if (try_ropen_file(saveFname)) + if (try_ropen_file(saveFname, time)) return saveFname; } } @@ -807,7 +837,7 @@ char *emu_get_save_fname(int load, int is_sram, int slot) int emu_check_save_file(int slot, int *time) { - return emu_get_save_fname(1, 0, slot) ? 1 : 0; + return emu_get_save_fname(1, 0, slot, time) ? 1 : 0; } int emu_save_load_game(int load, int sram) @@ -816,7 +846,7 @@ int emu_save_load_game(int load, int sram) char *saveFname; // make save filename - saveFname = emu_get_save_fname(load, sram, state_slot); + saveFname = emu_get_save_fname(load, sram, state_slot, NULL); if (saveFname == NULL) { if (!sram) emu_status_msg(load ? "LOAD FAILED (missing file)" : "SAVE FAILED"); diff --git a/platform/common/emu.h b/platform/common/emu.h index 93787c77..8f8f61f4 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -121,7 +121,7 @@ void emu_set_defconfig(void); int emu_read_config(const char *rom_fname, int no_defaults); int emu_write_config(int game); -char *emu_get_save_fname(int load, int is_sram, int slot); +char *emu_get_save_fname(int load, int is_sram, int slot, int *time); int emu_check_save_file(int slot, int *time); void emu_text_out8 (int x, int y, const char *text); diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 8e723ff6..44b5bdd5 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -135,7 +135,7 @@ static void draw_savestate_bg(int slot) const char *fname; void *tmp_state; - fname = emu_get_save_fname(1, 0, slot); + fname = emu_get_save_fname(1, 0, slot, NULL); if (!fname) return; @@ -1166,6 +1166,7 @@ void menu_update_msg(const char *msg) static menu_entry e_menu_hidden[] = { mee_onoff("Accurate sprites", MA_OPT_ACC_SPRITES, PicoOpt, 0x080), + mee_onoff("autoload savestates", MA_OPT_AUTOLOAD_SAVE, g_autostateld_opt, 1), mee_end, }; diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index 583a77cf..b5bd602d 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -41,6 +41,7 @@ typedef enum MA_OPT_ROTATION, /* uiq */ MA_OPT_TEARING_FIX, /* wiz */ MA_OPT_VOUT_MODE, + MA_OPT_AUTOLOAD_SAVE, MA_OPT2_GAMMA, MA_OPT2_A_SN_GAMMA, MA_OPT2_DBLBUFF, /* giz */ diff --git a/platform/libpicofe b/platform/libpicofe index 7ceadd99..9089665c 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 7ceadd9993ea84078e9d74d79215419e06496f90 +Subproject commit 9089665ca1260c338c4239583f59de981bc80c1c diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 306f2c36..bbe88137 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -74,16 +74,21 @@ static struct in_default_bind in_evdev_defbinds[] = { KEY_D, IN_BINDTYPE_PLAYER12, GBTN_C }, { KEY_ENTER, IN_BINDTYPE_PLAYER12, GBTN_START }, { KEY_F, IN_BINDTYPE_EMU, PEVB_FF }, - { KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU }, + { KEY_BACKSPACE,IN_BINDTYPE_EMU, PEVB_FF }, + { KEY_BACKSLASH,IN_BINDTYPE_EMU, PEVB_MENU }, { KEY_SPACE, IN_BINDTYPE_EMU, PEVB_MENU }, - /* Pandora */ + { KEY_LEFTCTRL, IN_BINDTYPE_EMU, PEVB_MENU }, { KEY_HOME, IN_BINDTYPE_PLAYER12, GBTN_A }, { KEY_PAGEDOWN, IN_BINDTYPE_PLAYER12, GBTN_B }, { KEY_END, IN_BINDTYPE_PLAYER12, GBTN_C }, { KEY_LEFTALT, IN_BINDTYPE_PLAYER12, GBTN_START }, - { KEY_RIGHTSHIFT,IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, - { KEY_RIGHTCTRL, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, - { KEY_LEFTCTRL, IN_BINDTYPE_EMU, PEVB_MENU }, + { KEY_1, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, + { KEY_2, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, + { KEY_3, IN_BINDTYPE_EMU, PEVB_SSLOT_PREV }, + { KEY_4, IN_BINDTYPE_EMU, PEVB_SSLOT_NEXT }, + { KEY_5, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, + { KEY_6, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, + { KEY_7, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, { 0, 0, 0 } }; From 835122bc0c583a74707847f350349e6050b42bb5 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 31 Aug 2013 02:23:57 +0300 Subject: [PATCH 40/41] sms: add pause support --- cpu/DrZ80/drz80.h | 2 +- cpu/DrZ80/drz80.s | 37 +++++++++++++++++++++++++++++++++++-- pico/pico_int.h | 7 ++++++- pico/sms.c | 7 ++++++- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/cpu/DrZ80/drz80.h b/cpu/DrZ80/drz80.h index 708f0a98..05773f93 100644 --- a/cpu/DrZ80/drz80.h +++ b/cpu/DrZ80/drz80.h @@ -52,7 +52,7 @@ struct DrZ80 int cycles; /*0x44 - Cycles pending to be executed yet */ int previouspc; /*0x48 - Previous PC */ unsigned char Z80_IRQ; /*0x4C - Set IRQ Number (must be halfword aligned) */ - unsigned char Z80IF; /*0x4D - Interrupt Flags: bit1=_IFF1, bit2=_IFF2, bit3=_HALT */ + unsigned char Z80IF; /*0x4D - Interrupt Flags: bit0=_IFF1, bit1=_IFF2, bit2=_HALT, b3=NMI */ unsigned char Z80IM; /*0x4E - Set IRQ Mode */ unsigned char spare; /*0x4F - N/A */ unsigned int z80irqvector; /*0x50 - Set IRQ Vector i.e. 0xFF=RST */ diff --git a/cpu/DrZ80/drz80.s b/cpu/DrZ80/drz80.s index edb29dfd..ff2a6b8b 100644 --- a/cpu/DrZ80/drz80.s +++ b/cpu/DrZ80/drz80.s @@ -97,6 +97,7 @@ DrZ80Ver: .long 0x0001 .equ Z80_IF1, 1<<0 .equ Z80_IF2, 1<<1 .equ Z80_HALT, 1<<2 + .equ Z80_NMI, 1<<3 ;@--------------------------------------- @@ -1359,9 +1360,11 @@ DrZ80Run: .if INTERRUPT_MODE == 0 ;@ check ints + tst r0,#(Z80_NMI<<8) + blne DoNMI tst r0,#0xff movne r0,r0,lsr #8 - tstne r0,#1 + tstne r0,#Z80_IF1 blne DoInterrupt .endif @@ -1515,6 +1518,36 @@ DoInterrupt_end: ldmfd sp!,{pc} ;@ return .endif +DoNMI: + stmfd sp!,{lr} + + bic r0,r0,#((Z80_NMI|Z80_HALT|Z80_IF1)<<8) + strh r0,[cpucontext,#z80irq] @ 0x4C, irq and IFF bits + + ;@ push pc on stack + ldr r0,[cpucontext,#z80pc_base] + sub r2,z80pc,r0 + opPUSHareg r2 + + ;@ read new pc from vector address +.if UPDATE_CONTEXT + str z80pc,[cpucontext,#z80pc_pointer] +.endif + mov r0,#0x66 +.if DRZ80_XMAP + rebasepc +.else + stmfd sp!,{r3,r12} + mov lr,pc + ldr pc,[cpucontext,#z80_rebasePC] ;@ r0=new pc - external function sets z80pc_base and returns new z80pc in r0 + ldmfd sp!,{r3,r12} + mov z80pc,r0 +.endif + ldrh r0,[cpucontext,#z80irq] @ 0x4C, irq and IFF bits + eatcycles 11 + ldmfd sp!,{pc} + + .data .align 4 @@ -5615,7 +5648,7 @@ ei_return: ;@ check ints tst r0,#0xff movne r0,r0,lsr #8 - tstne r0,#1 + tstne r0,#Z80_IF1 blne DoInterrupt ;@ continue diff --git a/pico/pico_int.h b/pico/pico_int.h index 690c233c..1acc1b08 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -174,6 +174,8 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) ((cycles) - DrZ80Run(&drZ80, cycles)) #define z80_run_nr(cycles) DrZ80Run(&drZ80, cycles) #define z80_int() drZ80.Z80_IRQ = 1 +#define z80_int() drZ80.Z80_IRQ = 1 +#define z80_nmi() drZ80.Z80IF |= 8 #define z80_cyclesLeft drZ80.cycles #define z80_pc() (drZ80.Z80PC - drZ80.Z80PC_BASE) @@ -184,6 +186,7 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) Cz80_Exec(&CZ80, cycles) #define z80_run_nr(cycles) Cz80_Exec(&CZ80, cycles) #define z80_int() Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE) +#define z80_nmi() Cz80_Set_IRQ(&CZ80, IRQ_LINE_NMI, 0) #define z80_cyclesLeft (CZ80.ICount - CZ80.ExtraCycles) #define z80_pc() Cz80_Get_Reg(&CZ80, CZ80_PC) @@ -193,6 +196,7 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) (cycles) #define z80_run_nr(cycles) #define z80_int() +#define z80_nmi() #endif @@ -313,7 +317,8 @@ struct PicoMS { unsigned char carthw[0x10]; unsigned char io_ctl; - unsigned char pad[0x4f]; + unsigned char nmi_state; + unsigned char pad[0x4e]; }; // some assembly stuff depend on these, do not touch! diff --git a/pico/sms.c b/pico/sms.c index 58905bde..8c44d51f 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -11,7 +11,6 @@ * - remaining status flags (OVR/COL) * - RAM support in mapper * - region support - * - Pause button (NMI) * - SN76496 DAC-like usage * - H counter */ @@ -256,8 +255,14 @@ void PicoFrameMS(void) int skip = PicoSkipFrame; int lines_vis = 192; int hint; // Hint counter + int nmi; int y; + nmi = (PicoPad[0] >> 7) & 1; + if (!Pico.ms.nmi_state && nmi) + z80_nmi(); + Pico.ms.nmi_state = nmi; + PicoFrameStartMode4(); hint = pv->reg[0x0a]; From 0185b677364b849e1e11f523d9f025d90ce86770 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 31 Aug 2013 20:02:59 +0300 Subject: [PATCH 41/41] allow to disable SH2 dynarec on runtime --- Makefile | 1 - Makefile.libretro | 1 - cpu/drc/cmn.c | 1 + cpu/sh2/compiler.c | 6 ++-- cpu/sh2/mame/sh2pico.c | 58 +++++++++++++++++++++++++++++--------- cpu/sh2/sh2.h | 18 +++++++++++- pico/32x/32x.c | 2 +- platform/common/common.mak | 3 -- platform/libretro.c | 14 +++++++++ 9 files changed, 80 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index d094104c..99c09369 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,6 @@ asm_mix ?= 1 else # if not arm use_fame ?= 1 use_cz80 ?= 1 -use_sh2mame ?= 1 endif -include Makefile.local diff --git a/Makefile.libretro b/Makefile.libretro index 141277c8..87360482 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -52,7 +52,6 @@ else ifeq ($(platform), ios) use_fame = 1 use_drz80 = 0 use_cz80 = 1 - use_sh2mame = 0 use_sh2drc = 1 use_svpdrc = 1 diff --git a/cpu/drc/cmn.c b/cpu/drc/cmn.c index cfb0219c..37f17ce9 100644 --- a/cpu/drc/cmn.c +++ b/cpu/drc/cmn.c @@ -20,6 +20,7 @@ void drc_cmn_init(void) tcache, sizeof(tcache), ret); #ifdef __arm__ + if (PicoOpt & POPT_EN_DRC) { static int test_done; if (!test_done) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 76df2204..25ba9d2f 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -3111,12 +3111,10 @@ void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid) 1 + cpuid, SH2_DRCBLK_DA_SHIFT, 0xfff); } -int sh2_execute(SH2 *sh2c, int cycles) +int sh2_execute_drc(SH2 *sh2c, int cycles) { int ret_cycles; - sh2c->cycles_timeslice = cycles; - // cycles are kept in SHR_SR unused bits (upper 20) // bit11 contains T saved for delay slot // others are usual SH2 flags @@ -3130,7 +3128,7 @@ int sh2_execute(SH2 *sh2c, int cycles) dbg(1, "warning: drc returned with cycles: %d", ret_cycles); sh2c->sr &= 0x3f3; - return sh2c->cycles_timeslice - ret_cycles; + return ret_cycles; } #if (DRC_DEBUG & 2) diff --git a/cpu/sh2/mame/sh2pico.c b/cpu/sh2/mame/sh2pico.c index 37ade45f..a3ad9f47 100644 --- a/cpu/sh2/mame/sh2pico.c +++ b/cpu/sh2/mame/sh2pico.c @@ -17,12 +17,46 @@ typedef unsigned short UINT16; typedef unsigned char UINT8; #endif -#define RB(sh2, a) p32x_sh2_read8(a,sh2) -#define RW(sh2, a) p32x_sh2_read16(a,sh2) -#define RL(sh2, a) p32x_sh2_read32(a,sh2) -#define WB(sh2, a, d) p32x_sh2_write8(a,d,sh2) -#define WW(sh2, a, d) p32x_sh2_write16(a,d,sh2) -#define WL(sh2, a, d) p32x_sh2_write32(a,d,sh2) +#ifdef DRC_SH2 + +// this nasty conversion is needed for drc-expecting memhandlers +#define MAKE_READFUNC(name, cname) \ +static inline unsigned int name(SH2 *sh2, unsigned int a) \ +{ \ + unsigned int ret; \ + sh2->sr |= sh2->icount << 12; \ + ret = cname(a, sh2); \ + sh2->icount = (signed int)sh2->sr >> 12; \ + sh2->sr &= 0x3f3; \ + return ret; \ +} + +#define MAKE_WRITEFUNC(name, cname) \ +static inline void name(SH2 *sh2, unsigned int a, unsigned int d) \ +{ \ + sh2->sr |= sh2->icount << 12; \ + cname(a, d, sh2); \ + sh2->icount = (signed int)sh2->sr >> 12; \ + sh2->sr &= 0x3f3; \ +} + +MAKE_READFUNC(RB, p32x_sh2_read8) +MAKE_READFUNC(RW, p32x_sh2_read16) +MAKE_READFUNC(RL, p32x_sh2_read32) +MAKE_WRITEFUNC(WB, p32x_sh2_write8) +MAKE_WRITEFUNC(WW, p32x_sh2_write16) +MAKE_WRITEFUNC(WL, p32x_sh2_write32) + +#else + +#define RB(sh2, a) p32x_sh2_read8(a, sh2) +#define RW(sh2, a) p32x_sh2_read16(a, sh2) +#define RL(sh2, a) p32x_sh2_read32(a, sh2) +#define WB(sh2, a, d) p32x_sh2_write8(a, d, sh2) +#define WW(sh2, a, d) p32x_sh2_write16(a, d, sh2) +#define WL(sh2, a, d) p32x_sh2_write32(a, d, sh2) + +#endif // some stuff from sh2comn.h #define T 0x00000001 @@ -71,14 +105,13 @@ static unsigned int op_refs[0x10000]; #include "sh2.c" -#ifndef DRC_SH2 #ifndef DRC_CMP -int sh2_execute(SH2 *sh2, int cycles) +int sh2_execute_interpreter(SH2 *sh2, int cycles) { UINT32 opcode; - sh2->icount = sh2->cycles_timeslice = cycles; + sh2->icount = cycles; if (sh2->icount <= 0) goto out; @@ -134,12 +167,12 @@ int sh2_execute(SH2 *sh2, int cycles) while (sh2->icount > 0 || sh2->delay); /* can't interrupt before delay */ out: - return sh2->cycles_timeslice - sh2->icount; + return sh2->icount; } #else // if DRC_CMP -int sh2_execute(SH2 *sh2, int cycles) +int sh2_execute_interpreter(SH2 *sh2, int cycles) { static unsigned int base_pc_[2] = { 0, 0 }; static unsigned int end_pc_[2] = { 0, 0 }; @@ -233,11 +266,10 @@ int sh2_execute(SH2 *sh2, int cycles) while (1); out: - return sh2->cycles_timeslice - sh2->icount; + return sh2->icount; } #endif // DRC_CMP -#endif // DRC_SH2 #ifdef SH2_STATS #include diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index d0b7377c..1394f94a 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -89,7 +89,23 @@ void sh2_do_irq(SH2 *sh2, int level, int vector); void sh2_pack(const SH2 *sh2, unsigned char *buff); void sh2_unpack(SH2 *sh2, const unsigned char *buff); -int sh2_execute(SH2 *sh2, int cycles); +int sh2_execute_drc(SH2 *sh2c, int cycles); +int sh2_execute_interpreter(SH2 *sh2c, int cycles); + +static inline int sh2_execute(SH2 *sh2, int cycles, int use_drc) +{ + int ret; + + sh2->cycles_timeslice = cycles; +#ifdef DRC_SH2 + if (use_drc) + ret = sh2_execute_drc(sh2, cycles); + else +#endif + ret = sh2_execute_interpreter(sh2, cycles); + + return sh2->cycles_timeslice - ret; +} // regs, pending_int*, cycles, reserved #define SH2_STATE_SIZE ((24 + 2 + 2 + 12) * 4) diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 54250f18..92d5216d 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -371,7 +371,7 @@ static inline void run_sh2(SH2 *sh2, int m68k_cycles) elprintf_sh2(sh2, EL_32X, "+run %u %d @%08x", sh2->m68krcycles_done, cycles, sh2->pc); - done = sh2_execute(sh2, cycles); + done = sh2_execute(sh2, cycles, PicoOpt & POPT_EN_DRC); sh2->m68krcycles_done += C_SH2_TO_M68K(*sh2, done); sh2->state &= ~SH2_STATE_RUN; diff --git a/platform/common/common.mak b/platform/common/common.mak index da5a52e4..a87a6b49 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -165,10 +165,7 @@ SRCS_COMMON += $(R)platform/libpicofe/linux/host_dasm.c LDFLAGS += -lbfd -lopcodes -liberty endif endif # use_sh2drc -# -ifeq "$(use_sh2mame)" "1" SRCS_COMMON += $(R)cpu/sh2/mame/sh2pico.c -endif endif # !no_32x OBJS_COMMON := $(SRCS_COMMON:.c=.o) diff --git a/platform/libretro.c b/platform/libretro.c index 3ae89740..cc50307e 100644 --- a/platform/libretro.c +++ b/platform/libretro.c @@ -185,6 +185,9 @@ void retro_set_environment(retro_environment_t cb) //{ "region", "Region; Auto|NTSC|PAL" }, { "picodrive_input1", "Input device 1; 3 button pad|6 button pad|None" }, { "picodrive_input2", "Input device 2; 3 button pad|6 button pad|None" }, +#ifdef DRC_SH2 + { "picodrive_drc", "Dynamic recompilers; enabled|disabled" }, +#endif { NULL, NULL }, }; @@ -688,6 +691,17 @@ static void update_variables(void) var.key = "picodrive_input2"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) PicoSetInputDevice(1, input_name_to_val(var.value)); + +#ifdef DRC_SH2 + var.value = NULL; + var.key = "picodrive_drc"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "enabled") == 0) + PicoOpt |= POPT_EN_DRC; + else + PicoOpt &= ~POPT_EN_DRC; + } +#endif } void retro_run(void)