diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af1f43920..50847c340 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ jobs: build-linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install dependencies @@ -14,16 +14,16 @@ jobs: - name: configure run: DUMP_CONFIG_LOG=1 ./configure - name: make - run: make -j2 + run: make -j$(getconf _NPROCESSORS_ONLN) build-libretro: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: make - run: LDFLAGS=-Wl,--no-undefined make -j2 -f Makefile.libretro + run: LDFLAGS=-Wl,--no-undefined make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.libretro build-gp2x: @@ -32,7 +32,7 @@ jobs: permissions: packages: read steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -40,11 +40,11 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=gph - make -j2 PLATFORM_MP3=0 + make -j$(getconf _NPROCESSORS_ONLN) PLATFORM_MP3=0 make -C platform/gp2x rel VER=$ver mv PicoDrive_$ver.zip PicoDrive-gph_$ver.zip - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: GP2X path: PicoDrive-gph_*.zip @@ -53,7 +53,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-pandora steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -61,11 +61,11 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=pandora - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) make -C platform/pandora rel VER=$ver mv platform/pandora/PicoDrive_*.pnd . - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Pandora path: PicoDrive_*.pnd @@ -77,7 +77,7 @@ jobs: - name: build environment run: | apk add git gcc g++ zip - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -86,14 +86,38 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=psp - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) make -C platform/psp rel VER=$ver - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: PSP path: PicoDrive_psp_*.zip + build-ps2: + runs-on: ubuntu-latest + container: ps2dev/ps2dev + steps: + - name: build environment + run: | + apk add build-base cmake git zip make + - uses: actions/checkout@v4 + with: + submodules: true + - name: build + run: | + export CROSS_COMPILE=mips64r5900el-ps2-elf- + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + ./configure --platform=ps2 + make -j$(getconf _NPROCESSORS_ONLN) + make -C platform/ps2 rel VER=$ver + - name: artifacts + uses: actions/upload-artifact@v4 + with: + name: PS2 + path: PicoDrive_ps2_*.zip + build-dingux: runs-on: ubuntu-latest @@ -101,7 +125,7 @@ jobs: packages: read container: ghcr.io/irixxxx/toolchain-dingux steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -109,10 +133,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=dingux - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive-dge.zip PicoDrive-dge-$ver.zip - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Dingux path: PicoDrive-dge*.zip @@ -121,7 +145,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-opendingux steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -129,10 +153,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=opendingux-gcw0 - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-gcw0-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: GCW0 path: PicoDrive-gcw0*.opk @@ -141,7 +165,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-opendingux steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -149,10 +173,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=opendingux - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-opendingux-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Opendingux path: PicoDrive-opendingux*.opk @@ -163,7 +187,7 @@ jobs: packages: read container: ghcr.io/irixxxx/toolchain-miyoo steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -171,10 +195,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=miyoo - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive-miyoo.zip PicoDrive-miyoo-$ver.zip - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Miyoo path: PicoDrive-miyoo*.zip @@ -183,7 +207,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-retrofw steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -191,10 +215,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=retrofw - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-retrofw-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: RetroFW path: PicoDrive-retrofw*.opk @@ -203,7 +227,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-odbeta-gcw0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -211,10 +235,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=odbeta - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-odbeta-gcw0-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ODbeta gcw0 path: PicoDrive-odbeta-*.opk @@ -223,7 +247,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-odbeta-lepus steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -231,10 +255,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=odbeta - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-odbeta-lepus-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ODbeta lepus path: PicoDrive-odbeta-*.opk @@ -243,7 +267,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-odbeta-rs90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: build @@ -251,10 +275,10 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=odbeta - make -j2 + make -j$(getconf _NPROCESSORS_ONLN) mv PicoDrive.opk PicoDrive-odbeta-rg99-$ver.opk - name: artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ODbeta rg99 path: PicoDrive-odbeta-*.opk diff --git a/.gitmodules b/.gitmodules index 4f610dff6..5d28012a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/irixxxx/libpicofe.git [submodule "cpu/cyclone"] path = cpu/cyclone - url = https://github.com/notaz/cyclone68000.git + url = https://github.com/irixxxx/cyclone68000.git [submodule "pico/sound/emu2413"] path = pico/sound/emu2413 url = https://github.com/digital-sound-antiques/emu2413.git diff --git a/Makefile b/Makefile index bd8a5b5c5..7b87043ee 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,10 @@ CFLAGS += $(call chkCCflag, -fno-caller-saves -fno-guess-branch-probability -fno # very old gcc toolchains may not have these options CFLAGS += $(call chkCCflag, -fno-tree-loop-if-convert -fipa-pta -fno-ipa-cp) endif +else +ifneq ($(STATIC_LINKING), 1) +CFLAGS += $(call chkCCflag, -flto) +endif endif # revision info from repository if this not a tagged release @@ -149,10 +153,6 @@ all: $(TARGET).opk endif endif -ifneq (,$(filter %mips32r2, $(CFLAGS))) -CFLAGS += -DMIPS_USE_SYNCI # mips32r2 clear_cache uses SYNCI instead of a syscall -endif - OBJS += platform/opendingux/inputmap.o use_inputmap ?= 1 @@ -237,21 +237,35 @@ OBJS += platform/psp/asm_utils.o OBJS += platform/psp/mp3.o USE_FRONTEND = 1 endif +ifeq "$(PLATFORM)" "ps2" +CFLAGS += -DUSE_BGR555 # -DLOG_TO_FILE +LDLIBS += -lpatches -lgskit -ldmakit -lps2_drivers +OBJS += platform/ps2/plat.o +OBJS += platform/ps2/emu.o +OBJS += platform/ps2/in_ps2.o +USE_FRONTEND = 1 +endif ifeq "$(PLATFORM)" "libretro" OBJS += platform/libretro/libretro.o ifneq ($(STATIC_LINKING), 1) +CFLAGS += -DHAVE_ZLIB +OBJS += platform/libretro/libretro-common/formats/png/rpng.o +OBJS += platform/libretro/libretro-common/streams/trans_stream.o +OBJS += platform/libretro/libretro-common/streams/trans_stream_pipe.o +OBJS += platform/libretro/libretro-common/streams/trans_stream_zlib.o +OBJS += platform/libretro/libretro-common/file/file_path_io.o +OBJS += platform/libretro/libretro-common/file/file_path.o +OBJS += platform/libretro/libretro-common/vfs/vfs_implementation.o +OBJS += platform/libretro/libretro-common/time/rtime.o +OBJS += platform/libretro/libretro-common/string/stdstring.o OBJS += platform/libretro/libretro-common/compat/compat_strcasestr.o +OBJS += platform/libretro/libretro-common/encodings/encoding_utf.o +OBJS += platform/libretro/libretro-common/compat/compat_strl.o ifeq "$(USE_LIBRETRO_VFS)" "1" OBJS += platform/libretro/libretro-common/compat/compat_posix_string.o -OBJS += platform/libretro/libretro-common/compat/compat_strl.o OBJS += platform/libretro/libretro-common/compat/fopen_utf8.o -OBJS += platform/libretro/libretro-common/encodings/encoding_utf.o -OBJS += platform/libretro/libretro-common/string/stdstring.o -OBJS += platform/libretro/libretro-common/time/rtime.o OBJS += platform/libretro/libretro-common/streams/file_stream.o OBJS += platform/libretro/libretro-common/streams/file_stream_transforms.o -OBJS += platform/libretro/libretro-common/file/file_path.o -OBJS += platform/libretro/libretro-common/vfs/vfs_implementation.o endif endif ifeq "$(USE_LIBRETRO_VFS)" "1" @@ -416,6 +430,10 @@ ifneq (,$(findstring -flto,$(CFLAGS))) # to avoid saving and reloading it. However, this collides with the use of LTO. pico/32x/memory.o: CFLAGS += -fno-lto pico/32x/sh2soc.o: CFLAGS += -fno-lto +cpu/sh2/compiler.o: CFLAGS += -fno-lto +endif +ifneq (,$(filter mips64%, $(ARCH))$(filter %mips32r2, $(CFLAGS))) +CFLAGS += -DMIPS_USE_SYNCI # mips32r2 clear_cache uses SYNCI instead of a syscall endif endif diff --git a/Makefile.libretro b/Makefile.libretro index 9e2511d0c..7028b270a 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -33,6 +33,7 @@ CFLAGS += -I$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) CFLAGS += -I platform/libretro/libretro-common/include CFLAGS += -I platform/libretro/libretro-common/include/compat CFLAGS += -I platform/libretro/libretro-common/include/encodings +CFLAGS += -I platform/libretro/libretro-common/include/formats CFLAGS += -I platform/libretro/libretro-common/include/streams CFLAGS += -I platform/libretro/libretro-common/include/string CFLAGS += -I platform/libretro/libretro-common/include/vfs @@ -279,7 +280,7 @@ else ifeq ($(platform), wii) TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float + CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -ffat-lto-objects STATIC_LINKING = 1 STATIC_LINKING_LINK = 1 diff --git a/configure b/configure index fd2d9a7e3..e73c69597 100755 --- a/configure +++ b/configure @@ -39,7 +39,7 @@ check_define() # "" means "autodetect". # TODO this is annoyingly messy. should have platform and device -platform_list="generic pandora gph dingux retrofw opendingux[-gcw0] odbeta[-gcw0] miyoo rpi1 rpi2 psp" +platform_list="generic pandora gph dingux retrofw opendingux[-gcw0] odbeta[-gcw0] miyoo rpi1 rpi2 ps2 psp" platform="generic" sound_driver_list="oss alsa sdl" sound_drivers="" @@ -59,6 +59,7 @@ CC="${CC-${CROSS_COMPILE}gcc}" CXX="${CXX-${CROSS_COMPILE}g++}" AS="${AS-${CROSS_COMPILE}as}" STRIP="${STRIP-${CROSS_COMPILE}strip}" +LD="${LD-${CROSS_COMPILE}gcc}" # Use better gcc for linking SYSROOT=`$CC $CFLAGS $LDFLAGS --print-sysroot 2> /dev/null || true` config_mak="config.mak" @@ -150,6 +151,15 @@ set_platform() MFLAGS="-march=allegrex" ARCH=mipsel ;; + ps2) + # use newlib + SYSLIBS="" + MFLAGS="" + ARCH=mips64r5900el + ASFLAGS="$ASFLAGS -G0 -call_shared" + CFLAGS="$CFLAGS -D_EE -G0 -I${PS2SDK}/ee/include -I${PS2SDK}/common/include -I${PS2DEV}/gsKit/include -I${PS2SDK}/ports/include" + LDFLAGS="$LDFLAGS -Wl,-zmax-page-size=128 -T${PS2SDK}/ee/startup/linkfile -L${PS2SDK}/ee/lib -L${PS2DEV}/gsKit/lib -L${PS2SDK}/ports/lib" + ;; *) fail "unsupported platform: $platform" ;; @@ -457,6 +467,7 @@ echo "CC = $CC" >> $config_mak echo "CXX = $CXX" >> $config_mak echo "AS = $AS" >> $config_mak echo "STRIP = $STRIP" >> $config_mak +echo "LD = $LD" >> $config_mak echo "CFLAGS += $MFLAGS $CFLAGS" >> $config_mak echo "ASFLAGS += $MFLAGS $ASFLAGS" >> $config_mak echo "LDFLAGS += $LDFLAGS" >> $config_mak diff --git a/cpu/DrZ80/drz80.S b/cpu/DrZ80/drz80.S index edcebb8ba..655814ca3 100644 --- a/cpu/DrZ80/drz80.S +++ b/cpu/DrZ80/drz80.S @@ -208,6 +208,7 @@ z80_xmap_read16: @ addr bl z80_xmap_read8 mov r9,r0 add r0,r8,#1 + bic r0,r0,#1<<16 bl z80_xmap_read8 orr r0,r9,r0,lsl #8 ldmfd sp!,{r2,r8,r9,pc} @@ -236,6 +237,7 @@ z80_xmap_write16: @ data, addr bl z80_xmap_write8 mov r0,r8,lsr #8 add r1,r9,#1 + bic r1,r1,#1<<16 bl z80_xmap_write8 ldmfd sp!,{r2,r8,r9,pc} @@ -827,6 +829,7 @@ z80_xmap_rebase_sp: mov r0,z80sp readmem16 add z80sp,z80sp,#2 + bic z80sp,z80sp,#1<<16 .endif .endm @@ -855,7 +858,8 @@ z80_xmap_rebase_sp: strb \reg,[z80sp,#-1]! .else mov r0,\reg - sub z80sp,z80sp,#2 + subs z80sp,z80sp,#2 + addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 .endif @@ -872,7 +876,8 @@ z80_xmap_rebase_sp: strb r1,[z80sp,#-1]! .else mov r0,\reg,lsr #16 - sub z80sp,z80sp,#2 + subs z80sp,z80sp,#2 + addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 .endif @@ -1472,7 +1477,7 @@ DoInterrupt: ;@ r0 == z80if stmfd sp!,{r2,lr} - tst r0,#4 ;@ check halt + tst r0,#Z80_HALT ;@ check halt addne z80pc,z80pc,#1 ldrb r1,[cpucontext,#z80im] @@ -1503,7 +1508,8 @@ DoInterrupt_mode0: strb r1,[z80sp,#-1]! strb r0,[z80sp,#-1]! .else - sub z80sp,z80sp,#2 + subs z80sp,z80sp,#2 + addcc z80sp,z80sp,#1<<16 mov r1,z80sp writemem16 ldr r2,[cpucontext, #z80irqvector] @@ -1577,7 +1583,9 @@ DoInterrupt_end: ;@ interupt accepted so callback irq interface ldr r0,[cpucontext, #z80irqcallback] tst r0,r0 - streqb r0,[cpucontext,#z80irq] ;@ default handling + ldreqb r0,[cpucontext,#z80irq] ;@ default handling + biceq r0,r0,#1 + streqb r0,[cpucontext,#z80irq] ldmeqfd sp!,{r2,pc} stmfd sp!,{r3,r12} mov lr,pc @@ -4727,6 +4735,9 @@ opcode_3_2: ;@INC SP opcode_3_3: add z80sp,z80sp,#1 +.if !FAST_Z80SP + bic z80sp,z80sp,#1<<16 +.endif fetch 6 ;@INC (HL) opcode_3_4: @@ -4777,7 +4788,10 @@ opcode_3_A: fetch 13 ;@DEC SP opcode_3_B: - sub z80sp,z80sp,#1 + subs z80sp,z80sp,#1 +.if !FAST_Z80SP + addcc z80sp,z80sp,#1<<16 +.endif fetch 6 ;@INC A opcode_3_C: @@ -5740,6 +5754,7 @@ opcode_F_1: mov r0,z80sp readmem16 add z80sp,z80sp,#2 + bic z80sp,z80sp,#1<<16 and z80a,r0,#0xFF00 mov z80a,z80a,lsl#16 and z80f,r0,#0xFF @@ -5758,7 +5773,10 @@ opcode_F_3: ldrb r1,[cpucontext,#z80if] bic r1,r1,#(Z80_IF1)|(Z80_IF2) strb r1,[cpucontext,#z80if] - fetch 4 + + ldrb r0,[z80pc],#1 + eatcycles 4 + ldr pc,[opcodes, r0, lsl #2] ;@CALL P,NN opcode_F_4: tst z80f,#1<IRQState) { CPU->Status |= CZ80_HAS_INT; @@ -727,7 +718,7 @@ switch (Opcode) CPU->ICount = 0; } } - else zIFF2 = (1 << 2); + zIFF1 = zIFF2 = (1 << 2); goto Cz80_Exec_nocheck; /*----------------------------------------- diff --git a/cpu/cz80/cz80_opED.c b/cpu/cz80/cz80_opED.c index 71f7dbce5..844d91eec 100644 --- a/cpu/cz80/cz80_opED.c +++ b/cpu/cz80/cz80_opED.c @@ -407,36 +407,29 @@ switch (Opcode) RET(8) /*----------------------------------------- - RETN + RETI/RETN -----------------------------------------*/ - OPED(0x45): // RETN; - OPED(0x55): // RETN; - OPED(0x65): // RETN; - OPED(0x75): // RETN; + // works the same, but Z80 PIO can detect the opcode + OPED(0x45): // RETN + OPED(0x55): // RETN + OPED(0x65): // RETN + OPED(0x75): // RETN + + OPED(0x4d): // RETI + OPED(0x5d): // RETI + OPED(0x6d): // RETI + OPED(0x7d): // RETI POP_16(res); SET_PC(res); if (!zIFF1 && zIFF2) { - zIFF1 = (1 << 2); if (CPU->IRQState) { CPU->Status |= CZ80_HAS_INT; } } - else zIFF1 = zIFF2; - RET(10) - -/*----------------------------------------- - RETI ------------------------------------------*/ - - OPED(0x4d): // RETI - OPED(0x5d): // RETI - OPED(0x6d): // RETI - OPED(0x7d): // RETI - POP_16(res); - SET_PC(res); + zIFF1 = zIFF2; RET(10) /*----------------------------------------- diff --git a/cpu/drc/cmn.c b/cpu/drc/cmn.c index 3f174a031..65ffd0439 100644 --- a/cpu/drc/cmn.c +++ b/cpu/drc/cmn.c @@ -10,7 +10,13 @@ #include #include "cmn.h" -u8 ALIGNED(4096) tcache_default[DRC_TCACHE_SIZE]; +#if defined(__linux__) && (defined(__aarch64__) || defined(__VFP_FP__)) +// might be running on a 64k-page kernel +#define PICO_PAGE_ALIGN 65536 +#else +#define PICO_PAGE_ALIGN 4096 +#endif +u8 ALIGNED(PICO_PAGE_ALIGN) tcache_default[DRC_TCACHE_SIZE]; u8 *tcache; void drc_cmn_init(void) diff --git a/cpu/fame/famec.c b/cpu/fame/famec.c index 9e832bc4e..a2edb3d6e 100644 --- a/cpu/fame/famec.c +++ b/cpu/fame/famec.c @@ -183,6 +183,11 @@ // internals core macros ///////////////////////// +// helper macros +#define BITCOUNT(r,v) \ + (r = (v) - (((v)>>1)&0x55555555), r = (r&0x33333333) + ((r>>2)&0x33333333), \ + r = (((r + (r>>4))&0x0f0f0f0f) * 0x01010101)>>24) + #define XB MEM_LE4(0) #define XW MEM_LE2(0) @@ -525,13 +530,13 @@ static const s32 exception_cycle_table[256] = 50, // 2: Bus Error 50, // 3: Address Error 34, // 4: Illegal Instruction - 38, // 5: Divide by Zero - 40, // 6: CHK + 34, // 5: Divide by Zero + 34, // 6: CHK 34, // 7: TRAPV 34, // 8: Privilege Violation 34, // 9: Trace - 4, // 10: - 4, // 11: + 34, // 10: Line A + 34, // 11: Line F 4, // 12: RESERVED 4, // 13: Coprocessor Protocol Violation 4, // 14: Format Error diff --git a/cpu/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index ffb7c4ed9..7a7832cfc 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -1074,11 +1074,7 @@ OPCODE(0x0280) flag_NotZ = res; flag_N = res >> 24; DREGu32((Opcode >> 0) & 7) = res; -#ifdef USE_CYCLONE_TIMING -RET(14) -#else RET(16) -#endif } // ANDI @@ -1303,7 +1299,11 @@ OPCODE(0x027C) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -1953,7 +1953,11 @@ OPCODE(0x0A7C) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING RET(0) +#else + RET(4) +#endif } RET(20) } @@ -3904,7 +3908,12 @@ OPCODE(0x0840) flag_NotZ = res & src; res ^= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(10) +#else RET(12) +#endif } // BCHGn @@ -4087,7 +4096,12 @@ OPCODE(0x0880) flag_NotZ = res & src; res &= ~src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(12) +#else RET(14) +#endif } // BCLRn @@ -4270,7 +4284,12 @@ OPCODE(0x08C0) flag_NotZ = res & src; res |= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(10) +#else RET(12) +#endif } // BSETn @@ -4663,7 +4682,12 @@ OPCODE(0x0140) flag_NotZ = res & src; res ^= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(6) +#else RET(8) +#endif } // BCHG @@ -4846,7 +4870,12 @@ OPCODE(0x0180) flag_NotZ = res & src; res &= ~src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(8) +#else RET(10) +#endif } // BCLR @@ -5029,7 +5058,12 @@ OPCODE(0x01C0) flag_NotZ = res & src; res |= src; DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING + if (src >> 16) ctx->io_cycle_counter -= 2; +RET(6) +#else RET(8) +#endif } // BSET @@ -16571,7 +16605,11 @@ OPCODE(0x46C0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(12) } @@ -16600,7 +16638,11 @@ OPCODE(0x46D0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16630,7 +16672,11 @@ OPCODE(0x46D8) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16660,7 +16706,11 @@ OPCODE(0x46E0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(18) } @@ -16690,7 +16740,11 @@ OPCODE(0x46E8) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -16720,7 +16774,11 @@ OPCODE(0x46F0) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(22) } @@ -16750,7 +16808,11 @@ OPCODE(0x46F8) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -16779,7 +16841,11 @@ OPCODE(0x46F9) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(24) } @@ -16809,7 +16875,11 @@ OPCODE(0x46FA) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(20) } @@ -16839,7 +16909,11 @@ OPCODE(0x46FB) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(22) } @@ -16865,7 +16939,11 @@ OPCODE(0x46FC) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16895,7 +16973,11 @@ OPCODE(0x46DF) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(16) } @@ -16925,7 +17007,11 @@ OPCODE(0x46E7) else { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else RET(4) +#endif } RET(18) } @@ -18327,7 +18413,7 @@ OPCODE(0x4AD0) POST_IO #ifdef USE_CYCLONE_TIMING -RET(18) +RET(14) #else RET(8) #endif @@ -18357,7 +18443,7 @@ OPCODE(0x4AD8) POST_IO #ifdef USE_CYCLONE_TIMING -RET(18) +RET(14) #else RET(8) #endif @@ -18387,7 +18473,7 @@ OPCODE(0x4AE0) POST_IO #ifdef USE_CYCLONE_TIMING -RET(20) +RET(16) #else RET(10) #endif @@ -18417,7 +18503,7 @@ OPCODE(0x4AE8) POST_IO #ifdef USE_CYCLONE_TIMING -RET(22) +RET(18) #else RET(12) #endif @@ -18447,7 +18533,7 @@ OPCODE(0x4AF0) POST_IO #ifdef USE_CYCLONE_TIMING -RET(24) +RET(20) #else RET(14) #endif @@ -18476,7 +18562,7 @@ OPCODE(0x4AF8) POST_IO #ifdef USE_CYCLONE_TIMING -RET(22) +RET(18) #else RET(12) #endif @@ -18505,7 +18591,7 @@ OPCODE(0x4AF9) POST_IO #ifdef USE_CYCLONE_TIMING -RET(26) +RET(22) #else RET(16) #endif @@ -18535,7 +18621,7 @@ OPCODE(0x4ADF) POST_IO #ifdef USE_CYCLONE_TIMING -RET(18) +RET(14) #else RET(8) #endif @@ -18593,7 +18679,7 @@ RET(0) OPCODE(0xF000) { SET_PC(execute_exception(ctx, M68K_1111_EX, GET_PC-2, GET_SR)); -RET(0) // 4 already taken by exc. handler +RET(0) } // MOVEMaR @@ -19154,7 +19240,11 @@ RET(12) OPCODE(0x4E40) { SET_PC(execute_exception(ctx, M68K_TRAP_BASE_EX + (Opcode & 0xF), GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } // LINK @@ -19225,7 +19315,11 @@ OPCODE(0x4E60) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } res = AREGu32((Opcode >> 0) & 7); ASP = res; @@ -19241,7 +19335,11 @@ OPCODE(0x4E68) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } res = ASP; AREG((Opcode >> 0) & 7) = res; @@ -19257,7 +19355,11 @@ OPCODE(0x4E70) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } PRE_IO if (ctx->reset_handler) ctx->reset_handler(); @@ -19281,7 +19383,11 @@ OPCODE(0x4E72) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } FETCH_WORD(res); res &= M68K_SR_MASK; @@ -19305,7 +19411,11 @@ OPCODE(0x4E73) if (!flag_S) { SET_PC(execute_exception(ctx, M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#else RET(4) +#endif } PRE_IO POP_16_F(res) @@ -19342,8 +19452,12 @@ RET(16) // TRAPV OPCODE(0x4E76) { - if (flag_V & 0x80) + if (flag_V & 0x80) { SET_PC(execute_exception(ctx, M68K_TRAPV_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING +RET(0) +#endif + } RET(4) } @@ -19606,6 +19720,7 @@ OPCODE(0x4180) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(4) } RET(10) } @@ -19624,6 +19739,7 @@ OPCODE(0x4190) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19644,6 +19760,7 @@ OPCODE(0x4198) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19664,6 +19781,7 @@ OPCODE(0x41A0) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(10) } POST_IO RET(16) @@ -19684,6 +19802,7 @@ OPCODE(0x41A8) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(12) } POST_IO RET(18) @@ -19704,6 +19823,7 @@ OPCODE(0x41B0) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(14) } POST_IO RET(20) @@ -19723,6 +19843,7 @@ OPCODE(0x41B8) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(12) } POST_IO RET(18) @@ -19742,6 +19863,7 @@ OPCODE(0x41B9) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(16) } POST_IO RET(22) @@ -19762,6 +19884,7 @@ OPCODE(0x41BA) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(12) } POST_IO RET(18) @@ -19782,6 +19905,7 @@ OPCODE(0x41BB) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(14) } POST_IO RET(20) @@ -19799,6 +19923,7 @@ OPCODE(0x41BC) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19819,6 +19944,7 @@ OPCODE(0x419F) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(8) } POST_IO RET(14) @@ -19839,6 +19965,7 @@ OPCODE(0x41A7) { flag_N = res >> 8; SET_PC(execute_exception(ctx, M68K_CHK_EX, GET_PC, GET_SR)); +RET(10) } POST_IO RET(16) @@ -27099,9 +27226,9 @@ OPCODE(0x80C0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(140) +RET(4) #else -RET(10) +RET(14) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27115,7 +27242,7 @@ RET(10) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(140) +RET(10) #else RET(70) #endif @@ -27126,12 +27253,12 @@ RET(70) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(140) +RET(138-BITCOUNT(res,q)*2) #else RET(90) #endif + } } // DIVU @@ -27147,9 +27274,9 @@ OPCODE(0x80D0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27163,7 +27290,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27174,12 +27301,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27196,9 +27323,9 @@ OPCODE(0x80D8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27212,7 +27339,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27223,12 +27350,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27245,9 +27372,9 @@ OPCODE(0x80E0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(10) #else -RET(16) +RET(20) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27261,7 +27388,7 @@ RET(16) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(16) #else RET(76) #endif @@ -27272,12 +27399,12 @@ RET(146) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(144-BITCOUNT(res,q)*2) #else RET(96) #endif + } } // DIVU @@ -27294,9 +27421,9 @@ OPCODE(0x80E8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(12) #else -RET(18) +RET(22) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27310,7 +27437,7 @@ RET(18) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(18) #else RET(78) #endif @@ -27321,12 +27448,12 @@ RET(148) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(146-BITCOUNT(res,q)*2) #else RET(98) #endif + } } // DIVU @@ -27343,9 +27470,9 @@ OPCODE(0x80F0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(14) #else -RET(20) +RET(24) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27359,7 +27486,7 @@ RET(20) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(20) #else RET(80) #endif @@ -27370,12 +27497,12 @@ RET(150) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(148-BITCOUNT(res,q)*2) #else RET(100) #endif + } } // DIVU @@ -27391,9 +27518,9 @@ OPCODE(0x80F8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(12) #else -RET(18) +RET(22) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27407,7 +27534,7 @@ RET(18) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(18) #else RET(78) #endif @@ -27418,12 +27545,12 @@ RET(148) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(146-BITCOUNT(res,q)*2) #else RET(98) #endif + } } // DIVU @@ -27439,9 +27566,9 @@ OPCODE(0x80F9) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(152) +RET(16) #else -RET(22) +RET(26) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27455,7 +27582,7 @@ RET(22) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(152) +RET(22) #else RET(82) #endif @@ -27466,12 +27593,12 @@ RET(152) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(152) +RET(150-BITCOUNT(res,q)*2) #else RET(102) #endif + } } // DIVU @@ -27488,9 +27615,9 @@ OPCODE(0x80FA) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(12) #else -RET(18) +RET(22) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27504,7 +27631,7 @@ RET(18) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(18) #else RET(78) #endif @@ -27515,12 +27642,12 @@ RET(148) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(148) +RET(146-BITCOUNT(res,q)*2) #else RET(98) #endif + } } // DIVU @@ -27537,9 +27664,9 @@ OPCODE(0x80FB) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(14) #else -RET(20) +RET(24) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27553,7 +27680,7 @@ RET(20) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(20) #else RET(80) #endif @@ -27564,12 +27691,12 @@ RET(150) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(150) +RET(148-BITCOUNT(res,q)*2) #else RET(100) #endif + } } // DIVU @@ -27583,9 +27710,9 @@ OPCODE(0x80FC) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27599,7 +27726,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27610,12 +27737,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27632,9 +27759,9 @@ OPCODE(0x80DF) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(8) #else -RET(14) +RET(18) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27648,7 +27775,7 @@ RET(14) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(14) #else RET(74) #endif @@ -27659,12 +27786,12 @@ RET(144) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(144) +RET(142-BITCOUNT(res,q)*2) #else RET(94) #endif + } } // DIVU @@ -27681,9 +27808,9 @@ OPCODE(0x80E7) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(10) #else -RET(16) +RET(20) #endif } dst = DREGu32((Opcode >> 9) & 7); @@ -27697,7 +27824,7 @@ RET(16) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(16) #else RET(76) #endif @@ -27708,12 +27835,12 @@ RET(146) flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -RET(146) +RET(144-BITCOUNT(res,q)*2) #else RET(96) #endif + } } // DIVS @@ -27727,9 +27854,10 @@ OPCODE(0x81C0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81C0; +RET(4) +#else + RET(14) #endif - RET(10) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27739,9 +27867,10 @@ goto end81C0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81C0; -#endif +RET(16+(dst>>31)*2) +#else RET(50) +#endif } { s32 q, r; @@ -27753,9 +27882,12 @@ goto end81C0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81C0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(16+(dst>>31)*2) +} else RET(152+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(80) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27763,11 +27895,12 @@ goto end81C0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81C0: ctx->io_cycle_counter -= 50; -#endif +RET(152+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(108) +#endif + } } // DIVS @@ -27783,9 +27916,10 @@ OPCODE(0x81D0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81D0; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27795,9 +27929,10 @@ goto end81D0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D0; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -27809,9 +27944,12 @@ goto end81D0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27819,11 +27957,12 @@ goto end81D0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81D0: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -27840,9 +27979,10 @@ OPCODE(0x81D8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81D8; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27852,9 +27992,10 @@ goto end81D8; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D8; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -27866,9 +28007,12 @@ goto end81D8; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81D8; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27876,11 +28020,12 @@ goto end81D8; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81D8: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -27897,9 +28042,10 @@ OPCODE(0x81E0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81E0; +RET(10) +#else + RET(20) #endif - RET(16) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27909,9 +28055,10 @@ goto end81E0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E0; -#endif +RET(22+(dst>>31)*2) +#else RET(56) +#endif } { s32 q, r; @@ -27923,9 +28070,12 @@ goto end81E0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(22+(dst>>31)*2) +} else RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(86) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27933,11 +28083,12 @@ goto end81E0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81E0: ctx->io_cycle_counter -= 50; -#endif +RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(114) +#endif + } } // DIVS @@ -27954,9 +28105,10 @@ OPCODE(0x81E8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81E8; +RET(12) +#else + RET(22) #endif - RET(18) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -27966,9 +28118,10 @@ goto end81E8; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E8; -#endif +RET(24+(dst>>31)*2) +#else RET(58) +#endif } { s32 q, r; @@ -27980,9 +28133,12 @@ goto end81E8; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E8; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(24+(dst>>31)*2) +} else RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(88) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -27990,11 +28146,12 @@ goto end81E8; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81E8: ctx->io_cycle_counter -= 50; -#endif +RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(116) +#endif + } } // DIVS @@ -28011,9 +28168,10 @@ OPCODE(0x81F0) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81F0; +RET(14) +#else + RET(24) #endif - RET(20) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28023,9 +28181,10 @@ goto end81F0; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F0; -#endif +RET(26+(dst>>31)*2) +#else RET(60) +#endif } { s32 q, r; @@ -28037,9 +28196,12 @@ goto end81F0; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F0; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(26+(dst>>31)*2) +} else RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(90) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28047,11 +28209,12 @@ goto end81F0; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81F0: ctx->io_cycle_counter -= 50; -#endif +RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(118) +#endif + } } // DIVS @@ -28067,9 +28230,10 @@ OPCODE(0x81F8) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81F8; +RET(12) +#else + RET(22) #endif - RET(18) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28079,9 +28243,10 @@ goto end81F8; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F8; -#endif +RET(24+(dst>>31)*2) +#else RET(58) +#endif } { s32 q, r; @@ -28093,9 +28258,12 @@ goto end81F8; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F8; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(24+(dst>>31)*2) +} else RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(88) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28103,11 +28271,12 @@ goto end81F8; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81F8: ctx->io_cycle_counter -= 50; -#endif +RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(116) +#endif + } } // DIVS @@ -28123,9 +28292,10 @@ OPCODE(0x81F9) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81F9; +RET(16) +#else + RET(26) #endif - RET(22) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28135,9 +28305,10 @@ goto end81F9; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F9; -#endif +RET(28+(dst>>31)*2) +#else RET(62) +#endif } { s32 q, r; @@ -28149,9 +28320,12 @@ goto end81F9; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81F9; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(28+(dst>>31)*2) +} else RET(164+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(92) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28159,11 +28333,12 @@ goto end81F9; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81F9: ctx->io_cycle_counter -= 50; -#endif +RET(164+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(120) +#endif + } } // DIVS @@ -28180,9 +28355,10 @@ OPCODE(0x81FA) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81FA; +RET(12) +#else + RET(22) #endif - RET(18) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28192,9 +28368,10 @@ goto end81FA; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FA; -#endif +RET(24+(dst>>31)*2) +#else RET(58) +#endif } { s32 q, r; @@ -28206,9 +28383,12 @@ goto end81FA; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FA; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(24+(dst>>31)*2) +} else RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(88) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28216,11 +28396,12 @@ goto end81FA; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81FA: ctx->io_cycle_counter -= 50; -#endif +RET(160+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(116) +#endif + } } // DIVS @@ -28237,9 +28418,10 @@ OPCODE(0x81FB) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81FB; +RET(14) +#else + RET(24) #endif - RET(20) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28249,9 +28431,10 @@ goto end81FB; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FB; -#endif +RET(26+(dst>>31)*2) +#else RET(60) +#endif } { s32 q, r; @@ -28263,9 +28446,12 @@ goto end81FB; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FB; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(26+(dst>>31)*2) +} else RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(90) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28273,11 +28459,12 @@ goto end81FB; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81FB: ctx->io_cycle_counter -= 50; -#endif +RET(162+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(118) +#endif + } } // DIVS @@ -28291,9 +28478,10 @@ OPCODE(0x81FC) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81FC; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28303,9 +28491,10 @@ goto end81FC; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FC; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -28317,9 +28506,12 @@ goto end81FC; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81FC; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28327,11 +28519,12 @@ goto end81FC; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81FC: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -28348,9 +28541,10 @@ OPCODE(0x81DF) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81DF; +RET(8) +#else + RET(18) #endif - RET(14) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28360,9 +28554,10 @@ goto end81DF; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81DF; -#endif +RET(20+(dst>>31)*2) +#else RET(54) +#endif } { s32 q, r; @@ -28374,9 +28569,12 @@ goto end81DF; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81DF; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(20+(dst>>31)*2) +} else RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(84) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28384,11 +28582,12 @@ goto end81DF; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81DF: ctx->io_cycle_counter -= 50; -#endif +RET(156+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(112) +#endif + } } // DIVS @@ -28405,9 +28604,10 @@ OPCODE(0x81E7) { SET_PC(execute_exception(ctx, M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -goto end81E7; +RET(10) +#else + RET(20) #endif - RET(16) } dst = DREGu32((Opcode >> 9) & 7); if ((dst == 0x80000000) && (src == (u32)-1)) @@ -28417,9 +28617,10 @@ goto end81E7; res = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E7; -#endif +RET(22+(dst>>31)*2) +#else RET(56) +#endif } { s32 q, r; @@ -28431,9 +28632,12 @@ goto end81E7; { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -goto end81E7; -#endif +if (q > 0xFFFF || q < -0x10000) { + RET(22+(dst>>31)*2) +} else RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(86) +#endif } q &= 0x0000FFFF; flag_NotZ = q; @@ -28441,11 +28645,12 @@ goto end81E7; flag_V = flag_C = 0; res = q | (r << 16); DREGu32((Opcode >> 9) & 7) = res; - } #ifdef USE_CYCLONE_TIMING_DIV -end81E7: ctx->io_cycle_counter -= 50; -#endif +RET(158+(dst>>31)*4-(q>>31)*2-BITCOUNT(res,abs(q))*2) +#else RET(114) +#endif + } } // SUBaD @@ -34309,7 +34514,7 @@ OPCODE(0xC0C0) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(54) +RET(38+BITCOUNT(res,src)*2) #else RET(50) #endif @@ -34332,7 +34537,7 @@ OPCODE(0xC0D0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34356,7 +34561,7 @@ OPCODE(0xC0D8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34380,7 +34585,7 @@ OPCODE(0xC0E0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src)*2) #else RET(56) #endif @@ -34404,7 +34609,7 @@ OPCODE(0xC0E8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src)*2) #else RET(58) #endif @@ -34428,7 +34633,7 @@ OPCODE(0xC0F0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src)*2) #else RET(60) #endif @@ -34451,7 +34656,7 @@ OPCODE(0xC0F8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src)*2) #else RET(58) #endif @@ -34474,7 +34679,7 @@ OPCODE(0xC0F9) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(66) +RET(50+BITCOUNT(res,src)*2) #else RET(62) #endif @@ -34498,7 +34703,7 @@ OPCODE(0xC0FA) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src)*2) #else RET(58) #endif @@ -34522,7 +34727,7 @@ OPCODE(0xC0FB) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src)*2) #else RET(60) #endif @@ -34542,7 +34747,7 @@ OPCODE(0xC0FC) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34566,7 +34771,7 @@ OPCODE(0xC0DF) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src)*2) #else RET(54) #endif @@ -34590,7 +34795,7 @@ OPCODE(0xC0E7) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src)*2) #else RET(56) #endif @@ -34610,7 +34815,7 @@ OPCODE(0xC1C0) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(54) +RET(38+BITCOUNT(res,src^(src<<1))) #else RET(50) #endif @@ -34633,7 +34838,7 @@ OPCODE(0xC1D0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34657,7 +34862,7 @@ OPCODE(0xC1D8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34681,7 +34886,7 @@ OPCODE(0xC1E0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src^(src<<1))*2) #else RET(56) #endif @@ -34705,7 +34910,7 @@ OPCODE(0xC1E8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src^(src<<1))*2) #else RET(58) #endif @@ -34729,7 +34934,7 @@ OPCODE(0xC1F0) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src^(src<<1))*2) #else RET(60) #endif @@ -34752,7 +34957,7 @@ OPCODE(0xC1F8) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src^(src<<1))*2) #else RET(58) #endif @@ -34775,7 +34980,7 @@ OPCODE(0xC1F9) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(66) +RET(50+BITCOUNT(res,src^(src<<1))*2) #else RET(62) #endif @@ -34799,7 +35004,7 @@ OPCODE(0xC1FA) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(62) +RET(46+BITCOUNT(res,src^(src<<1))*2) #else RET(58) #endif @@ -34823,7 +35028,7 @@ OPCODE(0xC1FB) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(64) +RET(48+BITCOUNT(res,src^(src<<1))*2) #else RET(60) #endif @@ -34843,7 +35048,7 @@ OPCODE(0xC1FC) flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34867,7 +35072,7 @@ OPCODE(0xC1DF) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(58) +RET(42+BITCOUNT(res,src^(src<<1))*2) #else RET(54) #endif @@ -34891,7 +35096,7 @@ OPCODE(0xC1E7) DREGu32((Opcode >> 9) & 7) = res; POST_IO #ifdef USE_CYCLONE_TIMING -RET(60) +RET(44+BITCOUNT(res,src^(src<<1))*2) #else RET(56) #endif diff --git a/cpu/musashi/m68k_in.c b/cpu/musashi/m68k_in.c index 14c1347d2..04fedf876 100644 --- a/cpu/musashi/m68k_in.c +++ b/cpu/musashi/m68k_in.c @@ -257,11 +257,62 @@ void m68ki_build_opcode_table(void) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX M68KMAKE_OPCODE_HANDLER_HEADER +#include #include "m68kcpu.h" extern void m68040_fpu_op0(void); extern void m68040_fpu_op1(void); +/* Count non-0 bits */ +INLINE int m68ki_bit_count(uint32 arg) +{ + arg = arg - ((arg>>1)&0x55555555); + arg = (arg&0x33333333) + ((arg>>2)&0x33333333); + return (((arg + (arg>>4))&0x0f0f0f0f) * 0x01010101) >> 24; +} + +INLINE int m68ki_mulu_cycles(uint32 arg) +{ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return m68ki_bit_count(arg) * 2; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return m68ki_bit_count(arg); /* guesswork */ + else + return m68ki_bit_count(arg) / 2; /* guesswork */ +} + +INLINE int m68ki_muls_cycles(sint32 arg) +{ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return m68ki_bit_count(arg ^ (arg<<1)) * 2; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return m68ki_bit_count(arg ^ (arg<<1)); /* guesswork */ + else + return m68ki_bit_count(arg ^ (arg<<1)) / 2; /* guesswork */ +} + +INLINE int m68ki_divu_cycles(uint32 arg) +{ + /* approximation only. Doesn't factor in shorter cycles by carry */ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return 128 - m68ki_bit_count(arg) * 2; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return 96; /* guesswork */ + else + return 32; /* guesswork */ +} + +INLINE int m68ki_divs_cycles(uint32 scyc, sint32 arg) +{ + /* approximation only. Doesn't factor in shorter cycles by carry */ + if (CPU_TYPE_IS_000(CPU_TYPE)) + return 128 - m68ki_bit_count(abs(arg)) * 2 + scyc*2 + 8; + else if (CPU_TYPE_IS_010(CPU_TYPE)) + return 96 + scyc*2 + 8; /* guesswork */ + else + return 32 + scyc + 4; /* guesswork */ +} + /* ======================================================================== */ /* ========================= INSTRUCTION HANDLERS ========================= */ /* ======================================================================== */ @@ -418,7 +469,7 @@ andi 8 . d 0000001000000... .......... U U U U 8 8 2 2 andi 8 . . 0000001000...... A+-DXWL... U U U U 12 12 4 4 andi 16 . d 0000001001000... .......... U U U U 8 8 2 2 andi 16 . . 0000001001...... A+-DXWL... U U U U 12 12 4 4 -andi 32 . d 0000001010000... .......... U U U U 14 14 2 2 +andi 32 . d 0000001010000... .......... U U U U 16 14 2 2 andi 32 . . 0000001010...... A+-DXWL... U U U U 20 20 4 4 asr 8 s . 1110...000000... .......... U U U U 6 6 6 6 asr 16 s . 1110...001000... .......... U U U U 6 6 6 6 @@ -438,13 +489,13 @@ bcc 8 . . 0110............ .......... U U U U 10 10 6 6 bcc 16 . . 0110....00000000 .......... U U U U 10 10 6 6 bcc 32 . . 0110....11111111 .......... U U U U 10 10 6 6 bchg 8 r . 0000...101...... A+-DXWL... U U U U 8 8 4 4 -bchg 32 r d 0000...101000... .......... U U U U 8 8 4 4 +bchg 32 r d 0000...101000... .......... U U U U 6 6 4 4 bchg 8 s . 0000100001...... A+-DXWL... U U U U 12 12 4 4 -bchg 32 s d 0000100001000... .......... U U U U 12 12 4 4 -bclr 8 r . 0000...110...... A+-DXWL... U U U U 8 10 4 4 -bclr 32 r d 0000...110000... .......... U U U U 10 10 4 4 +bchg 32 s d 0000100001000... .......... U U U U 10 10 4 4 +bclr 8 r . 0000...110...... A+-DXWL... U U U U 8 8 4 4 +bclr 32 r d 0000...110000... .......... U U U U 8 8 4 4 bclr 8 s . 0000100010...... A+-DXWL... U U U U 12 12 4 4 -bclr 32 s d 0000100010000... .......... U U U U 14 14 4 4 +bclr 32 s d 0000100010000... .......... U U U U 12 12 4 4 bfchg 32 . d 1110101011000... .......... . . U U . . 12 12 timing not quite correct bfchg 32 . . 1110101011...... A..DXWL... . . U U . . 20 20 bfclr 32 . d 1110110011000... .......... . . U U . . 12 12 @@ -465,10 +516,10 @@ bkpt 0 . . 0100100001001... .......... . U U U . 10 10 10 bra 8 . . 01100000........ .......... U U U U 10 10 10 10 bra 16 . . 0110000000000000 .......... U U U U 10 10 10 10 bra 32 . . 0110000011111111 .......... U U U U 10 10 10 10 -bset 32 r d 0000...111000... .......... U U U U 8 8 4 4 +bset 32 r d 0000...111000... .......... U U U U 6 6 4 4 bset 8 r . 0000...111...... A+-DXWL... U U U U 8 8 4 4 bset 8 s . 0000100011...... A+-DXWL... U U U U 12 12 4 4 -bset 32 s d 0000100011000... .......... U U U U 12 12 4 4 +bset 32 s d 0000100011000... .......... U U U U 10 10 4 4 bsr 8 . . 01100001........ .......... U U U U 18 18 7 7 bsr 16 . . 0110000100000000 .......... U U U U 18 18 7 7 bsr 32 . . 0110000111111111 .......... U U U U 18 18 7 7 @@ -482,8 +533,8 @@ cas 16 . . 0000110011...... A+-DXWL... . . U U . . 12 12 cas 32 . . 0000111011...... A+-DXWL... . . U U . . 12 12 cas2 16 . . 0000110011111100 .......... . . U U . . 12 12 cas2 32 . . 0000111011111100 .......... . . U U . . 12 12 -chk 16 . d 0100...110000... .......... U U U U 10 8 8 8 -chk 16 . . 0100...110...... A+-DXWLdxI U U U U 10 8 8 8 +chk 16 . d 0100...110000... .......... U U U U 4 2 2 2 +chk 16 . . 0100...110...... A+-DXWLdxI U U U U 4 2 2 2 chk 32 . d 0100...100000... .......... . . U U . . 8 8 chk 32 . . 0100...100...... A+-DXWLdxI . . U U . . 8 8 chk2cmp2 8 . pcdi 0000000011111010 .......... . . U U . . 23 23 @@ -541,10 +592,10 @@ cptrapcc 32 . . 1111...001111... .......... . . U . . . 4 . dbt 16 . . 0101000011001... .......... U U U U 12 12 6 6 dbf 16 . . 0101000111001... .......... U U U U 12 12 6 6 dbcc 16 . . 0101....11001... .......... U U U U 12 12 6 6 -divs 16 . d 1000...111000... .......... U U U U 158 122 56 56 -divs 16 . . 1000...111...... A+-DXWLdxI U U U U 158 122 56 56 -divu 16 . d 1000...011000... .......... U U U U 140 108 44 44 -divu 16 . . 1000...011...... A+-DXWLdxI U U U U 140 108 44 44 +divs 16 . d 1000...111000... .......... U U U U 16 16 16 16 cycles depending on operands +divs 16 . . 1000...111...... A+-DXWLdxI U U U U 16 16 16 16 cycles depending on operands +divu 16 . d 1000...011000... .......... U U U U 10 10 10 10 cycles depending on operands +divu 16 . . 1000...011...... A+-DXWLdxI U U U U 10 10 10 10 cycles depending on operands divl 32 . d 0100110001000... .......... . . U U . . 84 84 divl 32 . . 0100110001...... A+-DXWLdxI . . U U . . 84 84 eor 8 . d 1011...100000... .......... U U U U 4 4 2 2 @@ -696,10 +747,10 @@ moves 8 . . 0000111000...... A+-DXWL... . S S S . 14 5 5 moves 16 . . 0000111001...... A+-DXWL... . S S S . 14 5 5 moves 32 . . 0000111010...... A+-DXWL... . S S S . 16 5 5 move16 32 . . 1111011000100... .......... . . . U . . . 4 TODO: correct timing -muls 16 . d 1100...111000... .......... U U U U 54 32 27 27 -muls 16 . . 1100...111...... A+-DXWLdxI U U U U 54 32 27 27 -mulu 16 . d 1100...011000... .......... U U U U 54 30 27 27 -mulu 16 . . 1100...011...... A+-DXWLdxI U U U U 54 30 27 27 +muls 16 . d 1100...111000... .......... U U U U 38 28 20 20 cycles depending on operands +muls 16 . . 1100...111...... A+-DXWLdxI U U U U 38 28 20 20 cycles depending on operands +mulu 16 . d 1100...011000... .......... U U U U 38 26 20 20 cycles depending on operands +mulu 16 . . 1100...011...... A+-DXWLdxI U U U U 38 26 20 20 cycles depending on operands mull 32 . d 0100110000000... .......... . . U U . . 43 43 mull 32 . . 0100110000...... A+-DXWLdxI . . U U . . 43 43 nbcd 8 . d 0100100000000... .......... U U U U 6 6 6 6 @@ -835,7 +886,7 @@ subx 16 mm . 1001...101001... .......... U U U U 18 18 12 12 subx 32 mm . 1001...110001... .......... U U U U 30 30 12 12 swap 32 . . 0100100001000... .......... U U U U 4 4 4 4 tas 8 . d 0100101011000... .......... U U U U 4 4 4 4 -tas 8 . . 0100101011...... A+-DXWL... U U U U 14 14 12 12 +tas 8 . . 0100101011...... A+-DXWL... U U U U 10 10 8 8 trap 0 . . 010011100100.... .......... U U U U 4 4 4 4 trapt 0 . . 0101000011111100 .......... . . U U . . 4 4 trapt 16 . . 0101000011111010 .......... . . U U . . 6 6 @@ -2332,6 +2383,8 @@ M68KMAKE_OP(bchg, 32, r, d) uint* r_dst = &DY; uint mask = 1 << (DX & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst ^= mask; } @@ -2353,6 +2406,8 @@ M68KMAKE_OP(bchg, 32, s, d) uint* r_dst = &DY; uint mask = 1 << (OPER_I_8() & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst ^= mask; } @@ -2374,6 +2429,8 @@ M68KMAKE_OP(bclr, 32, r, d) uint* r_dst = &DY; uint mask = 1 << (DX & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst &= ~mask; } @@ -2395,6 +2452,8 @@ M68KMAKE_OP(bclr, 32, s, d) uint* r_dst = &DY; uint mask = 1 << (OPER_I_8() & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst &= ~mask; } @@ -3182,6 +3241,8 @@ M68KMAKE_OP(bset, 32, r, d) uint* r_dst = &DY; uint mask = 1 << (DX & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst |= mask; } @@ -3203,6 +3264,8 @@ M68KMAKE_OP(bset, 32, s, d) uint* r_dst = &DY; uint mask = 1 << (OPER_I_8() & 0x1f); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE) && mask >= 0x10000) + USE_CYCLES(2); FLAG_Z = *r_dst & mask; *r_dst |= mask; } @@ -3490,6 +3553,7 @@ M68KMAKE_OP(chk, 16, ., d) if(src >= 0 && src <= bound) { + USE_CYCLES(6); return; } FLAG_N = (src < 0)<<7; @@ -3508,6 +3572,7 @@ M68KMAKE_OP(chk, 16, ., .) if(src >= 0 && src <= bound) { + USE_CYCLES(6); return; } FLAG_N = (src < 0)<<7; @@ -4487,8 +4552,10 @@ M68KMAKE_OP(divs, 16, ., d) { uint* r_dst = &DX; sint src = MAKE_INT_16(DY); + sint dst = MAKE_INT_32(*r_dst); sint quotient; sint remainder; + int cycles; if(src != 0) { @@ -4499,12 +4566,21 @@ M68KMAKE_OP(divs, 16, ., d) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = 0; + USE_CYCLES(m68ki_divs_cycles(2, 0)); return; } - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; + if(abs(dst) >= abs(src<<16)) + { + FLAG_V = VFLAG_SET; + USE_CYCLES(2*(dst < 0)); + return; + } + + quotient = dst / src; + remainder = dst % src; + cycles = m68ki_divs_cycles(2*(dst < 0) + (quotient < 0), quotient); if(quotient == MAKE_INT_16(quotient)) { FLAG_Z = quotient; @@ -4512,12 +4588,15 @@ M68KMAKE_OP(divs, 16, ., d) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(cycles); return; } FLAG_V = VFLAG_SET; + USE_CYCLES(cycles); return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(12); } @@ -4525,8 +4604,10 @@ M68KMAKE_OP(divs, 16, ., .) { uint* r_dst = &DX; sint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + sint dst = MAKE_INT_32(*r_dst); sint quotient; sint remainder; + int cycles; if(src != 0) { @@ -4537,12 +4618,21 @@ M68KMAKE_OP(divs, 16, ., .) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = 0; + USE_CYCLES(m68ki_divs_cycles(2, 0)); + return; + } + + if(abs(dst) >= abs(src<<16)) + { + FLAG_V = VFLAG_SET; + USE_CYCLES(2*(dst < 0)); return; } - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; + quotient = dst / src; + remainder = dst % src; + cycles = m68ki_divs_cycles(2*(dst < 0) + (quotient < 0), quotient); if(quotient == MAKE_INT_16(quotient)) { FLAG_Z = quotient; @@ -4550,12 +4640,15 @@ M68KMAKE_OP(divs, 16, ., .) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(cycles); return; } FLAG_V = VFLAG_SET; + USE_CYCLES(cycles); return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(12); } @@ -4576,12 +4669,14 @@ M68KMAKE_OP(divu, 16, ., d) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(m68ki_divu_cycles(quotient)); return; } FLAG_V = VFLAG_SET; return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(6); } @@ -4602,12 +4697,14 @@ M68KMAKE_OP(divu, 16, ., .) FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + USE_CYCLES(m68ki_divu_cycles(quotient)); return; } FLAG_V = VFLAG_SET; return; } m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + ADD_CYCLES(6); } @@ -7500,9 +7597,11 @@ M68KMAKE_OP(move16, 32, ., .) M68KMAKE_OP(muls, 16, ., d) { uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + uint x = MAKE_INT_16(DY); + uint res = MASK_OUT_ABOVE_32(x * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); *r_dst = res; + USE_CYCLES(m68ki_muls_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); @@ -7514,9 +7613,11 @@ M68KMAKE_OP(muls, 16, ., d) M68KMAKE_OP(muls, 16, ., .) { uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + uint x = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + uint res = MASK_OUT_ABOVE_32(x * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); *r_dst = res; + USE_CYCLES(m68ki_muls_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); @@ -7528,9 +7629,11 @@ M68KMAKE_OP(muls, 16, ., .) M68KMAKE_OP(mulu, 16, ., d) { uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); + uint x = MASK_OUT_ABOVE_16(DY); + uint res = x * MASK_OUT_ABOVE_16(*r_dst); *r_dst = res; + USE_CYCLES(m68ki_mulu_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); @@ -7542,9 +7645,11 @@ M68KMAKE_OP(mulu, 16, ., d) M68KMAKE_OP(mulu, 16, ., .) { uint* r_dst = &DX; - uint res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst); + uint x = M68KMAKE_GET_OPER_AY_16; + uint res = x * MASK_OUT_ABOVE_16(*r_dst); *r_dst = res; + USE_CYCLES(m68ki_mulu_cycles(x)); FLAG_Z = res; FLAG_N = NFLAG_32(res); diff --git a/cpu/musashi/m68kcpu.c b/cpu/musashi/m68kcpu.c index d729f2cfa..1ac1a5d95 100644 --- a/cpu/musashi/m68kcpu.c +++ b/cpu/musashi/m68kcpu.c @@ -133,13 +133,13 @@ uint8 m68ki_exception_cycle_table[4][256] = 50, /* 2: Bus Error (unemulated) */ 50, /* 3: Address Error (unemulated) */ 34, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero -- ASG: changed from 42 */ - 40, /* 6: CHK -- ASG: chanaged from 44 */ + 34, /* 5: Divide by Zero -- ASG: changed from 42 */ + 34, /* 6: CHK -- ASG: chanaged from 44 */ 34, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 34, /* 9: Trace */ - 4, /* 10: 1010 */ - 4, /* 11: 1111 */ + 34, /* 10: 1010 */ + 34, /* 11: 1111 */ 4, /* 12: RESERVED */ 4, /* 13: Coprocessor Protocol Violation (unemulated) */ 4, /* 14: Format Error */ @@ -206,13 +206,13 @@ uint8 m68ki_exception_cycle_table[4][256] = 126, /* 2: Bus Error (unemulated) */ 126, /* 3: Address Error (unemulated) */ 38, /* 4: Illegal Instruction */ - 44, /* 5: Divide by Zero */ - 44, /* 6: CHK */ + 38, /* 5: Divide by Zero */ + 38, /* 6: CHK */ 34, /* 7: TRAPV */ 38, /* 8: Privilege Violation */ 38, /* 9: Trace */ - 4, /* 10: 1010 */ - 4, /* 11: 1111 */ + 38, /* 10: 1010 */ + 38, /* 11: 1111 */ 4, /* 12: RESERVED */ 4, /* 13: Coprocessor Protocol Violation (unemulated) */ 4, /* 14: Format Error */ @@ -279,8 +279,8 @@ uint8 m68ki_exception_cycle_table[4][256] = 50, /* 2: Bus Error (unemulated) */ 50, /* 3: Address Error (unemulated) */ 20, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ + 34, /* 5: Divide by Zero */ + 34, /* 6: CHK */ 20, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 25, /* 9: Trace */ @@ -352,8 +352,8 @@ uint8 m68ki_exception_cycle_table[4][256] = 50, /* 2: Bus Error (unemulated) */ 50, /* 3: Address Error (unemulated) */ 20, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ + 34, /* 5: Divide by Zero */ + 34, /* 6: CHK */ 20, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 25, /* 9: Trace */ @@ -787,12 +787,12 @@ void m68k_set_cpu_type(unsigned int cpu_type) /* ASG: removed per-instruction interrupt checks */ int m68k_execute(int num_cycles) { + // notaz + m68ki_check_interrupts(); + /* Make sure we're not stopped */ if(!CPU_STOPPED) { - // notaz - m68ki_check_interrupts(); - /* Set our pool of clock cycles available */ SET_CYCLES(num_cycles); m68ki_initial_cycles = num_cycles; diff --git a/cpu/musashi/m68kcpu.h b/cpu/musashi/m68kcpu.h index 6ab0ba0b6..3b40765f2 100644 --- a/cpu/musashi/m68kcpu.h +++ b/cpu/musashi/m68kcpu.h @@ -71,8 +71,12 @@ typedef uint8_t UINT8; #define uint32 unsigned int /* AWJ: changed from long to int */ /* signed and unsigned int must be at least 32 bits wide */ -#define sint signed int -#define uint unsigned int +//#define sint signed int +//#define uint unsigned int +#define sint _sint +#define uint _uint +typedef signed int sint; +typedef unsigned int uint; #if M68K_USE_64_BIT @@ -1537,7 +1541,7 @@ INLINE void m68ki_set_sr_noint_nosp(uint value) INLINE void m68ki_set_sr(uint value) { m68ki_set_sr_noint(value); - if (GET_CYCLES() >= 0) // notaz + if (GET_CYCLES() > 0) // notaz m68ki_check_interrupts(); } diff --git a/jni/Android.mk b/jni/Android.mk index f0b5c99a4..295c76f0e 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -54,7 +54,18 @@ endif include $(COMMON_DIR)/common.mak SOURCES_C := $(LIBRETRO_DIR)/libretro.c \ + $(LIBRETRO_COMM_DIR)/formats/png/rpng.c \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream.c \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream_pipe.c \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream_zlib.c \ + $(LIBRETRO_COMM_DIR)/file/file_path_io.c \ + $(LIBRETRO_COMM_DIR)/file/file_path.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \ + $(LIBRETRO_COMM_DIR)/time/rtime.c \ + $(LIBRETRO_COMM_DIR)/string/stdstring.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ $(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ $(COMMON_DIR)/mp3.c \ $(COMMON_DIR)/mp3_sync.c \ $(COMMON_DIR)/mp3_dummy.c \ diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index a3c3c93a0..78fae75d9 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -182,7 +182,7 @@ static void cdd_change_track(int index, int lba) { int i, base, lba_offset, lb_len; - for (i = index; i > 0; i--) + for (i = index; i >= 0; i--) if (cdd.toc.tracks[i].fd != NULL) break; @@ -510,7 +510,7 @@ int cdd_unload(void) void cdd_read_data(uint8 *dst) { /* only read DATA track sectors */ - if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[cdd.index].end)) + if (!is_audio(cdd.index) && (cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[cdd.index].end)) { /* BIN format ? */ if (cdd.sectorSize == 2352) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index ac42b8c53..b13644b13 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -97,9 +97,9 @@ void m68k_comm_check(u32 a) u32 pcd_stopwatch_read(int sub) { - // ugh.. + // ugh... stopwatch runs 384 cycles per step, divide by mult with inverse u32 d = sub ? SekCyclesDoneS68k() : pcd_cycles_m68k_to_s68k(SekCyclesDone()); - d = (d - Pico_mcd->m.stopwatch_base_c) / 384; + d = ((d - Pico_mcd->m.stopwatch_base_c) * ((1LL << 32) / 384)) >> 32; return d & 0x0fff; } @@ -1225,6 +1225,7 @@ PICO_INTERNAL void PicoMemSetupCD(void) { if (!Pico_mcd) Pico_mcd = plat_mmap(0x05000000, sizeof(mcd_state), 0, 0); + memset(Pico_mcd, 0, sizeof(mcd_state)); pcd_base_address = (Pico.romsize > 0x20000 ? 0x400000 : 0x000000); // setup default main68k map diff --git a/pico/draw.c b/pico/draw.c index 40903e74f..1b4ceb3cf 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1607,46 +1607,46 @@ static int BgcDMAlen, BgcDMAoffs; static #endif // handle DMA to background color -int BgcDMA(u16 *pd, int len, struct PicoEState *est) +void BgcDMA(struct PicoEState *est) { + u16 *pd=est->DrawLineDest; + int len = (est->Pico->video.reg[12]&1) ? 320 : 256; + // TODO for now handles the line as all background. int xl = (len == 320 ? 38 : 33); // DMA slots during HSYNC int upscale = (est->rendstatus & PDRAW_SOFTSCALE) && len < 320; + u16 *q = upscale ? DefOutBuff : pd; + int i, l = len; + u16 t; - if (BgcDMAlen > 0) { - // BG color DMA under way. TODO for now handles the line as all background. - int i, l = len; - u16 *q = upscale ? DefOutBuff : pd; - u16 t; - - if ((est->rendstatus & PDRAW_BORDER_32) && !upscale) - q += (320-len) / 2; + if ((est->rendstatus & PDRAW_BORDER_32) && !upscale) + q += (320-len) / 2; - BgcDMAlen -= (l>>1)+xl; - if (BgcDMAlen < 0) - // partial line - l += 2*BgcDMAlen; + BgcDMAlen -= ((l-BgcDMAoffs)>>1)+xl; + if (BgcDMAlen <= 0) { + // partial line + l += 2*BgcDMAlen; + est->rendstatus &= ~PDRAW_BGC_DMA; + } - for (i = 0; i < l; i += 2) { - // TODO use ps to overwrite only real bg pixels - t = BgcDMAbase[BgcDMAsrc++ & BgcDMAmask]; - q[i] = q[i+1] = PXCONV(t); - } - BgcDMAsrc += xl; // HSYNC DMA + for (i = BgcDMAoffs; i < l; i += 2) { + // TODO use ps to overwrite only real bg pixels + t = BgcDMAbase[BgcDMAsrc++ & BgcDMAmask]; + q[i] = q[i+1] = PXCONV(t); + } + BgcDMAsrc += xl; // HSYNC DMA + BgcDMAoffs = 0; - t = est->HighPal[Pico.video.reg[7] & 0x3f]; - while (i < len) q[i++] = t; // fill partial line with BG + t = PXCONV(PicoMem.cram[Pico.video.reg[7] & 0x3f]); + while (i < len) q[i++] = t; // fill partial line with BG - if (upscale) { - switch (PicoIn.filter) { - case 3: h_upscale_bl4_4_5(pd, 320, q, 256, len, f_nop); break; - case 2: h_upscale_bl2_4_5(pd, 320, q, 256, len, f_nop); break; - case 1: h_upscale_snn_4_5(pd, 320, q, 256, len, f_nop); break; - default: h_upscale_nn_4_5(pd, 320, q, 256, len, f_nop); break; - } + if (upscale) { + switch (PicoIn.filter) { + case 3: h_upscale_bl4_4_5(pd, 320, q, 256, len, f_nop); break; + case 2: h_upscale_bl2_4_5(pd, 320, q, 256, len, f_nop); break; + case 1: h_upscale_snn_4_5(pd, 320, q, 256, len, f_nop); break; + default: h_upscale_nn_4_5(pd, 320, q, 256, len, f_nop); break; } - return 1; } - return 0; } // -------------------------------------------- @@ -1737,6 +1737,9 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) if (DrawLineDestIncrement == 0) return; + if (est->rendstatus & PDRAW_BGC_DMA) + return BgcDMA(est); + PicoDrawUpdateHighPal(); len = 256; @@ -1747,9 +1750,6 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) else if ((PicoIn.AHW & PAHW_SMS) && (est->Pico->video.reg[0] & 0x20)) len -= 8, ps += 8; - if (BgcDMA(pd, len, est)) - return; - if ((est->rendstatus & PDRAW_SOFTSCALE) && len < 320) { if (len >= 240 && len <= 256) { pd += (256-len)>>1; @@ -2095,17 +2095,16 @@ static void PicoLine(int line, int offs, int sh, int bgc, int off, int on) void PicoDrawSync(int to, int off, int on) { struct PicoEState *est = &Pico.est; - int line, offs = 0; + int line, offs; int sh = (est->Pico->video.reg[0xC] & 8) >> 3; // shadow/hilight? int bgc = est->Pico->video.reg[7] & 0x3f; pprof_start(draw); - if (rendlines != 240) { - offs = 8; - if (to > 223) - to = 223; - } + offs = (240-rendlines) >> 1; + if (to >= rendlines) + to = rendlines-1; + if (est->DrawScanline <= to && (est->rendstatus & (PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES))) ParseSprites(to + 1, on); @@ -2193,6 +2192,8 @@ void PicoDrawBgcDMA(u16 *base, u32 source, u32 mask, int dlen, int sl) BgcDMAlen -= (len>>1)+xl; BgcDMAoffs = 0; } + if (BgcDMAlen > 0) + est->rendstatus |= PDRAW_BGC_DMA; } // also works for fast renderer diff --git a/pico/draw_arm.S b/pico/draw_arm.S index e3ef3e281..c01439aa4 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -20,6 +20,7 @@ .equ PDRAW_SHHI_DONE, (1<<7) .equ PDRAW_BORDER_32, (1<<9) .equ PDRAW_32X_SCALE, (1<<12) +.equ PDRAW_BGC_DMA, (1<<14) .equ PDRAW_SOFTSCALE, (1<<15) @ helpers @@ -1630,12 +1631,18 @@ PicoDoHighPal555_end: .global FinalizeLine555 FinalizeLine555: + ldr r3, [r2, #OFS_EST_rendstatus] + mov r0, r2 + tst r3, #PDRAW_BGC_DMA + bne BgcDMA + stmfd sp!, {r4-r11,lr} mov r11,r2 @ est - ldr r8, [r11, #OFS_EST_Pico] + mov r4, r3 bl PicoDrawUpdateHighPal + ldr r8, [r11, #OFS_EST_Pico] add r3, r11, #OFS_EST_HighPal mov lr, #0xff @@ -1644,7 +1651,6 @@ FinalizeLine555: ldr r5, [r11, #OFS_EST_PicoOpt] ldr r1, [r11, #OFS_EST_HighCol] ldr r0, [r11, #OFS_EST_DrawLineDest] - ldr r4, [r11, #OFS_EST_rendstatus] ldr r7, [r5, #OFS_PicoIn_AHW-OFS_PicoIn_opt] ldrb r12,[r8, #OFS_Pico_video_reg+12] ldrb r6, [r8, #OFS_Pico_video_reg+0] diff --git a/pico/media.c b/pico/media.c index 7c147b2f1..63d3d9979 100644 --- a/pico/media.c +++ b/pico/media.c @@ -138,16 +138,18 @@ static int detect_media(const char *fname, const unsigned char *rom, unsigned in extension_check: /* probably some headerless thing. Maybe check the extension after all. */ + ext_ptr = pmf && *pmf->ext ? pmf->ext : ext; + for (i = 0; i < ARRAY_SIZE(md_exts); i++) - if (strcasecmp(ext, md_exts[i]) == 0) + if (strcasecmp(ext_ptr, md_exts[i]) == 0) goto looks_like_md; for (i = 0; i < ARRAY_SIZE(sms_exts); i++) - if (strcasecmp(ext, sms_exts[i]) == 0) + if (strcasecmp(ext_ptr, sms_exts[i]) == 0) goto looks_like_sms; for (i = 0; i < ARRAY_SIZE(pico_exts); i++) - if (strcasecmp(ext, pico_exts[i]) == 0) + if (strcasecmp(ext_ptr, pico_exts[i]) == 0) goto looks_like_pico; /* If everything else fails, make a guess on the reset vector */ diff --git a/pico/memory.c b/pico/memory.c index cf2db5ba8..1bd230d0e 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -199,16 +199,25 @@ void cpu68k_map_all_funcs(u32 start_addr, u32 end_addr, u32 (*r8)(u32), u32 (*r1 r8map[i] = ar8, r16map[i] = ar16, w8map[i] = aw8, w16map[i] = aw16; } +u32 PicoRead16_floating(u32 a) +{ + // faking open bus + u32 d = (Pico.m.rotate += 0x41); + d ^= (d << 5) ^ (d << 8); + if ((a & 0xff0000) == 0xa10000) d = 0; // MegaCD pulldowns don't work here curiously + return (PicoIn.AHW & PAHW_MCD) ? 0x00 : d; // pulldown if MegaCD2 attached +} + static u32 m68k_unmapped_read8(u32 a) { elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); - return (PicoIn.AHW & PAHW_MCD) ? 0x00 : 0xff; // pulldown if MegaCD2 attached + return (u8)PicoRead16_floating(a); } static u32 m68k_unmapped_read16(u32 a) { elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); - return (PicoIn.AHW & PAHW_MCD) ? 0x00 : 0xffff; + return PicoRead16_floating(a); } static void m68k_unmapped_write8(u32 a, u32 d) @@ -521,13 +530,19 @@ void NOINLINE ctl_write_z80busreq(u32 d) { if (d) { - Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; + Pico.t.z80c_cnt = z80_cycles_from_68k() + (Pico.t.z80_busdelay >> 8); + Pico.t.z80_busdelay &= 0xff; } else { if ((PicoIn.opt & POPT_EN_Z80) && !Pico.m.z80_reset) { + // Z80 grants bus 2 cycles after the next M cycle, even within an insn + // simulate this by accumulating the last insn overhang in busdelay + unsigned granted = z80_cycles_from_68k() + 6; pprof_start(m68k); PicoSyncZ80(SekCyclesDone()); + Pico.t.z80_busdelay += (Pico.t.z80c_cnt - granted) << 8; + Pico.t.z80c_cnt = granted; pprof_end_sub(m68k); } } @@ -674,20 +689,22 @@ static void PicoWrite16_sram(u32 a, u32 d) // TODO: verify mirrors VDP and bank reg (bank area mirroring verified) static u32 PicoRead8_z80(u32 a) { - u32 d = 0xff; - if (((Pico.m.z80Run & 1) || Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { + u32 d; + if ((Pico.m.z80Run | Pico.m.z80_reset | (z80_cycles_from_68k() < Pico.t.z80c_cnt)) && + !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); - // open bus. Pulled down if MegaCD2 is attached. - return 0; + return (u8)PicoRead16_floating(a); } + SekCyclesBurnRun(1); if ((a & 0x4000) == 0x0000) { - SekCyclesBurnRun(1); d = PicoMem.zram[a & 0x1fff]; } else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff d = ym2612_read_local_68k(); - else + else { elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + d = (u8)PicoRead16_floating(a); + } return d; } @@ -699,14 +716,14 @@ static u32 PicoRead16_z80(u32 a) static void PicoWrite8_z80(u32 a, u32 d) { - if (((Pico.m.z80Run & 1) || Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { + if ((Pico.m.z80Run | Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) { // verified on real hw elprintf(EL_ANOMALY, "68k z80 write with no bus or reset! [%06x] %02x @ %06x", a, d&0xff, SekPc); return; } + SekCyclesBurnRun(1); if ((a & 0x4000) == 0x0000) { // z80 RAM - SekCyclesBurnRun(1); PicoMem.zram[a & 0x1fff] = (u8)d; return; } @@ -750,18 +767,18 @@ u32 PicoRead8_io(u32 a) goto end; } - // faking open bus (MegaCD pulldowns don't work here curiously) - d = Pico.m.rotate++; - d ^= d << 6; + d = PicoRead16_floating(a); if ((a & 0xfc00) == 0x1000) { - // bit8 seems to be readable in this range - if (!(a & 1)) - d &= ~0x01; - if ((a & 0xff01) == 0x1100) { // z80 busreq (verified) - d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; - elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc); + // bit8 seems to be readable in this range + if (!(a & 1)) { + d &= ~0x01; + // Z80 ahead of 68K only if in BUSREQ, BUSACK only after 68K reached Z80 + d |= (z80_cycles_from_68k() < Pico.t.z80c_cnt); + d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; + elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc); + } } goto end; } @@ -782,15 +799,13 @@ u32 PicoRead16_io(u32 a) goto end; } - // faking open bus - d = (Pico.m.rotate += 0x41); - d ^= (d << 5) ^ (d << 8); + d = PicoRead16_floating(a); // bit8 seems to be readable in this range if ((a & 0xfc00) == 0x1000) { - d &= ~0x0100; - if ((a & 0xff00) == 0x1100) { // z80 busreq + d &= ~0x0100; + d |= (z80_cycles_from_68k() < Pico.t.z80c_cnt) << 8; d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8; elprintf(EL_BUSREQ, "get_zrun: %04x [%u] @%06x", d, SekCyclesDone(), SekPc); } @@ -855,22 +870,25 @@ void PicoWrite16_io(u32 a, u32 d) // TODO: verify if lower byte goes to PSG on word writes u32 PicoRead8_vdp(u32 a) { + u32 d; if ((a & 0x00f0) == 0x0000) { switch (a & 0x0d) { - case 0x00: return PicoVideoRead8DataH(0); - case 0x01: return PicoVideoRead8DataL(0); - case 0x04: return PicoVideoRead8CtlH(0); - case 0x05: return PicoVideoRead8CtlL(0); + case 0x00: d = PicoVideoRead8DataH(0); break; + case 0x01: d = PicoVideoRead8DataL(0); break; + case 0x04: d = PicoVideoRead8CtlH(0); break; + case 0x05: d = PicoVideoRead8CtlL(0); break; case 0x08: - case 0x0c: return PicoVideoRead8HV_H(0); + case 0x0c: d = PicoVideoRead8HV_H(0); break; case 0x09: - case 0x0d: return PicoVideoRead8HV_L(0); + case 0x0d: d = PicoVideoRead8HV_L(0); break; + default: d = (u8)PicoRead16_floating(a); break; } + } else { + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + d = (u8)PicoRead16_floating(a); } - - elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); - return 0; + return d; } static u32 PicoRead16_vdp(u32 a) @@ -1064,6 +1082,8 @@ static int get_scanline(int is_from_z80) } #define ym2612_update_status(xcycles) \ + ym2612.OPN.ST.status &= ~0x80; \ + ym2612.OPN.ST.status |= (xcycles < Pico.t.ym2612_busy) * 0x80; \ if (xcycles >= Pico.t.timer_a_next_oflow) \ ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 1; \ if (xcycles >= Pico.t.timer_b_next_oflow) \ @@ -1093,7 +1113,7 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) * Starting a timer takes place at the next tick, so xcycles needs to be * rounded up to that: t = next tick# = (xcycles / TICK_ZCYCLES) + 1 */ - unsigned t = ((xcycles * (((1<<20)/TIMER_A_TICK_ZCYCLES)+1))>>20) + 1; + unsigned t = ((xcycles * (((1LL<<32)/TIMER_A_TICK_ZCYCLES)+1))>>32) + 1; Pico.t.timer_a_next_oflow = t*TIMER_A_TICK_ZCYCLES + Pico.t.timer_a_step; } } @@ -1116,7 +1136,7 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) * reset by loading timer b. The first run of timer b after loading is * therefore shorter by up to 15 ticks. */ - unsigned t = ((xcycles * (((1<<20)/TIMER_A_TICK_ZCYCLES)+1))>>20) + 1; + unsigned t = ((xcycles * (((1LL<<32)/TIMER_A_TICK_ZCYCLES)+1))>>32) + 1; int step = Pico.t.timer_b_step - TIMER_A_TICK_ZCYCLES*(t&15); Pico.t.timer_b_next_oflow = t*TIMER_A_TICK_ZCYCLES + step; } @@ -1129,6 +1149,7 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) // ym2612 DAC and timer I/O handlers for z80 static int ym2612_write_local(u32 a, u32 d, int is_from_z80) { + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); int addr; a &= 3; @@ -1148,6 +1169,10 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8); ym2612.REGS[addr] = d; + // the busy flag in the YM2612 status is actually a 32 cycle timer + // (89.6 Z80 cycles), triggered by any write to the data port. + Pico.t.ym2612_busy = (cycles + 90) << 8; // Q8 for convenience + switch (addr) { case 0x24: // timer A High 8 @@ -1156,7 +1181,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) : ((ym2612.OPN.ST.TA & 0x3fc)|(d&3)); if (ym2612.OPN.ST.TA != TAnew) { - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); ym2612_sync_timers(cycles, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); //elprintf(EL_STATUS, "timer a set %i", TAnew); ym2612.OPN.ST.TA = TAnew; @@ -1169,7 +1193,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) } case 0x26: // timer B if (ym2612.OPN.ST.TB != d) { - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); ym2612_sync_timers(cycles, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); //elprintf(EL_STATUS, "timer b set %i", d); ym2612.OPN.ST.TB = d; @@ -1181,7 +1204,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) return 0; case 0x27: { /* mode, timer control */ int old_mode = ym2612.OPN.ST.mode; - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); elprintf(EL_YMTIMER, "st mode %02x", d); ym2612_sync_timers(cycles, old_mode, d); @@ -1206,7 +1228,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) return 0; } case 0x2a: { /* DAC data */ - int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); //elprintf(EL_STATUS, "%03i dac w %08x z80 %i", cycles, d, is_from_z80); if (ym2612.dacen) PsndDoDAC(cycles); @@ -1228,7 +1249,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) if (PicoIn.opt & POPT_EXT_FM) return YM2612Write_940(a, d, get_scanline(is_from_z80)); #endif - PsndDoFM(is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k()); + PsndDoFM(cycles); return YM2612Write_(a, d); } @@ -1345,13 +1366,18 @@ void PicoWrite16_32x(u32 a, u32 d) {} static void access_68k_bus(int delay) // bus delay as Q8 { + // TODO: if the 68K is in DMA wait, Z80 has to wait until DMA ends + if (Pico.video.status & (PVS_CPUWR|PVS_CPURD)) + z80_subCLeft(z80_cyclesLeft); // rather rough on both condition and action + // 68k bus access delay for z80. The fractional part needs to be accumulated // until an additional cycle is full. That is then added to the integer part. - Pico.t.z80_busdelay = (delay&0xff) + (Pico.t.z80_busdelay&0xff); // accumulate + Pico.t.z80_busdelay += (delay&0xff); // accumulate z80_subCLeft((delay>>8) + (Pico.t.z80_busdelay>>8)); + Pico.t.z80_busdelay &= 0xff; // leftover cycle fraction // don't use SekCyclesBurn() here since the Z80 doesn't run in cycle lock to // the 68K. Count the stolen cycles to be accounted later in the 68k CPU runs - Pico.t.z80_buscycles += 7; + Pico.t.z80_buscycles += 8; } static unsigned char z80_md_vdp_read(unsigned short a) @@ -1380,7 +1406,7 @@ static unsigned char z80_md_vdp_read(unsigned short a) static unsigned char z80_md_bank_read(unsigned short a) { unsigned int addr68k; - unsigned char ret; + unsigned char ret = 0xff; // 68k bus access delay=3.3 per kabuto, but for notaz picotest 3.023.02)-0x351(<3.32) @@ -1388,7 +1414,8 @@ static unsigned char z80_md_bank_read(unsigned short a) addr68k = Pico.m.z80_bank68k << 15; addr68k |= a & 0x7fff; - ret = m68k_read8(addr68k); + if (addr68k < 0xe00000) // can't read from 68K RAM + ret = m68k_read8(addr68k); elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); return ret; diff --git a/pico/pico.h b/pico/pico.h index 2db502d5b..6759f73d6 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -235,6 +235,7 @@ void PicoDoHighPal555(int sh, int line, struct PicoEState *est); #define PDRAW_30_ROWS (1<<11) // 30 rows mode (240 lines) #define PDRAW_32X_SCALE (1<<12) // scale CLUT layer for 32X #define PDRAW_SMS_BLANK_1 (1<<13) // 1st column blanked +#define PDRAW_BGC_DMA (1<<14) // in background color DMA #define PDRAW_SOFTSCALE (1<<15) // H32 upscaling #define PDRAW_SYNC_NEEDED (1<<16) // redraw needed #define PDRAW_SYNC_NEXT (1<<17) // redraw next frame diff --git a/pico/pico/pico.c b/pico/pico/pico.c index d190a9402..94c80f203 100644 --- a/pico/pico/pico.c +++ b/pico/pico/pico.c @@ -36,6 +36,8 @@ static void PicoResetPico(void) PicoPicohw.fifo_bytes = 0; PicoPicohw.r12 = 0; + PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; + PicoPicoPCMIrqEn(0); PicoPicoPCMFilter(0); PicoPicoPCMGain(8); @@ -58,6 +60,5 @@ PICO_INTERNAL void PicoInitPico(void) PicoIn.AHW = PAHW_PICO; memset(&PicoPicohw, 0, sizeof(PicoPicohw)); - PicoPicohw.pen_pos[0] = 0x03c + 320/2; - PicoPicohw.pen_pos[1] = 0x200 + 240/2; + PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; } diff --git a/pico/pico/xpcm.c b/pico/pico/xpcm.c index 91749bacd..7d69b43e0 100644 --- a/pico/pico/xpcm.c +++ b/pico/pico/xpcm.c @@ -7,6 +7,17 @@ * See COPYING file in the top-level directory. * * The following ADPCM algorithm was derived from MAME upd7759 driver. + * + * The Pico is using this chip in slave mode. In this mode there are no ROM + * headers, but the first byte sent to the chip is used to start the ADPCM + * engine. This byte is discarded, i.e. not processed by the engine. + * + * Data is fed into the chip through a FIFO. An Interrupt is created if the + * FIFO has been drained below the low water mark. + * + * The Pico has 2 extensions to the standard upd7759 chip: + * - gain control, used to control the volume of the ADPCM output + * - filtering, used to remove (some of) the ADPCM compression artifacts */ #include @@ -42,21 +53,24 @@ static const int step_deltas[16][16] = static const int state_deltas[16] = { -1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3 }; -s32 stepsamples = (44100LL<<16)/ADPCM_CLOCK; +static s32 stepsamples; // ratio as Q16, host sound rate / chip sample rate static struct xpcm_state { s32 samplepos; // leftover duration for current sample wrt sndrate, Q16 int sample; // current sample - short state; // ADPCM engine state + short state; // ADPCM decoder state short samplegain; // programmable gain char startpin; // value on the !START pin char irqenable; // IRQ enabled? - char portstate; // data stream state + char portstate; // ADPCM stream state short silence; // silence blocks still to be played short rate, nibbles; // ADPCM nibbles still to be played - unsigned char highlow, cache; // nibble selector and cache + unsigned char highlow, cache; // nibble selector and cache + + char filter; // filter selector + s32 x[3], y[3]; // filter history } xpcm; enum { RESET, START, HDR, COUNT }; // portstate @@ -66,15 +80,15 @@ enum { RESET, START, HDR, COUNT }; // portstate #define QB 16 // mantissa bits #define FP(f) (int)((f)*(1<= rate/2) { memset(iir, 0, sizeof(*iir)); return; @@ -95,12 +109,12 @@ static int PicoPicoFilterApply(struct iir2 *iir, int sample) return sample; // NB Butterworth specific! - iir->x[0] = iir->x[1]; iir->x[1] = iir->x[2]; - iir->x[2] = sample * iir->gain; // Qb - iir->y[0] = iir->y[1]; iir->y[1] = iir->y[2]; - iir->y[2] = (iir->x[0] + 2*iir->x[1] + iir->x[2] - + iir->y[0]*iir->a[1] + iir->y[1]*iir->a[0]) >> QB; - return iir->y[2]; + xpcm.x[0] = xpcm.x[1]; xpcm.x[1] = xpcm.x[2]; + xpcm.x[2] = sample * iir->gain; // Qb + xpcm.y[0] = xpcm.y[1]; xpcm.y[1] = xpcm.y[2]; + xpcm.y[2] = (xpcm.x[0] + 2*xpcm.x[1] + xpcm.x[2] + + xpcm.y[0]*iir->a[1] + xpcm.y[1]*iir->a[0]) >> QB; + return xpcm.y[2]; } @@ -131,13 +145,23 @@ PICO_INTERNAL int PicoPicoPCMBusyN(void) PICO_INTERNAL void PicoPicoPCMRerate(void) { + s32 nextstep = ((u64)PicoIn.sndRate<<16)/ADPCM_CLOCK; + + // if the sound rate changes, erase filter history to avoid freak behaviour + if (stepsamples != nextstep) { + memset(xpcm.x, 0, sizeof(xpcm.x)); + memset(xpcm.y, 0, sizeof(xpcm.y)); + } + // output samples per chip clock - stepsamples = ((u64)PicoIn.sndRate<<16)/ADPCM_CLOCK; + stepsamples = nextstep; // compute filter coefficients, cutoff at half the ADPCM sample rate PicoPicoFilterCoeff(&filters[1], 6000/2, PicoIn.sndRate); // 5-6 KHz PicoPicoFilterCoeff(&filters[2], 9000/2, PicoIn.sndRate); // 8-12 KHz PicoPicoFilterCoeff(&filters[3], 15000/2, PicoIn.sndRate); // 14-16 KHz + + PicoPicoPCMFilter(xpcm.filter); } PICO_INTERNAL void PicoPicoPCMGain(int gain) @@ -147,6 +171,13 @@ PICO_INTERNAL void PicoPicoPCMGain(int gain) PICO_INTERNAL void PicoPicoPCMFilter(int index) { + // if the filter changes, erase the history to avoid freak behaviour + if (index != xpcm.filter) { + memset(xpcm.x, 0, sizeof(xpcm.x)); + memset(xpcm.y, 0, sizeof(xpcm.y)); + } + + xpcm.filter = index; filter = filters+index; if (filter->a[0] == 0) filter = NULL; @@ -204,12 +235,13 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) // loop over FIFO data, generating ADPCM samples while (length > 0 && src < lim) { - if (xpcm.silence > 0) { + // ADPCM state engine + if (xpcm.silence > 0) { // generate silence xpcm.silence --; xpcm.sample = 0; xpcm.samplepos += stepsamples*256; - } else if (xpcm.nibbles > 0) { + } else if (xpcm.nibbles > 0) { // produce samples xpcm.nibbles --; if (xpcm.highlow) @@ -221,7 +253,7 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) do_sample((xpcm.cache & 0xf0) >> 4); xpcm.samplepos += stepsamples*xpcm.rate; - } else switch (xpcm.portstate) { + } else switch (xpcm.portstate) { // handle stream headers case RESET: xpcm.sample = 0; xpcm.samplepos += length<<16; @@ -301,15 +333,13 @@ PICO_INTERNAL int PicoPicoPCMSave(void *buffer, int length) { u8 *bp = buffer; - if (length < sizeof(xpcm) + sizeof(filters)) { + if (length < sizeof(xpcm)) { elprintf(EL_ANOMALY, "save buffer too small?"); return 0; } memcpy(bp, &xpcm, sizeof(xpcm)); bp += sizeof(xpcm); - memcpy(bp, filters, sizeof(filters)); - bp += sizeof(filters); return (bp - (u8*)buffer); } @@ -320,7 +350,4 @@ PICO_INTERNAL void PicoPicoPCMLoad(void *buffer, int length) if (length >= sizeof(xpcm)) memcpy(&xpcm, bp, sizeof(xpcm)); bp += sizeof(xpcm); - if (length >= sizeof(xpcm) + sizeof(filters)) - memcpy(filters, bp, sizeof(filters)); - bp += sizeof(filters); } diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index d51477f1a..c3b14caa6 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -80,7 +80,7 @@ static __inline void SekAimM68k(int cyc, int mult) static __inline void SekRunM68k(int cyc) { - // TODO 0x100 would by 2 cycles/128, moreover far too sensitive + // TODO 0x100 would be 2 cycles/128, moreover far too sensitive SekAimM68k(cyc, 0x10c); // OutRunners, testpico, VDPFIFOTesting SekSyncM68k(0); } @@ -250,9 +250,10 @@ static int PicoFrameHints(void) SekInterrupt(6); } - if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) { + // assert Z80 interrupt for one scanline even in busrq hold (Teddy Blues) + if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) { elprintf(EL_INTS, "zint"); - z80_int(); + z80_int_assert(1); } // Run scanline: @@ -262,6 +263,10 @@ static int PicoFrameHints(void) if (PicoLineHook) PicoLineHook(); pevt_log_m68k_o(EVT_NEXT_LINE); + if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80)) + PicoSyncZ80(Pico.t.m68c_aim); + z80_int_assert(0); + // === VBLANK === lines = Pico.m.pal ? 313 : 262; for (y++; y < lines - 1; y++) diff --git a/pico/pico_int.h b/pico/pico_int.h index 86259cd75..31802f4ca 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -91,6 +91,9 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; #ifdef EMU_M68K #include +#undef INLINE +#undef USE_CYCLES +#undef ADD_CYCLES extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #ifndef SekCyclesLeft #define SekCyclesLeft PicoCpuMM68k.cyc_remaining_cycles @@ -166,7 +169,7 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) ((cycles) - DrZ80Run(&drZ80, cycles)) #define z80_run_nr(cycles) DrZ80Run(&drZ80, cycles) #define z80_int() drZ80.Z80_IRQ = 1 -#define z80_int_assert(a) drZ80.Z80_IRQ = (a) +#define z80_int_assert(a) drZ80.Z80_IRQ = (a ? 2 : 0) #define z80_nmi() drZ80.Z80IF |= 8 #define z80_cyclesLeft drZ80.cycles @@ -457,6 +460,7 @@ struct PicoTiming int timer_a_next_oflow, timer_a_step; // in z80 cycles int timer_b_next_oflow, timer_b_step; + int ym2612_busy; int vcnt_wrap, vcnt_adj; }; @@ -736,6 +740,7 @@ void PicoDrawSetOutputSMS(pdso_t which); // memory.c PICO_INTERNAL void PicoMemSetup(void); +PICO_INTERNAL u32 PicoRead16_floating(u32 a); u32 PicoRead8_io(u32 a); u32 PicoRead16_io(u32 a); void PicoWrite8_io(u32 a, u32 d); @@ -897,6 +902,8 @@ void ym2612_unpack_state(void); #define TIMER_B_TICK_ZCYCLES cycles_68k_to_z80(256LL*16*72*2) // Q8 #define timers_cycle(ticks) \ + if (Pico.t.ym2612_busy > 0) \ + Pico.t.ym2612_busy -= ticks << 8; \ if (Pico.t.timer_a_next_oflow < TIMER_NO_OFLOW) \ Pico.t.timer_a_next_oflow -= ticks << 8; \ if (Pico.t.timer_b_next_oflow < TIMER_NO_OFLOW) \ @@ -904,6 +911,7 @@ void ym2612_unpack_state(void); ym2612_sync_timers(0, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); #define timers_reset() \ + Pico.t.ym2612_busy = 0; \ Pico.t.timer_a_next_oflow = Pico.t.timer_b_next_oflow = TIMER_NO_OFLOW; \ Pico.t.timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \ Pico.t.timer_b_step = TIMER_B_TICK_ZCYCLES * 256; \ diff --git a/pico/sms.c b/pico/sms.c index 615ba36ea..6b1425b25 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -795,6 +795,9 @@ void PicoMemSetupMS(void) void PicoStateLoadedMS(void) { u8 mapper = Pico.ms.mapper; + u8 zram_dff0[16]; // TODO xwrite also writes to zram :-/ + + memcpy(zram_dff0, PicoMem.zram+0x1ff0, 16); if (mapper == PMS_MAP_8KBRAM || mapper == PMS_MAP_32KBRAM) { u16 a = Pico.ms.carthw[0] << 12; xwrite(a, *(unsigned char *)(PicoMem.vram+0x4000)); @@ -828,6 +831,7 @@ void PicoStateLoadedMS(void) xwrite(0xfffe, Pico.ms.carthw[0x0e]); xwrite(0xffff, Pico.ms.carthw[0x0f]); } + memcpy(PicoMem.zram+0x1ff0, zram_dff0, 16); } void PicoFrameMS(void) @@ -868,6 +872,7 @@ void PicoFrameMS(void) switch (is_pal ? -lines_vis : lines_vis) { case 192: if (y > 218) pv->v_counter = y - (lines-256); break; case 224: if (y > 234) pv->v_counter = y - (lines-256); break; +/* case 240: if (y > 252) pv->v_counter = y - (lines-256); break; ? */ case -192: if (y > 242) pv->v_counter = y - (lines-256); break; case -224: if (y > 258) pv->v_counter = y - (lines-256); break; case -240: if (y > 266) pv->v_counter = y - (lines-256); break; diff --git a/pico/sound/mix.c b/pico/sound/mix.c index 1c79b4854..edcdbb5f5 100644 --- a/pico/sound/mix.c +++ b/pico/sound/mix.c @@ -114,7 +114,7 @@ void mix_16h_to_32(s32 *dest_buf, s16 *mp3_buf, int count) { while (count--) { - *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; } } @@ -123,8 +123,8 @@ void mix_16h_to_32_s1(s32 *dest_buf, s16 *mp3_buf, int count) count >>= 1; while (count--) { - *dest_buf++ += *mp3_buf++ >> 1; - *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; mp3_buf += 1*2; } } @@ -134,8 +134,8 @@ void mix_16h_to_32_s2(s32 *dest_buf, s16 *mp3_buf, int count) count >>= 1; while (count--) { - *dest_buf++ += *mp3_buf++ >> 1; - *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; + *dest_buf++ += (*mp3_buf++ * 5) >> 3; mp3_buf += 3*2; } } @@ -146,8 +146,8 @@ void mix_16h_to_32_resample_stereo(s32 *dest_buf, s16 *cdda_buf, int count, int int pos16 = 0; while (count--) { int pos = 2 * (pos16>>16); - *dest_buf++ += cdda_buf[pos ] >> 1; - *dest_buf++ += cdda_buf[pos+1] >> 1; + *dest_buf++ += (cdda_buf[pos ] * 5) >> 3; + *dest_buf++ += (cdda_buf[pos+1] * 5) >> 3; pos16 += fac16; } } @@ -158,8 +158,8 @@ void mix_16h_to_32_resample_mono(s32 *dest_buf, s16 *cdda_buf, int count, int fa int pos16 = 0; while (count--) { int pos = 2 * (pos16>>16); - *dest_buf += cdda_buf[pos ] >> 2; - *dest_buf++ += cdda_buf[pos+1] >> 2; + *dest_buf += (cdda_buf[pos ] * 5) >> 4; + *dest_buf++ += (cdda_buf[pos+1] * 5) >> 4; pos16 += fac16; } } diff --git a/pico/sound/mix_arm.S b/pico/sound/mix_arm.S index dc9e980b4..835d30abc 100644 --- a/pico/sound/mix_arm.S +++ b/pico/sound/mix_arm.S @@ -31,12 +31,16 @@ m16_32_loop: ldmia r0, {r3-r6} ldmia r1!,{r12,lr} subs r2, r2, #4 - add r4, r4, r12,asr #17 @ we use half volume + add r4, r4, r12,asr #17 @ we use 5/8 volume + add r4, r4, r12,asr #19 mov r12,r12,lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 mov lr, lr, lsl #16 add r5, r5, lr, asr #17 + add r5, r5, lr, asr #19 stmia r0!,{r3-r6} bpl m16_32_loop @@ -47,7 +51,9 @@ m16_32_end: ldmia r0, {r3,r4} mov r12,r5, lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r4, r4, r5, asr #17 + add r4, r4, r5, asr #19 stmia r0!,{r3,r4} m16_32_no_unal2: @@ -56,6 +62,7 @@ m16_32_no_unal2: ldrsh r4, [r1], #2 ldr r3, [r0] add r3, r3, r4, asr #1 + add r3, r3, r4, asr #3 str r3, [r0], #4 ldmfd sp!, {r4-r6,lr} @@ -76,12 +83,16 @@ m16_32_s1_loop: ldr r12,[r1], #8 ldr lr, [r1], #8 subs r2, r2, #4 - add r4, r4, r12,asr #17 + add r4, r4, r12,asr #17 @ we use 5/8 volume + add r4, r4, r12,asr #19 mov r12,r12,lsl #16 - add r3, r3, r12,asr #17 @ we use half volume + add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 mov lr, lr, lsl #16 add r5, r5, lr, asr #17 + add r5, r5, lr, asr #19 stmia r0!,{r3-r6} bpl m16_32_s1_loop @@ -92,7 +103,9 @@ m16_32_s1_end: ldmia r0, {r3,r4} mov r12,r5, lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r4, r4, r5, asr #17 + add r4, r4, r5, asr #19 stmia r0!,{r3,r4} m16_32_s1_no_unal2: @@ -101,6 +114,7 @@ m16_32_s1_no_unal2: ldrsh r4, [r1], #2 ldr r3, [r0] add r3, r3, r4, asr #1 + add r3, r3, r4, asr #3 str r3, [r0], #4 ldmfd sp!, {r4-r6,lr} @@ -121,12 +135,16 @@ m16_32_s2_loop: ldr r12,[r1], #16 ldr lr, [r1], #16 subs r2, r2, #4 - add r4, r4, r12,asr #17 + add r4, r4, r12,asr #17 @ we use 5/8 volume + add r4, r4, r12,asr #19 mov r12,r12,lsl #16 - add r3, r3, r12,asr #17 @ we use half volume + add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 mov lr, lr, lsl #16 add r5, r5, lr, asr #17 + add r5, r5, lr, asr #19 stmia r0!,{r3-r6} bpl m16_32_s2_loop @@ -137,7 +155,9 @@ m16_32_s2_end: ldmia r0, {r3,r4} mov r12,r5, lsl #16 add r3, r3, r12,asr #17 + add r3, r3, r12,asr #19 add r4, r4, r5, asr #17 + add r4, r4, r5, asr #19 stmia r0!,{r3,r4} m16_32_s2_no_unal2: @@ -146,6 +166,7 @@ m16_32_s2_no_unal2: ldrsh r4, [r1], #2 ldr r3, [r0] add r3, r3, r4, asr #1 + add r3, r3, r4, asr #3 str r3, [r0], #4 ldmfd sp!, {r4-r6,lr} @@ -171,12 +192,16 @@ m16_32_rss_loop: ldr lr ,[r1, r9, lsl #2] add r4, r4, r3 subs r2, r2, #2 - add r6, r6, r12,asr #17 + add r6, r6, r12,asr #17 @ we use 5/8 volume + add r6, r6, r12,asr #19 mov r12,r12,lsl #16 - add r5, r5, r12,asr #17 @ we use half volume + add r5, r5, r12,asr #17 + add r5, r5, r12,asr #19 add r8, r8, lr, asr #17 + add r8, r8, lr, asr #19 mov lr, lr, lsl #16 add r7, r7, lr, asr #17 + add r7, r7, lr, asr #19 stmia r0!,{r5-r8} bpl m16_32_rss_loop @@ -188,7 +213,9 @@ m16_32_rss_end: ldmia r0, {r5,r6} mov r12,lr, lsl #16 add r5, r5, r12,asr #17 + add r5, r5, r12,asr #19 add r6, r6, lr, asr #17 + add r6, r6, lr, asr #19 stmia r0!,{r5,r6} ldmfd sp!, {r4-r9,lr} @@ -214,12 +241,16 @@ m16_32_rsm_loop: ldr lr ,[r1, r9, lsl #2] add r4, r4, r3 subs r2, r2, #2 - add r5, r5, r12,asr #18 + add r5, r5, r12,asr #18 @ we use 5/8 volume (= 5/16 vol per channel) + add r5, r5, r12,asr #20 mov r12,r12,lsl #16 - add r5, r5, r12,asr #18 @ we use half volume (= quarter vol per channel) + add r5, r5, r12,asr #18 + add r5, r5, r12,asr #20 add r6, r6, lr, asr #18 + add r6, r6, lr, asr #20 mov lr, lr, lsl #16 add r6, r6, lr, asr #18 + add r6, r6, lr, asr #20 stmia r0!,{r5-r6} bpl m16_32_rsm_loop @@ -231,7 +262,9 @@ m16_32_rsm_end: ldr r5, [r0] mov r12,lr, lsl #16 add r5, r5, r12,asr #18 + add r5, r5, r12,asr #20 add r5, r5, lr, asr #18 + add r5, r5, lr, asr #20 str r5, [r0] ldmfd sp!, {r4-r6,r9,lr} diff --git a/pico/state.c b/pico/state.c index 3b93765fa..bd801b157 100644 --- a/pico/state.c +++ b/pico/state.c @@ -187,7 +187,7 @@ static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = { "32X events", }; -static int write_chunk(chunk_name_e name, int len, void *data, void *file) +static int write_chunk(unsigned char name, int len, void *data, void *file) { size_t bwritten = 0; bwritten += areaWrite(&name, 1, 1, file); @@ -605,12 +605,13 @@ static int state_load(void *file) Pico32xStateLoaded(0); if (PicoIn.AHW & PAHW_MCD) pcd_state_loaded(); + if (!(PicoIn.AHW & PAHW_SMS)) { + Pico.video.status &= ~(SR_VB | SR_F); + Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB; + Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F; + } Pico.m.dirtyPal = 1; - Pico.video.status &= ~(SR_VB | SR_F); - Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB; - Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F; - retval = 0; out: diff --git a/pico/videoport.c b/pico/videoport.c index dcfc58c8c..d4a986f1e 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -397,7 +397,7 @@ int PicoVideoFIFOHint(void) // reset slot to start of scanline vf->fifo_slot = 0; // only need to refresh sprite position if we are synced - if (Pico.est.DrawScanline == Pico.m.scanline) + if (Pico.est.DrawScanline == Pico.m.scanline && !(pv->status & SR_VB)) PicoDrawRefreshSprites(); // if CPU is waiting for the bus, advance CPU and FIFO until bus is free @@ -439,8 +439,9 @@ void PicoVideoFIFOMode(int active, int h40) static __inline void AutoIncrement(void) { - Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]); - if (Pico.video.addr < Pico.video.reg[0xf]) Pico.video.addr_u ^= 1; + struct PicoVideo *pvid = &Pico.video; + pvid->addr=(unsigned short)(pvid->addr+pvid->reg[0xf]); + if (pvid->addr < pvid->reg[0xf]) pvid->addr_u ^= 1; } static NOINLINE void VideoWriteVRAM128(u32 a, u16 d) @@ -458,23 +459,24 @@ static NOINLINE void VideoWriteVRAM128(u32 a, u16 d) static void VideoWrite(u16 d) { - unsigned int a = Pico.video.addr; + struct PicoVideo *pvid = &Pico.video; + unsigned int a = pvid->addr; - switch (Pico.video.type) + switch (pvid->type) { case 1: if (a & 1) d = (u16)((d << 8) | (d >> 8)); - a |= Pico.video.addr_u << 16; + a |= pvid->addr_u << 16; VideoWriteVRAM(a, d); break; - case 3: if (PicoMem.cram [(a >> 1) & 0x3f] != d) Pico.m.dirtyPal = 1; + case 3: if (PicoMem.cram [(a >> 1) & 0x3f] != (d & 0xeee)) Pico.m.dirtyPal = 1; PicoMem.cram [(a >> 1) & 0x3f] = d & 0xeee; break; case 5: PicoMem.vsram[(a >> 1) & 0x3f] = d & 0x7ff; break; case 0x81: - a |= Pico.video.addr_u << 16; + a |= pvid->addr_u << 16; VideoWriteVRAM128(a, d); break; - //default:elprintf(EL_ANOMALY, "VDP write %04x with bad type %i", d, Pico.video.type); break; + //default:elprintf(EL_ANOMALY, "VDP write %04x with bad type %i", d, pvid->type); break; } AutoIncrement(); @@ -482,21 +484,22 @@ static void VideoWrite(u16 d) static unsigned int VideoRead(int is_from_z80) { + struct PicoVideo *pvid = &Pico.video; unsigned int a, d = VdpFIFO.fifo_data[(VdpFIFO.fifo_dx+1)&3]; - a=Pico.video.addr; a>>=1; + a=pvid->addr; a>>=1; if (!is_from_z80) SekCyclesBurnRun(PicoVideoFIFORead()); - switch (Pico.video.type) + switch (pvid->type) { case 0: d=PicoMem.vram [a & 0x7fff]; break; case 8: d=PicoMem.cram [a & 0x003f] | (d & ~0x0eee); break; case 4: if ((a & 0x3f) >= 0x28) a = 0; d=PicoMem.vsram [a & 0x003f] | (d & ~0x07ff); break; - case 12:a=PicoMem.vram [a & 0x7fff]; if (Pico.video.addr&1) a >>= 8; + case 12:a=PicoMem.vram [a & 0x7fff]; if (pvid->addr&1) a >>= 8; d=(a & 0x00ff) | (d & ~0x00ff); break; - default:elprintf(EL_ANOMALY, "VDP read with bad type %i", Pico.video.type); break; + default:elprintf(EL_ANOMALY, "VDP read with bad type %i", pvid->type); break; } AutoIncrement(); @@ -518,17 +521,18 @@ static int GetDmaLength(void) static void DmaSlow(int len, u32 source) { - u32 inc = Pico.video.reg[0xf]; - u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e; + struct PicoVideo *pvid=&Pico.video; + u32 inc = pvid->reg[0xf]; + u32 a = pvid->addr | (pvid->addr_u << 16), e; u16 *r, *base = NULL; u32 mask = 0x1ffff; int lc = SekCyclesDone()-Pico.t.m68c_line_start; elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%u] @ %06x", - Pico.video.type, source, a, len, inc, (Pico.video.status&SR_VB)||!(Pico.video.reg[1]&0x40), + pvid->type, source, a, len, inc, (pvid->status&SR_VB)||!(pvid->reg[1]&0x40), SekCyclesDone(), SekPc); - SekCyclesBurnRun(PicoVideoFIFOWrite(len, FQ_FGDMA | (Pico.video.type == 1), + SekCyclesBurnRun(PicoVideoFIFOWrite(len, FQ_FGDMA | (pvid->type == 1), PVS_DMABG, SR_DMA | PVS_CPUWR)); if ((source & 0xe00000) == 0xe00000) { // Ram @@ -569,7 +573,7 @@ static void DmaSlow(int len, u32 source) base = m68k_dma_source(source); } if (!base) { - elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: invalid src", Pico.video.type, source, a); + elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: invalid src", pvid->type, source, a); return; } @@ -577,7 +581,7 @@ static void DmaSlow(int len, u32 source) source >>= 1; mask >>= 1; - switch (Pico.video.type) + switch (pvid->type) { case 1: // vram e = a + len*2-1; @@ -604,7 +608,8 @@ static void DmaSlow(int len, u32 source) case 3: // cram Pico.m.dirtyPal = 1; r = PicoMem.cram; - if (inc == 0 && (Pico.video.reg[7] & 0x3f) == ((a/2) & 0x3f)) { // bg color DMA + if (inc == 0 && !(pvid->reg[1] & 0x40) && + (pvid->reg[7] & 0x3f) == ((a/2) & 0x3f)) { // bg color DMA PicoVideoSync(1); int sl = VdpFIFO.fifo_hcounts[lc/clkdiv]; if (sl > VdpFIFO.fifo_hcounts[0]-5) // hint delay is 5 slots @@ -612,6 +617,9 @@ static void DmaSlow(int len, u32 source) // TODO this is needed to cover timing inaccuracies if (sl <= 12) sl = -2; PicoDrawBgcDMA(base, source, mask, len, sl); + // do last DMA cycle since it's all going to the same cram location + source = source+len-1; + len = 1; } for (; len; len--) { @@ -642,20 +650,21 @@ static void DmaSlow(int len, u32 source) break; default: - if (Pico.video.type != 0 || (EL_LOGMASK & EL_VDPDMA)) - elprintf(EL_VDPDMA|EL_ANOMALY, "DMA with bad type %i", Pico.video.type); + if (pvid->type != 0 || (EL_LOGMASK & EL_VDPDMA)) + elprintf(EL_VDPDMA|EL_ANOMALY, "DMA with bad type %i", pvid->type); break; } // remember addr - Pico.video.addr = a; - Pico.video.addr_u = a >> 16; + pvid->addr = a; + pvid->addr_u = a >> 16; } static void DmaCopy(int len) { - u32 a = Pico.video.addr | (Pico.video.addr_u << 16); + struct PicoVideo *pvid=&Pico.video; + u32 a = pvid->addr | (pvid->addr_u << 16); u8 *vr = (u8 *)PicoMem.vram; - u8 inc = Pico.video.reg[0xf]; + u8 inc = pvid->reg[0xf]; int source; elprintf(EL_VDPDMA, "DmaCopy len %i [%u]", len, SekCyclesDone()); @@ -663,8 +672,8 @@ static void DmaCopy(int len) SekCyclesBurnRun(PicoVideoFIFOWrite(2*len, FQ_BGDMA, // 2 slots each (rd+wr) PVS_CPUWR, SR_DMA | PVS_DMABG)); - source =Pico.video.reg[0x15]; - source|=Pico.video.reg[0x16]<<8; + source =pvid->reg[0x15]; + source|=pvid->reg[0x16]<<8; for (; len; len--) { @@ -675,16 +684,17 @@ static void DmaCopy(int len) a = (a+inc) & ~0x20000; } // remember addr - Pico.video.addr = a; - Pico.video.addr_u = a >> 16; + pvid->addr = a; + pvid->addr_u = a >> 16; } static NOINLINE void DmaFill(int data) { - u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e; + struct PicoVideo *pvid=&Pico.video; + u32 a = pvid->addr | (pvid->addr_u << 16), e; u8 *vr = (u8 *)PicoMem.vram; u8 high = (u8)(data >> 8); - u8 inc = Pico.video.reg[0xf]; + u8 inc = pvid->reg[0xf]; int source; int len, l; @@ -694,7 +704,7 @@ static NOINLINE void DmaFill(int data) SekCyclesBurnRun(PicoVideoFIFOWrite(len, FQ_BGDMA, // 1 slot each (wr) PVS_CPUWR | PVS_DMAFILL, SR_DMA | PVS_DMABG)); - switch (Pico.video.type) + switch (pvid->type) { case 1: // vram e = a + len-1; @@ -751,16 +761,15 @@ static NOINLINE void DmaFill(int data) } // remember addr - Pico.video.addr = a; - Pico.video.addr_u = a >> 16; + pvid->addr = a; + pvid->addr_u = a >> 16; // register update - Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; - source = Pico.video.reg[0x15]; - source |= Pico.video.reg[0x16] << 8; + pvid->reg[0x13] = pvid->reg[0x14] = 0; + source = pvid->reg[0x15]; + source |= pvid->reg[0x16] << 8; source += len; - Pico.video.reg[0x15] = source; - Pico.video.reg[0x16] = source >> 8; - + pvid->reg[0x15] = source; + pvid->reg[0x16] = source >> 8; } // VDP command handling @@ -780,9 +789,9 @@ static NOINLINE void CommandDma(void) } len = GetDmaLength(); - source =Pico.video.reg[0x15]; - source|=Pico.video.reg[0x16] << 8; - source|=Pico.video.reg[0x17] << 16; + source = pvid->reg[0x15]; + source |= pvid->reg[0x16] << 8; + source |= pvid->reg[0x17] << 16; method=pvid->reg[0x17]>>6; if (method < 2) @@ -794,9 +803,9 @@ static NOINLINE void CommandDma(void) return; } source += len; - Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; - Pico.video.reg[0x15] = source; - Pico.video.reg[0x16] = source >> 8; + pvid->reg[0x13] = pvid->reg[0x14] = 0; + pvid->reg[0x15] = source; + pvid->reg[0x16] = source >> 8; } static NOINLINE void CommandChange(struct PicoVideo *pvid) @@ -893,7 +902,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) SekCyclesBurnRun(PicoVideoFIFOWrite(1, pvid->type == 1, 0, PVS_CPUWR)); elprintf(EL_ASVDP, "VDP data write: [%04x] %04x [%u] {%i} @ %06x", - Pico.video.addr, d, SekCyclesDone(), Pico.video.type, SekPc); + pvid->addr, d, SekCyclesDone(), pvid->type, SekPc); } VideoWrite(d); @@ -948,7 +957,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) lineenabled = (d&0x40) ? Pico.m.scanline : -1; linedisabled = (d&0x40) ? -1 : Pico.m.scanline; lineoffset = SekCyclesDone() - Pico.t.m68c_line_start; - } else if (((1<reg[num] != d) + } else if (((1<reg[num] != d) // VDP regs 0-7,11-13,16-18 influence rendering, ignore all others PicoVideoSync(InHblank(93)); // Toy Story pvid->reg[num] = d; @@ -1064,11 +1073,11 @@ static u32 VideoSr(const struct PicoVideo *pv) PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) { + struct PicoVideo *pv = &Pico.video; a &= 0x1c; if (a == 0x04) // control port { - struct PicoVideo *pv = &Pico.video; u32 d = VideoSr(pv); if (pv->pending) { CommandChange(pv); @@ -1078,17 +1087,17 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) return d; } - if ((a&0x1c)==0x08) + if (a == 0x08) { unsigned int c; u32 d; c = SekCyclesDone() - Pico.t.m68c_line_start; - if (Pico.video.reg[0]&2) - d = Pico.video.hv_latch; - else d = VdpFIFO.fifo_hcounts[c/clkdiv] | (Pico.video.v_counter << 8); + if (pv->reg[0]&2) + d = pv->hv_latch; + else d = VdpFIFO.fifo_hcounts[c/clkdiv] | (pv->v_counter << 8); - elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc); + elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, pv->v_counter, SekCyclesDone(), SekPc); return d; } @@ -1097,7 +1106,7 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a) return VideoRead(0); } - return 0; + return PicoRead16_floating(a | 0xc00000); } unsigned char PicoVideoRead8DataH(int is_from_z80) diff --git a/pico/z80if.c b/pico/z80if.c index 7fbfc3421..558607c6e 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -112,18 +112,13 @@ void z80_reset(void) drZ80.Z80IF = 0; drZ80.z80irqvector = 0xff0000; // RST 38h drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1; - // others not changed, undefined on cold boot -/* - drZ80.Z80F = (1<<2); // set ZFlag - drZ80.Z80F2 = (1<<2); // set ZFlag - drZ80.Z80IX = 0xFFFF << 16; - drZ80.Z80IY = 0xFFFF << 16; -*/ + // other registers not changed, undefined on cold boot #ifdef FAST_Z80SP // drZ80 is locked in single bank drz80_sp_base = (PicoIn.AHW & PAHW_SMS) ? 0xc000 : 0x0000; drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1; #endif + drZ80.Z80SP = drZ80.Z80SP_BASE + 0xffff; drZ80.z80_irq_callback = NULL; // use auto-clear if (PicoIn.AHW & PAHW_SMS) { drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS @@ -134,6 +129,7 @@ void z80_reset(void) #endif #ifdef _USE_CZ80 Cz80_Reset(&CZ80); + Cz80_Set_Reg(&CZ80, CZ80_SP, 0xffff); if (PicoIn.AHW & PAHW_SMS) Cz80_Set_Reg(&CZ80, CZ80_SP, 0xdff0); #endif @@ -213,7 +209,7 @@ void z80_pack(void *data) s->iff1 = !!zIFF1; s->iff2 = !!zIFF2; s->im = zIM; - s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) == HOLD_LINE); + s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) != CLEAR_LINE); s->irq_vector[0] = 0xff; } #endif @@ -280,7 +276,8 @@ int z80_unpack(const void *data) Cz80_Set_Reg(&CZ80, CZ80_IFF1, s->iff1); Cz80_Set_Reg(&CZ80, CZ80_IFF2, s->iff2); zIM = s->im; - Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? HOLD_LINE : CLEAR_LINE); + Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? ASSERT_LINE : CLEAR_LINE); + Cz80_Set_IRQ(&CZ80, 0, Cz80_Get_Reg(&CZ80, CZ80_IRQ)); return 0; } #else diff --git a/platform/base_readme.txt b/platform/base_readme.txt index 5925a4725..d45752157 100644 --- a/platform/base_readme.txt +++ b/platform/base_readme.txt @@ -26,8 +26,6 @@ the root of SD, etc). If you are running a custom firmware, just copy the whole PicoDrive directory to /PSP/GAME or /PSP/GAMEXXX directory in your memory stick (it shouldn't matter which one GAME* directory to use). - -If you are on 1.5, there is a separate KXploited version for it. #endif #ifdef PANDORA Just copy the .pnd to /pandora/menu or /pandora/desktop. diff --git a/platform/common/common.mak b/platform/common/common.mak index 550de72f9..68ca6ff6b 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -205,8 +205,9 @@ $(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/$(CYCLONE_CONFIG) $(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/cyclone/*.cpp $(FR)cpu/cyclone/*.h -$(FR)cpu/musashi/m68kops.c: +$(FR)cpu/musashi/m68kops.c: $(FR)cpu/musashi/m68k_in.c @make -C $(R)cpu/musashi +$(FR)cpu/musashi/m68kcpu.c: $(FR)cpu/musashi/m68kops.c deps_set = yes endif # deps_set diff --git a/platform/common/emu.c b/platform/common/emu.c index 309178c5a..051f8b4d0 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2007-2010 + * (C) irixxxx, 2019-2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -19,6 +20,7 @@ #include "../libpicofe/fonts.h" #include "../libpicofe/sndout.h" #include "../libpicofe/lprintf.h" +#include "../libpicofe/readpng.h" #include "../libpicofe/plat.h" #include "emu.h" #include "input_pico.h" @@ -618,7 +620,7 @@ void emu_prep_defconfig(void) { memset(&defaultConfig, 0, sizeof(defaultConfig)); defaultConfig.EmuOpt = EOPT_EN_SRAM | EOPT_EN_SOUND | EOPT_16BPP | - EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | 0x10/*?*/; + EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | EOPT_PICO_PEN; defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_GG_LCD|POPT_EN_YM2413 | POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX | @@ -1041,20 +1043,76 @@ void emu_reset_game(void) reset_timing = 1; } -void run_events_pico(unsigned int events) +static int pico_page; +static int pico_w, pico_h; +static u16 *pico_overlay; + +static u16 *load_pico_overlay(int page, int w, int h) { - if (events & PEV_PICO_SWINP) { - pico_inp_mode++; - if (pico_inp_mode > 2) - pico_inp_mode = 0; - switch (pico_inp_mode) { - case 2: emu_status_msg("Input: Pen on Pad"); break; - case 1: emu_status_msg("Input: Pen on Storyware"); break; - case 0: emu_status_msg("Input: Joystick"); - PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; - break; + static const char *pic_exts[] = { "png", "PNG" }; + char *ext, *fname = NULL; + int extpos, i; + + if (pico_page == page && pico_w == w && pico_h == h) + return pico_overlay; + pico_page = page; + pico_w = w, pico_h = h; + + ext = strrchr(rom_fname_loaded, '.'); + extpos = ext ? ext-rom_fname_loaded : strlen(rom_fname_loaded); + strcpy(static_buff, rom_fname_loaded); + static_buff[extpos++] = '_'; + if (page < 0) { + static_buff[extpos++] = 'p'; + static_buff[extpos++] = 'a'; + static_buff[extpos++] = 'd'; + } else + static_buff[extpos++] = '0'+PicoPicohw.page; + static_buff[extpos++] = '.'; + + for (i = 0; i < ARRAY_SIZE(pic_exts); i++) { + strcpy(static_buff+extpos, pic_exts[i]); + if (access(static_buff, R_OK) == 0) { + printf("found Pico file: %s\n", static_buff); + fname = static_buff; + break; } } + + pico_overlay = realloc(pico_overlay, w*h*2); + memset(pico_overlay, 0, w*h*2); + if (!fname || !pico_overlay || readpng(pico_overlay, fname, READPNG_SCALE, w, h)) { + if (pico_overlay) + free(pico_overlay); + pico_overlay = NULL; + } + + return pico_overlay; +} + +void emu_pico_overlay(u16 *pd, int w, int h, int pitch) +{ + u16 *overlay = NULL; + int y, oh = h; + + // get overlay + if (pico_inp_mode == 1) { + oh = (w/2 < h ? w/2 : h); // storyware has squished h + overlay = load_pico_overlay(PicoPicohw.page, w, oh); + } else if (pico_inp_mode == 2) + overlay = load_pico_overlay(-1, w, oh); + + // copy overlay onto buffer + if (overlay) { + for (y = 0; y < oh; y++) + memcpy(pd + y*pitch, overlay + y*w, w*2); + if (y < h) + memset(pd + y*pitch, 0, w*2); + } +} + +void run_events_pico(unsigned int events) +{ if (events & PEV_PICO_PPREV) { PicoPicohw.page--; if (PicoPicohw.page < 0) @@ -1067,11 +1125,35 @@ void run_events_pico(unsigned int events) PicoPicohw.page = 6; emu_status_msg("Page %i", PicoPicohw.page); } - if (events & PEV_PICO_PEN) { - currentConfig.EmuOpt ^= EOPT_PICO_PEN; - emu_status_msg("%s Pen", currentConfig.EmuOpt & EOPT_PICO_PEN ? "Show" : "Hide"); + if (events & PEV_PICO_STORY) { + if (pico_inp_mode == 1) { + pico_inp_mode = 0; + emu_status_msg("Input: D-Pad"); + } else { + pico_inp_mode = 1; + emu_status_msg("Input: Pen on Storyware"); + } + } + if (events & PEV_PICO_PAD) { + if (pico_inp_mode == 2) { + pico_inp_mode = 0; + emu_status_msg("Input: D-Pad"); + } else { + pico_inp_mode = 2; + emu_status_msg("Input: Pen on Pad"); + } + } + if (events & PEV_PICO_PENST) { + PicoPicohw.pen_pos[0] ^= 0x8000; + PicoPicohw.pen_pos[1] ^= 0x8000; + emu_status_msg("Pen %s", PicoPicohw.pen_pos[0] & 0x8000 ? "Up" : "Down"); } + if ((currentConfig.EmuOpt & EOPT_PICO_PEN) && + (PicoIn.pad[0]&0x20) && pico_inp_mode && pico_overlay) { + pico_inp_mode = 0; + emu_status_msg("Input: D-Pad"); + } if (pico_inp_mode == 0) return; @@ -1082,17 +1164,20 @@ void run_events_pico(unsigned int events) if (PicoIn.pad[0] & 8) pico_pen_x++; PicoIn.pad[0] &= ~0x0f; // release UDLR + /* cursor position, cursor drawing must not cross screen borders */ if (pico_pen_y < PICO_PEN_ADJUST_Y) pico_pen_y = PICO_PEN_ADJUST_Y; - if (pico_pen_y > 224 - PICO_PEN_ADJUST_Y) - pico_pen_y = 224 - PICO_PEN_ADJUST_Y; + if (pico_pen_y > 223-1 - PICO_PEN_ADJUST_Y) + pico_pen_y = 223-1 - PICO_PEN_ADJUST_Y; if (pico_pen_x < PICO_PEN_ADJUST_X) pico_pen_x = PICO_PEN_ADJUST_X; - if (pico_pen_x > 320 - PICO_PEN_ADJUST_X) - pico_pen_x = 320 - PICO_PEN_ADJUST_X; + if (pico_pen_x > 319-1 - PICO_PEN_ADJUST_X) + pico_pen_x = 319-1 - PICO_PEN_ADJUST_X; - PicoPicohw.pen_pos[0] = 0x03c + pico_pen_x; - PicoPicohw.pen_pos[1] = pico_inp_mode == 1 ? (0x2f8 + pico_pen_y) : (0x1fc + pico_pen_y); + PicoPicohw.pen_pos[0] &= 0x8000; + PicoPicohw.pen_pos[1] &= 0x8000; + PicoPicohw.pen_pos[0] |= 0x03c + pico_pen_x; + PicoPicohw.pen_pos[1] |= (pico_inp_mode == 1 ? 0x2f8 : 0x1fc) + pico_pen_y; } static void do_turbo(unsigned short *pad, int acts) @@ -1243,7 +1328,7 @@ static void mkdir_path(char *path_with_reserve, int pos, const char *name) strcpy(path_with_reserve + pos, name); if (plat_is_dir(path_with_reserve)) return; - if (mkdir(path_with_reserve, 0777) < 0) + if (mkdir(path_with_reserve, 0755) < 0) lprintf("failed to create: %s\n", path_with_reserve); } @@ -1349,15 +1434,16 @@ void emu_sound_start(void) { int is_stereo = (PicoIn.opt & POPT_EN_STEREO) ? 1 : 0; + memset(sndBuffer, 0, sizeof(sndBuffer)); + PicoIn.sndOut = sndBuffer; PsndRerate(Pico.m.frame_count ? 1 : 0); printf("starting audio: %i len: %i stereo: %i, pal: %i\n", PicoIn.sndRate, Pico.snd.len, is_stereo, Pico.m.pal); + sndout_start(PicoIn.sndRate, is_stereo); PicoIn.writeSound = snd_write_nonblocking; plat_update_volume(0, 0); - memset(sndBuffer, 0, sizeof(sndBuffer)); - PicoIn.sndOut = sndBuffer; } } @@ -1395,17 +1481,17 @@ static void emu_loop_prep(void) } /* our tick here is 1 us right now */ -#define ms_to_ticks(x) (int)(x * 1000) -#define get_ticks() plat_get_ticks_us() -#define vsync_delay_x3 3*ms_to_ticks(1) +#define ms_to_ticks(x) (int)(x * 1000) +#define get_ticks() plat_get_ticks_us() +#define vsync_delay ms_to_ticks(1) void emu_loop(void) { int frames_done, frames_shown; /* actual frames for fps counter */ - int target_frametime_x3; - unsigned int timestamp_x3 = 0; - unsigned int timestamp_aim_x3 = 0; - unsigned int timestamp_fps_x3 = 0; + int target_frametime; + unsigned int timestamp = 0; + unsigned int timestamp_aim = 0; + unsigned int timestamp_fps = 0; char *notice_msg = NULL; char fpsbuff[24]; int fskip_cnt = 0; @@ -1420,9 +1506,9 @@ void emu_loop(void) /* number of ticks per frame */ if (Pico.m.pal) - target_frametime_x3 = 3 * ms_to_ticks(1000) / 50; + target_frametime = ms_to_ticks(1000) / 50; else - target_frametime_x3 = 3 * ms_to_ticks(1000) / 60; + target_frametime = ms_to_ticks(1000) / 60; reset_timing = 1; frames_done = frames_shown = 0; @@ -1438,22 +1524,22 @@ void emu_loop(void) if (reset_timing) { reset_timing = 0; plat_video_wait_vsync(); - timestamp_aim_x3 = get_ticks() * 3; - timestamp_fps_x3 = timestamp_aim_x3; + timestamp_aim = get_ticks(); + timestamp_fps = timestamp_aim; fskip_cnt = 0; } else if (currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) { - timestamp_aim_x3 = get_ticks() * 3; + timestamp_aim = get_ticks(); } - timestamp_x3 = get_ticks() * 3; + timestamp = get_ticks(); // show notice_msg message? if (notice_msg_time != 0) { static int noticeMsgSum; - if (timestamp_x3 - ms_to_ticks(notice_msg_time) * 3 - > ms_to_ticks(STATUS_MSG_TIMEOUT) * 3) + if (timestamp - ms_to_ticks(notice_msg_time) + > ms_to_ticks(STATUS_MSG_TIMEOUT)) { notice_msg_time = 0; notice_msg = NULL; @@ -1470,7 +1556,7 @@ void emu_loop(void) } // second changed? - if (timestamp_x3 - timestamp_fps_x3 >= ms_to_ticks(1000) * 3) + if (timestamp - timestamp_fps >= ms_to_ticks(1000)) { #ifdef BENCHMARK static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; @@ -1488,13 +1574,13 @@ void emu_loop(void) snprintf(fpsbuff, 8, "%02i/%02i ", frames_shown, frames_done); #endif frames_shown = frames_done = 0; - timestamp_fps_x3 += ms_to_ticks(1000) * 3; + timestamp_fps += ms_to_ticks(1000); } #ifdef PFRAMES sprintf(fpsbuff, "%i", Pico.m.frame_count); #endif - diff = timestamp_aim_x3 - timestamp_x3; + diff = timestamp_aim - timestamp; if (currentConfig.Frameskip >= 0) // frameskip enabled (or 0) { @@ -1506,7 +1592,7 @@ void emu_loop(void) fskip_cnt = 0; } } - else if (diff < -target_frametime_x3) + else if (diff < -target_frametime) { /* no time left for this frame - skip */ /* limit auto frameskip to max_skip */ @@ -1521,14 +1607,14 @@ void emu_loop(void) fskip_cnt = 0; // don't go in debt too much - while (diff < -target_frametime_x3 * 3) { - timestamp_aim_x3 += target_frametime_x3; - diff = timestamp_aim_x3 - timestamp_x3; + while (diff < -target_frametime * 3) { + timestamp_aim += target_frametime; + diff = timestamp_aim - timestamp; } emu_update_input(); if (skip) { - int do_audio = diff > -target_frametime_x3 * 2; + int do_audio = diff > -target_frametime * 2; PicoIn.skipFrame = do_audio ? 1 : 2; PicoFrame(); PicoIn.skipFrame = 0; @@ -1539,7 +1625,7 @@ void emu_loop(void) frames_shown++; } frames_done++; - timestamp_aim_x3 += target_frametime_x3; + timestamp_aim += target_frametime; if (!skip && !flip_after_sync) plat_video_flip(); @@ -1549,18 +1635,18 @@ void emu_loop(void) && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) { unsigned int timestamp = get_ticks(); - diff = timestamp_aim_x3 - timestamp * 3; + diff = timestamp_aim - timestamp; // sleep or vsync if we are still too fast - if (diff > target_frametime_x3 + vsync_delay_x3 && (currentConfig.EmuOpt & EOPT_VSYNC)) { + if (diff > target_frametime + vsync_delay && (currentConfig.EmuOpt & EOPT_VSYNC)) { // we are too fast plat_video_wait_vsync(); timestamp = get_ticks(); - diff = timestamp_aim_x3 - timestamp * 3; + diff = timestamp_aim - timestamp; } - if (diff > target_frametime_x3 + vsync_delay_x3) { + if (diff > target_frametime + vsync_delay) { // still too fast - plat_wait_till_us(timestamp + (diff - target_frametime_x3) / 3); + plat_wait_till_us(timestamp + (diff - target_frametime)); } } diff --git a/platform/common/emu.h b/platform/common/emu.h index d32cf7058..c477883ef 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -107,8 +107,8 @@ extern unsigned char *movie_data; extern int reset_timing; extern int flip_after_sync; -#define PICO_PEN_ADJUST_X 2 -#define PICO_PEN_ADJUST_Y 2 +#define PICO_PEN_ADJUST_X 1 +#define PICO_PEN_ADJUST_Y 1 extern int pico_pen_x, pico_pen_y; extern int pico_inp_mode; @@ -160,6 +160,8 @@ void emu_get_game_name(char *str150); void emu_set_fastforward(int set_on); void emu_status_msg(const char *format, ...); +void emu_pico_overlay(unsigned short *pd, int w, int h, int pitch); + /* default sound code */ void emu_sound_start(void); void emu_sound_stop(void); diff --git a/platform/common/input_pico.h b/platform/common/input_pico.h index b3138d0b3..2f3de4186 100644 --- a/platform/common/input_pico.h +++ b/platform/common/input_pico.h @@ -27,9 +27,10 @@ #define PEVB_FF 22 #define PEVB_PICO_PNEXT 21 #define PEVB_PICO_PPREV 20 -#define PEVB_PICO_SWINP 19 -#define PEVB_PICO_PEN 18 -#define PEVB_RESET 17 +#define PEVB_PICO_STORY 19 +#define PEVB_PICO_PAD 18 +#define PEVB_PICO_PENST 17 +#define PEVB_RESET 16 #define PEV_VOL_DOWN (1 << PEVB_VOL_DOWN) #define PEV_VOL_UP (1 << PEVB_VOL_UP) @@ -42,10 +43,11 @@ #define PEV_FF (1 << PEVB_FF) #define PEV_PICO_PNEXT (1 << PEVB_PICO_PNEXT) #define PEV_PICO_PPREV (1 << PEVB_PICO_PPREV) -#define PEV_PICO_SWINP (1 << PEVB_PICO_SWINP) -#define PEV_PICO_PEN (1 << PEVB_PICO_PEN) +#define PEV_PICO_STORY (1 << PEVB_PICO_STORY) +#define PEV_PICO_PAD (1 << PEVB_PICO_PAD) +#define PEV_PICO_PENST (1 << PEVB_PICO_PENST) #define PEV_RESET (1 << PEVB_RESET) -#define PEV_MASK 0x7ffe0000 +#define PEV_MASK 0x7fff0000 #endif /* INCLUDE_c48097f3ff2a6a9af1cce8fd7a9b3f0c */ diff --git a/platform/common/inputmap_kbd.c b/platform/common/inputmap_kbd.c index 038651122..c41abbb38 100644 --- a/platform/common/inputmap_kbd.c +++ b/platform/common/inputmap_kbd.c @@ -29,8 +29,9 @@ const struct in_default_bind in_sdl_defbinds[] = { { SDLK_F5, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, { SDLK_F6, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, { SDLK_F7, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, - { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, - { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_PEN }, + { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_STORY }, + { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_PAD }, + { SDLK_F10, IN_BINDTYPE_EMU, PEVB_PICO_PENST }, { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF }, { 0, 0, 0 } }; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 1492738ad..00f2aa690 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2010,2011 + * (C) irixxxx, 2023,2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -14,25 +15,19 @@ #include "input_pico.h" #include "version.h" +#include "../libpicofe/plat.h" + #include #include -#ifdef PANDORA +#if defined(PANDORA) || defined(__PS2__) #define MENU_X2 1 #else #define MENU_X2 0 #endif -#if defined USE_BGR555 -#define COL_ROM 0x5eff -#define COL_OTH 0x5ff5 -#elif defined USE_BGR565 -#define COL_ROM 0xfdf7 -#define COL_OTH 0xaff5 -#else -#define COL_ROM 0xbdff -#define COL_OTH 0xaff5 -#endif +#define COL_ROM PXMAKE(0xbf, 0xbf, 0xff) +#define COL_OTH PXMAKE(0xaf, 0xff, 0xaf) // FIXME #ifndef REVISION @@ -65,7 +60,7 @@ static unsigned short fname2color(const char *fname) if (strcasecmp(ext, rom_exts[i]) == 0) return COL_ROM; for (i = 0; i < array_size(other_exts); i++) if (strcasecmp(ext, other_exts[i]) == 0) return COL_OTH; - return 0xffff; + return PXMAKE(0xff, 0xff, 0xff); } #include @@ -78,6 +73,8 @@ static int menu_w, menu_h; #include #elif defined(__PSP__) #include +#elif defined(__PS2__) +#include #elif defined(PANDORA) #include #else @@ -113,7 +110,7 @@ static void make_bg(int no_scale, int from_screen) for (y = 0; y < h; y++, src += pp, d += g_menuscreen_w*2/2) { for (x = 0; x < w; x++) { t = src[x]; - t = ((t & 0xf79e)>>1) - ((t & 0xc618)>>3); + t = (PXMASKH(t,1)>>1) - (PXMASKH(t,3)>>3); t |= t << 16; d[x] = d[x + g_menuscreen_w / 2] = t; } @@ -232,8 +229,8 @@ static void cdload_progress_cb(const char *fname, int percent) copy_bg(0); menuscreen_memset_lines(dst, 0xff, me_sfont_h - 2); - smalltext_out16(1, 3 * me_sfont_h, "Processing CD image / MP3s", 0xffff); - smalltext_out16(1, 4 * me_sfont_h, fname, 0xffff); + smalltext_out16(1, 3 * me_sfont_h, "Processing CD image / MP3s", PXMAKE(0xff, 0xff, 0xff)); + smalltext_out16(1, 4 * me_sfont_h, fname, PXMAKE(0xff, 0xff, 0xff)); dst += g_menuscreen_pp * me_sfont_h * 3; if (len > g_menuscreen_w) @@ -254,8 +251,8 @@ void menu_romload_prepare(const char *rom_name) p--; menu_draw_begin(1, 1); - smalltext_out16(1, 1, "Loading", 0xffff); - smalltext_out16(1, me_sfont_h, p, 0xffff); + smalltext_out16(1, 1, "Loading", PXMAKE(0xff, 0xff, 0xff)); + smalltext_out16(1, me_sfont_h, p, PXMAKE(0xff, 0xff, 0xff)); /* copy menu to bg for callbacks. OK since we are not in menu_loop here */ copy_bg(1); menu_draw_end(); @@ -273,7 +270,7 @@ void menu_romload_end(void) menu_draw_begin(0, 1); copy_bg(0); smalltext_out16(1, (cdload_called ? 6 : 3) * me_sfont_h, - "Starting emulation...", 0xffff); + "Starting emulation...", PXMAKE(0xff, 0xff, 0xff)); menu_draw_end(); } @@ -293,12 +290,12 @@ static void draw_patchlist(int sel) if (pos < 0) continue; if (pos >= max_cnt) break; active = PicoPatches[i].active; - smalltext_out16(14, pos * me_sfont_h, active ? "ON " : "OFF", active ? 0xfff6 : 0xffff); - smalltext_out16(14 + me_sfont_w*4, pos * me_sfont_h, PicoPatches[i].name, active ? 0xfff6 : 0xffff); + smalltext_out16(14, pos * me_sfont_h, active ? "ON " : "OFF", PXMAKE(0xff, 0xff, active ? 0xff : 0xb0)); + smalltext_out16(14 + me_sfont_w*4, pos * me_sfont_h, PicoPatches[i].name, PXMAKE(0xff, 0xff, active ? 0xff : 0xb0)); } pos = start + i; if (pos < max_cnt) - smalltext_out16(14, pos * me_sfont_h, "done", 0xffff); + smalltext_out16(14, pos * me_sfont_h, "done", PXMAKE(0xff, 0xff, 0xff)); text_out16(5, max_cnt / 2 * me_sfont_h, ">"); menu_draw_end(); @@ -353,20 +350,21 @@ me_bind_action me_ctrl_actions[] = me_bind_action emuctrl_actions[] = { - { "Load State ", PEV_STATE_LOAD }, - { "Save State ", PEV_STATE_SAVE }, - { "Prev Save Slot ", PEV_SSLOT_PREV }, - { "Next Save Slot ", PEV_SSLOT_NEXT }, - { "Switch Renderer ", PEV_SWITCH_RND }, - { "Volume Down ", PEV_VOL_DOWN }, - { "Volume Up ", PEV_VOL_UP }, - { "Fast forward ", PEV_FF }, - { "Reset Game ", PEV_RESET }, - { "Enter Menu ", PEV_MENU }, - { "Pico Next page ", PEV_PICO_PNEXT }, - { "Pico Prev page ", PEV_PICO_PPREV }, - { "Pico Switch input", PEV_PICO_SWINP }, - { "Pico Display pen ", PEV_PICO_PEN }, + { "Load State ", PEV_STATE_LOAD }, + { "Save State ", PEV_STATE_SAVE }, + { "Prev Save Slot ", PEV_SSLOT_PREV }, + { "Next Save Slot ", PEV_SSLOT_NEXT }, + { "Switch Renderer", PEV_SWITCH_RND }, + { "Volume Down ", PEV_VOL_DOWN }, + { "Volume Up ", PEV_VOL_UP }, + { "Fast forward ", PEV_FF }, + { "Reset Game ", PEV_RESET }, + { "Enter Menu ", PEV_MENU }, + { "Pico Next page ", PEV_PICO_PNEXT }, + { "Pico Prev page ", PEV_PICO_PPREV }, + { "Pico Storyware ", PEV_PICO_STORY }, + { "Pico Pad ", PEV_PICO_PAD }, + { "Pico Pen state ", PEV_PICO_PENST }, { NULL, 0 } }; @@ -466,15 +464,17 @@ static const char h_fmsound[] = "Disabling improves performance, but breaks sou static const char h_dacnoise[] = "FM chips in the 1st Mega Drive model have DAC noise,\n" "newer models used different chips without this"; static const char h_fmfilter[] = "Improves sound accuracy but is noticeably slower,\n" - "best´quality if native rate isn't working"; + "best quality if native rate isn't working"; +static const char h_picopen[] = "Enabling resets Pico display and d-pad input back to\n" + "screen if the Pico pen button is pressed"; static menu_entry e_menu_md_options[] = { - mee_enum_h ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names, h_renderer), - mee_onoff_h ("FM audio", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM, h_fmsound), - mee_onoff_h ("FM filter", MA_OPT_FM_FILTER, PicoIn.opt, POPT_EN_FM_FILTER, h_fmfilter), - mee_onoff_h ("FM DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC, h_dacnoise), - mee_onoff ("Show Pico pen", MA_OPT_PICO_PEN, currentConfig.EmuOpt, EOPT_PICO_PEN), + mee_enum_h ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names, h_renderer), + mee_onoff_h ("FM audio", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM, h_fmsound), + mee_onoff_h ("FM filter", MA_OPT_FM_FILTER, PicoIn.opt, POPT_EN_FM_FILTER, h_fmfilter), + mee_onoff_h ("FM DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC, h_dacnoise), + mee_onoff_h ("Pen button shows screen", MA_OPT_PICO_PEN, currentConfig.EmuOpt, EOPT_PICO_PEN, h_picopen), mee_end, }; @@ -643,10 +643,12 @@ static int menu_loop_adv_options(int id, int keys) static int sndrate_prevnext(int rate, int dir) { - static const int rates[] = { 8000, 11025, 16000, 22050, 44100, 53000 }; - int rate_count = sizeof(rates)/sizeof(rates[0]); + const int *rates = plat_target.sound_rates; + int rate_count; int i; + for (rate_count = 0; rates[rate_count] != -1; rate_count++) + ; for (i = 0; i < rate_count; i++) if (rates[i] == rate) break; @@ -1009,7 +1011,7 @@ static void draw_text_debug(const char *str, int skip, int from) str = p; for (line = from; line < g_menuscreen_h / me_sfont_h; line++) { - smalltext_out16(1, line * me_sfont_h, str, 0xffff); + smalltext_out16(1, line * me_sfont_h, str, PXMAKE(0xff, 0xff, 0xff)); while (*p && *p != '\n') p++; if (*p == 0) @@ -1038,8 +1040,8 @@ static void draw_frame_debug(void) pemu_forced_frame(1, 0); make_bg(1, 1); - smalltext_out16(4, 1, "build: r" REVISION " "__DATE__ " " __TIME__ " " COMPILER, 0xffff); - smalltext_out16(4, g_menuscreen_h - me_sfont_h, layer_str, 0xffff); + smalltext_out16(4, 1, "build: r" REVISION " "__DATE__ " " __TIME__ " " COMPILER, PXMAKE(0xff, 0xff, 0xff)); + smalltext_out16(4, g_menuscreen_h - me_sfont_h, layer_str, PXMAKE(0xff, 0xff, 0xff)); } static void debug_menu_loop(void) @@ -1063,7 +1065,7 @@ static void debug_menu_loop(void) draw_text_debug(tmp, 0, 0); if (dumped) { smalltext_out16(g_menuscreen_w - 6 * me_sfont_h, - g_menuscreen_h - me_mfont_h, "dumped", 0xffff); + g_menuscreen_h - me_mfont_h, "dumped", PXMAKE(0xff, 0xff, 0xff)); dumped = 0; } break; @@ -1137,7 +1139,7 @@ static void debug_menu_loop(void) static void draw_frame_credits(void) { - smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__, 0xe7fc); + smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__, PXMAKE(0xe0, 0xff, 0xe0)); } static const char credits[] = @@ -1296,8 +1298,6 @@ static const char *mgn_picopage(int id, int *offs) static int mh_picopage(int id, int keys) { - int ret; - if (keys & (PBTN_LEFT|PBTN_RIGHT)) { // multi choice PicoPicohw.page += (keys & PBTN_LEFT) ? -1 : 1; if (PicoPicohw.page < 0) PicoPicohw.page = 6; diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index c47ef1b7f..785fb1bf7 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -30,7 +30,8 @@ static struct in_pdata in_sdl_platform_data = { .defbinds = in_sdl_defbinds, }; -struct plat_target plat_target; +static int sound_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 53000, -1 }; +struct plat_target plat_target = { .sound_rates = sound_rates }; #if defined __MIYOO__ const char *plat_device = "miyoo"; diff --git a/platform/common/version.h b/platform/common/version.h index db39ac35a..65c9150e0 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "pre-2.00-alpha3" REVISION +#define VERSION "pre-2.00-beta1" REVISION diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index d59f3ecae..aae7fbd53 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -194,10 +194,14 @@ static void draw_cd_leds(void) static void draw_pico_ptr(void) { + int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000; int x, y, pitch = 320, offs; + // storyware pages are actually squished, 2:1 + int h = (pico_inp_mode == 1 ? 160 : linecount); + if (h < 224) y++; - x = ((pico_pen_x * colcount * ((1ULL<<32) / 320)) >> 32) + firstcol; - y = ((pico_pen_y * linecount * ((1ULL<<32) / 224)) >> 32) + firstline; + x = ((pico_pen_x * colcount * ((1ULL<<32)/320 + 1)) >> 32) + firstcol; + y = ((pico_pen_y * h * ((1ULL<<32)/224 + 1)) >> 32) + firstline; if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { pitch = 240; @@ -207,16 +211,20 @@ static void draw_pico_ptr(void) if (is_16bit_mode()) { unsigned short *p = (unsigned short *)g_screen_ptr + offs; + int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000); - p[0] ^= 0xffff; - p[pitch-1] ^= 0xffff; p[pitch] ^= 0xffff; p[pitch+1] ^= 0xffff; - p[pitch*2] ^= 0xffff; + p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o; + p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _; + p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _; + p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o; } else { unsigned char *p = (unsigned char *)g_screen_ptr + offs; + int o = (up ? 0xe0 : 0xf0), _ = (up ? 0xf0 : 0xe0); - p[-1] = 0xe0; p[0] = 0xf0; p[1] = 0xe0; - p[pitch-1] = 0xf0; p[pitch] = 0xf0; p[pitch+1] = 0xf0; - p[2*pitch-1] = 0xe0; p[2*pitch] = 0xf0; p[2*pitch+1] = 0xe0; + p[-pitch-1] = o; p[-pitch] = _; p[-pitch+1] = _; p[-pitch+2] = o; + p[-1] = _; p[0] = o; p[1] = o; p[2] = _; + p[pitch-1] = _; p[pitch] = o; p[pitch+1] = o; p[pitch+2] = _; + p[2*pitch-1]= o; p[2*pitch]= _; p[2*pitch+1]= _; p[2*pitch+2]= o; } } @@ -431,8 +439,15 @@ void pemu_finalize_frame(const char *fps, const char *notice) osd_text(osd_fps_x, osd_y, fps); if ((PicoIn.AHW & PAHW_MCD) && (emu_opt & EOPT_EN_CD_LEDS)) draw_cd_leds(); - if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) - if (pico_inp_mode) draw_pico_ptr(); + if (PicoIn.AHW & PAHW_PICO) { + int h = linecount, w = colcount; + u16 *pd = g_screen_ptr + firstline*g_screen_ppitch + firstcol; + + if (pico_inp_mode && is_16bit_mode()) + emu_pico_overlay(pd, w, h, g_screen_ppitch); + if (pico_inp_mode /*== 2 || overlay*/) + draw_pico_ptr(); + } } void plat_video_flip(void) @@ -778,7 +793,7 @@ void pemu_sound_start(void) } } -static const int sound_rates[] = { 53000, 44100, 32000, 22050, 16000, 11025, 8000 }; +static const int sound_rates[] = { 52000, 44100, 32000, 22050, 16000, 11025, 8000 }; void pemu_sound_stop(void) { diff --git a/platform/libpicofe b/platform/libpicofe index 7cddc27ac..4563c1316 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 7cddc27accc089fdb58e99cdac0071cc904ecef1 +Subproject commit 4563c13167deb97851397789bf2fb95bb44cf1ed diff --git a/platform/libretro/libretro-common/file/file_path.c b/platform/libretro/libretro-common/file/file_path.c index 320c5a2da..c696ff045 100644 --- a/platform/libretro/libretro-common/file/file_path.c +++ b/platform/libretro/libretro-common/file/file_path.c @@ -24,13 +24,12 @@ #include #include #include -#include +#include #include #include #include -#include #include #include #include