From: notaz Date: Sat, 14 Oct 2017 18:31:28 +0000 (+0300) Subject: Merge branch 'libretro' into libretro-reset X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a90cc666d08526ada34a87c3e6d9a5312d90be84;hp=9ae88ef15ff00cacc3877c7ecc13b0092bab50b8;p=picodrive.git Merge branch 'libretro' into libretro-reset This effectively resets libretro git to upstream and syncs both repos. Everything in platform/libretro should be retained as I imported that in my git verbatim, but some core changes may be lost and will have to be redone. I've checked that picodrive_libretro.so builds and works on x86, and Android also builds for all archs. I've even bothered to try it under msvc where it's building for me too. With this you also get the benefits from significant accuracy improvement work from 1.92. --- diff --git a/Makefile b/Makefile index 9b7e37e..f0cd64e 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,14 @@ TARGET ?= PicoDrive -DEBUG = 0 -CFLAGS += -Wall -CFLAGS += -I. -DINLINE=inline - -ifeq ($(DEBUG),1) - CFLAGS += -g -O0 -else - ifeq ($(platform), vita) - CFLAGS += -O3 -DNDEBUG - else - CFLAGS += -O2 -DNDEBUG -ffunction-sections - endif -endif - -ifneq ($(APPLE),1) - LDFLAGS += -Wl,--gc-sections +CFLAGS += -Wall -g +CFLAGS += -I. +ifndef DEBUG +CFLAGS += -O3 -DNDEBUG endif -#CFLAGS += -DEVT_LOG -#CFLAGS += -DDRC_CMP -#cpu_cmp = 1 -#drc_debug = 7 -#profile = 1 - -ifeq ($(WANT_GDB),1) -CFLAGS += ggdb -falign-functions=2 +# This is actually needed, bevieve me. +# If you really have to disable this, set NO_ALIGN_FUNCTIONS elsewhere. +ifndef NO_ALIGN_FUNCTIONS +CFLAGS += -falign-functions=2 endif all: config.mak target_ @@ -64,11 +48,6 @@ endif -include Makefile.local -ifneq "$(use_cyclone)" "1" -# due to CPU stop flag access -asm_cdmemory = 0 -endif - ifeq "$(PLATFORM)" "opendingux" opk: $(TARGET).opk @@ -84,6 +63,18 @@ OBJS += platform/opendingux/inputmap.o # OpenDingux is a generic platform, really. PLATFORM := generic endif +ifeq ("$(PLATFORM)",$(filter "$(PLATFORM)","rpi1" "rpi2")) +CFLAGS += -DHAVE_GLES -DRASPBERRY +CFLAGS += -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads/ -I/opt/vc/include/interface/vmcs_host/linux/ +LDFLAGS += -ldl -lbcm_host -L/opt/vc/lib -lEGL -lGLESv2 +OBJS += platform/linux/emu.o platform/linux/blit.o # FIXME +OBJS += platform/common/plat_sdl.o +OBJS += platform/libpicofe/plat_sdl.o platform/libpicofe/in_sdl.o +OBJS += platform/libpicofe/plat_dummy.o +OBJS += platform/libpicofe/gl.o +OBJS += platform/libpicofe/gl_platform.o +USE_FRONTEND = 1 +endif ifeq "$(PLATFORM)" "generic" OBJS += platform/linux/emu.o platform/linux/blit.o # FIXME OBJS += platform/common/plat_sdl.o @@ -120,7 +111,7 @@ USE_FRONTEND = 1 PLATFORM_MP3 = 1 endif ifeq "$(PLATFORM)" "libretro" -OBJS += platform/libretro/libretro.o +OBJS += platform/libretro/libretro.o endif ifeq "$(USE_FRONTEND)" "1" @@ -191,7 +182,7 @@ clean: $(TARGET): $(OBJS) ifeq ($(STATIC_LINKING), 1) - $(AR) rcs $@ $(OBJS) + $(AR) rcs $@ $^ else $(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS) $(LDLIBS) endif @@ -212,16 +203,27 @@ tools/textfilter: tools/textfilter.c pico/draw.o: CFLAGS += -fno-strict-aliasing pico/draw2.o: CFLAGS += -fno-strict-aliasing pico/mode4.o: CFLAGS += -fno-strict-aliasing -pico/cd/cd_memory.o: CFLAGS += -fno-strict-aliasing +pico/cd/memory.o: CFLAGS += -fno-strict-aliasing pico/cd/cd_file.o: CFLAGS += -fno-strict-aliasing pico/cd/pcm.o: CFLAGS += -fno-strict-aliasing pico/cd/LC89510.o: CFLAGS += -fno-strict-aliasing pico/cd/gfx_cd.o: CFLAGS += -fno-strict-aliasing +# fame needs ~2GB of RAM to compile on gcc 4.8 +# on x86, this is reduced by ~300MB when debug info is off (but not on ARM) +# not using O3 and -fno-expensive-optimizations seems to also help, but you may +# want to remove this stuff for better performance if your compiler can handle it +ifndef DEBUG +cpu/fame/famec.o: CFLAGS += -g0 -O2 -fno-expensive-optimizations +endif + +pico/carthw_cfg.c: pico/carthw.cfg + tools/make_carthw_c $< $@ + # random deps pico/carthw/svp/compiler.o : cpu/drc/emit_$(ARCH).c cpu/sh2/compiler.o : cpu/drc/emit_$(ARCH).c cpu/sh2/mame/sh2pico.o : cpu/sh2/mame/sh2.c pico/pico.o pico/cd/mcd.o pico/32x/32x.o : pico/pico_cmn.c pico/pico_int.h -pico/memory.o pico/cd/cd_memory.o pico/32x/32x_memory.o : pico/pico_int.h pico/memory.h +pico/memory.o pico/cd/memory.o pico/32x/memory.o : pico/pico_int.h pico/memory.h cpu/fame/famec.o: cpu/fame/famec.c cpu/fame/famec_opcodes.h diff --git a/Makefile.libretro b/Makefile.libretro index 14f2dc5..b35a0da 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -215,7 +215,7 @@ else ifeq ($(platform), psp1) CC = psp-gcc$(EXE_EXT) AR = psp-ar$(EXE_EXT) CFLAGS += -G0 -ftracer - CFLAGS += -DPSP -D_ASM_DRAW_C_AMIPS + CFLAGS += -DPSP STATIC_LINKING = 1 NO_MMAP = 1 DONT_COMPILE_IN_ZLIB = 1 @@ -232,8 +232,6 @@ else ifeq ($(platform), psp1) use_drz80 = 0 use_cz80 = 1 - OBJS +=platform/libretro/psp/draw_amips.o - # CTR (3DS) else ifeq ($(platform), ctr) TARGET := $(TARGET_NAME)_libretro_$(platform).a diff --git a/README b/README index fbcecc1..d9c1091 100644 --- a/README +++ b/README @@ -13,3 +13,9 @@ then taken over and expanded by notaz. PicoDrive was the first emulator ever to properly emulate Virtua Racing and it's SVP chip. +How to compile on Raspbian Wheezy: + +export CC=gcc-4.8 +export CXX=g++-4.8 +./configure --platform=rpi2 +make diff --git a/configure b/configure index a25e7c1..1310ab2 100755 --- a/configure +++ b/configure @@ -31,7 +31,7 @@ check_define() # setting options to "yes" or "no" will make that choice default, # "" means "autodetect". -platform_list="generic pandora gp2x opendingux" +platform_list="generic pandora gp2x opendingux rpi1 rpi2" platform="generic" sound_driver_list="oss alsa sdl" sound_drivers="" @@ -44,6 +44,8 @@ need_sdl="no" need_xlib="no" # these are for known platforms optimize_cortexa8="no" +optimize_cortexa7="no" +optimize_arm1176jzf="no" optimize_arm926ej="no" optimize_arm920="no" @@ -67,6 +69,13 @@ set_platform() { platform=$1 case "$platform" in + rpi1) + optimize_arm1176jzf="yes" + ;; + rpi2) + optimize_cortexa7="yes" + have_arm_neon="yes" + ;; generic) ;; opendingux) @@ -159,6 +168,14 @@ arm*) CFLAGS="$CFLAGS -mcpu=cortex-a8 -mtune=cortex-a8" ASFLAGS="$ASFLAGS -mcpu=cortex-a8" fi + if [ "$optimize_cortexa7" = "yes" ]; then + CFLAGS="$CFLAGS -mcpu=cortex-a7" + ASFLAGS="$ASFLAGS -mcpu=cortex-a7" + fi + if [ "$optimize_arm1176jzf" = "yes" ]; then + CFLAGS="$CFLAGS -mcpu=arm1176jzf-s -mfloat-abi=hard" + ASFLAGS="$ASFLAGS -mcpu=arm1176jzf-s -mfloat-abi=hard" + fi if [ "$optimize_arm926ej" = "yes" ]; then CFLAGS="$CFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s" ASFLAGS="$ASFLAGS -mcpu=arm926ej-s -mfloat-abi=softfp" @@ -229,7 +246,7 @@ arm*) esac case "$platform" in -generic | opendingux) +rpi1 | rpi2 | generic | opendingux) need_sdl="yes" ;; esac diff --git a/cpu/cyclone b/cpu/cyclone index 66dda84..b889883 160000 --- a/cpu/cyclone +++ b/cpu/cyclone @@ -1 +1 @@ -Subproject commit 66dda842eae01f47f5389b931ec9567fb0bbb6a1 +Subproject commit b889883d36b2d247488c82d79d1eaab4dd41d236 diff --git a/cpu/cyclone_config.h b/cpu/cyclone_config.h index 13e2c5e..2320517 100644 --- a/cpu/cyclone_config.h +++ b/cpu/cyclone_config.h @@ -8,6 +8,9 @@ **/ +#ifndef HAVE_ARMv6 +#define HAVE_ARMv6 1 +#endif #define USE_MS_SYNTAX 0 #define CYCLONE_FOR_GENESIS 2 #define COMPRESS_JUMPTABLE 0 diff --git a/cpu/cyclone_config_armv4.h b/cpu/cyclone_config_armv4.h new file mode 100644 index 0000000..2319029 --- /dev/null +++ b/cpu/cyclone_config_armv4.h @@ -0,0 +1,2 @@ +#define HAVE_ARMv6 0 +#include "cyclone_config.h" diff --git a/cpu/cz80/cz80.c b/cpu/cz80/cz80.c index 28d762c..61ca5f8 100644 --- a/cpu/cz80/cz80.c +++ b/cpu/cz80/cz80.c @@ -216,7 +216,7 @@ void Cz80_Reset(cz80_struc *CPU) /* */ #if PICODRIVE_HACKS -static INLINE unsigned char picodrive_read(unsigned short a) +static inline unsigned char picodrive_read(unsigned short a) { uptr v = z80_read_map[a >> Z80_MEM_SHIFT]; if (map_flag_set(v)) diff --git a/cpu/debug.h b/cpu/debug.h index 4ad618d..63728ad 100644 --- a/cpu/debug.h +++ b/cpu/debug.h @@ -26,6 +26,6 @@ int pdb_net_connect(const char *host, const char *port); #else -static INLINE int pdb_net_connect(const char *host, const char *port) {return 0;} +static __inline int pdb_net_connect(const char *host, const char *port) {return 0;} #endif diff --git a/cpu/drc/cmn.c b/cpu/drc/cmn.c index 721340a..27ff981 100644 --- a/cpu/drc/cmn.c +++ b/cpu/drc/cmn.c @@ -1,8 +1,6 @@ /* * PicoDrive * Copyright (C) 2009,2010 notaz - * Copyright (C) 2016 lentillog - * Copyright (C) 2016 Daniel De Matteis * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -12,28 +10,20 @@ #include #include "cmn.h" -#ifdef _MSC_VER -u8 tcache[DRC_TCACHE_SIZE]; -#elif defined(VITA) -#include +u8 ALIGNED(4096) tcache_default[DRC_TCACHE_SIZE]; u8 *tcache; -static int sceBlock; -int getVMBlock(); -#else -u8 __attribute__((aligned(4096))) tcache[DRC_TCACHE_SIZE]; -#endif - void drc_cmn_init(void) { -#ifdef VITA - sceBlock = getVMBlock(); - sceKernelGetMemBlockBase(sceBlock, (void **)&tcache); -#endif + int ret; + + tcache = plat_mem_get_for_drc(DRC_TCACHE_SIZE); + if (tcache == NULL) + tcache = tcache_default; - int ret = plat_mem_set_exec(tcache, sizeof(tcache)); + ret = plat_mem_set_exec(tcache, DRC_TCACHE_SIZE); elprintf(EL_STATUS, "drc_cmn_init: %p, %zd bytes: %d", - tcache, sizeof(tcache), ret); + tcache, DRC_TCACHE_SIZE, ret); #ifdef __arm__ if (PicoOpt & POPT_EN_DRC) diff --git a/cpu/drc/cmn.h b/cpu/drc/cmn.h index e6da6ea..8953edd 100644 --- a/cpu/drc/cmn.h +++ b/cpu/drc/cmn.h @@ -5,11 +5,7 @@ typedef unsigned int u32; #define DRC_TCACHE_SIZE (2*1024*1024) -#ifdef VITA extern u8 *tcache; -#else -extern u8 tcache[DRC_TCACHE_SIZE]; -#endif void drc_cmn_init(void); void drc_cmn_cleanup(void); diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 26289a4..64face1 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -1,8 +1,6 @@ /* * Basic macros to emit ARM instructions and some utils * Copyright (C) 2008,2009,2010 notaz - * Copyright (C) 2016 lentillog - * Copyright (C) 2016 Daniel De Matteis * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. diff --git a/cpu/fame/famec.c b/cpu/fame/famec.c index 9e9dc15..db4eae6 100644 --- a/cpu/fame/famec.c +++ b/cpu/fame/famec.c @@ -742,6 +742,9 @@ static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR) //u32 oldSR = GET_SR; m68kcontext.io_cycle_counter -= exception_cycle_table[vect]; +#ifdef FAMEC_EMULATE_TRACE + m68kcontext.execinfo &= ~FM68K_EMULATE_TRACE; +#endif PRE_IO @@ -763,6 +766,7 @@ static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR) /* adjust SR */ flag_S = M68K_SR_S; + flag_T = 0; #ifndef FAMEC_32BIT_PC newPC&=M68K_ADR_MASK @@ -916,12 +920,11 @@ famec_Exec: #ifdef FAMEC_EMULATE_TRACE if (m68kcontext.execinfo & FM68K_EMULATE_TRACE) { - m68kcontext.io_cycle_counter = cycles_needed; + m68kcontext.io_cycle_counter += cycles_needed; cycles_needed = 0; m68kcontext.execinfo &= ~FM68K_EMULATE_TRACE; m68kcontext.execinfo |= FM68K_DO_TRACE; SET_PC(execute_exception(M68K_TRACE_EX, GET_PC, GET_SR)); - flag_T=0; if (m68kcontext.io_cycle_counter > 0) { //NEXT @@ -933,9 +936,9 @@ famec_Exec: if (cycles_needed != 0) { u32 line; - m68kcontext.io_cycle_counter = cycles_needed; + m68kcontext.io_cycle_counter += cycles_needed; cycles_needed = 0; - if (m68kcontext.io_cycle_counter <= 0) goto famec_End; + //if (m68kcontext.io_cycle_counter <= 0) goto famec_End; line=interrupt_chk__(); if (line>0) { diff --git a/cpu/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index c690b45..2df6d78 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -16936,18 +16936,20 @@ OPCODE(0x4800) u32 adr, res; u32 src, dst; - res = DREGu8((Opcode >> 0) & 7); - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + dst = DREGu8((Opcode >> 0) & 7); + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - DREGu8((Opcode >> 0) & 7) = res; + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; RET(6) } @@ -16960,18 +16962,20 @@ OPCODE(0x4810) adr = AREG((Opcode >> 0) & 7); PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(12) @@ -16986,18 +16990,20 @@ OPCODE(0x4818) adr = AREG((Opcode >> 0) & 7); AREG((Opcode >> 0) & 7) += 1; PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(12) @@ -17012,18 +17018,20 @@ OPCODE(0x4820) adr = AREG((Opcode >> 0) & 7) - 1; AREG((Opcode >> 0) & 7) = adr; PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(14) @@ -17038,18 +17046,20 @@ OPCODE(0x4828) FETCH_SWORD(adr); adr += AREG((Opcode >> 0) & 7); PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(16) @@ -17064,18 +17074,20 @@ OPCODE(0x4830) adr = AREG((Opcode >> 0) & 7); DECODE_EXT_WORD PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(18) @@ -17089,18 +17101,20 @@ OPCODE(0x4838) FETCH_SWORD(adr); PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(16) @@ -17114,18 +17128,20 @@ OPCODE(0x4839) FETCH_LONG(adr); PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(20) @@ -17140,18 +17156,20 @@ OPCODE(0x481F) adr = AREG(7); AREG(7) += 2; PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(12) @@ -17166,18 +17184,20 @@ OPCODE(0x4827) adr = AREG(7) - 2; AREG(7) = adr; PRE_IO - READ_BYTE_F(adr, res) - res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + READ_BYTE_F(adr, dst) + res = -dst - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res != 0x9a) + if (res != 0) { - if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; - res &= 0xFF; - WRITE_BYTE_F(adr, res) + flag_V = res; + if (((res|dst) & 0x0f) == 0) res = (res & 0xf0) + 6; + res = (res + 0x9a) & 0xFF; + WRITE_BYTE_F(adr, res) + flag_V &= ~res; flag_NotZ |= res; flag_X = flag_C = M68K_SR_C; } - else flag_X = flag_C = 0; + else flag_V = flag_X = flag_C = 0; flag_N = res; POST_IO RET(14) @@ -18554,6 +18574,10 @@ RET(8) // ILLEGAL OPCODE(0x4AFC) { +#ifdef PICODRIVE_HACK + extern void SekFinishIdleDet(void); + SekFinishIdleDet(); +#endif SET_PC(execute_exception(M68K_ILLEGAL_INSTRUCTION_EX, GET_PC-2, GET_SR)); RET(0) } @@ -19573,12 +19597,11 @@ RET(14) // CHK OPCODE(0x4180) { - u32 adr, res; - u32 src, dst; + s32 src, res; - src = DREGu16((Opcode >> 0) & 7); - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + src = DREGs16((Opcode >> 0) & 7); + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19589,14 +19612,14 @@ RET(10) // CHK OPCODE(0x4190) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = AREG((Opcode >> 0) & 7); PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19608,15 +19631,15 @@ RET(14) // CHK OPCODE(0x4198) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = AREG((Opcode >> 0) & 7); AREG((Opcode >> 0) & 7) += 2; PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19628,15 +19651,15 @@ RET(14) // CHK OPCODE(0x41A0) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = AREG((Opcode >> 0) & 7) - 2; AREG((Opcode >> 0) & 7) = adr; PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19648,15 +19671,15 @@ RET(16) // CHK OPCODE(0x41A8) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; FETCH_SWORD(adr); adr += AREG((Opcode >> 0) & 7); PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19668,15 +19691,15 @@ RET(18) // CHK OPCODE(0x41B0) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = AREG((Opcode >> 0) & 7); DECODE_EXT_WORD PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19688,14 +19711,14 @@ RET(20) // CHK OPCODE(0x41B8) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; FETCH_SWORD(adr); PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19707,14 +19730,14 @@ RET(18) // CHK OPCODE(0x41B9) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; FETCH_LONG(adr); PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19726,15 +19749,15 @@ RET(22) // CHK OPCODE(0x41BA) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = GET_SWORD + GET_PC; PC++; PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19746,15 +19769,15 @@ RET(18) // CHK OPCODE(0x41BB) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = GET_PC; DECODE_EXT_WORD PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19766,12 +19789,12 @@ RET(20) // CHK OPCODE(0x41BC) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; - FETCH_WORD(src); - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + FETCH_SWORD(src); + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19783,15 +19806,15 @@ RET(14) // CHK OPCODE(0x419F) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = AREG(7); AREG(7) += 2; PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -19803,15 +19826,15 @@ RET(14) // CHK OPCODE(0x41A7) { - u32 adr, res; - u32 src, dst; + s32 src, res; + u32 adr; adr = AREG(7) - 2; AREG(7) = adr; PRE_IO - READ_WORD_F(adr, src) - res = DREGu16((Opcode >> 9) & 7); - if (((s32)res < 0) || (res > src)) + READSX_WORD_F(adr, src) + res = DREGs16((Opcode >> 9) & 7); + if ((res < 0) || (res > src)) { flag_N = res >> 8; SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); @@ -26934,19 +26957,19 @@ OPCODE(0x8100) { u32 adr, res; u32 src, dst; + u32 corf = 0; src = DREGu8((Opcode >> 0) & 7); dst = DREGu8((Opcode >> 9) & 7); res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res -= 6; + if (res > 0xF) corf = 6; res += (dst & 0xF0) - (src & 0xF0); - if (res > 0x99) - { - res += 0xA0; - flag_X = flag_C = M68K_SR_C; - } - else flag_X = flag_C = 0; - flag_NotZ |= res & 0xFF; + flag_V = res; + flag_X = flag_C = (s32)res < (s32)corf ? M68K_SR_C : 0; + if (res > 0xff) res += 0xA0; + res = (res - corf) & 0xFF; + flag_V &= ~res; + flag_NotZ |= res; flag_N = res; DREGu8((Opcode >> 9) & 7) = res; RET(6) @@ -26957,6 +26980,7 @@ OPCODE(0x8108) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG((Opcode >> 0) & 7) - 1; AREG((Opcode >> 0) & 7) = adr; @@ -26966,15 +26990,14 @@ OPCODE(0x8108) AREG((Opcode >> 9) & 7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res -= 6; + if (res > 0xF) corf = 6; res += (dst & 0xF0) - (src & 0xF0); - if (res > 0x99) - { - res += 0xA0; - flag_X = flag_C = M68K_SR_C; - } - else flag_X = flag_C = 0; - flag_NotZ |= res & 0xFF; + flag_V = res; + flag_X = flag_C = (s32)res < (s32)corf ? M68K_SR_C : 0; + if (res > 0xff) res += 0xA0; + res = (res - corf) & 0xFF; + flag_V &= ~res; + flag_NotZ |= res; flag_N = res; WRITE_BYTE_F(adr, res) POST_IO @@ -26986,6 +27009,7 @@ OPCODE(0x810F) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG(7) - 2; AREG(7) = adr; @@ -26995,15 +27019,14 @@ OPCODE(0x810F) AREG((Opcode >> 9) & 7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res -= 6; + if (res > 0xF) corf = 6; res += (dst & 0xF0) - (src & 0xF0); - if (res > 0x99) - { - res += 0xA0; - flag_X = flag_C = M68K_SR_C; - } - else flag_X = flag_C = 0; - flag_NotZ |= res & 0xFF; + flag_V = res; + flag_X = flag_C = (s32)res < (s32)corf ? M68K_SR_C : 0; + if (res > 0xff) res += 0xA0; + res = (res - corf) & 0xFF; + flag_V &= ~res; + flag_NotZ |= res; flag_N = res; WRITE_BYTE_F(adr, res) POST_IO @@ -27015,6 +27038,7 @@ OPCODE(0x8F08) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG((Opcode >> 0) & 7) - 1; AREG((Opcode >> 0) & 7) = adr; @@ -27024,15 +27048,14 @@ OPCODE(0x8F08) AREG(7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res -= 6; + if (res > 0xF) corf = 6; res += (dst & 0xF0) - (src & 0xF0); - if (res > 0x99) - { - res += 0xA0; - flag_X = flag_C = M68K_SR_C; - } - else flag_X = flag_C = 0; - flag_NotZ |= res & 0xFF; + flag_V = res; + flag_X = flag_C = (s32)res < (s32)corf ? M68K_SR_C : 0; + if (res > 0xff) res += 0xA0; + res = (res - corf) & 0xFF; + flag_V &= ~res; + flag_NotZ |= res; flag_N = res; WRITE_BYTE_F(adr, res) POST_IO @@ -27044,6 +27067,7 @@ OPCODE(0x8F0F) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG(7) - 2; AREG(7) = adr; @@ -27053,15 +27077,14 @@ OPCODE(0x8F0F) AREG(7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res -= 6; + if (res > 0xF) corf = 6; res += (dst & 0xF0) - (src & 0xF0); - if (res > 0x99) - { - res += 0xA0; - flag_X = flag_C = M68K_SR_C; - } - else flag_X = flag_C = 0; - flag_NotZ |= res & 0xFF; + flag_V = res; + flag_X = flag_C = (s32)res < (s32)corf ? M68K_SR_C : 0; + if (res > 0xff) res += 0xA0; + res = (res - corf) & 0xFF; + flag_V &= ~res; + flag_NotZ |= res; flag_N = res; WRITE_BYTE_F(adr, res) POST_IO @@ -27419,7 +27442,7 @@ OPCODE(0x80F9) { SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(162) +RET(152) #else RET(22) #endif @@ -27435,7 +27458,7 @@ RET(22) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(162) +RET(152) #else RET(82) #endif @@ -27448,7 +27471,7 @@ RET(162) DREGu32((Opcode >> 9) & 7) = res; } #ifdef USE_CYCLONE_TIMING_DIV -RET(162) +RET(152) #else RET(102) #endif @@ -27517,7 +27540,7 @@ OPCODE(0x80FB) { SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); #ifdef USE_CYCLONE_TIMING_DIV -RET(160) +RET(150) #else RET(20) #endif @@ -27533,7 +27556,7 @@ RET(20) { flag_V = M68K_SR_V; #ifdef USE_CYCLONE_TIMING_DIV -RET(160) +RET(150) #else RET(80) #endif @@ -27546,7 +27569,7 @@ RET(160) DREGu32((Opcode >> 9) & 7) = res; } #ifdef USE_CYCLONE_TIMING_DIV -RET(160) +RET(150) #else RET(100) #endif @@ -34121,18 +34144,22 @@ OPCODE(0xC100) { u32 adr, res; u32 src, dst; + u32 corf = 0; src = DREGu8((Opcode >> 0) & 7); dst = DREGu8((Opcode >> 9) & 7); res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res += 6; + if (res > 9) corf = 6; res += (dst & 0xF0) + (src & 0xF0); - if (res > 0x99) + flag_V = ~res; + res += corf; + if (res > 0x9F) { res -= 0xA0; flag_X = flag_C = M68K_SR_C; } else flag_X = flag_C = 0; + flag_V &= res; flag_NotZ |= res & 0xFF; flag_N = res; DREGu8((Opcode >> 9) & 7) = res; @@ -34144,6 +34171,7 @@ OPCODE(0xC108) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG((Opcode >> 0) & 7) - 1; AREG((Opcode >> 0) & 7) = adr; @@ -34153,14 +34181,17 @@ OPCODE(0xC108) AREG((Opcode >> 9) & 7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res += 6; + if (res > 9) corf = 6; res += (dst & 0xF0) + (src & 0xF0); - if (res > 0x99) + flag_V = ~res; + res += corf; + if (res > 0x9F) { res -= 0xA0; flag_X = flag_C = M68K_SR_C; } else flag_X = flag_C = 0; + flag_V &= res; flag_NotZ |= res & 0xFF; flag_N = res; WRITE_BYTE_F(adr, res) @@ -34173,6 +34204,7 @@ OPCODE(0xC10F) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG(7) - 2; AREG(7) = adr; @@ -34182,14 +34214,17 @@ OPCODE(0xC10F) AREG((Opcode >> 9) & 7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res += 6; + if (res > 9) corf = 6; res += (dst & 0xF0) + (src & 0xF0); - if (res > 0x99) + flag_V = ~res; + res += corf; + if (res > 0x9F) { res -= 0xA0; flag_X = flag_C = M68K_SR_C; } else flag_X = flag_C = 0; + flag_V &= res; flag_NotZ |= res & 0xFF; flag_N = res; WRITE_BYTE_F(adr, res) @@ -34202,6 +34237,7 @@ OPCODE(0xCF08) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG((Opcode >> 0) & 7) - 1; AREG((Opcode >> 0) & 7) = adr; @@ -34211,14 +34247,17 @@ OPCODE(0xCF08) AREG(7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res += 6; + if (res > 9) corf = 6; res += (dst & 0xF0) + (src & 0xF0); - if (res > 0x99) + flag_V = ~res; + res += corf; + if (res > 0x9F) { res -= 0xA0; flag_X = flag_C = M68K_SR_C; } else flag_X = flag_C = 0; + flag_V &= res; flag_NotZ |= res & 0xFF; flag_N = res; WRITE_BYTE_F(adr, res) @@ -34231,6 +34270,7 @@ OPCODE(0xCF0F) { u32 adr, res; u32 src, dst; + u32 corf = 0; adr = AREG(7) - 2; AREG(7) = adr; @@ -34240,14 +34280,17 @@ OPCODE(0xCF0F) AREG(7) = adr; READ_BYTE_F(adr, dst) res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); - if (res > 9) res += 6; + if (res > 9) corf = 6; res += (dst & 0xF0) + (src & 0xF0); - if (res > 0x99) + flag_V = ~res; + res += corf; + if (res > 0x9F) { res -= 0xA0; flag_X = flag_C = M68K_SR_C; } else flag_X = flag_C = 0; + flag_V &= res; flag_NotZ |= res & 0xFF; flag_N = res; WRITE_BYTE_F(adr, res) @@ -37966,7 +38009,7 @@ OPCODE(0xE0B0) { if (sft == 1) res = (src >> 1) | ((flag_X & M68K_SR_X) << (32 - (M68K_SR_X_SFT + 1))); else res = (src >> sft) | (src << (33 - sft)) | (((flag_X & M68K_SR_X) << (32 - (M68K_SR_X_SFT + 1))) >> (sft - 1)); - flag_X = (src >> (32 - sft)) << M68K_SR_X_SFT; + flag_X = (src >> (sft - 1)) << M68K_SR_X_SFT; } else res = src; flag_C = flag_X; diff --git a/cpu/musashi/m68k_in.c b/cpu/musashi/m68k_in.c index 5c9cc06..d1756a5 100644 --- a/cpu/musashi/m68k_in.c +++ b/cpu/musashi/m68k_in.c @@ -918,13 +918,15 @@ M68KMAKE_OP(abcd, 8, rr, .) uint src = DY; uint dst = *r_dst; uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -944,13 +946,15 @@ M68KMAKE_OP(abcd, 8, mm, ax7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -970,13 +974,15 @@ M68KMAKE_OP(abcd, 8, mm, ay7) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -996,13 +1002,15 @@ M68KMAKE_OP(abcd, 8, mm, axy7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -1022,13 +1030,15 @@ M68KMAKE_OP(abcd, 8, mm, .) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -7794,19 +7804,19 @@ M68KMAKE_OP(mull, 32, ., .) M68KMAKE_OP(nbcd, 8, ., d) { uint* r_dst = &DY; - uint dst = *r_dst; - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = -dst - XFLAG_AS_1(); - if(res != 0x9a) + if(res != 0) { - FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = res; /* Undefined V behavior */ - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; + if(((res|dst) & 0x0f) == 0) + res = (res & 0xf0) + 6; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res + 0x9a); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; @@ -7828,18 +7838,18 @@ M68KMAKE_OP(nbcd, 8, ., .) { uint ea = M68KMAKE_GET_EA_AY_8; uint dst = m68ki_read_8(ea); - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + uint res = -dst - XFLAG_AS_1(); - if(res != 0x9a) + if(res != 0) { - FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = res; /* Undefined V behavior */ - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; + if(((res|dst) & 0x0f) == 0) + res = (res & 0xf0) + 6; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res + 0x9a); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); @@ -9359,26 +9369,26 @@ M68KMAKE_OP(sbcd, 8, rr, .) uint src = DY; uint dst = *r_dst; uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; -// FLAG_V = ~res; /* Undefined V behavior */ - FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to assume cleared. */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - if(res > 0x99) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; FLAG_X = FLAG_C = CFLAG_SET; - FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ } + else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; else - FLAG_N = FLAG_X = FLAG_C = 0; + FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); -// FLAG_V &= res; /* Undefined V behavior part II */ -// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_V &= ~res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; @@ -9391,26 +9401,26 @@ M68KMAKE_OP(sbcd, 8, mm, ax7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; -// FLAG_V = ~res; /* Undefined V behavior */ - FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - if(res > 0x99) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; FLAG_X = FLAG_C = CFLAG_SET; - FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ } + else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; else - FLAG_N = FLAG_X = FLAG_C = 0; + FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); -// FLAG_V &= res; /* Undefined V behavior part II */ -// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_V &= ~res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; m68ki_write_8(ea, res); @@ -9423,26 +9433,26 @@ M68KMAKE_OP(sbcd, 8, mm, ay7) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; -// FLAG_V = ~res; /* Undefined V behavior */ - FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - if(res > 0x99) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; FLAG_X = FLAG_C = CFLAG_SET; - FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ } + else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; else - FLAG_N = FLAG_X = FLAG_C = 0; + FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); -// FLAG_V &= res; /* Undefined V behavior part II */ -// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_V &= ~res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; m68ki_write_8(ea, res); @@ -9455,26 +9465,26 @@ M68KMAKE_OP(sbcd, 8, mm, axy7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; -// FLAG_V = ~res; /* Undefined V behavior */ - FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - if(res > 0x99) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; FLAG_X = FLAG_C = CFLAG_SET; - FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ } + else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; else - FLAG_N = FLAG_X = FLAG_C = 0; + FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); -// FLAG_V &= res; /* Undefined V behavior part II */ -// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_V &= ~res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; m68ki_write_8(ea, res); @@ -9487,26 +9497,26 @@ M68KMAKE_OP(sbcd, 8, mm, .) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; -// FLAG_V = ~res; /* Undefined V behavior */ - FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - if(res > 0x99) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; FLAG_X = FLAG_C = CFLAG_SET; - FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ } + else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; else - FLAG_N = FLAG_X = FLAG_C = 0; + FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); -// FLAG_V &= res; /* Undefined V behavior part II */ -// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_V &= ~res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; m68ki_write_8(ea, res); diff --git a/cpu/musashi/m68kcpu.c b/cpu/musashi/m68kcpu.c index 72bb217..38469f3 100644 --- a/cpu/musashi/m68kcpu.c +++ b/cpu/musashi/m68kcpu.c @@ -808,7 +808,7 @@ int m68k_execute(int num_cycles) // notaz m68ki_trace_t1(); - while(GET_CYCLES() >= 0) + while(GET_CYCLES() > 0) // do { /* Set tracing accodring to T1. (T0 is done inside instruction) */ diff --git a/cpu/musashi/m68kcpu.h b/cpu/musashi/m68kcpu.h index 83e92c5..63055cb 100644 --- a/cpu/musashi/m68kcpu.h +++ b/cpu/musashi/m68kcpu.h @@ -1623,7 +1623,7 @@ INLINE void m68ki_stack_frame_buserr(uint sr) /* Format 8 stack frame (68010). * 68010 only. This is the 29 word bus/address error frame. */ -void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) +INLINE void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) { /* VERSION * NUMBER @@ -1677,7 +1677,7 @@ void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) * if the error happens at an instruction boundary. * PC stacked is address of next instruction. */ -void m68ki_stack_frame_1010(uint sr, uint vector, uint pc) +INLINE void m68ki_stack_frame_1010(uint sr, uint vector, uint pc) { /* INTERNAL REGISTER */ m68ki_push_16(0); @@ -1724,7 +1724,7 @@ void m68ki_stack_frame_1010(uint sr, uint vector, uint pc) * if the error happens during instruction execution. * PC stacked is address of instruction in progress. */ -void m68ki_stack_frame_1011(uint sr, uint vector, uint pc) +INLINE void m68ki_stack_frame_1011(uint sr, uint vector, uint pc) { /* INTERNAL REGISTERS (18 words) */ m68ki_push_32(0); @@ -1968,7 +1968,7 @@ m68k_read_memory_8(0x00ffff01); /* Service an interrupt request and start exception processing */ -void m68ki_exception_interrupt(uint int_level) +INLINE void m68ki_exception_interrupt(uint int_level) { uint vector; uint sr; diff --git a/cpu/musashi/m68kmake.c b/cpu/musashi/m68kmake.c index f315734..361481b 100644 --- a/cpu/musashi/m68kmake.c +++ b/cpu/musashi/m68kmake.c @@ -1043,6 +1043,11 @@ void process_opcode_handlers(FILE* filep) if(opinfo == NULL) error_exit("Unable to find matching table entry for %s", func_name); +#if 1 /* PD hack: 000 only */ + if (opinfo->cpus[0] == UNSPECIFIED_CH) + continue; +#endif + replace->length = 0; /* Generate opcode variants */ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 3f006c7..4403378 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -1017,7 +1017,7 @@ static void rcache_unlock_all(void) reg_temp[i].flags &= ~HRF_LOCKED; } -static INLINE u32 rcache_used_hreg_mask(void) +static u32 rcache_used_hreg_mask(void) { u32 mask = 0; int i; diff --git a/cpu/sh2/mame/sh2pico.c b/cpu/sh2/mame/sh2pico.c index 7324166..636ebc6 100644 --- a/cpu/sh2/mame/sh2pico.c +++ b/cpu/sh2/mame/sh2pico.c @@ -21,7 +21,7 @@ typedef unsigned char UINT8; // this nasty conversion is needed for drc-expecting memhandlers #define MAKE_READFUNC(name, cname) \ -static INLINE unsigned int name(SH2 *sh2, unsigned int a) \ +static __inline unsigned int name(SH2 *sh2, unsigned int a) \ { \ unsigned int ret; \ sh2->sr |= sh2->icount << 12; \ @@ -32,7 +32,7 @@ static INLINE unsigned int name(SH2 *sh2, unsigned int a) \ } #define MAKE_WRITEFUNC(name, cname) \ -static INLINE void name(SH2 *sh2, unsigned int a, unsigned int d) \ +static __inline void name(SH2 *sh2, unsigned int a, unsigned int d) \ { \ sh2->sr |= sh2->icount << 12; \ cname(a, d, sh2); \ diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index 8c37f43..e945354 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -1,11 +1,7 @@ #ifndef __SH2_H__ #define __SH2_H__ -#if !defined(REGPARM) && defined(__i386__) -#define REGPARM(x) __attribute__((regparm(x))) -#else -#define REGPARM(x) -#endif +#include "../../pico/pico_port.h" // registers - matches structure order typedef enum { @@ -92,7 +88,7 @@ void sh2_unpack(SH2 *sh2, const unsigned char *buff); int sh2_execute_drc(SH2 *sh2c, int cycles); int sh2_execute_interpreter(SH2 *sh2c, int cycles); -static INLINE int sh2_execute(SH2 *sh2, int cycles, int use_drc) +static __inline int sh2_execute(SH2 *sh2, int cycles, int use_drc) { int ret; diff --git a/jni/Android.mk b/jni/Android.mk index e322752..bc81702 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -7,9 +7,6 @@ ifneq ($(GIT_VERSION)," unknown") LOCAL_CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" endif -#fix stupid change in ndk r11 that breaks compiling even when the exe would run fine -LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true - LOCAL_MODULE := retro R := ../ @@ -52,6 +49,13 @@ ifeq ($(TARGET_ARCH),arm) asm_misc = 1 # asm_cdmemory = 1 # texrels asm_mix = 1 + +# for armeabi to build... +CYCLONE_CONFIG = cyclone_config_armv4.h + +$(cleantarget):: + $(MAKE) -C $(FR)cpu/cyclone/ clean + else use_fame = 1 use_cz80 = 1 @@ -83,7 +87,7 @@ LOCAL_SRC_FILES += $(R)unzip/unzip.c LOCAL_C_INCLUDES += $(R) # note: don't use -O3, causes some NDKs run out of memory while compiling FAME -LOCAL_CFLAGS += -Wall -O2 -ffast-math -DNDEBUG -DINLINE=inline +LOCAL_CFLAGS += -Wall -O2 -ffast-math -DNDEBUG LOCAL_CFLAGS += $(addprefix -D,$(DEFINES)) LOCAL_LDLIBS := -llog diff --git a/jni/Application.mk b/jni/Application.mk index 222106e..a252a72 100644 --- a/jni/Application.mk +++ b/jni/Application.mk @@ -1 +1 @@ -APP_ABI := armeabi-v7a mips x86 +APP_ABI := all diff --git a/pico/32x/32x.c b/pico/32x/32x.c index 14d1c84..1c166ce 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -134,28 +134,31 @@ void p32x_reset_sh2s(void) // if we don't have BIOS set, perform it's work here. // MSH2 if (p32x_bios_m == NULL) { - unsigned int idl_src, idl_dst, idl_size; // initial data load - unsigned int vbr; + sh2_set_gbr(0, 0x20004000); - // initial data - idl_src = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d4)) & ~0xf0000000; - idl_dst = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d8)) & ~0xf0000000; - idl_size= HWSWAP(*(unsigned int *)(Pico.rom + 0x3dc)); - if (idl_size > Pico.romsize || idl_src + idl_size > Pico.romsize || - idl_size > 0x40000 || idl_dst + idl_size > 0x40000 || (idl_src & 3) || (idl_dst & 3)) { - elprintf(EL_STATUS|EL_ANOMALY, "32x: invalid initial data ptrs: %06x -> %06x, %06x", - idl_src, idl_dst, idl_size); - } - else - memcpy(Pico32xMem->sdram + idl_dst, Pico.rom + idl_src, idl_size); + if (!(PicoAHW & PAHW_MCD)) { + unsigned int idl_src, idl_dst, idl_size; // initial data load + unsigned int vbr; + + // initial data + idl_src = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d4)) & ~0xf0000000; + idl_dst = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d8)) & ~0xf0000000; + idl_size= HWSWAP(*(unsigned int *)(Pico.rom + 0x3dc)); + if (idl_size > Pico.romsize || idl_src + idl_size > Pico.romsize || + idl_size > 0x40000 || idl_dst + idl_size > 0x40000 || (idl_src & 3) || (idl_dst & 3)) { + elprintf(EL_STATUS|EL_ANOMALY, "32x: invalid initial data ptrs: %06x -> %06x, %06x", + idl_src, idl_dst, idl_size); + } + else + memcpy(Pico32xMem->sdram + idl_dst, Pico.rom + idl_src, idl_size); - // GBR/VBR - vbr = HWSWAP(*(unsigned int *)(Pico.rom + 0x3e8)); - sh2_set_gbr(0, 0x20004000); - sh2_set_vbr(0, vbr); + // VBR + vbr = HWSWAP(*(unsigned int *)(Pico.rom + 0x3e8)); + sh2_set_vbr(0, vbr); - // checksum and M_OK - Pico32x.regs[0x28 / 2] = *(unsigned short *)(Pico.rom + 0x18e); + // checksum and M_OK + Pico32x.regs[0x28 / 2] = *(unsigned short *)(Pico.rom + 0x18e); + } // program will set M_OK } @@ -227,7 +230,7 @@ static void p32x_start_blank(void) // XXX: no proper handling of 32col mode.. if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0 && // 32x not blanking (Pico.video.reg[12] & 1) && // 40col mode - (PicoDrawMask & PDRAW_32X_ON)) + (!(Pico.video.debug_p & PVD_KILL_32X))) { int md_bg = Pico.video.reg[7] & 0x3f; @@ -294,9 +297,9 @@ typedef void (event_cb)(unsigned int now); unsigned int p32x_event_times[P32X_EVENT_COUNT]; static unsigned int event_time_next; static event_cb *p32x_event_cbs[P32X_EVENT_COUNT] = { - p32x_pwm_irq_event, - fillend_event, - hint_event, + p32x_pwm_irq_event, // P32X_EVENT_PWM + fillend_event, // P32X_EVENT_FILLEND + hint_event, // P32X_EVENT_HINT }; // schedule event at some time 'after', in m68k clocks @@ -363,7 +366,7 @@ static void p32x_run_events(unsigned int until) oldest, event_time_next); } -static INLINE void run_sh2(SH2 *sh2, int m68k_cycles) +static void run_sh2(SH2 *sh2, int m68k_cycles) { int cycles, done; diff --git a/pico/32x/32x_draw.c b/pico/32x/draw.c similarity index 99% rename from pico/32x/32x_draw.c rename to pico/32x/draw.c index e33cb37..ee541bd 100644 --- a/pico/32x/32x_draw.c +++ b/pico/32x/draw.c @@ -96,7 +96,7 @@ void FinalizeLine32xRGB555(int sh, int line, struct PicoEState *est) if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 0 || // 32x blanking // XXX: how is 32col mode hadled by real hardware? !(Pico.video.reg[12] & 1) || // 32col mode - !(PicoDrawMask & PDRAW_32X_ON)) + (Pico.video.debug_p & PVD_KILL_32X)) { return; } @@ -292,7 +292,7 @@ void PicoDraw32xLayerMdOnly(int offs, int lines) for (l = 0; l < lines; l++) { if (have_scan) { PicoScan32xBegin(l + offs); - dst = (unsigned short*)Pico.est.DrawLineDest + poffs; + dst = (unsigned short *)Pico.est.DrawLineDest + poffs; } for (p = 0; p < plen; p += 4) { dst[p + 0] = pal[*pmd++]; diff --git a/pico/32x/32x_memory.c b/pico/32x/memory.c similarity index 99% rename from pico/32x/32x_memory.c rename to pico/32x/memory.c index 8b9254f..f3b7006 100644 --- a/pico/32x/32x_memory.c +++ b/pico/32x/memory.c @@ -1159,7 +1159,7 @@ static void bank_switch(int b) return; bank = b << 20; - if ((Pico.m.sram_reg & SRR_MAPPED) && bank == SRam.start) { + if ((Pico.m.sram_reg & SRR_MAPPED) && bank == Pico.sv.start) { bank_map_handler(); return; } @@ -1179,12 +1179,6 @@ static void bank_switch(int b) cpu68k_map_set(m68k_read16_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0); elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank); - -#ifdef EMU_F68K - // setup FAME fetchmap - for (rs = 0x90; rs < 0xa0; rs++) - PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom + bank - 0x900000; -#endif } // ----------------------------------------------------------------- diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 1aba914..5073564 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -326,11 +326,11 @@ void p32x_pwm_state_loaded(void) p32x_pwm_ctl_changed(); // for old savestates - cycles_diff_sh2 = SekCycleCnt * 3 - Pico32x.pwm_cycle_p; + cycles_diff_sh2 = Pico.t.m68c_cnt * 3 - Pico32x.pwm_cycle_p; if (cycles_diff_sh2 >= pwm_cycles || cycles_diff_sh2 < 0) { Pico32x.pwm_irq_cnt = pwm_irq_reload; - Pico32x.pwm_cycle_p = SekCycleCnt * 3; - p32x_pwm_schedule(SekCycleCnt); + Pico32x.pwm_cycle_p = Pico.t.m68c_cnt * 3; + p32x_pwm_schedule(Pico.t.m68c_cnt); } } diff --git a/pico/cart.c b/pico/cart.c index d29e96c..f17ce5e 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -109,7 +109,6 @@ pm_file *pm_open(const char *path) return NULL; ext = get_ext(path); -#ifndef NO_ZLIB if (strcasecmp(ext, "zip") == 0) { struct zip_file *zfile = NULL; @@ -163,9 +162,7 @@ zip_failed: return NULL; } } - else -#endif - if (strcasecmp(ext, "cso") == 0) + else if (strcasecmp(ext, "cso") == 0) { cso_struct *cso = NULL, *tmp = NULL; int size; @@ -260,7 +257,6 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream) { ret = fread(ptr, 1, bytes, stream->file); } -#ifndef NO_ZLIB else if (stream->type == PMT_ZIP) { struct zip_file *z = stream->file; @@ -291,7 +287,6 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream) z->pos += bytes - z->stream.avail_out; return bytes - z->stream.avail_out; } -#endif else if (stream->type == PMT_CSO) { cso_struct *cso = stream->param; @@ -367,7 +362,6 @@ int pm_seek(pm_file *stream, long offset, int whence) fseek(stream->file, offset, whence); return ftell(stream->file); } -#ifndef NO_ZLIB else if (stream->type == PMT_ZIP) { struct zip_file *z = stream->file; @@ -410,7 +404,6 @@ int pm_seek(pm_file *stream, long offset, int whence) } return z->pos; } -#endif else if (stream->type == PMT_CSO) { cso_struct *cso = stream->param; @@ -436,14 +429,12 @@ int pm_close(pm_file *fp) { fclose(fp->file); } -#ifndef NO_ZLIB else if (fp->type == PMT_ZIP) { struct zip_file *z = fp->file; inflateEnd(&z->stream); closezip(z->zip); } -#endif else if (fp->type == PMT_CSO) { free(fp->param); @@ -626,9 +617,9 @@ int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_ Pico.rom=rom; Pico.romsize=romsize; - if (SRam.data) { - free(SRam.data); - SRam.data = NULL; + if (Pico.sv.data) { + free(Pico.sv.data); + Pico.sv.data = NULL; } if (PicoCartUnloadHook != NULL) { @@ -958,8 +949,8 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) elprintf(EL_STATUS, "carthw:%d: bad sram_range: %08x - %08x", line, start, end); goto bad_nomsg; } - SRam.start = start; - SRam.end = end; + Pico.sv.start = start; + Pico.sv.end = end; continue; } else if (is_expr("prop", &p)) { @@ -968,9 +959,9 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) rstrip(p); if (strcmp(p, "no_sram") == 0) - SRam.flags &= ~SRF_ENABLED; + Pico.sv.flags &= ~SRF_ENABLED; else if (strcmp(p, "no_eeprom") == 0) - SRam.flags &= ~SRF_EEPROM; + Pico.sv.flags &= ~SRF_EEPROM; else if (strcmp(p, "filled_sram") == 0) *fill_sram = 1; else if (strcmp(p, "force_6btn") == 0) @@ -991,8 +982,8 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) type = strtoul(p, &r, 0); if (r == p || type < 0) goto bad; - SRam.eeprom_type = type; - SRam.flags |= SRF_EEPROM; + Pico.sv.eeprom_type = type; + Pico.sv.flags |= SRF_EEPROM; continue; } else if (is_expr("eeprom_lines", &p)) { @@ -1007,9 +998,9 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) sda_out < 0 || sda_out > 15) goto bad; - SRam.eeprom_bit_cl = scl; - SRam.eeprom_bit_in = sda_in; - SRam.eeprom_bit_out= sda_out; + Pico.sv.eeprom_bit_cl = scl; + Pico.sv.eeprom_bit_in = sda_in; + Pico.sv.eeprom_bit_out= sda_out; continue; } else if ((tmp = is_expr("prot_ro_value16", &p)) || is_expr("prot_rw_value16", &p)) { @@ -1049,54 +1040,54 @@ static void PicoCartDetect(const char *carthw_cfg) { int fill_sram = 0; - memset(&SRam, 0, sizeof(SRam)); + memset(&Pico.sv, 0, sizeof(Pico.sv)); if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A') { - SRam.start = rom_read32(0x1B4) & ~0xff000001; // align - SRam.end = (rom_read32(0x1B8) & ~0xff000000) | 1; + Pico.sv.start = rom_read32(0x1B4) & ~0xff000001; // align + Pico.sv.end = (rom_read32(0x1B8) & ~0xff000000) | 1; if (Pico.rom[0x1B2] & 0x40) // EEPROM - SRam.flags |= SRF_EEPROM; - SRam.flags |= SRF_ENABLED; + Pico.sv.flags |= SRF_EEPROM; + Pico.sv.flags |= SRF_ENABLED; } - if (SRam.end == 0 || SRam.start > SRam.end) + if (Pico.sv.end == 0 || Pico.sv.start > Pico.sv.end) { // some games may have bad headers, like S&K and Sonic3 // note: majority games use 0x200000 as starting address, but there are some which // use something else (0x300000 by HardBall '95). Luckily they have good headers. - SRam.start = 0x200000; - SRam.end = 0x203FFF; - SRam.flags |= SRF_ENABLED; + Pico.sv.start = 0x200000; + Pico.sv.end = 0x203FFF; + Pico.sv.flags |= SRF_ENABLED; } // set EEPROM defaults, in case it gets detected - SRam.eeprom_type = 0; // 7bit (24C01) - SRam.eeprom_bit_cl = 1; - SRam.eeprom_bit_in = 0; - SRam.eeprom_bit_out= 0; + Pico.sv.eeprom_type = 0; // 7bit (24C01) + Pico.sv.eeprom_bit_cl = 1; + Pico.sv.eeprom_bit_in = 0; + Pico.sv.eeprom_bit_out= 0; if (carthw_cfg != NULL) parse_carthw(carthw_cfg, &fill_sram); - if (SRam.flags & SRF_ENABLED) + if (Pico.sv.flags & SRF_ENABLED) { - if (SRam.flags & SRF_EEPROM) - SRam.size = 0x2000; + if (Pico.sv.flags & SRF_EEPROM) + Pico.sv.size = 0x2000; else - SRam.size = SRam.end - SRam.start + 1; + Pico.sv.size = Pico.sv.end - Pico.sv.start + 1; - SRam.data = calloc(SRam.size, 1); - if (SRam.data == NULL) - SRam.flags &= ~SRF_ENABLED; + Pico.sv.data = calloc(Pico.sv.size, 1); + if (Pico.sv.data == NULL) + Pico.sv.flags &= ~SRF_ENABLED; - if (SRam.eeprom_type == 1) // 1 == 0 in PD EEPROM code - SRam.eeprom_type = 0; + if (Pico.sv.eeprom_type == 1) // 1 == 0 in PD EEPROM code + Pico.sv.eeprom_type = 0; } - if ((SRam.flags & SRF_ENABLED) && fill_sram) + if ((Pico.sv.flags & SRF_ENABLED) && fill_sram) { elprintf(EL_STATUS, "SRAM fill"); - memset(SRam.data, 0xff, SRam.size); + memset(Pico.sv.data, 0xff, Pico.sv.size); } // Unusual region 'code' diff --git a/pico/carthw.cfg b/pico/carthw.cfg index 72d4a9a..20742e0 100644 --- a/pico/carthw.cfg +++ b/pico/carthw.cfg @@ -70,6 +70,10 @@ check_str = 0x32b74c, "Bishop Level" prop = force_6btn # The SSF2 mapper +[Mega Everdrive] +check_str = 0x100, "SEGA SSF" +hw = ssf2_mapper + [Super Street Fighter II - The New Challengers (U)] check_str = 0x150, "SUPER STREET FIGHTER2 The New Challengers" hw = ssf2_mapper diff --git a/pico/carthw/carthw.c b/pico/carthw/carthw.c index 06936fb..cd47e7c 100644 --- a/pico/carthw/carthw.c +++ b/pico/carthw/carthw.c @@ -8,8 +8,19 @@ #include "../pico_int.h" #include "../memory.h" +#include "eeprom_spi.h" +static int have_bank(u32 base) +{ + // the loader allocs in 512K quantities + if (base >= Pico.romsize) { + elprintf(EL_ANOMALY|EL_STATUS, "carthw: missing bank @ %06x", base); + return 0; + } + return 1; +} + /* The SSFII mapper */ static unsigned char ssf2_banks[8]; @@ -35,10 +46,8 @@ static void carthw_ssf2_write8(u32 a, u32 d) ssf2_banks[a >> 1] = d; base = d << 19; target = a << 18; - if (base + 0x80000 > Pico.romsize) { - elprintf(EL_ANOMALY|EL_STATUS, "ssf2: missing bank @ %06x", base); + if (!have_bank(base)) return; - } cpu68k_map_set(m68k_read8_map, target, target + 0x80000 - 1, Pico.rom + base, 0); cpu68k_map_set(m68k_read16_map, target, target + 0x80000 - 1, Pico.rom + base, 0); @@ -270,6 +279,7 @@ static carthw_state_chunk carthw_pier_state[] = { { CHUNK_CARTHW, sizeof(pier_regs), pier_regs }, { CHUNK_CARTHW + 1, sizeof(pier_dump_prot), &pier_dump_prot }, + { CHUNK_CARTHW + 2, 0, NULL }, // filled later { 0, 0, NULL } }; @@ -308,7 +318,8 @@ static void carthw_pier_write8(u32 a, u32 d) base = d << 19; goto do_map; case 0x09: - // TODO + Pico.sv.changed = 1; + eeprom_spi_write(d); break; case 0x0b: // eeprom read @@ -321,10 +332,9 @@ static void carthw_pier_write8(u32 a, u32 d) return; do_map: - if (base + 0x80000 > Pico.romsize) { - elprintf(EL_ANOMALY|EL_STATUS, "pier: missing bank @ %06x", base); + if (!have_bank(base)) return; - } + cpu68k_map_set(m68k_read8_map, target, target + 0x80000 - 1, Pico.rom + base, 0); cpu68k_map_set(m68k_read16_map, target, target + 0x80000 - 1, Pico.rom + base, 0); } @@ -346,7 +356,7 @@ static u32 carthw_pier_read8(u32 a) return PicoRead8_io(a); if (a == 0xa1300b) - return 0; // TODO + return eeprom_spi_read(a); elprintf(EL_UIO, "pier r8 [%06x] @%06x", a, SekPc); return 0; @@ -413,12 +423,14 @@ static void carthw_pier_reset(void) { pier_regs[0] = 1; pier_regs[1] = pier_regs[2] = pier_regs[3] = 0; - pier_dump_prot = 3; carthw_pier_statef(); + eeprom_spi_init(NULL); } void carthw_pier_startup(void) { + void *eeprom_state; + int eeprom_size = 0; int i; elprintf(EL_STATUS, "Pier Solar mapper startup"); @@ -430,10 +442,22 @@ void carthw_pier_startup(void) return; } + pier_dump_prot = 3; + // create dump protection bank for (i = 0; i < M68K_BANK_SIZE; i += 0x8000) memcpy(Pico.rom + Pico.romsize + i, Pico.rom, 0x8000); + // save EEPROM + eeprom_state = eeprom_spi_init(&eeprom_size); + Pico.sv.flags = 0; + Pico.sv.size = 0x10000; + Pico.sv.data = calloc(1, Pico.sv.size); + if (!Pico.sv.data) + Pico.sv.size = 0; + carthw_pier_state[2].ptr = eeprom_state; + carthw_pier_state[2].size = eeprom_size; + PicoCartMemSetup = carthw_pier_mem_setup; PicoResetHook = carthw_pier_reset; PicoLoadStateHook = carthw_pier_statef; @@ -679,3 +703,4 @@ void carthw_prot_lk3_startup(void) PicoCartMemSetup = carthw_prot_lk3_mem_setup; } +// vim:ts=2:sw=2:expandtab diff --git a/pico/carthw/eeprom_spi.c b/pico/carthw/eeprom_spi.c new file mode 100644 index 0000000..b250aff --- /dev/null +++ b/pico/carthw/eeprom_spi.c @@ -0,0 +1,360 @@ +/**************************************************************************** + * Genesis Plus + * SPI Serial EEPROM (25xxx/95xxx) support + * + * Copyright (C) 2012 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ + +#include "../pico_int.h" +#include "../cd/genplus_macros.h" +#include "eeprom_spi.h" + +/* max supported size 64KB (25x512/95x512) */ +#define SIZE_MASK 0xffff +#define PAGE_MASK 0x7f + +/* hard-coded board implementation (!WP pin not used) */ +#define BIT_DATA (0) +#define BIT_CLK (1) +#define BIT_HOLD (2) +#define BIT_CS (3) + +typedef enum +{ + STANDBY, + GET_OPCODE, + GET_ADDRESS, + WRITE_BYTE, + READ_BYTE +} T_STATE_SPI; + +typedef struct +{ + uint8 cs; /* !CS line state */ + uint8 clk; /* SCLK line state */ + uint8 out; /* SO line state */ + uint8 status; /* status register */ + uint8 opcode; /* 8-bit opcode */ + uint8 buffer; /* 8-bit data buffer */ + uint16 addr; /* 16-bit address */ + uint32 cycles; /* current operation cycle */ + T_STATE_SPI state; /* current operation state */ +} T_EEPROM_SPI; + +static T_EEPROM_SPI spi_eeprom; + +void *eeprom_spi_init(int *size) +{ + /* reset eeprom state */ + memset(&spi_eeprom, 0, sizeof(T_EEPROM_SPI)); + spi_eeprom.out = 1; + spi_eeprom.state = GET_OPCODE; + + if (size) + *size = sizeof(T_EEPROM_SPI); + return &spi_eeprom; +} + +void eeprom_spi_write(unsigned char data) +{ + /* Make sure !HOLD is high */ + if (data & (1 << BIT_HOLD)) + { + /* Check !CS state */ + if (data & (1 << BIT_CS)) + { + /* !CS high -> end of current operation */ + spi_eeprom.cycles = 0; + spi_eeprom.out = 1; + spi_eeprom.opcode = 0; + spi_eeprom.state = GET_OPCODE; + } + else + { + /* !CS low -> process current operation */ + switch (spi_eeprom.state) + { + case GET_OPCODE: + { + /* latch data on CLK positive edge */ + if ((data & (1 << BIT_CLK)) && !spi_eeprom.clk) + { + /* 8-bit opcode buffer */ + spi_eeprom.opcode |= ((data >> BIT_DATA) & 1); + spi_eeprom.cycles++; + + /* last bit ? */ + if (spi_eeprom.cycles == 8) + { + /* reset cycles count */ + spi_eeprom.cycles = 0; + + /* Decode instruction */ + switch (spi_eeprom.opcode) + { + case 0x01: + { + /* WRITE STATUS */ + spi_eeprom.buffer = 0; + spi_eeprom.state = WRITE_BYTE; + break; + } + + case 0x02: + { + /* WRITE BYTE */ + spi_eeprom.addr = 0; + spi_eeprom.state = GET_ADDRESS; + break; + } + + case 0x03: + { + /* READ BYTE */ + spi_eeprom.addr = 0; + spi_eeprom.state = GET_ADDRESS; + break; + } + + case 0x04: + { + /* WRITE DISABLE */ + spi_eeprom.status &= ~0x02; + spi_eeprom.state = STANDBY; + break; + } + + case 0x05: + { + /* READ STATUS */ + spi_eeprom.buffer = spi_eeprom.status; + spi_eeprom.state = READ_BYTE; + break; + } + + case 0x06: + { + /* WRITE ENABLE */ + spi_eeprom.status |= 0x02; + spi_eeprom.state = STANDBY; + break; + } + + default: + { + /* specific instructions (not supported) */ + spi_eeprom.state = STANDBY; + break; + } + } + } + else + { + /* shift opcode value */ + spi_eeprom.opcode = spi_eeprom.opcode << 1; + } + } + break; + } + + case GET_ADDRESS: + { + /* latch data on CLK positive edge */ + if ((data & (1 << BIT_CLK)) && !spi_eeprom.clk) + { + /* 16-bit address */ + spi_eeprom.addr |= ((data >> BIT_DATA) & 1); + spi_eeprom.cycles++; + + /* last bit ? */ + if (spi_eeprom.cycles == 16) + { + /* reset cycles count */ + spi_eeprom.cycles = 0; + + /* mask unused address bits */ + spi_eeprom.addr &= SIZE_MASK; + + /* operation type */ + if (spi_eeprom.opcode & 0x01) + { + /* READ operation */ + spi_eeprom.buffer = Pico.sv.data[spi_eeprom.addr]; + spi_eeprom.state = READ_BYTE; + } + else + { + /* WRITE operation */ + spi_eeprom.buffer = 0; + spi_eeprom.state = WRITE_BYTE; + } + } + else + { + /* shift address value */ + spi_eeprom.addr = spi_eeprom.addr << 1; + } + } + break; + } + + case WRITE_BYTE: + { + /* latch data on CLK positive edge */ + if ((data & (1 << BIT_CLK)) && !spi_eeprom.clk) + { + /* 8-bit data buffer */ + spi_eeprom.buffer |= ((data >> BIT_DATA) & 1); + spi_eeprom.cycles++; + + /* last bit ? */ + if (spi_eeprom.cycles == 8) + { + /* reset cycles count */ + spi_eeprom.cycles = 0; + + /* write data to destination */ + if (spi_eeprom.opcode & 0x01) + { + /* update status register */ + spi_eeprom.status = (spi_eeprom.status & 0x02) | (spi_eeprom.buffer & 0x0c); + + /* wait for operation end */ + spi_eeprom.state = STANDBY; + } + else + { + /* Memory Array (write-protected) */ + if (spi_eeprom.status & 2) + { + /* check array protection bits (BP0, BP1) */ + switch ((spi_eeprom.status >> 2) & 0x03) + { + case 0x01: + { + /* $C000-$FFFF (sector #3) is protected */ + if (spi_eeprom.addr < 0xC000) + { + Pico.sv.data[spi_eeprom.addr] = spi_eeprom.buffer; + } + break; + } + + case 0x02: + { + /* $8000-$FFFF (sectors #2 and #3) is protected */ + if (spi_eeprom.addr < 0x8000) + { + Pico.sv.data[spi_eeprom.addr] = spi_eeprom.buffer; + } + break; + } + + case 0x03: + { + /* $0000-$FFFF (all sectors) is protected */ + break; + } + + default: + { + /* no sectors protected */ + Pico.sv.data[spi_eeprom.addr] = spi_eeprom.buffer; + break; + } + } + } + + /* reset data buffer */ + spi_eeprom.buffer = 0; + + /* increase array address (sequential writes are limited within the same page) */ + spi_eeprom.addr = (spi_eeprom.addr & ~PAGE_MASK) | ((spi_eeprom.addr + 1) & PAGE_MASK); + } + } + else + { + /* shift data buffer value */ + spi_eeprom.buffer = spi_eeprom.buffer << 1; + } + } + break; + } + + case READ_BYTE: + { + /* output data on CLK positive edge */ + if ((data & (1 << BIT_CLK)) && !spi_eeprom.clk) + { + /* read out bits */ + spi_eeprom.out = (spi_eeprom.buffer >> (7 - spi_eeprom.cycles)) & 1; + spi_eeprom.cycles++; + + /* last bit ? */ + if (spi_eeprom.cycles == 8) + { + /* reset cycles count */ + spi_eeprom.cycles = 0; + + /* read from memory array ? */ + if (spi_eeprom.opcode == 0x03) + { + /* read next array byte */ + spi_eeprom.addr = (spi_eeprom.addr + 1) & SIZE_MASK; + spi_eeprom.buffer = Pico.sv.data[spi_eeprom.addr]; + } + } + } + break; + } + + default: + { + /* wait for !CS low->high transition */ + break; + } + } + } + } + + /* update input lines */ + spi_eeprom.cs = (data >> BIT_CS) & 1; + spi_eeprom.clk = (data >> BIT_CLK) & 1; +} + +unsigned int eeprom_spi_read(unsigned int address) +{ + return (spi_eeprom.out << BIT_DATA); +} + diff --git a/pico/carthw/eeprom_spi.h b/pico/carthw/eeprom_spi.h new file mode 100644 index 0000000..2d60e0f --- /dev/null +++ b/pico/carthw/eeprom_spi.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * Genesis Plus + * SPI Serial EEPROM (25XX512 only) support + * + * Copyright (C) 2012 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ + +#ifndef _EEPROM_SPI_H_ +#define _EEPROM_SPI_H_ + +/* Function prototypes */ +extern void *eeprom_spi_init(int *size); +extern void eeprom_spi_write(unsigned char data); +extern unsigned int eeprom_spi_read(unsigned int address); + +#endif diff --git a/pico/carthw/svp/svp_memory.c b/pico/carthw/svp/memory.c similarity index 98% rename from pico/carthw/svp/svp_memory.c rename to pico/carthw/svp/memory.c index b37985e..c721611 100644 --- a/pico/carthw/svp/svp_memory.c +++ b/pico/carthw/svp/memory.c @@ -87,7 +87,7 @@ static u32 PicoRead16_svpr(u32 a) a15004_looping = 0; if (!a15004_looping) - elprintf(EL_SVP, "SVP r%i: [%06x] %04x @%06x", realsize, a, d, SekPc); + elprintf(EL_SVP, "SVP r: [%06x] %04x @%06x", a, d, SekPc); if (a == 0xa15004 && !(d&1)) { if (!a15004_looping) diff --git a/pico/carthw/svp/svp.c b/pico/carthw/svp/svp.c index 1bccb3f..8861de0 100644 --- a/pico/carthw/svp/svp.c +++ b/pico/carthw/svp/svp.c @@ -91,23 +91,20 @@ static void PicoSVPLine(void) } -static int PicoSVPDma(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp) +static int PicoSVPDma(unsigned int source, int len, unsigned short **base, unsigned int *mask) { if (source < Pico.romsize) // Rom { - source -= 2; - *srcp = (unsigned short *)(Pico.rom + (source&~1)); - *limitp = (unsigned short *)(Pico.rom + Pico.romsize); - return 1; + *base = (unsigned short *)(Pico.rom + (source & 0xfe0000)); + *mask = 0x1ffff; + return source - 2; } else if ((source & 0xfe0000) == 0x300000) { elprintf(EL_VDPDMA|EL_SVP, "SVP DmaSlow from %06x, len=%i", source, len); - source &= 0x1fffe; - source -= 2; - *srcp = (unsigned short *)(svp->dram + source); - *limitp = (unsigned short *)(svp->dram + sizeof(svp->dram)); - return 1; + *base = (unsigned short *)svp->dram; + *mask = 0x1ffff; + return source - 2; } else elprintf(EL_VDPDMA|EL_SVP|EL_ANOMALY, "SVP FIXME unhandled DmaSlow from %06x, len=%i", source, len); diff --git a/pico/carthw_cfg.c b/pico/carthw_cfg.c index 91ddec7..2fdd199 100644 --- a/pico/carthw_cfg.c +++ b/pico/carthw_cfg.c @@ -1,4 +1,4 @@ -/* generated by ./tools/make_carthw_c, do not modify */ +/* generated by tools/make_carthw_c, do not modify */ static const char builtin_carthw_cfg[] = "[]\n" "check_str=0x150,\"Virtua Racing\"\n" @@ -28,6 +28,9 @@ static const char builtin_carthw_cfg[] = "check_str=0x32b74c,\"Bishop Level\"\n" "prop=force_6btn\n" "[]\n" + "check_str=0x100,\"SEGA SSF\"\n" + "hw=ssf2_mapper\n" + "[]\n" "check_str=0x150,\"SUPER STREET FIGHTER2 The New Challengers\"\n" "hw=ssf2_mapper\n" "prop=no_sram\n" diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index c6b24b8..501d09e 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -122,12 +122,14 @@ static const uint32 toc_ffightj[29] = 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052 }; +#if 0 /* supported WAVE file header (16-bit stereo samples @44.1kHz) */ static const unsigned char waveHeader[32] = { 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00, 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61 }; +#endif #ifdef USE_LIBTREMOR #ifdef DISABLE_MANY_OGG_OPEN_FILES diff --git a/pico/cd/gfx_dma.c b/pico/cd/gfx_dma.c index a24a1c3..7dfe4bc 100644 --- a/pico/cd/gfx_dma.c +++ b/pico/cd/gfx_dma.c @@ -26,7 +26,7 @@ PICO_INTERNAL void DmaSlowCell(unsigned int source, unsigned int a, int len, uns switch (Pico.video.type) { case 1: // vram - r = Pico.vram; + r = PicoMem.vram; for(; len; len--) { asrc = cell_map(source >> 2) << 2; @@ -42,7 +42,7 @@ PICO_INTERNAL void DmaSlowCell(unsigned int source, unsigned int a, int len, uns case 3: // cram Pico.m.dirtyPal = 1; - r = Pico.cram; + r = PicoMem.cram; for(a2=a&0x7f; len; len--) { asrc = cell_map(source >> 2) << 2; @@ -58,7 +58,7 @@ PICO_INTERNAL void DmaSlowCell(unsigned int source, unsigned int a, int len, uns break; case 5: // vsram[a&0x003f]=d; - r = Pico.vsram; + r = PicoMem.vsram; for(a2=a&0x7f; len; len--) { asrc = cell_map(source >> 2) << 2; diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 73502b2..af320bd 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -31,6 +31,7 @@ PICO_INTERNAL void PicoExitMCD(void) PICO_INTERNAL void PicoPowerMCD(void) { int fmt_size; + SekCycleCntS68k = SekCycleAimS68k = 0; fmt_size = sizeof(formatted_bram); @@ -77,16 +78,16 @@ PICO_INTERNAL int PicoResetMCD(void) { // reset button doesn't affect MCD hardware - // use SRam.data for RAM cart + // use Pico.sv.data for RAM cart if (PicoOpt & POPT_EN_MCD_RAMCART) { - if (SRam.data == NULL) - SRam.data = calloc(1, 0x12000); + if (Pico.sv.data == NULL) + Pico.sv.data = calloc(1, 0x12000); } - else if (SRam.data != NULL) { - free(SRam.data); - SRam.data = NULL; + else if (Pico.sv.data != NULL) { + free(Pico.sv.data); + Pico.sv.data = NULL; } - SRam.start = SRam.end = 0; // unused + Pico.sv.start = Pico.sv.end = 0; // unused return 0; } @@ -96,17 +97,17 @@ static void SekRunM68kOnce(void) int cyc_do; pevt_log_m68k_o(EVT_RUN_START); - if ((cyc_do = SekCycleAim - SekCycleCnt) > 0) { - SekCycleCnt += cyc_do; + if ((cyc_do = Pico.t.m68c_aim - Pico.t.m68c_cnt) > 0) { + Pico.t.m68c_cnt += cyc_do; #if defined(EMU_C68K) PicoCpuCM68k.cycles = cyc_do; CycloneRun(&PicoCpuCM68k); - SekCycleCnt -= PicoCpuCM68k.cycles; + Pico.t.m68c_cnt -= PicoCpuCM68k.cycles; #elif defined(EMU_M68K) - SekCycleCnt += m68k_execute(cyc_do) - cyc_do; + Pico.t.m68c_cnt += m68k_execute(cyc_do) - cyc_do; #elif defined(EMU_F68K) - SekCycleCnt += fm68k_emulate(cyc_do, 0) - cyc_do; + Pico.t.m68c_cnt += fm68k_emulate(cyc_do, 0) - cyc_do; #endif } @@ -147,7 +148,7 @@ static void pcd_set_cycle_mult(void) { // ~1.63 for NTSC, ~1.645 for PAL if (Pico.m.pal) - mcd_m68k_cycle_mult = ((12500000ull << 16) / (50*312*488)); + mcd_m68k_cycle_mult = ((12500000ull << 16) / (50*313*488)); else mcd_m68k_cycle_mult = ((12500000ull << 16) / (60*262*488)) + 1; } @@ -201,10 +202,10 @@ typedef void (event_cb)(unsigned int now); unsigned int pcd_event_times[PCD_EVENT_COUNT]; static unsigned int event_time_next; static event_cb *pcd_event_cbs[PCD_EVENT_COUNT] = { - pcd_cdc_event, - pcd_int3_timer_event, - gfx_update, - pcd_dma_event, + pcd_cdc_event, // PCD_EVENT_CDC + pcd_int3_timer_event, // PCD_EVENT_TIMER3 + gfx_update, // PCD_EVENT_GFX + pcd_dma_event, // PCD_EVENT_DMA }; void pcd_event_schedule(unsigned int now, enum pcd_event event, int after) @@ -317,39 +318,39 @@ static void SekSyncM68k(void); void pcd_run_cpus_normal(int m68k_cycles) { - SekCycleAim += m68k_cycles; + Pico.t.m68c_aim += m68k_cycles; if (SekShouldInterrupt() || Pico_mcd->m.m68k_poll_cnt < 12) Pico_mcd->m.m68k_poll_cnt = 0; else if (Pico_mcd->m.m68k_poll_cnt >= 16) { - int s68k_left = pcd_sync_s68k(SekCycleAim, 1); + int s68k_left = pcd_sync_s68k(Pico.t.m68c_aim, 1); if (s68k_left <= 0) { elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x", Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc); - SekCycleCnt = SekCycleAim; + Pico.t.m68c_cnt = Pico.t.m68c_aim; return; } - SekCycleCnt = SekCycleAim - (s68k_left * 40220 >> 16); + Pico.t.m68c_cnt = Pico.t.m68c_aim - (s68k_left * 40220 >> 16); } - while (CYCLES_GT(SekCycleAim, SekCycleCnt)) { + while (CYCLES_GT(Pico.t.m68c_aim, Pico.t.m68c_cnt)) { SekRunM68kOnce(); if (Pico_mcd->m.need_sync) { Pico_mcd->m.need_sync = 0; - pcd_sync_s68k(SekCycleCnt, 0); + pcd_sync_s68k(Pico.t.m68c_cnt, 0); } } } void pcd_run_cpus_lockstep(int m68k_cycles) { - unsigned int target = SekCycleAim + m68k_cycles; + unsigned int target = Pico.t.m68c_aim + m68k_cycles; do { - SekCycleAim += 8; + Pico.t.m68c_aim += 8; SekSyncM68k(); - pcd_sync_s68k(SekCycleAim, 0); - } while (CYCLES_GT(target, SekCycleAim)); + pcd_sync_s68k(Pico.t.m68c_aim, 0); + } while (CYCLES_GT(target, Pico.t.m68c_aim)); - SekCycleAim = target; + Pico.t.m68c_aim = target; } #define PICO_CD @@ -365,7 +366,7 @@ void pcd_prepare_frame(void) // need this because we can't have direct mapping between // master<->slave cycle counters because of overflows - mcd_m68k_cycle_base = SekCycleAim; + mcd_m68k_cycle_base = Pico.t.m68c_aim; mcd_s68k_cycle_base = SekCycleAimS68k; } @@ -391,7 +392,7 @@ void pcd_state_loaded(void) Pico_mcd->pcm_regs_dirty = 1; // old savestates.. - cycles = pcd_cycles_m68k_to_s68k(SekCycleAim); + cycles = pcd_cycles_m68k_to_s68k(Pico.t.m68c_aim); diff = cycles - SekCycleAimS68k; if (diff < -1000 || diff > 1000) { SekCycleCntS68k = SekCycleAimS68k = cycles; diff --git a/pico/cd/cd_memory.c b/pico/cd/memory.c similarity index 94% rename from pico/cd/cd_memory.c rename to pico/cd/memory.c index 6070161..6890b57 100644 --- a/pico/cd/cd_memory.c +++ b/pico/cd/memory.c @@ -602,14 +602,14 @@ static u32 PicoReadM68k8_ramc(u32 a) { u32 d = 0; if (a == 0x400001) { - if (SRam.data != NULL) + if (Pico.sv.data != NULL) d = 3; // 64k cart return d; } if ((a & 0xfe0000) == 0x600000) { - if (SRam.data != NULL) - d = SRam.data[((a >> 1) & 0xffff) + 0x2000]; + if (Pico.sv.data != NULL) + d = Pico.sv.data[((a >> 1) & 0xffff) + 0x2000]; return d; } @@ -629,9 +629,9 @@ static u32 PicoReadM68k16_ramc(u32 a) static void PicoWriteM68k8_ramc(u32 a, u32 d) { if ((a & 0xfe0000) == 0x600000) { - if (SRam.data != NULL && (Pico_mcd->m.bcram_reg & 1)) { - SRam.data[((a>>1) & 0xffff) + 0x2000] = d; - SRam.changed = 1; + if (Pico.sv.data != NULL && (Pico_mcd->m.bcram_reg & 1)) { + Pico.sv.data[((a>>1) & 0xffff) + 0x2000] = d; + Pico.sv.changed = 1; } return; } @@ -877,7 +877,7 @@ static u32 PicoReadS68k16_bram(u32 a) static void PicoWriteS68k8_bram(u32 a, u32 d) { Pico_mcd->bram[(a >> 1) & 0x1fff] = d; - SRam.changed = 1; + Pico.sv.changed = 1; } static void PicoWriteS68k16_bram(u32 a, u32 d) @@ -886,7 +886,7 @@ static void PicoWriteS68k16_bram(u32 a, u32 d) a = (a >> 1) & 0x1fff; Pico_mcd->bram[a++] = d; Pico_mcd->bram[a++] = d >> 8; // TODO: verify.. - SRam.changed = 1; + Pico.sv.changed = 1; } #ifndef _ASM_CD_MEMORY_C @@ -1044,7 +1044,6 @@ static void remap_prg_window(u32 r1, u32 r3) static void remap_word_ram(u32 r3) { void *bank; - int i; // WORD RAM if (!(r3 & 4)) { @@ -1072,22 +1071,6 @@ static void remap_word_ram(u32 r3) cpu68k_map_set(s68k_write8_map, 0x080000, 0x0bffff, s68k_dec_write8[b0 ^ 1][m], 1); cpu68k_map_set(s68k_write16_map, 0x080000, 0x0bffff, s68k_dec_write16[b0 ^ 1][m], 1); } - -#ifdef EMU_F68K - // update fetchmap.. - if (!(r3 & 4)) - { - for (i = M68K_FETCHBANK1*2/16; (i<<(24-FAMEC_FETCHBITS)) < 0x240000; i++) - PicoCpuFM68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram2M - 0x200000; - } - else - { - for (i = M68K_FETCHBANK1*2/16; (i<<(24-FAMEC_FETCHBITS)) < 0x220000; i++) - PicoCpuFM68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram1M[r3 & 1] - 0x200000; - for (i = M68K_FETCHBANK1*0x0c/0x100; (i<<(24-FAMEC_FETCHBITS)) < 0x0e0000; i++) - PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram1M[(r3&1)^1] - 0x0c0000; - } -#endif } void pcd_state_loaded_mem(void) @@ -1182,7 +1165,12 @@ PICO_INTERNAL void PicoMemSetupCD(void) // setup FAME fetchmap { +#ifdef __clang__ + volatile // prevent strange relocs from clang +#endif + unsigned long ptr_ram = (unsigned long)PicoMem.ram; int i; + // M68k // by default, point everything to fitst 64k of ROM (BIOS) for (i = 0; i < M68K_FETCHBANK1; i++) @@ -1192,7 +1180,7 @@ PICO_INTERNAL void PicoMemSetupCD(void) PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom; // .. and RAM for (i = M68K_FETCHBANK1*14/16; i < M68K_FETCHBANK1; i++) - PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.ram - (i<<(24-FAMEC_FETCHBITS)); + PicoCpuFM68k.Fetch[i] = ptr_ram - (i<<(24-FAMEC_FETCHBITS)); // S68k // PRG RAM is default for (i = 0; i < M68K_FETCHBANK1; i++) diff --git a/pico/cd/memory_arm.s b/pico/cd/memory_arm.S similarity index 93% rename from pico/cd/memory_arm.s rename to pico/cd/memory_arm.S index f3a1372..fe82ecb 100644 --- a/pico/cd/memory_arm.s +++ b/pico/cd/memory_arm.S @@ -6,6 +6,8 @@ @* See COPYING file in the top-level directory. @* +#include "../pico_int_o32.h" + .equiv PCM_STEP_SHIFT, 11 .text @@ -57,7 +59,6 @@ .extern s68k_poll_detect .extern pcd_pcm_write .extern pcd_pcm_read -.extern PicoCpuCS68k .extern PicoRead8_io .extern PicoRead16_io .extern PicoWrite8_io @@ -127,9 +128,9 @@ PicoReadM68k8_cell1: @ 0x220000 - 0x23ffff, cell arranged mov r3, #0x0e0000 0: cell_map - ldr r1, =(Pico+0x22200) + ldr r1, =Pico add r0, r0, r3 - ldr r1, [r1] + ldr r1, [r1, #OFS_Pico_rom] @ Pico.mcd (used everywhere) eor r0, r0, #1 ldrb r0, [r1, r0] bx lr @@ -140,9 +141,9 @@ PicoRead8_mcd_io: cmp r1, #0x2000 @ a120xx? bne PicoRead8_io - ldr r1, =(Pico+0x22200) + ldr r1, =Pico and r0, r0, #0x3f - ldr r1, [r1] @ Pico.mcd (used everywhere) + ldr r1, [r1, #OFS_Pico_rom] @ Pico.mcd cmp r0, #0x0e ldrlt pc, [pc, r0, lsl #2] b m_m68k_read8_hi @@ -237,9 +238,9 @@ PicoReadM68k16_cell1: @ 0x220000 - 0x23ffff, cell arranged mov r3, #0x0e0000 0: cell_map - ldr r1, =(Pico+0x22200) + ldr r1, =Pico add r0, r0, r3 - ldr r1, [r1] + ldr r1, [r1, #OFS_Pico_rom] @ Pico.mcd bic r0, r0, #1 ldrh r0, [r1, r0] bx lr @@ -251,9 +252,9 @@ PicoRead16_mcd_io: bne PicoRead16_io m_m68k_read16_m68k_regs: - ldr r1, =(Pico+0x22200) + ldr r1, =Pico and r0, r0, #0x3e - ldr r1, [r1] @ Pico.mcd (used everywhere) + ldr r1, [r1, #OFS_Pico_rom] @ Pico.mcd cmp r0, #0x0e ldrlt pc, [pc, r0, lsl #1] b m_m68k_read16_hi @@ -328,8 +329,9 @@ PicoWriteM68k8_cell1: @ 0x220000 - 0x23ffff, cell arranged 0: mov r3, r1 cell_map - ldr r2, =(Pico+0x22200) + ldr r2, =Pico add r0, r0, r12 + ldr r2, [r2, #OFS_Pico_rom] @ Pico.mcd ldr r2, [r2] eor r0, r0, #1 strb r3, [r2, r0] @@ -355,9 +357,9 @@ PicoWriteM68k16_cell1: @ 0x220000 - 0x23ffff, cell arranged 0: mov r3, r1 cell_map - ldr r1, =(Pico+0x22200) + ldr r1, =Pico add r0, r0, r12 - ldr r1, [r1] + ldr r1, [r1, #OFS_Pico_rom] @ Pico.mcd bic r0, r0, #1 strh r3, [r1, r0] bx lr @@ -397,9 +399,9 @@ PicoReadS68k8_dec0: @ 0x080000 - 0x0bffff PicoReadS68k8_dec1: mov r3, #0x0a0000 @ + ^ / 2 0: - ldr r2, =(Pico+0x22200) + ldr r2, =Pico eor r0, r0, #2 - ldr r2, [r2] + ldr r2, [r2, #OFS_Pico_rom] @ Pico.mcd movs r0, r0, lsr #1 @ +4-6 <<16 add r2, r2, r3 @ map to our address ldrb r0, [r2, r0] @@ -429,8 +431,8 @@ m_s68k_read8_regs: bx lr m_s68k_read8_comm: - ldr r1, =(Pico+0x22200) - ldr r1, [r1] + ldr r1, =Pico + ldr r1, [r1, #OFS_Pico_rom] @ Pico.mcd add r1, r1, #0x110000 ldrb r1, [r1, r0] bic r0, r0, #1 @@ -442,9 +444,9 @@ m_s68k_read8_pcm: bne m_read_null @ must not trash r3 and r12 - ldr r1, =(Pico+0x22200) + ldr r1, =Pico bic r0, r0, #0xff0000 - ldr r1, [r1] + ldr r1, [r1, #OFS_Pico_rom] @ Pico.mcd mov r2, #0x110000 orr r2, r2, #0x002200 cmp r0, #0x2000 @@ -477,9 +479,9 @@ PicoReadS68k16_dec0: @ 0x080000 - 0x0bffff PicoReadS68k16_dec1: mov r3, #0x0a0000 @ + ^ / 2 0: - ldr r2, =(Pico+0x22200) + ldr r2, =Pico eor r0, r0, #2 - ldr r2, [r2] + ldr r2, [r2, #OFS_Pico_rom] @ Pico.mcd mov r0, r0, lsr #1 @ +4-6 <<16 add r2, r2, r3 @ map to our address ldrb r0, [r2, r0] @@ -508,9 +510,9 @@ m_s68k_read16_regs: .macro m_s68k_write8_2M_decode - ldr r2, =(Pico+0x22200) + ldr r2, =Pico eor r0, r0, #2 - ldr r2, [r2] @ Pico.rom + ldr r2, [r2, #OFS_Pico_rom] @ Pico.mcd movs r0, r0, lsr #1 @ +4-6 <<16 add r2, r2, r3 @ map to our address .endm @@ -592,9 +594,9 @@ m_s68k_write8_pcm: bxlt lr m_s68k_write8_pcm_ram: - ldr r3, =(Pico+0x22200) + ldr r3, =Pico bic r0, r0, #0x00e000 - ldr r3, [r3] + ldr r3, [r3, #OFS_Pico_rom] @ Pico.mcd mov r0, r0, lsr #1 add r2, r3, #0x110000 add r2, r2, #0x002200 @@ -611,9 +613,9 @@ m_s68k_write8_pcm_ram: .macro m_s68k_write16_2M_decode - ldr r2, =(Pico+0x22200) + ldr r2, =Pico eor r0, r0, #2 - ldr r2, [r2] + ldr r2, [r2, #OFS_Pico_rom] @ Pico.mcd mov r0, r0, lsr #1 @ +4-6 <<16 add r2, r2, r3 @ map to our address .endm @@ -692,9 +694,9 @@ m_s68k_write16_regs: bne s68k_reg_write16 m_s68k_write16_regs_spec: @ special case - ldr r2, =(Pico+0x22200) + ldr r2, =Pico mov r0, #0x110000 - ldr r2, [r2] + ldr r2, [r2, #OFS_Pico_rom] @ Pico.mcd add r0, r0, #0x00000f strb r1, [r2, r0] @ if (a == 0xe) s68k_regs[0xf] = d; bx lr diff --git a/pico/cd/cd_misc.c b/pico/cd/misc.c similarity index 100% rename from pico/cd/cd_misc.c rename to pico/cd/misc.c diff --git a/pico/cd/cd_sek.c b/pico/cd/sek.c similarity index 96% rename from pico/cd/cd_sek.c rename to pico/cd/sek.c index d491490..42fea93 100644 --- a/pico/cd/cd_sek.c +++ b/pico/cd/sek.c @@ -178,10 +178,8 @@ PICO_INTERNAL int SekInterruptS68k(int irq) PicoCpuCS68k.irq=real_irq; #endif #ifdef EMU_M68K - void *oldcontext = m68ki_cpu_p; - m68k_set_context(&PicoCpuMS68k); - m68k_set_irq(real_irq); - m68k_set_context(oldcontext); + // avoid m68k_set_irq() for delaying to work + PicoCpuMS68k.int_level = real_irq << 8; #endif #ifdef EMU_F68K PicoCpuFS68k.interrupts[0]=real_irq; diff --git a/pico/debug.c b/pico/debug.c index efcd3fd..82ae8a5 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -8,6 +8,7 @@ #include "pico_int.h" #include "sound/ym2612.h" +#include "memory.h" #include "debug.h" #define bit(r, x) ((r>>x)&1) @@ -39,10 +40,10 @@ char *PDebugMain(void) sprintf(dstrp, "mode set 4: %02x\n", (r=reg[0xC])); MVP; sprintf(dstrp, "interlace: %i%i, cells: %i, shadow: %i\n", bit(r,2), bit(r,1), (r&0x80) ? 40 : 32, bit(r,3)); MVP; sprintf(dstrp, "scroll size: w: %i, h: %i SRAM: %i; eeprom: %i (%i)\n", reg[0x10]&3, (reg[0x10]&0x30)>>4, - !!(SRam.flags & SRF_ENABLED), !!(SRam.flags & SRF_EEPROM), SRam.eeprom_type); MVP; - sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", SRam.start, SRam.end, Pico.m.sram_reg); MVP; + !!(Pico.sv.flags & SRF_ENABLED), !!(Pico.sv.flags & SRF_EEPROM), Pico.sv.eeprom_type); MVP; + sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", Pico.sv.start, Pico.sv.end, Pico.m.sram_reg); MVP; sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP; - sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDone()); MVP; + sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %u\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDone()); MVP; sprintf(dstrp, "M68k: PC: %06x, SR: %04x, irql: %i\n", SekPc, SekSr, SekIrqLevel); MVP; for (r = 0; r < 8; r++) { sprintf(dstrp, "d%i=%08x, a%i=%08x\n", r, SekDar(r), r, SekDar(r+8)); MVP; @@ -116,7 +117,7 @@ char *PDebugSpriteList(void) unsigned int *sprite; int code, code2, sx, sy, height; - sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite // get sprite info code = sprite[0]; @@ -233,6 +234,7 @@ void PDebugShowSprite(unsigned short *screen, int stride, int which) struct PicoVideo *pvid=&Pico.video; int table=0,u,link=0,*sprite=0,*fsprite,oldsprite[2]; int x,y,max_sprites = 80, oldcol, oldreg; + unsigned char olddbg; if (!(pvid->reg[12]&1)) max_sprites = 64; @@ -243,23 +245,24 @@ void PDebugShowSprite(unsigned short *screen, int stride, int which) for (u=0; u < max_sprites && u <= which; u++) { - sprite=(int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + sprite=(int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite link=(sprite[0]>>16)&0x7f; if (!link) break; // End of sprites } if (u >= max_sprites) return; - fsprite = (int *)(Pico.vram+(table&0x7ffc)); + fsprite = (int *)(PicoMem.vram+(table&0x7ffc)); oldsprite[0] = fsprite[0]; oldsprite[1] = fsprite[1]; fsprite[0] = (sprite[0] & ~0x007f01ff) | 0x000080; fsprite[1] = (sprite[1] & ~0x01ff8000) | 0x800000; oldreg = pvid->reg[7]; - oldcol = Pico.cram[0]; + oldcol = PicoMem.cram[0]; + olddbg = pvid->debug_p; pvid->reg[7] = 0; - Pico.cram[0] = 0; - PicoDrawMask = PDRAW_SPRITES_LOW_ON; + PicoMem.cram[0] = 0; + pvid->debug_p = PVD_KILL_A | PVD_KILL_B; PicoFrameFull(); for (y = 0; y < 8*4; y++) @@ -273,11 +276,11 @@ void PDebugShowSprite(unsigned short *screen, int stride, int which) fsprite[0] = oldsprite[0]; fsprite[1] = oldsprite[1]; pvid->reg[7] = oldreg; - Pico.cram[0] = oldcol; - PicoDrawMask = -1; + PicoMem.cram[0] = oldcol; + pvid->debug_p = olddbg; } -#define dump_ram(ram,fname) \ +#define dump_ram_m(ram,fname,mode) \ { \ unsigned short *sram = (unsigned short *) ram; \ FILE *f; \ @@ -285,7 +288,7 @@ void PDebugShowSprite(unsigned short *screen, int stride, int which) \ for (i = 0; i < sizeof(ram)/2; i++) \ sram[i] = (sram[i]<<8) | (sram[i]>>8); \ - f = fopen(fname, "wb"); \ + f = fopen(fname, mode); \ if (f) { \ fwrite(ram, 1, sizeof(ram), f); \ fclose(f); \ @@ -294,6 +297,9 @@ void PDebugShowSprite(unsigned short *screen, int stride, int which) sram[i] = (sram[i]<<8) | (sram[i]>>8); \ } +#define dump_ram(ram,fname) \ + dump_ram_m(ram,fname,"wb") + #define dump_ram_noswab(ram,fname) \ { \ FILE *f; \ @@ -306,18 +312,31 @@ void PDebugShowSprite(unsigned short *screen, int stride, int which) void PDebugDumpMem(void) { - dump_ram_noswab(Pico.zram, "dumps/zram.bin"); - dump_ram(Pico.cram, "dumps/cram.bin"); +#if 0 + char buf[1 << M68K_MEM_SHIFT]; + unsigned int a; + for (a = 0; ; a++) { + uptr v = m68k_read16_map[a]; + if (map_flag_set(v)) + break; + v <<= 1; + v += a << M68K_MEM_SHIFT; + memcpy(buf, (void *)v, sizeof(buf)); + dump_ram_m(buf, "dumps/cart.bin", a ? "ab" : "wb"); + } +#endif + dump_ram_noswab(PicoMem.zram, "dumps/zram.bin"); + dump_ram(PicoMem.cram, "dumps/cram.bin"); if (PicoAHW & PAHW_SMS) { - dump_ram_noswab(Pico.vramb, "dumps/vram.bin"); + dump_ram_noswab(PicoMem.vramb, "dumps/vram.bin"); } else { - dump_ram(Pico.ram, "dumps/ram.bin"); - dump_ram(Pico.vram, "dumps/vram.bin"); - dump_ram(Pico.vsram,"dumps/vsram.bin"); + dump_ram(PicoMem.ram, "dumps/ram.bin"); + dump_ram(PicoMem.vram, "dumps/vram.bin"); + dump_ram(PicoMem.vsram,"dumps/vsram.bin"); } if (PicoAHW & PAHW_MCD) @@ -356,7 +375,7 @@ void PDebugZ80Frame(void) return; if (Pico.m.pal) { - lines = 312; + lines = 313; line_sample = 68; } else { lines = 262; @@ -364,31 +383,31 @@ void PDebugZ80Frame(void) } z80_resetCycles(); - emustatus &= ~1; + PsndStartFrame(); - if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) - PicoSyncZ80(line_sample*488); - if (ym2612.dacen && PsndDacLine <= line_sample) - PsndDoDAC(line_sample); + if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) + PicoSyncZ80(Pico.t.m68c_cnt + line_sample * 488); if (PsndOut) PsndGetSamples(line_sample); - if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) { - PicoSyncZ80(224*488); + if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) { + PicoSyncZ80(Pico.t.m68c_cnt + 224 * 488); z80_int(); } - if (ym2612.dacen && PsndDacLine <= 224) - PsndDoDAC(224); if (PsndOut) PsndGetSamples(224); // sync z80 - if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) - PicoSyncZ80(Pico.m.pal ? 151809 : 127671); // cycles adjusted for converter - if (PsndOut && ym2612.dacen && PsndDacLine <= lines-1) - PsndDoDAC(lines-1); + if (/*Pico.m.z80Run &&*/ !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) { + Pico.t.m68c_cnt += Pico.m.pal ? 151809 : 127671; // cycles adjusted for converter + PicoSyncZ80(Pico.t.m68c_cnt); + } + if (PsndOut && ym2612.dacen && PsndDacLine < lines) + PsndDoDAC(lines - 1); + PsndDoPSG(lines - 1); timers_cycle(); + Pico.t.m68c_aim = Pico.t.m68c_cnt; } void PDebugCPUStep(void) diff --git a/pico/draw.c b/pico/draw.c index 4c96a9a..83010a4 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -35,7 +35,6 @@ int (*PicoScanBegin)(unsigned int num) = NULL; int (*PicoScanEnd) (unsigned int num) = NULL; static unsigned char DefHighCol[8+320+8]; -unsigned char *HighCol = DefHighCol; static unsigned char *HighColBase = DefHighCol; static int HighColIncrement; @@ -47,6 +46,10 @@ static int HighCacheA[41+1]; // caches for high layers static int HighCacheB[41+1]; static int HighPreSpr[80*2+1]; // slightly preprocessed sprites +#define LF_PLANE_1 (1 << 0) +#define LF_SH (1 << 1) // must be = 2 +#define LF_FORCE (1 << 2) + #define SPRL_HAVE_HI 0x80 // have hi priority sprites #define SPRL_HAVE_LO 0x40 // *lo* #define SPRL_MAY_HAVE_OP 0x20 // may have operator sprites on the line @@ -55,12 +58,9 @@ unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES]; // sprite_count, ^flags, til int rendstatus_old; int rendlines; -int PicoDrawMask = -1; static int skip_next_line=0; -//unsigned short ppt[] = { 0x0f11, 0x0ff1, 0x01f1, 0x011f, 0x01ff, 0x0f1f, 0x0f0e, 0x0e7c }; - struct TileStrip { int nametab; // Position in VRAM of name table (for this tile line) @@ -97,66 +97,44 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat) #define TileNormMaker(funcname,pix_func) \ -static int funcname(int sx,int addr,int pal) \ +static void funcname(int sx, unsigned int pack, int pal) \ { \ - unsigned char *pd = Pico.est.HighCol+sx; \ - unsigned int pack=0; unsigned int t=0; \ - \ - pack=*(unsigned int *)(Pico.vram+addr); /* Get 8 pixels */ \ - if (pack) \ - { \ - t=(pack&0x0000f000)>>12; pix_func(0); \ - t=(pack&0x00000f00)>> 8; pix_func(1); \ - t=(pack&0x000000f0)>> 4; pix_func(2); \ - t=(pack&0x0000000f) ; pix_func(3); \ - t=(pack&0xf0000000)>>28; pix_func(4); \ - t=(pack&0x0f000000)>>24; pix_func(5); \ - t=(pack&0x00f00000)>>20; pix_func(6); \ - t=(pack&0x000f0000)>>16; pix_func(7); \ - return 0; \ - } \ + unsigned char *pd = Pico.est.HighCol + sx; \ + unsigned int t; \ \ - return 1; /* Tile blank */ \ + t = (pack&0x0000f000)>>12; pix_func(0); \ + t = (pack&0x00000f00)>> 8; pix_func(1); \ + t = (pack&0x000000f0)>> 4; pix_func(2); \ + t = (pack&0x0000000f) ; pix_func(3); \ + t = (pack&0xf0000000)>>28; pix_func(4); \ + t = (pack&0x0f000000)>>24; pix_func(5); \ + t = (pack&0x00f00000)>>20; pix_func(6); \ + t = (pack&0x000f0000)>>16; pix_func(7); \ } - #define TileFlipMaker(funcname,pix_func) \ -static int funcname(int sx,int addr,int pal) \ +static void funcname(int sx, unsigned int pack, int pal) \ { \ - unsigned char *pd = Pico.est.HighCol+sx; \ - unsigned int pack=0; unsigned int t=0; \ - \ - pack=*(unsigned int *)(Pico.vram+addr); /* Get 8 pixels */ \ - if (pack) \ - { \ - t=(pack&0x000f0000)>>16; pix_func(0); \ - t=(pack&0x00f00000)>>20; pix_func(1); \ - t=(pack&0x0f000000)>>24; pix_func(2); \ - t=(pack&0xf0000000)>>28; pix_func(3); \ - t=(pack&0x0000000f) ; pix_func(4); \ - t=(pack&0x000000f0)>> 4; pix_func(5); \ - t=(pack&0x00000f00)>> 8; pix_func(6); \ - t=(pack&0x0000f000)>>12; pix_func(7); \ - return 0; \ - } \ + unsigned char *pd = Pico.est.HighCol + sx; \ + unsigned int t; \ \ - return 1; /* Tile blank */ \ + t = (pack&0x000f0000)>>16; pix_func(0); \ + t = (pack&0x00f00000)>>20; pix_func(1); \ + t = (pack&0x0f000000)>>24; pix_func(2); \ + t = (pack&0xf0000000)>>28; pix_func(3); \ + t = (pack&0x0000000f) ; pix_func(4); \ + t = (pack&0x000000f0)>> 4; pix_func(5); \ + t = (pack&0x00000f00)>> 8; pix_func(6); \ + t = (pack&0x0000f000)>>12; pix_func(7); \ } -#ifdef _ASM_DRAW_C_AMIPS -int TileNorm(int sx,int addr,int pal); -int TileFlip(int sx,int addr,int pal); -#else - #define pix_just_write(x) \ if (t) pd[x]=pal|t TileNormMaker(TileNorm,pix_just_write) TileFlipMaker(TileFlip,pix_just_write) -#endif - #ifndef _ASM_DRAW_C // draw a sprite pixel, process operator colors @@ -208,18 +186,24 @@ TileFlipMaker(TileFlipAS_noop, pix_sh_as_noop) TileNormMaker(TileNormAS_onlymark, pix_sh_as_onlymark) TileFlipMaker(TileFlipAS_onlymark, pix_sh_as_onlymark) +// mark pixel as sprite pixel (AS) +#define pix_and(x) \ + pd[x] = (pd[x] & 0xc0) | (pd[x] & (pal | t)) + +TileNormMaker(TileNorm_and, pix_and) +TileFlipMaker(TileFlip_and, pix_and) // -------------------------------------------- #ifndef _ASM_DRAW_C -static void DrawStrip(struct TileStrip *ts, int plane_sh, int cellskip) +static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip) { int tilex,dx,ty,code=0,addr=0,cells; int oldcode=-1,blank=-1; // The tile we know is blank int pal=0,sh; // Draw tiles across screen: - sh=(plane_sh<<5)&0x40; + sh = (lflags & LF_SH) << 5; // 0x40 tilex=((-ts->hscroll)>>3)+cellskip; ty=(ts->line&7)<<1; // Y-Offset into tile dx=((ts->hscroll-1)&7)+1; @@ -227,13 +211,14 @@ static void DrawStrip(struct TileStrip *ts, int plane_sh, int cellskip) if(dx != 8) cells++; // have hscroll, need to draw 1 cell more dx+=cellskip<<3; - for (; cells > 0; dx+=8,tilex++,cells--) + for (; cells > 0; dx+=8, tilex++, cells--) { - int zero=0; + unsigned int pack; - code=Pico.vram[ts->nametab+(tilex&ts->xmask)]; - if (code==blank) continue; - if (code>>15) { // high priority tile + code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; + if (code == blank) + continue; + if ((code >> 15) | (lflags & LF_FORCE)) { // high priority tile int cval = code | (dx<<16) | (ty<<25); if(code&0x1000) cval^=7<<26; *ts->hc++ = cval; // cache it @@ -250,10 +235,14 @@ static void DrawStrip(struct TileStrip *ts, int plane_sh, int cellskip) pal=((code>>9)&0x30)|sh; } - if (code&0x0800) zero=TileFlip(dx,addr,pal); - else zero=TileNorm(dx,addr,pal); + pack = *(unsigned int *)(PicoMem.vram + addr); + if (!pack) { + blank = code; + continue; + } - if (zero) blank=code; // We know this tile is blank now + if (code & 0x0800) TileFlip(dx, pack, pal); + else TileNorm(dx, pack, pal); } // terminate the cache list @@ -263,7 +252,7 @@ static void DrawStrip(struct TileStrip *ts, int plane_sh, int cellskip) } // this is messy -void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) +static void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) { int tilex,dx,code=0,addr=0,cell=0; int oldcode=-1,blank=-1; // The tile we know is blank @@ -272,19 +261,24 @@ void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) // Draw tiles across screen: tilex=(-ts->hscroll)>>3; dx=((ts->hscroll-1)&7)+1; - if(dx != 8) cell--; // have hscroll, start with negative cell + if (ts->hscroll & 0x0f) { + int adj = ((ts->hscroll ^ dx) >> 3) & 1; + cell -= adj + 1; + ts->cells -= adj; + } cell+=cellskip; tilex+=cellskip; dx+=cellskip<<3; for (; cell < ts->cells; dx+=8,tilex++,cell++) { - int zero=0,nametabadd,ty; + int nametabadd, ty; + unsigned int pack; //if((cell&1)==0) { int line,vscroll; - vscroll=Pico.vsram[(plane_sh&1)+(cell&~1)]; + vscroll=PicoMem.vsram[(plane_sh&1)+(cell&~1)]; // Find the line in the name table line=(vscroll+scan)&ts->line&0xffff; // ts->line is really ymask .. @@ -292,7 +286,7 @@ void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) ty=(line&7)<<1; // Y-Offset into tile } - code=Pico.vram[ts->nametab+nametabadd+(tilex&ts->xmask)]; + code=PicoMem.vram[ts->nametab+nametabadd+(tilex&ts->xmask)]; if (code==blank) continue; if (code>>15) { // high priority tile int cval = code | (dx<<16) | (ty<<25); @@ -310,10 +304,14 @@ void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) pal=((code>>9)&0x30)|((plane_sh<<5)&0x40); } - if (code&0x0800) zero=TileFlip(dx,addr,pal); - else zero=TileNorm(dx,addr,pal); + pack = *(unsigned int *)(PicoMem.vram + addr); + if (!pack) { + blank = code; + continue; + } - if (zero) blank=code; // We know this tile is blank now + if (code & 0x0800) TileFlip(dx, pack, pal); + else TileNorm(dx, pack, pal); } // terminate the cache list @@ -340,9 +338,9 @@ void DrawStripInterlace(struct TileStrip *ts) for (; cells; dx+=8,tilex++,cells--) { - int zero=0; + unsigned int pack; - code=Pico.vram[ts->nametab+(tilex&ts->xmask)]; + code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; if (code==blank) continue; if (code>>15) { // high priority tile int cval = (code&0xfc00) | (dx<<16) | (ty<<25); @@ -362,10 +360,14 @@ void DrawStripInterlace(struct TileStrip *ts) pal=((code>>9)&0x30); } - if (code&0x0800) zero=TileFlip(dx,addr,pal); - else zero=TileNorm(dx,addr,pal); + pack = *(unsigned int *)(PicoMem.vram + addr); + if (!pack) { + blank = code; + continue; + } - if (zero) blank=code; // We know this tile is blank now + if (code & 0x0800) TileFlip(dx, pack, pal); + else TileNorm(dx, pack, pal); } // terminate the cache list @@ -395,8 +397,11 @@ static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells, ts.xmask=(1<1) ymask =0x0ff; + switch (width) { + case 1: ymask &= 0x1ff; break; + case 2: ymask = 0x007; break; + case 3: ymask = 0x0ff; break; + } // Find name table: if (plane_sh&1) ts.nametab=(pvid->reg[4]&0x07)<<12; // B @@ -408,11 +413,11 @@ static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells, htab+=plane_sh&1; // A or B // Get horizontal scroll value, will be masked later - ts.hscroll=Pico.vram[htab&0x7fff]; + ts.hscroll = PicoMem.vram[htab & 0x7fff]; if((pvid->reg[12]&6) == 6) { // interlace mode 2 - vscroll=Pico.vsram[plane_sh&1]; // Get vertical scroll value + vscroll = PicoMem.vsram[plane_sh & 1]; // Get vertical scroll value // Find the line in the name table ts.line=(vscroll+(est->DrawScanline<<1))&((ymask<<1)|1); @@ -425,7 +430,7 @@ static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells, ts.line=ymask|(shift[width]<<24); // save some stuff instead of line DrawStripVSRam(&ts, plane_sh, cellskip); } else { - vscroll=Pico.vsram[plane_sh&1]; // Get vertical scroll value + vscroll = PicoMem.vsram[plane_sh & 1]; // Get vertical scroll value // Find the line in the name table ts.line=(vscroll+est->DrawScanline)&ymask; @@ -462,7 +467,7 @@ static void DrawWindow(int tstart, int tend, int prio, int sh, if (!(est->rendstatus & PDRAW_WND_DIFF_PRIO)) { // check the first tile code - code=Pico.vram[nametab+tilex]; + code = PicoMem.vram[nametab + tilex]; // if the whole window uses same priority (what is often the case), we may be able to skip this field if ((code>>15) != prio) return; } @@ -475,36 +480,43 @@ static void DrawWindow(int tstart, int tend, int prio, int sh, { for (; tilex < tend; tilex++) { - int addr=0,zero=0; + unsigned int pack; + int dx, addr; int pal; - code=Pico.vram[nametab+tilex]; + code = PicoMem.vram[nametab + tilex]; if (code==blank) continue; if ((code>>15) != prio) { est->rendstatus |= PDRAW_WND_DIFF_PRIO; continue; } - pal=((code>>9)&0x30); - // Get tile address/2: addr=(code&0x7ff)<<4; if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip - if (code&0x0800) zero=TileFlip(8+(tilex<<3),addr,pal); - else zero=TileNorm(8+(tilex<<3),addr,pal); + pack = *(unsigned int *)(PicoMem.vram + addr); + if (!pack) { + blank = code; + continue; + } - if (zero) blank=code; // We know this tile is blank now + pal = ((code >> 9) & 0x30); + dx = 8 + (tilex << 3); + + if (code & 0x0800) TileFlip(dx, pack, pal); + else TileNorm(dx, pack, pal); } } else { for (; tilex < tend; tilex++) { - int addr=0,zero=0; + unsigned int pack; + int dx, addr; int pal; - code=Pico.vram[nametab+tilex]; + code = PicoMem.vram[nametab + tilex]; if(code==blank) continue; if((code>>15) != prio) { est->rendstatus |= PDRAW_WND_DIFF_PRIO; @@ -525,10 +537,16 @@ static void DrawWindow(int tstart, int tend, int prio, int sh, addr=(code&0x7ff)<<4; if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip - if (code&0x0800) zero=TileFlip(8+(tilex<<3),addr,pal); - else zero=TileNorm(8+(tilex<<3),addr,pal); + pack = *(unsigned int *)(PicoMem.vram + addr); + if (!pack) { + blank = code; + continue; + } + + dx = 8 + (tilex << 3); - if (zero) blank=code; // We know this tile is blank now + if (code & 0x0800) TileFlip(dx, pack, pal); + else TileNorm(dx, pack, pal); } } } @@ -551,6 +569,7 @@ static void DrawTilesFromCacheShPrep(void) static void DrawTilesFromCache(int *hc, int sh, int rlim, struct PicoEState *est) { int code, addr, dx; + unsigned int pack; int pal; // *ts->hc++ = code | (dx<<16) | (ty<<25); // cache it @@ -566,26 +585,32 @@ static void DrawTilesFromCache(int *hc, int sh, int rlim, struct PicoEState *est { short blank=-1; // The tile we know is blank while ((code=*hc++)) { - int zero; - if((short)code == blank) continue; + if (!(code & 0x8000) || (short)code == blank) + continue; // Get tile address/2: - addr=(code&0x7ff)<<4; - addr+=(unsigned int)code>>25; // y offset into tile - dx=(code>>16)&0x1ff; + addr = (code & 0x7ff) << 4; + addr += code >> 25; // y offset into tile - pal=((code>>9)&0x30); - if (rlim-dx < 0) goto last_cut_tile; + pack = *(unsigned int *)(PicoMem.vram + addr); + if (!pack) { + blank = (short)code; + continue; + } - if (code&0x0800) zero=TileFlip(dx,addr,pal); - else zero=TileNorm(dx,addr,pal); + dx = (code >> 16) & 0x1ff; + pal = ((code >> 9) & 0x30); + if (rlim-dx < 0) + goto last_cut_tile; - if (zero) blank=(short)code; + if (code & 0x0800) TileFlip(dx, pack, pal); + else TileNorm(dx, pack, pal); } } else { while ((code=*hc++)) { unsigned char *zb; + // Get tile address/2: addr=(code&0x7ff)<<4; addr+=(unsigned int)code>>25; // y offset into tile @@ -594,20 +619,26 @@ static void DrawTilesFromCache(int *hc, int sh, int rlim, struct PicoEState *est *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; - pal=((code>>9)&0x30); - if (rlim-dx < 0) goto last_cut_tile; + pack = *(unsigned int *)(PicoMem.vram + addr); + if (!pack) + continue; + + pal = ((code >> 9) & 0x30); + if (rlim - dx < 0) + goto last_cut_tile; - if (code&0x0800) TileFlip(dx,addr,pal); - else TileNorm(dx,addr,pal); + if (code & 0x0800) TileFlip(dx, pack, pal); + else TileNorm(dx, pack, pal); } } return; last_cut_tile: + // for vertical window cutoff { - unsigned int t, pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels - unsigned char *pd = est->HighCol+dx; - if (!pack) return; + unsigned char *pd = est->HighCol + dx; + unsigned int t; + if (code&0x0800) { switch (rlim-dx+8) @@ -651,7 +682,7 @@ static void DrawSprite(int *sprite, int sh) int pal; int tile=0,delta=0; int sx, sy; - int (*fTileFunc)(int sx,int addr,int pal); + void (*fTileFunc)(int sx, unsigned int pack, int pal); // parse the sprite data sy=sprite[0]; @@ -685,15 +716,38 @@ static void DrawSprite(int *sprite, int sh) for (; width; width--,sx+=8,tile+=delta) { + unsigned int pack; + if(sx<=0) continue; if(sx>=328) break; // Offscreen - tile&=0x7fff; // Clip tile address - fTileFunc(sx,tile,pal); + pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff)); + fTileFunc(sx, pack, pal); } } #endif +static NOINLINE void DrawTilesFromCacheForced(const int *hc) +{ + int code, addr, dx; + unsigned int pack; + int pal; + + // *ts->hc++ = code | (dx<<16) | (ty<<25); + while ((code = *hc++)) { + // Get tile address/2: + addr = (code & 0x7ff) << 4; + addr += (code >> 25) & 0x0e; // y offset into tile + + dx = (code >> 16) & 0x1ff; + pal = ((code >> 9) & 0x30); + pack = *(unsigned int *)(PicoMem.vram + addr); + + if (code & 0x0800) TileFlip_and(dx, pack, pal); + else TileNorm_and(dx, pack, pal); + } +} + static void DrawSpriteInterlace(unsigned int *sprite) { int width=0,height=0; @@ -728,17 +782,19 @@ static void DrawSpriteInterlace(unsigned int *sprite) for (; width; width--,sx+=8,tile+=delta) { + unsigned int pack; + if(sx<=0) continue; if(sx>=328) break; // Offscreen - tile&=0x7fff; // Clip tile address - if (code&0x0800) TileFlip(sx,tile,pal); - else TileNorm(sx,tile,pal); + pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff)); + if (code & 0x0800) TileFlip(sx, pack, pal); + else TileNorm(sx, pack, pal); } } -static void DrawAllSpritesInterlace(int pri, int sh) +static NOINLINE void DrawAllSpritesInterlace(int pri, int sh) { struct PicoVideo *pvid=&Pico.video; int i,u,table,link=0,sline=Pico.est.DrawScanline<<1; @@ -753,7 +809,7 @@ static void DrawAllSpritesInterlace(int pri, int sh) unsigned int *sprite; int code, sx, sy, height; - sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite // get sprite info code = sprite[0]; @@ -795,7 +851,7 @@ static void DrawAllSpritesInterlace(int pri, int sh) */ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est) { - int (*fTileFunc)(int sx,int addr,int pal); + void (*fTileFunc)(int sx, unsigned int pack, int pal); unsigned char *p; int cnt; @@ -851,11 +907,13 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est) for (; width; width--,sx+=8,tile+=delta) { + unsigned int pack; + if(sx<=0) continue; if(sx>=328) break; // Offscreen - tile&=0x7fff; // Clip tile address - fTileFunc(sx,tile,pal); + pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff)); + fTileFunc(sx, pack, pal); } } } @@ -863,7 +921,7 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est) static void DrawSpritesHiAS(unsigned char *sprited, int sh) { - int (*fTileFunc)(int sx,int addr,int pal); + void (*fTileFunc)(int sx, unsigned int pack, int pal); unsigned char *p; int entry, cnt, sh_cnt = 0; @@ -923,11 +981,13 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh) pal |= 0x80; for (; width; width--,sx+=8,tile+=delta) { + unsigned int pack; + if(sx<=0) continue; if(sx>=328) break; // Offscreen - tile&=0x7fff; // Clip tile address - fTileFunc(sx,tile,pal); + pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff)); + fTileFunc(sx, pack, pal); } } @@ -955,7 +1015,7 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh) // Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size // Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 -void PrepareSprites(int full) +static NOINLINE void PrepareSprites(int full) { const struct PicoVideo *pvid=&Pico.video; const struct PicoEState *est=&Pico.est; @@ -986,7 +1046,7 @@ void PrepareSprites(int full) unsigned int *sprite; int code2, sx, sy, height; - sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite // parse sprite info code2 = sprite[1]; @@ -1039,7 +1099,7 @@ found:; unsigned int *sprite; int code, code2, sx, sy, hv, height, width; - sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite // parse sprite info code = sprite[0]; @@ -1118,16 +1178,9 @@ found:; static void DrawAllSprites(unsigned char *sprited, int prio, int sh, struct PicoEState *est) { - int rs = est->rendstatus; unsigned char *p; int cnt; - if (rs & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES)) { - //elprintf(EL_STATUS, "PrepareSprites(%i)", (rs>>4)&1); - PrepareSprites(rs & PDRAW_DIRTY_SPRITES); - est->rendstatus = rs & ~(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES); - } - cnt = sprited[0] & 0x7f; if (cnt == 0) return; @@ -1170,7 +1223,7 @@ void PicoDoHighPal555(int sh, int line, struct PicoEState *est) Pico.m.dirtyPal = 0; - spal = (void *)Pico.cram; + spal = (void *)PicoMem.cram; dpal = (void *)est->HighPal; for (i = 0; i < 0x40 / 2; i++) { @@ -1252,9 +1305,9 @@ static void FinalizeLine8bit(int sh, int line, struct PicoEState *est) rs |= PDRAW_SONIC_MODE; est->rendstatus = rs; if (dirty_count == 3) { - blockcpy(est->HighPal, Pico.cram, 0x40*2); + blockcpy(est->HighPal, PicoMem.cram, 0x40*2); } else if (dirty_count == 11) { - blockcpy(est->HighPal+0x40, Pico.cram, 0x40*2); + blockcpy(est->HighPal+0x40, PicoMem.cram, 0x40*2); } } @@ -1286,8 +1339,14 @@ static int DrawDisplay(int sh) struct PicoEState *est=&Pico.est; unsigned char *sprited = &HighLnSpr[est->DrawScanline][0]; struct PicoVideo *pvid=&Pico.video; - int win=0,edge=0,hvwind=0; - int maxw,maxcells; + int win=0, edge=0, hvwind=0, lflags; + int maxw, maxcells; + + if (est->rendstatus & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES)) { + // elprintf(EL_STATUS, "PrepareSprites(%i)", (est->rendstatus>>4)&1); + PrepareSprites(est->rendstatus & PDRAW_DIRTY_SPRITES); + est->rendstatus &= ~(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES); + } est->rendstatus &= ~(PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO); @@ -1319,29 +1378,40 @@ static int DrawDisplay(int sh) } /* - layer B low - */ - if (PicoDrawMask & PDRAW_LAYERB_ON) - DrawLayer(1|(sh<<1), HighCacheB, 0, maxcells, est); + if (!(pvid->debug_p & PVD_KILL_B)) { + lflags = LF_PLANE_1 | (sh << 1); + if (pvid->debug_p & PVD_FORCE_B) + lflags |= LF_FORCE; + DrawLayer(lflags, HighCacheB, 0, maxcells, est); + } /* - layer A low - */ - if (!(PicoDrawMask & PDRAW_LAYERA_ON)); + lflags = 0 | (sh << 1); + if (pvid->debug_p & PVD_FORCE_A) + lflags |= LF_FORCE; + if (pvid->debug_p & PVD_KILL_A) + ; else if (hvwind == 1) DrawWindow(0, maxcells>>1, 0, sh, est); else if (hvwind == 2) { - DrawLayer(0|(sh<<1), HighCacheA, (win&0x80) ? 0 : edge<<1, (win&0x80) ? edge<<1 : maxcells, est); - DrawWindow( (win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 0, sh, est); - } else - DrawLayer(0|(sh<<1), HighCacheA, 0, maxcells, est); + DrawLayer(lflags, HighCacheA, (win&0x80) ? 0 : edge<<1, (win&0x80) ? edge<<1 : maxcells, est); + DrawWindow( (win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 0, sh, est); + } + else + DrawLayer(lflags, HighCacheA, 0, maxcells, est); /* - sprites low - */ - if (!(PicoDrawMask & PDRAW_SPRITES_LOW_ON)); - else if (Pico.est.rendstatus & PDRAW_INTERLACE) + if (pvid->debug_p & PVD_KILL_S_LO) + ; + else if (est->rendstatus & PDRAW_INTERLACE) DrawAllSpritesInterlace(0, sh); else if (sprited[1] & SPRL_HAVE_LO) DrawAllSprites(sprited, 0, sh, est); /* - layer B hi - */ - if ((PicoDrawMask & PDRAW_LAYERB_ON) && HighCacheB[0]) + if (!(pvid->debug_p & PVD_KILL_B) && HighCacheB[0]) DrawTilesFromCache(HighCacheB, sh, maxw, est); /* - layer A hi - */ - if (!(PicoDrawMask & PDRAW_LAYERA_ON)); + if (pvid->debug_p & PVD_KILL_A) + ; else if (hvwind == 1) DrawWindow(0, maxcells>>1, 1, sh, est); else if (hvwind == 2) { @@ -1352,8 +1422,9 @@ static int DrawDisplay(int sh) if (HighCacheA[0]) DrawTilesFromCache(HighCacheA, sh, maxw, est); /* - sprites hi - */ - if (!(PicoDrawMask & PDRAW_SPRITES_HI_ON)); - else if (Pico.est.rendstatus & PDRAW_INTERLACE) + if (pvid->debug_p & PVD_KILL_S_HI) + ; + else if (est->rendstatus & PDRAW_INTERLACE) DrawAllSpritesInterlace(1, sh); // have sprites without layer pri bit ontop of sprites with that bit else if ((sprited[1] & 0xd0) == 0xd0 && (PicoOpt & POPT_ACC_SPRITES)) @@ -1363,6 +1434,11 @@ static int DrawDisplay(int sh) else if (sprited[1] & SPRL_HAVE_HI) DrawAllSprites(sprited, 1, 0, est); + if (pvid->debug_p & PVD_FORCE_B) + DrawTilesFromCacheForced(HighCacheB); + else if (pvid->debug_p & PVD_FORCE_A) + DrawTilesFromCacheForced(HighCacheA); + #if 0 { int *c, a, b; @@ -1448,6 +1524,9 @@ static void PicoLine(int line, int offs, int sh, int bgc) return; } + if (Pico.video.debug_p & (PVD_FORCE_A | PVD_FORCE_B)) + bgc = 0x3f; + // Draw screen: BackFill(bgc, sh, &Pico.est); if (Pico.video.reg[1]&0x40) @@ -1471,13 +1550,14 @@ void PicoDrawSync(int to, int blank_last_line) pprof_start(draw); - if (rendlines != 240) + if (rendlines != 240) { offs = 8; + if (to > 223) + to = 223; + } for (line = Pico.est.DrawScanline; line < to; line++) - { PicoLine(line, offs, sh, bgc); - } // last line if (line <= to) @@ -1537,7 +1617,7 @@ void PicoDrawSetOutBuf(void *dest, int increment) { DrawLineDestBase = dest; DrawLineDestIncrement = increment; - Pico.est.DrawLineDest = (unsigned char*)DrawLineDestBase + Pico.est.DrawScanline * increment; + Pico.est.DrawLineDest = (char *)DrawLineDestBase + Pico.est.DrawScanline * increment; } void PicoDrawSetInternalBuf(void *dest, int increment) diff --git a/pico/draw2.c b/pico/draw2.c index 1b8cdf5..f0e0518 100644 --- a/pico/draw2.c +++ b/pico/draw2.c @@ -25,7 +25,7 @@ static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)]; static int HighCache2A[41*(TILE_ROWS+1)+1+1]; // caches for high layers static int HighCache2B[41*(TILE_ROWS+1)+1+1]; -unsigned short *PicoCramHigh=Pico.cram; // pointer to CRAM buff (0x40 shorts), converted to native device color (works only with 16bit for now) +unsigned short *PicoCramHigh=PicoMem.cram; // pointer to CRAM buff (0x40 shorts), converted to native device color (works only with 16bit for now) void (*PicoPrepareCram)()=0; // prepares PicoCramHigh for renderer to use @@ -46,7 +46,7 @@ static int TileXnormYnorm(unsigned char *pd,int addr,unsigned char pal) int i; for(i=8; i; i--, addr+=2, pd += LINE_WIDTH) { - pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x0000f000; if (t) pd[0]=(unsigned char)((t>>12)|pal); @@ -69,7 +69,7 @@ static int TileXflipYnorm(unsigned char *pd,int addr,unsigned char pal) int i; for(i=8; i; i--, addr+=2, pd += LINE_WIDTH) { - pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x000f0000; if (t) pd[0]=(unsigned char)((t>>16)|pal); @@ -92,7 +92,7 @@ static int TileXnormYflip(unsigned char *pd,int addr,unsigned char pal) addr+=14; for(i=8; i; i--, addr-=2, pd += LINE_WIDTH) { - pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x0000f000; if (t) pd[0]=(unsigned char)((t>>12)|pal); @@ -116,7 +116,7 @@ static int TileXflipYflip(unsigned char *pd,int addr,unsigned char pal) addr+=14; for(i=8; i; i--, addr-=2, pd += LINE_WIDTH) { - pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x000f0000; if (t) pd[0]=(unsigned char)((t>>16)|pal); @@ -161,7 +161,7 @@ static void DrawWindowFull(int start, int end, int prio, struct PicoEState *est) nametab += nametab_step*start; // check priority - code=Pico.vram[nametab+tile_start]; + code=PicoMem.vram[nametab+tile_start]; if ((code>>15) != prio) return; // hack: just assume that whole window uses same priority scrpos+=8*LINE_WIDTH+8; @@ -175,7 +175,7 @@ static void DrawWindowFull(int start, int end, int prio, struct PicoEState *est) // unsigned short *pal=NULL; unsigned char pal; - code=Pico.vram[nametab+tilex]; + code=PicoMem.vram[nametab+tilex]; if (code==blank) continue; // Get tile address/2: @@ -222,7 +222,7 @@ static void DrawLayerFull(int plane, int *hcache, int planestart, int planeend, if(!(pvid->reg[11]&3)) { // full screen scroll // Get horizontal scroll value - hscroll=Pico.vram[htab&0x7fff]; + hscroll=PicoMem.vram[htab&0x7fff]; htab = 0; // this marks that we don't have to update scroll value } @@ -243,7 +243,7 @@ static void DrawLayerFull(int plane, int *hcache, int planestart, int planeend, scrpos+=8*LINE_WIDTH*(planestart-START_ROW); // Get vertical scroll value: - vscroll=Pico.vsram[plane]&0x1ff; + vscroll=PicoMem.vsram[plane]&0x1ff; scrpos+=(8-(vscroll&7))*LINE_WIDTH; if(vscroll&7) planeend++; // we have vertically clipped tiles due to vscroll, so we need 1 more row @@ -262,7 +262,7 @@ static void DrawLayerFull(int plane, int *hcache, int planestart, int planeend, if(htab) { int htaddr=htab+(trow<<4); if(trow) htaddr-=(vscroll&7)<<1; - hscroll=Pico.vram[htaddr&0x7fff]; + hscroll=PicoMem.vram[htaddr&0x7fff]; } // Draw tiles across screen: @@ -276,7 +276,7 @@ static void DrawLayerFull(int plane, int *hcache, int planestart, int planeend, // unsigned short *pal=NULL; unsigned char pal; - code=Pico.vram[nametab_row+(tilex&xmask)]; + code=PicoMem.vram[nametab_row+(tilex&xmask)]; if (code==blank) continue; if (code>>15) { // high priority tile @@ -422,7 +422,7 @@ static void DrawAllSpritesFull(int prio, int maxwidth) unsigned int *sprite=NULL; int code, code2, sx, sy, height; - sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite // get sprite info code = sprite[0]; @@ -551,9 +551,9 @@ static void DrawDisplayFull(void) if (hvwin==1) { winend|=maxcolc<<16; planeend|=maxcolc<<16; } HighCache2A[1] = HighCache2B[1] = 0; - if (PicoDrawMask & PDRAW_LAYERB_ON) + if (!(pvid->debug_p & PVD_KILL_B)) DrawLayerFull(1, HighCache2B, START_ROW, (maxcolc<<16)|END_ROW, est); - if (PicoDrawMask & PDRAW_LAYERA_ON) switch (hvwin) + if (!(pvid->debug_p & PVD_KILL_A)) switch (hvwin) { case 4: // fullscreen window @@ -579,12 +579,12 @@ static void DrawDisplayFull(void) DrawLayerFull(0, HighCache2A, START_ROW, (maxcolc<<16)|END_ROW, est); break; } - if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) + if (!(pvid->debug_p & PVD_KILL_S_LO)) DrawAllSpritesFull(0, maxw); if (HighCache2B[1]) DrawTilesFromCacheF(HighCache2B, est); if (HighCache2A[1]) DrawTilesFromCacheF(HighCache2A, est); - if (PicoDrawMask & PDRAW_LAYERA_ON) switch (hvwin) + if (!(pvid->debug_p & PVD_KILL_A)) switch (hvwin) { case 4: // fullscreen window @@ -603,7 +603,7 @@ static void DrawDisplayFull(void) DrawWindowFull(winstart, winend, 1, est); break; } - if (PicoDrawMask & PDRAW_SPRITES_HI_ON) + if (!(pvid->debug_p & PVD_KILL_S_HI)) DrawAllSpritesFull(1, maxw); } diff --git a/pico/draw2_arm.S b/pico/draw2_arm.S index 6e7e1ac..6b110b3 100644 --- a/pico/draw2_arm.S +++ b/pico/draw2_arm.S @@ -73,8 +73,17 @@ BackFillFull: @ -------- some macros -------- +@ helpers +.macro add_c24 d s c + add \d, \s, #(\c & 0x00ff00) +.if \c & 0x0000ff + add \d, \d, #(\c & 0x0000ff) +.endif +.if \c & 0xff0000 + add \d, \d, #(\c & 0xff0000) +.endif +.endm -@ helper @ TileLineSinglecol (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: pixels8_old .macro TileLineSinglecol notsinglecol=0 and r2, r2, #0xf @ #0x0000000f @@ -353,10 +362,10 @@ DrawLayerFull: mov r6, r1 @ hcache - ldr r11, [r12, #OFS_Pico_video] - ldr r10, [r12, #OFS_Pico_vram] - ldrb r5, [r11, #13] @ pvid->reg[13] - ldrb r7, [r11, #11] + ldr r11, [r12, #OFS_EST_Pico] + ldr r10, [r12, #OFS_EST_PicoMem_vram] + ldrb r5, [r11, #OFS_Pico_video_reg+13] @ pvid->reg[13] + ldrb r7, [r11, #OFS_Pico_video_reg+11] sub lr, r3, r2 and lr, lr, #0x00ff0000 @ lr=cells @@ -366,7 +375,7 @@ DrawLayerFull: bic r5, r5, #0x00ff0000 @ just in case tst r7, #3 @ full screen scroll? (if ==0) - ldrb r7, [r11, #16] @ ??hh??ww + ldrb r7, [r11, #OFS_Pico_video_reg+16] @ ??hh??ww ldreqh r5, [r10, r5] biceq r5, r5, #0x0000fc00 @ r5=hscroll (0-0x3ff) movne r5, r5, lsr #1 @@ -397,22 +406,21 @@ DrawLayerFull: @ Find name table: tst r0, r0 - ldreqb r4, [r11, #2] + ldreqb r4, [r11, #OFS_Pico_video_reg+2] moveq r4, r4, lsr #3 - ldrneb r4, [r11, #4] + ldrneb r4, [r11, #OFS_Pico_video_reg+4] and r4, r4, #7 orr lr, lr, r4, lsl #13 @ lr|=nametab_bits{3}<<13 ldr r11,[sp, #9*4] @ est sub r4, r9, #(START_ROW<<24) - ldr r11, [r11, #OFS_Draw2FB] + ldr r11, [r11, #OFS_EST_Draw2FB] mov r4, r4, asr #24 mov r7, #328*8 mla r11, r4, r7, r11 @ scrpos+=8*328*(planestart-START_ROW); @ Get vertical scroll value: - add r7, r10, #0x012000 - add r7, r7, #0x000180 @ r7=Pico.vsram (Pico+0x22180) + add_c24 r7, r10, (OFS_PMEM_vsram-OFS_PMEM_vram) ldr r7, [r7] tst r0, r0 moveq r7, r7, lsl #22 @@ -582,13 +590,13 @@ DrawTilesFromCacheF: mov r9, #0xff000000 @ r9=prevcode=-1 mvn r6, #0 @ r6=prevy=-1 - ldr r4, [r1, #OFS_Draw2FB] + ldr r4, [r1, #OFS_EST_Draw2FB] ldr r2, [r0], #4 @ read y offset mov r7, #328 mla r2, r7, r2, r4 sub r12, r2, #(328*8*START_ROW) @ r12=scrpos - ldr r10, [r1, #OFS_Pico_vram] + ldr r10, [r1, #OFS_EST_PicoMem_vram] mov r8, r0 @ hc mov r0, #0xf @@ -674,11 +682,11 @@ DrawTilesFromCacheF: DrawWindowFull: stmfd sp!, {r4-r11,lr} - ldr r11, [r3, #OFS_Pico_video] - ldrb r12, [r11, #3] @ pvid->reg[3] + ldr r11, [r3, #OFS_EST_Pico] + ldrb r12, [r11, #OFS_Pico_video_reg+3] @ pvid->reg[3] mov r12, r12, lsl #10 - ldr r4, [r11, #12] + ldr r4, [r11, #OFS_Pico_video_reg+12] mov r5, #1 @ nametab_step tst r4, #1 @ 40 cell mode? andne r12, r12, #0xf000 @ 0x3c<<10 @@ -689,7 +697,7 @@ DrawWindowFull: and r4, r0, #0xff mla r12, r5, r4, r12 @ nametab += nametab_step*start; - ldr r10, [r3, #OFS_Pico_vram] + ldr r10, [r3, #OFS_EST_PicoMem_vram] mov r4, r0, lsr #16 @ r4=start_cell_h add r7, r12, r4, lsl #1 @@ -707,7 +715,7 @@ DrawWindowFull: mov r9, #0xff000000 @ r9=prevcode=-1 - ldr r11, [r3, #OFS_Draw2FB] + ldr r11, [r3, #OFS_EST_Draw2FB] and r4, r0, #0xff add r11, r11, #328*8 sub r4, r4, #START_ROW @@ -760,7 +768,8 @@ DrawWindowFull: tst r9, #0x080000 @ hflip? bne .dwf_hflip - @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf + @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=PicoMem.vram) + @ r2,r4,r7: scratch, r0=0xf Tile 0, 0 b .dwfloop @@ -870,7 +879,8 @@ DrawWindowFull: cmp r6, #(END_ROW*8+8) bge 52b - @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf + @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=PicoMem.vram) + @ r2,r4,r7: scratch, r0=0xf Tile \hflip, \vflip b 52b .endm @@ -905,8 +915,8 @@ DrawSpriteFull: and r3, lr, #0x6000 mov r3, r3, lsr #9 @ r3=pal=((code>>9)&0x30); - ldr r11, [r1, #OFS_Draw2FB] - ldr r10, [r1, #OFS_Pico_vram] + ldr r11, [r1, #OFS_EST_Draw2FB] + ldr r10, [r1, #OFS_EST_PicoMem_vram] sub r1, r12, #(START_ROW*8) mov r0, #328 mla r11, r1, r0, r11 @ scrpos+=(sy-START_ROW*8)*328; diff --git a/pico/draw_amips.s b/pico/draw_amips.s deleted file mode 100644 index fa7906e..0000000 --- a/pico/draw_amips.s +++ /dev/null @@ -1,1756 +0,0 @@ -#* -#* several drawing related functions for Allegrex MIPS -#* (C) notaz, 2007-2008 -#* -#* This work is licensed under the terms of MAME license. -#* See COPYING file in the top-level directory. -#* -#* this is highly specialized, be careful if changing related C code! -#* - -.set noreorder # don't reorder any instructions -.set noat # don't use $at - -.text -.align 4 - -# void amips_clut(unsigned short *dst, unsigned char *src, unsigned short *pal, int count) - -.global amips_clut - -amips_clut: - srl $a3, 2 -amips_clut_loop: - lbu $t0, 0($a1) # tried lw here, no improvement noticed - lbu $t1, 1($a1) - lbu $t2, 2($a1) - lbu $t3, 3($a1) - sll $t0, 1 - sll $t1, 1 - sll $t2, 1 - sll $t3, 1 - addu $t0, $a2 - addu $t1, $a2 - addu $t2, $a2 - addu $t3, $a2 - lhu $t0, 0($t0) - lhu $t1, 0($t1) - lhu $t2, 0($t2) - lhu $t3, 0($t3) - ins $t0, $t1, 16, 16 # ins rt, rs, pos, size - Insert size bits starting - ins $t2, $t3, 16, 16 # from the LSB of rs into rt starting at position pos - sw $t0, 0($a0) - sw $t2, 4($a0) - addiu $a0, 8 - addiu $a3, -1 - bnez $a3, amips_clut_loop - addiu $a1, 4 - jr $ra - nop - - -.global amips_clut_6bit - -amips_clut_6bit: - srl $a3, 2 - li $t4, 0 - li $t5, 0 - li $t6, 0 - li $t7, 0 -amips_clut_loop6: - lbu $t0, 0($a1) # tried lw here, no improvement noticed - lbu $t1, 1($a1) - lbu $t2, 2($a1) - lbu $t3, 3($a1) - ins $t4, $t0, 1, 6 - ins $t5, $t1, 1, 6 - ins $t6, $t2, 1, 6 - ins $t7, $t3, 1, 6 - addu $t0, $t4, $a2 - addu $t1, $t5, $a2 - addu $t2, $t6, $a2 - addu $t3, $t7, $a2 - lhu $t0, 0($t0) - lhu $t1, 0($t1) - lhu $t2, 0($t2) - lhu $t3, 0($t3) - ins $t0, $t1, 16, 16 # ins rt, rs, pos, size - Insert size bits starting - ins $t2, $t3, 16, 16 # from the LSB of rs into rt starting at position pos - sw $t0, 0($a0) - sw $t2, 4($a0) - addiu $a0, 8 - addiu $a3, -1 - bnez $a3, amips_clut_loop6 - addiu $a1, 4 - jr $ra - nop - - -# $a0 - pd, $a1 - tile word, $a2 - pal -# ext rt, rs, pos, size // Extract size bits from position pos in rs and store in rt - -.macro TilePixelPrep shift dreg offs -.if \shift - ext \dreg, $a1, \shift, 4 -.else - andi \dreg, $a1, 0xf -.endif -.if \offs - sltu $t8, $0, \dreg - ins $t9, $t8, \offs, 1 -.else - sltu $t9, $0, \dreg -.endif -.endm - -.macro TileStartCode - sll $a1, $a1, 1 - lui $t1, %hi(Pico+0x10000) - addu $a1, $a1, $t1 - lw $a1, %lo(Pico+0x10000)($a1) # Pico.vram + addr - beqz $a1, TileEmpty - rotr $t1, $a1, 4 - beq $t1, $a1, SingleColor - and $v0, $0 # not empty tile -.endm - -.macro TileEndCode - xori $t8, $t9, 0xff - beqz $t8, tile11111111 # common case - lui $v1, %hi(HighCol) - lui $t8, %hi(TileTable) - ins $t8, $t9, 2, 8 - lw $t8, %lo(TileTable)($t8) - lw $v1, %lo(HighCol)($v1) - jr $t8 - addu $a0, $v1 -.endm - - -.global TileNorm - -TileNorm: - TileStartCode - TilePixelPrep 12, $t0, 0 - TilePixelPrep 8, $t1, 1 - TilePixelPrep 4, $t2, 2 - TilePixelPrep 0, $t3, 3 - TilePixelPrep 28, $t4, 4 - TilePixelPrep 24, $t5, 5 - TilePixelPrep 20, $t6, 6 - TilePixelPrep 16, $t7, 7 - TileEndCode - - -.global TileFlip - -TileFlip: - TileStartCode - TilePixelPrep 16, $t0, 0 - TilePixelPrep 20, $t1, 1 - TilePixelPrep 24, $t2, 2 - TilePixelPrep 28, $t3, 3 - TilePixelPrep 0, $t4, 4 - TilePixelPrep 4, $t5, 5 - TilePixelPrep 8, $t6, 6 - TilePixelPrep 12, $t7, 7 - TileEndCode - - -SingleColor: - lui $t9, %hi(HighCol) - lw $t9, %lo(HighCol)($t9) - andi $t0, $a1, 0xf - or $t0, $t0, $a2 - addu $a0, $t9 - sb $t0, 0($a0) - sb $t0, 1($a0) - sb $t0, 2($a0) - sb $t0, 3($a0) - sb $t0, 4($a0) - sb $t0, 5($a0) - sb $t0, 6($a0) - jr $ra - sb $t0, 7($a0) - -TileEmpty: - jr $ra - or $v0, $0, 1 # empty tile - -tile11111111: - lw $v1, %lo(HighCol)($v1) - or $t0, $t0, $a2 - addu $a0, $v1 - sb $t0, 0($a0) -tile11111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile11110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile11100000: - or $t5, $t5, $a2 - sb $t5, 5($a0) -tile11000000: - or $t6, $t6, $a2 - sb $t6, 6($a0) -tile10000000: - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile11010000: - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11001000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11000100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11000010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile10110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile10100000: - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile10010000: - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10001000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10000100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10000010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile01111111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile01110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile01100000: - or $t5, $t5, $a2 - sb $t5, 5($a0) -tile01000000: - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile00000000: -tile01111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile01010000: - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01001000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01000100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01000010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile00111111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile00110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile00100000: - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile00010000: - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00001000: - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00000100: - or $t2, $t2, $a2 - jr $ra - sb $t2, 2($a0) -tile00000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - jr $ra - sb $t2, 2($a0) -tile00000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00000010: - or $t1, $t1, $a2 - jr $ra - sb $t1, 1($a0) -tile00000001: - or $t0, $t0, $a2 - jr $ra - sb $t0, 0($a0) - -.data -.align 4 - -TileTable: - .long 000000000000, tile00000001, tile00000010, tile00000011, tile00000100, tile00000101, tile00000110, tile00000111 - .long tile00001000, tile00001001, tile00001010, tile00001011, tile00001100, tile00001101, tile00001110, tile00001111 - .long tile00010000, tile00010001, tile00010010, tile00010011, tile00010100, tile00010101, tile00010110, tile00010111 - .long tile00011000, tile00011001, tile00011010, tile00011011, tile00011100, tile00011101, tile00011110, tile00011111 - .long tile00100000, tile00100001, tile00100010, tile00100011, tile00100100, tile00100101, tile00100110, tile00100111 - .long tile00101000, tile00101001, tile00101010, tile00101011, tile00101100, tile00101101, tile00101110, tile00101111 - .long tile00110000, tile00110001, tile00110010, tile00110011, tile00110100, tile00110101, tile00110110, tile00110111 - .long tile00111000, tile00111001, tile00111010, tile00111011, tile00111100, tile00111101, tile00111110, tile00111111 - .long tile01000000, tile01000001, tile01000010, tile01000011, tile01000100, tile01000101, tile01000110, tile01000111 - .long tile01001000, tile01001001, tile01001010, tile01001011, tile01001100, tile01001101, tile01001110, tile01001111 - .long tile01010000, tile01010001, tile01010010, tile01010011, tile01010100, tile01010101, tile01010110, tile01010111 - .long tile01011000, tile01011001, tile01011010, tile01011011, tile01011100, tile01011101, tile01011110, tile01011111 - .long tile01100000, tile01100001, tile01100010, tile01100011, tile01100100, tile01100101, tile01100110, tile01100111 - .long tile01101000, tile01101001, tile01101010, tile01101011, tile01101100, tile01101101, tile01101110, tile01101111 - .long tile01110000, tile01110001, tile01110010, tile01110011, tile01110100, tile01110101, tile01110110, tile01110111 - .long tile01111000, tile01111001, tile01111010, tile01111011, tile01111100, tile01111101, tile01111110, tile01111111 - .long tile10000000, tile10000001, tile10000010, tile10000011, tile10000100, tile10000101, tile10000110, tile10000111 - .long tile10001000, tile10001001, tile10001010, tile10001011, tile10001100, tile10001101, tile10001110, tile10001111 - .long tile10010000, tile10010001, tile10010010, tile10010011, tile10010100, tile10010101, tile10010110, tile10010111 - .long tile10011000, tile10011001, tile10011010, tile10011011, tile10011100, tile10011101, tile10011110, tile10011111 - .long tile10100000, tile10100001, tile10100010, tile10100011, tile10100100, tile10100101, tile10100110, tile10100111 - .long tile10101000, tile10101001, tile10101010, tile10101011, tile10101100, tile10101101, tile10101110, tile10101111 - .long tile10110000, tile10110001, tile10110010, tile10110011, tile10110100, tile10110101, tile10110110, tile10110111 - .long tile10111000, tile10111001, tile10111010, tile10111011, tile10111100, tile10111101, tile10111110, tile10111111 - .long tile11000000, tile11000001, tile11000010, tile11000011, tile11000100, tile11000101, tile11000110, tile11000111 - .long tile11001000, tile11001001, tile11001010, tile11001011, tile11001100, tile11001101, tile11001110, tile11001111 - .long tile11010000, tile11010001, tile11010010, tile11010011, tile11010100, tile11010101, tile11010110, tile11010111 - .long tile11011000, tile11011001, tile11011010, tile11011011, tile11011100, tile11011101, tile11011110, tile11011111 - .long tile11100000, tile11100001, tile11100010, tile11100011, tile11100100, tile11100101, tile11100110, tile11100111 - .long tile11101000, tile11101001, tile11101010, tile11101011, tile11101100, tile11101101, tile11101110, tile11101111 - .long tile11110000, tile11110001, tile11110010, tile11110011, tile11110100, tile11110101, tile11110110, tile11110111 - .long tile11111000, tile11111001, tile11111010, tile11111011, tile11111100, tile11111101, tile11111110, tile11111111 - -# vim:filetype=mips diff --git a/pico/draw_arm.S b/pico/draw_arm.S index 71db183..29af1c1 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -19,7 +19,17 @@ .equ PDRAW_PLANE_HI_PRIO, (1<<6) .equ PDRAW_SHHI_DONE, (1<<7) -@ helper +@ helpers +.macro add_c24 d s c + add \d, \s, #(\c & 0x00ff00) +.if \c & 0x0000ff + add \d, \d, #(\c & 0x0000ff) +.endif +.if \c & 0xff0000 + add \d, \d, #(\c & 0xff0000) +.endif +.endm + .macro TilePixel pat lsrr offs .if !\lsrr ands r4, \pat, r2 @@ -278,7 +288,7 @@ @ int cells; // 0x14 @ }; -@ void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells, +@ void DrawLayer(int lflags, int *hcache, int cellskip, int maxcells, @ struct PicoEState *est) .global DrawLayer @@ -287,14 +297,14 @@ DrawLayer: ldr r12, [sp] @ est stmfd sp!, {r4-r11,lr} - ldr r11, [r12, #OFS_Pico_video] + ldr r11, [r12, #OFS_EST_Pico] mov r8, #1 - ldrb r7, [r11, #16] @ ??vv??hh + ldrb r7, [r11, #OFS_Pico_video_reg+16] @ ??vv??hh mov r6, r1 @ hcache - orr r9, r3, r0, lsl #30 - orr r9, r9, r2, lsl #8 @ r9=sh[31]|cellskip[15:8]|maxcells[7:0] (tmp) + orr r9, r3, r0, lsl #29 @ r9=force[31]|sh[30]|plane[29] + orr r9, r9, r2, lsl #8 @ |cellskip[15:8]|maxcells[7:0] (tmp) mov r1, r7, lsl #4 orr r1, r1, #0x00ff @@ -303,19 +313,21 @@ DrawLayer: cmp r10, #1 biclt r1, r1, #0xfc00 biceq r1, r1, #0xfe00 - bicgt r1, r1, #0xff00 @ r1=ymask=(height<<8)|0xff; ...; // Y Mask in pixels + cmp r10, #2 + moveq r1, #0x0007 + movgt r1, #0x00ff @ r1=ymask=(height<<8)|0xff; ...; // Y Mask in pixels add r10, r10, #5 cmp r10, #7 subge r10, r10, #1 @ r10=shift[width] (5,6,6,7) - ldr r2, [r12, #OFS_DrawScanline] - ldr lr, [r12, #OFS_Pico_vram] + ldr r2, [r12, #OFS_EST_DrawScanline] + ldr lr, [r12, #OFS_EST_PicoMem_vram] @ Find name table: ands r0, r0, #1 - ldreqb r12, [r11, #2] - ldrneb r12, [r11, #4] + ldreqb r12, [r11, #OFS_Pico_video_reg+2] + ldrneb r12, [r11, #OFS_Pico_video_reg+4] @ calculate xmask: mov r5, r8, lsl r10 @@ -325,8 +337,8 @@ DrawLayer: movne r12, r12, lsl #13 and r12, r12, #(7<<13) @ r12=(ts->nametab<<1) (halfword compliant) - ldrh r8, [r11, #12] - ldrb r7, [r11, #11] + ldrh r8, [r11, #OFS_Pico_video_reg+12] + ldrb r7, [r11, #OFS_Pico_video_reg+11] mov r4, r8, lsr #8 @ pvid->reg[13] mov r4, r4, lsl #10 @ htab=pvid->reg[13]<<9; (halfwords) @@ -342,8 +354,7 @@ DrawLayer: bne .DrawStrip_vsscroll @ Get vertical scroll value: - add r7, lr, #0x012000 - add r7, r7, #0x000180 @ r7=Pico.vsram (Pico+0x22180) + add_c24 r7, lr, (OFS_PMEM_vsram-OFS_PMEM_vram) ldr r7, [r7] tst r8, #2 @@ -373,10 +384,11 @@ DrawLayer: and r1, r1, #7 add r7, r1, #1 @ r7=dx=((ts->hscroll-1)&7)+1 - tst r9, #1<<31 + movs r3, r9, lsl #1 @ (force[31]|sh[30]) << 1 mov r3, #0 - orrne r10,r10, #1<<23 @ r10=(cells<<24|sh<<23|hi_not_empty<<22|had_output<<21|ty) - movne r3, #0x40 @ default to shadowed pal on sh mode + orrmi r10,r10, #1<<23 @ r10=cells[31:24]|sh[23]|hi_not_empty[22] + orrcs r10,r10, #1<<20 @ |had_output[21]|force[20]|ty[15:0] + movmi r3, #0x40 @ default to shadowed pal on sh mode cmp r7, #8 addne r10,r10, #0x01000000 @ we will loop cells+1 times if there is scroll @@ -389,7 +401,7 @@ DrawLayer: @ cache some stuff to avoid mem access ldr r11,[sp, #9*4] @ est mov r0, #0xf - ldr r11,[r11, #OFS_HighCol] + ldr r11,[r11, #OFS_EST_HighCol] mvn r9, #0 @ r9=prevcode=-1 add r1, r11, r7 @ r1=pdest @@ -411,6 +423,7 @@ DrawLayer: add r8, r8, #1 tst r7, #0x8000 + tsteq r10, #1<<20 @ force? bne .DrawStrip_hiprio cmp r7, r9 @@ -478,7 +491,7 @@ DrawLayer: orr r10, r10, #1<<22 .DrawStrip_hiprio: - tst r10, #0x00c00000 + tst r10, #0x00d00000 @ sh[23]|hi_not_empty[22]|force[20] beq .DrawStrip_hiprio_maybempt sub r0, r1, r11 orr r7, r7, r0, lsl #16 @@ -493,10 +506,10 @@ DrawLayer: tst r10, #1<<21 @ seen non hi-prio tile ldr r1, [sp, #9*4] @ est mov r0, #0 - ldreq r2, [r1, #OFS_rendstatus] + ldreq r2, [r1, #OFS_EST_rendstatus] str r0, [r6] @ terminate the cache list orreq r2, r2, #PDRAW_PLANE_HI_PRIO @ had a layer with all hi-prio tiles - streq r2, [r1, #OFS_rendstatus] + streq r2, [r1, #OFS_EST_rendstatus] ldmfd sp!, {r4-r11,lr} bx lr @@ -511,24 +524,29 @@ DrawLayer: ldr r11, [sp, #9*4] @ est orr r5, r1, r10, lsl #24 - ldr r4, [r11, #OFS_DrawScanline] + ldr r4, [r11, #OFS_EST_DrawScanline] sub r1, r3, #1 orr r5, r5, r4, lsl #16 @ r5=(shift_width[31:24]|scanline[23:16]|ymask[15:0]) and r1, r1, #7 add r7, r1, #1 @ r7=dx=((ts->hscroll-1)&7)+1 mov r10,r9, lsl #16 + orr r10,r10, #0xff000000 @ will be adjusted on entering loop tst r0, #1 orrne r10,r10, #0x8000 + tst r3, #0x0f @ hscroll & 0x0f? + beq 0f + eor r3, r3, r7 + sub r10,r10, #1<<24 @ cell-- // start from negative for hscroll + tst r3, #0x08 + subne r10,r10, #1<<16 @ cells-- + subne r10,r10, #1<<24 @ cell-- // even more negative +0: tst r9, #1<<31 mov r3, #0 - orr r10,r10, #0xff000000 @ will be adjusted on entering loop orrne r10,r10, #1<<23 @ r10=(cell[31:24]|sh[23]|hi_not_empty[22]|cells_max[21:16]|plane[15]|ty[14:0]) movne r3, #0x40 @ default to shadowed pal on sh mode - cmp r7, #8 - subne r10,r10, #0x01000000 @ have hscroll, start with negative cell - and r9, r9, #0xff00 add r8, r8, r9, lsr #8 @ tilex+=cellskip add r7, r7, r9, lsr #5 @ dx+=cellskip<<3; @@ -537,7 +555,7 @@ DrawLayer: @ cache some stuff to avoid mem access ldr r11,[sp, #9*4] @ est mov r0, #0xf - ldr r11,[r11, #OFS_HighCol] + ldr r11,[r11, #OFS_EST_HighCol] mvn r9, #0 @ r9=prevcode=-1 add r1, r11, r7 @ r1=pdest @@ -552,8 +570,7 @@ DrawLayer: ble .dsloop_vs_exit @ calc offset and read tileline code to r7, also calc ty - add r7, lr, #0x012000 - add r7, r7, #0x000180 @ r7=Pico.vsram (Pico+0x22180) + add_c24 r7, lr, (OFS_PMEM_vsram-OFS_PMEM_vram) add r7, r7, r10,asr #23 @ vsram + ((cell&~1)<<1) bic r7, r7, #3 tst r10,#0x8000 @ plane1? @@ -572,7 +589,7 @@ DrawLayer: mov r4, r4, lsl r7 @ nametabadd and r7, r8, r8, lsr #25 - add r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords) + add r7, lr, r7, lsl #1 @ PicoMem.vram+((tilex&ts->xmask) as halfwords) add r7, r7, r4, lsl #1 ldrh r7, [r7, r12] @ r7=code (int, but from unsigned, no sign extend) @@ -594,7 +611,7 @@ DrawLayer: mov r2, r2, lsr #17 eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; - ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels bic r7, r3, #0x3f and r3, r9, #0x6000 @@ -652,7 +669,7 @@ DrawLayer: add r2, r2, r10, lsl #17 mov r2, r2, lsr #17 eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; - ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels mov r9, r7 @ remember code tst r2, r2 orrne r10, r10, #1<<22 @@ -663,10 +680,10 @@ DrawLayer: tst r8, #(1<<24) @ seen non hi-prio tile ldr r1, [sp, #9*4] @ est mov r0, #0 - ldreq r2, [r1, #OFS_rendstatus] + ldreq r2, [r1, #OFS_EST_rendstatus] str r0, [r6] @ terminate the cache list orreq r2, r2, #PDRAW_PLANE_HI_PRIO @ had a layer with all hi-prio tiles - streq r2, [r1, #OFS_rendstatus] + streq r2, [r1, #OFS_EST_rendstatus] ldmfd sp!, {r4-r11,lr} bx lr @@ -712,7 +729,7 @@ BackFill: stmfd sp!, {r4-r9,lr} mov r0, r0, lsl #26 - ldr lr, [r2, #OFS_HighCol] + ldr lr, [r2, #OFS_EST_HighCol] mov r0, r0, lsr #26 add lr, lr, #8 @@ -754,9 +771,9 @@ DrawTilesFromCache: stmfd sp!, {r4-r9,r11,lr} @ cache some stuff to avoid mem access - ldr r11,[r3, #OFS_HighCol] + ldr r11,[r3, #OFS_EST_HighCol] mov r12,#0xf - ldr lr, [r3, #OFS_Pico_vram] + ldr lr, [r3, #OFS_EST_PicoMem_vram] mov r9, r3 @ est mvn r5, #0 @ r5=prevcode=-1 @@ -772,7 +789,8 @@ DrawTilesFromCache: bic r4, r1, #0xfe00 add r1, r11, r4 @ r1=pdest - mov r7, r6, lsl #16 + movs r7, r6, lsl #16 + bpl .dtfc_loop @ !(code & 0x8000) cmp r5, r7, lsr #16 beq .dtfc_samecode @ if (code==prevcode) @@ -887,14 +905,14 @@ DrawTilesFromCache: @ check if we have detected layer covered with hi-prio tiles: .dtfc_check_rendflags: - ldr r2, [r9, #OFS_rendstatus] + ldr r2, [r9, #OFS_EST_rendstatus] tst r2, #(PDRAW_PLANE_HI_PRIO|PDRAW_SHHI_DONE) beq .dtfc_loop bic r8, r8, #1 @ sh/hi mode off tst r2, #PDRAW_SHHI_DONE bne .dtfc_loop @ already processed orr r2, r2, #PDRAW_SHHI_DONE - str r2, [r9, #OFS_rendstatus] + str r2, [r9, #OFS_EST_rendstatus] add r1, r11,#8 mov r3, #320/4/4 @@ -934,16 +952,16 @@ DrawSpritesSHi: add r10,r0, #3 @ r10=HighLnSpr end add r10,r10,r3 @ r10=HighLnSpr end - ldr r11,[r1, #OFS_HighCol] + ldr r11,[r1, #OFS_EST_HighCol] mov r12,#0xf - ldr lr, [r1, #OFS_Pico_vram] + ldr lr, [r1, #OFS_EST_PicoMem_vram] DrawSpriteSHi: @ draw next sprite ldrb r0, [r10,#-1]! ldr r7, [sp] @ est - ldr r1, [r7, #OFS_HighPreSpr] + ldr r1, [r7, #OFS_EST_HighPreSpr] cmp r0, #0xff ldmeqfd sp!, {r1,r4-r11,pc} @ end of list and r0, r0, #0x7f @@ -969,7 +987,7 @@ DrawSpriteSHi: mov r5, r3, lsr #24 and r5, r5, #7 @ r5=height - ldr r7, [r7, #OFS_DrawScanline] + ldr r7, [r7, #OFS_EST_DrawScanline] mov r0, r3, lsl #16 @ r4=sy<<16 (tmp) sub r7, r7, r0, asr #16 @ r7=row=DrawScanline-sy @@ -1010,7 +1028,7 @@ DrawSpriteSHi: mov r8, r8, lsl #17 mov r8, r8, lsr #17 @ tile&=0x7fff; // Clip tile address - ldr r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + ldr r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels add r1, r11, r0 @ r1=pdest tst r2, r2 beq .dsprShi_loop @@ -1101,17 +1119,6 @@ DrawSpriteSHi: DrawAllSprites: orr r1, r2, r1, lsl #1 - ldr r12,[r3, #OFS_rendstatus] - tst r12,#(PDRAW_DIRTY_SPRITES|PDRAW_SPRITES_MOVED) - beq das_no_prep - stmfd sp!, {r0,r1,r3,lr} - and r0, r12,#PDRAW_DIRTY_SPRITES - bic r12,r12,#(PDRAW_DIRTY_SPRITES|PDRAW_SPRITES_MOVED) - str r12,[r3, #OFS_rendstatus] - bl PrepareSprites - ldmfd sp!, {r0,r1,r3,lr} - -das_no_prep: ldr r2, [r0] ands r2, r2, #0x7f bxeq lr @@ -1123,9 +1130,9 @@ das_no_prep: add r10,r0, #3 add r10,r10,r2 @ r10=HighLnSpr end - ldr r11,[r3, #OFS_HighCol] + ldr r11,[r3, #OFS_EST_HighCol] mov r12,#0xf - ldr lr, [r3, #OFS_Pico_vram] + ldr lr, [r3, #OFS_EST_PicoMem_vram] @ + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: horiz. size @ + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 @@ -1140,12 +1147,12 @@ DrawSprite: ldmeqfd sp!, {r1,r3-r11,pc} @ end of list cmp r2, r8, lsr #1 bne DrawSprite @ wrong priority - ldr r1, [r7, #OFS_HighPreSpr] + ldr r1, [r7, #OFS_EST_HighPreSpr] and r0, r0, #0x7f add r0, r1, r0, lsl #3 ldr r3, [r0] @ sprite[0] - ldr r7, [r7, #OFS_DrawScanline] + ldr r7, [r7, #OFS_EST_DrawScanline] mov r6, r3, lsr #28 sub r6, r6, #1 @ r6=width-1 (inc later) mov r5, r3, lsr #24 @@ -1204,7 +1211,7 @@ DrawSprite: mov r8, r8, lsl #17 mov r8, r8, lsr #17 @ tile&=0x7fff; // Clip tile address - ldr r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + ldr r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels add r1, r11, r0 @ r1=pdest tst r2, r2 beq .dspr_loop @@ -1273,12 +1280,12 @@ DrawWindow: ldr r12, [sp] @ est stmfd sp!, {r4-r11,lr} - ldr r6, [r12, #OFS_Pico_video] - ldr r10, [r12, #OFS_DrawScanline] + ldr r6, [r12, #OFS_EST_Pico] + ldr r10, [r12, #OFS_EST_DrawScanline] mov r11, r12 @ est - ldrb r12, [r6, #3] @ pvid->reg[3] + ldrb r12, [r6, #OFS_Pico_video_reg+3] @ pvid->reg[3] - ldr r4, [r6, #12] + ldr r4, [r6, #OFS_Pico_video_reg+12] mov r5, r10, lsr #3 and r10, r10, #7 mov r10, r10, lsl #1 @ r10=ty @@ -1292,8 +1299,8 @@ DrawWindow: addeq r12, r12, r5, lsl #6 @ nametab add r12, r12, r0, lsl #2 @ +starttile - ldr lr, [r11, #OFS_Pico_vram] - ldr r6, [r11, #OFS_rendstatus] + ldr lr, [r11, #OFS_EST_PicoMem_vram] + ldr r6, [r11, #OFS_EST_rendstatus] @ fetch the first code now ldrh r7, [lr, r12] @@ -1310,7 +1317,7 @@ DrawWindow: sub r8, r1, r0 @ cache some stuff to avoid mem access - ldr r11, [r11, #OFS_HighCol] + ldr r11, [r11, #OFS_EST_HighCol] mov r8, r8, lsl #1 @ cells add r11,r11,#8 mvn r9, #0 @ r9=prevcode=-1 @@ -1398,9 +1405,9 @@ DrawWindow: and r2, r6, #PDRAW_WND_DIFF_PRIO ldmfd sp!, {r4-r11,lr} ldr r0, [sp] - ldr r1, [r0, #OFS_rendstatus] + ldr r1, [r0, #OFS_EST_rendstatus] orr r1, r1, r2 - str r1, [r0, #OFS_rendstatus] + str r1, [r0, #OFS_EST_rendstatus] bx lr @@ -1492,17 +1499,17 @@ PicoDoHighPal555: stmfd sp!, {r4-r10,lr} mov r10,r2 @ est mov r1, #0 - ldr r8, [r10, #OFS_Pico_video] + ldr r8, [r10, #OFS_EST_Pico] PicoDoHighPal555_nopush: orr r9, r1, r0, lsl #31 @ 0:called from FinalizeLine555, 31: s/h - add r0, r10, #OFS_HighPal + add r0, r10, #OFS_EST_HighPal mov r1, #0 - strb r1, [r8, #-0x1a] @ 0x2220e ~ dirtyPal + strb r1, [r8, #OFS_Pico_m_dirtyPal] - sub r1, r8, #0x128 @ r1=Pico.cram + ldr r1, [r10, #OFS_EST_PicoMem_cram] mov r2, #0x40 mov r8, #0x0061 orr r8, r8, #0x0800 @@ -1513,7 +1520,7 @@ PicoDoHighPal555_nopush: tst r9, #(1<<31) beq PicoDoHighPal555_end - add r3, r10, #OFS_HighPal + add r3, r10, #OFS_EST_HighPal @ shadowed pixels: mov r12, #0x008e @@ -1556,7 +1563,7 @@ PicoDoHighPal555_end: tst r9, #1 ldmeqfd sp!, {r4-r10,pc} - ldr r8, [r10, #OFS_Pico_video] + ldr r8, [r10, #OFS_EST_Pico] b FinalizeLineRGB555_pal_done @@ -1567,33 +1574,33 @@ PicoDoHighPal555_end: FinalizeLine555: stmfd sp!, {r4-r10,lr} mov r10,r2 @ est - ldr r8, [r10, #OFS_Pico_video] + ldr r8, [r10, #OFS_EST_Pico] - ldrb r2, [r8, #-0x1a] @ 0x2220e ~ dirtyPal + ldrb r2, [r8, #OFS_Pico_m_dirtyPal] mov r1, #1 tst r2, r2 bne PicoDoHighPal555_nopush FinalizeLineRGB555_pal_done: - add r3, r10, #OFS_HighPal + add r3, r10, #OFS_EST_HighPal - ldr r12, [r10, #OFS_rendstatus] + ldr r12, [r10, #OFS_EST_rendstatus] eors r0, r0, #1 @ sh is 0 mov lr, #0xff tstne r12,#PDRAW_ACC_SPRITES movne lr, #0x3f - ldr r1, [r10, #OFS_HighCol] - ldr r0, [r10, #OFS_DrawLineDest] + ldr r1, [r10, #OFS_EST_HighCol] + ldr r0, [r10, #OFS_EST_DrawLineDest] add r1, r1, #8 - ldrb r12, [r8, #12] + ldrb r12, [r8, #OFS_Pico_video_reg+12] mov lr, lr, lsl #1 tst r12, #1 movne r2, #320/8 @ len bne .fl_no32colRGB555 - ldr r4, [r10, #OFS_PicoOpt] + ldr r4, [r10, #OFS_EST_PicoOpt] mov r2, #256/8 ldr r4, [r4] tst r4, #0x4000 diff --git a/pico/eeprom.c b/pico/eeprom.c index 16f6c05..d727766 100644 --- a/pico/eeprom.c +++ b/pico/eeprom.c @@ -42,14 +42,14 @@ static void EEPROM_write_do(unsigned int d) // ???? ??la (l=SCL, a=SDA) { // we are started and SCL went high - next cycle scyc++; // pre-increment - if(SRam.eeprom_type) { + if(Pico.sv.eeprom_type) { // X24C02+ if((ssa&1) && scyc == 18) { scyc = 9; saddr++; // next address in read mode - /*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask + /*if(Pico.sv.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask } - else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18; + else if(Pico.sv.eeprom_type == 2 && scyc == 27) scyc = 18; else if(scyc == 36) scyc = 27; } else { // X24C01 @@ -63,29 +63,29 @@ static void EEPROM_write_do(unsigned int d) // ???? ??la (l=SCL, a=SDA) else if((sreg & 8) && (sreg & 2) && !(d&2)) { // we are started and SCL went low (falling edge) - if(SRam.eeprom_type) { + if(Pico.sv.eeprom_type) { // X24C02+ if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles - else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) { + else if( (Pico.sv.eeprom_type == 3 && scyc > 27) || (Pico.sv.eeprom_type == 2 && scyc > 18) ) { if(!(ssa&1)) { // data write - unsigned char *pm=SRam.data+saddr; + unsigned char *pm=Pico.sv.data+saddr; *pm <<= 1; *pm |= d&1; if(scyc == 26 || scyc == 35) { saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm); } - SRam.changed = 1; + Pico.sv.changed = 1; } } else if(scyc > 9) { if(!(ssa&1)) { // we latch another addr bit saddr<<=1; - if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask + if(Pico.sv.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask saddr|=d&1; if(scyc==17||scyc==26) { elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr); - if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too + if(scyc==17&&Pico.sv.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too } } } else { @@ -99,13 +99,13 @@ static void EEPROM_write_do(unsigned int d) // ???? ??la (l=SCL, a=SDA) else if(scyc > 9) { if(!(saddr&1)) { // data write - unsigned char *pm=SRam.data+(saddr>>1); + unsigned char *pm=Pico.sv.data+(saddr>>1); *pm <<= 1; *pm |= d&1; if(scyc == 17) { saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm); } - SRam.changed = 1; + Pico.sv.changed = 1; } } else { // we latch another addr bit @@ -129,11 +129,11 @@ static void EEPROM_upd_pending(unsigned int d) sreg &= ~0xc0; // SCL - d1 = (d >> SRam.eeprom_bit_cl) & 1; + d1 = (d >> Pico.sv.eeprom_bit_cl) & 1; sreg |= d1 << 7; // SDA in - d1 = (d >> SRam.eeprom_bit_in) & 1; + d1 = (d >> Pico.sv.eeprom_bit_in) & 1; sreg |= d1 << 6; Pico.m.eeprom_status = (unsigned char) sreg; @@ -190,23 +190,23 @@ unsigned int EEPROM_read(void) } else if (scyc > 9 && scyc < 18) { // started and first command word received shift = 17-scyc; - if (SRam.eeprom_type) { + if (Pico.sv.eeprom_type) { // X24C02+ if (ssa&1) { elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg); - if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]); - d = (SRam.data[saddr]>>shift)&1; + if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", Pico.sv.data[saddr]); + d = (Pico.sv.data[saddr]>>shift)&1; } } else { // X24C01 if (saddr&1) { elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg); - if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]); - d = (SRam.data[saddr>>1]>>shift)&1; + if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", Pico.sv.data[saddr>>1]); + d = (Pico.sv.data[saddr>>1]>>shift)&1; } } } - return (d << SRam.eeprom_bit_out); + return (d << Pico.sv.eeprom_bit_out); } diff --git a/pico/memory.c b/pico/memory.c index e72628e..e747552 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -63,6 +63,17 @@ void cpu68k_map_set(uptr *map, int start_addr, int end_addr, const void *func_or_mh, int is_func) { xmap_set(map, M68K_MEM_SHIFT, start_addr, end_addr, func_or_mh, is_func); +#ifdef EMU_F68K + // setup FAME fetchmap + if (!is_func) + { + int shiftout = 24 - FAMEC_FETCHBITS; + int i = start_addr >> shiftout; + uptr base = (uptr)func_or_mh - (i << shiftout); + for (; i <= (end_addr >> shiftout); i++) + PicoCpuFM68k.Fetch[i] = base; + } +#endif } // more specialized/optimized function (does same as above) @@ -89,6 +100,17 @@ void cpu68k_map_all_ram(int start_addr, int end_addr, void *ptr, int is_sub) addr >>= 1; for (i = start_addr >> shift; i <= end_addr >> shift; i++) r8map[i] = r16map[i] = w8map[i] = w16map[i] = addr; +#ifdef EMU_F68K + // setup FAME fetchmap + { + M68K_CONTEXT *ctx = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k; + int shiftout = 24 - FAMEC_FETCHBITS; + i = start_addr >> shiftout; + addr = (uptr)ptr - (i << shiftout); + for (; i <= (end_addr >> shiftout); i++) + ctx->Fetch[i] = addr; + } +#endif } static u32 m68k_unmapped_read8(u32 a) @@ -243,8 +265,8 @@ static port_read_func *port_readers[3] = { static NOINLINE u32 port_read(int i) { - u32 data_reg = Pico.ioports[i + 1]; - u32 ctrl_reg = Pico.ioports[i + 4] | 0x80; + u32 data_reg = PicoMem.ioports[i + 1]; + u32 ctrl_reg = PicoMem.ioports[i + 4] | 0x80; u32 in, out; out = data_reg & ctrl_reg; @@ -288,7 +310,7 @@ NOINLINE u32 io_ports_read(u32 a) case 1: d = port_read(0); break; case 2: d = port_read(1); break; case 3: d = port_read(2); break; - default: d = Pico.ioports[a]; break; // IO ports can be used as RAM + default: d = PicoMem.ioports[a]; break; // IO ports can be used as RAM } return d; } @@ -301,30 +323,29 @@ NOINLINE void io_ports_write(u32 a, u32 d) if (1 <= a && a <= 2) { Pico.m.padDelay[a - 1] = 0; - if (!(Pico.ioports[a] & 0x40) && (d & 0x40)) + if (!(PicoMem.ioports[a] & 0x40) && (d & 0x40)) Pico.m.padTHPhase[a - 1]++; } // certain IO ports can be used as RAM - Pico.ioports[a] = d; + PicoMem.ioports[a] = d; } -// lame.. static int z80_cycles_from_68k(void) { - return z80_cycle_aim - + cycles_68k_to_z80(SekCyclesDone() - last_z80_sync); + int m68k_cnt = SekCyclesDone() - Pico.t.m68c_frame_start; + return cycles_68k_to_z80(m68k_cnt); } void NOINLINE ctl_write_z80busreq(u32 d) { d&=1; d^=1; - elprintf(EL_BUSREQ, "set_zrun: %i->%i [%i] @%06x", Pico.m.z80Run, d, SekCyclesDone(), SekPc); + elprintf(EL_BUSREQ, "set_zrun: %i->%i [%u] @%06x", Pico.m.z80Run, d, SekCyclesDone(), SekPc); if (d ^ Pico.m.z80Run) { if (d) { - z80_cycle_cnt = z80_cycles_from_68k(); + Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; } else { @@ -341,7 +362,7 @@ void NOINLINE ctl_write_z80busreq(u32 d) void NOINLINE ctl_write_z80reset(u32 d) { d&=1; d^=1; - elprintf(EL_BUSREQ, "set_zreset: %i->%i [%i] @%06x", Pico.m.z80_reset, d, SekCyclesDone(), SekPc); + elprintf(EL_BUSREQ, "set_zreset: %i->%i [%u] @%06x", Pico.m.z80_reset, d, SekCyclesDone(), SekPc); if (d ^ Pico.m.z80_reset) { if (d) @@ -356,13 +377,35 @@ void NOINLINE ctl_write_z80reset(u32 d) } else { - z80_cycle_cnt = z80_cycles_from_68k(); + Pico.t.z80c_cnt = z80_cycles_from_68k() + 2; z80_reset(); } Pico.m.z80_reset = d; } } +static int get_scanline(int is_from_z80); + +static void psg_write_68k(u32 d) +{ + // look for volume write and update if needed + if ((d & 0x90) == 0x90 && PsndPsgLine < Pico.m.scanline) + PsndDoPSG(Pico.m.scanline); + + SN76496Write(d); +} + +static void psg_write_z80(u32 d) +{ + if ((d & 0x90) == 0x90) { + int scanline = get_scanline(1); + if (PsndPsgLine < scanline) + PsndDoPSG(scanline); + } + + SN76496Write(d); +} + // ----------------------------------------------------------------- #ifndef _ASM_MEMORY_C @@ -371,14 +414,14 @@ void NOINLINE ctl_write_z80reset(u32 d) static u32 PicoRead8_sram(u32 a) { u32 d; - if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED)) + if (Pico.sv.start <= a && a <= Pico.sv.end && (Pico.m.sram_reg & SRR_MAPPED)) { - if (SRam.flags & SRF_EEPROM) { + if (Pico.sv.flags & SRF_EEPROM) { d = EEPROM_read(); if (!(a & 1)) d >>= 8; } else - d = *(u8 *)(SRam.data - SRam.start + a); + d = *(u8 *)(Pico.sv.data - Pico.sv.start + a); elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc); return d; } @@ -393,12 +436,12 @@ static u32 PicoRead8_sram(u32 a) static u32 PicoRead16_sram(u32 a) { u32 d; - if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED)) + if (Pico.sv.start <= a && a <= Pico.sv.end && (Pico.m.sram_reg & SRR_MAPPED)) { - if (SRam.flags & SRF_EEPROM) + if (Pico.sv.flags & SRF_EEPROM) d = EEPROM_read(); else { - u8 *pm = (u8 *)(SRam.data - SRam.start + a); + u8 *pm = (u8 *)(Pico.sv.data - Pico.sv.start + a); d = pm[0] << 8; d |= pm[1]; } @@ -416,20 +459,20 @@ static u32 PicoRead16_sram(u32 a) static void PicoWrite8_sram(u32 a, u32 d) { - if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) { + if (a > Pico.sv.end || a < Pico.sv.start || !(Pico.m.sram_reg & SRR_MAPPED)) { m68k_unmapped_write8(a, d); return; } elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d & 0xff, SekPc); - if (SRam.flags & SRF_EEPROM) + if (Pico.sv.flags & SRF_EEPROM) { EEPROM_write8(a, d); } else { - u8 *pm = (u8 *)(SRam.data - SRam.start + a); + u8 *pm = (u8 *)(Pico.sv.data - Pico.sv.start + a); if (*pm != (u8)d) { - SRam.changed = 1; + Pico.sv.changed = 1; *pm = (u8)d; } } @@ -437,29 +480,32 @@ static void PicoWrite8_sram(u32 a, u32 d) static void PicoWrite16_sram(u32 a, u32 d) { - if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) { + if (a > Pico.sv.end || a < Pico.sv.start || !(Pico.m.sram_reg & SRR_MAPPED)) { m68k_unmapped_write16(a, d); return; } elprintf(EL_SRAMIO, "sram w16 [%06x] %04x @ %06x", a, d & 0xffff, SekPc); - if (SRam.flags & SRF_EEPROM) + if (Pico.sv.flags & SRF_EEPROM) { EEPROM_write16(d); } else { - // XXX: hardware could easily use MSB too.. - u8 *pm = (u8 *)(SRam.data - SRam.start + a); - if (*pm != (u8)d) { - SRam.changed = 1; - *pm = (u8)d; + u8 *pm = (u8 *)(Pico.sv.data - Pico.sv.start + a); + if (pm[0] != (u8)(d >> 8)) { + Pico.sv.changed = 1; + pm[0] = (u8)(d >> 8); + } + if (pm[1] != (u8)d) { + Pico.sv.changed = 1; + pm[1] = (u8)d; } } } // z80 area (0xa00000 - 0xa0ffff) // TODO: verify mirrors VDP and bank reg (bank area mirroring verified) -u32 PicoRead8_z80(u32 a) +static u32 PicoRead8_z80(u32 a) { u32 d = 0xff; if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { @@ -469,7 +515,7 @@ u32 PicoRead8_z80(u32 a) } if ((a & 0x4000) == 0x0000) - d = Pico.zram[a & 0x1fff]; + d = PicoMem.zram[a & 0x1fff]; else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff d = ym2612_read_local_68k(); else @@ -483,7 +529,7 @@ static u32 PicoRead16_z80(u32 a) return d | (d << 8); } -void PicoWrite8_z80(u32 a, u32 d) +static void PicoWrite8_z80(u32 a, u32 d) { if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { // verified on real hw @@ -492,8 +538,7 @@ void PicoWrite8_z80(u32 a, u32 d) } if ((a & 0x4000) == 0x0000) { // z80 RAM - SekCyclesBurnRun(2); // FIXME hack - Pico.zram[a & 0x1fff] = (u8)d; + PicoMem.zram[a & 0x1fff] = (u8)d; return; } if ((a & 0x6000) == 0x4000) { // FM Sound @@ -503,8 +548,7 @@ void PicoWrite8_z80(u32 a, u32 d) } // TODO: probably other VDP access too? Maybe more mirrors? if ((a & 0x7ff9) == 0x7f11) { // PSG Sound - if (PicoOpt & POPT_EN_PSG) - SN76496Write(d); + psg_write_68k(d); return; } if ((a & 0x7f00) == 0x6000) // Z80 BANK register @@ -548,7 +592,7 @@ u32 PicoRead8_io(u32 a) if ((a & 0xff01) == 0x1100) { // z80 busreq (verified) d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; - elprintf(EL_BUSREQ, "get_zrun: %02x [%i] @%06x", d, SekCyclesDone(), SekPc); + elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc); } goto end; } @@ -583,7 +627,7 @@ u32 PicoRead16_io(u32 a) if ((a & 0xff00) == 0x1100) { // z80 busreq d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8; - elprintf(EL_BUSREQ, "get_zrun: %04x [%i] @%06x", d, SekCyclesDone(), SekPc); + elprintf(EL_BUSREQ, "get_zrun: %04x [%u] @%06x", d, SekCyclesDone(), SekPc); } goto end; } @@ -657,10 +701,21 @@ void PicoWrite16_io(u32 a, u32 d) // VDP area (0xc00000 - 0xdfffff) // TODO: verify if lower byte goes to PSG on word writes -static u32 PicoRead8_vdp(u32 a) +u32 PicoRead8_vdp(u32 a) { - if ((a & 0x00e0) == 0x0000) - return PicoVideoRead8(a); + if ((a & 0x00f0) == 0x0000) { + switch (a & 0x0d) + { + case 0x00: return PicoVideoRead8DataH(); + case 0x01: return PicoVideoRead8DataL(); + case 0x04: return PicoVideoRead8CtlH(); + case 0x05: return PicoVideoRead8CtlL(); + case 0x08: + case 0x0c: return PicoVideoRead8HV_H(); + case 0x09: + case 0x0d: return PicoVideoRead8HV_L(); + } + } elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); return 0; @@ -678,8 +733,7 @@ static u32 PicoRead16_vdp(u32 a) static void PicoWrite8_vdp(u32 a, u32 d) { if ((a & 0x00f9) == 0x0011) { // PSG Sound - if (PicoOpt & POPT_EN_PSG) - SN76496Write(d); + psg_write_68k(d); return; } if ((a & 0x00e0) == 0x0000) { @@ -693,11 +747,8 @@ static void PicoWrite8_vdp(u32 a, u32 d) static void PicoWrite16_vdp(u32 a, u32 d) { - if ((a & 0x00f9) == 0x0010) { // PSG Sound - if (PicoOpt & POPT_EN_PSG) - SN76496Write(d); - return; - } + if ((a & 0x00f9) == 0x0010) // PSG Sound + psg_write_68k(d); if ((a & 0x00e0) == 0x0000) { PicoVideoWrite(a, d); return; @@ -714,7 +765,7 @@ static void m68k_mem_setup(void); PICO_INTERNAL void PicoMemSetup(void) { - int mask, rs, a; + int mask, rs, sstart, a; // setup the memory map cpu68k_map_set(m68k_read8_map, 0x000000, 0xffffff, m68k_unmapped_read8, 1); @@ -730,15 +781,16 @@ PICO_INTERNAL void PicoMemSetup(void) cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0); // Common case of on-cart (save) RAM, usually at 0x200000-... - if ((SRam.flags & SRF_ENABLED) && SRam.data != NULL) { - rs = SRam.end - SRam.start; + if ((Pico.sv.flags & SRF_ENABLED) && Pico.sv.data != NULL) { + sstart = Pico.sv.start; + rs = Pico.sv.end - sstart; rs = (rs + mask) & ~mask; - if (SRam.start + rs >= 0x1000000) - rs = 0x1000000 - SRam.start; - cpu68k_map_set(m68k_read8_map, SRam.start, SRam.start + rs - 1, PicoRead8_sram, 1); - cpu68k_map_set(m68k_read16_map, SRam.start, SRam.start + rs - 1, PicoRead16_sram, 1); - cpu68k_map_set(m68k_write8_map, SRam.start, SRam.start + rs - 1, PicoWrite8_sram, 1); - cpu68k_map_set(m68k_write16_map, SRam.start, SRam.start + rs - 1, PicoWrite16_sram, 1); + if (sstart + rs >= 0x1000000) + rs = 0x1000000 - sstart; + cpu68k_map_set(m68k_read8_map, sstart, sstart + rs - 1, PicoRead8_sram, 1); + cpu68k_map_set(m68k_read16_map, sstart, sstart + rs - 1, PicoRead16_sram, 1); + cpu68k_map_set(m68k_write8_map, sstart, sstart + rs - 1, PicoWrite8_sram, 1); + cpu68k_map_set(m68k_write16_map, sstart, sstart + rs - 1, PicoWrite16_sram, 1); } // Z80 region @@ -765,10 +817,10 @@ PICO_INTERNAL void PicoMemSetup(void) // RAM and it's mirrors for (a = 0xe00000; a < 0x1000000; a += 0x010000) { - cpu68k_map_set(m68k_read8_map, a, a + 0xffff, Pico.ram, 0); - cpu68k_map_set(m68k_read16_map, a, a + 0xffff, Pico.ram, 0); - cpu68k_map_set(m68k_write8_map, a, a + 0xffff, Pico.ram, 0); - cpu68k_map_set(m68k_write16_map, a, a + 0xffff, Pico.ram, 0); + cpu68k_map_set(m68k_read8_map, a, a + 0xffff, PicoMem.ram, 0); + cpu68k_map_set(m68k_read16_map, a, a + 0xffff, PicoMem.ram, 0); + cpu68k_map_set(m68k_write8_map, a, a + 0xffff, PicoMem.ram, 0); + cpu68k_map_set(m68k_write16_map, a, a + 0xffff, PicoMem.ram, 0); } // Setup memory callbacks: @@ -796,14 +848,12 @@ PICO_INTERNAL void PicoMemSetup(void) { int i; // by default, point everything to first 64k of ROM - for (i = 0; i < M68K_FETCHBANK1; i++) + for (i = 0; i < M68K_FETCHBANK1 * 0xe0 / 0x100; i++) PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom - (i<<(24-FAMEC_FETCHBITS)); // now real ROM for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < Pico.romsize; i++) PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom; - // .. and RAM - for (i = M68K_FETCHBANK1*14/16; i < M68K_FETCHBANK1; i++) - PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.ram - (i<<(24-FAMEC_FETCHBITS)); + // RAM already set } #endif #ifdef EMU_M68K @@ -846,10 +896,11 @@ static void m68k_mem_setup(void) static int get_scanline(int is_from_z80) { if (is_from_z80) { - int cycles = z80_cyclesDone(); - while (cycles - z80_scanline_cycles >= 228) - z80_scanline++, z80_scanline_cycles += 228; - return z80_scanline; + int mclk_z80 = z80_cyclesDone() * 15; + int mclk_line = Pico.t.z80_scanline * 488 * 7; + while (mclk_z80 - mclk_line >= 488 * 7) + Pico.t.z80_scanline++, mclk_line += 488 * 7; + return Pico.t.z80_scanline; } return Pico.m.scanline; @@ -909,7 +960,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) int scanline = get_scanline(is_from_z80); //elprintf(EL_STATUS, "%03i -> %03i dac w %08x z80 %i", PsndDacLine, scanline, d, is_from_z80); ym2612.dacout = ((int)d - 0x80) << 6; - if (PsndOut && ym2612.dacen && scanline >= PsndDacLine) + if (ym2612.dacen) PsndDoDAC(scanline); return 0; } @@ -993,8 +1044,10 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80) } case 0x2b: { /* DAC Sel (YM2612) */ int scanline = get_scanline(is_from_z80); - ym2612.dacen = d & 0x80; - if (d & 0x80) PsndDacLine = scanline; + if (ym2612.dacen != (d & 0x80)) { + ym2612.dacen = d & 0x80; + PsndDacLine = scanline; + } #ifdef __GP2X__ if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, scanline); #endif @@ -1142,7 +1195,22 @@ void PicoWrite16_32x(u32 a, u32 d) {} static unsigned char z80_md_vdp_read(unsigned short a) { - // TODO? + z80_subCLeft(2); + + if ((a & 0x00f0) == 0x0000) { + switch (a & 0x0d) + { + case 0x00: return PicoVideoRead8DataH(); + case 0x01: return PicoVideoRead8DataL(); + case 0x04: return PicoVideoRead8CtlH(); + case 0x05: return PicoVideoRead8CtlL(); + case 0x08: + case 0x0c: return get_scanline(1); // FIXME: make it proper + case 0x09: + case 0x0d: return Pico.m.rotate++; + } + } + elprintf(EL_ANOMALY, "z80 invalid r8 [%06x] %02x", a, 0xff); return 0xff; } @@ -1152,8 +1220,10 @@ static unsigned char z80_md_bank_read(unsigned short a) unsigned int addr68k; unsigned char ret; - addr68k = Pico.m.z80_bank68k<<15; - addr68k += a & 0x7fff; + z80_subCLeft(3); + + addr68k = Pico.m.z80_bank68k << 15; + addr68k |= a & 0x7fff; ret = m68k_read8(addr68k); @@ -1169,13 +1239,12 @@ static void z80_md_ym2612_write(unsigned int a, unsigned char data) static void z80_md_vdp_br_write(unsigned int a, unsigned char data) { - // TODO: allow full VDP access if ((a&0xfff9) == 0x7f11) // 7f11 7f13 7f15 7f17 { - if (PicoOpt & POPT_EN_PSG) - SN76496Write(data); + psg_write_z80(data); return; } + // at least VDP data writes hang my machine if ((a>>8) == 0x60) { @@ -1214,14 +1283,14 @@ static void z80_md_out(unsigned short p, unsigned char d) static void z80_mem_setup(void) { - z80_map_set(z80_read_map, 0x0000, 0x1fff, Pico.zram, 0); - z80_map_set(z80_read_map, 0x2000, 0x3fff, Pico.zram, 0); + z80_map_set(z80_read_map, 0x0000, 0x1fff, PicoMem.zram, 0); + z80_map_set(z80_read_map, 0x2000, 0x3fff, PicoMem.zram, 0); z80_map_set(z80_read_map, 0x4000, 0x5fff, ym2612_read_local_z80, 1); z80_map_set(z80_read_map, 0x6000, 0x7fff, z80_md_vdp_read, 1); z80_map_set(z80_read_map, 0x8000, 0xffff, z80_md_bank_read, 1); - z80_map_set(z80_write_map, 0x0000, 0x1fff, Pico.zram, 0); - z80_map_set(z80_write_map, 0x2000, 0x3fff, Pico.zram, 0); + z80_map_set(z80_write_map, 0x0000, 0x1fff, PicoMem.zram, 0); + z80_map_set(z80_write_map, 0x2000, 0x3fff, PicoMem.zram, 0); z80_map_set(z80_write_map, 0x4000, 0x5fff, z80_md_ym2612_write, 1); z80_map_set(z80_write_map, 0x6000, 0x7fff, z80_md_vdp_br_write, 1); z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write, 1); @@ -1231,8 +1300,8 @@ static void z80_mem_setup(void) drZ80.z80_out = z80_md_out; #endif #ifdef _USE_CZ80 - Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (FPTR)Pico.zram); // main RAM - Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (FPTR)Pico.zram); // mirror + Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (FPTR)PicoMem.zram); // main RAM + Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (FPTR)PicoMem.zram); // mirror Cz80_Set_INPort(&CZ80, z80_md_in); Cz80_Set_OUTPort(&CZ80, z80_md_out); #endif diff --git a/pico/memory.h b/pico/memory.h index afca082..ae7ae50 100644 --- a/pico/memory.h +++ b/pico/memory.h @@ -133,6 +133,25 @@ void name(u32 a, u32 d) \ } \ } +#ifdef NEED_DMA_SOURCE // meh + +static __inline void *m68k_dma_source(u32 a) +{ + u8 *base; + uptr v; + v = m68k_read16_map[a >> M68K_MEM_SHIFT]; + if (map_flag_set(v)) { + if (a >= Pico.romsize) // Rom + return NULL; + base = Pico.rom; + } + else + base = (void *)(v << 1); + return base + (a & 0xfe0000); +} + +#endif + // 32x typedef struct { uptr addr; // stores (membase >> 1) or ((handler >> 1) | (1<<31)) diff --git a/pico/memory_amips.s b/pico/memory_amips.S similarity index 93% rename from pico/memory_amips.s rename to pico/memory_amips.S index 4f09198..7ae2592 100644 --- a/pico/memory_amips.s +++ b/pico/memory_amips.S @@ -8,6 +8,8 @@ # OUT OF DATE +#include "pico_int_o32.h" + .set noreorder .set noat @@ -184,8 +186,8 @@ m_read32_table: PicoMemReset: - lui $v1, %hi(Pico+0x22204) - lw $v1, %lo(Pico+0x22204)($v1) # romsize + lui $v1, %hi(Pico+OFS_Pico_romsize) + lw $v1, %lo(Pico+OFS_Pico_romsize)($v1) # romsize lui $t0, 8 addu $v1, $t0 addiu $v1, -1 @@ -235,12 +237,11 @@ m_read_neg1: jr $ra addiu $v0, $0, 0xffff -# loads &Pico.rom to $t3 +# loads &Pico to $t3 .macro m_read_rom_try_sram is200000 size - lui $t2, %hi(SRam) - addiu $t2, %lo(SRam) - lui $t3, %hi(Pico+0x22200) - lw $t1, 8($t2) # SRam.end + lui $t2, %hi(Pico) + addiu $t2, %lo(Pico) + lw $t1, OFS_Pico_sv_end($t2) .if \is200000 ins $a0, $0, 19, 13 lui $t4, 0x20 @@ -248,12 +249,11 @@ m_read_neg1: .endif subu $t4, $a0, $t1 bgtz $t4, 1f - addiu $t3, %lo(Pico+0x22200) - lw $t1, 4($t2) # SRam.start + lw $t1, OFS_Pico_sv_start($t2) subu $t4, $t1, $a0 bgtz $t4, 1f nop - lb $t1, 0x11($t3) # Pico.m.sram_reg + lb $t1, OFS_Pico_m_sram_reg($t2) andi $t4, $t1, 5 beqz $t4, 1f nop @@ -288,8 +288,8 @@ m_read_neg1: .endm .macro m_read8_rom sect - lui $t0, %hi(Pico+0x22200) - lw $t0, %lo(Pico+0x22200)($t0) # rom + lui $t0, %hi(Pico+OFS_Pico_rom) + lw $t0, %lo(Pico+OFS_Pico_rom)($t0) # rom xori $a0, 1 ins $a0, $0, 19, 13 .if \sect @@ -388,15 +388,15 @@ m_read8_misc_io: nop m_read8_misc_hwreg: - lui $v0, %hi(Pico+0x2220f) + lui $v0, %hi(Pico+OFS_Pico_m_hardware) jr $ra - lb $v0, %lo(Pico+0x2220f)($v0) + lb $v0, %lo(Pico+OFS_Pico_m_hardware)($v0) m_read8_misc_ioports: - lui $v0, %hi(Pico+0x22000) + lui $v0, %hi(PicoMem+0x22000) ins $v0, $t0, 0, 5 jr $ra - lb $v0, %lo(Pico+0x22000)($v0) + lb $v0, %lo(PicoMem+0x22000)($v0) m_read8_misc2: lui $t0, 0xa1 @@ -423,10 +423,10 @@ m_read8_z80_misc: nop m_read8_fake_ym2612: - lb $v0, %lo(Pico+0x22208)($t0) # Pico.m.rotate + lb $v0, %lo(Pico+OFS_Pico_m_rotate)($t0) addiu $t1, $v0, 1 jr $ra - sb $t1, %lo(Pico+0x22208)($t0) + sb $t1, %lo(Pico+OFS_Pico_m_rotate)($t0) # delay slot friendly .macro m_read8_call16 funcname is_func_ptr=0 @@ -468,15 +468,15 @@ m_read8_vdp: or $t0, $t1 bnez $t0, m_read_null # invalid address nop - j PicoVideoRead8 + j PicoRead8_vdp nop m_read8_ram: - lui $t0, %hi(Pico) + lui $t0, %hi(PicoMem) ins $t0, $a0, 0, 16 xori $t0, 1 jr $ra - lb $v0, %lo(Pico)($t0) + lb $v0, %lo(PicoMem)($t0) m_read8_above_rom: # might still be SRam (Micro Machines, HardBall '95) @@ -486,8 +486,8 @@ m_read8_above_rom: # ############################################################################# .macro m_read16_rom sect - lui $t0, %hi(Pico+0x22200) - lw $t0, %lo(Pico+0x22200)($t0) # rom + lui $t0, %hi(Pico+OFS_Pico_rom) + lw $t0, %lo(Pico+OFS_Pico_rom)($t0) # rom ins $a0, $0, 0, 1 ins $a0, $0, 19, 13 .if \sect @@ -583,11 +583,11 @@ m_read16_vdp: nop m_read16_ram: - lui $t0, %hi(Pico) + lui $t0, %hi(PicoMem) ins $a0, $0, 0, 1 ins $t0, $a0, 0, 16 jr $ra - lh $v0, %lo(Pico)($t0) + lh $v0, %lo(PicoMem)($t0) m_read16_above_rom: # might still be SRam @@ -600,8 +600,8 @@ m_read16_above_rom: # ############################################################################# .macro m_read32_rom sect - lui $t0, %hi(Pico+0x22200) - lw $t0, %lo(Pico+0x22200)($t0) # rom + lui $t0, %hi(Pico+OFS_Pico_rom) + lw $t0, %lo(Pico+OFS_Pico_rom)($t0) # rom ins $a0, $0, 0, 1 ins $a0, $0, 19, 13 .if \sect @@ -723,11 +723,11 @@ m_read32_vdp: m_read32_call16 PicoVideoRead m_read32_ram: - lui $t0, %hi(Pico) + lui $t0, %hi(PicoMem) ins $a0, $0, 0, 1 ins $t0, $a0, 0, 16 - lh $v1, %lo(Pico)($t0) - lh $v0, %lo(Pico+2)($t0) + lh $v1, %lo(PicoMem)($t0) + lh $v0, %lo(PicoMem+2)($t0) jr $ra ins $v0, $v1, 16, 16 @@ -771,11 +771,11 @@ PicoWriteRomHW_SSF2: # u32 a, u32 d bnez $a0, pwr_banking # sram register - lui $t0, %hi(Pico+0x22211) - lb $t1, %lo(Pico+0x22211)($t0) # Pico.m.sram_reg + lui $t0, %hi(Pico+OFS_Pico_m_sram_reg) + lb $t1, %lo(Pico+OFS_Pico_m_sram_reg)($t0) # Pico.m.sram_reg ins $t1, $a1, 0, 2 jr $ra - sb $t1, %lo(Pico+0x22211)($t0) + sb $t1, %lo(Pico+OFS_Pico_m_sram_reg)($t0) pwr_banking: andi $a1, 0x1f diff --git a/pico/memory_arm.s b/pico/memory_arm.S similarity index 73% rename from pico/memory_arm.s rename to pico/memory_arm.S index f6d7f79..87846d6 100644 --- a/pico/memory_arm.s +++ b/pico/memory_arm.S @@ -6,6 +6,8 @@ * See COPYING file in the top-level directory. */ +#include "pico_int_o32.h" + .equ SRR_MAPPED, (1 << 0) .equ SRR_READONLY, (1 << 1) .equ SRF_EEPROM, (1 << 1) @@ -21,35 +23,32 @@ .global PicoWrite8_io .global PicoWrite16_io -PicoRead8_sram: @ u32 a, u32 d - ldr r2, =(SRam) - ldr r3, =(Pico+0x22200) - ldr r1, [r2, #8] @ SRam.end +PicoRead8_sram: @ u32 a + ldr r3, =Pico + ldr r1, [r3, #OFS_Pico_sv_end] cmp r0, r1 bgt m_read8_nosram - ldr r1, [r2, #4] @ SRam.start - cmp r0, r1 + ldr r2, [r3, #OFS_Pico_sv_start] + cmp r0, r2 blt m_read8_nosram - ldrb r1, [r3, #0x11] @ Pico.m.sram_reg + ldrb r1, [r3, #OFS_Pico_m_sram_reg] tst r1, #SRR_MAPPED beq m_read8_nosram - ldr r1, [r2, #0x0c] + ldr r1, [r3, #OFS_Pico_sv_flags] tst r1, #SRF_EEPROM bne m_read8_eeprom - ldr r1, [r2, #4] @ SRam.start - ldr r2, [r2] @ SRam.data - sub r0, r0, r1 - add r0, r0, r2 - ldrb r0, [r0] + ldr r1, [r3, #OFS_Pico_sv_data] + sub r0, r0, r2 + ldrb r0, [r0, r1] bx lr m_read8_nosram: - ldr r1, [r3, #4] @ romsize + ldr r1, [r3, #OFS_Pico_romsize] cmp r0, r1 movgt r0, #0 bxgt lr @ bad location @ XXX: banking unfriendly - ldr r1, [r3] + ldr r1, [r3, #OFS_Pico_rom] eor r0, r0, #1 ldrb r0, [r1, r0] bx lr @@ -63,7 +62,7 @@ m_read8_eeprom: bx lr -PicoRead8_io: @ u32 a, u32 d +PicoRead8_io: @ u32 a bic r2, r0, #0x001f @ most commonly we get i/o port read, cmp r2, #0xa10000 @ so check for it first beq io_ports_read @@ -73,11 +72,11 @@ m_read8_not_io: cmp r2, #0x1000 bne m_read8_not_brq - ldr r3, =(Pico+0x22200) + ldr r3, =Pico mov r1, r0 - ldr r0, [r3, #8] @ Pico.m.rotate + ldr r0, [r3, #OFS_Pico_m_rotate] add r0, r0, #1 - strb r0, [r3, #8] + strb r0, [r3, #OFS_Pico_m_rotate] eor r0, r0, r0, lsl #6 tst r1, #1 @@ -87,8 +86,8 @@ m_read8_not_io: cmp r2, #0x1100 bxne lr @ not busreq - ldrb r1, [r3, #(8+0x01)] @ Pico.m.z80Run - ldrb r2, [r3, #(8+0x0f)] @ Pico.m.z80_reset + ldrb r1, [r3, #OFS_Pico_m_z80Run] + ldrb r2, [r3, #OFS_Pico_m_z80_reset] orr r0, r0, r1 orr r0, r0, r2 bx lr @@ -104,36 +103,33 @@ m_read8_not_brq: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PicoRead16_sram: @ u32 a, u32 d - ldr r2, =(SRam) - ldr r3, =(Pico+0x22200) - ldr r1, [r2, #8] @ SRam.end + ldr r3, =Pico + ldr r1, [r3, #OFS_Pico_sv_end] cmp r0, r1 bgt m_read16_nosram - ldr r1, [r2, #4] @ SRam.start - cmp r0, r1 + ldr r2, [r3, #OFS_Pico_sv_start] + cmp r0, r2 blt m_read16_nosram - ldrb r1, [r3, #0x11] @ Pico.m.sram_reg + ldrb r1, [r3, #OFS_Pico_m_sram_reg] tst r1, #SRR_MAPPED beq m_read16_nosram - ldr r1, [r2, #0x0c] + ldr r1, [r3, #OFS_Pico_sv_flags] tst r1, #SRF_EEPROM bne EEPROM_read - ldr r1, [r2, #4] @ SRam.start - ldr r2, [r2] @ SRam.data - sub r0, r0, r1 - add r0, r0, r2 - ldrb r1, [r0], #1 - ldrb r0, [r0] + ldr r1, [r3, #OFS_Pico_sv_data] + sub r0, r0, r2 + ldrb r1, [r0, r1]! + ldrb r0, [r0, #1] orr r0, r0, r1, lsl #8 bx lr m_read16_nosram: - ldr r1, [r3, #4] @ romsize + ldr r1, [r3, #OFS_Pico_romsize] cmp r0, r1 movgt r0, #0 bxgt lr @ bad location @ XXX: banking unfriendly - ldr r1, [r3] + ldr r1, [r3, #OFS_Pico_rom] ldrh r0, [r1, r0] bx lr @@ -152,19 +148,19 @@ m_read16_not_io: cmp r2, #0x1000 bne m_read16_not_brq - ldr r3, =(Pico+0x22200) + ldr r3, =Pico and r2, r0, #0xff00 - ldr r0, [r3, #8] @ Pico.m.rotate + ldr r0, [r3, #OFS_Pico_m_rotate] add r0, r0, #1 - strb r0, [r3, #8] + strb r0, [r3, #OFS_Pico_m_rotate] eor r0, r0, r0, lsl #5 eor r0, r0, r0, lsl #8 bic r0, r0, #0x100 @ bit8 defined in this area cmp r2, #0x1100 bxne lr @ not busreq - ldrb r1, [r3, #(8+0x01)] @ Pico.m.z80Run - ldrb r2, [r3, #(8+0x0f)] @ Pico.m.z80_reset + ldrb r1, [r3, #OFS_Pico_m_z80Run] + ldrb r2, [r3, #OFS_Pico_m_z80_reset] orr r0, r0, r1, lsl #8 orr r0, r0, r2, lsl #8 bx lr @@ -202,12 +198,12 @@ m_write8_not_z80ctl: eor r2, r2, #0x003000 eors r2, r2, #0x0000f1 bne m_write8_not_sreg - ldr r3, =(Pico+0x22200) - ldrb r2, [r3, #(8+9)] @ Pico.m.sram_reg + ldr r3, =Pico + ldrb r2, [r3, #OFS_Pico_m_sram_reg] and r1, r1, #(SRR_MAPPED|SRR_READONLY) bic r2, r2, #(SRR_MAPPED|SRR_READONLY) orr r2, r2, r1 - strb r2, [r3, #(8+9)] + strb r2, [r3, #OFS_Pico_m_sram_reg] bx lr m_write8_not_sreg: @@ -239,12 +235,12 @@ m_write16_not_z80ctl: eor r2, r2, #0x003000 eors r2, r2, #0x0000f0 bne m_write16_not_sreg - ldr r3, =(Pico+0x22200) - ldrb r2, [r3, #(8+9)] @ Pico.m.sram_reg + ldr r3, =Pico + ldrb r2, [r3, #OFS_Pico_m_sram_reg] and r1, r1, #(SRR_MAPPED|SRR_READONLY) bic r2, r2, #(SRR_MAPPED|SRR_READONLY) orr r2, r2, r1 - strb r2, [r3, #(8+9)] + strb r2, [r3, #OFS_Pico_m_sram_reg] bx lr m_write16_not_sreg: diff --git a/pico/misc.c b/pico/misc.c index ba24f95..47842e3 100644 --- a/pico/misc.c +++ b/pico/misc.c @@ -87,35 +87,6 @@ const unsigned char hcounts_32[] = { #ifndef _ASM_MISC_C -typedef struct -{ - int b0; - int b1; - int b2; - int b3; - int b4; - int b5; - int b6; - int b7; -} intblock; - -PICO_INTERNAL_ASM void pmemcpy16(unsigned short *dest, unsigned short *src, int count) -{ - if ((((long)dest | (long)src) & 3) == 0) - { - if (count >= 32) { - memcpy32((int *)dest, (int *)src, count/2); - count&=1; - } else { - for (; count >= 2; count -= 2, dest+=2, src+=2) - *(int *)dest = *(int *)src; - } - } - while (count--) - *dest++ = *src++; -} - - PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count) { unsigned char *src_ = src; @@ -125,21 +96,10 @@ PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count) } #ifndef _ASM_MISC_C_AMIPS -PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count) +PICO_INTERNAL_ASM void memset32(void *dest_in, int c, int count) { - intblock *bd = (intblock *) dest, *bs = (intblock *) src; + int *dest = dest_in; - for (; count >= sizeof(*bd)/4; count -= sizeof(*bd)/4) - *bd++ = *bs++; - - dest = (int *)bd; src = (int *)bs; - while (count--) - *dest++ = *src++; -} - - -PICO_INTERNAL_ASM void memset32(int *dest, int c, int count) -{ for (; count >= 8; count -= 8, dest += 8) dest[0] = dest[1] = dest[2] = dest[3] = dest[4] = dest[5] = dest[6] = dest[7] = c; diff --git a/pico/misc_amips.s b/pico/misc_amips.s index 3aa70c7..7c3f1ad 100644 --- a/pico/misc_amips.s +++ b/pico/misc_amips.s @@ -101,78 +101,4 @@ ms32u_return: nop -.globl memcpy32 # int *dest, int *src, int count - -memcpy32: -mc32_aloop: - andi $t0, $a0, 0x3f - beqz $t0, mc32_bloop_prep - nop - lw $t1, 0($a1) - addiu $a2, -1 - sw $t1, 0($a0) - beqz $a2, mc32_return - addiu $a0, 4 - j mc32_aloop - addiu $a1, 4 - -mc32_bloop_prep: - srl $t0, $a2, 4 # we will do 64 bytes per iteration (cache line) - beqz $t0, mc32_bloop_end - -mc32_bloop: - addiu $t0, -1 - cache 0x18, ($a0) # create dirty exclusive - lw $t2, 0x00($a1) - lw $t3, 0x04($a1) - lw $t4, 0x08($a1) - lw $t5, 0x0c($a1) - lw $t6, 0x10($a1) - lw $t7, 0x14($a1) - lw $t8, 0x18($a1) - lw $t9, 0x1c($a1) - sw $t2, 0x00($a0) - sw $t3, 0x04($a0) - sw $t4, 0x08($a0) - sw $t5, 0x0c($a0) - sw $t6, 0x10($a0) - sw $t7, 0x14($a0) - sw $t8, 0x18($a0) - sw $t9, 0x1c($a0) - lw $t2, 0x20($a1) - lw $t3, 0x24($a1) - lw $t4, 0x28($a1) - lw $t5, 0x2c($a1) - lw $t6, 0x30($a1) - lw $t7, 0x34($a1) - lw $t8, 0x38($a1) - lw $t9, 0x3c($a1) - sw $t2, 0x20($a0) - sw $t3, 0x24($a0) - sw $t4, 0x28($a0) - sw $t5, 0x2c($a0) - sw $t6, 0x30($a0) - sw $t7, 0x34($a0) - sw $t8, 0x38($a0) - sw $t9, 0x3c($a0) - addiu $a0, 0x40 - bnez $t0, mc32_bloop - addiu $a1, 0x40 - -mc32_bloop_end: - andi $a2, $a2, 0x0f - beqz $a2, mc32_return - -mc32_cloop: - lw $t1, 0($a1) - addiu $a2, -1 - addiu $a1, 4 - sw $t1, 0($a0) - bnez $a2, mc32_cloop - addiu $a0, 4 - -mc32_return: - jr $ra - nop - # vim:filetype=mips diff --git a/pico/misc_arm.s b/pico/misc_arm.s index 260094e..56c7401 100644 --- a/pico/misc_arm.s +++ b/pico/misc_arm.s @@ -6,44 +6,6 @@ * See COPYING file in the top-level directory. */ -.global pmemcpy16 @ unsigned short *dest, unsigned short *src, int count - -pmemcpy16: - eor r3, r0, r1 - tst r3, #2 - bne mcp16_cant_align - - tst r0, #2 - ldrneh r3, [r1], #2 - subne r2, r2, #1 - strneh r3, [r0], #2 - - subs r2, r2, #4 - bmi mcp16_fin - -mcp16_loop: - ldmia r1!, {r3,r12} - subs r2, r2, #4 - stmia r0!, {r3,r12} - bpl mcp16_loop - -mcp16_fin: - tst r2, #2 - ldrne r3, [r1], #4 - strne r3, [r0], #4 - ands r2, r2, #1 - bxeq lr - -mcp16_cant_align: - ldrh r3, [r1], #2 - subs r2, r2, #1 - strh r3, [r0], #2 - bne mcp16_cant_align - - bx lr - - - @ 0x12345678 -> 0x34127856 @ r4=temp, lr=0x00ff00ff .macro bswap reg @@ -52,7 +14,6 @@ mcp16_cant_align: orr \reg, \reg, r4, lsl #8 .endm - @ dest must be halfword aligned, src can be unaligned .global memcpy16bswap @ unsigned short *dest, void *src, int count @@ -121,37 +82,6 @@ mcp16bs_cant_align2: bx lr - -.global memcpy32 @ int *dest, int *src, int count - -memcpy32: - stmfd sp!, {r4,lr} - - subs r2, r2, #4 - bmi mcp32_fin - -mcp32_loop: - ldmia r1!, {r3,r4,r12,lr} - subs r2, r2, #4 - stmia r0!, {r3,r4,r12,lr} - bpl mcp32_loop - -mcp32_fin: - tst r2, #3 - ldmeqfd sp!, {r4,pc} - tst r2, #1 - ldrne r3, [r1], #4 - strne r3, [r0], #4 - -mcp32_no_unal1: - tst r2, #2 - ldmneia r1!, {r3,r12} - ldmfd sp!, {r4,lr} - stmneia r0!, {r3,r12} - bx lr - - - .global memset32 @ int *dest, int c, int count memset32: diff --git a/pico/mode4.c b/pico/mode4.c index 4abace6..0f3d766 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -31,7 +31,7 @@ static int TileNormM4(int sx, int addr, int pal) unsigned char *pd = Pico.est.HighCol + sx; unsigned int pack, t; - pack = *(unsigned int *)(Pico.vram + addr); /* Get 4 bitplanes / 8 pixels */ + pack = *(unsigned int *)(PicoMem.vram + addr); /* Get 4 bitplanes / 8 pixels */ if (pack) { PLANAR_PIXEL(0, 0) @@ -53,7 +53,7 @@ static int TileFlipM4(int sx,int addr,int pal) unsigned char *pd = Pico.est.HighCol + sx; unsigned int pack, t; - pack = *(unsigned int *)(Pico.vram + addr); /* Get 4 bitplanes / 8 pixels */ + pack = *(unsigned int *)(PicoMem.vram + addr); /* Get 4 bitplanes / 8 pixels */ if (pack) { PLANAR_PIXEL(0, 7) @@ -83,7 +83,7 @@ static void draw_sprites(int scanline) if (pv->reg[0] & 8) xoff = 0; - sat = (unsigned char *)Pico.vram + ((pv->reg[5] & 0x7e) << 7); + sat = (unsigned char *)PicoMem.vram + ((pv->reg[5] & 0x7e) << 7); if (pv->reg[1] & 2) { addr_mask = 0xfe; h = 16; } else { @@ -161,7 +161,7 @@ static void DrawDisplayM4(int scanline) line -= 224; // Find name table: - nametab = Pico.vram; + nametab = PicoMem.vram; nametab += (pv->reg[2] & 0x0e) << (10-1); nametab += (line>>3) << (6-1); @@ -179,15 +179,15 @@ static void DrawDisplayM4(int scanline) dx += cellskip << 3; // low priority tiles - if (PicoDrawMask & PDRAW_LAYERB_ON) + if (!(pv->debug_p & PVD_KILL_B)) draw_strip(nametab, dx, cells, tilex | 0x0000 | (ty << 16)); // sprites - if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) + if (!(pv->debug_p & PVD_KILL_S_LO)) draw_sprites(scanline); // high priority tiles (use virtual layer switch just for fun) - if (PicoDrawMask & PDRAW_LAYERA_ON) + if (!(pv->debug_p & PVD_KILL_A)) draw_strip(nametab, dx, cells, tilex | 0x1000 | (ty << 16)); if (pv->reg[0] & 0x20) @@ -248,7 +248,7 @@ void PicoLineMode4(int line) void PicoDoHighPal555M4(void) { - unsigned int *spal=(void *)Pico.cram; + unsigned int *spal=(void *)PicoMem.cram; unsigned int *dpal=(void *)Pico.est.HighPal; unsigned int t; int i; @@ -287,7 +287,7 @@ static void FinalizeLine8bitM4(int line) if (!(PicoOpt & POPT_DIS_32C_BORDER)) pd += 32; - memcpy32((int *)pd, (int *)(Pico.est.HighCol+8), 256/4); + memcpy(pd, Pico.est.HighCol + 8, 256); } void PicoDrawSetOutputMode4(pdso_t which) diff --git a/pico/patch.c b/pico/patch.c index d2bbec4..d534a2c 100644 --- a/pico/patch.c +++ b/pico/patch.c @@ -22,6 +22,7 @@ */ #include "pico_int.h" +#include "memory.h" #include "patch.h" struct patch @@ -173,8 +174,8 @@ void genie_decode_ms(const char *code, struct patch *result) /* Correct the address */ result->addr = ((result->addr >> 4) | (result->addr << 12 & 0xF000)) ^ 0xF000; /* Optional: 3 digits for comp */ - printf("CHEAT: code[8]==%c\n",code[8]); - if (code[7]=='-'){ + if (code[7]=='-') + { for(i=8;i<11;++i) { if (i==9) continue; /* 2nd character is ignored */ @@ -354,15 +355,6 @@ void decode(const char* code, struct patch* result) return; } - - -unsigned int PicoRead16(unsigned int a); -void PicoWrite16(unsigned int a, unsigned short d); -extern unsigned short m68k_read16(unsigned int a); -extern void m68k_write16(unsigned int a, unsigned short d); -extern char PicoRead8_z80(unsigned short a); -extern void PicoWrite8_z80(unsigned short a, char d); - void PicoPatchUnload(void) { if (PicoPatches != NULL) @@ -456,7 +448,7 @@ void PicoPatchPrepare(void) if(!(PicoAHW & PAHW_SMS)) PicoPatches[i].data_old = (unsigned short) m68k_read16(addr); else - PicoPatches[i].data_old = (unsigned char) PicoRead8_z80(addr); + ;// wrong: PicoPatches[i].data_old = (unsigned char) PicoRead8_z80(addr); } if (strstr(PicoPatches[i].name, "AUTO")) PicoPatches[i].active = 1; @@ -504,7 +496,7 @@ void PicoPatchApply(void) if (!(PicoAHW & PAHW_SMS)) m68k_write16(addr,PicoPatches[i].data); else - PicoWrite8_z80(addr,PicoPatches[i].data); + ;// wrong: PicoWrite8_z80(addr,PicoPatches[i].data); } else { @@ -513,10 +505,10 @@ void PicoPatchApply(void) if (PicoPatches[u].addr == addr) break; if (u == i) { - if (!(PicoAHW & PAHW_SMS)) - m68k_write16(PicoPatches[i].addr,PicoPatches[i].data_old); + if (!(PicoAHW & PAHW_SMS)) + m68k_write16(PicoPatches[i].addr,PicoPatches[i].data_old); else - PicoWrite8_z80(PicoPatches[i].addr,PicoPatches[i].data_old); + ;// wrong: PicoWrite8_z80(PicoPatches[i].addr,PicoPatches[i].data_old); } } } diff --git a/pico/pico.c b/pico/pico.c index 62994c1..bf9df26 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -11,19 +11,17 @@ #include "sound/ym2612.h" struct Pico Pico; +struct PicoMem PicoMem; int PicoOpt; -int PicoSkipFrame; // skip rendering frame? -int PicoPad[2]; // Joypads, format is MXYZ SACB RLDU -int PicoPadInt[2]; // internal copy -int PicoAHW; // active addon hardware: PAHW_* -int PicoQuirks; // game-specific quirks -int PicoRegionOverride; // override the region detection 0: Auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe -int PicoRegionFPSOverride; // override the refresh rate of the region 0: Auto, 1: NTSC, 2: PAL +int PicoSkipFrame; // skip rendering frame? +int PicoPad[2]; // Joypads, format is MXYZ SACB RLDU +int PicoPadInt[2]; // internal copy +int PicoAHW; // active addon hardware: PAHW_* +int PicoQuirks; // game-specific quirks +int PicoRegionOverride; // override the region detection 0: Auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe int PicoAutoRgnOrder; -struct PicoSRAM SRam; int emustatus; // rapid_ym2612, multi_ym_updates -int scanlines_total; void (*PicoWriteSound)(int len) = NULL; // called at the best time to send sound buffer (PsndOut) to hardware void (*PicoResetHook)(void) = NULL; @@ -34,11 +32,13 @@ void PicoInit(void) { // Blank space for state: memset(&Pico,0,sizeof(Pico)); + memset(&PicoMem,0,sizeof(PicoMem)); memset(&PicoPad,0,sizeof(PicoPad)); memset(&PicoPadInt,0,sizeof(PicoPadInt)); - Pico.est.Pico_video = &Pico.video; - Pico.est.Pico_vram = Pico.vram; + Pico.est.Pico = &Pico; + Pico.est.PicoMem_vram = PicoMem.vram; + Pico.est.PicoMem_cram = PicoMem.cram; Pico.est.PicoOpt = &PicoOpt; // Init CPUs: @@ -61,18 +61,19 @@ void PicoExit(void) PicoCartUnload(); z80_exit(); - if (SRam.data) - free(SRam.data); + free(Pico.sv.data); + Pico.sv.data = NULL; + Pico.sv.start = Pico.sv.end = 0; pevt_dump(); } void PicoPower(void) { Pico.m.frame_count = 0; - SekCycleCnt = SekCycleAim = 0; + Pico.t.m68c_cnt = Pico.t.m68c_aim = 0; // clear all memory of the emulated machine - memset(&Pico.ram,0,(unsigned char *)&Pico.rom - Pico.ram); + memset(&PicoMem,0,sizeof(PicoMem)); memset(&Pico.video,0,sizeof(Pico.video)); memset(&Pico.m,0,sizeof(Pico.m)); @@ -81,7 +82,7 @@ void PicoPower(void) z80_reset(); // my MD1 VA6 console has this in IO - Pico.ioports[1] = Pico.ioports[2] = Pico.ioports[3] = 0xff; + PicoMem.ioports[1] = PicoMem.ioports[2] = PicoMem.ioports[3] = 0xff; // default VDP register values (based on Fusion) Pico.video.reg[0] = Pico.video.reg[1] = 0x04; @@ -99,10 +100,6 @@ void PicoPower(void) PICO_INTERNAL void PicoDetectRegion(void) { - // PicoDetectRegion not ready yet - if (Pico.romsize <= 0) - return; - int support=0, hw=0, i; unsigned char pal=0; @@ -155,10 +152,6 @@ PICO_INTERNAL void PicoDetectRegion(void) else hw=0x80; // USA Pico.m.hardware=(unsigned char)(hw|0x20); // No disk attached - - if (PicoRegionFPSOverride > 0) - pal = PicoRegionFPSOverride - 1; // pal - 0: NTSC, 1: PAL | PicoRegionFPSOverride - 0: Auto, 1: NTSC, 2: PAL - Pico.m.pal=pal; } @@ -219,12 +212,12 @@ int PicoReset(void) // reset sram state; enable sram access by default if it doesn't overlap with ROM Pico.m.sram_reg = 0; - if ((SRam.flags & SRF_EEPROM) || Pico.romsize <= SRam.start) + if ((Pico.sv.flags & SRF_EEPROM) || Pico.romsize <= Pico.sv.start) Pico.m.sram_reg |= SRR_MAPPED; - if (SRam.flags & SRF_ENABLED) - elprintf(EL_STATUS, "sram: %06x - %06x; eeprom: %i", SRam.start, SRam.end, - !!(SRam.flags & SRF_EEPROM)); + if (Pico.sv.flags & SRF_ENABLED) + elprintf(EL_STATUS, "sram: %06x - %06x; eeprom: %i", Pico.sv.start, Pico.sv.end, + !!(Pico.sv.flags & SRF_EEPROM)); return 0; } @@ -232,40 +225,28 @@ int PicoReset(void) // flush config changes before emu loop starts void PicoLoopPrepare(void) { - if (PicoRegionFPSOverride) // PicoRegionFPSOverride is proprietary on PicoRegionOverride - { - // force setting possibly changed.. - Pico.m.pal = PicoRegionFPSOverride - 1; // Pico.m.pal - 0: NTSC, 1: PAL | PicoRegionFPSOverride - 0: Auto, 1: NTSC, 2: PAL - } - else if (PicoRegionOverride) - { + if (PicoRegionOverride) // force setting possibly changed.. Pico.m.pal = (PicoRegionOverride == 2 || PicoRegionOverride == 8) ? 1 : 0; - } - - // FIXME: PAL has 313 scanlines.. - scanlines_total = Pico.m.pal ? 312 : 262; Pico.m.dirtyPal = 1; rendstatus_old = -1; } - -// dma2vram settings are just hacks to unglitch Legend of Galahad (needs <= 104 to work) -// same for Outrunners (92-121, when active is set to 24) -// 96 is VR hack +// this table is wrong and should be removed +// keeping it for now to compensate wrong timing elswhere, mainly for Outrunners static const int dma_timings[] = { - 167, 167, 166, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy - 102, 205, 204, 102, // vblank: 40cell: - 16, 16, 15, 8, // active: 32cell: - 24, 18, 17, 9 // ... + 83, 166, 83, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy + 102, 204, 102, 102, // vblank: 40cell: + 8, 16, 8, 8, // active: 32cell: + 17, 18, 9, 9 // ... }; static const int dma_bsycles[] = { - (488<<8)/167, (488<<8)/167, (488<<8)/166, (488<<8)/83, - (488<<8)/102, (488<<8)/233, (488<<8)/204, (488<<8)/102, - (488<<8)/16, (488<<8)/16, (488<<8)/15, (488<<8)/8, - (488<<8)/24, (488<<8)/18, (488<<8)/17, (488<<8)/9 + (488<<8)/83, (488<<8)/166, (488<<8)/83, (488<<8)/83, + (488<<8)/102, (488<<8)/204, (488<<8)/102, (488<<8)/102, + (488<<8)/8, (488<<8)/16, (488<<8)/8, (488<<8)/8, + (488<<8)/9, (488<<8)/18, (488<<8)/9, (488<<8)/9 }; // grossly inaccurate.. FIXME FIXXXMEE @@ -292,38 +273,32 @@ PICO_INTERNAL int CheckDMA(void) Pico.m.dma_xfers -= xfers_can; } - elprintf(EL_VDPDMA, "~Dma %i op=%i can=%i burn=%i [%i]", Pico.m.dma_xfers, dma_op1, xfers_can, burn, SekCyclesDone()); - //dprintf("~aim: %i, cnt: %i", SekCycleAim, SekCycleCnt); + elprintf(EL_VDPDMA, "~Dma %i op=%i can=%i burn=%i [%u]", + Pico.m.dma_xfers, dma_op1, xfers_can, burn, SekCyclesDone()); + //dprintf("~aim: %i, cnt: %i", Pico.t.m68c_aim, Pico.t.m68c_cnt); return burn; } #include "pico_cmn.c" -unsigned int last_z80_sync; /* in 68k cycles */ -int z80_cycle_cnt; -int z80_cycle_aim; -int z80_scanline; -int z80_scanline_cycles; /* cycles done until z80_scanline */ - /* sync z80 to 68k */ PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done) { int m68k_cnt; int cnt; - m68k_cnt = m68k_cycles_done - last_z80_sync; - z80_cycle_aim += cycles_68k_to_z80(m68k_cnt); - cnt = z80_cycle_aim - z80_cycle_cnt; - last_z80_sync = m68k_cycles_done; + m68k_cnt = m68k_cycles_done - Pico.t.m68c_frame_start; + Pico.t.z80c_aim = cycles_68k_to_z80(m68k_cnt); + cnt = Pico.t.z80c_aim - Pico.t.z80c_cnt; pprof_start(z80); elprintf(EL_BUSREQ, "z80 sync %i (%u|%u -> %u|%u)", cnt, - z80_cycle_cnt, z80_cycle_cnt / 288, - z80_cycle_aim, z80_cycle_aim / 288); + Pico.t.z80c_cnt, Pico.t.z80c_cnt * 15 / 7 / 488, + Pico.t.z80c_aim, Pico.t.z80c_aim * 15 / 7 / 488); if (cnt > 0) - z80_cycle_cnt += z80_run(cnt); + Pico.t.z80c_cnt += z80_run(cnt); pprof_end(z80); } diff --git a/pico/pico.h b/pico/pico.h index d22babd..f1687f5 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -34,6 +34,9 @@ extern void cache_flush_d_inval_i(void *start_addr, void *end_addr); extern void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed); extern void *plat_mremap(void *ptr, size_t oldsize, size_t newsize); extern void plat_munmap(void *ptr, size_t size); + +// memory for the dynarec; plat_mem_get_for_drc() can just return NULL +extern void *plat_mem_get_for_drc(size_t size); extern int plat_mem_set_exec(void *ptr, size_t size); // this one should handle display mode changes @@ -81,10 +84,9 @@ extern int PicoAHW; // Pico active hw #define PQUIRK_FORCE_6BTN (1<<0) extern int PicoQuirks; -extern int PicoSkipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff -extern int PicoRegionOverride; // override the region detection 0: auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe -extern int PicoRegionFPSOverride; // override the refresh rate of the region 0: Auto, 1: NTSC, 2: PAL -extern int PicoAutoRgnOrder; // packed priority list of regions, for example 0x148 means this detection order: EUR, USA, JAP +extern int PicoSkipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff +extern int PicoRegionOverride; // override the region detection 0: auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe +extern int PicoAutoRgnOrder; // packed priority list of regions, for example 0x148 means this detection order: EUR, USA, JAP extern int PicoSVPCycles; void PicoInit(void); void PicoExit(void); @@ -172,18 +174,11 @@ typedef enum void PicoDrawSetOutFormat(pdso_t which, int use_32x_line_mode); void PicoDrawSetOutBuf(void *dest, int increment); void PicoDrawSetCallbacks(int (*begin)(unsigned int num), int (*end)(unsigned int num)); -extern unsigned char *HighCol; // utility #ifdef _ASM_DRAW_C void vidConvCpyRGB565(void *to, void *from, int pixels); #endif void PicoDoHighPal555(int sh, int line, struct PicoEState *est); -extern int PicoDrawMask; -#define PDRAW_LAYERB_ON (1<<2) -#define PDRAW_LAYERA_ON (1<<3) -#define PDRAW_SPRITES_LOW_ON (1<<4) -#define PDRAW_SPRITES_HI_ON (1<<7) -#define PDRAW_32X_ON (1<<8) // internals #define PDRAW_SPRITES_MOVED (1<<0) // (asm) #define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority diff --git a/pico/pico/pico_memory.c b/pico/pico/memory.c similarity index 100% rename from pico/pico/pico_memory.c rename to pico/pico/memory.c diff --git a/pico/pico/pico_pico.c b/pico/pico/pico.c similarity index 98% rename from pico/pico/pico_pico.c rename to pico/pico/pico.c index bff5a2a..d893f9d 100644 --- a/pico/pico/pico_pico.c +++ b/pico/pico/pico.c @@ -23,7 +23,7 @@ PICO_INTERNAL void PicoReratePico(void) { int rate = guessed_rates[PicoPicohw.r12 & 7]; if (Pico.m.pal) - fifo_bytes_line = (rate<<16)/50/312/2; + fifo_bytes_line = (rate<<16)/50/313/2; else fifo_bytes_line = (rate<<16)/60/262/2; PicoPicoPCMRerate(rate); } diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 70d7807..27a66cd 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -7,8 +7,7 @@ */ #define CYCLES_M68K_LINE 488 // suitable for both PAL/NTSC -#define CYCLES_M68K_VINT_LAG 68 -#define CYCLES_M68K_ASD 148 +#define CYCLES_M68K_VINT_LAG 112 // pad delay (for 6 button pads) #define PAD_DELAY() { \ @@ -22,24 +21,24 @@ SekRunM68k(m68k_cycles) #endif -// sync m68k to SekCycleAim +// sync m68k to Pico.t.m68c_aim static void SekSyncM68k(void) { int cyc_do; pprof_start(m68k); pevt_log_m68k_o(EVT_RUN_START); - while ((cyc_do = SekCycleAim - SekCycleCnt) > 0) { - SekCycleCnt += cyc_do; + while ((cyc_do = Pico.t.m68c_aim - Pico.t.m68c_cnt) > 0) { + Pico.t.m68c_cnt += cyc_do; #if defined(EMU_C68K) PicoCpuCM68k.cycles = cyc_do; CycloneRun(&PicoCpuCM68k); - SekCycleCnt -= PicoCpuCM68k.cycles; + Pico.t.m68c_cnt -= PicoCpuCM68k.cycles; #elif defined(EMU_M68K) - SekCycleCnt += m68k_execute(cyc_do) - cyc_do; + Pico.t.m68c_cnt += m68k_execute(cyc_do) - cyc_do; #elif defined(EMU_F68K) - SekCycleCnt += fm68k_emulate(cyc_do, 0) - cyc_do; + Pico.t.m68c_cnt += fm68k_emulate(cyc_do, 0) - cyc_do; #endif } @@ -50,21 +49,53 @@ static void SekSyncM68k(void) pprof_end(m68k); } -static INLINE void SekRunM68k(int cyc) +static __inline void SekRunM68k(int cyc) { - SekCycleAim += cyc; + Pico.t.m68c_aim += cyc; + cyc = Pico.t.m68c_aim - Pico.t.m68c_cnt; + if (cyc <= 0) + return; + Pico.t.m68c_cnt += cyc >> 6; // refresh slowdowns SekSyncM68k(); } +static void do_hint(struct PicoVideo *pv) +{ + pv->pending_ints |= 0x10; + if (pv->reg[0] & 0x10) { + elprintf(EL_INTS, "hint: @ %06x [%u]", SekPc, SekCyclesDone()); + SekInterrupt(4); + } +} + +static void do_timing_hacks_as(struct PicoVideo *pv, int vdp_slots) +{ + pv->lwrite_cnt += vdp_slots - Pico.m.dma_xfers * 2; // wrong *2 + if (pv->lwrite_cnt > vdp_slots) + pv->lwrite_cnt = vdp_slots; + else if (pv->lwrite_cnt < 0) + pv->lwrite_cnt = 0; + if (Pico.m.dma_xfers) + SekCyclesBurn(CheckDMA()); +} + +static void do_timing_hacks_vb(void) +{ + if (Pico.m.dma_xfers) + SekCyclesBurn(CheckDMA()); +} + static int PicoFrameHints(void) { - struct PicoVideo *pv=&Pico.video; - int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap; + struct PicoVideo *pv = &Pico.video; + int line_sample = Pico.m.pal ? 68 : 93; + int vdp_slots = (Pico.video.reg[12] & 1) ? 18 : 16; + int lines, y, lines_vis, skip; + int vcnt_wrap, vcnt_adj; unsigned int cycles; int hint; // Hint counter pevt_log_m68k_o(EVT_FRAME_START); - pv->v_counter = Pico.m.scanline = 0; if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled // draw a frame just after vblank in alternative render mode @@ -77,26 +108,17 @@ static int PicoFrameHints(void) } else skip=PicoSkipFrame; - if (Pico.m.pal) { - line_sample = 68; - if (pv->reg[1]&8) lines_vis = 240; - } else { - line_sample = 93; - } - + Pico.t.m68c_frame_start = Pico.t.m68c_aim; + pv->v_counter = Pico.m.scanline = 0; z80_resetCycles(); - PsndDacLine = 0; - emustatus &= ~1; - - pv->status&=~0x88; // clear V-Int, come out of vblank + PsndStartFrame(); - hint=pv->reg[10]; // Load H-Int counter - //dprintf("-hint: %i", hint); + // Load H-Int counter + hint = (pv->status & PVS_ACTIVE) ? pv->hint_cnt : pv->reg[10]; - // This is to make active scan longer (needed for Double Dragon 2, mainly) - CPUS_RUN(CYCLES_M68K_ASD); + pv->status |= PVS_ACTIVE; - for (y = 0; y < lines_vis; y++) + for (y = 0; ; y++) { pv->v_counter = Pico.m.scanline = y; if ((pv->reg[12]&6) == 6) { // interlace mode 2 @@ -105,24 +127,16 @@ static int PicoFrameHints(void) pv->v_counter &= 0xff; } - // VDP FIFO - pv->lwrite_cnt -= 12; - if (pv->lwrite_cnt <= 0) { - pv->lwrite_cnt=0; - Pico.video.status|=0x200; - } + if ((y == 224 && !(pv->reg[1] & 8)) || y == 240) + break; PAD_DELAY(); // H-Interrupts: - if (--hint < 0) // y <= lines_vis: Comix Zone, Golden Axe + if (--hint < 0) { - hint=pv->reg[10]; // Reload H-Int counter - pv->pending_ints|=0x10; - if (pv->reg[0]&0x10) { - elprintf(EL_INTS, "hint: @ %06x [%i]", SekPc, SekCyclesDone()); - SekInterrupt(4); - } + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); } // decide if we draw this line @@ -145,8 +159,6 @@ static int PicoFrameHints(void) if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) PicoSyncZ80(cycles); - if (ym2612.dacen && PsndDacLine <= y) - PsndDoDAC(y); #ifdef PICO_CD if (PicoAHW & PAHW_MCD) pcd_sync_s68k(cycles, 0); @@ -158,14 +170,18 @@ static int PicoFrameHints(void) } // Run scanline: - line_base_cycles = SekCyclesDone(); - if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); + Pico.t.m68c_line_start = Pico.t.m68c_aim; + do_timing_hacks_as(pv, vdp_slots); CPUS_RUN(CYCLES_M68K_LINE); if (PicoLineHook) PicoLineHook(); pevt_log_m68k_o(EVT_NEXT_LINE); } + lines_vis = (pv->reg[1] & 8) ? 240 : 224; + if (y == lines_vis) + pv->status &= ~PVS_ACTIVE; + if (!skip) { if (Pico.est.DrawScanline < y) @@ -175,40 +191,36 @@ static int PicoFrameHints(void) #endif } - // V-int line (224 or 240) - Pico.m.scanline = y; - pv->v_counter = 0xe0; // bad for 240 mode - if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1; - // VDP FIFO - pv->lwrite_cnt=0; - Pico.video.status|=0x200; + pv->lwrite_cnt = 0; + Pico.video.status |= SR_EMPT; memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt)); PAD_DELAY(); - // Last H-Int: + // Last H-Int (normally): if (--hint < 0) { - hint=pv->reg[10]; // Reload H-Int counter - pv->pending_ints|=0x10; - //printf("rhint: %i @ %06x [%i|%i]\n", hint, SekPc, y, SekCyclesDone()); - if (pv->reg[0]&0x10) SekInterrupt(4); + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); } - pv->status|=0x08; // go into vblank - pv->pending_ints|=0x20; + pv->status |= SR_VB | PVS_VB2; // go into vblank // the following SekRun is there for several reasons: // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga) // also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants) // also delay between last H-int and V-int (Golden Axe 3) - line_base_cycles = SekCyclesDone(); - if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); + Pico.t.m68c_line_start = Pico.t.m68c_aim; + do_timing_hacks_vb(); CPUS_RUN(CYCLES_M68K_VINT_LAG); - if (pv->reg[1]&0x20) { - elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCyclesDone()); + pv->status |= SR_F; + pv->pending_ints |= 0x20; + if (pv->reg[1] & 0x20) { + Pico.t.m68c_aim = Pico.t.m68c_cnt + 11; // HACK + SekSyncM68k(); + elprintf(EL_INTS, "vint: @ %06x [%u]", SekPc, SekCyclesDone()); SekInterrupt(6); } @@ -230,47 +242,83 @@ static int PicoFrameHints(void) // get samples from sound chips if (y == 224 && PsndOut) - { - if (ym2612.dacen && PsndDacLine <= y) - PsndDoDAC(y); PsndGetSamples(y); - } // Run scanline: - CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG - CYCLES_M68K_ASD); + CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG); if (PicoLineHook) PicoLineHook(); pevt_log_m68k_o(EVT_NEXT_LINE); - lines = scanlines_total; - vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens, TODO: verify + if (Pico.m.pal) { + lines = 313; + vcnt_wrap = 0x103; + vcnt_adj = 57; + } + else { + lines = 262; + vcnt_wrap = 0xEB; + vcnt_adj = 6; + } - for (y++; y < lines; y++) + for (y++; y < lines - 1; y++) { pv->v_counter = Pico.m.scanline = y; if (y >= vcnt_wrap) - pv->v_counter -= Pico.m.pal ? 56 : 6; + pv->v_counter -= vcnt_adj; if ((pv->reg[12]&6) == 6) pv->v_counter = (pv->v_counter << 1) | 1; pv->v_counter &= 0xff; PAD_DELAY(); + if ((pv->status & PVS_ACTIVE) && --hint < 0) + { + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); + } + // Run scanline: - line_base_cycles = SekCyclesDone(); - if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); + Pico.t.m68c_line_start = Pico.t.m68c_aim; + do_timing_hacks_vb(); CPUS_RUN(CYCLES_M68K_LINE); if (PicoLineHook) PicoLineHook(); pevt_log_m68k_o(EVT_NEXT_LINE); } + pv->status &= ~(SR_VB | PVS_VB2); + pv->status |= ((pv->reg[1] >> 3) ^ SR_VB) & SR_VB; // forced blanking + + // last scanline + Pico.m.scanline = y; + pv->v_counter = 0xff; + pv->lwrite_cnt = 0; + + PAD_DELAY(); + + if ((pv->status & PVS_ACTIVE) && --hint < 0) + { + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); + } + + // Run scanline: + Pico.t.m68c_line_start = Pico.t.m68c_aim; + do_timing_hacks_as(pv, vdp_slots); + CPUS_RUN(CYCLES_M68K_LINE); + + if (PicoLineHook) PicoLineHook(); + pevt_log_m68k_o(EVT_NEXT_LINE); + // sync cpus cycles = SekCyclesDone(); if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) PicoSyncZ80(cycles); - if (PsndOut && ym2612.dacen && PsndDacLine <= lines-1) - PsndDoDAC(lines-1); + if (PsndOut && ym2612.dacen && PsndDacLine < lines) + PsndDoDAC(lines - 1); + if (PsndOut && PsndPsgLine < lines) + PsndDoPSG(lines - 1); #ifdef PICO_CD if (PicoAHW & PAHW_MCD) @@ -281,6 +329,8 @@ static int PicoFrameHints(void) #endif timers_cycle(); + pv->hint_cnt = hint; + return 0; } diff --git a/pico/pico_int.h b/pico/pico_int.h index b562b2f..e3bf03a 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -13,6 +13,7 @@ #include #include #include +#include "pico_port.h" #include "pico.h" #include "carthw/carthw.h" @@ -32,11 +33,6 @@ extern "C" { #endif -#ifdef _MSC_VER -#define snprintf _snprintf -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#endif // ----------------------- 68000 CPU ----------------------- #ifdef EMU_C68K @@ -122,37 +118,25 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #define SekNotPolling PicoCpuMM68k.not_polling #define SekNotPollingS68k PicoCpuMS68k.not_polling -#define SekInterrupt(irq) { \ - void *oldcontext = m68ki_cpu_p; \ - m68k_set_context(&PicoCpuMM68k); \ - m68k_set_irq(irq); \ - m68k_set_context(oldcontext); \ -} -#define SekIrqLevel (PicoCpuMM68k.int_level >> 8) +// avoid m68k_set_irq() for delaying to work +#define SekInterrupt(irq) PicoCpuMM68k.int_level = (irq) << 8 +#define SekIrqLevel (PicoCpuMM68k.int_level >> 8) #endif #endif // EMU_M68K -// while running, cnt represents target of current timeslice -// while not in SekRun(), it's actual cycles done -// (but always use SekCyclesDone() if you need current position) -// cnt may change if timeslice is ended prematurely or extended, -// so we use SekCycleAim for the actual target -extern unsigned int SekCycleCnt; -extern unsigned int SekCycleAim; - // number of cycles done (can be checked anywhere) -#define SekCyclesDone() (SekCycleCnt - SekCyclesLeft) +#define SekCyclesDone() (Pico.t.m68c_cnt - SekCyclesLeft) // burn cycles while not in SekRun() and while in -#define SekCyclesBurn(c) SekCycleCnt += c +#define SekCyclesBurn(c) Pico.t.m68c_cnt += c #define SekCyclesBurnRun(c) { \ SekCyclesLeft -= c; \ } // note: sometimes may extend timeslice to delay an irq #define SekEndRun(after) { \ - SekCycleCnt -= SekCyclesLeft - (after); \ + Pico.t.m68c_cnt -= SekCyclesLeft - (after); \ SekCyclesLeft = after; \ } @@ -190,6 +174,7 @@ extern struct DrZ80 drZ80; #define z80_nmi() drZ80.Z80IF |= 8 #define z80_cyclesLeft drZ80.cycles +#define z80_subCLeft(c) drZ80.cycles -= c #define z80_pc() (drZ80.Z80PC - drZ80.Z80PC_BASE) #elif defined(_USE_CZ80) @@ -201,6 +186,7 @@ extern struct DrZ80 drZ80; #define z80_nmi() Cz80_Set_IRQ(&CZ80, IRQ_LINE_NMI, 0) #define z80_cyclesLeft (CZ80.ICount - CZ80.ExtraCycles) +#define z80_subCLeft(c) CZ80.ICount -= c #define z80_pc() Cz80_Get_Reg(&CZ80, CZ80_PC) #else @@ -214,20 +200,13 @@ extern struct DrZ80 drZ80; #define Z80_STATE_SIZE 0x60 -extern unsigned int last_z80_sync; -extern int z80_cycle_cnt; /* 'done' z80 cycles before z80_run() */ -extern int z80_cycle_aim; -extern int z80_scanline; -extern int z80_scanline_cycles; /* cycles done until z80_scanline */ - #define z80_resetCycles() \ - last_z80_sync = SekCyclesDone(); \ - z80_cycle_cnt = z80_cycle_aim = z80_scanline = z80_scanline_cycles = 0; + Pico.t.z80c_cnt = Pico.t.z80c_aim = Pico.t.z80_scanline = 0 #define z80_cyclesDone() \ - (z80_cycle_aim - z80_cyclesLeft) + (Pico.t.z80c_aim - z80_cyclesLeft) -#define cycles_68k_to_z80(x) ((x)*957 >> 11) +#define cycles_68k_to_z80(x) ((x) * 3823 >> 13) // ----------------------- SH2 CPU ----------------------- @@ -286,6 +265,31 @@ extern SH2 sh2s[2]; #define OSC_NTSC 53693100 #define OSC_PAL 53203424 +// PicoVideo.debug_p +#define PVD_KILL_A (1 << 0) +#define PVD_KILL_B (1 << 1) +#define PVD_KILL_S_LO (1 << 2) +#define PVD_KILL_S_HI (1 << 3) +#define PVD_KILL_32X (1 << 4) +#define PVD_FORCE_A (1 << 5) +#define PVD_FORCE_B (1 << 6) +#define PVD_FORCE_S (1 << 7) + +// PicoVideo.status, not part of real SR +#define SR_PAL (1 << 0) +#define SR_DMA (1 << 1) +#define SR_HB (1 << 2) +#define SR_VB (1 << 3) +#define SR_ODD (1 << 4) +#define SR_C (1 << 5) +#define SR_SOVR (1 << 6) +#define SR_F (1 << 7) +#define SR_FULL (1 << 8) +#define SR_EMPT (1 << 9) +// not part of real SR +#define PVS_ACTIVE (1 << 16) +#define PVS_VB2 (1 << 17) // ignores forced blanking + struct PicoVideo { unsigned char reg[0x20]; @@ -293,11 +297,15 @@ struct PicoVideo unsigned char pending; // 1 if waiting for second half of 32-bit command unsigned char type; // Command type (v/c/vsram read/write) unsigned short addr; // Read/Write address - int status; // Status bits + unsigned int status; // Status bits (SR) and extra flags unsigned char pending_ints; // pending interrupts: ??VH???? signed char lwrite_cnt; // VDP write count during active display line unsigned short v_counter; // V-counter - unsigned char pad[0x10]; + unsigned short debug; // raw debug register + unsigned char debug_p; // ... parsed: PVD_* + unsigned char addr_u; // bit16 of .addr + unsigned char hint_cnt; + unsigned char pad[0x0b]; }; struct PicoMisc @@ -341,15 +349,15 @@ struct PicoEState void *DrawLineDest; // draw destination unsigned char *HighCol; int *HighPreSpr; - void *Pico_video; - void *Pico_vram; + struct Pico *Pico; + void *PicoMem_vram; + void *PicoMem_cram; int *PicoOpt; unsigned char *Draw2FB; unsigned short HighPal[0x100]; }; -// some assembly stuff depend on these, do not touch! -struct Pico +struct PicoMem { unsigned char ram[0x10000]; // 0x00000 scratch ram union { // vram is byteswapped for easier reads when drawing @@ -358,17 +366,9 @@ struct Pico }; unsigned char zram[0x2000]; // 0x20000 Z80 ram unsigned char ioports[0x10]; // XXX: fix asm and mv - unsigned char pad[0xf0]; // unused - unsigned short cram[0x40]; // 0x22100 - unsigned short vsram[0x40]; // 0x22180 - - unsigned char *rom; // 0x22200 - unsigned int romsize; // 0x22204 (on 32bits) - - struct PicoMisc m; - struct PicoVideo video; - struct PicoMS ms; - struct PicoEState est; + unsigned short cram[0x40]; // 0x22010 + unsigned char pad[0x70]; // 0x22050 DrawStripVSRam reads 0 from here + unsigned short vsram[0x40]; // 0x22100 }; // sram @@ -378,7 +378,7 @@ struct Pico #define SRF_ENABLED (1 << 0) #define SRF_EEPROM (1 << 1) -struct PicoSRAM +struct PicoCartSave { unsigned char *data; // actual data unsigned int start; // start address in 68k address space @@ -394,6 +394,38 @@ struct PicoSRAM unsigned int size; }; +struct PicoTiming +{ + // while running, cnt represents target of current timeslice + // while not in SekRun(), it's actual cycles done + // (but always use SekCyclesDone() if you need current position) + // _cnt may change if timeslice is ended prematurely or extended, + // so we use _aim for the actual target + unsigned int m68c_cnt; + unsigned int m68c_aim; + unsigned int m68c_frame_start; // m68k cycles + unsigned int m68c_line_start; + + unsigned int z80c_cnt; // z80 cycles done (this frame) + unsigned int z80c_aim; + int z80_scanline; +}; + +// run tools/mkoffsets pico/pico_int_o32.h if you change these +// careful with savestate compat +struct Pico +{ + struct PicoVideo video; + struct PicoMisc m; + struct PicoTiming t; + struct PicoCartSave sv; + struct PicoEState est; + struct PicoMS ms; + + unsigned char *rom; + unsigned int romsize; +}; + // MCD #define PCM_MIXBUF_LEN ((12500000 / 384) / 50 + 1) @@ -672,10 +704,9 @@ void pcd_state_loaded_mem(void); // pico.c extern struct Pico Pico; -extern struct PicoSRAM SRam; +extern struct PicoMem PicoMem; extern int PicoPadInt[2]; extern int emustatus; -extern int scanlines_total; extern void (*PicoResetHook)(void); extern void (*PicoLineHook)(void); PICO_INTERNAL int CheckDMA(void); @@ -783,17 +814,19 @@ void ym2612_unpack_state(void); // videoport.c -extern int line_base_cycles; PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d); PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a); -PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a); -extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp); +unsigned char PicoVideoRead8DataH(void); +unsigned char PicoVideoRead8DataL(void); +unsigned char PicoVideoRead8CtlH(void); +unsigned char PicoVideoRead8CtlL(void); +unsigned char PicoVideoRead8HV_H(void); +unsigned char PicoVideoRead8HV_L(void); +extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, unsigned int *mask); // misc.c -PICO_INTERNAL_ASM void pmemcpy16(unsigned short *dest, unsigned short *src, int count); PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count); -PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count); // 32bit word count -PICO_INTERNAL_ASM void memset32(int *dest, int c, int count); +PICO_INTERNAL_ASM void memset32(void *dest, int c, int count); // eeprom.c void EEPROM_write8(unsigned int a, unsigned int d); @@ -813,11 +846,13 @@ PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m); // sound/sound.c PICO_INTERNAL void PsndReset(void); +PICO_INTERNAL void PsndStartFrame(void); PICO_INTERNAL void PsndDoDAC(int line_to); +PICO_INTERNAL void PsndDoPSG(int line_to); PICO_INTERNAL void PsndClear(void); PICO_INTERNAL void PsndGetSamples(int y); PICO_INTERNAL void PsndGetSamplesMS(void); -extern int PsndDacLine; +extern int PsndDacLine, PsndPsgLine; // sms.c #ifndef NO_SMS @@ -865,7 +900,7 @@ void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after); void p32x_schedule_hint(SH2 *sh2, int m68k_cycles); // 32x/memory.c -struct Pico32xMem *Pico32xMem; +extern struct Pico32xMem *Pico32xMem; unsigned int PicoRead8_32x(unsigned int a); unsigned int PicoRead16_32x(unsigned int a); void PicoWrite8_32x(unsigned int a, unsigned int d); @@ -929,7 +964,7 @@ void REGPARM(3) sh2_peripheral_write32(unsigned int a, unsigned int d, SH2 *sh2) #endif /* avoid dependency on newer glibc */ -static INLINE int isspace_(int c) +static __inline int isspace_(int c) { return (0x09 <= c && c <= 0x0d) || c == ' '; } @@ -1036,28 +1071,10 @@ void pevt_dump(void); #define pevt_dump() #endif -// misc -#ifdef _MSC_VER -#define cdprintf -#else -#define cdprintf(x...) -#endif - -#if defined(__GNUC__) && defined(__i386__) -#define REGPARM(x) __attribute__((regparm(x))) -#else -#define REGPARM(x) -#endif - -#ifdef __GNUC__ -#define NOINLINE __attribute__((noinline)) -#else -#define NOINLINE -#endif - #ifdef __cplusplus } // End of extern "C" #endif #endif // PICO_INTERNAL_INCLUDED +// vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/pico_int_o32.h b/pico/pico_int_o32.h index dc7aaa2..ca3004f 100644 --- a/pico/pico_int_o32.h +++ b/pico/pico_int_o32.h @@ -1,11 +1,28 @@ -/* autogenerated by ./tools/mkoffsets, do not edit */ -#define OFS_DrawScanline 0x00 -#define OFS_rendstatus 0x04 -#define OFS_DrawLineDest 0x08 -#define OFS_HighCol 0x0c -#define OFS_HighPreSpr 0x10 -#define OFS_Pico_video 0x14 -#define OFS_Pico_vram 0x18 -#define OFS_PicoOpt 0x1c -#define OFS_Draw2FB 0x20 -#define OFS_HighPal 0x24 +/* autogenerated by tools/mkoffsets, do not edit */ +#define OFS_Pico_video_reg 0x0000 +#define OFS_Pico_m_rotate 0x0040 +#define OFS_Pico_m_z80Run 0x0041 +#define OFS_Pico_m_dirtyPal 0x0046 +#define OFS_Pico_m_hardware 0x0047 +#define OFS_Pico_m_z80_reset 0x004f +#define OFS_Pico_m_sram_reg 0x0049 +#define OFS_Pico_sv 0x007c +#define OFS_Pico_sv_data 0x007c +#define OFS_Pico_sv_start 0x0080 +#define OFS_Pico_sv_end 0x0084 +#define OFS_Pico_sv_flags 0x0088 +#define OFS_Pico_rom 0x031c +#define OFS_Pico_romsize 0x0320 +#define OFS_EST_DrawScanline 0x00 +#define OFS_EST_rendstatus 0x04 +#define OFS_EST_DrawLineDest 0x08 +#define OFS_EST_HighCol 0x0c +#define OFS_EST_HighPreSpr 0x10 +#define OFS_EST_Pico 0x14 +#define OFS_EST_PicoMem_vram 0x18 +#define OFS_EST_PicoMem_cram 0x1c +#define OFS_EST_PicoOpt 0x20 +#define OFS_EST_Draw2FB 0x24 +#define OFS_EST_HighPal 0x28 +#define OFS_PMEM_vram 0x10000 +#define OFS_PMEM_vsram 0x22100 diff --git a/pico/pico_port.h b/pico/pico_port.h new file mode 100644 index 0000000..605778d --- /dev/null +++ b/pico/pico_port.h @@ -0,0 +1,25 @@ +#ifndef PICO_PORT_INCLUDED +#define PICO_PORT_INCLUDED + +#if defined(__GNUC__) && defined(__i386__) +#define REGPARM(x) __attribute__((regparm(x))) +#else +#define REGPARM(x) +#endif + +#ifdef __GNUC__ +#define NOINLINE __attribute__((noinline)) +#define ALIGNED(n) __attribute__((aligned(n))) +#else +#define NOINLINE +#define ALIGNED(n) +#endif + +#ifdef _MSC_VER +#define snprintf _snprintf +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define strdup _strdup +#endif + +#endif // PICO_PORT_INCLUDED diff --git a/pico/sek.c b/pico/sek.c index 86a351f..8fece1a 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -10,11 +10,6 @@ #include "pico_int.h" #include "memory.h" - -unsigned int SekCycleCnt; -unsigned int SekCycleAim; - - /* context */ // Cyclone 68000 #ifdef EMU_C68K @@ -30,15 +25,30 @@ M68K_CONTEXT PicoCpuFM68k; #endif +static int do_ack(int level) +{ + struct PicoVideo *pv = &Pico.video; + + elprintf(EL_INTS, "%cack: @ %06x [%u], p=%02x", + level == 6 ? 'v' : 'h', SekPc, SekCyclesDone(), pv->pending_ints); + // the VDP doesn't look at the 68k level + if (pv->pending_ints & pv->reg[1] & 0x20) { + pv->pending_ints &= ~0x20; + pv->status &= ~SR_F; + return (pv->reg[0] & pv->pending_ints & 0x10) >> 2; + } + else if (pv->pending_ints & pv->reg[0] & 0x10) + pv->pending_ints &= ~0x10; + + return 0; +} + /* callbacks */ #ifdef EMU_C68K // interrupt acknowledgment static int SekIntAck(int level) { - // try to emulate VDP's reaction to 68000 int ack - if (level == 4) { Pico.video.pending_ints = 0; elprintf(EL_INTS, "hack: @ %06x [%i]", SekPc, SekCycleCnt); } - else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%i]", SekPc, SekCycleCnt); } - PicoCpuCM68k.irq = 0; + PicoCpuCM68k.irq = do_ack(level); return CYCLONE_INT_ACK_AUTOVECTOR; } @@ -60,6 +70,8 @@ static int SekUnrecognizedOpcode() PicoCpuCM68k.state_flags |= 1; return 1; } + // happened once - may happen again + SekFinishIdleDet(); #ifdef EMU_M68K // debugging cyclone { extern int have_illegal; @@ -74,9 +86,7 @@ static int SekUnrecognizedOpcode() #ifdef EMU_M68K static int SekIntAckM68K(int level) { - if (level == 4) { Pico.video.pending_ints = 0; elprintf(EL_INTS, "hack: @ %06x [%i]", SekPc, SekCycleCnt); } - else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%i]", SekPc, SekCycleCnt); } - CPU_INT_LEVEL = 0; + CPU_INT_LEVEL = do_ack(level) << 8; return M68K_INT_ACK_AUTOVECTOR; } @@ -90,15 +100,7 @@ static int SekTasCallback(void) #ifdef EMU_F68K static void SekIntAckF68K(unsigned level) { - if (level == 4) { - Pico.video.pending_ints = 0; - elprintf(EL_INTS, "hack: @ %06x [%i]", SekPc, SekCyclesDone()); - } - else if(level == 6) { - Pico.video.pending_ints &= ~0x20; - elprintf(EL_INTS, "vack: @ %06x [%i]", SekPc, SekCyclesDone()); - } - PicoCpuFM68k.interrupts[0] = 0; + PicoCpuFM68k.interrupts[0] = do_ack(level); } #endif @@ -166,17 +168,17 @@ PICO_INTERNAL int SekReset(void) void SekStepM68k(void) { - SekCycleAim=SekCycleCnt+1; + Pico.t.m68c_aim = Pico.t.m68c_cnt + 1; #if defined(EMU_CORE_DEBUG) - SekCycleCnt+=CM_compareRun(1, 0); + Pico.t.m68c_cnt += CM_compareRun(1, 0); #elif defined(EMU_C68K) PicoCpuCM68k.cycles=1; CycloneRun(&PicoCpuCM68k); - SekCycleCnt+=1-PicoCpuCM68k.cycles; + Pico.t.m68c_cnt += 1 - PicoCpuCM68k.cycles; #elif defined(EMU_M68K) - SekCycleCnt+=m68k_execute(1); + Pico.t.m68c_cnt += m68k_execute(1); #elif defined(EMU_F68K) - SekCycleCnt+=fm68k_emulate(1, 0); + Pico.t.m68c_cnt += fm68k_emulate(1, 0); #endif } @@ -226,7 +228,7 @@ PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub) *(unsigned int *)(cpu+0x40) = pc; *(unsigned int *)(cpu+0x50) = - is_sub ? SekCycleCntS68k : SekCycleCnt; + is_sub ? SekCycleCntS68k : Pico.t.m68c_cnt; } PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) @@ -266,7 +268,7 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) if (is_sub) SekCycleCntS68k = *(unsigned int *)(cpu+0x50); else - SekCycleCnt = *(unsigned int *)(cpu+0x50); + Pico.t.m68c_cnt = *(unsigned int *)(cpu+0x50); } @@ -300,7 +302,8 @@ void SekRegisterIdleHit(unsigned int pc) void SekInitIdleDet(void) { - unsigned short **tmp = realloc(idledet_ptrs, 0x200*4); + unsigned short **tmp; + tmp = realloc(idledet_ptrs, 0x200 * sizeof(tmp[0])); if (tmp == NULL) { free(idledet_ptrs); idledet_ptrs = NULL; @@ -408,7 +411,8 @@ int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx) } if (idledet_count >= 0x200 && (idledet_count & 0x1ff) == 0) { - unsigned short **tmp = realloc(idledet_ptrs, (idledet_count+0x200)*4); + unsigned short **tmp; + tmp = realloc(idledet_ptrs, (idledet_count+0x200) * sizeof(tmp[0])); if (tmp == NULL) return 1; idledet_ptrs = tmp; @@ -421,6 +425,8 @@ int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx) void SekFinishIdleDet(void) { + if (idledet_count < 0) + return; #ifdef EMU_C68K CycloneFinishIdle(); #endif @@ -439,6 +445,7 @@ void SekFinishIdleDet(void) else elprintf(EL_STATUS|EL_IDLE, "idle: don't know how to restore %04x", *op); } + idledet_count = -1; } @@ -460,7 +467,7 @@ void SekTrace(int is_s68k) struct ref_68k *x68k = &ref_68ks[is_s68k]; u32 pc = is_s68k ? SekPcS68k : SekPc; u32 sr = is_s68k ? SekSrS68k : SekSr; - u32 cycles = is_s68k ? SekCycleCntS68k : SekCycleCnt; + u32 cycles = is_s68k ? SekCycleCntS68k : Pico.t.m68c_cnt; u32 r; u8 cmd; #ifdef CPU_CMP_W @@ -549,6 +556,7 @@ breakloop: printf("D%d: %08x A%d: %08x\n", i, x68k->dar[i], i, x68k->dar[i + 8]); printf("PC: %08x, %08x\n", x68k->pc, x68k->pc_prev); + printf("SR: %04x\n", x68k->sr); PDebugDumpMem(); exit(1); diff --git a/pico/sms.c b/pico/sms.c index 8c44d51..a2351b0 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -23,7 +23,7 @@ static unsigned char vdp_data_read(void) struct PicoVideo *pv = &Pico.video; unsigned char d; - d = Pico.vramb[pv->addr]; + d = PicoMem.vramb[pv->addr]; pv->addr = (pv->addr + 1) & 0x3fff; pv->pending = 0; return d; @@ -44,10 +44,10 @@ static void vdp_data_write(unsigned char d) struct PicoVideo *pv = &Pico.video; if (pv->type == 3) { - Pico.cram[pv->addr & 0x1f] = d; + PicoMem.cram[pv->addr & 0x1f] = d; Pico.m.dirtyPal = 1; } else { - Pico.vramb[pv->addr] = d; + PicoMem.vramb[pv->addr] = d; } pv->addr = (pv->addr + 1) & 0x3fff; @@ -180,7 +180,7 @@ static void xwrite(unsigned int a, unsigned char d) { elprintf(EL_IO, "z80 write [%04x] %02x", a, d); if (a >= 0xc000) - Pico.zram[a & 0x1fff] = d; + PicoMem.zram[a & 0x1fff] = d; if (a >= 0xfff8) write_bank(a, d); } @@ -195,7 +195,7 @@ void PicoPowerMS(void) { int s, tmp; - memset(&Pico.ram,0,(unsigned char *)&Pico.rom - Pico.ram); + memset(&PicoMem,0,sizeof(PicoMem)); memset(&Pico.video,0,sizeof(Pico.video)); memset(&Pico.m,0,sizeof(Pico.m)); Pico.m.pal = 0; @@ -219,11 +219,11 @@ void PicoPowerMS(void) void PicoMemSetupMS(void) { z80_map_set(z80_read_map, 0x0000, 0xbfff, Pico.rom, 0); - z80_map_set(z80_read_map, 0xc000, 0xdfff, Pico.zram, 0); - z80_map_set(z80_read_map, 0xe000, 0xffff, Pico.zram, 0); + z80_map_set(z80_read_map, 0xc000, 0xdfff, PicoMem.zram, 0); + z80_map_set(z80_read_map, 0xe000, 0xffff, PicoMem.zram, 0); z80_map_set(z80_write_map, 0x0000, 0xbfff, xwrite, 1); - z80_map_set(z80_write_map, 0xc000, 0xdfff, Pico.zram, 0); + z80_map_set(z80_write_map, 0xc000, 0xdfff, PicoMem.zram, 0); z80_map_set(z80_write_map, 0xe000, 0xffff, xwrite, 1); #ifdef _USE_DRZ80 @@ -232,8 +232,8 @@ void PicoMemSetupMS(void) #endif #ifdef _USE_CZ80 Cz80_Set_Fetch(&CZ80, 0x0000, 0xbfff, (FPTR)Pico.rom); - Cz80_Set_Fetch(&CZ80, 0xc000, 0xdfff, (FPTR)Pico.zram); - Cz80_Set_Fetch(&CZ80, 0xe000, 0xffff, (FPTR)Pico.zram); + Cz80_Set_Fetch(&CZ80, 0xc000, 0xdfff, (FPTR)PicoMem.zram); + Cz80_Set_Fetch(&CZ80, 0xe000, 0xffff, (FPTR)PicoMem.zram); Cz80_Set_INPort(&CZ80, z80_sms_in); Cz80_Set_OUTPort(&CZ80, z80_sms_out); #endif @@ -258,6 +258,8 @@ void PicoFrameMS(void) int nmi; int y; + PsndStartFrame(); + nmi = (PicoPad[0] >> 7) & 1; if (!Pico.ms.nmi_state && nmi) z80_nmi(); diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c index 8474c70..b212759 100644 --- a/pico/sound/sn76496.c +++ b/pico/sound/sn76496.c @@ -73,96 +73,54 @@ int *sn76496_regs; void SN76496Write(int data) { struct SN76496 *R = &ono_sn; - int n; - + int n, r, c; /* update the output buffer before changing the registers */ //stream_update(R->Channel,0); + r = R->LastRegister; if (data & 0x80) - { - int r = (data & 0x70) >> 4; - int c = r/2; + r = R->LastRegister = (data & 0x70) >> 4; + c = r / 2; - R->LastRegister = r; - R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); - switch (r) - { - case 0: /* tone 0 : frequency */ - case 2: /* tone 1 : frequency */ - case 4: /* tone 2 : frequency */ - R->Period[c] = R->UpdateStep * R->Register[r]; - if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; - if (r == 4) - { - /* update noise shift frequency */ - if ((R->Register[6] & 0x03) == 0x03) - R->Period[3] = 2 * R->Period[2]; - } - break; - case 1: /* tone 0 : volume */ - case 3: /* tone 1 : volume */ - case 5: /* tone 2 : volume */ - case 7: /* noise : volume */ - R->Volume[c] = R->VolTable[data & 0x0f]; - break; - case 6: /* noise : frequency, mode */ - { - int n = R->Register[6]; - R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; - n &= 3; - /* N/512,N/1024,N/2048,Tone #3 output */ - R->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+(n&3))); - - /* reset noise shifter */ - R->RNG = NG_PRESET; - R->Output[3] = R->RNG & 1; - } - break; - } - } + if (!(data & 0x80) && (r == 0 || r == 2 || r == 4)) + // data byte (tone only) + R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4); else - { - int r = R->LastRegister; - int c = r/2; + R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); - switch (r) - { - case 0: /* tone 0 : frequency */ - case 2: /* tone 1 : frequency */ - case 4: /* tone 2 : frequency */ - R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4); - R->Period[c] = R->UpdateStep * R->Register[r]; - if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; - if (r == 4) - { - /* update noise shift frequency */ - if ((R->Register[6] & 0x03) == 0x03) - R->Period[3] = 2 * R->Period[2]; - } - break; - case 1: /* tone 0 : volume */ - case 3: /* tone 1 : volume */ - case 5: /* tone 2 : volume */ - case 7: /* noise : volume */ - R->Volume[c] = R->VolTable[data & 0x0f]; - R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); - break; - case 6: /* noise : frequency, mode */ - { - R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); - n = R->Register[6]; - R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; - n &= 3; - /* N/512,N/1024,N/2048,Tone #3 output */ - R->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+(n&3))); - - /* reset noise shifter */ - R->RNG = NG_PRESET; - R->Output[3] = R->RNG & 1; - } - break; - } + data = R->Register[r]; + switch (r) + { + case 0: /* tone 0 : frequency */ + case 2: /* tone 1 : frequency */ + case 4: /* tone 2 : frequency */ + R->Period[c] = R->UpdateStep * data; + if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; + if (r == 4) + { + /* update noise shift frequency */ + if ((R->Register[6] & 0x03) == 0x03) + R->Period[3] = 2 * R->Period[2]; + } + break; + case 1: /* tone 0 : volume */ + case 3: /* tone 1 : volume */ + case 5: /* tone 2 : volume */ + case 7: /* noise : volume */ + R->Volume[c] = R->VolTable[data & 0x0f]; + break; + case 6: /* noise : frequency, mode */ + n = data; + R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; + n &= 3; + /* N/512,N/1024,N/2048,Tone #3 output */ + R->Period[3] = (n == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5 + n)); + + /* reset noise shifter */ + R->RNG = NG_PRESET; + R->Output[3] = R->RNG & 1; + break; } } diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 18e1225..a67ebcc 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -14,15 +14,13 @@ #include "../cd/cue.h" #include "mix.h" -#define SIMPLE_WRITE_SOUND 0 - void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo; // master int buffer to mix to static int PsndBuffer[2*(44100+100)/50]; -// dac -static unsigned short dac_info[312+4]; // pppppppp ppppllll, p - pos in buff, l - length to write for this sample +// dac, psg +static unsigned short dac_info[312+4]; // pos in sample buffer // cdda output buffer short cdda_out_buffer[2*1152]; @@ -32,8 +30,9 @@ int PsndRate=0; int PsndLen=0; // number of mono samples, multiply by 2 for stereo int PsndLen_exc_add=0; // this is for non-integer sample counts per line, eg. 22050/60 int PsndLen_exc_cnt=0; -int PsndDacLine=0; +int PsndDacLine, PsndPsgLine; short *PsndOut=NULL; // PCM data buffer +static int PsndLen_use; // timers int timer_a_next_oflow, timer_a_step; // in z80 cycles @@ -45,7 +44,7 @@ extern int *sn76496_regs; static void dac_recalculate(void) { - int i, dac_cnt, pos, len, lines = Pico.m.pal ? 312 : 262, mid = Pico.m.pal ? 68 : 93; + int i, dac_cnt, pos, len, lines = Pico.m.pal ? 313 : 262, mid = Pico.m.pal ? 68 : 93; if (PsndLen <= lines) { @@ -57,14 +56,12 @@ static void dac_recalculate(void) for(i=226; i != 225; i++) { if (i >= lines) i = 0; - len = 0; if(dac_cnt < 0) { - len=1; pos++; dac_cnt += lines; } dac_cnt -= PsndLen; - dac_info[i] = (pos<<4)|len; + dac_info[i] = pos; } } else @@ -86,24 +83,12 @@ static void dac_recalculate(void) len++; } dac_cnt += PsndLen; - dac_info[i] = (pos<<4)|len; - pos+=len; + pos += len; + dac_info[i] = pos; } - // last sample - for(len = 0, i = pos; i < PsndLen; i++) len++; - if (PsndLen_exc_add) len++; - dac_info[224] = (pos<<4)|len; } - mid = (dac_info[lines-1] & 0xfff0) + ((dac_info[lines-1] & 0xf) << 4); for (i = lines; i < sizeof(dac_info) / sizeof(dac_info[0]); i++) - dac_info[i] = mid; - //for(i=len=0; i < lines; i++) { - // printf("%03i : %03i : %i\n", i, dac_info[i]>>4, dac_info[i]&0xf); - // len+=dac_info[i]&0xf; - //} - //printf("rate is %i, len %f\n", PsndRate, (double)PsndRate/(Pico.m.pal ? 50.0 : 60.0)); - //printf("len total: %i, last pos: %i\n", len, pos); - //exit(8); + dac_info[i] = dac_info[0]; } @@ -118,10 +103,6 @@ PICO_INTERNAL void PsndReset(void) // to be called after changing sound rate or chips void PsndRerate(int preserve_state) { - // PsndRerate not ready yet - if (Pico.romsize <= 0) - return; - void *state = NULL; int target_fps = Pico.m.pal ? 50 : 60; @@ -167,29 +148,77 @@ void PsndRerate(int preserve_state) } +PICO_INTERNAL void PsndStartFrame(void) +{ + // compensate for float part of PsndLen + PsndLen_use = PsndLen; + PsndLen_exc_cnt += PsndLen_exc_add; + if (PsndLen_exc_cnt >= 0x10000) { + PsndLen_exc_cnt -= 0x10000; + PsndLen_use++; + } + + PsndDacLine = PsndPsgLine = 0; + emustatus &= ~1; + dac_info[224] = PsndLen_use; +} + PICO_INTERNAL void PsndDoDAC(int line_to) { int pos, pos1, len; int dout = ym2612.dacout; int line_from = PsndDacLine; - if (line_to >= 312) - line_to = 311; + if (line_to >= 313) + line_to = 312; + + pos = dac_info[line_from]; + pos1 = dac_info[line_to + 1]; + len = pos1 - pos; + if (len <= 0) + return; PsndDacLine = line_to + 1; - pos =dac_info[line_from]>>4; - pos1=dac_info[line_to]; - len = ((pos1>>4)-pos) + (pos1&0xf); - if (!len) return; + if (!PsndOut) + return; if (PicoOpt & POPT_EN_STEREO) { short *d = PsndOut + pos*2; - for (; len > 0; len--, d+=2) *d = dout; + for (; len > 0; len--, d+=2) *d += dout; } else { short *d = PsndOut + pos; - for (; len > 0; len--, d++) *d = dout; + for (; len > 0; len--, d++) *d += dout; + } +} + +PICO_INTERNAL void PsndDoPSG(int line_to) +{ + int line_from = PsndPsgLine; + int pos, pos1, len; + int stereo = 0; + + if (line_to >= 313) + line_to = 312; + + pos = dac_info[line_from]; + pos1 = dac_info[line_to + 1]; + len = pos1 - pos; + //elprintf(EL_STATUS, "%3d %3d %3d %3d %3d", + // pos, pos1, len, line_from, line_to); + if (len <= 0) + return; + + PsndPsgLine = line_to + 1; + + if (!PsndOut || !(PicoOpt & POPT_EN_PSG)) + return; + + if (PicoOpt & POPT_EN_STEREO) { + stereo = 1; + pos <<= 1; } + SN76496Update(PsndOut + pos, len, stereo); } // cdda @@ -264,21 +293,6 @@ static int PsndRender(int offset, int length) pprof_start(sound); -#if !SIMPLE_WRITE_SOUND - if (offset == 0) { // should happen once per frame - // compensate for float part of PsndLen - PsndLen_exc_cnt += PsndLen_exc_add; - if (PsndLen_exc_cnt >= 0x10000) { - PsndLen_exc_cnt -= 0x10000; - length++; - } - } -#endif - - // PSG - if (PicoOpt & POPT_EN_PSG) - SN76496Update(PsndOut+offset, length, stereo); - if (PicoAHW & PAHW_PICO) { PicoPicoPCMUpdate(PsndOut+offset, length, stereo); return length; @@ -326,20 +340,17 @@ static int PsndRender(int offset, int length) // to be called on 224 or line_sample scanlines only PICO_INTERNAL void PsndGetSamples(int y) { -#if SIMPLE_WRITE_SOUND - if (y != 224) return; - PsndRender(0, PsndLen); - if (PicoWriteSound) - PicoWriteSound(PsndLen * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2)); - PsndClear(); -#else static int curr_pos = 0; + if (ym2612.dacen && PsndDacLine < y) + PsndDoDAC(y - 1); + PsndDoPSG(y - 1); + if (y == 224) { if (emustatus & 2) curr_pos += PsndRender(curr_pos, PsndLen-PsndLen/2); - else curr_pos = PsndRender(0, PsndLen); + else curr_pos = PsndRender(0, PsndLen_use); if (emustatus & 1) emustatus |= 2; else emustatus &= ~2; @@ -347,28 +358,20 @@ PICO_INTERNAL void PsndGetSamples(int y) PicoWriteSound(curr_pos * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2)); // clear sound buffer PsndClear(); + PsndDacLine = 224; + dac_info[224] = 0; } else if (emustatus & 3) { emustatus|= 2; emustatus&=~1; curr_pos = PsndRender(0, PsndLen/2); } -#endif } PICO_INTERNAL void PsndGetSamplesMS(void) { int stereo = (PicoOpt & 8) >> 3; - int length = PsndLen; - -#if !SIMPLE_WRITE_SOUND - // compensate for float part of PsndLen - PsndLen_exc_cnt += PsndLen_exc_add; - if (PsndLen_exc_cnt >= 0x10000) { - PsndLen_exc_cnt -= 0x10000; - length++; - } -#endif + int length = PsndLen_use; // PSG if (PicoOpt & POPT_EN_PSG) @@ -386,3 +389,4 @@ PICO_INTERNAL void PsndGetSamplesMS(void) PsndClear(); } +// vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index 692f34e..0867f55 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -139,10 +139,6 @@ void memset32(int *dest, int c, int count); #define INLINE static __inline #endif -#ifndef STRICTINLINE -#define STRICTINLINE static inline -#endif - #ifndef M_PI #define M_PI 3.14159265358979323846 #endif @@ -535,7 +531,7 @@ static int g_lfo_ampm = 0; /* OPN Mode Register Write */ -static INLINE void set_timers( int v ) +INLINE void set_timers( int v ) { /* b7 = CSM MODE */ /* b6 = 3 slot mode */ @@ -557,7 +553,7 @@ static INLINE void set_timers( int v ) } -static INLINE void FM_KEYON(int c , int s ) +INLINE void FM_KEYON(int c , int s ) { FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s]; if( !SLOT->key ) @@ -569,7 +565,7 @@ static INLINE void FM_KEYON(int c , int s ) } } -static INLINE void FM_KEYOFF(int c , int s ) +INLINE void FM_KEYOFF(int c , int s ) { FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s]; if( SLOT->key ) @@ -582,7 +578,7 @@ static INLINE void FM_KEYOFF(int c , int s ) /* set detune & multiple */ -static INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v) +INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v) { SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1; SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7]; @@ -590,13 +586,13 @@ static INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v) } /* set total level */ -static INLINE void set_tl(FM_SLOT *SLOT, int v) +INLINE void set_tl(FM_SLOT *SLOT, int v) { SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */ } /* set attack rate & key scale */ -static INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v) +INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v) { UINT8 old_KSR = SLOT->KSR; @@ -628,7 +624,7 @@ static INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v) } /* set decay rate */ -static INLINE void set_dr(FM_SLOT *SLOT, int v) +INLINE void set_dr(FM_SLOT *SLOT, int v) { int eg_sh_d1r, eg_sel_d1r; @@ -641,7 +637,7 @@ static INLINE void set_dr(FM_SLOT *SLOT, int v) } /* set sustain rate */ -static INLINE void set_sr(FM_SLOT *SLOT, int v) +INLINE void set_sr(FM_SLOT *SLOT, int v) { int eg_sh_d2r, eg_sel_d2r; @@ -654,7 +650,7 @@ static INLINE void set_sr(FM_SLOT *SLOT, int v) } /* set release rate */ -static INLINE void set_sl_rr(FM_SLOT *SLOT, int v) +INLINE void set_sl_rr(FM_SLOT *SLOT, int v) { int eg_sh_rr, eg_sel_rr; @@ -668,7 +664,9 @@ static INLINE void set_sl_rr(FM_SLOT *SLOT, int v) SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24); } -static INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm) + + +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm) { int ret, sin = (phase>>16) + (pm>>1); int neg = sin & 0x200; @@ -685,7 +683,7 @@ static INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm) return neg ? -ret : ret; } -static INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) { int ret, sin = (phase+pm)>>16; int neg = sin & 0x200; @@ -703,7 +701,7 @@ static INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) #if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612) /* advance LFO to next sample */ -static INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt) +INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt) { UINT8 pos; UINT8 prev_pos; @@ -741,83 +739,57 @@ static INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt) return lfo_ampm; } -#define EG_INC_VAL() \ - ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1) - -STRICTINLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt) +INLINE void update_eg_phase(UINT16 *vol_out, FM_SLOT *SLOT, UINT32 eg_cnt) { INT32 volume = SLOT->volume; + UINT32 pack = SLOT->eg_pack[SLOT->state - 1]; + UINT32 shift = pack >> 24; + INT32 eg_inc_val; - switch(SLOT->state) - { - case EG_ATT: /* attack phase */ - { - UINT32 pack = SLOT->eg_pack_ar; - UINT32 shift = pack>>24; - if ( !(eg_cnt & ((1<>4; + if (eg_cnt & ((1 << shift) - 1)) + return; - if (volume <= MIN_ATT_INDEX) - { - volume = MIN_ATT_INDEX; - SLOT->state = EG_DEC; - } - } - break; - } + eg_inc_val = pack >> ((eg_cnt >> shift) & 7) * 3; + eg_inc_val = (1 << (eg_inc_val & 7)) >> 1; - case EG_DEC: /* decay phase */ + switch (SLOT->state) + { + case EG_ATT: /* attack phase */ + volume += ( ~volume * eg_inc_val ) >> 4; + if ( volume <= MIN_ATT_INDEX ) { - UINT32 pack = SLOT->eg_pack_d1r; - UINT32 shift = pack>>24; - if ( !(eg_cnt & ((1<= (INT32) SLOT->sl ) - SLOT->state = EG_SUS; - } - break; + volume = MIN_ATT_INDEX; + SLOT->state = EG_DEC; } + break; - case EG_SUS: /* sustain phase */ - { - UINT32 pack = SLOT->eg_pack_d2r; - UINT32 shift = pack>>24; - if ( !(eg_cnt & ((1<= (INT32) SLOT->sl ) + SLOT->state = EG_SUS; + break; - if ( volume >= MAX_ATT_INDEX ) - { - volume = MAX_ATT_INDEX; - /* do not change SLOT->state (verified on real chip) */ - } - } - break; + case EG_SUS: /* sustain phase */ + volume += eg_inc_val; + if ( volume >= MAX_ATT_INDEX ) + { + volume = MAX_ATT_INDEX; + /* do not change SLOT->state (verified on real chip) */ } + break; - case EG_REL: /* release phase */ + case EG_REL: /* release phase */ + volume += eg_inc_val; + if ( volume >= MAX_ATT_INDEX ) { - UINT32 pack = SLOT->eg_pack_rr; - UINT32 shift = pack>>24; - if ( !(eg_cnt & ((1<= MAX_ATT_INDEX ) - { - volume = MAX_ATT_INDEX; - SLOT->state = EG_OFF; - } - } - break; + volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; } + break; } SLOT->volume = volume; - return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */ + *vol_out = SLOT->tl + volume; /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */ } #endif @@ -875,10 +847,10 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length) ct->eg_timer -= EG_TIMER_OVERFLOW; ct->eg_cnt++; - if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt); - if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt); - if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt); - if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt); + if (ct->CH->SLOT[SLOT1].state != EG_OFF) update_eg_phase(&ct->vol_out1, &ct->CH->SLOT[SLOT1], ct->eg_cnt); + if (ct->CH->SLOT[SLOT2].state != EG_OFF) update_eg_phase(&ct->vol_out2, &ct->CH->SLOT[SLOT2], ct->eg_cnt); + if (ct->CH->SLOT[SLOT3].state != EG_OFF) update_eg_phase(&ct->vol_out3, &ct->CH->SLOT[SLOT3], ct->eg_cnt); + if (ct->CH->SLOT[SLOT4].state != EG_OFF) update_eg_phase(&ct->vol_out4, &ct->CH->SLOT[SLOT4], ct->eg_cnt); } if (ct->pack & 4) continue; /* output disabled */ @@ -1073,7 +1045,7 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length) } else { buffer[scounter] += smp; } - ct->algo = 8; // algo is only used in asm, here only bit3 is used + ct->algo |= 8; } /* update phase counters AFTER output calculations */ @@ -1203,7 +1175,7 @@ static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: s } /* update phase increment and envelope generator */ -STRICTINLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc) +INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc) { int ksr, fdt; @@ -1252,7 +1224,7 @@ STRICTINLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc) } /* update phase increment counters */ -void refresh_fc_eg_chan(FM_CH *CH) +INLINE void refresh_fc_eg_chan(FM_CH *CH) { if( CH->SLOT[SLOT1].Incr==-1){ int fc = CH->fc; @@ -1264,7 +1236,7 @@ void refresh_fc_eg_chan(FM_CH *CH) } } -void refresh_fc_eg_chan_sl3(void) +INLINE void refresh_fc_eg_chan_sl3(void) { if( ym2612.CH[2].SLOT[SLOT1].Incr==-1) { @@ -1707,6 +1679,7 @@ void YM2612ResetChip_(void) for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0); /* DAC mode clear */ ym2612.dacen = 0; + ym2612.dacout = 0; ym2612.addr_A1 = 0; } @@ -1721,22 +1694,19 @@ int YM2612Write_(unsigned int a, unsigned int v) v &= 0xff; /* adjust to 8 bit bus */ - switch( a&3){ + switch( a & 3 ){ case 0: /* address port 0 */ + case 2: /* address port 1 */ ym2612.OPN.ST.address = v; - ym2612.addr_A1 = 0; - ret=0; + ym2612.addr_A1 = (a & 2) >> 1; + ret = 0; break; - case 1: /* data port 0 */ - if (ym2612.addr_A1 != 0) { - ret=0; - break; /* verified on real YM2608 */ - } - - addr = ym2612.OPN.ST.address; + case 1: + case 3: /* data port */ + addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8); - switch( addr & 0xf0 ) + switch( addr & 0x1f0 ) { case 0x20: /* 0x20-0x2f Mode */ switch( addr ) @@ -1749,6 +1719,7 @@ int YM2612Write_(unsigned int a, unsigned int v) else { ym2612.OPN.lfo_inc = 0; + ym2612.OPN.lfo_cnt = 0; } break; #if 0 // handled elsewhere @@ -1818,23 +1789,6 @@ int YM2612Write_(unsigned int a, unsigned int v) ret = OPNWriteReg(addr,v); } break; - - case 2: /* address port 1 */ - ym2612.OPN.ST.address = v; - ym2612.addr_A1 = 1; - ret=0; - break; - - case 3: /* data port 1 */ - if (ym2612.addr_A1 != 1) { - ret=0; - break; /* verified on real YM2608 */ - } - - addr = ym2612.OPN.ST.address | 0x100; - - ret = OPNWriteReg(addr, v); - break; } return ret; diff --git a/pico/sound/ym2612.h b/pico/sound/ym2612.h index f5e98a0..73a36a8 100644 --- a/pico/sound/ym2612.h +++ b/pico/sound/ym2612.h @@ -43,10 +43,16 @@ typedef struct INT16 volume; /* #0x1a envelope counter | need_save */ UINT32 sl; /* #0x1c sustain level:sl_table[SL] */ - UINT32 eg_pack_ar; /* #0x20 (attack state) */ - UINT32 eg_pack_d1r; /* #0x24 (decay state) */ - UINT32 eg_pack_d2r; /* #0x28 (sustain state) */ - UINT32 eg_pack_rr; /* #0x2c (release state) */ + /* asm relies on this order: */ + union { + struct { + UINT32 eg_pack_rr; /* #0x20 1 (release state) */ + UINT32 eg_pack_d2r; /* #0x24 2 (sustain state) */ + UINT32 eg_pack_d1r; /* #0x28 3 (decay state) */ + UINT32 eg_pack_ar; /* #0x2c 4 (attack state) */ + }; + UINT32 eg_pack[4]; + }; } FM_SLOT; diff --git a/pico/sound/ym2612_arm.s b/pico/sound/ym2612_arm.s index 7db3122..9c436d4 100644 --- a/pico/sound/ym2612_arm.s +++ b/pico/sound/ym2612_arm.s @@ -30,103 +30,73 @@ .equiv EG_TIMER_OVERFLOW, (3*(1<= (INT32) SLOT->sl ) - movge r3, #EG_SUS strgeb r3, [r5,#0x17] @ state - b 4f + b 10f + +4: @ EG_ATT + subs r3, r3, #1 @ eg_inc_val_shift - 1 + mov r2, #0 + mvnpl r2, r0 + mov r2, r2, lsl r3 + add r0, r0, r2, asr #4 + cmp r0, #0 @ if (volume <= MIN_ATT_INDEX) + movle r3, #EG_DEC + strleb r3, [r5,#0x17] @ state + movle r0, #0 + b 10f 2: @ EG_SUS - ldr r2, [r5,#0x28] @ eg_pack_d2r (1ci) - mov r0, r2, lsr #24 - mov r3, r3, lsl r0 - sub r3, r3, #1 - tst r1, r3 - bne 5f @ do smth for tl problem (set on init?) - mov r3, r1, lsr r0 - ldrh r0, [r5,#0x1a] @ volume - and r3, r3, #7 - add r3, r3, r3, lsl #1 - mov r3, r2, lsr r3 - and r3, r3, #7 @ shift for eg_inc calculation - mov r2, #1 - mov r3, r2, lsl r3 - add r0, r0, r3, asr #1 mov r2, #1024 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX ) movge r0, r2 - b 4f + b 10f -3: @ EG_REL - ldr r2, [r5,#0x2c] @ eg_pack_rr (1ci) - mov r0, r2, lsr #24 - mov r3, r3, lsl r0 - sub r3, r3, #1 - tst r1, r3 - bne 5f @ do smth for tl problem (set on init?) - mov r3, r1, lsr r0 - ldrh r0, [r5,#0x1a] @ volume - and r3, r3, #7 - add r3, r3, r3, lsl #1 - mov r3, r2, lsr r3 - and r3, r3, #7 @ shift for eg_inc calculation - mov r2, #1 - mov r3, r2, lsl r3 - add r0, r0, r3, asr #1 +1: @ EG_REL mov r2, #1024 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX ) @@ -134,7 +104,7 @@ movge r3, #EG_OFF strgeb r3, [r5,#0x17] @ state -4: +10: @ finish ldrh r3, [r5,#0x18] @ tl strh r0, [r5,#0x1a] @ volume .if \slot == SLOT1 @@ -157,7 +127,7 @@ orr r7, r0, r7, lsr #16 .endif -5: +0: @ EG_OFF .endm @@ -187,28 +157,30 @@ tstne r12, #(1<<(\slot+8)) .if \slot == SLOT1 mov r1, r6, lsl #16 - mov r1, r1, lsr #17 + mov r1, r1, lsr #16 .elseif \slot == SLOT2 - mov r1, r6, lsr #17 + mov r1, r6, lsr #16 .elseif \slot == SLOT3 mov r1, r7, lsl #16 - mov r1, r1, lsr #17 + mov r1, r1, lsr #16 .elseif \slot == SLOT4 - mov r1, r7, lsr #17 + mov r1, r7, lsr #16 .endif andne r2, r12, #0xc0 movne r2, r2, lsr #6 addne r2, r2, #24 addne r1, r1, r12, lsr r2 + bic r1, r1, #1 .endm +@ \r=sin/result, r1=env, r3=ym_tl_tab .macro lookup_tl r tst \r, #0x100 eorne \r, \r, #0xff @ if (sin & 0x100) sin = 0xff - (sin&0xff); tst \r, #0x200 and \r, \r, #0xff - orr \r, \r, r1, lsl #8 + orr \r, \r, r1, lsl #7 mov \r, \r, lsl #1 ldrh \r, [r3, \r] @ 2ci if ne rsbne \r, \r, #0 @@ -345,9 +317,9 @@ make_eg_out SLOT3 cmp r1, #ENV_QUIET ldr r2, [lr, #0x38] @ mem (for future) - movcs r0, r2 + mov r0, #0 bcs 0f - ldr r0, [lr, #0x18] @ 1ci + ldr r0, [lr, #0x18] @ phase3 mov r0, r0, lsr #16 lookup_tl r0 @ r0=c2 @@ -370,13 +342,13 @@ cmp r1, #ENV_QUIET movcs r2, #0 bcs 2f - ldr r2, [lr, #0x14] + ldr r2, [lr, #0x14] @ phase2 mov r5, r10, lsr #17 add r2, r5, r2, lsr #16 lookup_tl r2 @ r2=mem 2: - str r2, [lr, #0x38] @ mem + str r2, [lr, #0x38] @ mem .endm @@ -541,9 +513,9 @@ movne r0, r0, asr #16 movne r0, r0, lsl r2 - ldr r2, [lr, #0x10] + ldr r2, [lr, #0x10] @ phase1 + add r0, r0, r2 mov r0, r0, lsr #16 - add r0, r0, r2, lsr #16 lookup_tl r0 mov r10,r10,lsl #16 @ ct->op1_out <<= 16; mov r0, r0, lsl #16 @@ -759,11 +731,18 @@ chan_render_loop: crl_loop_lfo: add r0, lr, #0x30 ldmia r0, {r1,r2} + + subs r4, r4, #0x100 + bmi crl_loop_end + add r2, r2, r1 str r2, [lr, #0x30] + @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt advance_lfo_m + add r4, r4, #0x100 + crl_loop: subs r4, r4, #0x100 bmi crl_loop_end @@ -859,7 +838,6 @@ crl_algo6: crl_algo7: upd_algo7_m - .pool crl_algo_done: @@ -917,6 +895,7 @@ crl_do_phase: crl_loop_end: +@ stmia lr, {r6,r7} @ save volumes (for debug) str r8, [lr, #0x44] @ eg_timer str r12, [lr, #0x4c] @ pack (for lfo_ampm) str r4, [lr, #0x50] @ was_update @@ -925,3 +904,4 @@ crl_loop_end: .pool +@ vim:filetype=armasm diff --git a/pico/state.c b/pico/state.c index 88b8655..69e8be0 100644 --- a/pico/state.c +++ b/pico/state.c @@ -78,54 +78,6 @@ static void *open_save_file(const char *fname, int is_save) return afile; } -// legacy savestate loading -#define SCANP(f, x) areaRead(&Pico.x, sizeof(Pico.x), 1, f) - -static int state_load_legacy(void *file) -{ - unsigned char head[32]; - unsigned char cpu[0x60]; - unsigned char cpu_z80[Z80_STATE_SIZE]; - void *ym2612_regs; - int ok; - - memset(&cpu,0,sizeof(cpu)); - memset(&cpu_z80,0,sizeof(cpu_z80)); - - memset(head, 0, sizeof(head)); - areaRead(head, sizeof(head), 1, file); - if (strcmp((char *)head, "Pico") != 0) - return -1; - - elprintf(EL_STATUS, "legacy savestate"); - - // Scan all the memory areas: - SCANP(file, ram); - SCANP(file, vram); - SCANP(file, zram); - SCANP(file, cram); - SCANP(file, vsram); - - // Pack, scan and unpack the cpu data: - areaRead(cpu, sizeof(cpu), 1, file); - SekUnpackCpu(cpu, 0); - - SCANP(file, m); - SCANP(file, video); - - ok = areaRead(cpu_z80, sizeof(cpu_z80), 1, file) == sizeof(cpu_z80); - // do not unpack if we fail to load z80 state - if (!ok) z80_reset(); - else z80_unpack(cpu_z80); - - ym2612_regs = YM2612GetRegs(); - areaRead(sn76496_regs, 28*4, 1, file); - areaRead(ym2612_regs, 0x200+4, 1, file); - ym2612_unpack_state(); - - return 0; -} - // --------------------------------------------------------------------------- typedef enum { @@ -278,9 +230,9 @@ static int state_save(void *file) memset(buff, 0, sizeof(buff)); SekPackCpu(buff, 0); CHECKED_WRITE_BUFF(CHUNK_M68K, buff); - CHECKED_WRITE_BUFF(CHUNK_RAM, Pico.ram); - CHECKED_WRITE_BUFF(CHUNK_VSRAM, Pico.vsram); - CHECKED_WRITE_BUFF(CHUNK_IOPORTS, Pico.ioports); + CHECKED_WRITE_BUFF(CHUNK_RAM, PicoMem.ram); + CHECKED_WRITE_BUFF(CHUNK_VSRAM, PicoMem.vsram); + CHECKED_WRITE_BUFF(CHUNK_IOPORTS, PicoMem.ioports); ym2612_pack_state(); CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs); } @@ -288,9 +240,9 @@ static int state_save(void *file) CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms); } - CHECKED_WRITE_BUFF(CHUNK_VRAM, Pico.vram); - CHECKED_WRITE_BUFF(CHUNK_ZRAM, Pico.zram); - CHECKED_WRITE_BUFF(CHUNK_CRAM, Pico.cram); + CHECKED_WRITE_BUFF(CHUNK_VRAM, PicoMem.vram); + CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram); + CHECKED_WRITE_BUFF(CHUNK_CRAM, PicoMem.cram); CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m); CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video); @@ -469,14 +421,14 @@ static int state_load(void *file) CHECKED_READ_BUFF(buff_z80); break; - case CHUNK_RAM: CHECKED_READ_BUFF(Pico.ram); break; - case CHUNK_VRAM: CHECKED_READ_BUFF(Pico.vram); break; - case CHUNK_ZRAM: CHECKED_READ_BUFF(Pico.zram); break; - case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); break; - case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); break; + case CHUNK_RAM: CHECKED_READ_BUFF(PicoMem.ram); break; + case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); break; + case CHUNK_ZRAM: CHECKED_READ_BUFF(PicoMem.zram); break; + case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); break; + case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); break; case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break; case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); break; - case CHUNK_IOPORTS: CHECKED_READ_BUFF(Pico.ioports); break; + case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break; case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break; case CHUNK_FM: ym2612_regs = YM2612GetRegs(); @@ -589,6 +541,9 @@ readend: if (PicoAHW & PAHW_32X) Pico32xStateLoaded(1); + if (PicoLoadStateHook != NULL) + PicoLoadStateHook(); + // must unpack 68k and z80 after banks are set up if (!(PicoAHW & PAHW_SMS)) SekUnpackCpu(buff_m68k, 0); @@ -598,7 +553,7 @@ readend: z80_unpack(buff_z80); // due to dep from 68k cycles.. - SekCycleAim = SekCycleCnt; + Pico.t.m68c_aim = Pico.t.m68c_cnt; if (PicoAHW & PAHW_32X) Pico32xStateLoaded(0); if (PicoAHW & PAHW_MCD) @@ -607,6 +562,11 @@ readend: pcd_state_loaded(); } + 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: @@ -638,9 +598,9 @@ static int state_load_gfx(void *file) switch (buff[0]) { - case CHUNK_VRAM: CHECKED_READ_BUFF(Pico.vram); found++; break; - case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); found++; break; - case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); found++; break; + case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); found++; break; + case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); found++; break; + case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); found++; break; case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break; #ifndef NO_32X @@ -676,17 +636,8 @@ static int pico_state_internal(void *afile, int is_save) if (is_save) ret = state_save(afile); - else { + else ret = state_load(afile); - if (ret != 0) { - areaSeek(afile, 0, SEEK_SET); - ret = state_load_legacy(afile); - } - - if (PicoLoadStateHook != NULL) - PicoLoadStateHook(); - Pico.m.dirtyPal = 1; - } return ret; } @@ -730,10 +681,10 @@ int PicoStateLoadGfx(const char *fname) if (ret != 0) { // assume legacy areaSeek(afile, 0x10020, SEEK_SET); // skip header and RAM - areaRead(Pico.vram, 1, sizeof(Pico.vram), afile); + areaRead(PicoMem.vram, 1, sizeof(PicoMem.vram), afile); areaSeek(afile, 0x2000, SEEK_CUR); - areaRead(Pico.cram, 1, sizeof(Pico.cram), afile); - areaRead(Pico.vsram, 1, sizeof(Pico.vsram), afile); + areaRead(PicoMem.cram, 1, sizeof(PicoMem.cram), afile); + areaRead(PicoMem.vsram, 1, sizeof(PicoMem.vsram), afile); areaSeek(afile, 0x221a0, SEEK_SET); areaRead(&Pico.video, 1, sizeof(Pico.video), afile); } @@ -766,9 +717,9 @@ void *PicoTmpStateSave(void) if (t == NULL) return NULL; - memcpy(t->vram, Pico.vram, sizeof(Pico.vram)); - memcpy(t->cram, Pico.cram, sizeof(Pico.cram)); - memcpy(t->vsram, Pico.vsram, sizeof(Pico.vsram)); + memcpy(t->vram, PicoMem.vram, sizeof(PicoMem.vram)); + memcpy(t->cram, PicoMem.cram, sizeof(PicoMem.cram)); + memcpy(t->vsram, PicoMem.vsram, sizeof(PicoMem.vsram)); memcpy(&t->video, &Pico.video, sizeof(Pico.video)); #ifndef NO_32X @@ -788,9 +739,9 @@ void PicoTmpStateRestore(void *data) if (t == NULL) return; - memcpy(Pico.vram, t->vram, sizeof(Pico.vram)); - memcpy(Pico.cram, t->cram, sizeof(Pico.cram)); - memcpy(Pico.vsram, t->vsram, sizeof(Pico.vsram)); + memcpy(PicoMem.vram, t->vram, sizeof(PicoMem.vram)); + memcpy(PicoMem.cram, t->cram, sizeof(PicoMem.cram)); + memcpy(PicoMem.vsram, t->vsram, sizeof(PicoMem.vsram)); memcpy(&Pico.video, &t->video, sizeof(Pico.video)); Pico.m.dirtyPal = 1; diff --git a/pico/videoport.c b/pico/videoport.c index 1e67ddb..b5e3f86 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -8,8 +8,9 @@ */ #include "pico_int.h" +#define NEED_DMA_SOURCE +#include "memory.h" -int line_base_cycles; extern const unsigned char hcounts_32[]; extern const unsigned char hcounts_40[]; @@ -20,27 +21,39 @@ typedef unsigned int u32; #define UTYPES_DEFINED #endif -int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp) = NULL; +int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, unsigned int *mask) = NULL; -static INLINE void AutoIncrement(void) +static __inline void AutoIncrement(void) { Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]); } +static NOINLINE void VideoWrite128(u32 a, u16 d) +{ + // nasty + a = ((a & 2) >> 1) | ((a & 0x400) >> 9) | (a & 0x3FC) | ((a & 0x1F800) >> 1); + ((u8 *)PicoMem.vram)[a] = d; +} + static void VideoWrite(u16 d) { - unsigned int a=Pico.video.addr; + unsigned int a = Pico.video.addr; switch (Pico.video.type) { - case 1: if(a&1) d=(u16)((d<<8)|(d>>8)); // If address is odd, bytes are swapped (which game needs this?) - Pico.vram [(a>>1)&0x7fff]=d; + case 1: if (a & 1) + d = (u16)((d << 8) | (d >> 8)); + PicoMem.vram [(a >> 1) & 0x7fff] = d; if (a - ((unsigned)(Pico.video.reg[5]&0x7f) << 9) < 0x400) Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; break; case 3: Pico.m.dirtyPal = 1; - Pico.cram [(a>>1)&0x003f]=d; break; // wraps (Desert Strike) - case 5: Pico.vsram[(a>>1)&0x003f]=d; break; + PicoMem.cram [(a >> 1) & 0x3f] = d; break; + case 5: PicoMem.vsram[(a >> 1) & 0x3f] = d; break; + case 0x81: + a |= Pico.video.addr_u << 16; + VideoWrite128(a, d); + break; //default:elprintf(EL_ANOMALY, "VDP write %04x with bad type %i", d, Pico.video.type); break; } @@ -55,9 +68,9 @@ static unsigned int VideoRead(void) switch (Pico.video.type) { - case 0: d=Pico.vram [a&0x7fff]; break; - case 8: d=Pico.cram [a&0x003f]; break; - case 4: d=Pico.vsram[a&0x003f]; break; + case 0: d=PicoMem.vram [a & 0x7fff]; break; + case 8: d=PicoMem.cram [a & 0x003f]; break; + case 4: d=PicoMem.vsram[a & 0x003f]; break; default:elprintf(EL_ANOMALY, "VDP read with bad type %i", Pico.video.type); break; } @@ -72,104 +85,92 @@ static int GetDmaLength(void) // 16-bit words to transfer: len =pvid->reg[0x13]; len|=pvid->reg[0x14]<<8; - // Charles MacDonald: - if(!len) len = 0xffff; + len = ((len - 1) & 0xffff) + 1; return len; } -static void DmaSlow(int len) +static void DmaSlow(int len, unsigned int source) { - u16 *pd=0, *pdend, *r; - unsigned int a=Pico.video.addr, a2, d; - unsigned char inc=Pico.video.reg[0xf]; - unsigned int source; - - source =Pico.video.reg[0x15]<<1; - source|=Pico.video.reg[0x16]<<9; - source|=Pico.video.reg[0x17]<<17; + u32 inc = Pico.video.reg[0xf]; + u32 a = Pico.video.addr; + u16 *r, *base = NULL; + u32 mask = 0x1ffff; - elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%i] @ %06x", + 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&8)||!(Pico.video.reg[1]&0x40), SekCyclesDone(), SekPc); Pico.m.dma_xfers += len; + if (Pico.m.dma_xfers < len) // lame 16bit var + Pico.m.dma_xfers = ~0; SekCyclesBurnRun(CheckDMA()); - if ((source&0xe00000)==0xe00000) { // Ram - pd=(u16 *)(Pico.ram+(source&0xfffe)); - pdend=(u16 *)(Pico.ram+0x10000); + if ((source & 0xe00000) == 0xe00000) { // Ram + base = (u16 *)PicoMem.ram; + mask = 0xffff; } else if (PicoAHW & PAHW_MCD) { - elprintf(EL_VDPDMA, "DmaSlow CD, r3=%02x", Pico_mcd->s68k_regs[3]); - if(source<0x20000) { // Bios area - pd=(u16 *)(Pico_mcd->bios+(source&~1)); - pdend=(u16 *)(Pico_mcd->bios+0x20000); - } else if ((source&0xfc0000)==0x200000) { // Word Ram - source -= 2; - if (!(Pico_mcd->s68k_regs[3]&4)) { // 2M mode - pd=(u16 *)(Pico_mcd->word_ram2M+(source&0x3fffe)); - pdend=(u16 *)(Pico_mcd->word_ram2M+0x40000); + u8 r3 = Pico_mcd->s68k_regs[3]; + elprintf(EL_VDPDMA, "DmaSlow CD, r3=%02x", r3); + if (source < 0x20000) { // Bios area + base = (u16 *)Pico_mcd->bios; + } else if ((source & 0xfc0000) == 0x200000) { // Word Ram + if (!(r3 & 4)) { // 2M mode + base = (u16 *)(Pico_mcd->word_ram2M + (source & 0x20000)); } else { if (source < 0x220000) { // 1M mode - int bank = Pico_mcd->s68k_regs[3]&1; - pd=(u16 *)(Pico_mcd->word_ram1M[bank]+(source&0x1fffe)); - pdend=(u16 *)(Pico_mcd->word_ram1M[bank]+0x20000); + int bank = r3 & 1; + base = (u16 *)(Pico_mcd->word_ram1M[bank]); } else { - DmaSlowCell(source, a, len, inc); + DmaSlowCell(source - 2, a, len, inc); return; } } - } else if ((source&0xfe0000)==0x020000) { // Prg Ram - u8 *prg_ram = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; - pd=(u16 *)(prg_ram+(source&0x1fffe)); - pdend=(u16 *)(prg_ram+0x20000); - } else { - elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: FIXME: unsupported src", Pico.video.type, source, a); - return; + source -= 2; + } else if ((source & 0xfe0000) == 0x020000) { // Prg Ram + base = (u16 *)Pico_mcd->prg_ram_b[r3 >> 6]; + source -= 2; // XXX: test } } else { // if we have DmaHook, let it handle ROM because of possible DMA delay - if (PicoDmaHook && PicoDmaHook(source, len, &pd, &pdend)); - else if (source%04x: invalid src", Pico.video.type, source, a); - return; - } + u32 source2; + if (PicoDmaHook && (source2 = PicoDmaHook(source, len, &base, &mask))) + source = source2; + else // Rom + base = m68k_dma_source(source); } - - // overflow protection, might break something.. - if (len > pdend - pd) { - len = pdend - pd; - elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow overflow"); + if (!base) { + elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: invalid src", Pico.video.type, source, a); + return; } + // operate in words + source >>= 1; + mask >>= 1; + switch (Pico.video.type) { case 1: // vram - r = Pico.vram; - if (inc == 2 && !(a&1) && a+len*2 < 0x10000) + r = PicoMem.vram; + if (inc == 2 && !(a & 1) && a + len * 2 < 0x10000 + && !(((source + len - 1) ^ source) & ~mask)) { // most used DMA mode - pmemcpy16(r + (a>>1), pd, len); - a += len*2; + memcpy((char *)r + a, base + (source & mask), len * 2); + a += len * 2; } else { for(; len; len--) { - d=*pd++; - if(a&1) d=(d<<8)|(d>>8); - r[a>>1] = (u16)d; // will drop the upper bits + u16 d = base[source++ & mask]; + if(a & 1) d=(d<<8)|(d>>8); + r[a >> 1] = d; // AutoIncrement - a=(u16)(a+inc); - // didn't src overlap? - //if(pd >= pdend) pd-=0x8000; // should be good for RAM, bad for ROM + a = (u16)(a + inc); } } Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; @@ -177,33 +178,34 @@ static void DmaSlow(int len) case 3: // cram Pico.m.dirtyPal = 1; - r = Pico.cram; - for(a2=a&0x7f; len; len--) + r = PicoMem.cram; + for (; len; len--) + { + r[(a / 2) & 0x3f] = base[source++ & mask]; + // AutoIncrement + a += inc; + } + break; + + case 5: // vsram + r = PicoMem.vsram; + for (; len; len--) { - r[a2>>1] = (u16)*pd++; // bit 0 is ignored + r[(a / 2) & 0x3f] = base[source++ & mask]; // AutoIncrement - a2+=inc; - // didn't src overlap? - //if(pd >= pdend) pd-=0x8000; - // good dest? - if(a2 >= 0x80) break; // Todds Adventures in Slime World / Andre Agassi tennis + a += inc; } - a=(a&0xff00)|a2; break; - case 5: // vsram[a&0x003f]=d; - r = Pico.vsram; - for(a2=a&0x7f; len; len--) + case 0x81: // vram 128k + a |= Pico.video.addr_u << 16; + for(; len; len--) { - r[a2>>1] = (u16)*pd++; + VideoWrite128(a, base[source++ & mask]); // AutoIncrement - a2+=inc; - // didn't src overlap? - //if(pd >= pdend) pd-=0x8000; - // good dest? - if(a2 >= 0x80) break; + a = (a + inc) & 0x1ffff; } - a=(a&0xff00)|a2; + Pico.video.addr_u = a >> 16; break; default: @@ -217,25 +219,23 @@ static void DmaSlow(int len) static void DmaCopy(int len) { - u16 a=Pico.video.addr; - unsigned char *vr = (unsigned char *) Pico.vram; - unsigned char *vrs; - unsigned char inc=Pico.video.reg[0xf]; + u16 a = Pico.video.addr; + u8 *vr = (u8 *)PicoMem.vram; + u8 inc = Pico.video.reg[0xf]; int source; - elprintf(EL_VDPDMA, "DmaCopy len %i [%i]", len, SekCyclesDone()); + elprintf(EL_VDPDMA, "DmaCopy len %i [%u]", len, SekCyclesDone()); Pico.m.dma_xfers += len; + if (Pico.m.dma_xfers < len) + Pico.m.dma_xfers = ~0; Pico.video.status |= 2; // dma busy source =Pico.video.reg[0x15]; source|=Pico.video.reg[0x16]<<8; - vrs=vr+source; - - if (source+len > 0x10000) len=0x10000-source; // clip?? for (; len; len--) { - vr[a] = *vrs++; + vr[a] = vr[source++ & 0xffff]; // AutoIncrement a=(u16)(a+inc); } @@ -244,76 +244,104 @@ static void DmaCopy(int len) Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; } -// check: Contra, Megaman -// note: this is still inaccurate -static void DmaFill(int data) +static NOINLINE void DmaFill(int data) { - int len; - unsigned short a=Pico.video.addr; - unsigned char *vr=(unsigned char *) Pico.vram; - unsigned char high = (unsigned char) (data >> 8); - unsigned char inc=Pico.video.reg[0xf]; + u16 a = Pico.video.addr; + u8 *vr = (u8 *)PicoMem.vram; + u8 high = (u8)(data >> 8); + u8 inc = Pico.video.reg[0xf]; + int source; + int len, l; - len=GetDmaLength(); - elprintf(EL_VDPDMA, "DmaFill len %i inc %i [%i]", len, inc, SekCyclesDone()); + len = GetDmaLength(); + elprintf(EL_VDPDMA, "DmaFill len %i inc %i [%u]", len, inc, SekCyclesDone()); Pico.m.dma_xfers += len; + if (Pico.m.dma_xfers < len) // lame 16bit var + Pico.m.dma_xfers = ~0; Pico.video.status |= 2; // dma busy - // from Charles MacDonald's genvdp.txt: - // Write lower byte to address specified - vr[a] = (unsigned char) data; - a=(u16)(a+inc); - - if (!inc) len=1; - - for (; len; len--) { - // Write upper byte to adjacent address - // (here we are byteswapped, so address is already 'adjacent') - vr[a] = high; + switch (Pico.video.type) + { + case 1: // vram + for (l = len; l; l--) { + // Write upper byte to adjacent address + // (here we are byteswapped, so address is already 'adjacent') + vr[a] = high; - // Increment address register - a=(u16)(a+inc); + // Increment address register + a = (u16)(a + inc); + } + break; + case 3: // cram + case 5: { // vsram + // TODO: needs fifo; anyone using these? + static int once; + if (!once++) + elprintf(EL_STATUS|EL_ANOMALY|EL_VDPDMA, "TODO: cram/vsram fill"); + } + default: + a += len * inc; + break; } + // remember addr - Pico.video.addr=a; - // update length - Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; // Dino Dini's Soccer (E) (by Haze) + Pico.video.addr = a; + // register update + Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; + source = Pico.video.reg[0x15]; + source |= Pico.video.reg[0x16] << 8; + source += len; + Pico.video.reg[0x15] = source; + Pico.video.reg[0x16] = source >> 8; Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; } -static void CommandDma(void) +static NOINLINE void CommandDma(void) { struct PicoVideo *pvid=&Pico.video; - int len=0,method=0; + u32 len, method; + u32 source; if ((pvid->reg[1]&0x10)==0) return; // DMA not enabled - len=GetDmaLength(); + len = GetDmaLength(); + source =Pico.video.reg[0x15]; + source|=Pico.video.reg[0x16] << 8; + source|=Pico.video.reg[0x17] << 16; method=pvid->reg[0x17]>>6; - if (method< 2) DmaSlow(len); // 68000 to VDP - if (method==3) DmaCopy(len); // VRAM Copy + if (method < 2) + DmaSlow(len, source << 1); // 68000 to VDP + else if (method == 3) + DmaCopy(len); // VRAM Copy + else + return; + + source += len; + Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; + Pico.video.reg[0x15] = source; + Pico.video.reg[0x16] = source >> 8; } -static void CommandChange(void) +static NOINLINE void CommandChange(void) { - struct PicoVideo *pvid=&Pico.video; - unsigned int cmd=0,addr=0; + struct PicoVideo *pvid = &Pico.video; + unsigned int cmd, addr; - cmd=pvid->command; + cmd = pvid->command; // Get type of transfer 0xc0000030 (v/c/vsram read/write) - pvid->type=(unsigned char)(((cmd>>2)&0xc)|(cmd>>30)); + pvid->type = (u8)(((cmd >> 2) & 0xc) | (cmd >> 30)); + if (pvid->type == 1) // vram + pvid->type |= pvid->reg[1] & 0x80; // 128k // Get address 0x3fff0003 - addr =(cmd>>16)&0x3fff; - addr|=(cmd<<14)&0xc000; - pvid->addr=(unsigned short)addr; - - // Check for dma: - if (cmd&0x80) CommandDma(); + addr = (cmd >> 16) & 0x3fff; + addr |= (cmd << 14) & 0xc000; + pvid->addr = (u16)addr; + pvid->addr_u = (u8)((cmd >> 2) & 1); } static void DrawSync(int blank_on) @@ -329,16 +357,17 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) { struct PicoVideo *pvid=&Pico.video; - //if (Pico.m.scanline < 224) - // elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x", a, d); - a&=0x1c; + //elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x [%u] @ %06x", + // a, d, SekCyclesDone(), SekPc); - if (a==0x00) // Data port 0 or 2 + a &= 0x1c; + switch (a) { + case 0x00: // Data port 0 or 2 // try avoiding the sync.. if (Pico.m.scanline < 224 && (pvid->reg[1]&0x40) && !(!pvid->pending && - ((pvid->command & 0xc00000f0) == 0x40000010 && Pico.vsram[pvid->addr>>1] == d)) + ((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == d)) ) DrawSync(0); @@ -347,40 +376,35 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) pvid->pending=0; } - // If a DMA fill has been set up, do it - if ((pvid->command&0x80) && (pvid->reg[1]&0x10) && (pvid->reg[0x17]>>6)==2) + if (!(pvid->status & SR_VB) && !(PicoOpt&POPT_DIS_VDP_FIFO)) { - DmaFill(d); + int use = pvid->type == 1 ? 2 : 1; + pvid->lwrite_cnt -= use; + if (pvid->lwrite_cnt < 0) + SekCyclesLeft = 0; + elprintf(EL_ASVDP, "VDP data write: [%04x] %04x [%u] {%i} #%i @ %06x", + Pico.video.addr, d, SekCyclesDone(), Pico.video.type, pvid->lwrite_cnt, SekPc); } - else - { - // preliminary FIFO emulation for Chaos Engine, The (E) - if (!(pvid->status&8) && (pvid->reg[1]&0x40) && !(PicoOpt&POPT_DIS_VDP_FIFO)) // active display? - { - pvid->status&=~0x200; // FIFO no longer empty - pvid->lwrite_cnt++; - if (pvid->lwrite_cnt >= 4) pvid->status|=0x100; // FIFO full - if (pvid->lwrite_cnt > 4) { - SekCyclesBurnRun(32); // penalty // 488/12-8 - } - elprintf(EL_ASVDP, "VDP data write: %04x [%06x] {%i} #%i @ %06x", d, Pico.video.addr, - Pico.video.type, pvid->lwrite_cnt, SekPc); - } - VideoWrite(d); - } - return; - } + VideoWrite(d); - if (a==0x04) // Control (command) port 4 or 6 - { + if ((pvid->command&0x80) && (pvid->reg[1]&0x10) && (pvid->reg[0x17]>>6)==2) + DmaFill(d); + + break; + + case 0x04: // Control (command) port 4 or 6 if (pvid->pending) { - if (d & 0x80) DrawSync(0); // only need sync for DMA // Low word of command: - pvid->command&=0xffff0000; - pvid->command|=d; - pvid->pending=0; + pvid->command &= 0xffff0000; + pvid->command |= d; + pvid->pending = 0; CommandChange(); + // Check for dma: + if (d & 0x80) { + DrawSync(0); + CommandDma(); + } } else { @@ -396,19 +420,22 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) return; } - if (num == 1 && !(d&0x40) && SekCyclesDone() - line_base_cycles <= 488-390) + if (num == 1 && !(d&0x40) && SekCyclesDone() - Pico.t.m68c_line_start <= 488-390) blank_on = 1; DrawSync(blank_on); pvid->reg[num]=(unsigned char)d; switch (num) { case 0x00: - elprintf(EL_INTSW, "hint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x10)>>4, + elprintf(EL_INTSW, "hint_onoff: %i->%i [%u] pend=%i @ %06x", (dold&0x10)>>4, (d&0x10)>>4, SekCyclesDone(), (pvid->pending_ints&0x10)>>4, SekPc); goto update_irq; case 0x01: - elprintf(EL_INTSW, "vint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x20)>>5, + elprintf(EL_INTSW, "vint_onoff: %i->%i [%u] pend=%i @ %06x", (dold&0x20)>>5, (d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc); + if (!(pvid->status & PVS_VB2)) + pvid->status &= ~SR_VB; + pvid->status |= ((d >> 3) ^ SR_VB) & SR_VB; // forced blanking goto update_irq; case 0x05: //elprintf(EL_STATUS, "spritep moved to %04x", (unsigned)(Pico.video.reg[5]&0x7f) << 9); @@ -426,14 +453,15 @@ update_irq: // update IRQ level if (!SekShouldInterrupt()) // hack { - int lines, pints, irq=0; + int lines, pints, irq = 0; lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); - pints = (pvid->pending_ints&lines); + pints = pvid->pending_ints & lines; if (pints & 0x20) irq = 6; else if (pints & 0x10) irq = 4; SekInterrupt(irq); // update line - if (irq) SekEndRun(24); // make it delayed + // this is broken because cost of current insn isn't known here + if (irq) SekEndRun(21); // make it delayed } #endif } @@ -445,29 +473,58 @@ update_irq: pvid->pending=1; } } + break; + + // case 0x08: // 08 0a - HV counter - lock up + // case 0x0c: // 0c 0e - HV counter - lock up + // case 0x10: // 10 12 - PSG - handled by caller + // case 0x14: // 14 16 - PSG - handled by caller + // case 0x18: // 18 1a - no effect? + case 0x1c: // 1c 1e - debug + pvid->debug = d; + pvid->debug_p = 0; + if (d & (1 << 6)) { + pvid->debug_p |= PVD_KILL_A | PVD_KILL_B; + pvid->debug_p |= PVD_KILL_S_LO | PVD_KILL_S_HI; + } + switch ((d >> 7) & 3) { + case 1: + pvid->debug_p &= ~(PVD_KILL_S_LO | PVD_KILL_S_HI); + pvid->debug_p |= PVD_FORCE_S; + break; + case 2: + pvid->debug_p &= ~PVD_KILL_A; + pvid->debug_p |= PVD_FORCE_A; + break; + case 3: + pvid->debug_p &= ~PVD_KILL_B; + pvid->debug_p |= PVD_FORCE_B; + break; + } + break; } } -PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a) +static u32 SrLow(const struct PicoVideo *pv) { - a&=0x1c; + unsigned int c, d = pv->status; - if (a==0x04) // control port - { - struct PicoVideo *pv=&Pico.video; - unsigned int d; - d=pv->status; - //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast) - if (SekCyclesDone() - line_base_cycles >= 488-88) - d|=0x0004; // H-Blank (Sonic3 vs) - - d |= ((pv->reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled - d |= (pv->pending_ints&0x20)<<2; // V-int pending? - if (d&0x100) pv->status&=~0x100; // FIFO no longer full + c = SekCyclesDone() - Pico.t.m68c_line_start - 39; + if (c < 92) + d |= SR_HB; + return d; +} - pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald) +PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a) +{ + a &= 0x1c; - elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc); + if (a == 0x04) // control port + { + struct PicoVideo *pv = &Pico.video; + unsigned int d = SrLow(pv); + pv->pending = 0; + elprintf(EL_SR, "SR read: %04x [%u] @ %06x", d, SekCyclesDone(), SekPc); return d; } @@ -490,12 +547,12 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a) { unsigned int d; - d = (SekCyclesDone() - line_base_cycles) & 0x1ff; // FIXME + d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME if (Pico.video.reg[12]&1) d = hcounts_40[d]; else d = hcounts_32[d]; - elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc); + elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc); return d | (Pico.video.v_counter << 8); } @@ -507,43 +564,47 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a) return 0; } -unsigned int PicoVideoRead8(unsigned int a) +unsigned char PicoVideoRead8DataH(void) { - unsigned int d; - a&=0x1d; + return VideoRead() >> 8; +} - switch (a) - { - case 0: return VideoRead() >> 8; - case 1: return VideoRead() & 0xff; - case 4: // control port/status reg - d = Pico.video.status >> 8; - if (d&1) Pico.video.status&=~0x100; // FIFO no longer full - Pico.video.pending = 0; - elprintf(EL_SR, "SR read (h): %02x @ %06x", d, SekPc); - return d; - case 5: - d = Pico.video.status & 0xff; - //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast) - d |= ((Pico.video.reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled - d |= (Pico.video.pending_ints&0x20)<<2; // V-int pending? - if (SekCyclesDone() - line_base_cycles >= 488-88) d |= 4; // H-Blank - Pico.video.pending = 0; - elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc); - return d; - case 8: // hv counter - elprintf(EL_HVCNT, "vcounter: %02x (%i) @ %06x", Pico.video.v_counter, SekCyclesDone(), SekPc); - return Pico.video.v_counter; - case 9: - d = (SekCyclesDone() - line_base_cycles) & 0x1ff; // FIXME - if (Pico.video.reg[12]&1) - d = hcounts_40[d]; - else d = hcounts_32[d]; - elprintf(EL_HVCNT, "hcounter: %02x (%i) @ %06x", d, SekCyclesDone(), SekPc); - return d; - } +unsigned char PicoVideoRead8DataL(void) +{ + return VideoRead(); +} - return 0; +unsigned char PicoVideoRead8CtlH(void) +{ + u8 d = (u8)(Pico.video.status >> 8); + Pico.video.pending = 0; + elprintf(EL_SR, "SR read (h): %02x @ %06x", d, SekPc); + return d; +} + +unsigned char PicoVideoRead8CtlL(void) +{ + u8 d = SrLow(&Pico.video); + Pico.video.pending = 0; + elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc); + return d; +} + +unsigned char PicoVideoRead8HV_H(void) +{ + elprintf(EL_HVCNT, "vcounter: %02x [%u] @ %06x", Pico.video.v_counter, SekCyclesDone(), SekPc); + return Pico.video.v_counter; +} + +// FIXME: broken +unsigned char PicoVideoRead8HV_L(void) +{ + u32 d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME + if (Pico.video.reg[12]&1) + d = hcounts_40[d]; + else d = hcounts_32[d]; + elprintf(EL_HVCNT, "hcounter: %02x [%u] @ %06x", d, SekCyclesDone(), SekPc); + return d; } // vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/z80if.c b/pico/z80if.c index 33a8618..b69495e 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -119,29 +119,6 @@ void z80_reset(void) #endif } -/* save state stuff */ -static int z80_unpack_legacy(const void *data) -{ -#if defined(_USE_DRZ80) - if (*(int *)data == 0x015A7244) { // "DrZ" v1 save? - u32 pc, sp; - memcpy(&drZ80, data+4, 0x54); - pc = (drZ80.Z80PC - drZ80.Z80PC_BASE) & 0xffff; - sp = (drZ80.Z80SP - drZ80.Z80SP_BASE) & 0xffff; - // update bases - drz80_load_pcsp(pc, sp); - return 0; - } -#elif defined(_USE_CZ80) - if (*(int *)data == 0x00007a43) { // "Cz" save? - memcpy(&CZ80, (int*)data+8, offsetof(cz80_struc, BasePC)); - Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)((int*)data+4)); - return 0; - } -#endif - return -1; -} - struct z80sr_main { u8 a, f; u8 b, c; @@ -226,9 +203,7 @@ int z80_unpack(const void *data) { const struct z80_state *s = data; if (strcmp(s->magic, "Z80") != 0) { - if (z80_unpack_legacy(data) != 0) - goto fail; - elprintf(EL_STATUS, "legacy z80 state"); + elprintf(EL_STATUS, "legacy z80 state - ignored"); return 0; } @@ -278,13 +253,9 @@ int z80_unpack(const void *data) Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? HOLD_LINE : CLEAR_LINE); return 0; } +#else + return 0; #endif - -fail: - elprintf(EL_STATUS|EL_ANOMALY, "z80_unpack failed"); - z80_reset(); - z80_int(); - return -1; } void z80_exit(void) diff --git a/platform/common/common.mak b/platform/common/common.mak index c8571ac..89e4605 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -49,7 +49,7 @@ SRCS_COMMON += $(R)pico/draw_arm.S $(R)pico/draw2_arm.S endif ifeq "$(asm_memory)" "1" DEFINES += _ASM_MEMORY_C -SRCS_COMMON += $(R)pico/memory_arm.s +SRCS_COMMON += $(R)pico/memory_arm.S endif ifeq "$(asm_ym2612)" "1" DEFINES += _ASM_YM2612_C @@ -62,7 +62,7 @@ SRCS_COMMON += $(R)pico/cd/misc_arm.s endif ifeq "$(asm_cdmemory)" "1" DEFINES += _ASM_CD_MEMORY_C -SRCS_COMMON += $(R)pico/cd/memory_arm.s +SRCS_COMMON += $(R)pico/cd/memory_arm.S endif ifeq "$(asm_32xdraw)" "1" DEFINES += _ASM_32X_DRAW @@ -87,23 +87,24 @@ else DEFINES += NO_SMS endif # CD -SRCS_COMMON += $(R)pico/cd/mcd.c $(R)pico/cd/cd_memory.c $(R)pico/cd/cd_sek.c \ +SRCS_COMMON += $(R)pico/cd/mcd.c $(R)pico/cd/memory.c $(R)pico/cd/sek.c \ $(R)pico/cd/cdc.c $(R)pico/cd/cdd.c $(R)pico/cd/cd_image.c \ $(R)pico/cd/cue.c $(R)pico/cd/gfx.c $(R)pico/cd/gfx_dma.c \ - $(R)pico/cd/cd_misc.c $(R)pico/cd/pcm.c + $(R)pico/cd/misc.c $(R)pico/cd/pcm.c # 32X ifneq "$(no_32x)" "1" -SRCS_COMMON += $(R)pico/32x/32x.c $(R)pico/32x/32x_memory.c $(R)pico/32x/32x_draw.c \ +SRCS_COMMON += $(R)pico/32x/32x.c $(R)pico/32x/memory.c $(R)pico/32x/draw.c \ $(R)pico/32x/sh2soc.c $(R)pico/32x/pwm.c else DEFINES += NO_32X endif # Pico -SRCS_COMMON += $(R)pico/pico/pico_pico.c $(R)pico/pico/pico_memory.c $(R)pico/pico/xpcm.c +SRCS_COMMON += $(R)pico/pico/pico.c $(R)pico/pico/memory.c $(R)pico/pico/xpcm.c # carthw SRCS_COMMON += $(R)pico/carthw/carthw.c +SRCS_COMMON += $(R)pico/carthw/eeprom_spi.c # SVP -SRCS_COMMON += $(R)pico/carthw/svp/svp.c $(R)pico/carthw/svp/svp_memory.c \ +SRCS_COMMON += $(R)pico/carthw/svp/svp.c $(R)pico/carthw/svp/memory.c \ $(R)pico/carthw/svp/ssp16.c ifeq "$(use_svpdrc)" "1" DEFINES += _SVP_DRC @@ -172,13 +173,15 @@ ifeq "$(use_cyclone)" "1" $(FR)pico/pico.c: $(FR)cpu/cyclone/Cyclone.h endif +CYCLONE_CONFIG ?= cyclone_config.h + $(FR)cpu/cyclone/Cyclone.h: @echo "Cyclone submodule is missing, please run 'git submodule update --init'" @false -$(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/cyclone_config.h +$(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/$(CYCLONE_CONFIG) @echo building Cyclone... - @make -C $(R)cpu/cyclone/ CONFIG_FILE=../cyclone_config.h + @make -C $(R)cpu/cyclone/ CONFIG_FILE=../$(CYCLONE_CONFIG) $(FR)cpu/cyclone/Cyclone.s: $(FR)cpu/cyclone/*.cpp $(FR)cpu/cyclone/*.h diff --git a/platform/common/config_file.c b/platform/common/config_file.c index 97369cb..e66d4e1 100644 --- a/platform/common/config_file.c +++ b/platform/common/config_file.c @@ -417,7 +417,7 @@ static void keys_parse_all(FILE *f) acts = parse_bind_val(val, &type); if (acts == -1) { lprintf("config: unhandled action \"%s\"\n", val); - return; + continue; } mystrip(var + 5); diff --git a/platform/common/emu.c b/platform/common/emu.c index 6f42b73..85e1ba7 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -889,20 +889,20 @@ int emu_save_load_game(int load, int sram) { if (PicoOpt & POPT_EN_MCD_RAMCART) { sram_size = 0x12000; - sram_data = SRam.data; + sram_data = Pico.sv.data; if (sram_data) - memcpy32((int *)sram_data, (int *)Pico_mcd->bram, 0x2000/4); + memcpy(sram_data, Pico_mcd->bram, 0x2000); } else { sram_size = 0x2000; sram_data = Pico_mcd->bram; truncate = 0; // the .brm may contain RAM cart data after normal brm } } else { - sram_size = SRam.size; - sram_data = SRam.data; + sram_size = Pico.sv.size; + sram_data = Pico.sv.data; } if (sram_data == NULL) - return 0; // SRam forcefully disabled for this game + return 0; // cart saves forcefully disabled for this game if (load) { @@ -913,7 +913,7 @@ int emu_save_load_game(int load, int sram) ret = ret > 0 ? 0 : -1; fclose(sramFile); if ((PicoAHW & PAHW_MCD) && (PicoOpt&POPT_EN_MCD_RAMCART)) - memcpy32((int *)Pico_mcd->bram, (int *)sram_data, 0x2000/4); + memcpy(Pico_mcd->bram, sram_data, 0x2000); } else { // sram save needs some special processing // see if we have anything to save @@ -973,6 +973,9 @@ void emu_set_fastforward(int set_on) currentConfig.EmuOpt = set_EmuOpt; PsndRerate(1); is_on = 0; + // mainly to unbreak pcm + if (PicoAHW & PAHW_MCD) + pcd_state_loaded(); } } @@ -1138,6 +1141,8 @@ static void run_events_ui(unsigned int which) emu_status_msg("SAVE SLOT %i [%s]", state_slot, emu_check_save_file(state_slot, NULL) ? "USED" : "FREE"); } + if (which & PEV_RESET) + emu_reset_game(); if (which & PEV_MENU) engineState = PGS_Menu; } @@ -1257,9 +1262,9 @@ void emu_init(void) void emu_finish(void) { // save SRAM - if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && SRam.changed) { + if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && Pico.sv.changed) { emu_save_load_game(0, 1); - SRam.changed = 0; + Pico.sv.changed = 0; } if (!(currentConfig.EmuOpt & EOPT_NO_AUTOSVCFG)) { @@ -1509,10 +1514,10 @@ void emu_loop(void) emu_set_fastforward(0); // save SRAM - if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && SRam.changed) { + if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && Pico.sv.changed) { plat_status_msg_busy_first("Writing SRAM/BRAM..."); emu_save_load_game(0, 1); - SRam.changed = 0; + Pico.sv.changed = 0; } pemu_loop_end(); diff --git a/platform/common/input_pico.h b/platform/common/input_pico.h index c2730b5..c0501d3 100644 --- a/platform/common/input_pico.h +++ b/platform/common/input_pico.h @@ -28,6 +28,7 @@ #define PEVB_PICO_PNEXT 21 #define PEVB_PICO_PPREV 20 #define PEVB_PICO_SWINP 19 +#define PEVB_RESET 18 #define PEV_VOL_DOWN (1 << PEVB_VOL_DOWN) #define PEV_VOL_UP (1 << PEVB_VOL_UP) @@ -41,7 +42,8 @@ #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_RESET (1 << PEVB_RESET) -#define PEV_MASK 0x7ff80000 +#define PEV_MASK 0x7ffc0000 #endif /* INCLUDE_c48097f3ff2a6a9af1cce8fd7a9b3f0c */ diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index b127077..0f9fa61 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -14,7 +14,7 @@ #include "input_pico.h" #include "version.h" -#include +#include #include #ifdef PANDORA @@ -312,6 +312,7 @@ me_bind_action emuctrl_actions[] = { "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 }, @@ -405,8 +406,6 @@ static const char h_srcart[] = "Emulate the save RAM cartridge accessory\n" "most games don't need this"; static const char h_scfx[] = "Emulate scale/rotate ASIC chip for graphics effects\n" "disable to improve performance"; -static const char h_bsync[] = "More accurate mode for CPUs (needed for some games)\n" - "disable to improve performance"; static menu_entry e_menu_cd_options[] = { @@ -803,11 +802,13 @@ static void draw_text_debug(const char *str, int skip, int from) static void draw_frame_debug(void) { char layer_str[48] = "layers: "; - if (PicoDrawMask & PDRAW_LAYERB_ON) memcpy(layer_str + 8, "B", 1); - if (PicoDrawMask & PDRAW_LAYERA_ON) memcpy(layer_str + 10, "A", 1); - if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) memcpy(layer_str + 12, "spr_lo", 6); - if (PicoDrawMask & PDRAW_SPRITES_HI_ON) memcpy(layer_str + 19, "spr_hi", 6); - if (PicoDrawMask & PDRAW_32X_ON) memcpy(layer_str + 26, "32x", 4); + struct PicoVideo *pv = &Pico.video; + + if (!(pv->debug_p & PVD_KILL_B)) memcpy(layer_str + 8, "B", 1); + if (!(pv->debug_p & PVD_KILL_A)) memcpy(layer_str + 10, "A", 1); + if (!(pv->debug_p & PVD_KILL_S_LO)) memcpy(layer_str + 12, "spr_lo", 6); + if (!(pv->debug_p & PVD_KILL_S_HI)) memcpy(layer_str + 19, "spr_hi", 6); + if (!(pv->debug_p & PVD_KILL_32X)) memcpy(layer_str + 26, "32x", 4); pemu_forced_frame(1, 0); make_bg(1); @@ -818,6 +819,7 @@ static void draw_frame_debug(void) static void debug_menu_loop(void) { + struct PicoVideo *pv = &Pico.video; int inp, mode = 0; int spr_offs = 0, dumped = 0; char *tmp; @@ -878,11 +880,11 @@ static void debug_menu_loop(void) } break; case 1: - if (inp & PBTN_LEFT) PicoDrawMask ^= PDRAW_LAYERB_ON; - if (inp & PBTN_RIGHT) PicoDrawMask ^= PDRAW_LAYERA_ON; - if (inp & PBTN_DOWN) PicoDrawMask ^= PDRAW_SPRITES_LOW_ON; - if (inp & PBTN_UP) PicoDrawMask ^= PDRAW_SPRITES_HI_ON; - if (inp & PBTN_MA2) PicoDrawMask ^= PDRAW_32X_ON; + if (inp & PBTN_LEFT) pv->debug_p ^= PVD_KILL_B; + if (inp & PBTN_RIGHT) pv->debug_p ^= PVD_KILL_A; + if (inp & PBTN_DOWN) pv->debug_p ^= PVD_KILL_S_LO; + if (inp & PBTN_UP) pv->debug_p ^= PVD_KILL_S_HI; + if (inp & PBTN_MA2) pv->debug_p ^= PVD_KILL_32X; if (inp & PBTN_MOK) { PsndOut = NULL; // just in case PicoSkipFrame = 1; diff --git a/platform/common/mp3.c b/platform/common/mp3.c index 01ac782..b2bcaf4 100644 --- a/platform/common/mp3.c +++ b/platform/common/mp3.c @@ -8,8 +8,8 @@ #include #include -#include "../../pico/pico_int.h" -#include "../../pico/sound/mix.h" +#include +#include #include "mp3.h" static FILE *mp3_current_file; diff --git a/platform/common/mp3_libavcodec.c b/platform/common/mp3_libavcodec.c index 2d3c799..9a528c1 100644 --- a/platform/common/mp3_libavcodec.c +++ b/platform/common/mp3_libavcodec.c @@ -16,6 +16,11 @@ #include "../libpicofe/lprintf.h" #include "mp3.h" +#if LIBAVCODEC_VERSION_MAJOR < 55 +#define AVCodecID CodecID +#define AV_CODEC_ID_MP3 CODEC_ID_MP3 +#endif + static AVCodecContext *ctx; /* avoid compile time linking to libavcodec due to huge list of it's deps.. @@ -94,7 +99,7 @@ int mp3dec_decode(FILE *f, int *file_pos, int file_len) int mp3dec_start(FILE *f, int fpos_start) { void (*avcodec_register_all)(void); - AVCodec *(*avcodec_find_decoder)(enum CodecID id); + AVCodec *(*avcodec_find_decoder)(enum AVCodecID id); AVCodecContext *(*avcodec_alloc_context)(void); int (*avcodec_open)(AVCodecContext *avctx, AVCodec *codec); void (*av_free)(void *ptr); @@ -137,8 +142,7 @@ int mp3dec_start(FILE *f, int fpos_start) //avcodec_init(); avcodec_register_all(); - // AV_CODEC_ID_MP3 ? - codec = avcodec_find_decoder(CODEC_ID_MP3); + codec = avcodec_find_decoder(AV_CODEC_ID_MP3); if (codec == NULL) { lprintf("mp3dec: codec missing\n"); return -1; diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index 3387b95..1b617d5 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -35,6 +35,7 @@ const struct in_default_bind in_sdl_defbinds[] __attribute__((weak)) = { { SDLK_RETURN, IN_BINDTYPE_PLAYER12, GBTN_START }, { SDLK_f, IN_BINDTYPE_PLAYER12, GBTN_MODE }, { SDLK_ESCAPE, IN_BINDTYPE_EMU, PEVB_MENU }, + { SDLK_TAB, IN_BINDTYPE_EMU, PEVB_RESET }, { SDLK_F1, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, { SDLK_F2, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, { SDLK_F3, IN_BINDTYPE_EMU, PEVB_SSLOT_PREV }, diff --git a/platform/common/version.h b/platform/common/version.h index 01e9b7d..ce4223b 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "1.91" +#define VERSION "1.92" diff --git a/platform/gp2x/940ctl.c b/platform/gp2x/940ctl.c index 6ba13bd..ff79c88 100644 --- a/platform/gp2x/940ctl.c +++ b/platform/gp2x/940ctl.c @@ -391,7 +391,7 @@ int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty) ym_active_chs = shared_ctl->ym_active_chs; // mix in ym buffer. is_buf_empty means nobody mixed there anything yet and it may contain trash - if (is_buf_empty && ym_active_chs) memcpy32(buffer, ym_buf, length<writebuffsel == 1) { diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index c0bc71f..01fd162 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -280,7 +280,7 @@ static int EmuScanEnd16_ld(unsigned int num) ld_left = ld_lines; EmuScanBegin16_ld(num); - memcpy32(Pico.est.DrawLineDest, oldline, 320 * gp2x_current_bpp / 8 / 4); + memcpy(Pico.est.DrawLineDest, oldline, 320 * gp2x_current_bpp / 8); if (emu_scan_end) emu_scan_end(ld_counter); @@ -315,7 +315,7 @@ static int make_local_pal_md(int fast_mode) bgr444_to_rgb32(localPal+0x80, Pico.est.HighPal+0x40); } else - memcpy32(localPal+0x80, localPal, 0x40); // for spr prio mess + memcpy(localPal + 0x80, localPal, 0x40 * 4); // for spr prio mess return pallen; } diff --git a/platform/libpicofe b/platform/libpicofe index 21604a0..f287890 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 21604a047941b8fe81d381ede0371c75da964afd +Subproject commit f287890d65ad36ca75bb71d05745693ae78b1490 diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 934b685..7896ffb 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -98,6 +98,7 @@ void cache_flush_d_inval_i(void *start, void *end) { #ifdef __arm__ size_t len = (char *)end - (char *)start; + (void)len; #if defined(__BLACKBERRY_QNX__) msync(start, end - start, MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE); #elif defined(__MACH__) @@ -435,14 +436,25 @@ void plat_munmap(void *ptr, size_t size) } #endif +// if NULL is returned, static buffer is used +void *plat_mem_get_for_drc(size_t size) +{ + void *mem = NULL; +#ifdef VITA + sceKernelGetMemBlockBase(sceBlock, &mem); +#endif + return mem; +} + int plat_mem_set_exec(void *ptr, size_t size) { + int ret = -1; #ifdef _WIN32 - int ret = VirtualProtect(ptr,size,PAGE_EXECUTE_READWRITE,0); + ret = VirtualProtect(ptr, size, PAGE_EXECUTE_READWRITE, 0); if (ret == 0 && log_cb) - log_cb(RETRO_LOG_ERROR, "mprotect(%p, %zd) failed: %d\n", ptr, size, 0); + log_cb(RETRO_LOG_ERROR, "VirtualProtect(%p, %d) failed: %d\n", ptr, (int)size, + GetLastError()); #elif defined(_3DS) - int ret = -1; if (ctr_svchack_successful) { unsigned int currentHandle; @@ -461,9 +473,9 @@ int plat_mem_set_exec(void *ptr, size_t size) } #elif defined(VITA) - int ret = sceKernelOpenVMDomain(); + ret = sceKernelOpenVMDomain(); #else - int ret = mprotect(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC); + ret = mprotect(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret != 0 && log_cb) log_cb(RETRO_LOG_ERROR, "mprotect(%p, %zd) failed: %d\n", ptr, size, errno); #endif @@ -472,6 +484,8 @@ int plat_mem_set_exec(void *ptr, size_t size) void emu_video_mode_change(int start_line, int line_count, int is_32cols) { + struct retro_system_av_info av_info; + memset(vout_buf, 0, 320 * 240 * 2); vout_width = is_32cols ? 256 : 320; PicoDrawSetOutBuf(vout_buf, vout_width * 2); @@ -482,7 +496,6 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols) vout_offset = vout_width * start_line; // Update the geometry - struct retro_system_av_info av_info; retro_get_system_av_info(&av_info); environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &av_info); } @@ -512,7 +525,6 @@ void retro_set_environment(retro_environment_t cb) { "picodrive_sprlim", "No sprite limit; disabled|enabled" }, { "picodrive_ramcart", "MegaCD RAM cart; disabled|enabled" }, { "picodrive_region", "Region; Auto|Japan NTSC|Japan PAL|US|Europe" }, - { "picodrive_region_fps", "Region FPS; Auto|NTSC|PAL" }, { "picodrive_aspect", "Core-provided aspect ratio; PAR|4/3|CRT" }, { "picodrive_overscan", "Show Overscan; disabled|enabled" }, #ifdef DRC_SH2 @@ -555,6 +567,8 @@ void retro_get_system_info(struct retro_system_info *info) void retro_get_system_av_info(struct retro_system_av_info *info) { + float common_width; + memset(info, 0, sizeof(*info)); info->timing.fps = Pico.m.pal ? 50 : 60; info->timing.sample_rate = 44100; @@ -563,7 +577,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.max_width = vout_width; info->geometry.max_height = vout_height; - float common_width = vout_width; + common_width = vout_width; if (user_vout_width != 0) common_width = user_vout_width; @@ -959,22 +973,6 @@ static const char *find_bios(int *region, const char *cd_fname) return NULL; } -static void sram_reset() -{ - SRam.data = NULL; - SRam.start = 0; - SRam.end = 0; - SRam.flags = '\0'; - SRam.unused2 = '\0'; - SRam.changed = '\0' ; - SRam.eeprom_type = '\0'; - SRam.unused3 = '\0'; - SRam.eeprom_bit_cl = '\0'; - SRam.eeprom_bit_in = '\0'; - SRam.eeprom_bit_out = '\0'; - SRam.size = 0; -} - bool retro_load_game(const struct retro_game_info *info) { enum media_type_e media_type; @@ -1031,8 +1029,6 @@ bool retro_load_game(const struct retro_game_info *info) { 0 }, }; - sram_reset(); - enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { if (log_cb) @@ -1122,13 +1118,13 @@ void *retro_get_memory_data(unsigned type) if (PicoAHW & PAHW_MCD) data = Pico_mcd->bram; else - data = SRam.data; + data = Pico.sv.data; break; case RETRO_MEMORY_SYSTEM_RAM: if (PicoAHW & PAHW_SMS) - data = Pico.zram; + data = PicoMem.zram; else - data = Pico.ram; + data = PicoMem.ram; break; default: data = NULL; @@ -1151,20 +1147,20 @@ size_t retro_get_memory_size(unsigned type) return 0x2000; if (Pico.m.frame_count == 0) - return SRam.size; + return Pico.sv.size; // if game doesn't write to sram, don't report it to // libretro so that RA doesn't write out zeroed .srm - for (i = 0, sum = 0; i < SRam.size; i++) - sum |= SRam.data[i]; + for (i = 0, sum = 0; i < Pico.sv.size; i++) + sum |= Pico.sv.data[i]; - return (sum != 0) ? SRam.size : 0; + return (sum != 0) ? Pico.sv.size : 0; case RETRO_MEMORY_SYSTEM_RAM: if (PicoAHW & PAHW_SMS) return 0x2000; else - return sizeof(Pico.ram); + return sizeof(PicoMem.ram); default: return 0; @@ -1215,6 +1211,8 @@ static enum input_device input_name_to_val(const char *name) static void update_variables(void) { struct retro_variable var; + int OldPicoRegionOverride; + float old_user_vout_width; var.value = NULL; var.key = "picodrive_input1"; @@ -1244,7 +1242,7 @@ static void update_variables(void) PicoOpt &= ~POPT_EN_MCD_RAMCART; } - int OldPicoRegionOverride = PicoRegionOverride; + OldPicoRegionOverride = PicoRegionOverride; var.value = NULL; var.key = "picodrive_region"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -1260,28 +1258,15 @@ static void update_variables(void) PicoRegionOverride = 8; } - int OldPicoRegionFPSOverride = PicoRegionFPSOverride; - var.value = NULL; - var.key = "picodrive_region_fps"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if (strcmp(var.value, "Auto") == 0) - PicoRegionFPSOverride = 0; - else if (strcmp(var.value, "NTSC") == 0) - PicoRegionFPSOverride = 1; - else if (strcmp(var.value, "PAL") == 0) - PicoRegionFPSOverride = 2; - } - // Update region, fps and sound flags if needed - if (PicoRegionOverride != OldPicoRegionOverride || - PicoRegionFPSOverride != OldPicoRegionFPSOverride) + if (Pico.rom && PicoRegionOverride != OldPicoRegionOverride) { PicoDetectRegion(); PicoLoopPrepare(); PsndRerate(1); } - float old_user_vout_width = user_vout_width; + old_user_vout_width = user_vout_width; var.value = NULL; var.key = "picodrive_aspect"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -1349,13 +1334,6 @@ void retro_run(void) vout_width, vout_height, vout_width * 2); } -static void check_system_specs(void) -{ - /* TODO - set different performance level for 32X - 6 for ARM dynarec, higher for interpreter core */ - unsigned level = 5; - environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); -} - void retro_init(void) { struct retro_log_callback log; @@ -1419,3 +1397,5 @@ void retro_deinit(void) vout_buf = NULL; PicoExit(); } + +// vim:shiftwidth=3:ts=3:expandtab diff --git a/platform/libretro/msvc/msvc-2010/msvc-2010.suo b/platform/libretro/msvc/msvc-2010/msvc-2010.suo deleted file mode 100644 index e2d4612..0000000 Binary files a/platform/libretro/msvc/msvc-2010/msvc-2010.suo and /dev/null differ diff --git a/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj b/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj index b6a7611..e9bde07 100644 --- a/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj +++ b/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj @@ -1,157 +1,183 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {D4156C25-0E30-4407-9198-1F51EF74AA84} - Win32Proj - msvc2010 - - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - false - true - Unicode - - - - - - - - - - - - - true - $(SolutionDir)msvc-2010\$(Configuration)\ - - - false - $(SolutionDir)msvc-2010\$(Configuration)\ - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;%(PreprocessorDefinitions);INLINE=_inline;_CRT_SECURE_NO_WARNINGS;EMU_F68K;_USE_CZ80;NO_ZLIB;FAMEC_NO_GOTOS - CompileAsC - $(SolutionDir)\..\..\..\;$(SolutionDIr)\..\..\..\pico;%(AdditionalIncludeDirectories) - - - Windows - true - libretro.def - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;%(PreprocessorDefinitions);INLINE=_inline;_CRT_SECURE_NO_WARNINGS;EMU_F68K;_USE_CZ80;NO_ZLIB;FAMEC_NO_GOTOS - CompileAsC - $(SolutionDir)\..\..\..\;$(SolutionDIr)\..\..\..\pico;%(AdditionalIncludeDirectories) - - - Windows - true - true - true - libretro.def - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + + {D4156C25-0E30-4407-9198-1F51EF74AA84} + Win32Proj + msvc2010 + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + true + $(SolutionDir)msvc-2010\$(Configuration)\ + + + false + $(SolutionDir)msvc-2010\$(Configuration)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;EMU_F68K;_USE_CZ80;FAMEC_NO_GOTOS + CompileAsC + $(SolutionDir)\..\..\..\;$(SolutionDIr)\..\..\..\pico;$(SolutionDIr)\..\..\..\zlib;%(AdditionalIncludeDirectories) + 4018;4090;4101;4146;4244 + + + Windows + true + libretro.def + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;EMU_F68K;_USE_CZ80;FAMEC_NO_GOTOS + CompileAsC + $(SolutionDir)\..\..\..\;$(SolutionDIr)\..\..\..\pico;$(SolutionDIr)\..\..\..\zlib;%(AdditionalIncludeDirectories) + 4018;4090;4101;4146;4244 + + + Windows + true + true + true + libretro.def + + + + + + + + + + + $(IntDir)\32x\ + $(IntDir)\32x\ + + + $(IntDir)\32x\ + $(IntDir)\32x\ + + + + + + + + $(IntDir)\svp\ + $(IntDir)\svp\ + + + + + + + + + + + + + + $(IntDir)\cd\ + $(IntDir)\cd\ + + + $(IntDir)\cd\ + $(IntDir)\cd\ + + + + $(IntDir)\cd\ + $(IntDir)\cd\ + + + + + + + + + + + + + $(IntDir)\pico\ + $(IntDir)\pico\ + + + $(IntDir)\pico\ + $(IntDir)\pico\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters b/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters index 44573ab..a1c0e0f 100644 --- a/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters +++ b/platform/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters @@ -1,277 +1,277 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {13ad8d51-3614-47ce-9d0d-8eb47a4cfabe} - - - {56e5d1cc-a749-46f0-9c75-e26037b4e2b3} - - - {ab1e9796-fcf3-49c2-92f2-cbce4ad50f7f} - - - {d7cd40e2-d074-4967-84ad-89488a9eed11} - - - {76c63342-13b7-413c-b44b-52ef07b4dccc} - - - {04bd626c-6833-49c7-8256-dc94935efe03} - - - {3b94bd08-c15d-46a4-9672-094f4cafbc06} - - - {403b507e-7278-436e-b8a5-5a0deb70dfae} - - - {27323686-5607-4502-9488-ac65c90e6969} - - - {2e0a2f96-c25d-473e-9456-5e25b6eb8036} - - - {a208ee7f-75c1-4ff9-9ed5-ea2d42832fc6} - - - {04862576-b191-4769-a0f8-bb6400cfa861} - - - {337acc4a-3fe4-4547-b655-058d31318ffc} - - - {63c3bec2-54b1-4831-a420-5e1aa120738b} - - - {85be1810-42b8-4ec7-bbd5-6c7d1dc5b763} - - - {055bac11-1f11-4fe7-be7b-09ebaeab74d5} - - - {dd1911b8-6d08-42aa-ab21-0ba1154613e1} - - - {a635c355-0290-4923-84c6-8290ea8b0065} - - - - - Source Files\platform\libretro - - - Source Files\platform\common - - - Source Files\platform\common - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\zlib - - - Source Files\unzip - - - Source Files\unzip - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\cd - - - Source Files\pico\32x - - - Source Files\pico\32x - - - Source Files\pico\32x - - - Source Files\pico\32x - - - Source Files\pico\carthw - - - Source Files\pico\carthw\svp - - - Source Files\pico\carthw\svp - - - Source Files\pico\carthw\svp - - - Source Files\pico\sound - - - Source Files\pico\sound - - - Source Files\pico\sound - - - Source Files\pico\sound - - - Source Files\cpu\famec - - - Source Files\cpu\cz80 - - - Source Files\cpu\drc - - - Source Files\cpu\sh2 - - - Source Files\cpu\sh2\mame - - - Source Files - - - Source Files\pico\pico - - - Source Files\pico\pico - - - Source Files\pico\pico - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {13ad8d51-3614-47ce-9d0d-8eb47a4cfabe} + + + {56e5d1cc-a749-46f0-9c75-e26037b4e2b3} + + + {ab1e9796-fcf3-49c2-92f2-cbce4ad50f7f} + + + {d7cd40e2-d074-4967-84ad-89488a9eed11} + + + {76c63342-13b7-413c-b44b-52ef07b4dccc} + + + {04bd626c-6833-49c7-8256-dc94935efe03} + + + {3b94bd08-c15d-46a4-9672-094f4cafbc06} + + + {403b507e-7278-436e-b8a5-5a0deb70dfae} + + + {27323686-5607-4502-9488-ac65c90e6969} + + + {2e0a2f96-c25d-473e-9456-5e25b6eb8036} + + + {a208ee7f-75c1-4ff9-9ed5-ea2d42832fc6} + + + {04862576-b191-4769-a0f8-bb6400cfa861} + + + {337acc4a-3fe4-4547-b655-058d31318ffc} + + + {63c3bec2-54b1-4831-a420-5e1aa120738b} + + + {85be1810-42b8-4ec7-bbd5-6c7d1dc5b763} + + + {055bac11-1f11-4fe7-be7b-09ebaeab74d5} + + + {dd1911b8-6d08-42aa-ab21-0ba1154613e1} + + + {a635c355-0290-4923-84c6-8290ea8b0065} + + + + + Source Files\platform\libretro + + + Source Files\platform\common + + + Source Files\platform\common + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\unzip + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\cd + + + Source Files\pico\32x + + + Source Files\pico\32x + + + Source Files\pico\32x + + + Source Files\pico\32x + + + Source Files\pico\carthw + + + Source Files\pico\carthw + + + Source Files\pico\carthw\svp + + + Source Files\pico\carthw\svp + + + Source Files\pico\carthw\svp + + + Source Files\pico\sound + + + Source Files\pico\sound + + + Source Files\pico\sound + + + Source Files\pico\sound + + + Source Files\cpu\famec + + + Source Files\cpu\cz80 + + + Source Files\cpu\drc + + + Source Files\cpu\sh2 + + + Source Files\cpu\sh2\mame + + + Source Files\pico\pico + + + Source Files\pico\pico + + + Source Files\pico\pico + + + Source Files\pico\32x + + \ No newline at end of file diff --git a/platform/libretro/psp/draw_amips.s b/platform/libretro/psp/draw_amips.s deleted file mode 100644 index fa7906e..0000000 --- a/platform/libretro/psp/draw_amips.s +++ /dev/null @@ -1,1756 +0,0 @@ -#* -#* several drawing related functions for Allegrex MIPS -#* (C) notaz, 2007-2008 -#* -#* This work is licensed under the terms of MAME license. -#* See COPYING file in the top-level directory. -#* -#* this is highly specialized, be careful if changing related C code! -#* - -.set noreorder # don't reorder any instructions -.set noat # don't use $at - -.text -.align 4 - -# void amips_clut(unsigned short *dst, unsigned char *src, unsigned short *pal, int count) - -.global amips_clut - -amips_clut: - srl $a3, 2 -amips_clut_loop: - lbu $t0, 0($a1) # tried lw here, no improvement noticed - lbu $t1, 1($a1) - lbu $t2, 2($a1) - lbu $t3, 3($a1) - sll $t0, 1 - sll $t1, 1 - sll $t2, 1 - sll $t3, 1 - addu $t0, $a2 - addu $t1, $a2 - addu $t2, $a2 - addu $t3, $a2 - lhu $t0, 0($t0) - lhu $t1, 0($t1) - lhu $t2, 0($t2) - lhu $t3, 0($t3) - ins $t0, $t1, 16, 16 # ins rt, rs, pos, size - Insert size bits starting - ins $t2, $t3, 16, 16 # from the LSB of rs into rt starting at position pos - sw $t0, 0($a0) - sw $t2, 4($a0) - addiu $a0, 8 - addiu $a3, -1 - bnez $a3, amips_clut_loop - addiu $a1, 4 - jr $ra - nop - - -.global amips_clut_6bit - -amips_clut_6bit: - srl $a3, 2 - li $t4, 0 - li $t5, 0 - li $t6, 0 - li $t7, 0 -amips_clut_loop6: - lbu $t0, 0($a1) # tried lw here, no improvement noticed - lbu $t1, 1($a1) - lbu $t2, 2($a1) - lbu $t3, 3($a1) - ins $t4, $t0, 1, 6 - ins $t5, $t1, 1, 6 - ins $t6, $t2, 1, 6 - ins $t7, $t3, 1, 6 - addu $t0, $t4, $a2 - addu $t1, $t5, $a2 - addu $t2, $t6, $a2 - addu $t3, $t7, $a2 - lhu $t0, 0($t0) - lhu $t1, 0($t1) - lhu $t2, 0($t2) - lhu $t3, 0($t3) - ins $t0, $t1, 16, 16 # ins rt, rs, pos, size - Insert size bits starting - ins $t2, $t3, 16, 16 # from the LSB of rs into rt starting at position pos - sw $t0, 0($a0) - sw $t2, 4($a0) - addiu $a0, 8 - addiu $a3, -1 - bnez $a3, amips_clut_loop6 - addiu $a1, 4 - jr $ra - nop - - -# $a0 - pd, $a1 - tile word, $a2 - pal -# ext rt, rs, pos, size // Extract size bits from position pos in rs and store in rt - -.macro TilePixelPrep shift dreg offs -.if \shift - ext \dreg, $a1, \shift, 4 -.else - andi \dreg, $a1, 0xf -.endif -.if \offs - sltu $t8, $0, \dreg - ins $t9, $t8, \offs, 1 -.else - sltu $t9, $0, \dreg -.endif -.endm - -.macro TileStartCode - sll $a1, $a1, 1 - lui $t1, %hi(Pico+0x10000) - addu $a1, $a1, $t1 - lw $a1, %lo(Pico+0x10000)($a1) # Pico.vram + addr - beqz $a1, TileEmpty - rotr $t1, $a1, 4 - beq $t1, $a1, SingleColor - and $v0, $0 # not empty tile -.endm - -.macro TileEndCode - xori $t8, $t9, 0xff - beqz $t8, tile11111111 # common case - lui $v1, %hi(HighCol) - lui $t8, %hi(TileTable) - ins $t8, $t9, 2, 8 - lw $t8, %lo(TileTable)($t8) - lw $v1, %lo(HighCol)($v1) - jr $t8 - addu $a0, $v1 -.endm - - -.global TileNorm - -TileNorm: - TileStartCode - TilePixelPrep 12, $t0, 0 - TilePixelPrep 8, $t1, 1 - TilePixelPrep 4, $t2, 2 - TilePixelPrep 0, $t3, 3 - TilePixelPrep 28, $t4, 4 - TilePixelPrep 24, $t5, 5 - TilePixelPrep 20, $t6, 6 - TilePixelPrep 16, $t7, 7 - TileEndCode - - -.global TileFlip - -TileFlip: - TileStartCode - TilePixelPrep 16, $t0, 0 - TilePixelPrep 20, $t1, 1 - TilePixelPrep 24, $t2, 2 - TilePixelPrep 28, $t3, 3 - TilePixelPrep 0, $t4, 4 - TilePixelPrep 4, $t5, 5 - TilePixelPrep 8, $t6, 6 - TilePixelPrep 12, $t7, 7 - TileEndCode - - -SingleColor: - lui $t9, %hi(HighCol) - lw $t9, %lo(HighCol)($t9) - andi $t0, $a1, 0xf - or $t0, $t0, $a2 - addu $a0, $t9 - sb $t0, 0($a0) - sb $t0, 1($a0) - sb $t0, 2($a0) - sb $t0, 3($a0) - sb $t0, 4($a0) - sb $t0, 5($a0) - sb $t0, 6($a0) - jr $ra - sb $t0, 7($a0) - -TileEmpty: - jr $ra - or $v0, $0, 1 # empty tile - -tile11111111: - lw $v1, %lo(HighCol)($v1) - or $t0, $t0, $a2 - addu $a0, $v1 - sb $t0, 0($a0) -tile11111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile11110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile11100000: - or $t5, $t5, $a2 - sb $t5, 5($a0) -tile11000000: - or $t6, $t6, $a2 - sb $t6, 6($a0) -tile10000000: - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile11010000: - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile11001000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile11000100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile11000010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile11000001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t6, $t6, $a2 - sb $t6, 6($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile10110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile10100000: - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile10010000: - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile10001000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile10000100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile10000010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile10000001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t7, $t7, $a2 - jr $ra - sb $t7, 7($a0) -tile01111111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile01110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile01100000: - or $t5, $t5, $a2 - sb $t5, 5($a0) -tile01000000: - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile00000000: -tile01111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - sb $t5, 5($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile01010000: - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile01001000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile01000100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile01000010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile01000001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t6, $t6, $a2 - jr $ra - sb $t6, 6($a0) -tile00111111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00111110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00111100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00111000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile00110000: - or $t4, $t4, $a2 - sb $t4, 4($a0) -tile00100000: - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00111101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00111011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00111010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00111001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00110110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00110100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00110010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00110001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - sb $t4, 4($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00101110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00101100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00101000: - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00101010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00101001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00100110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00100100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00100010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00100001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t5, $t5, $a2 - jr $ra - sb $t5, 5($a0) -tile00011111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00011110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00011100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00011000: - or $t3, $t3, $a2 - sb $t3, 3($a0) -tile00010000: - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00011101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00011011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00011010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00011001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - sb $t3, 3($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00010110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00010100: - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00010010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00010001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t4, $t4, $a2 - jr $ra - sb $t4, 4($a0) -tile00001111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00001110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00001100: - or $t2, $t2, $a2 - sb $t2, 2($a0) -tile00001000: - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00001101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - sb $t2, 2($a0) - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00001011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00001010: - or $t1, $t1, $a2 - sb $t1, 1($a0) - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00001001: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t3, $t3, $a2 - jr $ra - sb $t3, 3($a0) -tile00000111: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00000110: - or $t1, $t1, $a2 - sb $t1, 1($a0) -tile00000100: - or $t2, $t2, $a2 - jr $ra - sb $t2, 2($a0) -tile00000101: - or $t0, $t0, $a2 - sb $t0, 0($a0) - or $t2, $t2, $a2 - jr $ra - sb $t2, 2($a0) -tile00000011: - or $t0, $t0, $a2 - sb $t0, 0($a0) -tile00000010: - or $t1, $t1, $a2 - jr $ra - sb $t1, 1($a0) -tile00000001: - or $t0, $t0, $a2 - jr $ra - sb $t0, 0($a0) - -.data -.align 4 - -TileTable: - .long 000000000000, tile00000001, tile00000010, tile00000011, tile00000100, tile00000101, tile00000110, tile00000111 - .long tile00001000, tile00001001, tile00001010, tile00001011, tile00001100, tile00001101, tile00001110, tile00001111 - .long tile00010000, tile00010001, tile00010010, tile00010011, tile00010100, tile00010101, tile00010110, tile00010111 - .long tile00011000, tile00011001, tile00011010, tile00011011, tile00011100, tile00011101, tile00011110, tile00011111 - .long tile00100000, tile00100001, tile00100010, tile00100011, tile00100100, tile00100101, tile00100110, tile00100111 - .long tile00101000, tile00101001, tile00101010, tile00101011, tile00101100, tile00101101, tile00101110, tile00101111 - .long tile00110000, tile00110001, tile00110010, tile00110011, tile00110100, tile00110101, tile00110110, tile00110111 - .long tile00111000, tile00111001, tile00111010, tile00111011, tile00111100, tile00111101, tile00111110, tile00111111 - .long tile01000000, tile01000001, tile01000010, tile01000011, tile01000100, tile01000101, tile01000110, tile01000111 - .long tile01001000, tile01001001, tile01001010, tile01001011, tile01001100, tile01001101, tile01001110, tile01001111 - .long tile01010000, tile01010001, tile01010010, tile01010011, tile01010100, tile01010101, tile01010110, tile01010111 - .long tile01011000, tile01011001, tile01011010, tile01011011, tile01011100, tile01011101, tile01011110, tile01011111 - .long tile01100000, tile01100001, tile01100010, tile01100011, tile01100100, tile01100101, tile01100110, tile01100111 - .long tile01101000, tile01101001, tile01101010, tile01101011, tile01101100, tile01101101, tile01101110, tile01101111 - .long tile01110000, tile01110001, tile01110010, tile01110011, tile01110100, tile01110101, tile01110110, tile01110111 - .long tile01111000, tile01111001, tile01111010, tile01111011, tile01111100, tile01111101, tile01111110, tile01111111 - .long tile10000000, tile10000001, tile10000010, tile10000011, tile10000100, tile10000101, tile10000110, tile10000111 - .long tile10001000, tile10001001, tile10001010, tile10001011, tile10001100, tile10001101, tile10001110, tile10001111 - .long tile10010000, tile10010001, tile10010010, tile10010011, tile10010100, tile10010101, tile10010110, tile10010111 - .long tile10011000, tile10011001, tile10011010, tile10011011, tile10011100, tile10011101, tile10011110, tile10011111 - .long tile10100000, tile10100001, tile10100010, tile10100011, tile10100100, tile10100101, tile10100110, tile10100111 - .long tile10101000, tile10101001, tile10101010, tile10101011, tile10101100, tile10101101, tile10101110, tile10101111 - .long tile10110000, tile10110001, tile10110010, tile10110011, tile10110100, tile10110101, tile10110110, tile10110111 - .long tile10111000, tile10111001, tile10111010, tile10111011, tile10111100, tile10111101, tile10111110, tile10111111 - .long tile11000000, tile11000001, tile11000010, tile11000011, tile11000100, tile11000101, tile11000110, tile11000111 - .long tile11001000, tile11001001, tile11001010, tile11001011, tile11001100, tile11001101, tile11001110, tile11001111 - .long tile11010000, tile11010001, tile11010010, tile11010011, tile11010100, tile11010101, tile11010110, tile11010111 - .long tile11011000, tile11011001, tile11011010, tile11011011, tile11011100, tile11011101, tile11011110, tile11011111 - .long tile11100000, tile11100001, tile11100010, tile11100011, tile11100100, tile11100101, tile11100110, tile11100111 - .long tile11101000, tile11101001, tile11101010, tile11101011, tile11101100, tile11101101, tile11101110, tile11101111 - .long tile11110000, tile11110001, tile11110010, tile11110011, tile11110100, tile11110101, tile11110110, tile11110111 - .long tile11111000, tile11111001, tile11111010, tile11111011, tile11111100, tile11111101, tile11111110, tile11111111 - -# vim:filetype=mips diff --git a/platform/linux/emu.c b/platform/linux/emu.c index d90d610..aee8d44 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -31,7 +31,9 @@ void pemu_validate_config(void) { extern int PicoOpt; // PicoOpt &= ~POPT_EXT_FM; +#ifndef __arm__ PicoOpt &= ~POPT_EN_DRC; +#endif } static void draw_cd_leds(void) @@ -201,3 +203,7 @@ void plat_wait_till_us(unsigned int us_to) } } +void *plat_mem_get_for_drc(size_t size) +{ + return NULL; +} diff --git a/platform/pandora/Makefile b/platform/pandora/Makefile index 4240897..a181e09 100644 --- a/platform/pandora/Makefile +++ b/platform/pandora/Makefile @@ -15,8 +15,8 @@ all: rel ../../tools/textfilter: ../../tools/textfilter.c make -C ../../tools/ -readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog - ../../tools/textfilter ../base_readme.txt $@ PANDORA +#readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog +# ../../tools/textfilter ../base_readme.txt $@ PANDORA /tmp/PicoDrive.pxml: PicoDrive.pxml.template FORCE ./make_pxml.sh $< $@ @@ -24,7 +24,7 @@ readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog rel: ../../PicoDrive PicoDrive.sh picorestore \ PicoDrive.png PicoDrive_p.png \ ../../pico/carthw.cfg skin \ - readme.txt /tmp/PicoDrive.pxml + ../../README /tmp/PicoDrive.pxml rm -rf out mkdir out cp -r $^ out/ diff --git a/platform/pandora/PicoDrive.pxml.template b/platform/pandora/PicoDrive.pxml.template index 220d48e..635d59c 100644 --- a/platform/pandora/PicoDrive.pxml.template +++ b/platform/pandora/PicoDrive.pxml.template @@ -33,7 +33,7 @@ - + diff --git a/platform/pandora/make_pxml.sh b/platform/pandora/make_pxml.sh index 2267c14..3fd03a2 100755 --- a/platform/pandora/make_pxml.sh +++ b/platform/pandora/make_pxml.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e verfile=../common/version.h diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 8f8eac6..9cd5fc5 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -74,6 +74,7 @@ static struct in_default_bind in_evdev_defbinds[] = { KEY_S, IN_BINDTYPE_PLAYER12, GBTN_B }, { KEY_D, IN_BINDTYPE_PLAYER12, GBTN_C }, { KEY_ENTER, IN_BINDTYPE_PLAYER12, GBTN_START }, + { KEY_R, IN_BINDTYPE_EMU, PEVB_RESET }, { KEY_F, IN_BINDTYPE_EMU, PEVB_FF }, { KEY_BACKSPACE,IN_BINDTYPE_EMU, PEVB_FF }, { KEY_BACKSLASH,IN_BINDTYPE_EMU, PEVB_MENU }, diff --git a/platform/psp/emu.c b/platform/psp/emu.c index dd4381b..8373a21 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -225,7 +225,7 @@ static void do_pal_update(int allow_sh, int allow_as) } else if (allow_as && (Pico.est.rendstatus & PDRAW_SPR_LO_ON_HI)) { - memcpy32((int *)dpal+0x80/2, (void *)localPal, 0x40*2/4); + memcpy(dpal + 0x80/2, localPal, 0x40*2); } } diff --git a/tools/mkoffsets.c b/tools/mkoffsets.c index a5c475f..7e57383 100644 --- a/tools/mkoffsets.c +++ b/tools/mkoffsets.c @@ -3,10 +3,25 @@ #include "../pico/pico_int.h" -#define DUMP(f, field) \ +#define DUMP(f, prefix, type, field) \ fprintf(f, "#define %-20s 0x%02x\n", \ - "OFS_" #field, \ - (int)offsetof(struct PicoEState, field)) + prefix #field, (int)offsetof(type, field)) + +#define DUMP_P(f, field) \ + fprintf(f, "#define %-20s 0x%04x\n", \ + "OFS_Pico_" #field, (char *)&p.field - (char *)&p) + +#define DUMP_PS(f, s1, field) \ + fprintf(f, "#define %-20s 0x%04x\n", \ + "OFS_Pico_" #s1 "_" #field, (char *)&p.s1.field - (char *)&p) + +#define DUMP_EST(f, field) \ + DUMP(f, "OFS_EST_", struct PicoEState, field) + +#define DUMP_PMEM(f, field) \ + DUMP(f, "OFS_PMEM_", struct PicoMem, field) + +extern struct Pico p; int main(int argc, char *argv[]) { @@ -21,16 +36,33 @@ int main(int argc, char *argv[]) } fprintf(f, "/* autogenerated by %s, do not edit */\n", argv[0]); - DUMP(f, DrawScanline); - DUMP(f, rendstatus); - DUMP(f, DrawLineDest); - DUMP(f, HighCol); - DUMP(f, HighPreSpr); - DUMP(f, Pico_video); - DUMP(f, Pico_vram); - DUMP(f, PicoOpt); - DUMP(f, Draw2FB); - DUMP(f, HighPal); + DUMP_PS(f, video, reg); + DUMP_PS(f, m, rotate); + DUMP_PS(f, m, z80Run); + DUMP_PS(f, m, dirtyPal); + DUMP_PS(f, m, hardware); + DUMP_PS(f, m, z80_reset); + DUMP_PS(f, m, sram_reg); + DUMP_P (f, sv); + DUMP_PS(f, sv, data); + DUMP_PS(f, sv, start); + DUMP_PS(f, sv, end); + DUMP_PS(f, sv, flags); + DUMP_P (f, rom); + DUMP_P (f, romsize); + DUMP_EST(f, DrawScanline); + DUMP_EST(f, rendstatus); + DUMP_EST(f, DrawLineDest); + DUMP_EST(f, HighCol); + DUMP_EST(f, HighPreSpr); + DUMP_EST(f, Pico); + DUMP_EST(f, PicoMem_vram); + DUMP_EST(f, PicoMem_cram); + DUMP_EST(f, PicoOpt); + DUMP_EST(f, Draw2FB); + DUMP_EST(f, HighPal); + DUMP_PMEM(f, vram); + DUMP_PMEM(f, vsram); fclose(f); return 0;