diff --git a/Makefile b/Makefile
index 90ba4945..8b70c763 100644
--- a/Makefile
+++ b/Makefile
@@ -872,6 +872,24 @@ ifeq ($(HAVE_ARMv6),1)
CFLAGS += -DHAVE_ARMv6
endif
+# threads (libretro-common rthreads), as the other libretro cores do (beetle-psx):
+# on by default, off where there is no thread library, and on the MSVC builds
+# (the ST-V threaded video needs MSVC 2015's thread-local storage, the
+# buildbot's MSVC lanes are 2005 and 2010: nothing would use the threads)
+HAVE_THREADS ?= 1
+ifneq (,$(filter $(platform), emscripten linux-portable ngc wii wiiu ps2 ps3 psl1ght psp1 ctr vita))
+ HAVE_THREADS = 0
+endif
+ifneq (,$(findstring msvc,$(platform)))
+ HAVE_THREADS = 0
+endif
+ifeq ($(HAVE_THREADS),1)
+ # pthreads are in the C library on Darwin and Android, Windows uses its own threads
+ ifeq (,$(findstring msvc,$(platform))$(findstring android,$(platform))$(findstring ios,$(platform))$(findstring tvos,$(platform))$(filter osx win,$(platform)))
+ LIBS += -lpthread
+ endif
+endif
+
# include the various .mak files
ifneq (,$(filter $(INCLUDE_DRV),all))
include Makefile.common
diff --git a/Makefile.common b/Makefile.common
index eda6b7a9..70849af0 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -532,7 +532,7 @@ SOURCES_C += \
$(CORE_DIR)/vidhrdw/segavdp.c $(CORE_DIR)/vidhrdw/segac2_vidhrdw.c $(CORE_DIR)/machine/megadriv.c $(CORE_DIR)/drivers/segac2.c $(CORE_DIR)/drivers/megaplay.c $(CORE_DIR)/drivers/megatech.c $(CORE_DIR)/drivers/megadriv_acbl.c $(CORE_DIR)/drivers/megadriv_ybox.c $(CORE_DIR)/drivers/megadriv_sunmix.c \
$(CORE_DIR)/drivers/stv.c $(CORE_DIR)/drivers/stvhacks.c $(CORE_DIR)/machine/stvcd.c \
$(CORE_DIR)/machine/scudsp.c \
- $(CORE_DIR)/vidhrdw/stvvdp1_vidhrdw.c $(CORE_DIR)/vidhrdw/stvvdp2_vidhrdw.c \
+ $(CORE_DIR)/vidhrdw/stvvid.c \
$(CORE_DIR)/vidhrdw/deniam_vidhrdw.c $(CORE_DIR)/drivers/deniam.c \
$(CORE_DIR)/machine/btime_machine.c $(CORE_DIR)/vidhrdw/btime_vidhrdw.c $(CORE_DIR)/drivers/btime.c \
$(CORE_DIR)/machine/decocass_machine.c $(CORE_DIR)/vidhrdw/decocass_vidhrdw.c $(CORE_DIR)/drivers/decocass.c \
@@ -2852,6 +2852,12 @@ SOURCES_C += \
# sljit: run-time code generator of the MIPS recompilers (empty where they are not supported)
SOURCES_C += $(CORE_DIR)/lib/sljit/sljit_mame.c
+# threads (libretro-common rthreads, set by the platform: see Makefile): the ST-V threaded video option
+ifeq ($(HAVE_THREADS),1)
+COREDEFINES += -DHAVE_THREADS
+SOURCES_C += $(LIBRETRO_COMM_DIR)/rthreads/rthreads.c
+endif
+
ifeq ($(STATIC_LINKING),1)
else
SOURCES_C += \
diff --git a/jni/Android.mk b/jni/Android.mk
index 4e65a9b2..3099ed9b 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -3,6 +3,9 @@ LOCAL_PATH := $(call my-dir)
ROOT_DIR := $(LOCAL_PATH)/..
CORE_DIR := $(ROOT_DIR)/src
+# threads: in bionic's C library
+HAVE_THREADS := 1
+
include $(ROOT_DIR)/Makefile.common
COREFLAGS := $(DEFS) $(COREDEFINES) $(CPUDEFS) $(SOUNDDEFS) $(ASMDEFS) $(DBGDEFS) -ffast-math -funroll-loops -DANDROID -DHAVE_ZLIB $(INCFLAGS)
diff --git a/metadata/mame2003-plus.xml b/metadata/mame2003-plus.xml
index 1267a0e7..27c0fb1f 100644
--- a/metadata/mame2003-plus.xml
+++ b/metadata/mame2003-plus.xml
@@ -204980,7 +204980,7 @@
-
+
@@ -204993,7 +204993,7 @@
-
+
@@ -205060,7 +205060,7 @@
-
+
Baku Baku Animal
@@ -205078,7 +205078,7 @@
-
+
@@ -205087,7 +205087,7 @@
-
+
@@ -205154,7 +205154,7 @@
-
+
Columns 97
@@ -205172,14 +205172,14 @@
-
+
-
+
@@ -205276,7 +205276,7 @@
-
+
@@ -205372,7 +205372,7 @@
-
+
@@ -205443,7 +205443,7 @@
Decathlete
- 1995
+ 1996
Sega
@@ -205457,7 +205457,7 @@
-
+
@@ -205467,7 +205467,7 @@
-
+
@@ -205534,7 +205534,7 @@
-
+
Die Hard Arcade (US)
@@ -205552,7 +205552,7 @@
-
+
@@ -205561,7 +205561,7 @@
-
+
@@ -205646,7 +205646,7 @@
-
+
@@ -205655,7 +205655,7 @@
-
+
@@ -205722,7 +205722,7 @@
-
+
Ejihon Tantei Jimusyo
@@ -205740,7 +205740,7 @@
-
+
@@ -205750,7 +205750,7 @@
-
+
@@ -205847,7 +205847,7 @@
-
+
@@ -205914,7 +205914,7 @@
-
+
Final Fight Revenge
@@ -205932,6 +205932,7 @@
+
@@ -205943,7 +205944,7 @@
-
+
@@ -206010,7 +206011,7 @@
-
+
Funky Head Boxers
@@ -206028,7 +206029,7 @@
-
+
@@ -206038,11 +206039,12 @@
+
-
+
@@ -206109,7 +206111,7 @@
-
+
Find Love
@@ -206127,7 +206129,7 @@
-
+
@@ -206140,11 +206142,12 @@
+
-
+
@@ -206211,9 +206214,9 @@
-
+
-
+
Final Arch (Japan)
1995
Sega
@@ -206229,7 +206232,7 @@
-
+
@@ -206238,7 +206241,7 @@
-
+
@@ -206305,7 +206308,7 @@
-
+
Golden Axe - The Duel
@@ -206323,7 +206326,7 @@
-
+
@@ -206334,7 +206337,7 @@
-
+
@@ -206401,7 +206404,7 @@
-
+
Guardian Force
@@ -206429,7 +206432,7 @@
-
+
@@ -206527,7 +206530,7 @@
-
+
@@ -206594,7 +206597,7 @@
-
+
Hanagumi Taisen Columns - Sakura Wars
@@ -206628,7 +206631,7 @@
-
+
@@ -206713,7 +206716,7 @@
-
+
@@ -206725,7 +206728,7 @@
-
+
@@ -206792,7 +206795,7 @@
-
+
Pro Mahjong Kiwame S
@@ -206810,15 +206813,16 @@
-
+
+
-
+
@@ -206885,7 +206889,7 @@
-
+
Maru-Chan de Goo!
@@ -206903,7 +206907,7 @@
-
+
@@ -206916,7 +206920,7 @@
-
+
@@ -206983,7 +206987,7 @@
-
+
Virtual Mahjong 2 - My Fair Lady
@@ -207009,11 +207013,12 @@
+
-
+
@@ -207080,7 +207085,7 @@
-
+
Othello Shiyouyo
@@ -207107,7 +207112,7 @@
-
+
@@ -207174,7 +207179,7 @@
-
+
Pebble Beach - The Great Shot
@@ -207192,7 +207197,7 @@
-
+
@@ -207201,7 +207206,7 @@
-
+
@@ -207268,7 +207273,7 @@
-
+
Princess Clara Daisakusen
@@ -207295,7 +207300,7 @@
-
+
@@ -207380,7 +207385,7 @@
-
+
@@ -207393,7 +207398,7 @@
-
+
@@ -207487,7 +207492,7 @@
-
+
@@ -207554,7 +207559,7 @@
-
+
Sando-R
@@ -207572,7 +207577,7 @@
-
+
@@ -207581,7 +207586,7 @@
-
+
@@ -207668,15 +207673,15 @@
-
-
-
-
+
+
+
+
-
+
@@ -207745,9 +207750,9 @@
-
+
Taisen Tanto-R Sashissu!!
- 1996
+ 1998
Sega
@@ -207761,7 +207766,7 @@
-
+
@@ -207772,7 +207777,7 @@
-
+
@@ -207839,7 +207844,967 @@
-
+
+
+
+ DaeJeon! SanJeon SuJeon
+ 1999
+ Sega / Deniam
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Critter Crusher
+ 1995
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tatacot (Japan)
+ 1995
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Danchi de Quiz: Okusan Yontaku Desuyo!
+ 2000
+ Altron
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Microman Battle Charge
+ 1999
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hashire Patrol Car
+ 2001
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sky Challenger
+ 2000
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Nerae! Super Goal
+ 1998
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Technical Bowling
+ 1997
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Wanpaku Safari
+ 1998
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Sea Bass Fishing
@@ -207857,7 +208822,7 @@
-
+
@@ -207866,11 +208831,12 @@
+
-
+
@@ -207937,7 +208903,7 @@
-
+
Shanghai - The Great Wall - Shanghai Triple Threat
@@ -207961,7 +208927,7 @@
-
+
@@ -208049,11 +209015,12 @@
+
-
+
@@ -208122,7 +209089,7 @@
-
+
Super Major League (US)
1995
Sega
@@ -208138,7 +209105,7 @@
-
+
@@ -208148,7 +209115,7 @@
-
+
@@ -208215,7 +209182,7 @@
-
+
Soukyugurentai - Terra Diver
@@ -208233,7 +209200,7 @@
-
+
@@ -208242,7 +209209,7 @@
-
+
@@ -208309,7 +209276,7 @@
-
+
Steep Slope Sliders
@@ -208327,17 +209294,18 @@
-
+
+
-
+
@@ -208404,7 +209372,7 @@
-
+
Suikoenbu
@@ -208422,7 +209390,7 @@
-
+
@@ -208435,7 +209403,7 @@
-
+
@@ -208502,7 +209470,7 @@
-
+
Tecmo World Cup '98
@@ -208520,16 +209488,16 @@
-
-
-
-
-
+
+
+
+
+
-
+
@@ -208596,7 +209564,7 @@
-
+
Virtua Fighter Kids
@@ -208614,7 +209582,7 @@
-
+
@@ -208628,7 +209596,7 @@
-
+
@@ -208695,7 +209663,7 @@
-
+
Virtua Fighter Remix
@@ -208713,7 +209681,7 @@
-
+
@@ -208724,7 +209692,7 @@
-
+
@@ -208791,7 +209759,7 @@
-
+
Virtual Mahjong
@@ -208817,11 +209785,12 @@
+
-
+
@@ -208888,7 +209857,7 @@
-
+
Winter Heat
@@ -208906,7 +209875,7 @@
-
+
@@ -208918,7 +209887,7 @@
-
+
@@ -208985,7 +209954,7 @@
-
+
Zen Nippon Pro-Wrestling Featuring Virtua
@@ -209003,7 +209972,7 @@
-
+
@@ -209017,7 +209986,7 @@
-
+
@@ -209084,7 +210053,205 @@
-
+
+
+
+ All Japan Pro-Wrestling Featuring Virtua (Taiwan)
+ 1997
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ All Japan Pro-Wrestling Featuring Virtua (English translation)
+ 1997
+ bootleg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Danchi de Hanafuda
@@ -209111,7 +210278,7 @@
-
+
@@ -209178,7 +210345,7 @@
-
+
Mausuke no Ojama the World
@@ -209196,7 +210363,7 @@
-
+
@@ -209208,7 +210375,7 @@
-
+
@@ -209296,22 +210463,22 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -209378,7 +210545,7 @@
-
+
Sport Fishing 2
@@ -209400,7 +210567,7 @@
-
+
@@ -209488,7 +210655,7 @@
-
+
diff --git a/src/cpu/sh2/sh2.c b/src/cpu/sh2/sh2.c
index 6175d6c5..a1323605 100644
--- a/src/cpu/sh2/sh2.c
+++ b/src/cpu/sh2/sh2.c
@@ -147,10 +147,23 @@ typedef struct
int is_slave, cpu_number;
data16_t (*opcode_read)(offs_t pc);
data32_t (*dma_read_hook)(UINT32 src, UINT32 dst, data32_t data, int size);
+
+ UINT8 **jit_rpage; /* sh2jit.c: this CPU's page tables for direct reads and writes */
+ UINT8 **jit_wpage;
} SH2;
int sh2_icount;
-static SH2 sh2;
+
+/*
+ The state of the active SH-2 is its own context buffer: switching
+ CPUs (every timeslice, many thousand times a frame on the ST-V with
+ its tight interleave) only moves this pointer instead of copying
+ the whole state out and in. Each CPU's saved state items point into
+ its buffer too, so a state save reads it whether it is active or not.
+*/
+static SH2 sh2_boot; /* before a CPU's buffer is known */
+static SH2 *sh2p = &sh2_boot;
+#define sh2 (*sh2p)
/* Atrocious hack that makes the soldivid music correct*/
@@ -179,6 +192,16 @@ static void sh2_timer_callback(int data);
#define Rn ((opcode>>8)&15)
#define Rm ((opcode>>4)&15)
+
+#ifdef SH2JIT_VERIFY
+extern int sh2_jit_verify_logging;
+void sh2_jit_verify_store(UINT32 address, int size);
+#define SH2JIT_STORE(A, size) do { if (sh2_jit_verify_logging) sh2_jit_verify_store(A, size); if (sh2_jit_code_present) sh2_jit_ram_written((A) & AM, size); } while (0)
+#else
+/* a store over translated code flushes the recompiler's cache */
+#define SH2JIT_STORE(A, size) do { if (sh2_jit_code_present) sh2_jit_ram_written((A) & AM, size); } while (0)
+#endif
+
static INLINE data8_t RB(offs_t A)
{
if (A >= 0xe0000000)
@@ -233,6 +256,7 @@ static INLINE void WB(offs_t A, data8_t V)
if (A >= 0xc0000000)
{
cpu_writemem32bedw(A,V);
+ SH2JIT_STORE(A, 1);
return;
}
@@ -240,6 +264,7 @@ static INLINE void WB(offs_t A, data8_t V)
return;
cpu_writemem32bedw(A & AM,V);
+ SH2JIT_STORE(A, 1);
}
static INLINE void WW(offs_t A, data16_t V)
@@ -253,6 +278,7 @@ static INLINE void WW(offs_t A, data16_t V)
if (A >= 0xc0000000)
{
cpu_writemem32bedw_word(A,V);
+ SH2JIT_STORE(A, 2);
return;
}
@@ -260,6 +286,7 @@ static INLINE void WW(offs_t A, data16_t V)
return;
cpu_writemem32bedw_word(A & AM,V);
+ SH2JIT_STORE(A, 2);
}
static INLINE void WL(offs_t A, data32_t V)
@@ -273,6 +300,7 @@ static INLINE void WL(offs_t A, data32_t V)
if (A >= 0xc0000000)
{
cpu_writemem32bedw_dword(A,V);
+ SH2JIT_STORE(A, 4);
return;
}
@@ -280,6 +308,7 @@ static INLINE void WL(offs_t A, data32_t V)
return;
cpu_writemem32bedw_dword(A & AM,V);
+ SH2JIT_STORE(A, 4);
}
static INLINE void sh2_exception(const char *message, int irqline)
@@ -2291,6 +2320,61 @@ static INLINE void op1111(UINT16 opcode)
NOP();
}
+/* one instruction (in the interpreter's loop and for the recompiler's checks) */
+static INLINE void sh2_dispatch(UINT16 opcode)
+{
+ switch ((opcode >> 12) & 15)
+ {
+ case 0: op0000(opcode); break;
+ case 1: op0001(opcode); break;
+ case 2: op0010(opcode); break;
+ case 3: op0011(opcode); break;
+ case 4: op0100(opcode); break;
+ case 5: op0101(opcode); break;
+ case 6: op0110(opcode); break;
+ case 7: op0111(opcode); break;
+ case 8: op1000(opcode); break;
+ case 9: op1001(opcode); break;
+ case 10: op1010(opcode); break;
+ case 11: op1011(opcode); break;
+ case 12: op1100(opcode); break;
+ case 13: op1101(opcode); break;
+ case 14: op1110(opcode); break;
+ default: op1111(opcode); break;
+ }
+}
+
+static INLINE void sh2_step(void)
+{
+ UINT32 opcode;
+
+ if (sh2.delay)
+ {
+ opcode = sh2.opcode_read ? sh2.opcode_read(sh2.delay) : RW(sh2.delay & AM);
+ change_pc32bedw(sh2.pc & AM);
+ sh2.pc -= 2;
+ }
+ else
+ opcode = sh2.opcode_read ? sh2.opcode_read(sh2.pc) : RW(sh2.pc & AM);
+
+ CALL_MAME_DEBUG;
+
+ sh2.delay = 0;
+ sh2.pc += 2;
+ sh2.ppc = sh2.pc;
+
+ sh2_dispatch(opcode);
+
+ if(sh2.test_irq && !sh2.delay)
+ {
+ CHECK_PENDING_IRQ("mame_sh2_execute");
+ sh2.test_irq = 0;
+ }
+ sh2_icount--;
+}
+
+#include "sh2jit.c"
+
/*****************************************************************************
* MAME CPU INTERFACE
*****************************************************************************/
@@ -2324,6 +2408,10 @@ void sh2_reset(void *param)
sh2.cpu_number = cpu_getactivecpu();
+ /* code and memory handlers may differ after a reset */
+ if (jit_enabled)
+ jit_flush();
+
sh2.pc = RL(0);
sh2.r[15] = RL(4);
sh2.sr = I;
@@ -2335,11 +2423,15 @@ void sh2_reset(void *param)
/* Shut down CPU core */
void sh2_exit(void)
{
+ sh2_jit_set(0);
if (sh2.m)
free(sh2.m);
sh2.m = NULL;
+ /* the core frees the buffers after this */
+ sh2p = &sh2_boot;
}
+
/* Execute cycles - returns number of cycles actually run */
int sh2_execute(int cycles)
{
@@ -2350,49 +2442,10 @@ int sh2_execute(int cycles)
do
{
- UINT32 opcode;
-
- if (sh2.delay)
- {
- opcode = sh2.opcode_read ? sh2.opcode_read(sh2.delay) : RW(sh2.delay & AM);
- change_pc32bedw(sh2.pc & AM);
- sh2.pc -= 2;
- }
- else
- opcode = sh2.opcode_read ? sh2.opcode_read(sh2.pc) : RW(sh2.pc & AM);
-
- CALL_MAME_DEBUG;
-
- sh2.delay = 0;
- sh2.pc += 2;
- sh2.ppc = sh2.pc;
-
- switch ((opcode >> 12) & 15)
- {
- case 0: op0000(opcode); break;
- case 1: op0001(opcode); break;
- case 2: op0010(opcode); break;
- case 3: op0011(opcode); break;
- case 4: op0100(opcode); break;
- case 5: op0101(opcode); break;
- case 6: op0110(opcode); break;
- case 7: op0111(opcode); break;
- case 8: op1000(opcode); break;
- case 9: op1001(opcode); break;
- case 10: op1010(opcode); break;
- case 11: op1011(opcode); break;
- case 12: op1100(opcode); break;
- case 13: op1101(opcode); break;
- case 14: op1110(opcode); break;
- default: op1111(opcode); break;
- }
-
- if(sh2.test_irq && !sh2.delay)
- {
- CHECK_PENDING_IRQ("mame_sh2_execute");
- sh2.test_irq = 0;
- }
- sh2_icount--;
+ /* a block, when there is one for the PC (no slot or interrupt test pending) */
+ if (jit_enabled && !sh2.delay && !sh2.test_irq && sh2_jit_run())
+ continue;
+ sh2_step();
} while( sh2_icount > 0 );
return cycles - sh2_icount;
@@ -2401,16 +2454,17 @@ int sh2_execute(int cycles)
/* Get registers, return context size */
unsigned sh2_get_context(void *dst)
{
- if( dst )
- memcpy(dst, &sh2, sizeof(SH2));
+ if( dst && dst != (void *)sh2p )
+ memcpy(dst, sh2p, sizeof(SH2));
return sizeof(SH2);
}
/* Set registers */
void sh2_set_context(void *src)
{
+ /* the core passes a CPU's own buffer: it becomes the live state */
if( src )
- memcpy(&sh2, src, sizeof(SH2));
+ sh2p = (SH2 *)src;
}
static void sh2_timer_resync(void)
@@ -2597,6 +2651,7 @@ static void sh2_dmac_check(int dma)
if(incd == 2)
dst --;
cpu_writemem32bedw(dst, DMA_READ(src, dst, cpu_readmem32bedw(src), 0));
+ SH2JIT_STORE(dst, 1);
if(incs == 1)
src ++;
if(incd == 1)
@@ -2613,6 +2668,7 @@ static void sh2_dmac_check(int dma)
if(incd == 2)
dst -= 2;
cpu_writemem32bedw_word(dst, DMA_READ(src, dst, cpu_readmem32bedw_word(src), 1));
+ SH2JIT_STORE(dst, 2);
if(incs == 1)
src += 2;
if(incd == 1)
@@ -2629,6 +2685,7 @@ static void sh2_dmac_check(int dma)
if(incd == 2)
dst -= 4;
cpu_writemem32bedw_dword(dst, DMA_READ(src, dst, cpu_readmem32bedw_dword(src), 2));
+ SH2JIT_STORE(dst, 4);
if(incs == 1)
src += 4;
if(incd == 1)
@@ -2647,6 +2704,7 @@ static void sh2_dmac_check(int dma)
cpu_writemem32bedw_dword(dst+4, DMA_READ(src+4, dst+4, cpu_readmem32bedw_dword(src+4), 2));
cpu_writemem32bedw_dword(dst+8, DMA_READ(src+8, dst+8, cpu_readmem32bedw_dword(src+8), 2));
cpu_writemem32bedw_dword(dst+12, DMA_READ(src+12, dst+12, cpu_readmem32bedw_dword(src+12), 2));
+ SH2JIT_STORE(dst, 16);
src += 16;
if(incd == 1)
dst += 16;
@@ -2666,6 +2724,46 @@ static void sh2_dmac_check(int dma)
}
}
+/* the division unit, as in current MAME (sh7604.cpp) */
+static void sh2_divu_start(INT64 dividend)
+{
+ INT32 divisor = (INT32)sh2.m[0x40];
+ INT64 remainder;
+ UINT32 quotient;
+ int i, negative;
+
+ sh2.m[0x41] = (UINT32)dividend;
+
+ if (divisor && (dividend != (INT64)((UINT64)1 << 63) || divisor != -1))
+ {
+ INT64 q = dividend / divisor;
+ if (q == (INT32)q)
+ {
+ sh2.m[0x45] = (UINT32)q;
+ sh2.m[0x44] = (UINT32)(dividend % divisor);
+ return;
+ }
+ }
+
+ /* overflow (zero divisor or a quotient outside 32 bits): the unit stops after three
+ steps, leaving the partial remainder in DVDNTH; with OVFIE clear DVDNTL saturates */
+ remainder = dividend >> 32;
+ quotient = (UINT32)dividend;
+ for (i = 0; i < 3; i++)
+ {
+ int subtract = (remainder < 0) == (divisor < 0);
+ remainder = (remainder << 1) | ((quotient >> 31) & 1);
+ quotient <<= 1;
+ remainder += subtract ? -(INT64)divisor : (INT64)divisor;
+ quotient |= ((remainder < 0) == (divisor < 0)) ? 1 : 0;
+ }
+ negative = (dividend < 0) != (divisor < 0);
+ sh2.m[0x44] = (UINT32)remainder;
+ sh2.m[0x45] = (sh2.m[0x42] & 2) ? quotient : negative ? 0x80000000 : 0x7fffffff;
+ sh2.m[0x42] |= 1;
+ sh2_recalc_irq();
+}
+
WRITE32_HANDLER( sh2_internal_w )
{
UINT32 old = sh2.m[offset];
@@ -2728,64 +2826,19 @@ WRITE32_HANDLER( sh2_internal_w )
/* Division box*/
case 0x40: /* DVSR*/
break;
- case 0x41: /* DVDNT*/
- {
- INT32 a = sh2.m[0x41];
- INT32 b = sh2.m[0x40];
- log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %d/%d\n", cpu_getactivecpu(), a, b);
- if (b)
- {
- sh2.m[0x45] = a / b;
- sh2.m[0x44] = a % b;
- }
- else
- {
- sh2.m[0x42] |= 0x00010000;
- sh2.m[0x45] = 0x7fffffff;
- sh2.m[0x44] = 0x7fffffff;
- sh2_recalc_irq();
- }
- break;
- }
- case 0x42: /* DVCR*/
- sh2.m[0x42] = (sh2.m[0x42] & ~0x00001000) | (old & sh2.m[0x42] & 0x00010000);
- sh2_recalc_irq();
+ case 0x41: /* DVDNT: a 32-bit division, the dividend sign-extended into DVDNTH */
+ sh2_divu_start((INT32)sh2.m[0x41]);
+ break;
+ case 0x42: /* DVCR: OVF (bit 0) and OVFIE (bit 1) are plain read/write bits */
break;
case 0x43: /* VCRDIV*/
sh2_recalc_irq();
break;
case 0x44: /* DVDNTH*/
break;
- case 0x45: /* DVDNTL*/
- {
- INT64 a = sh2.m[0x45] | ((UINT64)(sh2.m[0x44]) << 32);
- INT64 b = sh2.m[0x40];
- log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %08x%08x/%08x\n", cpu_getactivecpu(), sh2.m[0x44], sh2.m[0x45], sh2.m[0x40]);
- if (b)
- {
- INT64 q = a / b;
- if (q != (INT32)q)
- {
- sh2.m[0x42] |= 0x00010000;
- sh2.m[0x45] = 0x7fffffff;
- sh2.m[0x44] = 0x7fffffff;
- sh2_recalc_irq();
- }
- else
- {
- sh2.m[0x45] = q;
- sh2.m[0x44] = a % b;
- }
- }
- else
- {
- sh2.m[0x42] |= 0x00010000;
- sh2.m[0x45] = 0x7fffffff;
- sh2.m[0x44] = 0x7fffffff;
- sh2_recalc_irq();
- }
- break;
- }
+ case 0x45: /* DVDNTL: a 64-bit division of DVDNTH:DVDNTL */
+ sh2_divu_start((INT64)(((UINT64)sh2.m[0x44] << 32) | sh2.m[0x45]));
+ break;
/* DMA controller*/
case 0x60: /* SAR0*/
@@ -3096,6 +3149,12 @@ void sh2_init(void)
{
int cpu = cpu_getactivecpu();
+ /* this CPU's buffer from now on (the core allocated it before the init) */
+ sh2p = (SH2 *)cpunum_get_context_ptr(cpu);
+ if (!sh2p)
+ sh2p = &sh2_boot;
+ memset(sh2p, 0, sizeof(SH2));
+
sh2.timer = timer_alloc(sh2_timer_callback);
timer_adjust(sh2.timer, TIME_NEVER, 0, 0);
diff --git a/src/cpu/sh2/sh2.h b/src/cpu/sh2/sh2.h
index e3a58d98..30c16827 100644
--- a/src/cpu/sh2/sh2.h
+++ b/src/cpu/sh2/sh2.h
@@ -69,6 +69,17 @@ struct sh2_config
data32_t (*dma_read_hook)(UINT32 src, UINT32 dst, data32_t data, int size);
};
+/* optional recompiler (sh2jit.c): a driver declares the RAM the CPUs run
+ from and read directly ('base': host memory of 'start', as the memory
+ system keeps it), then enables it; anything else stays with the
+ interpreter. Writes the driver makes there by other means than the
+ CPUs (DMA) must be reported with sh2_jit_ram_written. */
+int sh2_jit_available(void);
+void sh2_jit_add_fastram(offs_t start, offs_t end, int readonly, void *base);
+void sh2_jit_set(int enable);
+void sh2_jit_ram_written(UINT32 address, UINT32 bytes);
+extern int sh2_jit_code_present;
+
extern void sh2_init(void);
extern void sh2_reset (void *param); /* Reset registers to the initial values */
extern void sh2_exit (void); /* Shut down CPU core */
diff --git a/src/cpu/sh2/sh2jit.c b/src/cpu/sh2/sh2jit.c
new file mode 100644
index 00000000..75118d8b
--- /dev/null
+++ b/src/cpu/sh2/sh2jit.c
@@ -0,0 +1,2126 @@
+/***************************************************************************
+
+ sh2jit.c
+
+ Optional recompiler for the SH-2, built on the bundled sljit
+ (src/lib/sljit/sljit_mame.h; included by sh2.c).
+
+ Straight-line runs of instructions, ending at an unconditional jump
+ (with its delay slot) or at the first instruction left to the
+ interpreter, become native code. A block only runs when the
+ timeslice has enough cycles left for the whole of it (taking every
+ conditional branch), so every instruction it runs would have run in
+ the interpreter too, with the same cycles: the cycles of each
+ instruction are exactly the interpreter's.
+
+ - The usual ALU, shift, compare, move and multiply instructions and
+ all the branches are native code. The rarer ALU instructions
+ (ADDC, SUBC, ADDV, SUBV, NEGC, DIV0S, DIV1, DMULS, DMULU, ROTCL,
+ ROTCR, CMP/STR) call the interpreter for that instruction.
+ - Loads and stores go straight to the fast RAM the driver declares
+ (sh2_jit_add_fastram). Any other address, a misaligned access, an
+ address a CPU has a memory handler on, or a store over translated
+ code leaves the block just before that instruction ("side exit")
+ and the interpreter runs it, with its memory handlers, cycles and
+ timing. MAC.L, MAC.W, AND.B/OR.B/XOR.B/TST.B @(R0,GBR) and TAS.B
+ call the interpreter once the block has checked their addresses.
+ - LDC to SR, RTE, TRAPA and SLEEP (they change the interrupt state or
+ the flow) and the two busy loops the interpreter shortens (BRA $,
+ DT / BF $-2) end the block: the interpreter runs them. A delay slot
+ is only translated when it is a plain instruction that does not
+ read the PC.
+
+ Blocks only start with no delay slot pending and no interrupt test
+ pending. Only code in fast RAM is translated. Writes over translated
+ code flush the translation cache, whoever makes them: the
+ interpreter (WB/WW/WL), the SH-2 DMA, the driver's DMA (through
+ sh2_jit_ram_written), and a state load.
+
+***************************************************************************/
+
+/* the sljit build shared by the recompilers decides where this one runs */
+#include "../../lib/sljit/sljit_mame.h"
+
+#define SH2JIT_SUPPORTED SLJIT_MAME_SUPPORTED
+
+int sh2_jit_available(void)
+{
+ return SH2JIT_SUPPORTED;
+}
+
+#if SH2JIT_SUPPORTED
+
+#include
+
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#define JIT_HOST64 1
+#else
+#define JIT_HOST64 0
+#endif
+
+#define JIT_TABLE_BITS 16
+#define JIT_TABLE_SIZE (1 << JIT_TABLE_BITS)
+#define JIT_MAX_BLOCK 64 /* instructions */
+#define JIT_MAX_EXITS (JIT_MAX_BLOCK * 4)
+#define JIT_MAX_FASTRAM 8
+#define JIT_CODE_BUDGET (32 * 1024 * 1024)
+
+/* fast RAM granules of 4 bytes: which hold translated code */
+
+struct jit_fastram
+{
+ offs_t start, end; /* SH-2 addresses (masked with AM) */
+ UINT8 * base; /* host memory of 'start', as the memory system keeps it */
+ int readonly;
+ UINT32 mapoff; /* first granule of the region in the maps */
+};
+
+struct jit_block
+{
+ void * code;
+ void * entry; /* where a block leaving for this one jumps in (after the prologue), NULL if none */
+ UINT32 pc; /* address of the first instruction */
+ UINT16 cost; /* most cycles the block can take, 0 = not translatable */
+ UINT8 valid;
+ UINT8 len; /* instructions */
+ UINT8 idle; /* the SGL idle counting loop starts here (see jit_idle_skip) */
+ UINT16 op0; /* first opcode, to retry an untranslatable block once it changes */
+};
+
+typedef sljit_u32 (SLJIT_FUNC *jit_func)(void);
+
+static UINT16 jit_fetch(UINT32 pc);
+
+static int jit_enabled;
+static struct jit_fastram jit_ram[JIT_MAX_FASTRAM];
+static int jit_ram_count;
+static UINT32 jit_granules;
+static UINT8 *jit_codemap; /* a granule holds translated code */
+/*
+ Per CPU page tables (4 KB pages of the masked address space): the
+ host memory of a page the blocks may read (write) directly, NULL for
+ one that goes through the memory system. A page is direct when it
+ lies in one fast region and no memory handler of that CPU covers any
+ of it; for writes also when it holds no translated code (wbase is
+ the same without that condition, to restore the table on a flush).
+*/
+#define JIT_PAGE_SHIFT 12
+#define JIT_PAGES ((AM + 1) >> JIT_PAGE_SHIFT)
+static UINT8 **jit_rpage[MAX_CPU];
+static UINT8 **jit_wpage[MAX_CPU];
+static UINT8 **jit_wbase[MAX_CPU];
+static UINT8 *jit_codepage; /* a page holds translated code */
+static struct jit_block *jit_table;
+int sh2_jit_code_present;
+static size_t jit_code_bytes;
+static int jit_nomem_logged;
+
+
+/*************************************
+ * Fast RAM and translated code maps
+ *************************************/
+
+/* the region holding 'size' bytes at 'address' (masked), or NULL */
+static INLINE struct jit_fastram *jit_find_ram(UINT32 address, UINT32 size)
+{
+ int i;
+ for (i = 0; i < jit_ram_count; i++)
+ if (address >= jit_ram[i].start && address + size - 1 <= jit_ram[i].end)
+ return &jit_ram[i];
+ return NULL;
+}
+
+static int jit_in_block; /* a memory handler runs inside a block */
+static int jit_flush_pending; /* flush once that block has returned */
+
+static void jit_flush(void)
+{
+ int i;
+
+ if (!jit_table)
+ return;
+ /* the running block's code must stay until it returns */
+ if (jit_in_block)
+ {
+ jit_flush_pending = 1;
+ for (i = 0; i < JIT_TABLE_SIZE; i++)
+ jit_table[i].entry = NULL;
+ return;
+ }
+ for (i = 0; i < JIT_TABLE_SIZE; i++)
+ {
+ if (jit_table[i].code)
+ sljit_free_code(jit_table[i].code, NULL);
+ jit_table[i].code = NULL;
+ jit_table[i].entry = NULL;
+ jit_table[i].valid = 0;
+ }
+ memset(jit_codemap, 0, jit_granules);
+ memset(jit_codepage, 0, JIT_PAGES);
+ for (i = 0; i < MAX_CPU; i++)
+ if (jit_wpage[i])
+ memcpy(jit_wpage[i], jit_wbase[i], JIT_PAGES * sizeof(UINT8 *));
+ sh2_jit_code_present = 0;
+ jit_code_bytes = 0;
+}
+
+/* something wrote 'bytes' bytes at 'address' (masked with AM): flush if it was translated code */
+void sh2_jit_ram_written(UINT32 address, UINT32 bytes)
+{
+ struct jit_fastram *ram;
+ UINT32 first, last, g;
+
+ if (!sh2_jit_code_present || bytes == 0)
+ return;
+ address &= AM;
+ ram = jit_find_ram(address, 1);
+ if (!ram)
+ return;
+ first = ram->mapoff + ((address - ram->start) >> 2);
+ last = ram->mapoff + ((address + bytes - 1 - ram->start) >> 2);
+ if (last > ram->mapoff + ((ram->end - ram->start) >> 2))
+ last = ram->mapoff + ((ram->end - ram->start) >> 2);
+ for (g = first; g <= last; g++)
+ {
+ if (jit_codemap[g])
+ {
+ jit_flush();
+ return;
+ }
+ }
+}
+
+/*
+ What this CPU may access directly: the memory system must map a page
+ straight to the host memory of the region, as a RAM bank. Memory
+ handlers a driver installs over the RAM (speedups, protection) keep
+ their pages on the memory system, so they still run.
+*/
+static int jit_build_pages(int cpunum)
+{
+ UINT32 p;
+
+ jit_rpage[cpunum] = calloc(JIT_PAGES, sizeof(UINT8 *));
+ jit_wpage[cpunum] = calloc(JIT_PAGES, sizeof(UINT8 *));
+ jit_wbase[cpunum] = calloc(JIT_PAGES, sizeof(UINT8 *));
+ if (!jit_rpage[cpunum] || !jit_wpage[cpunum] || !jit_wbase[cpunum])
+ return 0;
+ for (p = 0; p < JIT_PAGES; p++)
+ {
+ UINT32 start = p << JIT_PAGE_SHIFT, a;
+ struct jit_fastram *ram = jit_find_ram(start, 1 << JIT_PAGE_SHIFT);
+ int rd = 1, wr;
+ UINT8 *host;
+
+ if (!ram)
+ continue;
+ host = ram->base + (start - ram->start);
+ wr = !ram->readonly;
+ for (a = 0; a < (1 << JIT_PAGE_SHIFT) && (rd || wr); a += 4)
+ {
+ if ((UINT8 *)memory_get_read_ptr(cpunum, start + a) != host + a || (UINT8 *)memory_get_read_ptr(cpunum, start + a + 3) != host + a + 3)
+ rd = 0;
+ if (wr && ((UINT8 *)memory_get_write_ptr(cpunum, start + a) != host + a || (UINT8 *)memory_get_write_ptr(cpunum, start + a + 3) != host + a + 3))
+ wr = 0;
+ }
+ if (rd)
+ jit_rpage[cpunum][p] = host;
+ if (wr)
+ jit_wbase[cpunum][p] = jit_wpage[cpunum][p] = jit_codepage[p] ? NULL : host;
+ }
+ return 1;
+}
+
+void sh2_jit_add_fastram(offs_t start, offs_t end, int readonly, void *base)
+{
+ if (jit_ram_count >= JIT_MAX_FASTRAM || (start & 3) || ((end + 1) & 3))
+ return;
+ jit_ram[jit_ram_count].start = start & AM;
+ jit_ram[jit_ram_count].end = end & AM;
+ jit_ram[jit_ram_count].base = (UINT8 *)base;
+ jit_ram[jit_ram_count].readonly = readonly;
+ jit_ram[jit_ram_count].mapoff = jit_granules;
+ jit_granules += (end - start + 1) >> 2;
+ jit_ram_count++;
+}
+
+static void jit_exit_all(void)
+{
+ int i;
+ jit_flush();
+ free(jit_table);
+ free(jit_codemap);
+ jit_table = NULL;
+ jit_codemap = NULL;
+ free(jit_codepage);
+ jit_codepage = NULL;
+ for (i = 0; i < MAX_CPU; i++)
+ {
+ free(jit_rpage[i]);
+ free(jit_wpage[i]);
+ free(jit_wbase[i]);
+ jit_rpage[i] = jit_wpage[i] = jit_wbase[i] = NULL;
+ }
+ jit_enabled = 0;
+}
+
+void sh2_jit_set(int enable)
+{
+ if (enable && !jit_table)
+ {
+ if (!jit_ram_count)
+ return;
+ jit_table = calloc(JIT_TABLE_SIZE, sizeof(jit_table[0]));
+ jit_codemap = calloc(jit_granules, 1);
+ jit_codepage = calloc(JIT_PAGES, 1);
+ if (!jit_table || !jit_codemap || !jit_codepage)
+ {
+ free(jit_table);
+ free(jit_codemap);
+ free(jit_codepage);
+ jit_table = NULL;
+ jit_codemap = NULL;
+ jit_codepage = NULL;
+ return;
+ }
+ jit_enabled = 1;
+ sh2_jit_code_present = 0;
+ /* a loaded state rewrites RAM behind our back */
+ state_save_register_func_postload(jit_flush);
+ }
+ else if (!enable)
+ {
+ if (jit_table)
+ jit_exit_all();
+ /* the driver declares its fast RAM again for the next game */
+ jit_ram_count = 0;
+ jit_granules = 0;
+ }
+}
+
+
+/*************************************
+ * Instruction decoding
+ *************************************/
+
+enum
+{
+ JIT_END = 0, /* the interpreter runs it: the block stops before */
+ JIT_SIMPLE, /* native, falls through */
+ JIT_MEM, /* native load or store, falls through (may side exit) */
+ JIT_HELPER, /* the interpreter runs it (no memory), falls through */
+ JIT_HELPER_MEM, /* the interpreter runs it, after its addresses are checked */
+ JIT_BRANCH /* conditional branch (BT/BF) or jump with a delay slot */
+};
+
+struct jit_op
+{
+ int kind;
+ int cost; /* the interpreter's cycles (a taken branch for branches) */
+ int acct; /* cycles the block takes for it (helpers take their own extras) */
+ int pcrel; /* reads the PC (not allowed in a delay slot) */
+ int slot; /* a branch with a delay slot */
+ int store; /* writes memory */
+};
+
+#define OPN(op) (((op) >> 8) & 15)
+#define OPM(op) (((op) >> 4) & 15)
+
+static void jit_decode(UINT16 op, UINT16 next, struct jit_op *o)
+{
+ memset(o, 0, sizeof(*o));
+ o->kind = JIT_SIMPLE;
+ o->cost = o->acct = 1;
+
+ switch ((op >> 12) & 15)
+ {
+ case 0:
+ switch (op & 0x3f)
+ {
+ case 0x03: case 0x23: /* BSRF, BRAF */
+ o->kind = JIT_BRANCH; o->slot = 1; o->cost = o->acct = 2;
+ break;
+ case 0x04: case 0x05: case 0x06: case 0x14: case 0x15: case 0x16:
+ case 0x24: case 0x25: case 0x26: case 0x34: case 0x35: case 0x36:
+ o->kind = JIT_MEM; o->store = 1; /* MOV.x Rm,@(R0,Rn) */
+ break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x1c: case 0x1d: case 0x1e:
+ case 0x2c: case 0x2d: case 0x2e: case 0x3c: case 0x3d: case 0x3e:
+ o->kind = JIT_MEM; /* MOV.x @(R0,Rm),Rn */
+ break;
+ case 0x07: case 0x17: case 0x27: case 0x37: /* MUL.L */
+ o->cost = o->acct = 2;
+ break;
+ case 0x0b: /* RTS */
+ o->kind = JIT_BRANCH; o->slot = 1; o->cost = o->acct = 2;
+ break;
+ case 0x0f: case 0x1f: case 0x2f: case 0x3f: /* MAC.L */
+ o->kind = JIT_HELPER_MEM; o->cost = 3;
+ break;
+ case 0x19: /* DIV0U */
+ break;
+ case 0x1b: /* SLEEP */
+ case 0x2b: /* RTE */
+ o->kind = JIT_END;
+ break;
+ }
+ break;
+
+ case 1: /* MOV.L Rm,@(disp,Rn) */
+ o->kind = JIT_MEM; o->store = 1;
+ break;
+
+ case 2:
+ switch (op & 15)
+ {
+ case 0: case 1: case 2: case 4: case 5: case 6:
+ o->kind = JIT_MEM; o->store = 1;
+ break;
+ case 12: /* CMP/STR */
+ o->kind = JIT_HELPER;
+ break;
+ }
+ break;
+
+ case 3:
+ switch (op & 15)
+ {
+ case 11: case 15: /* SUBV, ADDV */
+ o->kind = JIT_HELPER;
+ break;
+ case 5: case 13: /* DMULU, DMULS */
+ o->cost = o->acct = 2;
+ break;
+ }
+ break;
+
+ case 4:
+ switch (op & 0x3f)
+ {
+ case 0x02: case 0x12: case 0x22: /* STS.L MACH/MACL/PR,@-Rn */
+ o->kind = JIT_MEM; o->store = 1;
+ break;
+ case 0x03: case 0x13: case 0x23: /* STC.L SR/GBR/VBR,@-Rn */
+ o->kind = JIT_MEM; o->store = 1; o->cost = o->acct = 2;
+ break;
+ case 0x06: case 0x16: case 0x26: /* LDS.L @Rm+,MACH/MACL/PR */
+ o->kind = JIT_MEM;
+ break;
+ case 0x07: /* LDC.L @Rm+,SR */
+ case 0x0e: /* LDC Rm,SR */
+ o->kind = JIT_END;
+ break;
+ case 0x17: case 0x27: /* LDC.L @Rm+,GBR/VBR */
+ o->kind = JIT_MEM; o->cost = o->acct = 3;
+ break;
+ case 0x0b: /* JSR */
+ o->kind = JIT_BRANCH; o->slot = 1; o->cost = o->acct = 2;
+ break;
+ case 0x2b: /* JMP */
+ o->kind = JIT_BRANCH; o->slot = 1;
+ break;
+ case 0x0f: case 0x1f: case 0x2f: case 0x3f: /* MAC.W */
+ o->kind = JIT_HELPER_MEM; o->cost = 3;
+ break;
+ case 0x10: /* DT: the interpreter shortens DT / BF $-2 */
+ if (next == 0x8bfd)
+ o->kind = JIT_END;
+ break;
+ case 0x1b: /* TAS.B */
+ o->kind = JIT_HELPER_MEM; o->cost = 4; o->store = 1;
+ break;
+ }
+ break;
+
+ case 5: /* MOV.L @(disp,Rm),Rn */
+ o->kind = JIT_MEM;
+ break;
+
+ case 6:
+ switch (op & 15)
+ {
+ case 0: case 1: case 2: case 4: case 5: case 6:
+ o->kind = JIT_MEM;
+ break;
+ }
+ break;
+
+ case 8:
+ switch (OPN(op))
+ {
+ case 0: case 1:
+ o->kind = JIT_MEM; o->store = 1; /* MOV.B/W R0,@(disp,Rn) */
+ break;
+ case 4: case 5:
+ o->kind = JIT_MEM; /* MOV.B/W @(disp,Rm),R0 */
+ break;
+ case 9: case 11: /* BT, BF */
+ o->kind = JIT_BRANCH; o->cost = 3;
+ break;
+ case 13: case 15: /* BT/S, BF/S */
+ o->kind = JIT_BRANCH; o->slot = 1; o->cost = 2;
+ break;
+ }
+ break;
+
+ case 9: case 13: /* MOV.W/L @(disp,PC),Rn */
+ o->kind = JIT_MEM; o->pcrel = 1;
+ break;
+
+ case 10: /* BRA: the interpreter shortens BRA $ / NOP */
+ if ((op & 0xfff) == 0xffe)
+ o->kind = JIT_END;
+ else
+ {
+ o->kind = JIT_BRANCH; o->slot = 1; o->cost = o->acct = 2;
+ }
+ break;
+ case 11: /* BSR */
+ o->kind = JIT_BRANCH; o->slot = 1; o->cost = o->acct = 2;
+ break;
+
+ case 12:
+ switch (OPN(op))
+ {
+ case 0: case 1: case 2:
+ o->kind = JIT_MEM; o->store = 1; /* MOV.x R0,@(disp,GBR) */
+ break;
+ case 3: /* TRAPA */
+ o->kind = JIT_END;
+ break;
+ case 4: case 5: case 6:
+ o->kind = JIT_MEM; /* MOV.x @(disp,GBR),R0 */
+ break;
+ case 7: /* MOVA */
+ o->pcrel = 1;
+ break;
+ case 11: /* OR #imm,R0 takes 3 cycles here */
+ o->cost = o->acct = 3;
+ break;
+ case 12: /* TST.B */
+ o->kind = JIT_HELPER_MEM; o->cost = 3;
+ break;
+ case 13: case 14: /* AND.B, XOR.B */
+ o->kind = JIT_HELPER_MEM; o->cost = 3; o->store = 1;
+ break;
+ case 15: /* OR.B (one cycle in the interpreter) */
+ o->kind = JIT_HELPER_MEM; o->store = 1;
+ break;
+ }
+ break;
+ }
+
+ /* helpers take their own extra cycles */
+ if (o->kind == JIT_HELPER || o->kind == JIT_HELPER_MEM)
+ o->acct = 1;
+}
+
+
+/*************************************
+ * Code generation helpers
+ *************************************/
+
+#define JMEM(off) SLJIT_MEM1(SLJIT_S0), (sljit_sw)(off)
+#define JREG(n) JMEM(offsetof(SH2, r) + (n) * sizeof(UINT32))
+#define JSR_ JMEM(offsetof(SH2, sr))
+#define JGBR JMEM(offsetof(SH2, gbr))
+#define JVBR JMEM(offsetof(SH2, vbr))
+#define JPR JMEM(offsetof(SH2, pr))
+#define JMACH JMEM(offsetof(SH2, mach))
+#define JMACL JMEM(offsetof(SH2, macl))
+#define JRPAGE JMEM(offsetof(SH2, jit_rpage))
+#define JWPAGE JMEM(offsetof(SH2, jit_wpage))
+
+/* translation context of one block */
+struct jit_ctx
+{
+ struct sljit_compiler * C;
+ UINT32 pc;
+ UINT32 count;
+ UINT32 pre[JIT_MAX_BLOCK + 2]; /* cycles the block takes for the instructions before n */
+ int nexits;
+ int overflow;
+ struct
+ {
+ struct sljit_jump * jump;
+ UINT32 index;
+ } exits[JIT_MAX_EXITS];
+};
+
+/* leave before instruction 'index': the interpreter runs it */
+static void jit_add_exit(struct jit_ctx *ctx, struct sljit_jump *jump, UINT32 index)
+{
+ if (ctx->nexits < JIT_MAX_EXITS)
+ {
+ ctx->exits[ctx->nexits].jump = jump;
+ ctx->exits[ctx->nexits].index = index;
+ ctx->nexits++;
+ }
+ else
+ ctx->overflow = 1;
+}
+
+static void jit_emit_sub_cycles(struct sljit_compiler *C, UINT32 cycles)
+{
+ if (cycles)
+ sljit_emit_op2(C, SLJIT_SUB32, SLJIT_MEM0(), (sljit_sw)&sh2_icount, SLJIT_MEM0(), (sljit_sw)&sh2_icount, SLJIT_IMM, cycles);
+}
+
+/* T from the flag 'cond' of the operation just emitted */
+static void jit_set_t(struct sljit_compiler *C, sljit_s32 cond)
+{
+ sljit_emit_op_flags(C, SLJIT_MOV32, SLJIT_R1, 0, cond);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R0, 0, JSR_, SLJIT_IMM, ~T);
+ sljit_emit_op2(C, SLJIT_OR32, JSR_, SLJIT_R0, 0, SLJIT_R1, 0);
+}
+
+/* T from bit 'bit' of R2 (before the register changes) */
+static void jit_set_t_bit(struct sljit_compiler *C, int bit)
+{
+ if (bit)
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, bit);
+ else
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R2, 0);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, T);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R0, 0, JSR_, SLJIT_IMM, ~T);
+ sljit_emit_op2(C, SLJIT_OR32, JSR_, SLJIT_R0, 0, SLJIT_R1, 0);
+}
+
+/* r[n] = r[n] op src */
+static void jit_alu(struct sljit_compiler *C, sljit_s32 op, int n, sljit_s32 src, sljit_sw srcw)
+{
+ sljit_emit_op2(C, op, SLJIT_R0, 0, JREG(n), src, srcw);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0);
+}
+
+/* T = (src1 cmp src2) */
+static void jit_cmp(struct sljit_compiler *C, sljit_s32 cond, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_emit_op2u(C, SLJIT_SUB32 | SLJIT_SET(cond & ~1), src1, src1w, src2, src2w);
+ jit_set_t(C, cond);
+}
+
+/* the interpreter runs one instruction (no exception, no memory but fast RAM) */
+static void sh2_dispatch(UINT16 opcode);
+
+static void SLJIT_FUNC jit_helper(sljit_u32 op)
+{
+ sh2_dispatch((UINT16)op);
+}
+
+static void jit_emit_helper(struct sljit_compiler *C, UINT16 op)
+{
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, op);
+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1V(32), SLJIT_IMM, SLJIT_FUNC_ADDR(jit_helper));
+}
+
+
+/*
+ DIV1 Rm,Rn. With Qn the old bit 31 of Rn, Rn = Rn << 1 | T, then Rm
+ is subtracted when the old Q equals M, added otherwise; c is the
+ borrow or carry. The interpreter's four cases reduce to
+ Q = Qn ^ c ^ M and T = !(Qn ^ c).
+*/
+static void jit_emit_div1(struct sljit_compiler *C, int n, int m)
+{
+ struct sljit_jump *add, *done;
+
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R3, 0, JSR_);
+ /* R1 = Rn << 1 | T */
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R0, 0, SLJIT_R3, 0, SLJIT_IMM, T);
+ sljit_emit_op2(C, SLJIT_OR32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);
+ /* R2 = Qn */
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 31);
+ /* R0 = (old Q ^ M) & 1: 1 adds, 0 subtracts */
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R3, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_XOR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R3, 0);
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, Q);
+ add = sljit_emit_jump(C, SLJIT_NOT_ZERO);
+ sljit_emit_op2(C, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, JREG(m));
+ sljit_emit_op_flags(C, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_CARRY);
+ done = sljit_emit_jump(C, SLJIT_JUMP);
+ sljit_set_label(add, sljit_emit_label(C));
+ sljit_emit_op2(C, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, JREG(m));
+ sljit_emit_op_flags(C, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_CARRY);
+ sljit_set_label(done, sljit_emit_label(C));
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R1, 0);
+ /* R0 = Qn ^ c; T = R0 ^ 1; Q = R0 ^ M */
+ sljit_emit_op2(C, SLJIT_XOR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R2, 0);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, SLJIT_R3, 0, SLJIT_IMM, 9);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_XOR32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 8);
+ sljit_emit_op2(C, SLJIT_XOR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R3, 0, SLJIT_R3, 0, SLJIT_IMM, ~(Q | T));
+ sljit_emit_op2(C, SLJIT_OR32, SLJIT_R3, 0, SLJIT_R3, 0, SLJIT_R1, 0);
+ sljit_emit_op2(C, SLJIT_OR32, JSR_, SLJIT_R3, 0, SLJIT_R0, 0);
+}
+
+/* DMULS.L / DMULU.L: the 64-bit product into MACH:MACL */
+static void jit_emit_dmul(struct sljit_compiler *C, int n, int m, int sign)
+{
+#if JIT_HOST64
+ sljit_emit_op1(C, sign ? SLJIT_MOV_S32 : SLJIT_MOV_U32, SLJIT_R0, 0, JREG(n));
+ sljit_emit_op1(C, sign ? SLJIT_MOV_S32 : SLJIT_MOV_U32, SLJIT_R1, 0, JREG(m));
+ sljit_emit_op2(C, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);
+ sljit_emit_op2(C, SLJIT_LSHR, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 32);
+#else
+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, JREG(n));
+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, JREG(m));
+ sljit_emit_op0(C, sign ? SLJIT_LMUL_SW : SLJIT_LMUL_UW);
+#endif
+ sljit_emit_op1(C, SLJIT_MOV32, JMACL, SLJIT_R0, 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JMACH, SLJIT_R1, 0);
+}
+
+/*
+ ADDC / SUBC: Rn = Rn +- Rm +- T, T = the carry (borrow) of either
+ step, as the interpreter's two comparisons.
+*/
+static void jit_emit_carry(struct sljit_compiler *C, int n, int m, int sub)
+{
+ sljit_s32 op = sub ? SLJIT_SUB32 : SLJIT_ADD32;
+ sljit_emit_op2(C, op | SLJIT_SET_CARRY, SLJIT_R0, 0, JREG(n), JREG(m));
+ sljit_emit_op_flags(C, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_CARRY);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, JSR_, SLJIT_IMM, T);
+ sljit_emit_op2(C, op | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);
+ sljit_emit_op_flags(C, SLJIT_OR32, SLJIT_R2, 0, SLJIT_CARRY);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, JSR_, SLJIT_IMM, ~T);
+ sljit_emit_op2(C, SLJIT_OR32, JSR_, SLJIT_R1, 0, SLJIT_R2, 0);
+}
+
+/*************************************
+ * Plain instructions
+ *
+ * Each case mirrors the interpreter in sh2.c exactly.
+ *************************************/
+
+static void jit_emit_simple(struct jit_ctx *ctx, UINT16 op, UINT32 pc)
+{
+ struct sljit_compiler *C = ctx->C;
+ int n = OPN(op), m = OPM(op);
+ sljit_sw imm8 = (sljit_sw)(INT32)(INT8)(op & 0xff);
+ sljit_sw uimm8 = (sljit_sw)(op & 0xff);
+
+ switch ((op >> 12) & 15)
+ {
+ case 0:
+ switch (op & 0x3f)
+ {
+ case 0x02: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JSR_); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* STC SR */
+ case 0x12: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JGBR); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* STC GBR */
+ case 0x22: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JVBR); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* STC VBR */
+ case 0x0a: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JMACH); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* STS MACH */
+ case 0x1a: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JMACL); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* STS MACL */
+ case 0x2a: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JPR); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* STS PR */
+ case 0x07: case 0x17: case 0x27: case 0x37: /* MUL.L */
+ sljit_emit_op2(C, SLJIT_MUL32, SLJIT_R0, 0, JREG(n), JREG(m));
+ sljit_emit_op1(C, SLJIT_MOV32, JMACL, SLJIT_R0, 0);
+ break;
+ case 0x08: /* CLRT */
+ sljit_emit_op2(C, SLJIT_AND32, JSR_, JSR_, SLJIT_IMM, ~T);
+ break;
+ case 0x18: /* SETT */
+ sljit_emit_op2(C, SLJIT_OR32, JSR_, JSR_, SLJIT_IMM, T);
+ break;
+ case 0x19: /* DIV0U */
+ sljit_emit_op2(C, SLJIT_AND32, JSR_, JSR_, SLJIT_IMM, ~(M | Q | T));
+ break;
+ case 0x28: /* CLRMAC */
+ sljit_emit_op1(C, SLJIT_MOV32, JMACH, SLJIT_IMM, 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JMACL, SLJIT_IMM, 0);
+ break;
+ case 0x29: /* MOVT */
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R0, 0, JSR_, SLJIT_IMM, T);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0);
+ break;
+ default: /* NOP and the unused codes */
+ break;
+ }
+ break;
+
+ case 2:
+ switch (op & 15)
+ {
+ case 8: /* TST Rm,Rn */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n));
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, JREG(m));
+ jit_set_t(C, SLJIT_ZERO);
+ break;
+ case 7: /* DIV0S: Q = Rn bit 31, M = Rm bit 31, T = Q ^ M */
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, JREG(n), SLJIT_IMM, 31);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R2, 0, JREG(m), SLJIT_IMM, 31);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R0, 0, JSR_, SLJIT_IMM, ~(M | Q | T));
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R3, 0, SLJIT_R1, 0, SLJIT_IMM, 8);
+ sljit_emit_op2(C, SLJIT_OR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R3, 0);
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R3, 0, SLJIT_R2, 0, SLJIT_IMM, 9);
+ sljit_emit_op2(C, SLJIT_OR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R3, 0);
+ sljit_emit_op2(C, SLJIT_XOR32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R2, 0);
+ sljit_emit_op2(C, SLJIT_OR32, JSR_, SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ case 9: jit_alu(C, SLJIT_AND32, n, JREG(m)); break;
+ case 10: jit_alu(C, SLJIT_XOR32, n, JREG(m)); break;
+ case 11: jit_alu(C, SLJIT_OR32, n, JREG(m)); break;
+ case 13: /* XTRCT */
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R0, 0, JREG(m), SLJIT_IMM, 16);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, JREG(n), SLJIT_IMM, 16);
+ sljit_emit_op2(C, SLJIT_OR32, JREG(n), SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ case 14: /* MULU */
+ sljit_emit_op1(C, SLJIT_MOV32_U16, SLJIT_R0, 0, JREG(n));
+ sljit_emit_op1(C, SLJIT_MOV32_U16, SLJIT_R1, 0, JREG(m));
+ sljit_emit_op2(C, SLJIT_MUL32, JMACL, SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ case 15: /* MULS */
+ sljit_emit_op1(C, SLJIT_MOV32_S16, SLJIT_R0, 0, JREG(n));
+ sljit_emit_op1(C, SLJIT_MOV32_S16, SLJIT_R1, 0, JREG(m));
+ sljit_emit_op2(C, SLJIT_MUL32, JMACL, SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ default: /* 3: NOP */
+ break;
+ }
+ break;
+
+ case 3:
+ switch (op & 15)
+ {
+ case 0: jit_cmp(C, SLJIT_EQUAL, JREG(n), JREG(m)); break;
+ case 2: jit_cmp(C, SLJIT_GREATER_EQUAL, JREG(n), JREG(m)); break;
+ case 3: jit_cmp(C, SLJIT_SIG_GREATER_EQUAL, JREG(n), JREG(m)); break;
+ case 6: jit_cmp(C, SLJIT_GREATER, JREG(n), JREG(m)); break;
+ case 7: jit_cmp(C, SLJIT_SIG_GREATER, JREG(n), JREG(m)); break;
+ case 8: jit_alu(C, SLJIT_SUB32, n, JREG(m)); break;
+ case 12: jit_alu(C, SLJIT_ADD32, n, JREG(m)); break;
+ case 4: jit_emit_div1(C, n, m); break;
+ case 5: jit_emit_dmul(C, n, m, 0); break;
+ case 13: jit_emit_dmul(C, n, m, 1); break;
+ case 10: jit_emit_carry(C, n, m, 1); break; /* SUBC */
+ case 14: jit_emit_carry(C, n, m, 0); break; /* ADDC */
+ default: break; /* 1, 9: NOP */
+ }
+ break;
+
+ case 4:
+ switch (op & 0x3f)
+ {
+ case 0x00: case 0x20: /* SHLL, SHAL */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ jit_set_t_bit(C, 31);
+ sljit_emit_op2(C, SLJIT_SHL32, JREG(n), SLJIT_R2, 0, SLJIT_IMM, 1);
+ break;
+ case 0x01: /* SHLR */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ jit_set_t_bit(C, 0);
+ sljit_emit_op2(C, SLJIT_LSHR32, JREG(n), SLJIT_R2, 0, SLJIT_IMM, 1);
+ break;
+ case 0x21: /* SHAR */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ jit_set_t_bit(C, 0);
+ sljit_emit_op2(C, SLJIT_ASHR32, JREG(n), SLJIT_R2, 0, SLJIT_IMM, 1);
+ break;
+ case 0x04: /* ROTL */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ jit_set_t_bit(C, 31);
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 31);
+ sljit_emit_op2(C, SLJIT_OR32, JREG(n), SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ case 0x05: /* ROTR */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ jit_set_t_bit(C, 0);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 31);
+ sljit_emit_op2(C, SLJIT_OR32, JREG(n), SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ case 0x24: /* ROTCL: T in at bit 0, bit 31 out to T */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R3, 0, JSR_, SLJIT_IMM, T);
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_OR32, JREG(n), SLJIT_R0, 0, SLJIT_R3, 0);
+ jit_set_t_bit(C, 31);
+ break;
+ case 0x25: /* ROTCR: T in at bit 31, bit 0 out to T */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(n));
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R3, 0, JSR_, SLJIT_IMM, 31);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_OR32, JREG(n), SLJIT_R0, 0, SLJIT_R3, 0);
+ jit_set_t_bit(C, 0);
+ break;
+ case 0x08: jit_alu(C, SLJIT_SHL32, n, SLJIT_IMM, 2); break;
+ case 0x09: jit_alu(C, SLJIT_LSHR32, n, SLJIT_IMM, 2); break;
+ case 0x18: jit_alu(C, SLJIT_SHL32, n, SLJIT_IMM, 8); break;
+ case 0x19: jit_alu(C, SLJIT_LSHR32, n, SLJIT_IMM, 8); break;
+ case 0x28: jit_alu(C, SLJIT_SHL32, n, SLJIT_IMM, 16); break;
+ case 0x29: jit_alu(C, SLJIT_LSHR32, n, SLJIT_IMM, 16); break;
+ case 0x0a: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n)); sljit_emit_op1(C, SLJIT_MOV32, JMACH, SLJIT_R0, 0); break; /* LDS MACH */
+ case 0x1a: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n)); sljit_emit_op1(C, SLJIT_MOV32, JMACL, SLJIT_R0, 0); break; /* LDS MACL */
+ case 0x2a: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n)); sljit_emit_op1(C, SLJIT_MOV32, JPR, SLJIT_R0, 0); break; /* LDS PR */
+ case 0x1e: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n)); sljit_emit_op1(C, SLJIT_MOV32, JGBR, SLJIT_R0, 0); break; /* LDC GBR */
+ case 0x2e: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n)); sljit_emit_op1(C, SLJIT_MOV32, JVBR, SLJIT_R0, 0); break; /* LDC VBR */
+ case 0x10: /* DT */
+ sljit_emit_op2(C, SLJIT_SUB32 | SLJIT_SET_Z, SLJIT_R0, 0, JREG(n), SLJIT_IMM, 1);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0);
+ sljit_emit_op2u(C, SLJIT_SUB32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0);
+ jit_set_t(C, SLJIT_ZERO);
+ break;
+ case 0x11: /* CMP/PZ */
+ jit_cmp(C, SLJIT_SIG_GREATER_EQUAL, JREG(n), SLJIT_IMM, 0);
+ break;
+ case 0x15: /* CMP/PL */
+ jit_cmp(C, SLJIT_SIG_GREATER, JREG(n), SLJIT_IMM, 0);
+ break;
+ default: /* NOP codes */
+ break;
+ }
+ break;
+
+ case 6:
+ switch (op & 15)
+ {
+ case 3: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(m)); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* MOV */
+ case 7: sljit_emit_op2(C, SLJIT_XOR32, SLJIT_R0, 0, JREG(m), SLJIT_IMM, -1); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* NOT */
+ case 8: /* SWAP.B */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(m));
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)(INT32)0xffff0000);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 0xff);
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 8);
+ sljit_emit_op2(C, SLJIT_OR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 8);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 0xff);
+ sljit_emit_op2(C, SLJIT_OR32, JREG(n), SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ case 9: /* SWAP.W */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(m));
+ sljit_emit_op2(C, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 16);
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 16);
+ sljit_emit_op2(C, SLJIT_OR32, JREG(n), SLJIT_R0, 0, SLJIT_R1, 0);
+ break;
+ case 11: sljit_emit_op2(C, SLJIT_SUB32, SLJIT_R0, 0, SLJIT_IMM, 0, JREG(m)); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* NEG */
+ case 10: /* NEGC: Rn = 0 - Rm - T, T = Rm != 0 || T */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(m));
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R3, 0, JSR_, SLJIT_IMM, T);
+ sljit_emit_op2(C, SLJIT_SUB32, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R2, 0);
+ sljit_emit_op2(C, SLJIT_SUB32, JREG(n), SLJIT_R0, 0, SLJIT_R3, 0);
+ sljit_emit_op2(C, SLJIT_OR32, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_R3, 0);
+ sljit_emit_op2u(C, SLJIT_SUB32 | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, 0);
+ jit_set_t(C, SLJIT_NOT_ZERO);
+ break;
+ case 12: sljit_emit_op1(C, SLJIT_MOV32_U8, SLJIT_R0, 0, JREG(m)); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* EXTU.B */
+ case 13: sljit_emit_op1(C, SLJIT_MOV32_U16, SLJIT_R0, 0, JREG(m)); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* EXTU.W */
+ case 14: sljit_emit_op1(C, SLJIT_MOV32_S8, SLJIT_R0, 0, JREG(m)); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* EXTS.B */
+ case 15: sljit_emit_op1(C, SLJIT_MOV32_S16, SLJIT_R0, 0, JREG(m)); sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R0, 0); break; /* EXTS.W */
+ }
+ break;
+
+ case 7: /* ADD #imm,Rn */
+ jit_alu(C, SLJIT_ADD32, n, SLJIT_IMM, imm8);
+ break;
+
+ case 8:
+ switch (OPN(op))
+ {
+ case 8: /* CMP/EQ #imm,R0 */
+ jit_cmp(C, SLJIT_EQUAL, JREG(0), SLJIT_IMM, imm8);
+ break;
+ default: /* NOP codes */
+ break;
+ }
+ break;
+
+ case 12:
+ switch (OPN(op))
+ {
+ case 7: /* MOVA */
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(0), SLJIT_IMM, (sljit_sw)(INT32)(((pc + 4) & ~3) + uimm8 * 4));
+ break;
+ case 8: /* TST #imm,R0 */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(0));
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, uimm8);
+ jit_set_t(C, SLJIT_ZERO);
+ break;
+ case 9: jit_alu(C, SLJIT_AND32, 0, SLJIT_IMM, uimm8); break;
+ case 10: jit_alu(C, SLJIT_XOR32, 0, SLJIT_IMM, uimm8); break;
+ case 11: jit_alu(C, SLJIT_OR32, 0, SLJIT_IMM, uimm8); break;
+ }
+ break;
+
+ case 14: /* MOV #imm,Rn */
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_IMM, imm8);
+ break;
+
+ default: /* 15: NOP */
+ break;
+ }
+}
+
+
+/*************************************
+ * Loads and stores
+ *************************************/
+
+/*
+ The address of the access into R0 (32 bits). Post-increment and
+ pre-decrement registers change only after the access, in
+ jit_emit_mem_finish.
+*/
+struct jit_mem
+{
+ int size;
+ int store;
+ int sext; /* sign extend a load */
+};
+
+static void jit_mem_info(UINT16 op, struct jit_mem *mi)
+{
+ static const int sizes[4] = { 1, 2, 4, 0 };
+ mi->size = 4;
+ mi->store = 0;
+ mi->sext = 1;
+ switch ((op >> 12) & 15)
+ {
+ case 0: mi->size = sizes[op & 3]; mi->store = !(op & 8); break;
+ case 1: mi->size = 4; mi->store = 1; break;
+ case 2: mi->size = sizes[op & 3]; mi->store = 1; break;
+ case 4:
+ mi->size = 4;
+ mi->store = ((op & 15) == 2 || (op & 15) == 3);
+ break;
+ case 5: mi->size = 4; break;
+ case 6: mi->size = sizes[op & 3]; break;
+ case 8: mi->size = sizes[OPN(op) & 1]; mi->store = OPN(op) < 4; break;
+ case 9: mi->size = 2; break;
+ case 12: mi->size = sizes[OPN(op) & 3]; mi->store = OPN(op) < 4; break;
+ case 13: mi->size = 4; break;
+ }
+}
+
+static void jit_emit_mem_ea(struct sljit_compiler *C, UINT16 op, UINT32 pc, const struct jit_mem *mi)
+{
+ int n = OPN(op), m = OPM(op);
+ UINT32 d4 = op & 15, d8 = op & 0xff;
+
+ switch ((op >> 12) & 15)
+ {
+ case 0: /* @(R0,Rn) / @(R0,Rm) */
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_R0, 0, JREG(mi->store ? n : m), JREG(0));
+ break;
+ case 1: /* @(disp,Rn) */
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_R0, 0, JREG(n), SLJIT_IMM, d4 * 4);
+ break;
+ case 2: /* @Rn, @-Rn */
+ if (op & 4)
+ sljit_emit_op2(C, SLJIT_SUB32, SLJIT_R0, 0, JREG(n), SLJIT_IMM, mi->size);
+ else
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n));
+ break;
+ case 4: /* STS.L / STC.L @-Rn, LDS.L / LDC.L @Rm+ */
+ if (mi->store)
+ sljit_emit_op2(C, SLJIT_SUB32, SLJIT_R0, 0, JREG(n), SLJIT_IMM, 4);
+ else
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n));
+ break;
+ case 5: /* @(disp,Rm) */
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_R0, 0, JREG(m), SLJIT_IMM, d4 * 4);
+ break;
+ case 6: /* @Rm, @Rm+ */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(m));
+ break;
+ case 8: /* @(disp,Rn) / @(disp,Rm), byte or word */
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_R0, 0, JREG(m), SLJIT_IMM, d4 * mi->size);
+ break;
+ case 9: /* @(disp,PC), word */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(INT32)(pc + 4 + d8 * 2));
+ break;
+ case 12: /* @(disp,GBR) */
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_R0, 0, JGBR, SLJIT_IMM, d8 * mi->size);
+ break;
+ case 13: /* @(disp,PC), long */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(INT32)(((pc + 4) & ~3) + d8 * 4));
+ break;
+ }
+}
+
+/*
+ Host address of the 'size' bytes at R0 into R1, through the page
+ table of this CPU. Otherwise the access leaves before instruction
+ 'index' for the interpreter, or goes to the 'slow' jumps (the memory
+ system in the block) when given: when it is misaligned (always a side
+ exit), at or above the special areas (cache, internal registers), or
+ in a page the memory system handles or, for a store, that holds
+ translated code. R0 keeps the address.
+*/
+static void jit_emit_mem_check(struct jit_ctx *ctx, int size, int store, UINT32 index, struct sljit_jump **slow, int *nslow)
+{
+ struct sljit_compiler *C = ctx->C;
+ struct sljit_jump *jump;
+
+ if (size > 1)
+ {
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, size - 1);
+ jit_add_exit(ctx, sljit_emit_jump(C, SLJIT_NOT_ZERO), index);
+ }
+ /* 0x40000000 and up: the interpreter's special areas */
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(INT32)0xc0000000);
+ jump = sljit_emit_jump(C, SLJIT_NOT_ZERO);
+ if (slow)
+ slow[(*nslow)++] = jump;
+ else
+ jit_add_exit(ctx, jump, index);
+
+ /* R3 = the page's host memory */
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, AM);
+ sljit_emit_op1(C, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0);
+ sljit_emit_op2(C, SLJIT_LSHR, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_IMM, JIT_PAGE_SHIFT);
+ if (store)
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R3, 0, JWPAGE);
+ else
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R3, 0, JRPAGE);
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R3, 0, SLJIT_MEM2(SLJIT_R3, SLJIT_R2), SLJIT_WORD_SHIFT);
+ jump = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R3, 0, SLJIT_IMM, 0);
+ if (slow)
+ slow[(*nslow)++] = jump;
+ else
+ jit_add_exit(ctx, jump, index);
+
+ /* the memory system keeps 32-bit big-endian words in host order */
+ sljit_emit_op2(C, SLJIT_AND, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, (1 << JIT_PAGE_SHIFT) - 1);
+ if (size == 1)
+ sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 3);
+ else if (size == 2)
+ sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 2);
+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R3, 0);
+}
+
+#ifdef SH2JIT_VERIFY
+static void SLJIT_FUNC jit_verify_log_store(sljit_up host, sljit_u32 size);
+#endif
+
+/* a load's value (sign extended) is in R2: the register updates */
+static void jit_emit_load_result(struct sljit_compiler *C, UINT16 op, const struct jit_mem *mi)
+{
+ int n = OPN(op), m = OPM(op);
+
+ switch ((op >> 12) & 15)
+ {
+ case 4: /* LDS.L / LDC.L @Rm+: the load, then Rm += 4 */
+ {
+ size_t field;
+ switch (op & 0x3f)
+ {
+ case 0x06: field = offsetof(SH2, mach); break;
+ case 0x16: field = offsetof(SH2, macl); break;
+ case 0x26: field = offsetof(SH2, pr); break;
+ case 0x17: field = offsetof(SH2, gbr); break;
+ default: field = offsetof(SH2, vbr); break; /* 0x27 */
+ }
+ sljit_emit_op1(C, SLJIT_MOV32, JMEM(field), SLJIT_R2, 0);
+ sljit_emit_op2(C, SLJIT_ADD32, JREG(n), JREG(n), SLJIT_IMM, 4);
+ break;
+ }
+ case 6: /* MOV.x @Rm,Rn / @Rm+,Rn: no increment when n == m */
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R2, 0);
+ if ((op & 4) && n != m)
+ sljit_emit_op2(C, SLJIT_ADD32, JREG(m), JREG(m), SLJIT_IMM, mi->size);
+ break;
+ case 8: /* MOV.B/W @(disp,Rm),R0 */
+ case 12: /* MOV.x @(disp,GBR),R0 */
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(0), SLJIT_R2, 0);
+ break;
+ default: /* MOV.x @(R0,Rm),Rn, MOV.L @(disp,Rm),Rn, MOV.x @(disp,PC),Rn */
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R2, 0);
+ break;
+ }
+}
+
+/* the access through the host pointer in R1, then the register updates */
+static void jit_emit_mem_access(struct sljit_compiler *C, UINT16 op, const struct jit_mem *mi)
+{
+ int n = OPN(op), m = OPM(op);
+ sljit_s32 ld = (mi->size == 1) ? SLJIT_MOV32_S8 : (mi->size == 2) ? SLJIT_MOV32_S16 : SLJIT_MOV32;
+ sljit_s32 st = (mi->size == 1) ? SLJIT_MOV32_U8 : (mi->size == 2) ? SLJIT_MOV32_U16 : SLJIT_MOV32;
+
+#ifdef SH2JIT_VERIFY
+ if (mi->store)
+ {
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_S1, 0, SLJIT_R1, 0);
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_R1, 0);
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, mi->size);
+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2V(P, 32), SLJIT_IMM, SLJIT_FUNC_ADDR(jit_verify_log_store));
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R1, 0, SLJIT_S1, 0);
+ }
+#endif
+
+ if (!mi->store)
+ {
+ sljit_emit_op1(C, ld, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ jit_emit_load_result(C, op, mi);
+ return;
+ }
+
+ switch ((op >> 12) & 15)
+ {
+ case 0:
+ if (mi->store) /* MOV.x Rm,@(R0,Rn) */
+ {
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(m));
+ sljit_emit_op1(C, st, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+ }
+ else /* MOV.x @(R0,Rm),Rn */
+ {
+ sljit_emit_op1(C, ld, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R2, 0);
+ }
+ break;
+ case 1: /* MOV.L Rm,@(disp,Rn) */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(m));
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+ break;
+ case 2: /* MOV.x Rm,@Rn / Rm,@-Rn: the data is read before Rn changes */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(m));
+ sljit_emit_op1(C, st, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+ if (op & 4)
+ sljit_emit_op2(C, SLJIT_SUB32, JREG(n), JREG(n), SLJIT_IMM, mi->size);
+ break;
+ case 4:
+ {
+ size_t field;
+ switch (op & 0x3f)
+ {
+ case 0x02: field = offsetof(SH2, mach); break;
+ case 0x12: field = offsetof(SH2, macl); break;
+ case 0x22: field = offsetof(SH2, pr); break;
+ case 0x03: field = offsetof(SH2, sr); break;
+ case 0x13: field = offsetof(SH2, gbr); break;
+ case 0x23: field = offsetof(SH2, vbr); break;
+ case 0x06: field = offsetof(SH2, mach); break;
+ case 0x16: field = offsetof(SH2, macl); break;
+ case 0x26: field = offsetof(SH2, pr); break;
+ case 0x17: field = offsetof(SH2, gbr); break;
+ default: field = offsetof(SH2, vbr); break; /* 0x27 */
+ }
+ if (mi->store) /* Rn -= 4, then the store */
+ {
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JMEM(field));
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+ sljit_emit_op2(C, SLJIT_SUB32, JREG(n), JREG(n), SLJIT_IMM, 4);
+ }
+ else /* the load, then Rm += 4 */
+ {
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JMEM(field), SLJIT_R2, 0);
+ sljit_emit_op2(C, SLJIT_ADD32, JREG(n), JREG(n), SLJIT_IMM, 4);
+ }
+ break;
+ }
+ case 5: /* MOV.L @(disp,Rm),Rn */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R2, 0);
+ break;
+ case 6: /* MOV.x @Rm,Rn / @Rm+,Rn: no increment when n == m */
+ sljit_emit_op1(C, ld, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R2, 0);
+ if ((op & 4) && n != m)
+ sljit_emit_op2(C, SLJIT_ADD32, JREG(m), JREG(m), SLJIT_IMM, mi->size);
+ break;
+ case 8:
+ if (mi->store) /* MOV.B/W R0,@(disp,Rn) */
+ {
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(0));
+ sljit_emit_op1(C, st, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+ }
+ else /* MOV.B/W @(disp,Rm),R0 */
+ {
+ sljit_emit_op1(C, ld, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(0), SLJIT_R2, 0);
+ }
+ break;
+ case 9: /* MOV.W @(disp,PC),Rn */
+ case 13: /* MOV.L @(disp,PC),Rn */
+ sljit_emit_op1(C, ld, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(n), SLJIT_R2, 0);
+ break;
+ case 12:
+ if (mi->store) /* MOV.x R0,@(disp,GBR) */
+ {
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, JREG(0));
+ sljit_emit_op1(C, st, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+ }
+ else /* MOV.x @(disp,GBR),R0 */
+ {
+ sljit_emit_op1(C, ld, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JREG(0), SLJIT_R2, 0);
+ }
+ break;
+ }
+}
+
+/*
+ A load the fast path cannot do (a memory handler, the internal
+ registers): the memory system reads it here, as in the interpreter's
+ step: sh2_icount has the cycles before the instruction and the PC is
+ past it. The block leaves after the instruction when the handler
+ took cycles (a spin or yield hack, the end of the timeslice), raised
+ an interrupt or flushed the translated code.
+*/
+static sljit_u32 jit_slow_break;
+
+static sljit_s32 SLJIT_FUNC jit_slow_read(sljit_u32 ea, sljit_u32 size)
+{
+ int before = sh2_icount;
+ INT32 v;
+
+ jit_in_block = 1;
+ if (size == 1)
+ v = (INT8)RB(ea);
+ else if (size == 2)
+ v = (INT16)RW(ea);
+ else
+ v = (INT32)RL(ea);
+ jit_in_block = 0;
+ jit_slow_break = (sh2_icount != before || sh2.test_irq || jit_flush_pending);
+ return v;
+}
+
+static void SLJIT_FUNC jit_slow_write(sljit_u32 ea, sljit_u32 v, sljit_u32 size)
+{
+ int before = sh2_icount;
+
+ jit_in_block = 1;
+ if (size == 1)
+ WB(ea, (UINT8)v);
+ else if (size == 2)
+ WW(ea, (UINT16)v);
+ else
+ WL(ea, v);
+ jit_in_block = 0;
+ jit_slow_break = (sh2_icount != before || sh2.test_irq || jit_flush_pending);
+}
+
+/* a store's data into R1 (before the registers change) */
+static void jit_emit_store_data(struct sljit_compiler *C, UINT16 op)
+{
+ int m = OPM(op);
+
+ switch ((op >> 12) & 15)
+ {
+ case 4:
+ switch (op & 0x3f)
+ {
+ case 0x02: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JMEM(offsetof(SH2, mach))); break;
+ case 0x12: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JMEM(offsetof(SH2, macl))); break;
+ case 0x22: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JMEM(offsetof(SH2, pr))); break;
+ case 0x03: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JMEM(offsetof(SH2, sr))); break;
+ case 0x13: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JMEM(offsetof(SH2, gbr))); break;
+ default: sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JMEM(offsetof(SH2, vbr))); break; /* 0x23 */
+ }
+ break;
+ case 8: /* MOV.B/W R0,@(disp,Rn) */
+ case 12: /* MOV.x R0,@(disp,GBR) */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JREG(0));
+ break;
+ default: /* Rm,@(R0,Rn), Rm,@(disp,Rn), Rm,@Rn, Rm,@-Rn */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, JREG(m));
+ break;
+ }
+}
+
+static void jit_emit_mem(struct jit_ctx *ctx, UINT16 op, UINT32 pc, UINT32 index)
+{
+ struct sljit_compiler *C = ctx->C;
+ struct sljit_jump *slow[JIT_MAX_FASTRAM + 2];
+ struct sljit_jump *done;
+ struct sljit_label *label;
+ struct jit_mem mi;
+ int nslow = 0, i, slowread;
+
+ jit_mem_info(op, &mi);
+ /* not in a delay slot (the slot's address is not its block index) */
+ slowread = pc == ctx->pc + index * 2;
+#ifdef SH2JIT_VERIFY
+ /* the check runs the block twice: a handler must not see a read twice */
+ slowread = 0;
+#endif
+ jit_emit_mem_ea(C, op, pc, &mi);
+ jit_emit_mem_check(ctx, mi.size, mi.store, index, slowread ? slow : NULL, &nslow);
+ jit_emit_mem_access(C, op, &mi);
+ if (!slowread)
+ return;
+ done = sljit_emit_jump(C, SLJIT_JUMP);
+
+ label = sljit_emit_label(C);
+ for (i = 0; i < nslow; i++)
+ sljit_set_label(slow[i], label);
+ /* R0 = the address: the memory system does the access as in the interpreter */
+ jit_emit_sub_cycles(C, ctx->pre[index]);
+ sljit_emit_op1(C, SLJIT_MOV32, JMEM(offsetof(SH2, pc)), SLJIT_IMM, (sljit_sw)(INT32)(pc + 2));
+ sljit_emit_op1(C, SLJIT_MOV32, JMEM(offsetof(SH2, ppc)), SLJIT_IMM, (sljit_sw)(INT32)(pc + 2));
+ if (mi.store)
+ {
+ jit_emit_store_data(C, op);
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, mi.size);
+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS3V(32, 32, 32), SLJIT_IMM, SLJIT_FUNC_ADDR(jit_slow_write));
+ }
+ else
+ {
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, mi.size);
+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(32, 32, 32), SLJIT_IMM, SLJIT_FUNC_ADDR(jit_slow_read));
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_RETURN_REG, 0);
+ }
+ if (ctx->pre[index])
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_MEM0(), (sljit_sw)&sh2_icount, SLJIT_MEM0(), (sljit_sw)&sh2_icount, SLJIT_IMM, ctx->pre[index]);
+ if (mi.store)
+ {
+ /* @-Rn: Rn changes after the store (the interpreter's order makes no difference) */
+ if ((((op >> 12) & 15) == 2 && (op & 4)) || ((op >> 12) & 15) == 4)
+ sljit_emit_op2(C, SLJIT_SUB32, JREG(OPN(op)), JREG(OPN(op)), SLJIT_IMM, mi.size);
+ }
+ else
+ jit_emit_load_result(C, op, &mi);
+ jit_add_exit(ctx, sljit_emit_cmp(C, SLJIT_NOT_EQUAL | SLJIT_32, SLJIT_MEM0(), (sljit_sw)&jit_slow_break, SLJIT_IMM, 0), index + 1);
+
+ sljit_set_label(done, sljit_emit_label(C));
+}
+
+/*
+ MAC.L, MAC.W, AND.B/OR.B/XOR.B/TST.B @(R0,GBR) and TAS.B: check the
+ addresses the interpreter will use, then let it run the instruction
+ (through fast RAM only, so no memory handler runs inside a block).
+*/
+static void jit_emit_helper_mem(struct jit_ctx *ctx, UINT16 op, UINT32 index)
+{
+ struct sljit_compiler *C = ctx->C;
+ int n = OPN(op), m = OPM(op);
+ int store = 0;
+
+ if (((op >> 12) & 15) == 0 || (((op >> 12) & 15) == 4 && (op & 15) == 15))
+ {
+ /* MAC.L / MAC.W @Rm+,@Rn+: Rn is read first, then Rm (Rn + size when the same) */
+ int size = (((op >> 12) & 15) == 0) ? 4 : 2;
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n));
+ jit_emit_mem_check(ctx, size, 0, index, NULL, NULL);
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_S1, 0, SLJIT_R1, 0);
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(m));
+ if (m == n)
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, size);
+ jit_emit_mem_check(ctx, size, 0, index, NULL, NULL);
+#if JIT_HOST64
+ if (size == 4)
+ {
+ /*
+ MAC.L without saturation (S clear) in native code: the signed
+ 64-bit product added to MACH:MACL, wrapping; with S set the
+ interpreter runs it. The 2 extra cycles are the helper's own
+ on that path, so they are taken here on this one.
+ */
+ struct sljit_jump *sat, *done;
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, JSR_, SLJIT_IMM, S);
+ sat = sljit_emit_jump(C, SLJIT_NOT_ZERO);
+ sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0);
+ sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), 0);
+ sljit_emit_op2(C, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);
+ sljit_emit_op1(C, SLJIT_MOV_U32, SLJIT_R2, 0, JMACH);
+ sljit_emit_op2(C, SLJIT_SHL, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 32);
+ sljit_emit_op1(C, SLJIT_MOV_U32, SLJIT_R3, 0, JMACL);
+ sljit_emit_op2(C, SLJIT_OR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_R3, 0);
+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R2, 0);
+ sljit_emit_op1(C, SLJIT_MOV32, JMACL, SLJIT_R0, 0);
+ sljit_emit_op2(C, SLJIT_LSHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 32);
+ sljit_emit_op1(C, SLJIT_MOV32, JMACH, SLJIT_R0, 0);
+ sljit_emit_op2(C, SLJIT_ADD32, JREG(n), JREG(n), SLJIT_IMM, 4);
+ sljit_emit_op2(C, SLJIT_ADD32, JREG(m), JREG(m), SLJIT_IMM, 4);
+ jit_emit_sub_cycles(C, 2);
+ done = sljit_emit_jump(C, SLJIT_JUMP);
+ sljit_set_label(sat, sljit_emit_label(C));
+ jit_emit_helper(C, op);
+ sljit_set_label(done, sljit_emit_label(C));
+ return;
+ }
+#endif
+ }
+ else if (((op >> 12) & 15) == 4)
+ {
+ /* TAS.B @Rn */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R0, 0, JREG(n));
+ jit_emit_mem_check(ctx, 1, 1, index, NULL, NULL);
+ store = 1;
+ }
+ else
+ {
+ /* AND.B / OR.B / XOR.B / TST.B #imm,@(R0,GBR) */
+ store = OPN(op) != 12;
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_R0, 0, JGBR, JREG(0));
+ jit_emit_mem_check(ctx, 1, store, index, NULL, NULL);
+ }
+#ifdef SH2JIT_VERIFY
+ if (store)
+ {
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_R1, 0);
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 1);
+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2V(P, 32), SLJIT_IMM, SLJIT_FUNC_ADDR(jit_verify_log_store));
+ }
+#else
+ (void)store;
+#endif
+ jit_emit_helper(C, op);
+}
+
+/* a plain instruction (not a branch) */
+static void jit_emit_one(struct jit_ctx *ctx, UINT16 op, const struct jit_op *o, UINT32 pc, UINT32 index)
+{
+ switch (o->kind)
+ {
+ case JIT_MEM:
+ jit_emit_mem(ctx, op, pc, index);
+ break;
+ case JIT_HELPER:
+ jit_emit_helper(ctx->C, op);
+ break;
+ case JIT_HELPER_MEM:
+ jit_emit_helper_mem(ctx, op, index);
+ break;
+ default:
+ jit_emit_simple(ctx, op, pc);
+ break;
+ }
+}
+
+
+/*************************************
+ * Branches
+ *************************************/
+
+/* BSR, BSRF and JSR write PR */
+static int jit_branch_links(UINT16 op)
+{
+ return ((op >> 12) & 15) == 11 || (op & 0xf0ff) == 0x0003 || (op & 0xf0ff) == 0x400b;
+}
+
+/* does the instruction read or write PR? */
+static int jit_touches_pr(UINT16 op)
+{
+ return (op & 0xf0ff) == 0x002a || /* STS PR,Rn */
+ (op & 0xf0ff) == 0x4022 || /* STS.L PR,@-Rn */
+ (op & 0xf0ff) == 0x402a || /* LDS Rm,PR */
+ (op & 0xf0ff) == 0x4026; /* LDS.L @Rm+,PR */
+}
+
+/*
+ Block chaining. Leaving for an address whose block is translated and
+ fits in what is left of the timeslice, jump straight into it instead
+ of returning to the dispatcher (sh2_jit_run), which would do the
+ same: no delay slot or interrupt test is pending on the way out of a
+ block, so it would look the block up, check that its cycles fit and
+ run it. All blocks share one stack frame (same sljit_emit_enter), so
+ the jump lands after the prologue and the block's own return goes
+ back to the dispatcher. The check reads the block table when it runs:
+ blocks compiled, replaced or flushed later are seen, and a block that
+ is not there or does not fit is simply a return to the dispatcher.
+*/
+static INLINE UINT32 jit_table_index(UINT32 pc)
+{
+ return (pc >> 1) & (JIT_TABLE_SIZE - 1);
+}
+
+static void jit_emit_chain(struct sljit_compiler *C, sljit_s32 src, sljit_sw srcw)
+{
+#ifndef SH2JIT_VERIFY
+ struct sljit_jump *miss[3];
+ struct sljit_label *out;
+ int i;
+
+ if (src == SLJIT_IMM)
+ {
+ UINT32 target = (UINT32)srcw;
+ if (target & 1)
+ return;
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&jit_table[jit_table_index(target)]);
+ miss[0] = sljit_emit_cmp(C, SLJIT_NOT_EQUAL | SLJIT_32, SLJIT_MEM1(SLJIT_R1), offsetof(struct jit_block, pc), SLJIT_IMM, (sljit_sw)(INT32)target);
+ }
+ else
+ {
+ /* R1 = &jit_table[(pc >> 1) & mask] */
+ sljit_emit_op2(C, SLJIT_LSHR32, SLJIT_R1, 0, src, srcw, SLJIT_IMM, 1);
+ sljit_emit_op2(C, SLJIT_AND32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, JIT_TABLE_SIZE - 1);
+ /* upper bits of a 32-bit result are undefined for word operations */
+ sljit_emit_op1(C, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0);
+ sljit_emit_op2(C, SLJIT_MUL, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(struct jit_block));
+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)jit_table);
+ miss[0] = sljit_emit_cmp(C, SLJIT_NOT_EQUAL | SLJIT_32, SLJIT_MEM1(SLJIT_R1), offsetof(struct jit_block, pc), src, srcw);
+ }
+ /* entry is NULL for a block that is flushed, being compiled or not translatable */
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), offsetof(struct jit_block, entry));
+ miss[1] = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_IMM, 0);
+ sljit_emit_op1(C, SLJIT_MOV32_U16, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), offsetof(struct jit_block, cost));
+ miss[2] = sljit_emit_cmp(C, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R1, 0, SLJIT_MEM0(), (sljit_sw)&sh2_icount);
+ sljit_emit_ijump(C, SLJIT_JUMP, SLJIT_R2, 0);
+ out = sljit_emit_label(C);
+ for (i = 0; i < 3; i++)
+ sljit_set_label(miss[i], out);
+#endif
+}
+
+/* leave the block for the address in src/srcw after taking 'cycles' */
+static void jit_emit_leave(struct sljit_compiler *C, UINT32 cycles, sljit_s32 src, sljit_sw srcw)
+{
+ jit_emit_sub_cycles(C, cycles);
+ jit_emit_chain(C, src, srcw);
+ sljit_emit_return(C, SLJIT_MOV32, src, srcw);
+}
+
+/* leave for the interpreter at 'pc' (a side exit): no chaining */
+static void jit_emit_exit(struct sljit_compiler *C, UINT32 cycles, UINT32 pc)
+{
+ jit_emit_sub_cycles(C, cycles);
+ sljit_emit_return(C, SLJIT_MOV32, SLJIT_IMM, (sljit_sw)(INT32)pc);
+}
+
+/*
+ Branch at instruction 'index' (address pc). BT/BF leave when taken.
+ The others have a delay slot (instruction index + 1): its address
+ checks come first (a side exit leaves before the branch), then the
+ branch takes its target and writes PR as the interpreter does, then
+ the slot runs. BT/S and BF/S not taken just go on with the slot as
+ the next instruction.
+*/
+static void jit_emit_branch(struct jit_ctx *ctx, UINT16 op, UINT16 slot, UINT32 pc, UINT32 index)
+{
+ struct sljit_compiler *C = ctx->C;
+ int n = OPN(op);
+ INT32 disp8 = (INT32)(INT8)(op & 0xff);
+ INT32 disp12 = ((INT32)(op & 0xfff) << 20) >> 20;
+ struct jit_op so;
+ struct sljit_jump *skip = NULL;
+ int cond = 0, taken_if_t = 0;
+
+ switch ((op >> 12) & 15)
+ {
+ case 8:
+ switch (OPN(op))
+ {
+ case 9: cond = 1; taken_if_t = 1; break; /* BT */
+ case 11: cond = 1; taken_if_t = 0; break; /* BF */
+ case 13: cond = 2; taken_if_t = 1; break; /* BT/S */
+ case 15: cond = 2; taken_if_t = 0; break; /* BF/S */
+ }
+ break;
+ }
+
+ if (cond == 1)
+ {
+ /* taken: 3 cycles, not taken: 1 */
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, JSR_, SLJIT_IMM, T);
+ skip = sljit_emit_jump(C, taken_if_t ? SLJIT_ZERO : SLJIT_NOT_ZERO);
+ jit_emit_leave(C, ctx->pre[index] + 3, SLJIT_IMM, (sljit_sw)(INT32)(pc + 4 + disp8 * 2));
+ sljit_set_label(skip, sljit_emit_label(C));
+ return;
+ }
+
+ jit_decode(slot, 0, &so);
+
+ if (cond == 2)
+ {
+ /* not taken: on with the slot as a plain instruction */
+ sljit_emit_op2u(C, SLJIT_AND32 | SLJIT_SET_Z, JSR_, SLJIT_IMM, T);
+ skip = sljit_emit_jump(C, taken_if_t ? SLJIT_ZERO : SLJIT_NOT_ZERO);
+ /* taken: the slot, then leave (2 cycles for the branch, the slot's own) */
+ jit_emit_one(ctx, slot, &so, pc + 2, index);
+ jit_emit_leave(C, ctx->pre[index] + 2 + so.acct, SLJIT_IMM, (sljit_sw)(INT32)(pc + 4 + disp8 * 2));
+ sljit_set_label(skip, sljit_emit_label(C));
+ return;
+ }
+
+ /* jumps: the target into S2 before the slot can change anything */
+ switch ((op >> 12) & 15)
+ {
+ case 0:
+ if ((op & 0x3f) == 0x0b) /* RTS */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_S2, 0, JPR);
+ else /* BSRF / BRAF: Rm + the branch + 4 */
+ sljit_emit_op2(C, SLJIT_ADD32, SLJIT_S2, 0, JREG(n), SLJIT_IMM, (sljit_sw)(INT32)(pc + 4));
+ break;
+ case 4: /* JSR / JMP */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_S2, 0, JREG(n));
+ break;
+ default: /* BRA / BSR */
+ sljit_emit_op1(C, SLJIT_MOV32, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)(INT32)(pc + 4 + disp12 * 2));
+ break;
+ }
+ /* the slot (its side exits leave before the branch), then PR: the */
+ /* block builder keeps a slot that touches PR out of linking jumps */
+ jit_emit_one(ctx, slot, &so, pc + 2, index);
+ if (jit_branch_links(op))
+ sljit_emit_op1(C, SLJIT_MOV32, JPR, SLJIT_IMM, (sljit_sw)(INT32)(pc + 4));
+ {
+ struct jit_op bo;
+ jit_decode(op, 0, &bo);
+ jit_emit_leave(C, ctx->pre[index] + bo.acct + so.acct, SLJIT_S2, 0);
+ }
+}
+
+
+/*************************************
+ * Debug: every block also runs through the interpreter
+ *************************************/
+
+#ifdef SH2JIT_VERIFY
+#define SH2JIT_VLOG 512
+
+static struct
+{
+ UINT8 * p;
+ int size;
+ UINT8 old[4];
+} jit_vlog[SH2JIT_VLOG];
+static int jit_vlog_count;
+static struct
+{
+ UINT32 address;
+ int size;
+} interp_vlog[SH2JIT_VLOG];
+static int interp_vlog_count;
+int sh2_jit_verify_logging;
+
+static void SLJIT_FUNC jit_verify_log_store(sljit_up host, sljit_u32 size)
+{
+ if (jit_vlog_count < SH2JIT_VLOG)
+ {
+ jit_vlog[jit_vlog_count].p = (UINT8 *)host;
+ jit_vlog[jit_vlog_count].size = size;
+ memcpy(jit_vlog[jit_vlog_count].old, (void *)host, size);
+ jit_vlog_count++;
+ }
+}
+
+/* called by WB/WW/WL while the interpreter checks a block */
+void sh2_jit_verify_store(UINT32 address, int size)
+{
+ if (interp_vlog_count < SH2JIT_VLOG)
+ {
+ interp_vlog[interp_vlog_count].address = address & AM;
+ interp_vlog[interp_vlog_count].size = size;
+ interp_vlog_count++;
+ }
+}
+
+static UINT8 *jit_host(UINT32 address, int size)
+{
+ struct jit_fastram *ram = jit_find_ram(address & AM, size);
+ UINT32 off;
+ if (!ram)
+ return NULL;
+ off = (address & AM) - ram->start;
+ return ram->base + (off ^ (size == 1 ? 3 : size == 2 ? 2 : 0));
+}
+
+static void sh2_step(void);
+
+/* runs the block, then the interpreter from the same state, and compares */
+static UINT32 jit_verify_block(struct jit_block *block)
+{
+ static SH2 save, jres;
+ static UINT8 jnew[SH2JIT_VLOG][4];
+ static unsigned long blocks;
+ int before = sh2_icount, after, i, j, bad = 0;
+ UINT32 jpc;
+
+ save = sh2;
+ jit_vlog_count = 0;
+ jpc = ((jit_func)block->code)();
+ after = sh2_icount;
+ jres = sh2;
+ for (i = 0; i < jit_vlog_count; i++)
+ memcpy(jnew[i], jit_vlog[i].p, jit_vlog[i].size);
+ for (i = jit_vlog_count - 1; i >= 0; i--)
+ memcpy(jit_vlog[i].p, jit_vlog[i].old, jit_vlog[i].size);
+ sh2 = save;
+ sh2_icount = before;
+ if (after == before)
+ return jpc;
+
+ interp_vlog_count = 0;
+ sh2_jit_verify_logging = 1;
+ while (before - sh2_icount < before - after)
+ sh2_step();
+ sh2_jit_verify_logging = 0;
+
+ if (sh2.pc != jpc || sh2_icount != after || sh2.delay ||
+ memcmp(sh2.r, jres.r, sizeof(sh2.r)) || sh2.sr != jres.sr || sh2.gbr != jres.gbr ||
+ sh2.vbr != jres.vbr || sh2.pr != jres.pr || sh2.mach != jres.mach || sh2.macl != jres.macl)
+ bad = 1;
+ for (i = 0; i < jit_vlog_count; i++)
+ if (memcmp(jnew[i], jit_vlog[i].p, jit_vlog[i].size))
+ bad |= 2;
+ for (i = 0; i < interp_vlog_count; i++)
+ {
+ int found = 0;
+ UINT8 *h = jit_host(interp_vlog[i].address, interp_vlog[i].size);
+ for (j = 0; j < jit_vlog_count; j++)
+ if (h && jit_vlog[j].p == h)
+ found = 1;
+ if (!found)
+ bad |= 4;
+ }
+ blocks++;
+ if (jit_vlog_count >= SH2JIT_VLOG || interp_vlog_count >= SH2JIT_VLOG)
+ bad = 0;
+ if (bad)
+ {
+ fprintf(stderr, "SH2JITVERIFY mismatch %d at block %08x (%u instructions, cost %u), cpu %d, block #%lu\n",
+ bad, save.pc, block->len, block->cost, cpu_getactivecpu(), blocks);
+ fprintf(stderr, "SH2JITVERIFY pc i=%08x j=%08x icount before %d i=%d j=%d delay %08x\n", sh2.pc, jpc, before, sh2_icount, after, sh2.delay);
+ fprintf(stderr, "SH2JITVERIFY sr %08x/%08x gbr %08x/%08x pr %08x/%08x mach %08x/%08x macl %08x/%08x\n",
+ sh2.sr, jres.sr, sh2.gbr, jres.gbr, sh2.pr, jres.pr, sh2.mach, jres.mach, sh2.macl, jres.macl);
+ for (i = 0; i < 16; i++)
+ if (sh2.r[i] != jres.r[i] || save.r[i] != sh2.r[i])
+ fprintf(stderr, "SH2JITVERIFY r%-2d before %08x interp %08x jit %08x%s\n", i, save.r[i], sh2.r[i], jres.r[i], sh2.r[i] != jres.r[i] ? " <<<" : "");
+ for (i = 0; i < interp_vlog_count; i++)
+ fprintf(stderr, "SH2JITVERIFY interp store %08x size %d\n", interp_vlog[i].address, interp_vlog[i].size);
+ for (i = 0; i < jit_vlog_count; i++)
+ fprintf(stderr, "SH2JITVERIFY jit store %p size %d\n", (void *)jit_vlog[i].p, jit_vlog[i].size);
+ for (i = 0; i < (int)block->len; i++)
+ fprintf(stderr, "SH2JITVERIFY op %08x %04x\n", save.pc + i * 2, jit_fetch(save.pc + i * 2));
+ exit(1);
+ }
+ return sh2.pc;
+}
+#endif
+
+
+/*************************************
+ * Block translation
+ *************************************/
+
+/* the opcode the interpreter would run */
+static UINT16 jit_fetch(UINT32 pc)
+{
+ return sh2.opcode_read ? sh2.opcode_read(pc) : RW(pc & AM);
+}
+
+/* can 'slot' be translated as the delay slot of 'op'? */
+static int jit_slot_ok(UINT16 op, UINT16 slot)
+{
+ struct jit_op so;
+ jit_decode(slot, 0, &so);
+ if (so.kind == JIT_END || so.kind == JIT_BRANCH || so.pcrel)
+ return 0;
+ /* DT reads the next opcode for its busy loop: not from a slot */
+ if ((slot & 0xf0ff) == 0x4010)
+ return 0;
+ if (jit_branch_links(op) && jit_touches_pr(slot))
+ return 0;
+ return 1;
+}
+
+/*
+ The idle loop of Sega's SGL library (vfremix, twcup98 and others),
+ where a CPU waits for a flag set by an interrupt, counting the
+ iterations in or out of vblank:
+
+ loop: MOV.W @R7,R2 ; VDP2 TVSTAT
+ EXTU.W R2,R2
+ AND R1,R2 ; R1 = 8: the vblank bit
+ TST R2,R2
+ BT out ; not in vblank
+ MOV.L @R5,R3 ; ++*R5
+ ADD #1,R3
+ MOV.L R3,@R5
+ BRA next
+ NOP
+ out: MOV.L @R4,R2 ; ++*R4
+ ADD #1,R2
+ MOV.L R2,@R4
+ next: MOV.L @R6,R0
+ CMP/EQ #1,R0
+ BT loop ; while *R6 == 1
+
+ Within a timeslice nothing can change *R6 (the other CPU and the
+ interrupts run between timeslices) nor the vblank bit (the line
+ counter changes between timeslices too), so every iteration takes
+ the same path: 15 cycles out of vblank, 16 in. The whole iterations
+ the timeslice has room for are done at once, leaving one and the
+ rest to the code; registers and flags are those every iteration
+ sets again.
+*/
+#define JIT_IDLE_LEN 16
+static const UINT16 jit_idle_ops[JIT_IDLE_LEN] =
+{
+ 0x6271, 0x622d, 0x2219, 0x2228, 0x8904, 0x6352, 0x7301, 0x2532,
+ 0xa003, 0x0009, 0x6242, 0x7201, 0x2422, 0x6062, 0x8801, 0x89ef
+};
+
+/* the host word of the RAM long at 'address', or NULL if it is not plain RAM of this CPU */
+static INLINE UINT32 *jit_idle_ram(UINT32 address)
+{
+ UINT8 *page;
+ if ((address & 3) || (address & 0xc0000000))
+ return NULL;
+ page = sh2.jit_wpage[(address & AM) >> JIT_PAGE_SHIFT];
+ return page ? (UINT32 *)(page + (address & ((1 << JIT_PAGE_SHIFT) - 1))) : NULL;
+}
+
+static void jit_idle_skip(void)
+{
+ UINT32 *flag, *count;
+ int cost, k;
+
+ if (sh2.delay || sh2.test_irq || !sh2.jit_wpage || ((sh2.r[7] & AM) != 0x05f80004))
+ return;
+ flag = jit_idle_ram(sh2.r[6]);
+ if (!flag || *flag != 1)
+ return;
+ if (((UINT16)RW(sh2.r[7]) & sh2.r[1]) == 0)
+ {
+ count = jit_idle_ram(sh2.r[4]);
+ cost = 15;
+ }
+ else
+ {
+ count = jit_idle_ram(sh2.r[5]);
+ cost = 16;
+ }
+ if (!count || count == flag)
+ return;
+ /* leave a whole iteration and the part of one that ends the timeslice to the code */
+ k = (sh2_icount - 1) / cost - 1;
+ if (k <= 0)
+ return;
+ *count += k;
+ sh2_icount -= k * cost;
+}
+
+static void jit_compile(struct jit_block *block, UINT32 pc)
+{
+ static struct jit_ctx ctx;
+ static UINT16 ops[JIT_MAX_BLOCK + 2];
+ static struct jit_op dec[JIT_MAX_BLOCK + 2];
+ struct jit_fastram *ram;
+ struct sljit_compiler *C;
+ struct sljit_label *entry;
+ UINT32 count = 0, maxcount, i, cost = 0;
+ int ends = 0;
+
+ block->pc = pc;
+ block->cost = 0;
+ block->len = 0;
+ block->valid = 1;
+ block->code = NULL;
+ block->entry = NULL;
+ block->idle = 0;
+ block->op0 = jit_fetch(pc);
+
+ /* code must sit in one fast RAM region, below the special areas */
+ if ((pc & 1) || (pc & 0xc0000000))
+ return;
+ ram = jit_find_ram(pc & AM, 2);
+ if (!ram)
+ return;
+ maxcount = (ram->end - (pc & AM) + 1) / 2;
+ if (maxcount > JIT_MAX_BLOCK)
+ maxcount = JIT_MAX_BLOCK;
+ for (i = 0; i < maxcount; i++)
+ ops[i] = jit_fetch(pc + i * 2);
+
+ ops[maxcount] = (maxcount < (ram->end - (pc & AM) + 1) / 2) ? jit_fetch(pc + maxcount * 2) : 0;
+
+ if (maxcount >= JIT_IDLE_LEN && memcmp(ops, jit_idle_ops, sizeof(jit_idle_ops)) == 0)
+ block->idle = 1;
+
+ /* walk the straight path: conditional branches fall through, jumps end the block */
+ while (count < maxcount && !ends)
+ {
+ jit_decode(ops[count], ops[count + 1], &dec[count]);
+ if (dec[count].kind == JIT_END)
+ break;
+ if (dec[count].kind == JIT_BRANCH && dec[count].slot)
+ {
+ if (count + 2 > maxcount || !jit_slot_ok(ops[count], ops[count + 1]))
+ break;
+ jit_decode(ops[count + 1], 0, &dec[count + 1]);
+ /* BT/S and BF/S go on with the slot as the next instruction */
+ if (((ops[count] >> 12) & 15) != 8)
+ ends = 1;
+ count += 2;
+ continue;
+ }
+ count++;
+ }
+ if (count == 0)
+ return;
+
+ /* cycles the block takes before each instruction, and at most in all */
+ ctx.pre[0] = 0;
+ for (i = 0; i < count; i++)
+ {
+ ctx.pre[i + 1] = ctx.pre[i] + dec[i].acct;
+ cost += dec[i].cost;
+ }
+
+ C = sljit_create_compiler(NULL);
+ if (!C)
+ return;
+ ctx.C = C;
+ ctx.pc = pc;
+ ctx.count = count;
+ ctx.nexits = 0;
+ ctx.overflow = 0;
+#ifdef SH2JIT_VERIFY
+ sljit_emit_enter(C, 0, SLJIT_ARGS0(32), 4, 3, 0);
+#else
+ sljit_emit_enter(C, 0, SLJIT_ARGS0(32), 4, 3, 0);
+#endif
+ /* the active SH-2's state (its context buffer, see sh2p) */
+ sljit_emit_op1(C, SLJIT_MOV_P, SLJIT_S0, 0, SLJIT_MEM0(), (sljit_sw)&sh2p);
+ entry = sljit_emit_label(C);
+
+ for (i = 0; i < count; i++)
+ {
+ UINT32 ipc = pc + i * 2;
+ if (dec[i].kind == JIT_BRANCH)
+ {
+ jit_emit_branch(&ctx, ops[i], ops[i + 1], ipc, i);
+ /* a jump ran its slot too */
+ if (dec[i].slot && ((ops[i] >> 12) & 15) != 8)
+ i++;
+ }
+ else
+ jit_emit_one(&ctx, ops[i], &dec[i], ipc, i);
+ }
+
+ /* straight off the end */
+ if (!ends)
+ jit_emit_leave(C, ctx.pre[count], SLJIT_IMM, (sljit_sw)(INT32)(pc + count * 2));
+
+ /* side exits: resume at that instruction with the interpreter */
+ for (i = 0; i < (UINT32)ctx.nexits; i++)
+ {
+ sljit_set_label(ctx.exits[i].jump, sljit_emit_label(C));
+ jit_emit_exit(C, ctx.pre[ctx.exits[i].index], pc + ctx.exits[i].index * 2);
+ }
+
+ if (ctx.overflow)
+ {
+ /* a jump without a label must not reach sljit_generate_code */
+ sljit_free_compiler(C);
+ return;
+ }
+
+ /* bounded code memory: start again once the budget is used */
+ if (jit_code_bytes > JIT_CODE_BUDGET)
+ {
+ jit_flush();
+ block->pc = pc;
+ block->valid = 1;
+ }
+ block->code = sljit_generate_code(C, 0, NULL);
+ if (block->code)
+ {
+ sljit_uw n_entry = sljit_get_label_addr(entry);
+ /* the idle loop goes through the dispatcher, where it is skipped */
+ block->entry = block->idle ? NULL : (void *)n_entry;
+ jit_code_bytes += sljit_get_generated_code_size(C);
+ }
+ sljit_free_compiler(C);
+ if (!block->code)
+ {
+ if (!jit_nomem_logged)
+ {
+ jit_nomem_logged = 1;
+ log_cb(RETRO_LOG_WARN, LOGPRE "SH-2 recompiler: no executable memory, using the interpreter\n");
+ }
+ return;
+ }
+ block->cost = cost;
+ block->len = count;
+
+ /* remember where translated code lives */
+ if (!ram->readonly)
+ {
+ UINT32 first = ram->mapoff + (((pc & AM) - ram->start) >> 2);
+ UINT32 last = ram->mapoff + (((pc & AM) + count * 2 - 1 - ram->start) >> 2);
+ UINT32 p, c;
+ for (i = first; i <= last; i++)
+ jit_codemap[i] = 1;
+ /* stores to these pages go through the memory system, which flushes on code */
+ for (p = (pc & AM) >> JIT_PAGE_SHIFT; p <= ((pc & AM) + count * 2 - 1) >> JIT_PAGE_SHIFT; p++)
+ {
+ jit_codepage[p] = 1;
+ for (c = 0; c < MAX_CPU; c++)
+ if (jit_wpage[c])
+ jit_wpage[c][p] = NULL;
+ }
+ sh2_jit_code_present = 1;
+ }
+}
+
+/*
+ Runs the block at the PC if there is one and the timeslice has room
+ for all of it: returns 1 when it ran at least one instruction
+ (sh2.pc and sh2_icount updated). Near the end of a timeslice the
+ interpreter steps through the last instructions one by one: blocks
+ are only translated when a long one could run, so those steps do not
+ leave blocks starting at every instruction.
+*/
+static INLINE int sh2_jit_run(void)
+{
+ struct jit_block *block = &jit_table[jit_table_index(sh2.pc)];
+ int before;
+
+ if (!block->valid || block->pc != sh2.pc || (!block->cost && block->op0 != jit_fetch(sh2.pc)))
+ {
+ if (sh2_icount < JIT_MAX_BLOCK * 3)
+ return 0;
+ if (block->code)
+ sljit_free_code(block->code, NULL);
+ jit_compile(block, sh2.pc);
+ }
+ if (!block->cost)
+ return 0;
+ if (!sh2.jit_rpage)
+ {
+ int cpu = cpu_getactivecpu();
+ if (!jit_rpage[cpu] && !jit_build_pages(cpu))
+ return 0;
+ sh2.jit_rpage = jit_rpage[cpu];
+ sh2.jit_wpage = jit_wpage[cpu];
+ }
+ before = sh2_icount;
+ if (block->idle)
+ jit_idle_skip();
+ if (block->cost > sh2_icount)
+ return sh2_icount != before; /* the iterations skipped, if any: the rest steps */
+#ifdef SH2JIT_VERIFY
+ sh2.pc = jit_verify_block(block);
+#else
+ sh2.pc = ((jit_func)block->code)();
+#endif
+ if (jit_flush_pending)
+ {
+ jit_flush_pending = 0;
+ jit_flush();
+ }
+ if (sh2_icount == before)
+ return 0;
+ change_pc32bedw(sh2.pc & AM);
+ /* an interrupt a memory handler raised is taken after its instruction */
+ if (sh2.test_irq)
+ {
+ CHECK_PENDING_IRQ("sh2_jit_run");
+ sh2.test_irq = 0;
+ }
+ return 1;
+}
+
+#else /* !SH2JIT_SUPPORTED */
+
+int sh2_jit_code_present;
+static const int jit_enabled = 0;
+static INLINE int sh2_jit_run(void) { return 0; }
+static void jit_flush(void) { }
+void sh2_jit_ram_written(UINT32 address, UINT32 bytes) { }
+void sh2_jit_add_fastram(offs_t start, offs_t end, int readonly, void *base) { }
+void sh2_jit_set(int enable) { }
+
+#endif /* SH2JIT_SUPPORTED */
diff --git a/src/driver.c b/src/driver.c
index 649b426e..276c320e 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -3576,11 +3576,21 @@ Sep.1994 Quiz Ghost Hunter
DRIVER( rsgun )
DRIVER( sandor )
DRIVER( thunt )
- DRIVER( sassisu )
+ DRIVER( sasissu )
+ DRIVER( sanjeon )
+ DRIVER( critcrsh )
+ DRIVER( tatacot )
+ DRIVER( danchiq )
+ DRIVER( micrombc )
+ DRIVER( patocar )
+ DRIVER( skychal )
+ DRIVER( supgoal )
+ DRIVER( techbowl )
+ DRIVER( wasafari )
DRIVER( seabass )
DRIVER( shanhigw )
DRIVER( shienryu )
- DRIVER( sleague )
+ DRIVER( smleague )
DRIVER( sokyugrt )
DRIVER( sss )
DRIVER( suikoenb )
@@ -3590,6 +3600,8 @@ Sep.1994 Quiz Ghost Hunter
DRIVER( vmahjong )
DRIVER( winterht )
DRIVER( znpwfv )
+ DRIVER( znpwfvt )
+ DRIVER( znpwfve )
DRIVER( danchih )
DRIVER( mausuke )
diff --git a/src/drivers/stv.c b/src/drivers/stv.c
index 74f8b054..320967bd 100644
--- a/src/drivers/stv.c
+++ b/src/drivers/stv.c
@@ -96,17 +96,17 @@ Preliminary Memory map:
#include "cpu/sh2/sh2.h"
#include "machine/stvcd.h"
#include "machine/scudsp.h"
+#include "machine/sega315_5881.h"
+#include "machine/sega315_5838.h"
+#include "state.h"
+#include "includes/stv.h"
#include
-extern data32_t* stv_vdp2_regs;
-extern data32_t* stv_vdp2_vram;
-extern data32_t* stv_vdp2_cram;
-
#define USE_SLAVE 1
/* stvhacks.c */
DRIVER_INIT( ic13 );
-void install_stvbios_speedups(void);
+DRIVER_INIT( smleague );
DRIVER_INIT(bakubaku);
DRIVER_INIT(mausuke);
DRIVER_INIT(puyosun);
@@ -130,39 +130,21 @@ data32_t* stv_workram_h;
static data32_t* stv_backupram;
data32_t* stv_scu;
static data32_t* ioga;
+/* the hopper of the medal games (MAME's ticket dispenser, hopper type) */
+static int stv_hopper, hopper_power, hopper_status;
+static int stv_critcrsh; /* the hammer position on ports A and B */
+static void *hopper_timer;
static data16_t* scsp_regs;
-int stv_vblank;
/*SMPC stuff*/
static UINT8 SCSP_reset;
static void system_reset(void);
static data8_t en_68k;
/*SCU stuff*/
-static int timer_0; /* Counter for Timer 0 irq*/
/*Maybe add these in a struct...*/
-static UINT32 scu_src_0, /* Source DMA lv 0 address*/
- scu_src_1, /* lv 1*/
- scu_src_2, /* lv 2*/
- scu_dst_0, /* Destination DMA lv 0 address*/
- scu_dst_1, /* lv 1*/
- scu_dst_2, /* lv 2*/
- scu_src_add_0, /* Source Addition for DMA lv 0*/
- scu_src_add_1, /* lv 1*/
- scu_src_add_2, /* lv 2*/
- scu_dst_add_0, /* Destination Addition for DMA lv 0*/
- scu_dst_add_1, /* lv 1*/
- scu_dst_add_2; /* lv 2*/
-static INT32 scu_size_0, /* Transfer DMA size lv 0*/
- scu_size_1, /* lv 1*/
- scu_size_2; /* lv 2*/
-
-
-static void dma_direct_lv0(void); /*DMA level 0 direct transfer function*/
-static void dma_direct_lv1(void); /*DMA level 1 direct transfer function*/
-static void dma_direct_lv2(void); /*DMA level 2 direct transfer function*/
-static void dma_indirect_lv0(void); /*DMA level 0 indirect transfer function*/
-static void dma_indirect_lv1(void); /*DMA level 1 indirect transfer function*/
-static void dma_indirect_lv2(void); /*DMA level 2 indirect transfer function*/
+static void scu_dma_trigger(int level); /* start a DMA level */
+static void scu_dma_end(int level);
+static void *scu_dma_timer[3]; /* the end of a DMA level */
int minit_boost,sinit_boost;
@@ -1619,6 +1601,10 @@ static READ32_HANDLER ( cdregister_r ){
exit(1);
}
*/
+ /* no transfer set up (ST-V has no CD drive) */
+ if (CD_info_ptr == NULL || CD_info_count + 1 >= CD_info_size)
+ return 0xffffffff;
+
d = ((UINT16)((UINT8)CD_info_ptr[CD_info_count+0]) << 8) |
(UINT16)((UINT8)CD_info_ptr[CD_info_count+1]);
@@ -1827,6 +1813,11 @@ UINT8 PDR2;
#define SMPC_CONTROL_MODE_PORT_1 IOSEL1 = 0
#define SMPC_CONTROL_MODE_PORT_2 IOSEL2 = 0
+static void smpc_ckchg_nmi(int param)
+{
+ cpu_set_nmi_line(0, PULSE_LINE);
+}
+
static void system_reset()
{
/*Only backup ram and SMPC ram is retained after that this command is issued.*/
@@ -1840,6 +1831,80 @@ static void system_reset()
/*Order is surely wrong but whatever...*/
}
+/* INTBACK as in MAME's SMPC HLE: SR, the peripheral stages with the
+ CONTINUE / BREAK requests in IREG0, and the command timing. ST-V has no
+ pads on the SMPC ports, so no peripheral data is returned, but the SGL
+ handlers of some games (findlove) wait for the stages to end */
+static UINT8 smpc_sr;
+static UINT8 smpc_intback_stage;
+static UINT8 smpc_intback_buf[3];
+static UINT8 smpc_pmode;
+static void *smpc_intback_timer;
+
+static void smpc_intback_continue(int param)
+{
+ if (smpc_intback_stage == 2)
+ {
+ smpc_sr = 0x80 | smpc_pmode; /* pad 2, no more data */
+ smpc_intback_stage = 0;
+ }
+ else
+ {
+ smpc_sr = 0xc0 | smpc_pmode; /* pad 1, more data */
+ smpc_intback_stage++;
+ }
+ stv_scu_raise_irq(7); /* SMPC */
+ smpc_ram[0x5f] = 0x10;
+ smpc_ram[0x63] = 0x00;
+}
+
+static void smpc_intback_resolve(int param)
+{
+ time_t ltime;
+ struct tm *today;
+ time(<ime);
+ today = localtime(<ime);
+
+ if (smpc_intback_buf[0] != 0)
+ {
+ smpc_ram[0x21]=0x80;
+ smpc_ram[0x23] = DectoBCD((today->tm_year + 1900)/100);
+ smpc_ram[0x25] = DectoBCD((today->tm_year + 1900)%100);
+ smpc_ram[0x27] = (today->tm_wday << 4) | (today->tm_mon+1);
+ smpc_ram[0x29] = DectoBCD(today->tm_mday);
+ smpc_ram[0x2b] = DectoBCD(today->tm_hour);
+ smpc_ram[0x2d] = DectoBCD(today->tm_min);
+ smpc_ram[0x2f] = DectoBCD(today->tm_sec);
+ smpc_ram[0x31]=0x00;
+ smpc_ram[0x35]=0x00;
+ smpc_ram[0x37]=0x00;
+ {
+ int i;
+ for (i = 0x39; i <= 0x5d; i += 2)
+ smpc_ram[i] = 0xff;
+ }
+
+ smpc_intback_stage = (smpc_intback_buf[1] & 8) >> 3; /* first peripheral */
+ smpc_sr = 0x40 | (smpc_intback_stage << 5);
+ smpc_pmode = smpc_intback_buf[0] >> 4;
+ stv_scu_raise_irq(7); /* SMPC */
+ smpc_ram[0x5f] = 0x10;
+ smpc_ram[0x63] = 0x00;
+ }
+ else if (smpc_intback_buf[1] & 8)
+ {
+ smpc_intback_stage = 1;
+ smpc_sr = 0x40;
+ smpc_ram[0x5f] = 0x10;
+ smpc_intback_continue(0);
+ }
+ else
+ {
+ smpc_ram[0x5f] = 0x10;
+ smpc_ram[0x63] = 0x00;
+ }
+}
+
static UINT8 stv_SMPC_r8 (int offset)
{
int return_data;
@@ -1847,8 +1912,8 @@ static UINT8 stv_SMPC_r8 (int offset)
return_data = smpc_ram[offset];
- if ((offset == 0x61)) /* ?? many games need this or the controls don't work*/
- return_data = 0x20 ^ 0xff;
+ if (offset == 0x61) /* SR */
+ return_data = smpc_sr;
if (offset == 0x75)/*PDR1 read*/
return_data = readinputport(0);
@@ -1869,14 +1934,25 @@ static UINT8 stv_SMPC_r8 (int offset)
static void stv_SMPC_w8 (int offset, UINT8 data)
{
- time_t ltime;
- struct tm *today;
- time(<ime);
- today = localtime(<ime);
-
/* logerror ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data);*/
smpc_ram[offset] = data;
+ /* IREG0 while under INTBACK: BREAK or CONTINUE */
+ if (offset == 0x01 && smpc_intback_stage)
+ {
+ if (data & 0x40)
+ {
+ smpc_sr &= 0x0f;
+ smpc_intback_stage = 0;
+ }
+ else if (data & 0x80)
+ {
+ timer_adjust(smpc_intback_timer, TIME_IN_USEC(700), 0, 0);
+ smpc_ram[0x5f] = 0x10;
+ smpc_ram[0x63] = 0x01;
+ }
+ }
+
if(offset == 0x75)
{
EEPROM_set_clock_line((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
@@ -1978,62 +2054,33 @@ static void stv_SMPC_w8 (int offset, UINT8 data)
system_reset();
break;
case 0x0e:
- logerror ("SMPC: Change Clock to 352\n");
- smpc_ram[0x5f]=0x0e;
- cpu_set_nmi_line(0,PULSE_LINE); /* ff said this causes nmi, should we set a timer then nmi?*/
- break;
case 0x0f:
- logerror ("SMPC: Change Clock to 320\n");
- smpc_ram[0x5f]=0x0f;
- cpu_set_nmi_line(0,PULSE_LINE); /* ff said this causes nmi, should we set a timer then nmi?*/
+ /* CKCHG352 / CKCHG320: the PLL change stops the slave and the sound CPU
+ and takes about four frames, then an NMI wakes the master from the
+ SLEEP that follows the command in the BIOS (as in MAME) */
+ logerror ("SMPC: Change Clock to %s\n", (data & 1) ? "320" : "352");
+ smpc_ram[0x5f]=data;
+ cpu_set_halt_line(1, ASSERT_LINE);
+ cpu_set_halt_line(2, ASSERT_LINE);
+ en_68k = 0;
+ timer_set(TIME_IN_HZ(60) * 4, 0, smpc_ckchg_nmi);
break;
/*"Interrupt Back"*/
case 0x10:
+ {
+ int timing = 8;
logerror ("SMPC: Status Acquire\n");
- smpc_ram[0x5f]=0x10;
- smpc_ram[0x21]=0x80;
- smpc_ram[0x23] = DectoBCD((today->tm_year + 1900)/100);
- smpc_ram[0x25] = DectoBCD((today->tm_year + 1900)%100);
- smpc_ram[0x27] = (today->tm_wday << 4) | (today->tm_mon+1);
- smpc_ram[0x29] = DectoBCD(today->tm_mday);
- smpc_ram[0x2b] = DectoBCD(today->tm_hour);
- smpc_ram[0x2d] = DectoBCD(today->tm_min);
- smpc_ram[0x2f] = DectoBCD(today->tm_sec);
-
- smpc_ram[0x31]=0x00; /*BHOOOOO*/
-
- /*smpc_ram[0x33]=readinputport(7);*/
-
- smpc_ram[0x35]=0x00;
- smpc_ram[0x37]=0x00;
-
- smpc_ram[0x39]=0xff;
- smpc_ram[0x3b]=0xff;
- smpc_ram[0x3d]=0xff;
- smpc_ram[0x3f]=0xff;
- smpc_ram[0x41]=0xff;
- smpc_ram[0x43]=0xff;
- smpc_ram[0x45]=0xff;
- smpc_ram[0x47]=0xff;
- smpc_ram[0x49]=0xff;
- smpc_ram[0x4b]=0xff;
- smpc_ram[0x4d]=0xff;
- smpc_ram[0x4f]=0xff;
- smpc_ram[0x51]=0xff;
- smpc_ram[0x53]=0xff;
- smpc_ram[0x55]=0xff;
- smpc_ram[0x57]=0xff;
- smpc_ram[0x59]=0xff;
- smpc_ram[0x5b]=0xff;
- smpc_ram[0x5d]=0xff;
-
- /* //This is for RTC,cartridge code and similar stuff.../*/
- /* if(!(stv_scu[40] & 0x0080)) */ /*System Manager(SMPC) irq*/ /* we can't check this .. breaks controls .. probably issues elsewhere? */
- {
- logerror ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline);
- cpu_set_irq_line_and_vector(0, 8, HOLD_LINE , 0x47);
- }
- break;
+ smpc_intback_buf[0] = smpc_ram[0x01];
+ smpc_intback_buf[1] = smpc_ram[0x03];
+ smpc_intback_buf[2] = smpc_ram[0x05];
+ if (smpc_intback_buf[0] != 0) /* non-peripheral data */
+ timing += 8;
+ if (smpc_intback_buf[1] & 8) /* peripheral data */
+ timing += 700;
+ timer_set(TIME_IN_USEC(timing), 0, smpc_intback_resolve);
+ /* the command ends in smpc_intback_resolve */
+ return;
+ }
/* RTC write*/
case 0x16:
log_cb(RETRO_LOG_DEBUG, LOGPRE "SMPC: RTC write\n");
@@ -2136,66 +2183,157 @@ SCU register[40] is for IRQ masking.
/* to do, update bios idle skips so they work better with this arrangement.. */
+/*
+SCU interrupts, as in current MAME: each source sets its bit in the status
+register (IST, also when masked), and the highest priority unmasked pending
+one is raised when no SCU interrupt is being serviced; the CPU takes it with
+the SCU's vector, which ends the service. Level per source:
+
+ bit 0 vblank-in 15, 1 vblank-out 14, 2 hblank-in 13, 3 timer 0 12,
+ 4 timer 1 11, 5 DSP end 10, 6 sound request 9, 7 SMPC 8, 8 pad 8,
+ 9 DMA level 2 6, 10 DMA level 1 6, 11 DMA level 0 5,
+ 12 DMA illegal 3, 13 VDP1 draw end 2
+
+The slave SH-2 sees the blanks on its IRL inputs: hblank-in level 2,
+vblank-out 4, vblank-in 6, 0 at the end of hblank.
+
+Timer 0 counts hblanks from vblank-out and fires on its compare value,
+timer 1 a programmable delay after each hblank (or after a timer 0 hit),
+both only while TENB is set.
+*/
+
+static UINT32 scu_ist; /* pending sources */
+static int scu_irq_level; /* the level being serviced, 0 if none */
+static int scu_irq_vector;
+static void stv_scu_dma_event(int event);
+static int scu_timer0_count;
+static int slave_irl;
+
+static const int scu_irq_levels[14] = { 15, 14, 13, 12, 11, 10, 9, 8, 8, 6, 6, 5, 3, 2 };
+
+static void scu_test_pending_irqs(void)
+{
+ UINT32 ism = stv_scu[40];
+ int i;
+
+ if (scu_irq_level != 0)
+ return;
+
+ for (i = 0; i < 14; i++)
+ {
+ if (!(ism & (1 << i)) && (scu_ist & (1 << i)))
+ {
+ scu_irq_level = scu_irq_levels[i];
+ scu_irq_vector = 0x40 + i;
+ scu_ist &= ~(1 << i);
+ cpu_set_irq_line_and_vector(0, scu_irq_level, HOLD_LINE, scu_irq_vector);
+ return;
+ }
+ }
+}
+
+void stv_scu_raise_irq(int bit)
+{
+ scu_ist |= 1 << bit;
+ scu_test_pending_irqs();
+}
+
+/* the master takes the interrupt: the service is over for the SCU */
+static int stv_master_irq_callback(int irqline)
+{
+ int vector = scu_irq_vector;
+ scu_irq_level = 0;
+ return vector;
+}
+
+static void stv_slave_irl(int level)
+{
+ if (slave_irl == level)
+ return;
+ if (slave_irl)
+ cpu_set_irq_line(1, slave_irl, CLEAR_LINE);
+ slave_irl = level;
+ /* the DCC drops it once taken, else the handler re-enters until the end of the blank */
+ if (level)
+ cpu_set_irq_line(1, level, HOLD_LINE);
+}
+
+static void scu_timer1_cb(int param)
+{
+ stv_scu_dma_event(4);
+ stv_scu_raise_irq(4);
+}
+
+static void stv_hblank_in(int param)
+{
+ stv_slave_irl(2);
+
+ stv_scu_dma_event(2);
+ scu_ist |= 1 << 2;
+
+ if (stv_scu[38] & 1) /* TENB */
+ {
+ int timer0_hit = scu_timer0_count == (stv_scu[36] & 0x3ff);
+ if (timer0_hit)
+ {
+ stv_scu_dma_event(3);
+ scu_ist |= 1 << 3;
+ }
+
+ /* timer 1: every line (mode 0) or after a timer 0 hit (mode 1) */
+ if (timer0_hit || !(stv_scu[38] & 0x100))
+ timer_set(TIME_IN_HZ(57272720 / 8) * (stv_scu[37] & 0x1ff), 0, scu_timer1_cb);
+ }
+ scu_timer0_count = (scu_timer0_count + 1) & 0x1ff;
+
+ scu_test_pending_irqs();
+}
+
+#define STV_LINES 263
+
static INTERRUPT_GEN( stv_interrupt )
{
- scanline = 261-cpu_getiloops();
+ int vblank_line = stv_vdp2_vblank_start_line();
+ scanline = (STV_LINES - 1) - cpu_getiloops();
- if(scanline == 0)
+ /* the end of the previous hblank */
+ stv_slave_irl(0);
+
+ stv_vdp2_scanline(scanline);
+
+ if (scanline == 0)
{
- if(!(stv_scu[40] & 2))/*VBLANK-OUT*/
- {
- logerror ("Interrupt: VBlank-OUT at scanline %04x, Vector 0x41 Level 0x0e\n",scanline);
- cpu_set_irq_line_and_vector(0, 0xe, HOLD_LINE , 0x41);
- stv_vblank = 0;
- return;
- }
+ /* vblank-out */
+ stv_slave_irl(4);
+ stv_scu_dma_event(1);
+ scu_ist |= 1 << 1;
+ scu_test_pending_irqs();
+ scu_timer0_count = 0;
}
- else if(scanline <= 223 && scanline >= 1)/*Correct?*/
+ else if (scanline == vblank_line)
{
- timer_0++;
- if(timer_0 == (stv_scu[36] & 0x1ff))
- {
- if(!(stv_scu[40] & 8))/*Timer 0*/
- {
- logerror ("Interrupt: Timer 0 at scanline %04x, Vector 0x43 Level 0x0c\n",scanline);
- cpu_set_irq_line_and_vector(0, 0xc, HOLD_LINE, 0x43 );
- return;
- }
- }
-
- /*TODO:use this *at the end* of the draw line.*/
- if(!(stv_scu[40] & 4))/*HBLANK-IN*/
- {
- logerror ("Interrupt: HBlank-In at scanline %04x, Vector 0x42 Level 0x0d\n",scanline);
- cpu_set_irq_line_and_vector(0, 0xd, HOLD_LINE , 0x42);
- }
+ /* vblank-in; the VDP1 changes frame and draws (automatic mode) now, as in MAME */
+ stv_slave_irl(6);
+ stv_scu_dma_event(0);
+ stv_scu_raise_irq(0);
+ stv_vdp1_video_update();
}
- else if(scanline == 224)
+ else if (scanline == vblank_line + 1)
{
- timer_0 = 0;
-
- if(!(stv_scu[40] & 1))/*VBLANK-IN*/
- {
- logerror ("Interrupt: VBlank IN at scanline %04x, Vector 0x40 Level 0x0f\n",scanline);
- cpu_set_irq_line_and_vector(0, 0xf, HOLD_LINE , 0x40);
- stv_vblank = 1;
- return;
- }
-
- if(timer_0 == (stv_scu[36] & 0x1ff))
- {
- if(!(stv_scu[40] & 8))/*Timer 0*/
- {
- logerror ("Interrupt: Timer 0 at scanline %04x, Vector 0x43 Level 0x0c\n",scanline);
- cpu_set_irq_line_and_vector(0, 0xc, HOLD_LINE, 0x43 );
- return;
- }
- }
-
-
+ /* the VDP1 erase on VBE comes one line after vblank-in */
+ stv_vdp1_vblank_erase();
+ }
+ else if (scanline == vblank_line + 8)
+ {
+ /* VDP1 draw end, 8 lines after vblank-in as in MAME */
+ stv_scu_dma_event(6);
+ stv_scu_raise_irq(13);
}
+ /* no hblank in vblank */
+ if (scanline < vblank_line)
+ timer_set(TIME_IN_HZ(60 * STV_LINES) * 3 / 4, 0, stv_hblank_in);
}
/*
@@ -2238,6 +2376,30 @@ static UINT8 port_sel,mux_data;
#define HI_WORD_ACCESS (mem_mask & 0x00ff0000) == 0
#define LO_WORD_ACCESS (mem_mask & 0x000000ff) == 0
+static void hopper_tick(int param)
+{
+ /* a medal out every 100ms while the motor runs, the last one ends after it stops */
+ hopper_status ^= 1;
+ if (hopper_power)
+ timer_adjust(hopper_timer, TIME_IN_MSEC(100), 0, 0);
+}
+
+static void hopper_motor_w(int state)
+{
+ if (state && !hopper_power)
+ {
+ hopper_power = 1;
+ hopper_status = 0;
+ timer_adjust(hopper_timer, TIME_IN_MSEC(100), 0, 0);
+ }
+ else if (!state && hopper_power)
+ {
+ if (!hopper_status)
+ timer_adjust(hopper_timer, TIME_NEVER, 0, 0);
+ hopper_power = 0;
+ }
+}
+
READ32_HANDLER ( stv_io_r32 )
{
static int i= -1;
@@ -2266,7 +2428,16 @@ READ32_HANDLER ( stv_io_r32 )
}
}
/*default: usrintf_showmessage("%02x PORT SEL",port_sel);*/
- default: return (readinputport(2) << 16) | (readinputport(3));
+ default:
+ if (stv_critcrsh)
+ {
+ /* the hammer position, with the hit latch */
+ int hit = (readinputport(4) & 0x10) ? 0 : 4;
+ UINT8 x = (BITSWAP8(readinputport(10), 2,3,0,1,6,7,5,4) & 0xf3) | hit;
+ UINT8 y = (BITSWAP8(readinputport(11), 2,3,0,1,6,7,5,4) & 0xf3) | hit;
+ return 0xff00ff00 | (x << 16) | y;
+ }
+ return ((readinputport(2) | (stv_hopper && hopper_status ? 0x02 : 0)) << 16) | (readinputport(3));
}
case 1:
return (readinputport(4) << 16) | (ioga[1]);
@@ -2321,6 +2492,8 @@ WRITE32_HANDLER ( stv_io_w32 )
{
/*Why does the BIOS tests these as ACTIVE HIGH?A program bug?*/
ioga[1] = (data) & 0xff;
+ if (stv_hopper)
+ hopper_motor_w(data & 0x80);
coin_counter_w(0,~data & 0x01);
coin_counter_w(1,~data & 0x02);
coin_lockout_w(0,~data & 0x04);
@@ -2457,29 +2630,7 @@ DMA Status Register:
00 - DSP side DMA in operation
**********************************************************************************/
-/*
-DMA TODO:
--Verify if there are any kind of bugs,do clean-ups,use better comments
- and macroize for better reading...
--Add timings(but how fast are each DMA?).
--Add level priority & DMA status register.
--Add DMA start factor conditions that are different than 7.
--Add byte data type transfer.
-*/
-
-#define DIRECT_MODE(_lv_) (!(stv_scu[5+(_lv_*8)] & 0x01000000))
-#define INDIRECT_MODE(_lv_) (stv_scu[5+(_lv_*8)] & 0x01000000)
-#define DRUP(_lv_) (stv_scu[5+(_lv_*8)] & 0x00010000)
-#define DWUP(_lv_) (stv_scu[5+(_lv_*8)] & 0x00000100)
-
#define DMA_STATUS (stv_scu[31])
-/*These macros sets the various DMA status flags.*/
-#define SET_D0MV_FROM_0_TO_1 if(!(DMA_STATUS & 0x10)) DMA_STATUS^=0x10
-#define SET_D1MV_FROM_0_TO_1 if(!(DMA_STATUS & 0x100)) DMA_STATUS^=0x100
-#define SET_D2MV_FROM_0_TO_1 if(!(DMA_STATUS & 0x1000)) DMA_STATUS^=0x1000
-#define SET_D0MV_FROM_1_TO_0 if(DMA_STATUS & 0x10) DMA_STATUS^=0x10
-#define SET_D1MV_FROM_1_TO_0 if(DMA_STATUS & 0x100) DMA_STATUS^=0x100
-#define SET_D2MV_FROM_1_TO_0 if(DMA_STATUS & 0x1000) DMA_STATUS^=0x1000
READ32_HANDLER( stv_scu_r32 )
{
@@ -2490,6 +2641,10 @@ READ32_HANDLER( stv_scu_r32 )
log_cb(RETRO_LOG_DEBUG, LOGPRE "DSP mem read at %08X\n", stv_scu[34]);
return dsp_ram_addr_r();
}
+ else if ( offset == 41 )
+ return scu_ist;
+ else if ( offset == 0x5c/4 )
+ return DMA_STATUS; /* undocumented DMA status mirror, smleague/finlarch wait on it */
else
{
log_cb(RETRO_LOG_DEBUG, LOGPRE "SCU reg read at %d = %08x\n",offset,stv_scu[offset]);
@@ -2503,142 +2658,17 @@ WRITE32_HANDLER( stv_scu_w32 )
switch(offset)
{
- /*LV 0 DMA*/
- case 0: scu_src_0 = ((stv_scu[0] & 0x07ffffff) >> 0); break;
- case 1: scu_dst_0 = ((stv_scu[1] & 0x07ffffff) >> 0); break;
- case 2: scu_size_0 = ((stv_scu[2] & 0x000fffff) >> 0); break;
- case 3:
- /*Read address add value for DMA lv 0*/
- if(stv_scu[3] & 0x100)
- scu_src_add_0 = 4;
- else
- scu_src_add_0 = 0;/*could be 2...*/
-
- /*Write address add value for DMA lv 0*/
- switch(stv_scu[3] & 7)
- {
- case 0: scu_dst_add_0 = 2; break;
- case 1: scu_dst_add_0 = 4; break;
- case 2: scu_dst_add_0 = 8; break;
- case 3: scu_dst_add_0 = 16; break;
- case 4: scu_dst_add_0 = 32; break;
- case 5: scu_dst_add_0 = 64; break;
- case 6: scu_dst_add_0 = 128; break;
- case 7: scu_dst_add_0 = 256; break;
- }
- break;
+ /* DxEN: DMA enable (bit 8) and start (bit 0, start factor 7) */
case 4:
-/*
--stv_scu[4] bit 0 is DMA starting bit.
- Used when the start factor is 7.Toggle after execution.
--stv_scu[4] bit 8 is DMA Enable bit.
- This is an execution mask flag.
--stv_scu[5] bit 0,bit 1 and bit 2 is DMA starting factor.
- It must be 7 for this specific condition.
--stv_scu[5] bit 24 is Indirect Mode/Direct Mode (0/1).
-*/
- if(stv_scu[4] & 1 && ((stv_scu[5] & 7) == 7) && stv_scu[4] & 0x100)
- {
- if(DIRECT_MODE(0))
- dma_direct_lv0();
- else
- dma_indirect_lv0();
-
- stv_scu[4]^=1;/*disable starting bit.*/
- }
- break;
- case 5:
- if(INDIRECT_MODE(0))
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Indirect Mode DMA lv 0 set\n");
-
- /*Start factor enable bits,bit 2,bit 1 and bit 0*/
- if((stv_scu[5] & 7) != 7)
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start factor chosen for lv 0 = %d\n",stv_scu[5] & 7);
- break;
- /*LV 1 DMA*/
- case 8: scu_src_1 = ((stv_scu[8] & 0x07ffffff) >> 0); break;
- case 9: scu_dst_1 = ((stv_scu[9] & 0x07ffffff) >> 0); break;
- case 10: scu_size_1 = ((stv_scu[10] & 0x00001fff) >> 0); break;
- case 11:
- /*Read address add value for DMA lv 1*/
- if(stv_scu[11] & 0x100)
- scu_src_add_1 = 4;
- else
- scu_src_add_1 = 0;
-
- /*Write address add value for DMA lv 1*/
- switch(stv_scu[11] & 7)
- {
- case 0: scu_dst_add_1 = 2; break;
- case 1: scu_dst_add_1 = 4; break;
- case 2: scu_dst_add_1 = 8; break;
- case 3: scu_dst_add_1 = 16; break;
- case 4: scu_dst_add_1 = 32; break;
- case 5: scu_dst_add_1 = 64; break;
- case 6: scu_dst_add_1 = 128; break;
- case 7: scu_dst_add_1 = 256; break;
- }
- break;
case 12:
- if(stv_scu[12] & 1 && ((stv_scu[13] & 7) == 7) && stv_scu[12] & 0x100)
- {
- if(DIRECT_MODE(1))
- dma_direct_lv1();
- else
- dma_indirect_lv1();
-
- stv_scu[12]^=1;
- }
- break;
- case 13:
- if(INDIRECT_MODE(1))
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Indirect Mode DMA lv 1 set\n");
-
- if((stv_scu[13] & 7) != 7)
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start factor chosen for lv 1 = %d\n",stv_scu[13] & 7);
- break;
- /*LV 2 DMA*/
- case 16: scu_src_2 = ((stv_scu[16] & 0x07ffffff) >> 0); break;
- case 17: scu_dst_2 = ((stv_scu[17] & 0x07ffffff) >> 0); break;
- case 18: scu_size_2 = ((stv_scu[18] & 0x00001fff) >> 0); break;
- case 19:
- /*Read address add value for DMA lv 2*/
- if(stv_scu[19] & 0x100)
- scu_src_add_2 = 4;
- else
- scu_src_add_2 = 0;
-
- /*Write address add value for DMA lv 2*/
- switch(stv_scu[19] & 7)
- {
- case 0: scu_dst_add_2 = 2; break;
- case 1: scu_dst_add_2 = 4; break;
- case 2: scu_dst_add_2 = 8; break;
- case 3: scu_dst_add_2 = 16; break;
- case 4: scu_dst_add_2 = 32; break;
- case 5: scu_dst_add_2 = 64; break;
- case 6: scu_dst_add_2 = 128; break;
- case 7: scu_dst_add_2 = 256; break;
- }
- break;
case 20:
- if(stv_scu[20] & 1 && ((stv_scu[21] & 7) == 7) && stv_scu[20] & 0x100)
{
- if(DIRECT_MODE(2))
- dma_direct_lv2();
- else
- dma_indirect_lv2();
-
- stv_scu[20]^=1;
+ int level = offset / 8;
+ if ((stv_scu[offset] & 0x101) == 0x101 && (stv_scu[offset + 1] & 7) == 7)
+ scu_dma_trigger(level);
+ stv_scu[offset] &= ~1;
+ break;
}
- break;
- case 21:
- if(INDIRECT_MODE(2))
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Indirect Mode DMA lv 2 set\n");
-
- if((stv_scu[21] & 7) != 7)
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start factor chosen for lv 2 = %d\n",stv_scu[21] & 7);
- break;
case 31: log_cb(RETRO_LOG_DEBUG, LOGPRE "Warning: DMA status WRITE! Offset %02x(%d)\n",offset*4,offset); break;
/*DSP section*/
/*Use functions so it is easier to work out*/
@@ -2687,10 +2717,12 @@ WRITE32_HANDLER( stv_scu_w32 )
stv_scu[offset] & 0x0002 ? 1 : 0, /*VBlank-OUT*/
stv_scu[offset] & 0x0001 ? 1 : 0);/*VBlank-IN*/
}
+ scu_test_pending_irqs();
break;
case 41:
- /*This is r/w by introdon...*/
- log_cb(RETRO_LOG_DEBUG, LOGPRE "IRQ status reg set:%08x\n",stv_scu[41]);
+ /* writing 0 bits acknowledges pending sources */
+ scu_ist &= data | mem_mask;
+ scu_test_pending_irqs();
break;
case 42: /*A-Bus IRQ ACK*/ break;
case 49: /*This sets the SDRAM size*/ break;
@@ -2698,294 +2730,169 @@ WRITE32_HANDLER( stv_scu_w32 )
}
}
-
-static void dma_direct_lv0()
+/* the DMA start factors other than the start bit (as in MAME): 0 vblank-in,
+ 1 vblank-out, 2 hblank-in, 3 timer 0, 4 timer 1, 5 sound request, 6 VDP1 end */
+static void stv_scu_dma_event(int event)
{
- static UINT32 tmp_src,tmp_dst,tmp_size;
- logerror("DMA lv 0 transfer START\n"
- "Start %08x End %08x Size %04x\n",scu_src_0,scu_dst_0,scu_size_0);
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start Add %04x Destination Add %04x\n",scu_src_add_0,scu_dst_add_0);
-
- SET_D0MV_FROM_0_TO_1;
-
- tmp_size = scu_size_0;
- if(!(DRUP(0))) tmp_src = scu_src_0;
- if(!(DWUP(0))) tmp_dst = scu_dst_0;
-
- for (; scu_size_0 > 0; scu_size_0-=scu_dst_add_0)
- {
- if(scu_dst_add_0 == 2)
- cpu_writemem16bew_word(scu_dst_0,cpu_readmem16bew_word(scu_src_0));
- else
- cpu_writemem32bedw_dword(scu_dst_0,cpu_readmem32bedw_dword(scu_src_0));
-
- scu_dst_0+=scu_dst_add_0;
- scu_src_0+=scu_src_add_0;
- }
-
- scu_size_0 = tmp_size;
- if(!(DRUP(0))) scu_src_0 = tmp_src;
- if(!(DWUP(0))) scu_dst_0 = tmp_dst;
-
- log_cb(RETRO_LOG_DEBUG, LOGPRE "DMA transfer END\n");
- if(!(stv_scu[40] & 0x800))/*Lv 0 DMA end irq*/
- cpu_set_irq_line_and_vector(0, 5, HOLD_LINE , 0x4b);
-
- SET_D0MV_FROM_1_TO_0;
+ int level;
+ for (level = 0; level < 3; level++)
+ if ((stv_scu[level * 8 + 4] & 0x100) && (stv_scu[level * 8 + 5] & 7) == event)
+ scu_dma_trigger(level);
}
-static void dma_direct_lv1()
+
+/*
+SCU DMA, as in current MAME (saturn_scu.cpp), except that the data is moved at
+once. A direct transfer halts the SH-2s while it runs: the CPU that started
+it loses the time and the level is free at once, the end interrupt comes
+after the transfer time. An indirect one leaves the CPUs free:
+the level stays busy and its end interrupt comes after the time of the
+transfer (one word per clock, MAME's ticks).
+- a transfer to the work RAM H (C-bus) always writes consecutive words, whatever
+ the add value (astrass, vmahjong, pblbeach)
+- a direct transfer between the same bus, or from an address the SCU can't read
+ (BIOS, work RAM L, backup RAM), is illegal and only raises the illegal DMA irq
+*/
+
+/* the bus of an address: 0 none, 1 A-bus, 2 B-bus, 3 C-bus */
+static int scu_dma_bus(UINT32 address)
{
- static UINT32 tmp_src,tmp_dst,tmp_size;
- logerror("DMA lv 1 transfer START\n"
- "Start %08x End %08x Size %04x\n",scu_src_1,scu_dst_1,scu_size_1);
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start Add %04x Destination Add %04x\n",scu_src_add_1,scu_dst_add_1);
-
- SET_D1MV_FROM_0_TO_1;
-
- tmp_size = scu_size_1;
- if(!(DRUP(1))) tmp_src = scu_src_1;
- if(!(DWUP(1))) tmp_dst = scu_dst_1;
-
- for (; scu_size_1 > 0; scu_size_1-=scu_dst_add_1)
+ switch (address & 0x07000000)
{
- if(scu_dst_add_1 == 2)
- cpu_writemem16bew_word(scu_dst_1,cpu_readmem16bew_word(scu_src_1));
- else
- cpu_writemem32bedw_dword(scu_dst_1,cpu_readmem32bedw_dword(scu_src_1));
-
- scu_dst_1+=scu_dst_add_1;
- scu_src_1+=scu_src_add_1;
- }
-
- scu_size_1 = tmp_size;
- if(!(DRUP(1))) scu_src_1 = tmp_src;
- if(!(DWUP(1))) scu_dst_1 = tmp_dst;
-
- log_cb(RETRO_LOG_DEBUG, LOGPRE "DMA transfer END\n");
- if(!(stv_scu[40] & 0x400))/*Lv 1 DMA end irq*/
- cpu_set_irq_line_and_vector(0, 6, HOLD_LINE , 0x4a);
-
- SET_D1MV_FROM_1_TO_0;
-}
-
-static void dma_direct_lv2()
-{
- static UINT32 tmp_src,tmp_dst,tmp_size;
- logerror("DMA lv 2 transfer START\n"
- "Start %08x End %08x Size %04x\n",scu_src_2,scu_dst_2,scu_size_2);
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start Add %04x Destination Add %04x\n",scu_src_add_2,scu_dst_add_2);
-
- SET_D2MV_FROM_0_TO_1;
-
- tmp_size = scu_size_2;
- if(!(DRUP(2))) tmp_src = scu_src_2;
- if(!(DWUP(2))) tmp_dst = scu_dst_2;
-
- for (; scu_size_2 > 0; scu_size_2-=scu_dst_add_2)
- {
- if(scu_dst_add_2 == 2)
- cpu_writemem16bew_word(scu_dst_2,cpu_readmem16bew_word(scu_src_2));
- else
- cpu_writemem32bedw_dword(scu_dst_2,cpu_readmem32bedw_dword(scu_src_2));
-
- scu_dst_2+=scu_dst_add_2;
- scu_src_2+=scu_src_add_2;
- }
-
- scu_size_2 = tmp_size;
- if(!(DRUP(2))) scu_src_2 = tmp_src;
- if(!(DWUP(2))) scu_dst_2 = tmp_dst;
-
- log_cb(RETRO_LOG_DEBUG, LOGPRE "DMA transfer END\n");
- if(!(stv_scu[40] & 0x200))/*Lv 2 DMA end irq*/
- cpu_set_irq_line_and_vector(0, 6, HOLD_LINE , 0x49);
-
- SET_D2MV_FROM_1_TO_0;
-}
-
-static void dma_indirect_lv0()
-{
- /*Helper to get out of the cycle*/
- UINT8 job_done = 0;
- /*temporary storage for the transfer data*/
- UINT32 tmp_src;
-
- SET_D0MV_FROM_0_TO_1;
-
- do{
- tmp_src = scu_dst_0;
-
- /*Thanks for Runik of Saturnin for pointing this out...*/
- scu_size_0 = cpu_readmem32bedw_dword(scu_dst_0);
- scu_src_0 = cpu_readmem32bedw_dword(scu_dst_0+8);
- scu_dst_0 = cpu_readmem32bedw_dword(scu_dst_0+4);
-
- /*Indirect Mode end factor*/
- if(scu_src_0 & 0x80000000)
- job_done = 1;
-
- logerror("DMA lv 0 indirect mode transfer START\n"
- "Start %08x End %08x Size %04x\n",scu_src_0,scu_dst_0,scu_size_0);
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start Add %04x Destination Add %04x\n",scu_src_add_0,scu_dst_add_0);
-
- /*guess,but I believe it's right.*/
- scu_src_0 &=0x07ffffff;
- scu_dst_0 &=0x07ffffff;
- scu_size_0 &=0xfffff;
-
- for (; scu_size_0 > 0; scu_size_0-=scu_dst_add_0)
- {
- if(scu_dst_add_0 == 2)
- cpu_writemem32bedw_word(scu_dst_0,cpu_readmem32bedw_word(scu_src_0));
- else
+ case 0x02000000:
+ case 0x03000000:
+ case 0x04000000:
+ return 1;
+ case 0x05000000:
+ switch (address & 0x00f00000)
{
- /* some games, eg columns97 are a bit weird, I'm not sure this is correct
- they start a dma on a 2 byte boundary in 4 byte add mode, using the dword reads we
- can't access 2 byte boundaries, and the end of the sprite list never gets marked,
- the length of the transfer is also set to a 2 byte boundary, maybe the add values
- should be different, I don't know */
- cpu_writemem32bedw_word(scu_dst_0,cpu_readmem32bedw_word(scu_src_0));
- cpu_writemem32bedw_word(scu_dst_0+2,cpu_readmem32bedw_word(scu_src_0+2));
+ case 0x00800000:
+ return 1;
+ case 0x00a00000: case 0x00b00000: /* sound */
+ case 0x00c00000: case 0x00d00000: /* VDP1 */
+ case 0x00e00000: case 0x00f00000: /* VDP2, SCU */
+ return 2;
+ default:
+ return (address & 0x00800000) ? 0 : 1; /* A-bus dummy */
}
- scu_dst_0+=scu_dst_add_0;
- scu_src_0+=scu_src_add_0;
+ case 0x06000000:
+ return 3;
+ }
+ return 0;
+}
+
+/* move one block a word at a time, returns the words moved */
+static UINT32 scu_dma_block(UINT32 *src, UINT32 *dst, UINT32 size, int src_add, int dst_add)
+{
+ UINT32 count = 0, words = 0;
+ int cbus = scu_dma_bus(*dst) == 3;
+
+ do
+ {
+ data16_t data = cpu_readmem32bedw_word(*src & 0x07fffffe);
+ cpu_writemem32bedw_word(*dst & 0x07fffffe, data);
+ if (sh2_jit_code_present)
+ sh2_jit_ram_written(*dst & 0x07fffffe, 2);
+ *src += src_add >> 1;
+ *dst += cbus ? 2 : dst_add;
+ count += 2;
+ words++;
+ } while (count < size);
+
+ return words;
+}
+
+static void scu_dma_end(int level)
+{
+ DMA_STATUS &= ~(0x30 << (level * 4));
+ stv_scu_raise_irq(11 - level); /* DMA level end */
+}
+
+static void scu_dma_trigger(int level)
+{
+ UINT32 *r = &stv_scu[level * 8];
+ int src_add = (r[3] & 0x100) ? 4 : 0;
+ int dst_add = 1 << (r[3] & 7);
+ UINT32 ticks;
+
+ /* a level that is still moving ignores the start */
+ if (DMA_STATUS & (0x30 << (level * 4)))
+ return;
+
+ if (dst_add == 1)
+ dst_add = 0;
+
+ /* the SH-2 that started it may not be the active context (blank events) */
+ cpuintrf_push_context(0);
+
+ if (r[5] & 0x01000000)
+ {
+ /* indirect: a table of size, destination and source, bit 31 of the source ends it */
+ UINT32 index = r[1] & 0x07fffffc;
+ int end;
+
+ ticks = 8;
+ do
+ {
+ UINT32 size = cpu_readmem32bedw_dword(index);
+ UINT32 dst = cpu_readmem32bedw_dword(index + 4);
+ UINT32 src = cpu_readmem32bedw_dword(index + 8);
+
+ end = src >> 31;
+ src &= 0x07ffffff;
+ dst &= 0x07ffffff;
+ size &= level ? 0x3ffff : 0xfffff;
+ ticks += 3 + scu_dma_block(&src, &dst, size, src_add, dst_add);
+ index += 12;
+ if (r[5] & 0x100) /* WUP */
+ r[1] = index;
+ } while (!end && ticks < 0x2000000);
+ }
+ else
+ {
+ UINT32 src = r[0] & 0x07ffffff;
+ UINT32 dst = r[1] & 0x07ffffff;
+ UINT32 size = r[2] & (level ? 0xfff : 0xfffff);
+ int src_bus = scu_dma_bus(src), dst_bus = scu_dma_bus(dst);
+
+ if (!src_bus || !dst_bus || src_bus == dst_bus)
+ {
+ cpuintrf_pop_context();
+ stv_scu_raise_irq(12); /* illegal DMA */
+ return;
}
- if(DRUP(0)) cpu_writemem32bedw_dword(tmp_src+8,scu_src_0|job_done ? 0x80000000 : 0);
- if(DWUP(0)) cpu_writemem32bedw_dword(tmp_src+4,scu_dst_0);
+ if (!size)
+ size = level ? 0x1000 : 0x100000;
- scu_dst_0 = tmp_src+0xc;
+ /* gunblaze: a maximum size transfer to the VDP1 would go past its VRAM */
+ if ((dst & 0x07f00000) == 0x05c00000 && size >= 0x80000)
+ size = 0x80000 - (dst & 0x7fffe);
- }while(job_done == 0);
+ ticks = 8 + scu_dma_block(&src, &dst, size, src_add, dst_add);
- if(!(stv_scu[40] & 0x800))/*Lv 0 DMA end irq*/
- cpu_set_irq_line_and_vector(0, 5, HOLD_LINE , 0x4b);
+ if (r[5] & 0x10000) /* RUP */
+ r[0] = src;
+ if (r[5] & 0x100) /* WUP */
+ r[1] = dst;
- SET_D0MV_FROM_1_TO_0;
-}
+ cpuintrf_pop_context();
-static void dma_indirect_lv1()
-{
- /*Helper to get out of the cycle*/
- UINT8 job_done = 0;
- /*temporary storage for the transfer data*/
- UINT32 tmp_src;
+ /* a direct transfer halts the SH-2s until it is over (MAME's main_dtack):
+ the CPU that started it loses the time, the level is free again for it,
+ and the end interrupt comes after the transfer time (danchih sets a
+ buffer right after the start and wants the interrupt after it) */
+ if (cpu_getactivecpu() >= 0 && cpu_getactivecpu() < 2)
+ activecpu_adjust_icount(-(int)(ticks / 2));
+ timer_adjust(scu_dma_timer[level], TIME_IN_HZ(57272720) * ticks, level, 0);
+ return;
+ }
- SET_D1MV_FROM_0_TO_1;
+ cpuintrf_pop_context();
- do{
- tmp_src = scu_dst_1;
-
- scu_size_1 = cpu_readmem32bedw_dword(scu_dst_1);
- scu_src_1 = cpu_readmem32bedw_dword(scu_dst_1+8);
- scu_dst_1 = cpu_readmem32bedw_dword(scu_dst_1+4);
-
- /*Indirect Mode end factor*/
- if(scu_src_1 & 0x80000000)
- job_done = 1;
-
- logerror("DMA lv 1 indirect mode transfer START\n"
- "Start %08x End %08x Size %04x\n",scu_src_1,scu_dst_1,scu_size_1);
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start Add %04x Destination Add %04x\n",scu_src_add_1,scu_dst_add_1);
-
- /*guess,but I believe it's right.*/
- scu_src_1 &=0x07ffffff;
- scu_dst_1 &=0x07ffffff;
- scu_size_1 &=0xffff;
-
-
- for (; scu_size_1 > 0; scu_size_1-=scu_dst_add_1)
- {
-
- if(scu_dst_add_1 == 2)
- cpu_writemem32bedw_word(scu_dst_1,cpu_readmem32bedw_word(scu_src_1));
- else
- {
- /* some games, eg columns97 are a bit weird, I'm not sure this is correct
- they start a dma on a 2 byte boundary in 4 byte add mode, using the dword reads we
- can't access 2 byte boundaries, and the end of the sprite list never gets marked,
- the length of the transfer is also set to a 2 byte boundary, maybe the add values
- should be different, I don't know */
- cpu_writemem32bedw_word(scu_dst_1,cpu_readmem32bedw_word(scu_src_1));
- cpu_writemem32bedw_word(scu_dst_1+2,cpu_readmem32bedw_word(scu_src_1+2));
- }
- scu_dst_1+=scu_dst_add_1;
- scu_src_1+=scu_src_add_1;
- }
-
- if(DRUP(1)) cpu_writemem32bedw_dword(tmp_src+8,scu_src_1|job_done ? 0x80000000 : 0);
- if(DWUP(1)) cpu_writemem32bedw_dword(tmp_src+4,scu_dst_1);
-
- scu_dst_1 = tmp_src+0xc;
-
- }while(job_done == 0);
-
- if(!(stv_scu[40] & 0x400))/*Lv 1 DMA end irq*/
- cpu_set_irq_line_and_vector(0, 6, HOLD_LINE , 0x4a);
-
- SET_D1MV_FROM_1_TO_0;
-}
-
-static void dma_indirect_lv2()
-{
- /*Helper to get out of the cycle*/
- UINT8 job_done = 0;
- /*temporary storage for the transfer data*/
- UINT32 tmp_src;
-
- SET_D2MV_FROM_0_TO_1;
-
- do{
- tmp_src = scu_dst_2;
-
- scu_size_2 = cpu_readmem32bedw_dword(scu_dst_2);
- scu_src_2 = cpu_readmem32bedw_dword(scu_dst_2+8);
- scu_dst_2 = cpu_readmem32bedw_dword(scu_dst_2+4);
-
- /*Indirect Mode end factor*/
- if(scu_src_2 & 0x80000000)
- job_done = 1;
-
- logerror("DMA lv 2 indirect mode transfer START\n"
- "Start %08x End %08x Size %04x\n",scu_src_2,scu_dst_2,scu_size_2);
- log_cb(RETRO_LOG_DEBUG, LOGPRE "Start Add %04x Destination Add %04x\n",scu_src_add_2,scu_dst_add_2);
-
- /*guess,but I believe it's right.*/
- scu_src_2 &=0x07ffffff;
- scu_dst_2 &=0x07ffffff;
- scu_size_2 &=0xffff;
-
- for (; scu_size_2 > 0; scu_size_2-=scu_dst_add_2)
- {
- if(scu_dst_add_2 == 2)
- cpu_writemem32bedw_word(scu_dst_2,cpu_readmem32bedw_word(scu_src_2));
- else
- {
- /* some games, eg columns97 are a bit weird, I'm not sure this is correct
- they start a dma on a 2 byte boundary in 4 byte add mode, using the dword reads we
- can't access 2 byte boundaries, and the end of the sprite list never gets marked,
- the length of the transfer is also set to a 2 byte boundary, maybe the add values
- should be different, I don't know */
- cpu_writemem32bedw_word(scu_dst_2,cpu_readmem32bedw_word(scu_src_2));
- cpu_writemem32bedw_word(scu_dst_2+2,cpu_readmem32bedw_word(scu_src_2+2));
- }
-
- scu_dst_2+=scu_dst_add_2;
- scu_src_2+=scu_src_add_2;
- }
-
- if(DRUP(2)) cpu_writemem32bedw_dword(tmp_src+8,scu_src_2|job_done ? 0x80000000 : 0);
- if(DWUP(2)) cpu_writemem32bedw_dword(tmp_src+4,scu_dst_2);
-
- scu_dst_2 = tmp_src+0xc;
-
- }while(job_done == 0);
-
- if(!(stv_scu[40] & 0x200))/*Lv 2 DMA end irq*/
- cpu_set_irq_line_and_vector(0, 6, HOLD_LINE , 0x49);
-
- SET_D2MV_FROM_1_TO_0;
+ /* moving until the end */
+ DMA_STATUS |= 0x10 << (level * 4);
+ timer_adjust(scu_dma_timer[level], TIME_IN_HZ(57272720) * ticks, level, 0);
}
@@ -3022,39 +2929,43 @@ static WRITE32_HANDLER( stv_scsp_regs_w32 )
SCSP_0_w(offset+1, data, mem_mask);
}
-/* communication,SLAVE CPU acquires data from the MASTER CPU and triggers an irq. *
- * Enter into Radiant Silver Gun specific menu for a test... */
+/*
+MINIT / SINIT: one SH-2 pulses the FRT input capture of the other (the DCC,
+315-5778). As in MAME, the pulse happens once the CPUs are in sync, and the
+interleave is tight for 1666us after it: the two CPUs exchange their jobs
+through the work RAM right after. Slices of 2us (about 56 SH-2 cycles) give
+the same output as 32 SCU clocks (about 16 cycles) on all the sets for 3600
+frames but vfremix (a fighter of its attract mode comes in a few frames
+earlier, it keeps 32 SCU clocks), while the games that signal often (colmns97, ffreveng, elandore,
+supgoal, ...) spend most of their time in that window: it takes a quarter
+to a third less host time. Communication breaks from 10us slices (7us for
+twcup98), MAME 0.264 uses 5us to 50us depending on the game.
+*/
+#define STV_INIT_SLICE TIME_IN_USEC(2)
+#define STV_INIT_SLICE_SCU TIME_IN_HZ(57272720 / 32)
+static double stv_init_slice;
+
+static void stv_frt_pulse(int cpu)
+{
+ sh2_set_frt_input(cpu, PULSE_LINE);
+}
+
static WRITE32_HANDLER( minit_w )
{
log_cb(RETRO_LOG_DEBUG, LOGPRE "cpu #%d (PC=%08X) MINIT write = %08x\n",cpu_getactivecpu(), activecpu_get_pc(),data);
- cpu_boost_interleave(0, TIME_IN_USEC(minit_boost));
- sh2_set_frt_input(1, PULSE_LINE);
+ if (minit_boost)
+ cpu_boost_interleave(stv_init_slice, TIME_IN_USEC(minit_boost));
+ timer_set(TIME_NOW, 1, stv_frt_pulse); /* the slave */
}
static WRITE32_HANDLER( sinit_w )
{
log_cb(RETRO_LOG_DEBUG, LOGPRE "cpu #%d (PC=%08X) SINIT write = %08x\n",cpu_getactivecpu(), activecpu_get_pc(),data);
- cpu_boost_interleave(0, TIME_IN_USEC(sinit_boost));
- sh2_set_frt_input(0, PULSE_LINE);
+ if (sinit_boost)
+ cpu_boost_interleave(stv_init_slice, TIME_IN_USEC(sinit_boost));
+ timer_set(TIME_NOW, 0, stv_frt_pulse); /* the master */
}
-extern WRITE32_HANDLER ( stv_vdp2_vram_w );
-extern READ32_HANDLER ( stv_vdp2_vram_r );
-
-extern WRITE32_HANDLER ( stv_vdp2_cram_w );
-extern READ32_HANDLER ( stv_vdp2_cram_r );
-
-extern WRITE32_HANDLER ( stv_vdp2_regs_w );
-extern READ32_HANDLER ( stv_vdp2_regs_r );
-
-extern VIDEO_START ( stv_vdp2 );
-extern VIDEO_UPDATE( stv_vdp2 );
-
-extern READ32_HANDLER( stv_vdp1_regs_r );
-extern WRITE32_HANDLER( stv_vdp1_regs_w );
-extern READ32_HANDLER ( stv_vdp1_vram_r );
-extern WRITE32_HANDLER ( stv_vdp1_vram_w );
-
static READ32_HANDLER( stv_workram_h_mirror_r )
{
offset = offset & ((0x0100000/4)-1);
@@ -3076,18 +2987,13 @@ static MEMORY_READ32_START( stv_master_readmem )
{ 0x05a00000, 0x05afffff, stv_sh2_soundram_r },
{ 0x05b00000, 0x05b00fff, stv_scsp_regs_r32 },
/* VDP1 */
- /*0x05c00000-0x05c7ffff VRAM*/
- /*0x05c80000-0x05c9ffff Frame Buffer 0*/
- /*0x05ca0000-0x05cbffff Frame Buffer 1*/
- /*0x05d00000-0x05d7ffff VDP1 Regs */
- { 0x05c00000, 0x05cbffff, stv_vdp1_vram_r },
+ { 0x05c00000, 0x05c7ffff, stv_vdp1_vram_r },
+ { 0x05c80000, 0x05cbffff, stv_vdp1_framebuffer0_r },
{ 0x05d00000, 0x05d0001f, stv_vdp1_regs_r },
- { 0x5e00000 , 0x5efffff, stv_vdp2_vram_r },
- { 0x5f00000 , 0x5f7ffff, stv_vdp2_cram_r },
- { 0x5f80000 , 0x5fbffff, stv_vdp2_regs_r },
-/* { 0x05e00000, 0x05e7ffff, MRA32_RAM },*/
-/* { 0x05f00000, 0x05f0ffff, stv_palette_r }, // CRAM /*/
-/* { 0x05f80000, 0x05fbffff, stv_vdp2_regs_r32 }, // REGS /*/
+ /* VDP2 (the VRAM is mirrored) */
+ { 0x05e00000, 0x05efffff, stv_vdp2_vram_r },
+ { 0x05f00000, 0x05f7ffff, stv_vdp2_cram_r },
+ { 0x05f80000, 0x05fbffff, stv_vdp2_regs_r },
{ 0x05fe0000, 0x05fe00cf, stv_scu_r32 },
{ 0x06000000, 0x060fffff, MRA32_BANK3 },
{ 0x06100000, 0x07ffffff, stv_workram_h_mirror_r }, /* hanagumi reads the char select 1p icon and timer gfx from here ..*/
@@ -3099,8 +3005,8 @@ static MEMORY_WRITE32_START( stv_master_writemem )
{ 0x00180000, 0x0018ffff, MWA32_BANK5 }, /* backup ram*/
{ 0x00200000, 0x002fffff, MWA32_BANK4 }, /* workram low*/
{ 0x00400000, 0x0040001f, stv_io_w32 ,&ioga },
- { 0x01000000, 0x01000003, minit_w },
- { 0x01406f40, 0x01406f43, minit_w }, /* needed by prikura */
+ { 0x01000000, 0x017fffff, minit_w }, /* MINIT, the whole mirror (prikura writes 0x01406f40) */
+ { 0x01800000, 0x01ffffff, sinit_w }, /* SINIT */
{ 0x02000000, 0x04ffffff, MWA32_ROM },
/* { 0x05000000, 0x058fffff, MWA32_RAM },*/
{ 0x05800000, 0x0589ffff, cdregister_w },
@@ -3108,11 +3014,13 @@ static MEMORY_WRITE32_START( stv_master_writemem )
{ 0x05a00000, 0x05afffff, stv_sh2_soundram_w },
{ 0x05b00000, 0x05b00fff, stv_scsp_regs_w32 },
/* VDP1 */
- { 0x05c00000, 0x05cbffff, stv_vdp1_vram_w },
+ { 0x05c00000, 0x05c7ffff, stv_vdp1_vram_w },
+ { 0x05c80000, 0x05cbffff, stv_vdp1_framebuffer0_w },
{ 0x05d00000, 0x05d0001f, stv_vdp1_regs_w },
- { 0x5e00000 , 0x5efffff, stv_vdp2_vram_w },
- { 0x5f00000 , 0x5f7ffff, stv_vdp2_cram_w },
- { 0x5f80000 , 0x5fbffff, stv_vdp2_regs_w },
+ /* VDP2 (the VRAM is mirrored) */
+ { 0x05e00000, 0x05efffff, stv_vdp2_vram_w },
+ { 0x05f00000, 0x05f7ffff, stv_vdp2_cram_w },
+ { 0x05f80000, 0x05fbffff, stv_vdp2_regs_w },
{ 0x05fe0000, 0x05fe00cf, stv_scu_w32 },
{ 0x06000000, 0x060fffff, MWA32_BANK3 },
/* { 0x06100000, 0x07ffffff, MWA32_NOP },*/
@@ -3130,7 +3038,8 @@ static MEMORY_READ32_START( stv_slave_readmem )
/* { 0x05000000, 0x058fffff, MRA32_RAM },*/
{ 0x05a00000, 0x05afffff, stv_sh2_soundram_r },
{ 0x05b00000, 0x05b00fff, stv_scsp_regs_r32 },
- { 0x05c00000, 0x05cbffff, stv_vdp1_vram_r },
+ { 0x05c00000, 0x05c7ffff, stv_vdp1_vram_r },
+ { 0x05c80000, 0x05cbffff, stv_vdp1_framebuffer0_r },
{ 0x05d00000, 0x05d0001f, stv_vdp1_regs_r },
{ 0x05e00000, 0x05efffff, stv_vdp2_vram_r },
{ 0x05f00000, 0x05f7ffff, stv_vdp2_cram_r },
@@ -3146,13 +3055,14 @@ static MEMORY_WRITE32_START( stv_slave_writemem )
{ 0x00180000, 0x0018ffff, MWA32_BANK5 },
{ 0x00200000, 0x002fffff, MWA32_BANK4 },
{ 0x00400000, 0x0040001f, stv_io_w32 ,&ioga },
-/* { 0x01000000, 0x01000003, minit_w },*/
- { 0x01800000, 0x01800003, sinit_w },
+ { 0x01000000, 0x017fffff, minit_w },
+ { 0x01800000, 0x01ffffff, sinit_w },
{ 0x02000000, 0x04ffffff, MWA32_ROM },
/* { 0x05000000, 0x058fffff, MWA32_RAM },*/
{ 0x05a00000, 0x05afffff, stv_sh2_soundram_w },
{ 0x05b00000, 0x05b00fff, stv_scsp_regs_w32 },
- { 0x05c00000, 0x05cbffff, stv_vdp1_vram_w },
+ { 0x05c00000, 0x05c7ffff, stv_vdp1_vram_w },
+ { 0x05c80000, 0x05cbffff, stv_vdp1_framebuffer0_w },
{ 0x05d00000, 0x05d0001f, stv_vdp1_regs_w },
{ 0x05e00000, 0x05efffff, stv_vdp2_vram_w },
{ 0x05f00000, 0x05f7ffff, stv_vdp2_cram_w },
@@ -3304,6 +3214,269 @@ INPUT_PORTS_START( stv )
#endif
INPUT_PORTS_END
+/* Critter Crusher: the hammer hit and its position on the screen */
+INPUT_PORTS_START( critcrsh )
+ PORT_START
+ PORT_DIPNAME( 0x01, 0x01, "PDR1" )
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START
+ PORT_DIPNAME( 0x01, 0x01, "PDR2" )
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START /* port A: the hammer X */
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START /* port B: the hammer Y */
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+/*
+ PORT_START
+ STV_PLAYER_INPUTS(3, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
+
+ PORT_START
+ STV_PLAYER_INPUTS(4, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
+*/
+
+ PORT_START
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
+ PORT_BITX(0x04, IP_ACTIVE_LOW, IPT_SERVICE, "Test", KEYCODE_F2, IP_JOY_NONE )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE1 )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* hammer hit */
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BITX(0x40, IP_ACTIVE_LOW, IPT_SERVICE, "1P Push Switch", KEYCODE_7, IP_JOY_NONE )
+ PORT_BITX(0x80, IP_ACTIVE_LOW, IPT_SERVICE, "2P Push Switch", KEYCODE_8, IP_JOY_NONE )
+
+ /*This *might* be unused...*/
+ PORT_START
+ PORT_BIT ( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ /*Extra button layout,used by Power Instinct 3 & Suikoenbu*/
+ PORT_START
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 | IPF_PLAYER1 )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 | IPF_PLAYER1 )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 | IPF_PLAYER1 )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 | IPF_PLAYER2 )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 | IPF_PLAYER2 )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON6 | IPF_PLAYER2 )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ /*We don't need these,AFAIK the country code doesn't work either...*/
+ #if 0
+ PORT_START /*7*/
+ PORT_DIPNAME( 0x0f, 0x01, "Country" )
+ PORT_DIPSETTING( 0x01, "Japan" )
+ PORT_DIPSETTING( 0x02, "Asia Ntsc" )
+ PORT_DIPSETTING( 0x04, "Usa" )
+ PORT_DIPSETTING( 0x08, "Sud America Ntsc" )
+ PORT_DIPSETTING( 0x06, "Korea" )
+ PORT_DIPSETTING( 0x0a, "Asia Pal" )
+ PORT_DIPSETTING( 0x0c, "Europe/Other Pal" )
+ PORT_DIPSETTING( 0x0d, "Sud America Pal" )
+
+ PORT_START /* Pad data 1a */
+ PORT_BITX(0x01, IP_ACTIVE_HIGH, 0, "B", KEYCODE_U, IP_JOY_NONE )
+ PORT_BITX(0x02, IP_ACTIVE_HIGH, 0, "C", KEYCODE_Y, IP_JOY_NONE )
+ PORT_BITX(0x04, IP_ACTIVE_HIGH, 0, "A", KEYCODE_T, IP_JOY_NONE )
+ PORT_BITX(0x08, IP_ACTIVE_HIGH, 0, "Start", KEYCODE_O, IP_JOY_NONE )
+ PORT_BITX(0x10, IP_ACTIVE_HIGH, 0, "Up", KEYCODE_I, IP_JOY_NONE )
+ PORT_BITX(0x20, IP_ACTIVE_HIGH, 0, "Down", KEYCODE_K, IP_JOY_NONE )
+ PORT_BITX(0x40, IP_ACTIVE_HIGH, 0, "Left", KEYCODE_J, IP_JOY_NONE )
+ PORT_BITX(0x80, IP_ACTIVE_HIGH, 0, "Right", KEYCODE_L, IP_JOY_NONE )
+
+ PORT_START /* Pad data 1b */
+ PORT_BITX(0x08, IP_ACTIVE_HIGH, 0, "L trig", KEYCODE_A, IP_JOY_NONE )
+ PORT_BITX(0x10, IP_ACTIVE_HIGH, 0, "Z", KEYCODE_Q, IP_JOY_NONE )
+ PORT_BITX(0x20, IP_ACTIVE_HIGH, 0, "Y", KEYCODE_W, IP_JOY_NONE )
+ PORT_BITX(0x40, IP_ACTIVE_HIGH, 0, "X", KEYCODE_E, IP_JOY_NONE )
+ PORT_BITX(0x80, IP_ACTIVE_HIGH, 0, "R trig", KEYCODE_S, IP_JOY_NONE )
+ #endif
+
+ PORT_START /* the hammer X */
+ PORT_ANALOG( 0x3f, 0x00, IPT_LIGHTGUN_X, 50, 1, 0, 0x3f )
+
+ PORT_START /* the hammer Y */
+ PORT_ANALOG( 0x3f, 0x02, IPT_LIGHTGUN_Y, 50, 1, 0x02, 0x2e )
+INPUT_PORTS_END
+
+/* the medal games (MAME's patocar and micrombc inputs), with a hopper */
+INPUT_PORTS_START( stvmedal )
+ PORT_START
+ PORT_DIPNAME( 0x01, 0x01, "PDR1" )
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START
+ PORT_DIPNAME( 0x01, 0x01, "PDR2" )
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START /* port A */
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) /* the hopper */
+ PORT_BIT( 0x1c, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* power button (micrombc) */
+ PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START /* port B */
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON4 ) /* door switch? */
+ PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_BUTTON5 ) /* magnet sensor (micrombc) */
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN3 ) /* medal */
+ PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
+/*
+ PORT_START
+ STV_PLAYER_INPUTS(3, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
+
+ PORT_START
+ STV_PLAYER_INPUTS(4, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
+*/
+
+ PORT_START
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
+ PORT_BITX(0x04, IP_ACTIVE_LOW, IPT_SERVICE, "Test", KEYCODE_F2, IP_JOY_NONE )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE1 )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 )
+ PORT_BITX(0x40, IP_ACTIVE_LOW, IPT_SERVICE, "1P Push Switch", KEYCODE_7, IP_JOY_NONE )
+ PORT_BITX(0x80, IP_ACTIVE_LOW, IPT_SERVICE, "2P Push Switch", KEYCODE_8, IP_JOY_NONE )
+
+ /*This *might* be unused...*/
+ PORT_START
+ PORT_BIT ( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ /*Extra button layout,used by Power Instinct 3 & Suikoenbu*/
+ PORT_START
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 | IPF_PLAYER1 )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 | IPF_PLAYER1 )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 | IPF_PLAYER1 )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 | IPF_PLAYER2 )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 | IPF_PLAYER2 )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON6 | IPF_PLAYER2 )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ /*We don't need these,AFAIK the country code doesn't work either...*/
+ #if 0
+ PORT_START /*7*/
+ PORT_DIPNAME( 0x0f, 0x01, "Country" )
+ PORT_DIPSETTING( 0x01, "Japan" )
+ PORT_DIPSETTING( 0x02, "Asia Ntsc" )
+ PORT_DIPSETTING( 0x04, "Usa" )
+ PORT_DIPSETTING( 0x08, "Sud America Ntsc" )
+ PORT_DIPSETTING( 0x06, "Korea" )
+ PORT_DIPSETTING( 0x0a, "Asia Pal" )
+ PORT_DIPSETTING( 0x0c, "Europe/Other Pal" )
+ PORT_DIPSETTING( 0x0d, "Sud America Pal" )
+
+ PORT_START /* Pad data 1a */
+ PORT_BITX(0x01, IP_ACTIVE_HIGH, 0, "B", KEYCODE_U, IP_JOY_NONE )
+ PORT_BITX(0x02, IP_ACTIVE_HIGH, 0, "C", KEYCODE_Y, IP_JOY_NONE )
+ PORT_BITX(0x04, IP_ACTIVE_HIGH, 0, "A", KEYCODE_T, IP_JOY_NONE )
+ PORT_BITX(0x08, IP_ACTIVE_HIGH, 0, "Start", KEYCODE_O, IP_JOY_NONE )
+ PORT_BITX(0x10, IP_ACTIVE_HIGH, 0, "Up", KEYCODE_I, IP_JOY_NONE )
+ PORT_BITX(0x20, IP_ACTIVE_HIGH, 0, "Down", KEYCODE_K, IP_JOY_NONE )
+ PORT_BITX(0x40, IP_ACTIVE_HIGH, 0, "Left", KEYCODE_J, IP_JOY_NONE )
+ PORT_BITX(0x80, IP_ACTIVE_HIGH, 0, "Right", KEYCODE_L, IP_JOY_NONE )
+
+ PORT_START /* Pad data 1b */
+ PORT_BITX(0x08, IP_ACTIVE_HIGH, 0, "L trig", KEYCODE_A, IP_JOY_NONE )
+ PORT_BITX(0x10, IP_ACTIVE_HIGH, 0, "Z", KEYCODE_Q, IP_JOY_NONE )
+ PORT_BITX(0x20, IP_ACTIVE_HIGH, 0, "Y", KEYCODE_W, IP_JOY_NONE )
+ PORT_BITX(0x40, IP_ACTIVE_HIGH, 0, "X", KEYCODE_E, IP_JOY_NONE )
+ PORT_BITX(0x80, IP_ACTIVE_HIGH, 0, "R trig", KEYCODE_S, IP_JOY_NONE )
+ #endif
+INPUT_PORTS_END
+
/*Same as the regular one,but with an additional & optional mahjong panel*/
INPUT_PORTS_START( stvmp )
PORT_START
@@ -3519,6 +3692,11 @@ WRITE32_HANDLER ( w60ffc48_write )
}
+static READ32_HANDLER( stv_cart_unmapped_r )
+{
+ return 0xffffffff;
+}
+
DRIVER_INIT ( stv )
{
unsigned char *ROM = memory_region(REGION_USER1);
@@ -3529,6 +3707,10 @@ DRIVER_INIT ( stv )
today = localtime(<ime);
cpu_setbank(1,&ROM[0x000000]);
+ stv_hopper = 0;
+ stv_critcrsh = 0;
+ hopper_timer = NULL;
+ scu_dma_timer[0] = scu_dma_timer[1] = scu_dma_timer[2] = NULL;
/* we allocate the memory here so its easier to share between cpus */
smpc_ram = auto_malloc (0x80);
@@ -3544,7 +3726,34 @@ DRIVER_INIT ( stv )
cpu_setbank(4,&stv_workram_l[0x000000]);
cpu_setbank(5,&stv_backupram[0x000000]);
- install_stvbios_speedups();
+ /* the SH-2 recompiler runs code from, and accesses directly, the BIOS */
+ /* and the work RAMs (the handlers a game installs there stay in use) */
+ sh2_jit_set(0);
+ if (options.sh2_dynarec)
+ {
+ sh2_jit_add_fastram(0x00000000, 0x0007ffff, 1, memory_region(REGION_CPU1));
+ sh2_jit_add_fastram(0x00200000, 0x002fffff, 0, stv_workram_l);
+ sh2_jit_add_fastram(0x06000000, 0x060fffff, 0, stv_workram_h);
+ /* the cartridge ROM, as far as it goes (the protection and */
+ /* decompression handlers some games install there stay in use) */
+ if (memory_region_length(REGION_USER1) >= 4)
+ {
+ UINT32 len = memory_region_length(REGION_USER1);
+ if (len > 0x3000000)
+ len = 0x3000000;
+ sh2_jit_add_fastram(0x02000000, 0x02000000 + (len & ~3) - 1, 1, memory_region(REGION_USER1));
+ }
+ sh2_jit_set(1);
+ }
+
+ /* the cartridge space is 0x02000000-0x04ffffff; past the ROMs it reads
+ as erased flash (MAME's carts are 0x3000000 bytes, 0xff filled) */
+ if (memory_region_length(REGION_USER1) < 0x3000000)
+ {
+ offs_t end = 0x02000000 + memory_region_length(REGION_USER1);
+ install_mem_read32_handler(0, end, 0x04ffffff, stv_cart_unmapped_r);
+ install_mem_read32_handler(1, end, 0x04ffffff, stv_cart_unmapped_r);
+ }
/* debug .. watch the command buffer rsgun, cottonbm etc. appear to use to communicate between cpus */
install_mem_write32_handler(0, 0x60ffc44, 0x60ffc47, w60ffc44_write );
@@ -3576,13 +3785,47 @@ MACHINE_INIT( stv )
cpu_set_halt_line(1, ASSERT_LINE);
cpu_set_halt_line(2, ASSERT_LINE);
- timer_0 = 0;
+ scu_ist = 0;
+ scu_irq_level = 0;
+ scu_irq_vector = 0;
+ {
+ int level;
+ for (level = 0; level < 3; level++)
+ {
+ if (!scu_dma_timer[level])
+ scu_dma_timer[level] = timer_alloc(scu_dma_end);
+ timer_adjust(scu_dma_timer[level], TIME_NEVER, 0, 0);
+ }
+ stv_scu[31] = 0; /* no DMA moving */
+ }
+ if (!hopper_timer)
+ hopper_timer = timer_alloc(hopper_tick);
+ timer_adjust(hopper_timer, TIME_NEVER, 0, 0);
+ hopper_power = hopper_status = 0;
+ scu_timer0_count = 0;
+ slave_irl = 0;
+ cpu_set_irq_callback(0, stv_master_irq_callback);
en_68k = 0;
smpc_ram[0x21] = 0x80;
+ if (!smpc_intback_timer)
+ smpc_intback_timer = timer_alloc(smpc_intback_continue);
+ timer_adjust(smpc_intback_timer, TIME_NEVER, 0, 0);
+ smpc_sr = smpc_intback_stage = smpc_pmode = 0;
- /* amount of time to boost interleave for on MINIT / SINIT, needed for communication to work */
- minit_boost = 400;
- sinit_boost = 400;
+ /* time of tight interleave after MINIT / SINIT (MAME's DCC) */
+ minit_boost = 1666;
+ sinit_boost = 1666;
+ stv_init_slice = STV_INIT_SLICE;
+
+ /* twcup98 computes on both CPUs for most of that window: 400us is
+ enough for it (as in MAME 0.264), same output, a tenth faster */
+ if (!strcmp(Machine->gamedrv->name, "twcup98"))
+ {
+ minit_boost = 400;
+ sinit_boost = 400;
+ }
+ if (!strcmp(Machine->gamedrv->name, "vfremix"))
+ stv_init_slice = STV_INIT_SLICE_SCU;
/* puyosun doesn't seem to care */
if ((!strcmp(Machine->gamedrv->name,"puyosun")) ||
@@ -3595,82 +3838,21 @@ MACHINE_INIT( stv )
}
-static struct GfxLayout tiles8x8x4_layout =
+/* both SH-2s run from the high work RAM: fetch the opcodes straight from it
+ instead of through the memory handlers (a fifth of the host time otherwise) */
+static data16_t stv_opcode_read(offs_t pc)
{
- 8,8,
- RGN_FRAC(1,1),
- 4,
- { 0, 1, 2, 3 },
- { 0, 4, 8, 12, 16, 20, 24, 28 },
- { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
- 32*8
-};
+ pc &= 0x07ffffff;
+ if ((pc & 0x07f00000) == 0x06000000)
+ {
+ UINT32 data = stv_workram_h[(pc & 0xfffff) >> 2];
+ return (pc & 2) ? (data & 0xffff) : (data >> 16);
+ }
+ return cpu_readmem32bedw_word(pc);
+}
-static struct GfxLayout tiles16x16x4_layout =
-{
- 16,16,
- RGN_FRAC(1,1),
- 4,
- { 0, 1, 2, 3 },
- { 0, 4, 8, 12, 16, 20, 24, 28,
- 32*8+0, 32*8+4, 32*8+8, 32*8+12, 32*8+16, 32*8+20, 32*8+24, 32*8+28,
-
- },
- { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32,
- 32*16, 32*17,32*18, 32*19,32*20,32*21,32*22,32*23
-
- },
- 32*32
-};
-
-static struct GfxLayout tiles8x8x8_layout =
-{
- 8,8,
- RGN_FRAC(1,1),
- 8,
- { 0, 1, 2, 3, 4, 5, 6, 7 },
- { 0, 8, 16, 24, 32, 40, 48, 56 },
- { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
- 64*8
-};
-
-static struct GfxLayout tiles16x16x8_layout =
-{
- 16,16,
- RGN_FRAC(1,1),
- 8,
- { 0, 1, 2, 3, 4, 5, 6, 7 },
- { 0, 8, 16, 24, 32, 40, 48, 56,
- 64*8+0, 65*8, 66*8, 67*8, 68*8, 69*8, 70*8, 71*8
-
- },
- { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,
- 64*16, 64*17, 64*18, 64*19, 64*20, 64*21, 64*22, 64*23
- },
- 128*16
-};
-
-
-
-
-static struct GfxDecodeInfo gfxdecodeinfo[] =
-{
- { REGION_GFX1, 0, &tiles8x8x4_layout, 0x00, 0x80 },
- { REGION_GFX1, 0, &tiles16x16x4_layout, 0x00, 0x80 },
- { REGION_GFX1, 0, &tiles8x8x8_layout, 0x00, 0x10 },
- { REGION_GFX1, 0, &tiles16x16x8_layout, 0x00, 0x10 },
-
- /* vdp1 .. pointless for drawing but can help us debug */
- { REGION_GFX2, 0, &tiles8x8x4_layout, 0x00, 0x100 },
- { REGION_GFX2, 0, &tiles16x16x4_layout, 0x00, 0x100 },
- { REGION_GFX2, 0, &tiles8x8x8_layout, 0x00, 0x20 },
- { REGION_GFX2, 0, &tiles16x16x8_layout, 0x00, 0x20 },
-
- { -1 } /* end of array */
-};
-
-struct sh2_config sh2_conf_master = { 0 };
-struct sh2_config sh2_conf_slave = { 1 };
+struct sh2_config sh2_conf_master = { 0, stv_opcode_read };
+struct sh2_config sh2_conf_slave = { 1, stv_opcode_read };
static int scsp_last_line = 0;
@@ -3701,12 +3883,20 @@ static struct SCSPinterface scsp_interface =
{ scsp_irq, },
};
+/* the 93c45 EEPROM, with the factory settings of the games that need them */
+static NVRAM_HANDLER( stv )
+{
+ nvram_handler_93C46(file, read_or_write);
+ if (!read_or_write && !file && memory_region(REGION_USER3))
+ EEPROM_set_data(memory_region(REGION_USER3), 0x80);
+}
+
static MACHINE_DRIVER_START( stv )
/* basic machine hardware */
MDRV_CPU_ADD(SH2, 28000000) /* 28MHz*/
MDRV_CPU_MEMORY(stv_master_readmem,stv_master_writemem)
- MDRV_CPU_VBLANK_INT(stv_interrupt,264)/*264 lines,224 display lines*/
+ MDRV_CPU_VBLANK_INT(stv_interrupt,STV_LINES)
MDRV_CPU_CONFIG(sh2_conf_master)
MDRV_CPU_ADD(SH2, 28000000) /* 28MHz*/
@@ -3720,16 +3910,16 @@ static MACHINE_DRIVER_START( stv )
MDRV_VBLANK_DURATION(DEFAULT_60HZ_VBLANK_DURATION)
MDRV_MACHINE_INIT(stv)
- MDRV_NVRAM_HANDLER(93C46) /* Actually 93c45 */
+ MDRV_NVRAM_HANDLER(stv) /* a 93c45 */
/* video hardware */
- MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER | VIDEO_UPDATE_AFTER_VBLANK | VIDEO_RGB_DIRECT )
- MDRV_SCREEN_SIZE(1024, 1024)
- MDRV_VISIBLE_AREA(0*8, 703, 0*8, 479) /* we need to use a resolution as high as the max size it can change to*/
+ MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER | VIDEO_RGB_DIRECT | VIDEO_NEEDS_6BITS_PER_GUN)
+ MDRV_SCREEN_SIZE(704, 512)
+ MDRV_VISIBLE_AREA(0, 319, 0, 223) /* the VDP2 sets the resolution */
MDRV_PALETTE_LENGTH(2048)
- MDRV_GFXDECODE(gfxdecodeinfo)
MDRV_VIDEO_START(stv_vdp2)
+ MDRV_VIDEO_STOP(stv_vdp2)
MDRV_VIDEO_UPDATE(stv_vdp2)
MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO)
@@ -3739,6 +3929,9 @@ MACHINE_DRIVER_END
#define ROM_LOAD16_WORD_SWAP_BIOS(bios,name,offset,length,hash) \
ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(bios+1)) /* Note '+1' */
+/* a reload that does not inherit the interleave of the previous load */
+#define ROM_RELOAD_PLAIN(offset,length) ROMX_LOAD(ROMENTRY_RELOAD, offset, length, 0, 0)
+
#define STV_BIOS \
ROM_REGION( 0x080000, REGION_CPU1, 0 ) /* SH2 code */ \
ROM_LOAD16_WORD_SWAP_BIOS( 0, "epr19730.ic8", 0x000000, 0x080000, CRC(d0e0889d) SHA1(fae53107c894e0c41c49e191dbe706c9cd6e50bd) ) /* jp */ \
@@ -3751,8 +3944,6 @@ MACHINE_DRIVER_END
ROM_REGION( 0x080000, REGION_CPU2, 0 ) /* SH2 code */ \
ROM_COPY( REGION_CPU1,0,0,0x080000) \
ROM_REGION( 0x100000, REGION_CPU3, 0 ) /* 68000 code */ \
- ROM_REGION( 0x100000, REGION_GFX1, 0 ) /* VDP2 GFX */ \
- ROM_REGION( 0x100000, REGION_GFX2, 0 ) /* VDP1 GFX */ \
ROM_START( stvbios )
STV_BIOS
@@ -3811,646 +4002,767 @@ some of the rom names were using something else and have been renamed to match t
ROM_START( astrass )
STV_BIOS
- ROM_REGION32_BE( 0x2400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr20825.13", 0x0000000, 0x0100000, CRC(94a9ad8f) SHA1(861311c14cfa9f560752aa5b023c147a539cf135) ) /* ic13 bad?! (was .24)*/
- ROM_LOAD16_WORD_SWAP( "mpr20827.2", 0x0400000, 0x0400000, CRC(65cabbb3) SHA1(5e7cb090101dc42207a4084465e419f4311b6baf) ) /* good (was .12)*/
- ROM_LOAD16_WORD_SWAP( "mpr20828.3", 0x0800000, 0x0400000, CRC(3934d44a) SHA1(969406b8bfac43b30f4d732702ca8cffeeefffb9) ) /* good (was .13)*/
- ROM_LOAD16_WORD_SWAP( "mpr20829.4", 0x0c00000, 0x0400000, CRC(814308c3) SHA1(45c3f551690224c95acd156ae8f8397667927a04) ) /* good (was .14)*/
- ROM_LOAD16_WORD_SWAP( "mpr20830.5", 0x1000000, 0x0400000, CRC(ff97fd19) SHA1(f37bcdce5f3f522527a44d59f1b8184ef290f829) ) /* good (was .15)*/
- ROM_LOAD16_WORD_SWAP( "mpr20831.6", 0x1400000, 0x0400000, CRC(4408e6fb) SHA1(d4228cad8a1128e9426dac9ac62e9513a7a0117b) ) /* good (was .16)*/
- ROM_LOAD16_WORD_SWAP( "mpr20826.1", 0x1800000, 0x0400000, CRC(bdc4b941) SHA1(c5e8b1b186324c2ccab617915f7bdbfe6897ca9f) ) /* good (was .17)*/
- ROM_LOAD16_WORD_SWAP( "mpr20832.8", 0x1c00000, 0x0400000, CRC(af1b0985) SHA1(d7a0e4e0a8b0556915f924bdde8c3d14e5b3423e) ) /* good (was .18s)*/
- ROM_LOAD16_WORD_SWAP( "mpr20833.9", 0x2000000, 0x0400000, CRC(cb6af231) SHA1(4a2e5d7c2fd6179c19cdefa84a03f9a34fbb9e70) ) /* good (was .19s)*/
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF ) /* SH2 code */
+ ROM_LOAD16_BYTE( "epr20825.13", 0x0000001, 0x0100000, CRC(94a9ad8f) SHA1(861311c14cfa9f560752aa5b023c147a539cf135) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20827.2", 0x0400000, 0x0400000, CRC(65cabbb3) SHA1(5e7cb090101dc42207a4084465e419f4311b6baf) ) /* good (was .12) */
+ ROM_LOAD16_WORD_SWAP( "mpr20828.3", 0x0800000, 0x0400000, CRC(3934d44a) SHA1(969406b8bfac43b30f4d732702ca8cffeeefffb9) ) /* good (was .13) */
+ ROM_LOAD16_WORD_SWAP( "mpr20829.4", 0x0c00000, 0x0400000, CRC(814308c3) SHA1(45c3f551690224c95acd156ae8f8397667927a04) ) /* good (was .14) */
+ ROM_LOAD16_WORD_SWAP( "mpr20830.5", 0x1000000, 0x0400000, CRC(ff97fd19) SHA1(f37bcdce5f3f522527a44d59f1b8184ef290f829) ) /* good (was .15) */
+ ROM_LOAD16_WORD_SWAP( "mpr20831.6", 0x1400000, 0x0400000, CRC(4408e6fb) SHA1(d4228cad8a1128e9426dac9ac62e9513a7a0117b) ) /* good (was .16) */
+ ROM_LOAD16_WORD_SWAP( "mpr20826.1", 0x1800000, 0x0400000, CRC(bdc4b941) SHA1(c5e8b1b186324c2ccab617915f7bdbfe6897ca9f) ) /* good (was .17) */
+ ROM_LOAD16_WORD_SWAP( "mpr20832.8", 0x1c00000, 0x0400000, CRC(af1b0985) SHA1(d7a0e4e0a8b0556915f924bdde8c3d14e5b3423e) ) /* good (was .18s) */
+ ROM_LOAD16_WORD_SWAP( "mpr20833.9", 0x2000000, 0x0400000, CRC(cb6af231) SHA1(4a2e5d7c2fd6179c19cdefa84a03f9a34fbb9e70) ) /* good (was .19s) */
+
+ /* 610-0374-90 1998 317-5040-COM ST-V (yes, the 317-5040-COM chip was reused for 3 different games and on both Naomi and ST-V!) */
ROM_END
ROM_START( bakubaku )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fpr17969.13", 0x0000000, 0x0100000, CRC(bee327e5) SHA1(1d226db72d6ef68fd294f60659df7f882b25def6) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr17970.2", 0x0400000, 0x0400000, CRC(bc4d6f91) SHA1(dcc241dcabea59325decfba3fd5e113c07958422) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17971.3", 0x0800000, 0x0400000, CRC(c780a3b3) SHA1(99587eea528a6413cacc3e4d3d1dbfff57b03dca) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17972.4", 0x0c00000, 0x0400000, CRC(8f29815a) SHA1(e86acd8096f2aee5f5e3ddfd3abb4f5c2b11df66) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17973.5", 0x1000000, 0x0400000, CRC(5f6e0e8b) SHA1(eeb5efb5216ab8b8fdee4656774bbd5a2a5b2d42) ) /* good*/
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr17969.13", 0x0000001, 0x0100000, CRC(bee327e5) SHA1(1d226db72d6ef68fd294f60659df7f882b25def6) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
+
+ ROM_LOAD16_WORD_SWAP( "mpr17970.2", 0x0400000, 0x0400000, CRC(bc4d6f91) SHA1(dcc241dcabea59325decfba3fd5e113c07958422) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17971.3", 0x0800000, 0x0400000, CRC(c780a3b3) SHA1(99587eea528a6413cacc3e4d3d1dbfff57b03dca) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17972.4", 0x0c00000, 0x0400000, CRC(8f29815a) SHA1(e86acd8096f2aee5f5e3ddfd3abb4f5c2b11df66) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17973.5", 0x1000000, 0x0400000, CRC(5f6e0e8b) SHA1(eeb5efb5216ab8b8fdee4656774bbd5a2a5b2d42) ) /* good */
ROM_END
ROM_START( colmns97 )
STV_BIOS
- ROM_REGION32_BE( 0xc00000, REGION_USER1, 0 ) /* SH2 code */
- /* it tests .13 at 0x000000 - 0x1fffff but reports as bad even if we put the rom there */
- ROM_LOAD( "fpr19553.13", 0x000000, 0x100000, CRC(d4fb6a5e) SHA1(bd3cfb4f451b6c9612e42af5ddcbffa14f057329) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr19554.2", 0x400000, 0x400000, CRC(5a3ebcac) SHA1(46e3d1cf515a7ff8a8f97e5050b29dbbeb5060c0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19555.3", 0x800000, 0x400000, CRC(74f6e6b8) SHA1(8080860550eb770e04447e344fb337748a249761) ) /* good*/
+ ROM_REGION32_BE( 0xc00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr19553.13", 0x000001, 0x100000, CRC(d4fb6a5e) SHA1(bd3cfb4f451b6c9612e42af5ddcbffa14f057329) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr19554.2", 0x400000, 0x400000, CRC(5a3ebcac) SHA1(46e3d1cf515a7ff8a8f97e5050b29dbbeb5060c0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19555.3", 0x800000, 0x400000, CRC(74f6e6b8) SHA1(8080860550eb770e04447e344fb337748a249761) ) /* good */
ROM_END
ROM_START( cotton2 )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr20122.7", 0x0200000, 0x0200000, CRC(d616f78a) SHA1(8039dcdfdafb8327a19a1da46a67c0b3f7eee53a) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20117.2", 0x0400000, 0x0400000, CRC(893656ea) SHA1(11e3160083ba018fbd588f07061a4e55c1efbebb) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20118.3", 0x0800000, 0x0400000, CRC(1b6a1d4c) SHA1(6b234d6b2d24df7f6d400a56698c0af2f78ce0e7) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20119.4", 0x0c00000, 0x0400000, CRC(5a76e72b) SHA1(0a058627ddf78a0bcdaba328a58712419f24e33b) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20120.5", 0x1000000, 0x0400000, CRC(7113dd7b) SHA1(f86add67c4e1349a9b9ebcd0145a30b1667df811) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20121.6", 0x1400000, 0x0400000, CRC(8c8fd521) SHA1(c715681330b5ed37a8506ac58ee2143baa721206) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20116.1", 0x1800000, 0x0400000, CRC(d30b0175) SHA1(2da5c3c02d68b8324948a8cdc93946d97fccdd8f) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20123.8", 0x1c00000, 0x0400000, CRC(35f1b89f) SHA1(1d6007c380f817def734fc3030d4fe56df4a15be) ) /* good*/
+ ROM_REGION32_BE( 0x2000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr20122.7", 0x0200000, 0x0200000, CRC(d616f78a) SHA1(8039dcdfdafb8327a19a1da46a67c0b3f7eee53a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20117.2", 0x0400000, 0x0400000, CRC(893656ea) SHA1(11e3160083ba018fbd588f07061a4e55c1efbebb) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20118.3", 0x0800000, 0x0400000, CRC(1b6a1d4c) SHA1(6b234d6b2d24df7f6d400a56698c0af2f78ce0e7) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20119.4", 0x0c00000, 0x0400000, CRC(5a76e72b) SHA1(0a058627ddf78a0bcdaba328a58712419f24e33b) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20120.5", 0x1000000, 0x0400000, CRC(7113dd7b) SHA1(f86add67c4e1349a9b9ebcd0145a30b1667df811) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20121.6", 0x1400000, 0x0400000, CRC(8c8fd521) SHA1(c715681330b5ed37a8506ac58ee2143baa721206) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20116.1", 0x1800000, 0x0400000, CRC(d30b0175) SHA1(2da5c3c02d68b8324948a8cdc93946d97fccdd8f) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20123.8", 0x1c00000, 0x0400000, CRC(35f1b89f) SHA1(1d6007c380f817def734fc3030d4fe56df4a15be) ) /* good */
ROM_END
ROM_START( cottonbm )
STV_BIOS
- ROM_REGION32_BE( 0x1c00000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr21075.7", 0x0200000, 0x0200000, CRC(200b58ba) SHA1(6daad6d70a3a41172e8d9402af775c03e191232d) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21070.2", 0x0400000, 0x0400000, CRC(56c0bf1d) SHA1(c2b564ce536c637bb723ed96683b27596e87ebe7) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21071.3", 0x0800000, 0x0400000, CRC(2bb18df2) SHA1(e900adb94ad3f48be00a4ce33e915147dc6a8737) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21072.4", 0x0c00000, 0x0400000, CRC(7c7cb977) SHA1(376dfb8014050605b00b6545520bd544768f5828) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21073.5", 0x1000000, 0x0400000, CRC(f2e5a5b7) SHA1(9258d508ef6f6529efc4ad172fd29e69877a99eb) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21074.6", 0x1400000, 0x0400000, CRC(6a7e7a7b) SHA1(a0b1e7a85e623b59886b28797281df1d65b8a5aa) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21069.1", 0x1800000, 0x0400000, CRC(6a28e3c5) SHA1(60454b71db49b872e0cb89fae2259fed601588bd) ) /* good*/
+ ROM_REGION32_BE( 0x1c00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr21075.7", 0x0200000, 0x0200000, CRC(200b58ba) SHA1(6daad6d70a3a41172e8d9402af775c03e191232d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21070.2", 0x0400000, 0x0400000, CRC(56c0bf1d) SHA1(c2b564ce536c637bb723ed96683b27596e87ebe7) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21071.3", 0x0800000, 0x0400000, CRC(2bb18df2) SHA1(e900adb94ad3f48be00a4ce33e915147dc6a8737) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21072.4", 0x0c00000, 0x0400000, CRC(7c7cb977) SHA1(376dfb8014050605b00b6545520bd544768f5828) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21073.5", 0x1000000, 0x0400000, CRC(f2e5a5b7) SHA1(9258d508ef6f6529efc4ad172fd29e69877a99eb) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21074.6", 0x1400000, 0x0400000, CRC(6a7e7a7b) SHA1(a0b1e7a85e623b59886b28797281df1d65b8a5aa) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21069.1", 0x1800000, 0x0400000, CRC(6a28e3c5) SHA1(60454b71db49b872e0cb89fae2259fed601588bd) ) /* good */
ROM_END
ROM_START( decathlt )
STV_BIOS
- ROM_REGION32_BE( 0x1800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr18967.13", 0x0000000, 0x0100000, CRC(c0446674) SHA1(4917089d95613c9d2a936ed9fe3ebd22f461aa4f) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr18968.2", 0x0400000, 0x0400000, CRC(11a891de) SHA1(1a4fa8d7e07e1d8fdc8122ef8a5b93723c007cda) ) /* good (was .1)*/
- ROM_LOAD16_WORD_SWAP( "mpr18969.3", 0x0800000, 0x0400000, CRC(199cc47d) SHA1(d78f7c6be7e9b43e208244c5c8722245f4c653e1) ) /* good (was .2)*/
- ROM_LOAD16_WORD_SWAP( "mpr18970.4", 0x0c00000, 0x0400000, CRC(8b7a509e) SHA1(8f4d36a858231764ed09b26a1141d1f055eee092) ) /* good (was .3)*/
- ROM_LOAD16_WORD_SWAP( "mpr18971.5", 0x1000000, 0x0400000, CRC(c87c443b) SHA1(f2fedb35c80e5c4855c7aebff88186397f4d51bc) ) /* good (was .4)*/
- ROM_LOAD16_WORD_SWAP( "mpr18972.6", 0x1400000, 0x0400000, CRC(45c64fca) SHA1(ae2f678b9885426ce99b615b7f62a451f9ef83f9) ) /* good (was .5)*/
+ ROM_REGION32_BE( 0x1800000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr18967a.13", 0x0000001, 0x0100000, CRC(ac59c186) SHA1(7d4924d1e4c1b9257b58a690de988b3f6486e86f) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18968.2", 0x0400000, 0x0400000, CRC(11a891de) SHA1(1a4fa8d7e07e1d8fdc8122ef8a5b93723c007cda) ) /* good (was .1) */
+ ROM_LOAD16_WORD_SWAP( "mpr18969.3", 0x0800000, 0x0400000, CRC(199cc47d) SHA1(d78f7c6be7e9b43e208244c5c8722245f4c653e1) ) /* good (was .2) */
+ ROM_LOAD16_WORD_SWAP( "mpr18970.4", 0x0c00000, 0x0400000, CRC(8b7a509e) SHA1(8f4d36a858231764ed09b26a1141d1f055eee092) ) /* good (was .3) */
+ ROM_LOAD16_WORD_SWAP( "mpr18971.5", 0x1000000, 0x0400000, CRC(c87c443b) SHA1(f2fedb35c80e5c4855c7aebff88186397f4d51bc) ) /* good (was .4) */
+ ROM_LOAD16_WORD_SWAP( "mpr18972.6", 0x1400000, 0x0400000, CRC(45c64fca) SHA1(ae2f678b9885426ce99b615b7f62a451f9ef83f9) ) /* good (was .5) */
ROM_END
-ROM_START( diehard )
- STV_BIOS /* must use USA*/
- ROM_REGION32_BE( 0x1800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fpr19119.13", 0x0000000, 0x0100000, CRC(de5c4f7c) SHA1(35f670a15e9c86edbe2fe718470f5a75b5b096ac) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr19115.2", 0x0400000, 0x0400000, CRC(6fe06a30) SHA1(dedb90f800bae8fd9df1023eb5bec7fb6c9d0179) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19116.3", 0x0800000, 0x0400000, CRC(af9e627b) SHA1(a53921c3185a93ec95299bf1c29e744e2fa3b8c0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19117.4", 0x0c00000, 0x0400000, CRC(74520ff1) SHA1(16c1acf878664b3bd866c9b94f3695ae892ac12f) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19118.5", 0x1000000, 0x0400000, CRC(2c9702f0) SHA1(5c2c66de83f2ccbe97d3b1e8c7e65999e1fa2de1) ) /* good*/
+ROM_START( diehard ) /* must use USA, Europe or Taiwan BIOS */
+ STV_BIOS
+
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr19119.13", 0x0000001, 0x0100000, CRC(de5c4f7c) SHA1(35f670a15e9c86edbe2fe718470f5a75b5b096ac) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr19115.2", 0x0400000, 0x0400000, CRC(6fe06a30) SHA1(dedb90f800bae8fd9df1023eb5bec7fb6c9d0179) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19116.3", 0x0800000, 0x0400000, CRC(af9e627b) SHA1(a53921c3185a93ec95299bf1c29e744e2fa3b8c0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19117.4", 0x0c00000, 0x0400000, CRC(74520ff1) SHA1(16c1acf878664b3bd866c9b94f3695ae892ac12f) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19118.5", 0x1000000, 0x0400000, CRC(2c9702f0) SHA1(5c2c66de83f2ccbe97d3b1e8c7e65999e1fa2de1) ) /* good */
ROM_END
ROM_START( dnmtdeka )
STV_BIOS
- ROM_REGION32_BE( 0x1800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fpr19114.13", 0x0000000, 0x0100000, CRC(1fd22a5f) SHA1(c3d9653b12354a73a3e15f23a2ab7992ffb83e46) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr19115.2", 0x0400000, 0x0400000, CRC(6fe06a30) SHA1(dedb90f800bae8fd9df1023eb5bec7fb6c9d0179) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19116.3", 0x0800000, 0x0400000, CRC(af9e627b) SHA1(a53921c3185a93ec95299bf1c29e744e2fa3b8c0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19117.4", 0x0c00000, 0x0400000, CRC(74520ff1) SHA1(16c1acf878664b3bd866c9b94f3695ae892ac12f) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19118.5", 0x1000000, 0x0400000, CRC(2c9702f0) SHA1(5c2c66de83f2ccbe97d3b1e8c7e65999e1fa2de1) ) /* good*/
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr19114.13", 0x0000001, 0x0100000, CRC(1fd22a5f) SHA1(c3d9653b12354a73a3e15f23a2ab7992ffb83e46) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr19115.2", 0x0400000, 0x0400000, CRC(6fe06a30) SHA1(dedb90f800bae8fd9df1023eb5bec7fb6c9d0179) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19116.3", 0x0800000, 0x0400000, CRC(af9e627b) SHA1(a53921c3185a93ec95299bf1c29e744e2fa3b8c0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19117.4", 0x0c00000, 0x0400000, CRC(74520ff1) SHA1(16c1acf878664b3bd866c9b94f3695ae892ac12f) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19118.5", 0x1000000, 0x0400000, CRC(2c9702f0) SHA1(5c2c66de83f2ccbe97d3b1e8c7e65999e1fa2de1) ) /* good */
ROM_END
ROM_START( ejihon )
STV_BIOS
- ROM_REGION32_BE( 0x1800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr18137.13", 0x0000000, 0x0080000, CRC(151aa9bc) SHA1(0959c60f31634816825acb57413838dcddb17d31) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr18138.2", 0x0400000, 0x0400000, CRC(f5567049) SHA1(6eb35e4b5fbda39cf7e8c42b6a568bd53a364d6d) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18139.3", 0x0800000, 0x0400000, CRC(f36b4878) SHA1(e3f63c0046bd37b7ab02fb3865b8ebcf4cf68e75) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18140.4", 0x0c00000, 0x0400000, CRC(228850a0) SHA1(d83f7fa7df08407fa45a13661393679b88800805) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18141.5", 0x1000000, 0x0400000, CRC(b51eef36) SHA1(2745cba48dc410d6d31327b956886ec284b9eac3) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18142.6", 0x1400000, 0x0400000, CRC(cf259541) SHA1(51e2c8d16506d6074f6511112ec4b6b44bed4886) ) /* good*/
+ ROM_REGION32_BE( 0x1800000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr18137.13", 0x0000001, 0x0080000, CRC(151aa9bc) SHA1(0959c60f31634816825acb57413838dcddb17d31) )
+ ROM_RELOAD( 0x100001, 0x0080000 )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18138.2", 0x0400000, 0x0400000, CRC(f5567049) SHA1(6eb35e4b5fbda39cf7e8c42b6a568bd53a364d6d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18139.3", 0x0800000, 0x0400000, CRC(f36b4878) SHA1(e3f63c0046bd37b7ab02fb3865b8ebcf4cf68e75) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18140.4", 0x0c00000, 0x0400000, CRC(228850a0) SHA1(d83f7fa7df08407fa45a13661393679b88800805) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18141.5", 0x1000000, 0x0400000, CRC(b51eef36) SHA1(2745cba48dc410d6d31327b956886ec284b9eac3) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18142.6", 0x1400000, 0x0400000, CRC(cf259541) SHA1(51e2c8d16506d6074f6511112ec4b6b44bed4886) ) /* good */
ROM_END
ROM_START( elandore )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr21307.7", 0x0200000, 0x0200000, CRC(966ad472) SHA1(d6db41d1c40d08eb6bce8a8a2f491e7533daf670) ) /* good (was .11s)*/
- ROM_LOAD16_WORD_SWAP( "mpr21301.2", 0x0400000, 0x0400000, CRC(1a23b0a0) SHA1(f9dbc7ba96dadfb00e5827622b557080449acd83) ) /* good (was .12)*/
- ROM_LOAD16_WORD_SWAP( "mpr21302.3", 0x0800000, 0x0400000, CRC(1c91ca33) SHA1(ae11209088e3bf8fc4a92dca850d7303ce949b29) ) /* good (was .13)*/
- ROM_LOAD16_WORD_SWAP( "mpr21303.4", 0x0c00000, 0x0400000, CRC(07b2350e) SHA1(f32f63fd8bec4e667f61da203d63be9a27798dfe) ) /* good (was .14)*/
- ROM_LOAD16_WORD_SWAP( "mpr21304.5", 0x1000000, 0x0400000, CRC(cfea52ae) SHA1(4b6d27e0b2a95300ee9e07ebcdc4953d77c4efbe) ) /* good (was .15)*/
- ROM_LOAD16_WORD_SWAP( "mpr21305.6", 0x1400000, 0x0400000, CRC(46cfc2a2) SHA1(8ca26bf8fa5ced040e815c125c13dd06d599e189) ) /* good (was .16)*/
- ROM_LOAD16_WORD_SWAP( "mpr21306.1", 0x1800000, 0x0400000, CRC(87a5929c) SHA1(b259341d7b0e1fa98959bf52d23db5c308a8efdd) ) /* good (was .17)*/
- ROM_LOAD16_WORD_SWAP( "mpr21308.8", 0x1c00000, 0x0400000, CRC(336ec1a4) SHA1(20d1fce050cf6132d284b91853a4dd5626372ef0) ) /* good (was .18s)*/
+ ROM_REGION32_BE( 0x2000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr21307.7", 0x0200000, 0x0200000, CRC(966ad472) SHA1(d6db41d1c40d08eb6bce8a8a2f491e7533daf670) ) /* good (was .11s) */
+ ROM_LOAD16_WORD_SWAP( "mpr21301.2", 0x0400000, 0x0400000, CRC(1a23b0a0) SHA1(f9dbc7ba96dadfb00e5827622b557080449acd83) ) /* good (was .12) */
+ ROM_LOAD16_WORD_SWAP( "mpr21302.3", 0x0800000, 0x0400000, CRC(1c91ca33) SHA1(ae11209088e3bf8fc4a92dca850d7303ce949b29) ) /* good (was .13) */
+ ROM_LOAD16_WORD_SWAP( "mpr21303.4", 0x0c00000, 0x0400000, CRC(07b2350e) SHA1(f32f63fd8bec4e667f61da203d63be9a27798dfe) ) /* good (was .14) */
+ ROM_LOAD16_WORD_SWAP( "mpr21304.5", 0x1000000, 0x0400000, CRC(cfea52ae) SHA1(4b6d27e0b2a95300ee9e07ebcdc4953d77c4efbe) ) /* good (was .15) */
+ ROM_LOAD16_WORD_SWAP( "mpr21305.6", 0x1400000, 0x0400000, CRC(46cfc2a2) SHA1(8ca26bf8fa5ced040e815c125c13dd06d599e189) ) /* good (was .16) */
+ ROM_LOAD16_WORD_SWAP( "mpr21306.1", 0x1800000, 0x0400000, CRC(87a5929c) SHA1(b259341d7b0e1fa98959bf52d23db5c308a8efdd) ) /* good (was .17) */
+ ROM_LOAD16_WORD_SWAP( "mpr21308.8", 0x1c00000, 0x0400000, CRC(336ec1a4) SHA1(20d1fce050cf6132d284b91853a4dd5626372ef0) ) /* good (was .18s) */
+
+ /* 610-0374-126 1998 317-5043-COM ST-V */
ROM_END
ROM_START( ffreveng )
STV_BIOS
- ROM_REGION32_BE( 0x1c00000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "opr21872.7", 0x0200000, 0x0200000, CRC(32d36fee) SHA1(441c4254ef2e9301e1006d69462a850ce339314b) ) /* good (was .11s)*/
- ROM_LOAD16_WORD_SWAP( "mpr21873.2", 0x0400000, 0x0400000, CRC(dac5bd98) SHA1(6102035ce9eb2f83d7d9b20f989a151f45087c67) ) /* good (was .12)*/
- ROM_LOAD16_WORD_SWAP( "mpr21874.3", 0x0800000, 0x0400000, CRC(0a7be2f1) SHA1(e2d13f36e54d1e2cb9d584db829c04a6ff65108c) ) /* good (was .13)*/
- ROM_LOAD16_WORD_SWAP( "mpr21875.4", 0x0c00000, 0x0400000, CRC(ccb75029) SHA1(9611a08a2ad0e0e82137ded6205440a948a339a4) ) /* good (was .14)*/
- ROM_LOAD16_WORD_SWAP( "mpr21876.5", 0x1000000, 0x0400000, CRC(bb92a7fc) SHA1(d9e0fab1104a46adeb0a0cfc0d070d4c63a28d55) ) /* good (was .15)*/
- ROM_LOAD16_WORD_SWAP( "mpr21877.6", 0x1400000, 0x0400000, CRC(c22a4a75) SHA1(3276bc0628e71b432f21ba9a4f5ff7ccc8769cd9) ) /* good (was .16)*/
- ROM_LOAD16_WORD_SWAP( "opr21878.1", 0x1800000, 0x0200000, CRC(2ea4a64d) SHA1(928a973dce5eba0a1628d61ba56a530de990a946) ) /* good (was .17)*/
+ ROM_REGION32_BE( 0x1a00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "ffr110.ic35", 0x0000001, 0x0100000, CRC(3ffea541) SHA1(715b070b1d574a99aeb12086de380b0b3aaa25a1) )
+
+ /* actual source ROM board have 21x 16Mbit FlashROMs instead */
+ ROM_LOAD16_WORD_SWAP( "opr21872.7", 0x0200000, 0x0200000, CRC(32d36fee) SHA1(441c4254ef2e9301e1006d69462a850ce339314b) ) /* good (was .11s) */
+ ROM_LOAD16_WORD_SWAP( "mpr21873.2", 0x0400000, 0x0400000, CRC(dac5bd98) SHA1(6102035ce9eb2f83d7d9b20f989a151f45087c67) ) /* good (was .12) */
+ ROM_LOAD16_WORD_SWAP( "mpr21874.3", 0x0800000, 0x0400000, CRC(0a7be2f1) SHA1(e2d13f36e54d1e2cb9d584db829c04a6ff65108c) ) /* good (was .13) */
+ ROM_LOAD16_WORD_SWAP( "mpr21875.4", 0x0c00000, 0x0400000, CRC(ccb75029) SHA1(9611a08a2ad0e0e82137ded6205440a948a339a4) ) /* good (was .14) */
+ ROM_LOAD16_WORD_SWAP( "mpr21876.5", 0x1000000, 0x0400000, CRC(bb92a7fc) SHA1(d9e0fab1104a46adeb0a0cfc0d070d4c63a28d55) ) /* good (was .15) */
+ ROM_LOAD16_WORD_SWAP( "mpr21877.6", 0x1400000, 0x0400000, CRC(c22a4a75) SHA1(3276bc0628e71b432f21ba9a4f5ff7ccc8769cd9) ) /* good (was .16) */
+ ROM_LOAD16_WORD_SWAP( "opr21878.1", 0x1800000, 0x0200000, CRC(2ea4a64d) SHA1(928a973dce5eba0a1628d61ba56a530de990a946) ) /* good (was .17) */
+
+ /* 610-0374-128 1998 317-5049-COM ST-V */
ROM_END
/* set system to 1 player to test rom */
ROM_START( fhboxers )
STV_BIOS
- ROM_REGION32_BE( 0x2400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fr18541a.13", 0x0000000, 0x0100000, CRC(8c61a17c) SHA1(a8aef27b53482923a506f7daa4b7a38653b4d8a4) ) /* ic13 bad?! (header is read from here, not ic7 even if both are populated on this board)*/
- ROM_RELOAD ( 0x0100000, 0x0100000 )
- ROM_RELOAD ( 0x0200000, 0x0100000 )
- ROM_RELOAD ( 0x0300000, 0x0100000 )
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fr18541a.13", 0x0000001, 0x0100000, CRC(8c61a17c) SHA1(a8aef27b53482923a506f7daa4b7a38653b4d8a4) ) /*(header is read from here, not ic7 even if both are populated on this board) */
- ROM_LOAD16_WORD_SWAP( "mpr18538.7", 0x0200000, 0x0200000, CRC(7b5230c5) SHA1(70cebc3281580b43adf42c37318e12159c28a13d) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18533.2", 0x0400000, 0x0400000, CRC(7181fe51) SHA1(646f95e1a5b64d721e961352cee6fd5adfd031ec) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18534.3", 0x0800000, 0x0400000, CRC(c87ef125) SHA1(c9ced130faf6dd9e626074b6519615654d8beb19) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18535.4", 0x0c00000, 0x0400000, CRC(929a64cf) SHA1(206dfc2a46befbcea974df1e27515c5759d88d00) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18536.5", 0x1000000, 0x0400000, CRC(51b9f64e) SHA1(bfbdfb73d24f26ce1cc5294c23a1712fb9631691) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18537.6", 0x1400000, 0x0400000, CRC(c364f6a7) SHA1(4db21bcf6ea3e75f9eb34f067b56a417589271c0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18532.1", 0x1800000, 0x0400000, CRC(39528643) SHA1(e35f4c35c9eb13e1cdcc26cb2599bb846f2c1af7) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18539.8", 0x1c00000, 0x0400000, CRC(62b3908c) SHA1(3f00e49beb0e5575cc4250a25c41f04dc91d6ed0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18540.9", 0x2000000, 0x0400000, CRC(4c2b59a4) SHA1(4d15503fcff0e9e0d1ed3bac724278102b506da0) ) /* good*/
+ ROM_LOAD16_WORD_SWAP( "mpr18538.7", 0x0200000, 0x0200000, CRC(7b5230c5) SHA1(70cebc3281580b43adf42c37318e12159c28a13d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18533.2", 0x0400000, 0x0400000, CRC(7181fe51) SHA1(646f95e1a5b64d721e961352cee6fd5adfd031ec) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18534.3", 0x0800000, 0x0400000, CRC(c87ef125) SHA1(c9ced130faf6dd9e626074b6519615654d8beb19) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18535.4", 0x0c00000, 0x0400000, CRC(929a64cf) SHA1(206dfc2a46befbcea974df1e27515c5759d88d00) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18536.5", 0x1000000, 0x0400000, CRC(51b9f64e) SHA1(bfbdfb73d24f26ce1cc5294c23a1712fb9631691) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18537.6", 0x1400000, 0x0400000, CRC(c364f6a7) SHA1(4db21bcf6ea3e75f9eb34f067b56a417589271c0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18532.1", 0x1800000, 0x0400000, CRC(39528643) SHA1(e35f4c35c9eb13e1cdcc26cb2599bb846f2c1af7) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18539.8", 0x1c00000, 0x0400000, CRC(62b3908c) SHA1(3f00e49beb0e5575cc4250a25c41f04dc91d6ed0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18540.9", 0x2000000, 0x0400000, CRC(4c2b59a4) SHA1(4d15503fcff0e9e0d1ed3bac724278102b506da0) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* the EEPROM as set up at the factory */
+ ROM_LOAD( "fhboxers.nv", 0x0000, 0x0080, CRC(590fd6da) SHA1(1abe71c62c51a246d854f02cd4cb79fd0d427e88) )
ROM_END
/* set system to 1 player to test rom */
ROM_START( findlove )
STV_BIOS
- ROM_REGION32_BE( 0x3000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr20424.13", 0x0000000, 0x0100000, CRC(4e61fa46) SHA1(e34624d98cbdf2dd04d997167d3c4decd2f208f7) ) /* ic13 bad?! (header is read from here, not ic7 even if both are populated on this board)*/
- ROM_RELOAD ( 0x0100000, 0x0100000 )
- ROM_RELOAD ( 0x0200000, 0x0100000 )
- ROM_RELOAD ( 0x0300000, 0x0100000 )
+ ROM_REGION32_BE( 0x3000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr20424.13", 0x0000001, 0x0100000, CRC(4e61fa46) SHA1(e34624d98cbdf2dd04d997167d3c4decd2f208f7) ) /*(header is read from here, not ic7 even if both are populated on this board) */
- ROM_LOAD16_WORD_SWAP( "mpr20431.7", 0x0200000, 0x0200000, CRC(ea656ced) SHA1(b2d6286081bd46a89d1284a2757b87d0bca1bbde) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20426.2", 0x0400000, 0x0400000, CRC(897d1747) SHA1(f3fb2c4ef8bc2c1658907e822f2ee2b88582afdd) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20427.3", 0x0800000, 0x0400000, CRC(a488a694) SHA1(80ec81f32e4b5712a607208b2a45cfdf6d5e1849) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20428.4", 0x0c00000, 0x0400000, CRC(4353b3b6) SHA1(f5e56396b345ff65f57a23f391b77d401f1f58b5) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20429.5", 0x1000000, 0x0400000, CRC(4f566486) SHA1(5b449288e33f02f2362ebbd515c87ea11cc02633) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20430.6", 0x1400000, 0x0400000, CRC(d1e11979) SHA1(14405997eefac22c42f0c86dca9411ba1dee9bf9) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20425.1", 0x1800000, 0x0400000, CRC(67f104c4) SHA1(8e965d2ce554ba8d37254f6bf3931dff4bce1a43) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20432.8", 0x1c00000, 0x0400000, CRC(79fcdecd) SHA1(df8e7733a51e24196914fc66a024515ee1565599) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20433.9", 0x2000000, 0x0400000, CRC(82289f29) SHA1(fb6a1015621b1afa3913da162ae71ded6b674649) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20434.10", 0x2400000, 0x0400000, CRC(85c94afc) SHA1(dfc2f16614bc499747ea87567a21c86e7bddce45) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20435.11", 0x2800000, 0x0400000, CRC(263a2e48) SHA1(27ef4bf577d240e36dcb6e6a09b9c5f24e59ce8c) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20436.12", 0x2c00000, 0x0400000, CRC(e3823f49) SHA1(754d48635bd1d4fb01ff665bfe2a71593d92f688) ) /* good*/
+ ROM_LOAD16_WORD_SWAP( "mpr20431.7", 0x0200000, 0x0200000, CRC(ea656ced) SHA1(b2d6286081bd46a89d1284a2757b87d0bca1bbde) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20426.2", 0x0400000, 0x0400000, CRC(897d1747) SHA1(f3fb2c4ef8bc2c1658907e822f2ee2b88582afdd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20427.3", 0x0800000, 0x0400000, CRC(a488a694) SHA1(80ec81f32e4b5712a607208b2a45cfdf6d5e1849) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20428.4", 0x0c00000, 0x0400000, CRC(4353b3b6) SHA1(f5e56396b345ff65f57a23f391b77d401f1f58b5) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20429.5", 0x1000000, 0x0400000, CRC(4f566486) SHA1(5b449288e33f02f2362ebbd515c87ea11cc02633) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20430.6", 0x1400000, 0x0400000, CRC(d1e11979) SHA1(14405997eefac22c42f0c86dca9411ba1dee9bf9) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20425.1", 0x1800000, 0x0400000, CRC(67f104c4) SHA1(8e965d2ce554ba8d37254f6bf3931dff4bce1a43) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20432.8", 0x1c00000, 0x0400000, CRC(79fcdecd) SHA1(df8e7733a51e24196914fc66a024515ee1565599) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20433.9", 0x2000000, 0x0400000, CRC(82289f29) SHA1(fb6a1015621b1afa3913da162ae71ded6b674649) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20434.10", 0x2400000, 0x0400000, CRC(85c94afc) SHA1(dfc2f16614bc499747ea87567a21c86e7bddce45) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20435.11", 0x2800000, 0x0400000, CRC(263a2e48) SHA1(27ef4bf577d240e36dcb6e6a09b9c5f24e59ce8c) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20436.12", 0x2c00000, 0x0400000, CRC(e3823f49) SHA1(754d48635bd1d4fb01ff665bfe2a71593d92f688) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* the EEPROM as set up at the factory */
+ ROM_LOAD( "findlove.nv", 0x0000, 0x0080, CRC(df2fa9f6) SHA1(f05450e1648eafd2ffb52e50769f07bdc75ffb95) )
ROM_END
ROM_START( finlarch )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "finlarch.13", 0x0000000, 0x0100000, CRC(4505fa9e) SHA1(96c6399146cf9c8f1d27a8fb6a265f937258004a) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr18257.2", 0x0400000, 0x0400000, CRC(137fdf55) SHA1(07a02fe531b3707e063498f5bc9749bd1b4cadb3) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18258.3", 0x0800000, 0x0400000, CRC(f519c505) SHA1(5cad39314e46b98c24a71f1c2c10c682ef3bdcf3) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18259.4", 0x0c00000, 0x0400000, CRC(5cabc775) SHA1(84383a4cbe3b1a9dcc6c140cff165425666dc780) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18260.5", 0x1000000, 0x0400000, CRC(f5b92082) SHA1(806ad85a187a23a5cf867f2f3dea7d8150065b8e) ) /* good*/
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "finlarch.13", 0x0000001, 0x0100000, CRC(4505fa9e) SHA1(96c6399146cf9c8f1d27a8fb6a265f937258004a) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18257.2", 0x0400000, 0x0400000, CRC(137fdf55) SHA1(07a02fe531b3707e063498f5bc9749bd1b4cadb3) ) /* good */
+ ROM_RELOAD( 0x1400000, 0x0400000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18258.3", 0x0800000, 0x0400000, CRC(f519c505) SHA1(5cad39314e46b98c24a71f1c2c10c682ef3bdcf3) ) /* good */
+ ROM_RELOAD( 0x1800000, 0x0400000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18259.4", 0x0c00000, 0x0400000, CRC(5cabc775) SHA1(84383a4cbe3b1a9dcc6c140cff165425666dc780) ) /* good */
+ ROM_RELOAD( 0x1c00000, 0x0400000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18260.5", 0x1000000, 0x0400000, CRC(f5b92082) SHA1(806ad85a187a23a5cf867f2f3dea7d8150065b8e) ) /* good */
+ ROM_RELOAD( 0x2000000, 0x0400000 )
ROM_END
ROM_START( gaxeduel )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr17766.13", 0x0000000, 0x0080000, CRC(a83fcd62) SHA1(4ce77ebaa0e93c6553ad8f7fb87cbdc32433402b) ) /* ic13 bad?!*/
- ROM_LOAD16_WORD_SWAP( "mpr17768.2", 0x0400000, 0x0400000, CRC(d6808a7d) SHA1(83a97bbe1160cb45b3bdcbde8adc0d9bae5ded60) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17769.3", 0x0800000, 0x0400000, CRC(3471dd35) SHA1(24febddfe70984cebc0e6948ad718e0e6957fa82) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17770.4", 0x0c00000, 0x0400000, CRC(06978a00) SHA1(a8d1333a9f4322e28b23724937f595805315b136) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17771.5", 0x1000000, 0x0400000, CRC(aea2ea3b) SHA1(2fbe3e10d3f5a3b3099a7ed5b38b93b6e22e19b8) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17772.6", 0x1400000, 0x0400000, CRC(b3dc0e75) SHA1(fbe2790c84466d186ea3e9d41edfcb7afaf54bea) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17767.1", 0x1800000, 0x0400000, CRC(9ba1e7b1) SHA1(f297c3697d2e8ba4476d672267163f91f371b362) ) /* good*/
+ ROM_REGION32_BE( 0x1c00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr17766.13", 0x0000001, 0x0080000, CRC(a83fcd62) SHA1(4ce77ebaa0e93c6553ad8f7fb87cbdc32433402b) )
+ ROM_RELOAD( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr17768.2", 0x0400000, 0x0400000, CRC(d6808a7d) SHA1(83a97bbe1160cb45b3bdcbde8adc0d9bae5ded60) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17769.3", 0x0800000, 0x0400000, CRC(3471dd35) SHA1(24febddfe70984cebc0e6948ad718e0e6957fa82) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17770.4", 0x0c00000, 0x0400000, CRC(06978a00) SHA1(a8d1333a9f4322e28b23724937f595805315b136) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17771.5", 0x1000000, 0x0400000, CRC(aea2ea3b) SHA1(2fbe3e10d3f5a3b3099a7ed5b38b93b6e22e19b8) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17772.6", 0x1400000, 0x0400000, CRC(b3dc0e75) SHA1(fbe2790c84466d186ea3e9d41edfcb7afaf54bea) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17767.1", 0x1800000, 0x0400000, CRC(9ba1e7b1) SHA1(f297c3697d2e8ba4476d672267163f91f371b362) ) /* good */
ROM_END
ROM_START( grdforce )
STV_BIOS
- ROM_REGION32_BE( 0x1800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr20844.7", 0x0200000, 0x0200000, CRC(283e7587) SHA1(477fabc27cfe149ad17757e31f10665dcf8c0860) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20839.2", 0x0400000, 0x0400000, CRC(facd4dd8) SHA1(2582894c98b31ab719f1865d4623dad6736dc877) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20840.3", 0x0800000, 0x0400000, CRC(fe0158e6) SHA1(73460effe69fb8f16dd952271542b7803471a599) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20841.4", 0x0c00000, 0x0400000, CRC(d87ac873) SHA1(35b8fa3862e09dca530e9597f983f5a22919cf08) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20842.5", 0x1000000, 0x0400000, CRC(baebc506) SHA1(f5f59f9263956d0c49c729729cf6db31dc861d3b) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20843.6", 0x1400000, 0x0400000, CRC(263e49cc) SHA1(67979861ca2784b3ce39d87e7994e6e7351b40e5) ) /* good*/
+ ROM_REGION32_BE( 0x1800000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr20844.7", 0x0200000, 0x0200000, CRC(283e7587) SHA1(477fabc27cfe149ad17757e31f10665dcf8c0860) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20839.2", 0x0400000, 0x0400000, CRC(facd4dd8) SHA1(2582894c98b31ab719f1865d4623dad6736dc877) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20840.3", 0x0800000, 0x0400000, CRC(fe0158e6) SHA1(73460effe69fb8f16dd952271542b7803471a599) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20841.4", 0x0c00000, 0x0400000, CRC(d87ac873) SHA1(35b8fa3862e09dca530e9597f983f5a22919cf08) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20842.5", 0x1000000, 0x0400000, CRC(baebc506) SHA1(f5f59f9263956d0c49c729729cf6db31dc861d3b) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20843.6", 0x1400000, 0x0400000, CRC(263e49cc) SHA1(67979861ca2784b3ce39d87e7994e6e7351b40e5) ) /* good */
ROM_END
ROM_START( groovef )
STV_BIOS
- ROM_REGION32_BE( 0x2400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr19820.7", 0x0200000, 0x0100000, CRC(e93c4513) SHA1(f9636529224880c49bd2cc5572bd5bf41dbf911a) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19815.2", 0x0400000, 0x0400000, CRC(1b9b14e6) SHA1(b1828c520cb108e2927a23273ebd2939dca52304) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19816.3", 0x0800000, 0x0400000, CRC(83f5731c) SHA1(2f645737f945c59a1a2fabf3b21a761be9e8c8a6) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19817.4", 0x0c00000, 0x0400000, CRC(525bd6c7) SHA1(2db2501177fb0b44d0fad2054eddf356c4ea08f2) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19818.5", 0x1000000, 0x0400000, CRC(66723ba8) SHA1(0a8379e46a8f8cab11befeadd9abdf59dba68e27) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19819.6", 0x1400000, 0x0400000, CRC(ee8c55f4) SHA1(f6d86b2c2ab43ec5baefb8ccc25e11af4d82712d) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19814.1", 0x1800000, 0x0400000, CRC(8f20e9f7) SHA1(30ff5ad0427208e7265cb996e870c4dc0fbbf7d2) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19821.8", 0x1c00000, 0x0400000, CRC(f69a76e6) SHA1(b7e41f34d8b787bf1b4d587e5d8bddb241c043a8) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19822.9", 0x2000000, 0x0200000, CRC(5e8c4b5f) SHA1(1d146fbe3d0bfa68993135ba94ef18081ab65d31) ) /* good*/
+ ROM_REGION32_BE( 0x2200000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr19820.7", 0x0200000, 0x0100000, CRC(e93c4513) SHA1(f9636529224880c49bd2cc5572bd5bf41dbf911a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19815.2", 0x0400000, 0x0400000, CRC(1b9b14e6) SHA1(b1828c520cb108e2927a23273ebd2939dca52304) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19816.3", 0x0800000, 0x0400000, CRC(83f5731c) SHA1(2f645737f945c59a1a2fabf3b21a761be9e8c8a6) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19817.4", 0x0c00000, 0x0400000, CRC(525bd6c7) SHA1(2db2501177fb0b44d0fad2054eddf356c4ea08f2) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19818.5", 0x1000000, 0x0400000, CRC(66723ba8) SHA1(0a8379e46a8f8cab11befeadd9abdf59dba68e27) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19819.6", 0x1400000, 0x0400000, CRC(ee8c55f4) SHA1(f6d86b2c2ab43ec5baefb8ccc25e11af4d82712d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19814.1", 0x1800000, 0x0400000, CRC(8f20e9f7) SHA1(30ff5ad0427208e7265cb996e870c4dc0fbbf7d2) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19821.8", 0x1c00000, 0x0400000, CRC(f69a76e6) SHA1(b7e41f34d8b787bf1b4d587e5d8bddb241c043a8) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19822.9", 0x2000000, 0x0200000, CRC(5e8c4b5f) SHA1(1d146fbe3d0bfa68993135ba94ef18081ab65d31) ) /* good */
ROM_END
ROM_START( hanagumi )
STV_BIOS
- ROM_REGION32_BE( 0x3000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr20143.7", 0x0200000, 0x0100000, CRC(7bfc38d0) SHA1(66f223e7ff2b5456a6f4185b7ab36f9cd833351a) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20138.2", 0x0400000, 0x0400000, CRC(fdcf1046) SHA1(cbb1f03879833c17feffdd6f5a4fbff06e1059a2) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20139.3", 0x0800000, 0x0400000, CRC(7f0140e5) SHA1(f2f7de7620d66a596d552e1af491a0592ebc4e51) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20140.4", 0x0c00000, 0x0400000, CRC(2fa03852) SHA1(798ce008f6fc24a00f85298188c8d0d01933640d) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20141.5", 0x1000000, 0x0400000, CRC(45d6d21b) SHA1(fe0f0b2195b74e79b8efb6a7c0b7bedca7194c48) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20142.6", 0x1400000, 0x0400000, CRC(e38561ec) SHA1(c04c400be033bc74a7bb2a60f6ae00853a2220d4) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20137.1", 0x1800000, 0x0400000, CRC(181d2688) SHA1(950059f89eda30d8a5bce145421f507e226b8b3e) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20144.8", 0x1c00000, 0x0400000, CRC(235b43f6) SHA1(e35d9bf15ac805513ab3edeca4f264647a2dc0b0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20145.9", 0x2000000, 0x0400000, CRC(aeaac7a1) SHA1(5c75ecce49a5c53dbb0b07e75f3a76e6db9976d0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20146.10", 0x2400000, 0x0400000, CRC(39bab9a2) SHA1(077132e6a03afd181ee9ca9ca4f7c9cbf418e57e) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20147.11", 0x2800000, 0x0400000, CRC(294ab997) SHA1(aeba269ae7d056f07edecf96bc138231c66c3637) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20148.12", 0x2c00000, 0x0400000, CRC(5337ccb0) SHA1(a998bb116eb10c4044410f065c5ddeb845f9dab5) ) /* good*/
+ ROM_REGION32_BE( 0x3000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr20143.7", 0x0200000, 0x0100000, CRC(7bfc38d0) SHA1(66f223e7ff2b5456a6f4185b7ab36f9cd833351a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20138.2", 0x0400000, 0x0400000, CRC(fdcf1046) SHA1(cbb1f03879833c17feffdd6f5a4fbff06e1059a2) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20139.3", 0x0800000, 0x0400000, CRC(7f0140e5) SHA1(f2f7de7620d66a596d552e1af491a0592ebc4e51) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20140.4", 0x0c00000, 0x0400000, CRC(2fa03852) SHA1(798ce008f6fc24a00f85298188c8d0d01933640d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20141.5", 0x1000000, 0x0400000, CRC(45d6d21b) SHA1(fe0f0b2195b74e79b8efb6a7c0b7bedca7194c48) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20142.6", 0x1400000, 0x0400000, CRC(e38561ec) SHA1(c04c400be033bc74a7bb2a60f6ae00853a2220d4) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20137.1", 0x1800000, 0x0400000, CRC(181d2688) SHA1(950059f89eda30d8a5bce145421f507e226b8b3e) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20144.8", 0x1c00000, 0x0400000, CRC(235b43f6) SHA1(e35d9bf15ac805513ab3edeca4f264647a2dc0b0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20145.9", 0x2000000, 0x0400000, CRC(aeaac7a1) SHA1(5c75ecce49a5c53dbb0b07e75f3a76e6db9976d0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20146.10", 0x2400000, 0x0400000, CRC(39bab9a2) SHA1(077132e6a03afd181ee9ca9ca4f7c9cbf418e57e) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20147.11", 0x2800000, 0x0400000, CRC(294ab997) SHA1(aeba269ae7d056f07edecf96bc138231c66c3637) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20148.12", 0x2c00000, 0x0400000, CRC(5337ccb0) SHA1(a998bb116eb10c4044410f065c5ddeb845f9dab5) ) /* good */
ROM_END
ROM_START( introdon )
STV_BIOS
- ROM_REGION32_BE( 0x1c00000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr18937.13", 0x0000000, 0x0080000, CRC(1f40d766) SHA1(35d9751c1b23cfbf448f2a9e9cf3b121929368ae) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr18944.7", 0x0200000, 0x0100000, CRC(f7f75ce5) SHA1(0787ece9f89cc1847889adbf08ba5d3ccbc405de) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18939.2", 0x0400000, 0x0400000, CRC(ef95a6e6) SHA1(3026c52ad542997d5b0e621b389c0e01240cb486) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18940.3", 0x0800000, 0x0400000, CRC(cabab4cd) SHA1(b251609573c4b0ccc933188f32226855b25fd9da) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18941.4", 0x0c00000, 0x0400000, CRC(f4a33a20) SHA1(bf0f33495fb5c9de4ae5036cedda65b3ece217e8) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18942.5", 0x1000000, 0x0400000, CRC(8dd0a446) SHA1(a75e3552b0fb99e0b253c0906f62fabcf204b735) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18943.6", 0x1400000, 0x0400000, CRC(d8702a9e) SHA1(960dd3cb0b9eb1f18b8d0bc0da532b600d583ceb) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18938.1", 0x1800000, 0x0400000, CRC(580ecb83) SHA1(6c59f7da408b53f9fa7aa32c1b53328b5fd6334d) ) /* good*/
+ ROM_REGION32_BE( 0x1c00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr18937.13", 0x0000001, 0x0080000, CRC(1f40d766) SHA1(35d9751c1b23cfbf448f2a9e9cf3b121929368ae) )
+ ROM_RELOAD( 0x0100001, 0x0080000)
+ ROM_LOAD16_WORD_SWAP( "mpr18944.7", 0x0200000, 0x0100000, CRC(f7f75ce5) SHA1(0787ece9f89cc1847889adbf08ba5d3ccbc405de) ) /* good */
+ ROM_RELOAD( 0x0300000, 0x0100000)
+ ROM_LOAD16_WORD_SWAP( "mpr18939.2", 0x0400000, 0x0400000, CRC(ef95a6e6) SHA1(3026c52ad542997d5b0e621b389c0e01240cb486) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18940.3", 0x0800000, 0x0400000, CRC(cabab4cd) SHA1(b251609573c4b0ccc933188f32226855b25fd9da) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18941.4", 0x0c00000, 0x0400000, CRC(f4a33a20) SHA1(bf0f33495fb5c9de4ae5036cedda65b3ece217e8) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18942.5", 0x1000000, 0x0400000, CRC(8dd0a446) SHA1(a75e3552b0fb99e0b253c0906f62fabcf204b735) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18943.6", 0x1400000, 0x0400000, CRC(d8702a9e) SHA1(960dd3cb0b9eb1f18b8d0bc0da532b600d583ceb) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18938.1", 0x1800000, 0x0400000, CRC(580ecb83) SHA1(6c59f7da408b53f9fa7aa32c1b53328b5fd6334d) ) /* good */
ROM_END
/* set system to 1 player to test rom */
ROM_START( kiwames )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr18737.13", 0x0000000, 0x0080000, CRC(cfad6c49) SHA1(fc69980a351ed13307706db506c79c774eabeb66) ) /* bad*/
- ROM_LOAD16_WORD_SWAP( "mpr18738.2", 0x0400000, 0x0400000, CRC(4b3c175a) SHA1(b6d2438ae1d3d51950a7ed1eaadf2dae45c4e7b1) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18739.3", 0x0800000, 0x0400000, CRC(eb41fa67) SHA1(d12acebb1df9eafd17aff1841087f5017225e7e7) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18740.4", 0x0c00000, 0x0200000, CRC(9ca7962f) SHA1(a09e0db2246b34ca7efa3165afbc5ba292a95398) ) /* good*/
+ ROM_REGION32_BE( 0xe00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr18737.13", 0x0000001, 0x0080000, CRC(cfad6c49) SHA1(fc69980a351ed13307706db506c79c774eabeb66) ) /* good */
+ ROM_RELOAD( 0x0100001, 0x0080000)
+
+ ROM_LOAD16_WORD_SWAP( "mpr18738.2", 0x0400000, 0x0400000, CRC(4b3c175a) SHA1(b6d2438ae1d3d51950a7ed1eaadf2dae45c4e7b1) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18739.3", 0x0800000, 0x0400000, CRC(eb41fa67) SHA1(d12acebb1df9eafd17aff1841087f5017225e7e7) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18740.4", 0x0c00000, 0x0200000, CRC(9ca7962f) SHA1(a09e0db2246b34ca7efa3165afbc5ba292a95398) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* the EEPROM as set up at the factory */
+ ROM_LOAD( "kiwames.nv", 0x0000, 0x0080, CRC(c7002732) SHA1(57395d256a58ddcedd354ce1f2c458321be40505) )
ROM_END
ROM_START( maruchan )
STV_BIOS
- ROM_REGION32_BE( 0x2400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr20416.13", 0x0000000, 0x0100000, CRC(8bf0176d) SHA1(5bd468e2ffed042ee84e2ceb8712ff5883a1d824) ) /* bad*/
- ROM_LOAD16_WORD_SWAP( "mpr20417.2", 0x0400000, 0x0400000, CRC(636c2a08) SHA1(47986b71d68f6a1852e4e2b03ca7b6e48e83718b) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20418.3", 0x0800000, 0x0400000, CRC(3f0d9e34) SHA1(2ec81e40ebf689d17b6421820bfb0a1280a8ef25) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20419.4", 0x0c00000, 0x0400000, CRC(ec969815) SHA1(b59782174051f5717b06f43e57dd8a2a6910d95f) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20420.5", 0x1000000, 0x0400000, CRC(f2902c88) SHA1(df81e137e8aa4bd37e1d14fce4d593cfd14608f0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20421.6", 0x1400000, 0x0400000, CRC(cd0b477c) SHA1(5169cc47fae465b11bc50f5e8410d84c2b2eee42) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20422.1", 0x1800000, 0x0400000, CRC(66335049) SHA1(59f1968001d1e9fe30990a56309bae18033eee62) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20423.8", 0x1c00000, 0x0400000, CRC(2bd55832) SHA1(1a1a510f30882d4d726b594a6541a12c552fafb4) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20443.9", 0x2000000, 0x0400000, CRC(8ac288f5) SHA1(0c08874e6ab2b07b17438721fb535434a626115f) ) /* good*/
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF ) /* SH2 code */
+ ROM_LOAD16_BYTE( "epr20416.13", 0x0000001, 0x0100000, CRC(8bf0176d) SHA1(5bd468e2ffed042ee84e2ceb8712ff5883a1d824) ) /* good */
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20417.2", 0x0400000, 0x0400000, CRC(636c2a08) SHA1(47986b71d68f6a1852e4e2b03ca7b6e48e83718b) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20418.3", 0x0800000, 0x0400000, CRC(3f0d9e34) SHA1(2ec81e40ebf689d17b6421820bfb0a1280a8ef25) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20419.4", 0x0c00000, 0x0400000, CRC(ec969815) SHA1(b59782174051f5717b06f43e57dd8a2a6910d95f) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20420.5", 0x1000000, 0x0400000, CRC(f2902c88) SHA1(df81e137e8aa4bd37e1d14fce4d593cfd14608f0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20421.6", 0x1400000, 0x0400000, CRC(cd0b477c) SHA1(5169cc47fae465b11bc50f5e8410d84c2b2eee42) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20422.1", 0x1800000, 0x0400000, CRC(66335049) SHA1(59f1968001d1e9fe30990a56309bae18033eee62) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20423.8", 0x1c00000, 0x0400000, CRC(2bd55832) SHA1(1a1a510f30882d4d726b594a6541a12c552fafb4) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20443.9", 0x2000000, 0x0400000, CRC(8ac288f5) SHA1(0c08874e6ab2b07b17438721fb535434a626115f) ) /* good */
ROM_END
/* set system to 1 player to test rom */
ROM_START( myfairld )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr21000.7", 0x0200000, 0x0200000, CRC(2581c560) SHA1(5fb64f0e09583d50dfea7ad613d45aad30b677a5) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20995.2", 0x0400000, 0x0400000, CRC(1bb73f24) SHA1(8773654810de760c5dffbb561f43e259b074a61b) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20996.3", 0x0800000, 0x0400000, CRC(993c3859) SHA1(93f95e3e080a08961784482607919c1ab3eeb5e5) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20997.4", 0x0c00000, 0x0400000, CRC(f0bf64a4) SHA1(f51431f1a736bbc498fa0baa1f8570f89984d9f9) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20998.5", 0x1000000, 0x0400000, CRC(d3b19786) SHA1(1933e57272cd68cc323922fa93a9af97dcef8450) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20999.6", 0x1400000, 0x0400000, CRC(82e31f25) SHA1(0cf74af14abb6ede21d19bc22041214232751594) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20994.1", 0x1800000, 0x0400000, CRC(a69243a0) SHA1(e5a1b6ec62bdd5b015ed6cf48f5a6aabaf4bd837) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21001.8", 0x1c00000, 0x0400000, CRC(95fbe549) SHA1(8cfb48f353b2849600373d66f293f103bca700df) ) /* good*/
+ ROM_REGION32_BE( 0x2000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr21000.7", 0x0200000, 0x0200000, CRC(2581c560) SHA1(5fb64f0e09583d50dfea7ad613d45aad30b677a5) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20995.2", 0x0400000, 0x0400000, CRC(1bb73f24) SHA1(8773654810de760c5dffbb561f43e259b074a61b) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20996.3", 0x0800000, 0x0400000, CRC(993c3859) SHA1(93f95e3e080a08961784482607919c1ab3eeb5e5) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20997.4", 0x0c00000, 0x0400000, CRC(f0bf64a4) SHA1(f51431f1a736bbc498fa0baa1f8570f89984d9f9) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20998.5", 0x1000000, 0x0400000, CRC(d3b19786) SHA1(1933e57272cd68cc323922fa93a9af97dcef8450) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20999.6", 0x1400000, 0x0400000, CRC(82e31f25) SHA1(0cf74af14abb6ede21d19bc22041214232751594) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20994.1", 0x1800000, 0x0400000, CRC(a69243a0) SHA1(e5a1b6ec62bdd5b015ed6cf48f5a6aabaf4bd837) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21001.8", 0x1c00000, 0x0400000, CRC(95fbe549) SHA1(8cfb48f353b2849600373d66f293f103bca700df) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* the EEPROM as set up at the factory */
+ ROM_LOAD( "myfairld.nv", 0x0000, 0x0080, CRC(c7cf3a5a) SHA1(5365f38047821305658f94395f03cf2c49c87576) )
ROM_END
ROM_START( othellos )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr20967.7", 0x0200000, 0x0200000, CRC(efc05b97) SHA1(a533366c3aaba90dcac8f3654db9ad902efca258) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20963.2", 0x0400000, 0x0400000, CRC(2cc4f141) SHA1(8bd1998aff8615b34d119fab3637a08ed6e8e1e4) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20964.3", 0x0800000, 0x0400000, CRC(5f5cda94) SHA1(616be219a2512e80c875eddf05137c23aedf6f65) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20965.4", 0x0c00000, 0x0400000, CRC(37044f3e) SHA1(cbc071554cfd8bb12a337c04b169de6c6309c3ab) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20966.5", 0x1000000, 0x0400000, CRC(b94b83de) SHA1(ba1b3135d0ad057f0786f94c9d06b5e347bedea8) ) /* good*/
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr20967.7", 0x0200000, 0x0200000, CRC(efc05b97) SHA1(a533366c3aaba90dcac8f3654db9ad902efca258) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20963.2", 0x0400000, 0x0400000, CRC(2cc4f141) SHA1(8bd1998aff8615b34d119fab3637a08ed6e8e1e4) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20964.3", 0x0800000, 0x0400000, CRC(5f5cda94) SHA1(616be219a2512e80c875eddf05137c23aedf6f65) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20965.4", 0x0c00000, 0x0400000, CRC(37044f3e) SHA1(cbc071554cfd8bb12a337c04b169de6c6309c3ab) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20966.5", 0x1000000, 0x0400000, CRC(b94b83de) SHA1(ba1b3135d0ad057f0786f94c9d06b5e347bedea8) ) /* good */
ROM_END
ROM_START( pblbeach )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr18852.13", 0x0000000, 0x0080000, CRC(d12414ec) SHA1(0f42ec9e41983781b6892622b00398a102072aa7) ) /* bad*/
- ROM_LOAD16_WORD_SWAP( "mpr18853.2", 0x0400000, 0x0400000, CRC(b9268c97) SHA1(8734e3f0e6b2849d173e3acc9d0308084a4e84fd) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18854.3", 0x0800000, 0x0400000, CRC(3113c8bc) SHA1(4e4600646ddd1978988d27430ffdf0d1d405b804) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18855.4", 0x0c00000, 0x0400000, CRC(daf6ad0c) SHA1(2a14a6a42e4eb68abb7a427e43062dfde2d13c5c) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18856.5", 0x1000000, 0x0400000, CRC(214cef24) SHA1(f62b462170b377cff16bb6c6126cbba00b013a87) ) /* good*/
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr18852.13", 0x0000001, 0x0080000, CRC(d12414ec) SHA1(0f42ec9e41983781b6892622b00398a102072aa7) ) /* good */
+ ROM_RELOAD ( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18853.2", 0x0400000, 0x0400000, CRC(b9268c97) SHA1(8734e3f0e6b2849d173e3acc9d0308084a4e84fd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18854.3", 0x0800000, 0x0400000, CRC(3113c8bc) SHA1(4e4600646ddd1978988d27430ffdf0d1d405b804) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18855.4", 0x0c00000, 0x0400000, CRC(daf6ad0c) SHA1(2a14a6a42e4eb68abb7a427e43062dfde2d13c5c) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18856.5", 0x1000000, 0x0400000, CRC(214cef24) SHA1(f62b462170b377cff16bb6c6126cbba00b013a87) ) /* good */
ROM_END
ROM_START( prikura )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr19337.7", 0x0200000, 0x0200000, CRC(76f69ff3) SHA1(5af2e1eb3288d70c2a1c71d0b6370125d65c7757) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19333.2", 0x0400000, 0x0400000, CRC(eb57a6a6) SHA1(cdacaa7a2fb1a343195e2ac5fd02eabf27f89ccd) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19334.3", 0x0800000, 0x0400000, CRC(c9979981) SHA1(be491a4ac118d5025d6a6f2d9267a6d52f21d2b6) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19335.4", 0x0c00000, 0x0400000, CRC(9e000140) SHA1(9b7dc3dc7f9dc048d2fcbc2b44ae79a631ceb381) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19336.5", 0x1000000, 0x0400000, CRC(2363fa4b) SHA1(f45e53352520be4ea313eeab87bcab83f479d5a8) ) /* good*/
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr19337.7", 0x0200000, 0x0200000, CRC(76f69ff3) SHA1(5af2e1eb3288d70c2a1c71d0b6370125d65c7757) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19333.2", 0x0400000, 0x0400000, CRC(eb57a6a6) SHA1(cdacaa7a2fb1a343195e2ac5fd02eabf27f89ccd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19334.3", 0x0800000, 0x0400000, CRC(c9979981) SHA1(be491a4ac118d5025d6a6f2d9267a6d52f21d2b6) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19335.4", 0x0c00000, 0x0400000, CRC(9e000140) SHA1(9b7dc3dc7f9dc048d2fcbc2b44ae79a631ceb381) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19336.5", 0x1000000, 0x0400000, CRC(2363fa4b) SHA1(f45e53352520be4ea313eeab87bcab83f479d5a8) ) /* good */
ROM_END
ROM_START( puyosun )
STV_BIOS
- ROM_REGION32_BE( 0x2400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr19531.13", 0x0000000, 0x0080000, CRC(ac81024f) SHA1(b22c7c1798fade7ae992ff83b138dd23e6292d3f) ) /* bad*/
- ROM_LOAD16_WORD_SWAP( "mpr19533.2", 0x0400000, 0x0400000, CRC(17ec54ba) SHA1(d4cdc86926519291cc78980ec513e1cfc677e76e) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19534.3", 0x0800000, 0x0400000, CRC(820e4781) SHA1(7ea5626ad4e1929a5ec28a99ec12bc364df8f70d) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19535.4", 0x0c00000, 0x0400000, CRC(94fadfa4) SHA1(a7d0727cf601e00f1ea31e6bf3e591349c3f6030) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19536.5", 0x1000000, 0x0400000, CRC(5765bc9c) SHA1(b217c292e7cc8ed73a39a3ae7009bc9dd031e376) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19537.6", 0x1400000, 0x0400000, CRC(8b736686) SHA1(aec347c0f3e5dd8646e85f68d71ca9acc3bf62c3) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19532.1", 0x1800000, 0x0400000, CRC(985f0c9d) SHA1(de1ad42ef3cf3f4f071e9801696407be7ae29d21) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19538.8", 0x1c00000, 0x0400000, CRC(915a723e) SHA1(96480441a69d6aad3887ed6f46b0a6bebfb752aa) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19539.9", 0x2000000, 0x0400000, CRC(72a297e5) SHA1(679987e62118dd1bf7c074f4b88678e1a1187437) ) /* good*/
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr19531.13", 0x0000001, 0x0080000, CRC(ac81024f) SHA1(b22c7c1798fade7ae992ff83b138dd23e6292d3f) ) /* good */
+ ROM_RELOAD ( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr19533.2", 0x0400000, 0x0400000, CRC(17ec54ba) SHA1(d4cdc86926519291cc78980ec513e1cfc677e76e) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19534.3", 0x0800000, 0x0400000, CRC(820e4781) SHA1(7ea5626ad4e1929a5ec28a99ec12bc364df8f70d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19535.4", 0x0c00000, 0x0400000, CRC(94fadfa4) SHA1(a7d0727cf601e00f1ea31e6bf3e591349c3f6030) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19536.5", 0x1000000, 0x0400000, CRC(5765bc9c) SHA1(b217c292e7cc8ed73a39a3ae7009bc9dd031e376) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19537.6", 0x1400000, 0x0400000, CRC(8b736686) SHA1(aec347c0f3e5dd8646e85f68d71ca9acc3bf62c3) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19532.1", 0x1800000, 0x0400000, CRC(985f0c9d) SHA1(de1ad42ef3cf3f4f071e9801696407be7ae29d21) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19538.8", 0x1c00000, 0x0400000, CRC(915a723e) SHA1(96480441a69d6aad3887ed6f46b0a6bebfb752aa) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19539.9", 0x2000000, 0x0400000, CRC(72a297e5) SHA1(679987e62118dd1bf7c074f4b88678e1a1187437) ) /* good */
ROM_END
ROM_START( rsgun )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr20958.7", 0x0200000, 0x0200000, CRC(cbe5a449) SHA1(b4744ab71ccbadda1921ba43dd1148e57c0f84c5) ) /* good (was .11s)*/
- ROM_LOAD16_WORD_SWAP( "mpr20959.2", 0x0400000, 0x0400000, CRC(a953330b) SHA1(965274a7297cb88e281fcbdd3ec5025c6463cc7b) ) /* good (was .12)*/
- ROM_LOAD16_WORD_SWAP( "mpr20960.3", 0x0800000, 0x0400000, CRC(b5ab9053) SHA1(87c5d077eb1219c35fa65b4e11d5b62e826f5236) ) /* good (was .13)*/
- ROM_LOAD16_WORD_SWAP( "mpr20961.4", 0x0c00000, 0x0400000, CRC(0e06295c) SHA1(0ec2842622f3e9dc5689abd58aeddc7e5603b97a) ) /* good (was .14)*/
- ROM_LOAD16_WORD_SWAP( "mpr20962.5", 0x1000000, 0x0400000, CRC(f1e6c7fc) SHA1(0ba0972f1bc7c56f4e0589d3e363523cea988bb0) ) /* good (was .15)*/
- /*Without the following the game crashes,maybe we need to mirror the previous roms in this location?*/
- ROM_FILL( 0x1400000, 0x0c00000, 0x00 )
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr20958.7", 0x0200000, 0x0200000, CRC(cbe5a449) SHA1(b4744ab71ccbadda1921ba43dd1148e57c0f84c5) ) /* good (was .11s) */
+ ROM_LOAD16_WORD_SWAP( "mpr20959.2", 0x0400000, 0x0400000, CRC(a953330b) SHA1(965274a7297cb88e281fcbdd3ec5025c6463cc7b) ) /* good (was .12) */
+ ROM_LOAD16_WORD_SWAP( "mpr20960.3", 0x0800000, 0x0400000, CRC(b5ab9053) SHA1(87c5d077eb1219c35fa65b4e11d5b62e826f5236) ) /* good (was .13) */
+ ROM_LOAD16_WORD_SWAP( "mpr20961.4", 0x0c00000, 0x0400000, CRC(0e06295c) SHA1(0ec2842622f3e9dc5689abd58aeddc7e5603b97a) ) /* good (was .14) */
+ ROM_LOAD16_WORD_SWAP( "mpr20962.5", 0x1000000, 0x0400000, CRC(f1e6c7fc) SHA1(0ba0972f1bc7c56f4e0589d3e363523cea988bb0) ) /* good (was .15) */
+
+ /* 610-0374-96 1998 317-5041-COM ST-V */
ROM_END
ROM_START( sandor )
STV_BIOS
- ROM_REGION32_BE( 0x2c00000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "sando-r.13", 0x0000000, 0x0100000, CRC(fe63a239) SHA1(01502d4494f968443581cd2c74f25967d41f775e) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr18635.8", 0x1c00000, 0x0400000, CRC(441e1368) SHA1(acb2a7e8d44c2203b8d3c7a7b70e20ffb120bebf) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18636.9", 0x2000000, 0x0400000, CRC(fff1dd80) SHA1(36b8e1526a4370ae33fd4671850faf51c448bca4) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18637.10", 0x2400000, 0x0400000, CRC(83aced0f) SHA1(6cd1702b9c2655dc4f56c666607c333f62b09fc0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18638.11", 0x2800000, 0x0400000, CRC(caab531b) SHA1(a77bdcc27d183896c0ed576eeebcc1785d93669e) ) /* good*/
+ ROM_REGION32_BE( 0x2c00000, REGION_USER1, ROMREGION_ERASEFF ) /* SH2 code */
+ ROM_LOAD16_BYTE( "sando-r.13", 0x0000001, 0x0100000, CRC(fe63a239) SHA1(01502d4494f968443581cd2c74f25967d41f775e) )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18635.8", 0x1c00000, 0x0400000, CRC(441e1368) SHA1(acb2a7e8d44c2203b8d3c7a7b70e20ffb120bebf) ) /* good */
+ ROM_RELOAD( 0x0400000, 0x0400000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18636.9", 0x2000000, 0x0400000, CRC(fff1dd80) SHA1(36b8e1526a4370ae33fd4671850faf51c448bca4) ) /* good */
+ ROM_RELOAD( 0x0800000, 0x0400000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18637.10", 0x2400000, 0x0400000, CRC(83aced0f) SHA1(6cd1702b9c2655dc4f56c666607c333f62b09fc0) ) /* good */
+ ROM_RELOAD( 0x0c00000, 0x0400000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18638.11", 0x2800000, 0x0400000, CRC(caab531b) SHA1(a77bdcc27d183896c0ed576eeebcc1785d93669e) ) /* good */
+ ROM_RELOAD( 0x1000000, 0x0400000 )
ROM_END
ROM_START( thunt )
STV_BIOS
- ROM_REGION32_BE( 0x2c00000, REGION_USER1, 0 ) /* SH2 code */
- /* I suspect this should be one rom */
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
ROM_LOAD16_BYTE( "th-ic7_2.stv", 0x0200000, 0x0080000, CRC(c4e993de) SHA1(7aa433bc2623cb19a09d4ef4c8233a2d29901020) )
ROM_LOAD16_BYTE( "th-ic7_1.stv", 0x0200001, 0x0080000, CRC(1355cc18) SHA1(a9b731228a807b2b01f933fe0f7dcdbadaf89b7e) )
- /* missing, putting sando-r roms here gives some good gfx but a lot wrong*/
- ROM_LOAD16_WORD_SWAP( "thunt.2", 0x0400000, 0x0400000, NO_DUMP )
- ROM_LOAD16_WORD_SWAP( "thunt.3", 0x0800000, 0x0400000, NO_DUMP )
- ROM_LOAD16_WORD_SWAP( "thunt.4", 0x0c00000, 0x0400000, NO_DUMP )
- ROM_LOAD16_WORD_SWAP( "thunt.5", 0x1000000, 0x0400000, NO_DUMP )
+ ROM_LOAD16_WORD_SWAP( "th-e-2.ic2", 0x0400000, 0x0400000, CRC(47315694) SHA1(4a7cc195b98dbca146f5efe3b5b35be0f13b2f4a) )
+ ROM_LOAD16_WORD_SWAP( "th-e-3.ic3", 0x0800000, 0x0400000, CRC(c9290b44) SHA1(4e51e667edf330cc20e600cf1500f332cc533e20) )
+ ROM_LOAD16_WORD_SWAP( "th-e-4.ic4", 0x0c00000, 0x0400000, CRC(c672e40b) SHA1(4ba189de7b8fb5ca45fb15c89cdaf0f860831d52) )
+ ROM_LOAD16_WORD_SWAP( "th-e-5.ic5", 0x1000000, 0x0400000, CRC(3914b805) SHA1(1331ce82ba0bdfc76fe3456a5252e69c00e2cf1f) )
ROM_END
-ROM_START( sassisu )
+ROM_START( sasissu )
STV_BIOS
- ROM_REGION32_BE( 0x1c00000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr20542.13", 0x0000000, 0x0100000, CRC(0e632db5) SHA1(9bc52794892eec22d381387d13a0388042e30714) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr20544.2", 0x0400000, 0x0400000, CRC(661fff5e) SHA1(41f4ddda7adf004b52cc9a076606a60f31947d19) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20545.3", 0x0800000, 0x0400000, CRC(8e3a37be) SHA1(a3227cdc4f03bb088e7f9aed225b238da3283e01) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20546.4", 0x0c00000, 0x0400000, CRC(72020886) SHA1(e80bdeb11b726eb23f2283950d65d55e31a5672e) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20547.5", 0x1000000, 0x0400000, CRC(8362e397) SHA1(71f13689a60572a04b91417a9a48adfd3bd0f5dc) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20548.6", 0x1400000, 0x0400000, CRC(e37534d9) SHA1(79988cbb1537ca99fdd0288a86564fe1f714d052) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20543.1", 0x1800000, 0x0400000, CRC(1f688cdf) SHA1(a90c1011119adb50e0d9d5cd3d7616a307b2d7e8) ) /* good*/
+ ROM_REGION32_BE( 0x1c00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr20542.13", 0x0000001, 0x0100000, CRC(0e632db5) SHA1(9bc52794892eec22d381387d13a0388042e30714) )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20544.2", 0x0400000, 0x0400000, CRC(661fff5e) SHA1(41f4ddda7adf004b52cc9a076606a60f31947d19) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20545.3", 0x0800000, 0x0400000, CRC(8e3a37be) SHA1(a3227cdc4f03bb088e7f9aed225b238da3283e01) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20546.4", 0x0c00000, 0x0400000, CRC(72020886) SHA1(e80bdeb11b726eb23f2283950d65d55e31a5672e) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20547.5", 0x1000000, 0x0400000, CRC(8362e397) SHA1(71f13689a60572a04b91417a9a48adfd3bd0f5dc) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20548.6", 0x1400000, 0x0400000, CRC(e37534d9) SHA1(79988cbb1537ca99fdd0288a86564fe1f714d052) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20543.1", 0x1800000, 0x0400000, CRC(1f688cdf) SHA1(a90c1011119adb50e0d9d5cd3d7616a307b2d7e8) ) /* good */
ROM_END
/* set to 1 player to test */
ROM_START( seabass )
STV_BIOS
- ROM_REGION32_BE( 0x2400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "seabassf.13", 0x0000000, 0x0100000, CRC(6d7c39cc) SHA1(d9d1663134420b75c65ee07d7d547254785f2f83) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr20551.2", 0x0400000, 0x0400000, CRC(9a0c6dd8) SHA1(26600372cc673ce3678945f4b5dc4e3ab31643a4) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20552.3", 0x0800000, 0x0400000, CRC(5f46b0aa) SHA1(1aa576b15971c0ffb4e08d4802246841b31b6f35) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20553.4", 0x0c00000, 0x0400000, CRC(c0f8a6b6) SHA1(2038b9231a950450267be0db24b31d8035db79ad) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20554.5", 0x1000000, 0x0400000, CRC(215fc1f9) SHA1(f042145622ba4bbbcce5f050a4c9eae42cb7adcd) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20555.6", 0x1400000, 0x0400000, CRC(3f5186a9) SHA1(d613f307ab150a7eae358aa449206af05db5f9d7) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20550.1", 0x1800000, 0x0400000, CRC(083e1ca8) SHA1(03944dd8fe86f305ca4bd2d71e2140e03798ffc9) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20556.8", 0x1c00000, 0x0400000, CRC(1fd70c6c) SHA1(d9d2e362d13238216f4f7e10095fb8383bbd91e8) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20557.9", 0x2000000, 0x0400000, CRC(3c9ba442) SHA1(2e5b795cf4cdc11ab3e4887b2f77c7147c6e3eec) ) /* good*/
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "seabassf.13", 0x0000001, 0x0100000, CRC(6d7c39cc) SHA1(d9d1663134420b75c65ee07d7d547254785f2f83) )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20551.2", 0x0400000, 0x0400000, CRC(9a0c6dd8) SHA1(26600372cc673ce3678945f4b5dc4e3ab31643a4) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20552.3", 0x0800000, 0x0400000, CRC(5f46b0aa) SHA1(1aa576b15971c0ffb4e08d4802246841b31b6f35) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20553.4", 0x0c00000, 0x0400000, CRC(c0f8a6b6) SHA1(2038b9231a950450267be0db24b31d8035db79ad) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20554.5", 0x1000000, 0x0400000, CRC(215fc1f9) SHA1(f042145622ba4bbbcce5f050a4c9eae42cb7adcd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20555.6", 0x1400000, 0x0400000, CRC(3f5186a9) SHA1(d613f307ab150a7eae358aa449206af05db5f9d7) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20550.1", 0x1800000, 0x0400000, CRC(083e1ca8) SHA1(03944dd8fe86f305ca4bd2d71e2140e03798ffc9) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20556.8", 0x1c00000, 0x0400000, CRC(1fd70c6c) SHA1(d9d2e362d13238216f4f7e10095fb8383bbd91e8) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20557.9", 0x2000000, 0x0400000, CRC(3c9ba442) SHA1(2e5b795cf4cdc11ab3e4887b2f77c7147c6e3eec) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* the EEPROM as set up at the factory */
+ ROM_LOAD( "seabass.nv", 0x0000, 0x0080, CRC(4e7c0944) SHA1(dbba78f6a7f3e7d12d5c4fff36117db82f5f9c01) )
ROM_END
ROM_START( shanhigw )
STV_BIOS
- ROM_REGION32_BE( 0x0800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr18341.7", 0x0200000, 0x0200000, CRC(cc5e8646) SHA1(a733616c118140ff3887d30d595533f9a1beae06) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18340.2", 0x0400000, 0x0200000, CRC(8db23212) SHA1(85d604a5c6ab97188716dbcd77d365af12a238fe) ) /* good*/
+ ROM_REGION32_BE( 0x600000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr18341.7", 0x0200000, 0x0200000, CRC(cc5e8646) SHA1(a733616c118140ff3887d30d595533f9a1beae06) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18340.2", 0x0400000, 0x0200000, CRC(8db23212) SHA1(85d604a5c6ab97188716dbcd77d365af12a238fe) ) /* good */
ROM_END
ROM_START( shienryu )
STV_BIOS
- ROM_REGION32_BE( 0x0c00000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr19631.7", 0x0200000, 0x0200000, CRC(3a4b1abc) SHA1(3b14b7fdebd4817da32ea374c15a38c695ffeff1) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19632.2", 0x0400000, 0x0400000, CRC(985fae46) SHA1(f953bde91805b97b60d2ab9270f9d2933e064d95) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19633.3", 0x0800000, 0x0400000, CRC(e2f0b037) SHA1(97861d09e10ce5d2b10bf5559574b3f489e28077) ) /* good*/
+ ROM_REGION32_BE( 0xc00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr19631.7", 0x0200000, 0x0200000, CRC(3a4b1abc) SHA1(3b14b7fdebd4817da32ea374c15a38c695ffeff1) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19632.2", 0x0400000, 0x0400000, CRC(985fae46) SHA1(f953bde91805b97b60d2ab9270f9d2933e064d95) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19633.3", 0x0800000, 0x0400000, CRC(e2f0b037) SHA1(97861d09e10ce5d2b10bf5559574b3f489e28077) ) /* good */
+
+ ROM_LOAD( "eeprom-shienryu.bin", 0x0000, 0x0080, CRC(98db6925) SHA1(e78545e8f62d19f8e00197c62ff0e56f6c85e355) )
ROM_END
-ROM_START( sleague )
- STV_BIOS /* must use USA*/
- ROM_REGION32_BE( 0x3000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr18777.13", 0x0000000, 0x0080000, CRC(8d180866) SHA1(d47ebabab6e06400312d39f68cd818852e496b96) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr18778.8", 0x1c00000, 0x0400000, CRC(25e1300e) SHA1(64f3843f62cee34a47244ad5ee78fb2aa35289e3) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18779.9", 0x2000000, 0x0400000, CRC(51e2fabd) SHA1(3aa361149af516f16d7d422596ee82014a183c2b) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18780.10", 0x2400000, 0x0400000, CRC(8cd4dd74) SHA1(9ffec1280b3965d52f643894bdfecdd792028191) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18781.11", 0x2800000, 0x0400000, CRC(13ee41ae) SHA1(cdbaeac4c90b5ee84233c299612f7f28280a6ba6) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18782.12", 0x2c00000, 0x0200000, CRC(9be2270a) SHA1(f2de5cd6b269f123305e30bed2b474019e4f05b8) ) /* good*/
+ROM_START( smleague ) /* only runs with the USA bios */
+ STV_BIOS
+
+ ROM_REGION32_BE( 0x2e00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr18777.13", 0x0000001, 0x0080000, CRC(8d180866) SHA1(d47ebabab6e06400312d39f68cd818852e496b96) )
+ ROM_RELOAD ( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18778.8", 0x1c00000, 0x0400000, CRC(25e1300e) SHA1(64f3843f62cee34a47244ad5ee78fb2aa35289e3) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18779.9", 0x2000000, 0x0400000, CRC(51e2fabd) SHA1(3aa361149af516f16d7d422596ee82014a183c2b) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18780.10", 0x2400000, 0x0400000, CRC(8cd4dd74) SHA1(9ffec1280b3965d52f643894bdfecdd792028191) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18781.11", 0x2800000, 0x0400000, CRC(13ee41ae) SHA1(cdbaeac4c90b5ee84233c299612f7f28280a6ba6) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18782.12", 0x2c00000, 0x0200000, CRC(9be2270a) SHA1(f2de5cd6b269f123305e30bed2b474019e4f05b8) ) /* good */
ROM_END
ROM_START( sokyugrt )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fpr19188.13", 0x0000000, 0x0100000, CRC(45a27e32) SHA1(96e1bab8bdadf7071afac2a0a6dd8fd8989f12a6) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr19189.2", 0x0400000, 0x0400000, CRC(0b202a3e) SHA1(6691b5af2cacd6092ec03886b78c2565953fa297) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19190.3", 0x0800000, 0x0400000, CRC(1777ded8) SHA1(dd332ac79f0a6d82b6bde35b795b2845003dd1a5) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19191.4", 0x0c00000, 0x0400000, CRC(ec6eb07b) SHA1(01fe4832ece8638ea6f4060099d9105fe8092c88) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19192.5", 0x1000000, 0x0200000, CRC(cb544a1e) SHA1(eb3ba9758487d0e8c4bbfc41453fe35b35cce3bf) ) /* good*/
+ ROM_REGION32_BE( 0x1200000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr19188.13", 0x0000001, 0x0100000, CRC(45a27e32) SHA1(96e1bab8bdadf7071afac2a0a6dd8fd8989f12a6) )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr19189.2", 0x0400000, 0x0400000, CRC(0b202a3e) SHA1(6691b5af2cacd6092ec03886b78c2565953fa297) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19190.3", 0x0800000, 0x0400000, CRC(1777ded8) SHA1(dd332ac79f0a6d82b6bde35b795b2845003dd1a5) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19191.4", 0x0c00000, 0x0400000, CRC(ec6eb07b) SHA1(01fe4832ece8638ea6f4060099d9105fe8092c88) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19192.5", 0x1000000, 0x0200000, CRC(cb544a1e) SHA1(eb3ba9758487d0e8c4bbfc41453fe35b35cce3bf) ) /* good */
ROM_END
/* set to 1 player to test */
ROM_START( sss )
STV_BIOS
- ROM_REGION32_BE( 0x1800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr21488.13", 0x0000000, 0x0080000, CRC(71c9def1) SHA1(a544a0b4046307172d2c1bf426ed24845f87d894) ) /* ic13 bad (was .24)*/
- ROM_LOAD16_WORD_SWAP( "mpr21489.2", 0x0400000, 0x0400000, CRC(4c85152b) SHA1(78f2f1c31718d5bf631d8813daf9a11ea2a0e451) ) /* ic2 good (was .12)*/
- ROM_LOAD16_WORD_SWAP( "mpr21490.3", 0x0800000, 0x0400000, CRC(03da67f8) SHA1(02f9ba7549ca552291dc0ff1b631103015838bba) ) /* ic3 good (was .13)*/
- ROM_LOAD16_WORD_SWAP( "mpr21491.4", 0x0c00000, 0x0400000, CRC(cf7ee784) SHA1(af823df2d60d8ef3d17628b95a04136b807ca095) ) /* ic4 good (was .14)*/
- ROM_LOAD16_WORD_SWAP( "mpr21492.5", 0x1000000, 0x0400000, CRC(57753894) SHA1(5c51167c158443d02a53d724a5ceb73055876c06) ) /* ic5 good (was .15)*/
- ROM_LOAD16_WORD_SWAP( "mpr21493.6", 0x1400000, 0x0400000, CRC(efb2d271) SHA1(a591e48206704fbda5fef3ce69ad279da1017ed6) ) /* ic6 good (was .16)*/
+ ROM_REGION32_BE( 0x1800000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr21488.13", 0x0000001, 0x0080000, CRC(71c9def1) SHA1(a544a0b4046307172d2c1bf426ed24845f87d894) )
+ ROM_RELOAD ( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr21489.2", 0x0400000, 0x0400000, CRC(4c85152b) SHA1(78f2f1c31718d5bf631d8813daf9a11ea2a0e451) ) /* ic2 good (was .12) */
+ ROM_LOAD16_WORD_SWAP( "mpr21490.3", 0x0800000, 0x0400000, CRC(03da67f8) SHA1(02f9ba7549ca552291dc0ff1b631103015838bba) ) /* ic3 good (was .13) */
+ ROM_LOAD16_WORD_SWAP( "mpr21491.4", 0x0c00000, 0x0400000, CRC(cf7ee784) SHA1(af823df2d60d8ef3d17628b95a04136b807ca095) ) /* ic4 good (was .14) */
+ ROM_LOAD16_WORD_SWAP( "mpr21492.5", 0x1000000, 0x0400000, CRC(57753894) SHA1(5c51167c158443d02a53d724a5ceb73055876c06) ) /* ic5 good (was .15) */
+ ROM_LOAD16_WORD_SWAP( "mpr21493.6", 0x1400000, 0x0400000, CRC(efb2d271) SHA1(a591e48206704fbda5fef3ce69ad279da1017ed6) ) /* ic6 good (was .16) */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* the EEPROM as set up at the factory */
+ ROM_LOAD( "sss.nv", 0x0000, 0x0080, CRC(3473b2f3) SHA1(6480b4b321af8ee6e967710e74f2556c17bfca97) )
+
+ /* 610-0374-107 1998 317-5042-COM ST-V */
ROM_END
ROM_START( suikoenb )
STV_BIOS
- ROM_REGION32_BE( 0x2400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fpr17834.13", 0x0000000, 0x0100000, CRC(746ef686) SHA1(e31c317991a687662a8a2a45aed411001e5f1941) ) /* ic13 bad*/
- ROM_RELOAD ( 0x0100000, 0x0100000 )
- ROM_RELOAD ( 0x0200000, 0x0100000 )
- ROM_RELOAD ( 0x0300000, 0x0100000 )
- ROM_LOAD16_WORD_SWAP( "mpr17836.2", 0x0400000, 0x0400000, CRC(55e9642d) SHA1(5198291cd1dce0398eb47760db2c19eae99273b0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17837.3", 0x0800000, 0x0400000, CRC(13d1e667) SHA1(cd513ceb33cc20032090113b61227638cf3b3998) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17838.4", 0x0c00000, 0x0400000, CRC(f9e70032) SHA1(8efdbcce01bdf77acfdb293545c59bf224a9c7d2) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17839.5", 0x1000000, 0x0400000, CRC(1b2762c5) SHA1(5c7d5fc8a4705249a5b0ea64d51dc3dc95d723f5) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17840.6", 0x1400000, 0x0400000, CRC(0fd4c857) SHA1(42caf22716e834d59e60d45c24f51d95734e63ae) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17835.1", 0x1800000, 0x0400000, CRC(77f5cb43) SHA1(a4f54bc08d73a56caee5b26bea06360568655bd7) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17841.8", 0x1c00000, 0x0400000, CRC(f48beffc) SHA1(92f1730a206f4a0abf7fb0ee1210e083a464ad70) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17842.9", 0x2000000, 0x0400000, CRC(ac8deed7) SHA1(370eb2216b8080d3ddadbd32804db63c4ebac76f) ) /* good*/
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr17834.13", 0x0000001, 0x0100000, CRC(746ef686) SHA1(e31c317991a687662a8a2a45aed411001e5f1941) )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr17836.2", 0x0400000, 0x0400000, CRC(55e9642d) SHA1(5198291cd1dce0398eb47760db2c19eae99273b0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17837.3", 0x0800000, 0x0400000, CRC(13d1e667) SHA1(cd513ceb33cc20032090113b61227638cf3b3998) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17838.4", 0x0c00000, 0x0400000, CRC(f9e70032) SHA1(8efdbcce01bdf77acfdb293545c59bf224a9c7d2) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17839.5", 0x1000000, 0x0400000, CRC(1b2762c5) SHA1(5c7d5fc8a4705249a5b0ea64d51dc3dc95d723f5) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17840.6", 0x1400000, 0x0400000, CRC(0fd4c857) SHA1(42caf22716e834d59e60d45c24f51d95734e63ae) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17835.1", 0x1800000, 0x0400000, CRC(77f5cb43) SHA1(a4f54bc08d73a56caee5b26bea06360568655bd7) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17841.8", 0x1c00000, 0x0400000, CRC(f48beffc) SHA1(92f1730a206f4a0abf7fb0ee1210e083a464ad70) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17842.9", 0x2000000, 0x0400000, CRC(ac8deed7) SHA1(370eb2216b8080d3ddadbd32804db63c4ebac76f) ) /* good */
ROM_END
ROM_START( twcup98 )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr20819.13", 0x0000000, 0x0100000, CRC(d930dfc8) SHA1(f66cc955181720661a0334fe67fa5750ddf9758b) ) /* ic13 bad (was .24)*/
- ROM_LOAD16_WORD_SWAP( "mpr20821.2", 0x0400000, 0x0400000, CRC(2d930d23) SHA1(5fcaf4257f3639cb3aa407d2936f616499a09d97) ) /* ic2 good (was .12)*/
- ROM_LOAD16_WORD_SWAP( "mpr20822.3", 0x0800000, 0x0400000, CRC(8b33a5e2) SHA1(d5689ac8aad63509febe9aa4077351be09b2d8d4) ) /* ic3 good (was .13)*/
- ROM_LOAD16_WORD_SWAP( "mpr20823.4", 0x0c00000, 0x0400000, CRC(6e6d4e95) SHA1(c387d03ba27580c62ac0bf780915fdf41552df6f) ) /* ic4 good (was .14)*/
- ROM_LOAD16_WORD_SWAP( "mpr20824.5", 0x1000000, 0x0400000, CRC(4cf18a25) SHA1(310961a5f114fea8938a3f514dffd5231e910a5a) ) /* ic5 good (was .15)*/
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr20819.24", 0x0000001, 0x0100000, CRC(d930dfc8) SHA1(f66cc955181720661a0334fe67fa5750ddf9758b) ) /* tested as IC13 */
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20821.12", 0x0400000, 0x0400000, CRC(2d930d23) SHA1(5fcaf4257f3639cb3aa407d2936f616499a09d97) ) /* tested as IC2 */
+ ROM_LOAD16_WORD_SWAP( "mpr20822.13", 0x0800000, 0x0400000, CRC(8b33a5e2) SHA1(d5689ac8aad63509febe9aa4077351be09b2d8d4) ) /* tested as IC3 */
+ ROM_LOAD16_WORD_SWAP( "mpr20823.14", 0x0c00000, 0x0400000, CRC(6e6d4e95) SHA1(c387d03ba27580c62ac0bf780915fdf41552df6f) ) /* tested as IC4 */
+ ROM_LOAD16_WORD_SWAP( "mpr20824.15", 0x1000000, 0x0400000, CRC(4cf18a25) SHA1(310961a5f114fea8938a3f514dffd5231e910a5a) ) /* tested as IC5 */
+
+ /* 610-0374-89 1998 317-5039-COM ST-V */
ROM_END
ROM_START( vfkids )
STV_BIOS
- ROM_REGION32_BE( 0x3000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fpr18914.13", 0x0000000, 0x0100000, CRC(cd35730a) SHA1(645b52b449766beb740ab8f99957f8f431351ceb) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr18916.4", 0x0c00000, 0x0400000, CRC(4aae3ddb) SHA1(b75479e73f1bce3f0c27fbd90820fa51eb1914a6) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18917.5", 0x1000000, 0x0400000, CRC(edf6edc3) SHA1(478e958f4f10a8126a00c83feca4a55ad6c25503) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18918.6", 0x1400000, 0x0400000, CRC(d3a95036) SHA1(e300bbbb71fb06027dc539c9bbb12946770ffc95) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18915.1", 0x1800000, 0x0400000, CRC(09cc38e5) SHA1(4dfe0e2f21f746020ec557e62487aa7558cbc1fd) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18919.8", 0x1c00000, 0x0400000, CRC(4ac700de) SHA1(b1a8501f1683de380dfa49c9cabbe28bd70a5b26) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18920.9", 0x2000000, 0x0400000, CRC(0106e36c) SHA1(f7c30dc9fedb9da079dd7d52fdecbeb8721c5dee) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18921.10", 0x2400000, 0x0400000, CRC(c23d51ad) SHA1(0169b7e2df84e8caa2b349843bd0673f6de2195f) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18922.11", 0x2800000, 0x0400000, CRC(99d0ab90) SHA1(e9c82a826cc76ffbe2423913645cf5d5ba2506d6) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr18923.12", 0x2c00000, 0x0400000, CRC(30a41ae9) SHA1(78a3d88b5e6cf669b660460ac967daf408038883) ) /* good*/
+ ROM_REGION32_BE( 0x3000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr18914.13", 0x0000001, 0x0100000, CRC(cd35730a) SHA1(645b52b449766beb740ab8f99957f8f431351ceb) )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr18916.4", 0x0c00000, 0x0400000, CRC(4aae3ddb) SHA1(b75479e73f1bce3f0c27fbd90820fa51eb1914a6) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18917.5", 0x1000000, 0x0400000, CRC(edf6edc3) SHA1(478e958f4f10a8126a00c83feca4a55ad6c25503) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18918.6", 0x1400000, 0x0400000, CRC(d3a95036) SHA1(e300bbbb71fb06027dc539c9bbb12946770ffc95) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18915.1", 0x1800000, 0x0400000, CRC(09cc38e5) SHA1(4dfe0e2f21f746020ec557e62487aa7558cbc1fd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18919.8", 0x1c00000, 0x0400000, CRC(4ac700de) SHA1(b1a8501f1683de380dfa49c9cabbe28bd70a5b26) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18920.9", 0x2000000, 0x0400000, CRC(0106e36c) SHA1(f7c30dc9fedb9da079dd7d52fdecbeb8721c5dee) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18921.10", 0x2400000, 0x0400000, CRC(c23d51ad) SHA1(0169b7e2df84e8caa2b349843bd0673f6de2195f) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18922.11", 0x2800000, 0x0400000, CRC(99d0ab90) SHA1(e9c82a826cc76ffbe2423913645cf5d5ba2506d6) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr18923.12", 0x2c00000, 0x0400000, CRC(30a41ae9) SHA1(78a3d88b5e6cf669b660460ac967daf408038883) ) /* good */
ROM_END
ROM_START( vfremix )
STV_BIOS
- ROM_REGION32_BE( 0x1c00000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr17944.13", 0x0000000, 0x0100000, CRC(a5bdc560) SHA1(d3830480a611b7d88760c672ce46a2ea74076487) ) /* ic13 bad*/
- ROM_LOAD16_WORD_SWAP( "mpr17946.2", 0x0400000, 0x0400000, CRC(4cb245f7) SHA1(363d9936b27043b5858c956a45736ac05aefc54e) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17947.3", 0x0800000, 0x0400000, CRC(fef4a9fb) SHA1(1b4bd095962db769da17d3644df10f62d041e914) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17948.4", 0x0c00000, 0x0400000, CRC(3e2b251a) SHA1(be6191c18727d7cbc6399fd4c1aaae59304af30c) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17949.5", 0x1000000, 0x0400000, CRC(b2ecea25) SHA1(320c0e7ce34e81e2fe6400cbeb2cb3ca74426cc8) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17950.6", 0x1400000, 0x0400000, CRC(5b1f981d) SHA1(693b5744d210a2ac8b77e7c8c87f07ca859f8aed) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr17945.1", 0x1800000, 0x0200000, CRC(03ede188) SHA1(849c7fab5b97e043fea3deb8df6cc195ccced0e0) ) /* good*/
+ ROM_REGION32_BE( 0x1a00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr17944.13", 0x0000001, 0x0080000, CRC(3304c175) SHA1(6d847efad73d361cac4d7fcb452ccf89efa13e24) ) /* 27C040 */
+ ROM_RELOAD ( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr17946.2", 0x0400000, 0x0400000, CRC(4cb245f7) SHA1(363d9936b27043b5858c956a45736ac05aefc54e) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17947.3", 0x0800000, 0x0400000, CRC(fef4a9fb) SHA1(1b4bd095962db769da17d3644df10f62d041e914) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17948.4", 0x0c00000, 0x0400000, CRC(3e2b251a) SHA1(be6191c18727d7cbc6399fd4c1aaae59304af30c) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17949.5", 0x1000000, 0x0400000, CRC(b2ecea25) SHA1(320c0e7ce34e81e2fe6400cbeb2cb3ca74426cc8) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17950.6", 0x1400000, 0x0400000, CRC(5b1f981d) SHA1(693b5744d210a2ac8b77e7c8c87f07ca859f8aed) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr17945.1", 0x1800000, 0x0200000, CRC(03ede188) SHA1(849c7fab5b97e043fea3deb8df6cc195ccced0e0) ) /* good */
ROM_END
/* set to 1 player to test */
ROM_START( vmahjong )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr19620.7", 0x0200000, 0x0200000, CRC(c98de7e5) SHA1(5346f884793bcb080aa01967e91b54ced4a9802f) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19615.2", 0x0400000, 0x0400000, CRC(c62896da) SHA1(52a5b10ca8af31295d2d700349eca038c418b522) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19616.3", 0x0800000, 0x0400000, CRC(f62207c7) SHA1(87e60183365c6f7e62c7a0667f88df0c7f5457fd) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19617.4", 0x0c00000, 0x0400000, CRC(ab667e19) SHA1(2608a567888fe052753d0679d9a831d7706dbc86) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19618.5", 0x1000000, 0x0400000, CRC(9782ceee) SHA1(405dd42706416e128b1e2fde225b5343e9330092) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19619.6", 0x1400000, 0x0400000, CRC(0b76866c) SHA1(10add2993dfe9daf757ec2ff8675390081a93c0a) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19614.1", 0x1800000, 0x0400000, CRC(b83b3f03) SHA1(e5a5919ee74964633eaaf4af2fe04c38604ccf16) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr19621.8", 0x1c00000, 0x0400000, CRC(f92616b3) SHA1(61a9dda92a86a02d027260e11b1bad3b0dda9f02) ) /* good*/
+ ROM_REGION32_BE( 0x2000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr19620.7", 0x0200000, 0x0200000, CRC(c98de7e5) SHA1(5346f884793bcb080aa01967e91b54ced4a9802f) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19615.2", 0x0400000, 0x0400000, CRC(c62896da) SHA1(52a5b10ca8af31295d2d700349eca038c418b522) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19616.3", 0x0800000, 0x0400000, CRC(f62207c7) SHA1(87e60183365c6f7e62c7a0667f88df0c7f5457fd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19617.4", 0x0c00000, 0x0400000, CRC(ab667e19) SHA1(2608a567888fe052753d0679d9a831d7706dbc86) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19618.5", 0x1000000, 0x0400000, CRC(9782ceee) SHA1(405dd42706416e128b1e2fde225b5343e9330092) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19619.6", 0x1400000, 0x0400000, CRC(0b76866c) SHA1(10add2993dfe9daf757ec2ff8675390081a93c0a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19614.1", 0x1800000, 0x0400000, CRC(b83b3f03) SHA1(e5a5919ee74964633eaaf4af2fe04c38604ccf16) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr19621.8", 0x1c00000, 0x0400000, CRC(f92616b3) SHA1(61a9dda92a86a02d027260e11b1bad3b0dda9f02) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* the EEPROM as set up at the factory */
+ ROM_LOAD( "vmahjong.nv", 0x0000, 0x0080, CRC(4e6487f4) SHA1(d6d930ab5f21b8c4f42812d08b3ee90f2bc94081) )
ROM_END
ROM_START( winterht )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "fpr20108.13", 0x0000000, 0x0100000, CRC(1ef9ced0) SHA1(abc90ce341cd17bb77349d611d6879389611f0bf) ) /* bad*/
- ROM_LOAD16_WORD_SWAP( "mpr20110.2", 0x0400000, 0x0400000, CRC(238ef832) SHA1(20fade5730ff8e249a1450c41bfdff6e133f4768) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20111.3", 0x0800000, 0x0400000, CRC(b0a86f69) SHA1(e66427f70413ad43fccc38423962c5eeda01094f) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20112.4", 0x0c00000, 0x0400000, CRC(3ba2b49b) SHA1(5ad154a8b774075479d791e29cbaf221d47557fc) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20113.5", 0x1000000, 0x0400000, CRC(8c858b41) SHA1(d05d2980363c8440863fe2fdb39274de246bd4b9) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20114.6", 0x1400000, 0x0400000, CRC(b723862c) SHA1(1e0a08669f16fc4cb647124e0c215233ccb98e5a) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20109.1", 0x1800000, 0x0400000, CRC(c1a713b8) SHA1(a7fefa6e9a1e3aecff5ead41da6fd3aec2ef502a) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20115.8", 0x1c00000, 0x0400000, CRC(dd01f2ad) SHA1(3bb48dc8670d9460fea2a67400ddb573472c2f4f) ) /* good*/
+ ROM_REGION32_BE( 0x2000000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "fpr20108.13", 0x0000001, 0x0100000, CRC(1ef9ced0) SHA1(abc90ce341cd17bb77349d611d6879389611f0bf) ) /* good */
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20110.2", 0x0400000, 0x0400000, CRC(238ef832) SHA1(20fade5730ff8e249a1450c41bfdff6e133f4768) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20111.3", 0x0800000, 0x0400000, CRC(b0a86f69) SHA1(e66427f70413ad43fccc38423962c5eeda01094f) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20112.4", 0x0c00000, 0x0400000, CRC(3ba2b49b) SHA1(5ad154a8b774075479d791e29cbaf221d47557fc) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20113.5", 0x1000000, 0x0400000, CRC(8c858b41) SHA1(d05d2980363c8440863fe2fdb39274de246bd4b9) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20114.6", 0x1400000, 0x0400000, CRC(b723862c) SHA1(1e0a08669f16fc4cb647124e0c215233ccb98e5a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20109.1", 0x1800000, 0x0400000, CRC(c1a713b8) SHA1(a7fefa6e9a1e3aecff5ead41da6fd3aec2ef502a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20115.8", 0x1c00000, 0x0400000, CRC(dd01f2ad) SHA1(3bb48dc8670d9460fea2a67400ddb573472c2f4f) ) /* good */
ROM_END
ROM_START( znpwfv )
STV_BIOS
- ROM_REGION32_BE( 0x2800000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "epr20398.13", 0x0000000, 0x0100000, CRC(3fb56a0b) SHA1(13c2fa2d94b106d39e46f71d15fbce3607a5965a) ) /* bad*/
- ROM_LOAD16_WORD_SWAP( "mpr20400.2", 0x0400000, 0x0400000, CRC(1edfbe05) SHA1(b0edd3f3d57408101ae6eb0aec742afbb4d289ca) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20401.3", 0x0800000, 0x0400000, CRC(99e98937) SHA1(e1b4d12a0b4d0fe97a62fcc085e19cce77657c99) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20402.4", 0x0c00000, 0x0400000, CRC(4572aa60) SHA1(8b2d76ea8c6e2f472c6ee7c9b6ad6e80e6a1a85a) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20403.5", 0x1000000, 0x0400000, CRC(26a8e13e) SHA1(07f5564b704598e3c3580d3d620ecc4f14549dbd) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20404.6", 0x1400000, 0x0400000, CRC(0b70275d) SHA1(47b8672e19c698dc948760f7091f4c6280e728d0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20399.1", 0x1800000, 0x0400000, CRC(c178a96e) SHA1(65f4aa05187d48ba8ad4fe75ff6ffe1f8524831d) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20405.8", 0x1c00000, 0x0400000, CRC(f53337b7) SHA1(09a21f81016ee54f10554ae1f790415d7436afe0) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20406.9", 0x2000000, 0x0400000, CRC(b677c175) SHA1(d0de7b5a29928036df0bdfced5a8021c0999eb26) ) /* good*/
- ROM_LOAD16_WORD_SWAP( "mpr20407.10", 0x2400000, 0x0400000, CRC(58356050) SHA1(f8fb5a14f4ec516093c785891b05d55ae345754e) ) /* good*/
+ ROM_REGION32_BE( 0x2800000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr20398.13", 0x0000001, 0x0100000, CRC(3fb56a0b) SHA1(13c2fa2d94b106d39e46f71d15fbce3607a5965a) ) /* good */
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20400.2", 0x0400000, 0x0400000, CRC(1edfbe05) SHA1(b0edd3f3d57408101ae6eb0aec742afbb4d289ca) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20401.3", 0x0800000, 0x0400000, CRC(99e98937) SHA1(e1b4d12a0b4d0fe97a62fcc085e19cce77657c99) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20402.4", 0x0c00000, 0x0400000, CRC(4572aa60) SHA1(8b2d76ea8c6e2f472c6ee7c9b6ad6e80e6a1a85a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20403.5", 0x1000000, 0x0400000, CRC(26a8e13e) SHA1(07f5564b704598e3c3580d3d620ecc4f14549dbd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20404.6", 0x1400000, 0x0400000, CRC(0b70275d) SHA1(47b8672e19c698dc948760f7091f4c6280e728d0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20399.1", 0x1800000, 0x0400000, CRC(c178a96e) SHA1(65f4aa05187d48ba8ad4fe75ff6ffe1f8524831d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20405.8", 0x1c00000, 0x0400000, CRC(f53337b7) SHA1(09a21f81016ee54f10554ae1f790415d7436afe0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20406.9", 0x2000000, 0x0400000, CRC(b677c175) SHA1(d0de7b5a29928036df0bdfced5a8021c0999eb26) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20407.10", 0x2400000, 0x0400000, CRC(58356050) SHA1(f8fb5a14f4ec516093c785891b05d55ae345754e) ) /* good */
+ROM_END
+
+ROM_START( znpwfvt )
+ STV_BIOS /* only runs with the Taiwan BIOS: the core selects it (stv_required_bios) */
+
+ ROM_REGION32_BE( 0x2800000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr20408.13", 0x0000001, 0x0100000, CRC(1d62fcf6) SHA1(3651261aa755da27b11462f2705311b7c639a687) ) /* good */
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20400.2", 0x0400000, 0x0400000, CRC(1edfbe05) SHA1(b0edd3f3d57408101ae6eb0aec742afbb4d289ca) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20401.3", 0x0800000, 0x0400000, CRC(99e98937) SHA1(e1b4d12a0b4d0fe97a62fcc085e19cce77657c99) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20402.4", 0x0c00000, 0x0400000, CRC(4572aa60) SHA1(8b2d76ea8c6e2f472c6ee7c9b6ad6e80e6a1a85a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20403.5", 0x1000000, 0x0400000, CRC(26a8e13e) SHA1(07f5564b704598e3c3580d3d620ecc4f14549dbd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20404.6", 0x1400000, 0x0400000, CRC(0b70275d) SHA1(47b8672e19c698dc948760f7091f4c6280e728d0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20399.1", 0x1800000, 0x0400000, CRC(c178a96e) SHA1(65f4aa05187d48ba8ad4fe75ff6ffe1f8524831d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20405.8", 0x1c00000, 0x0400000, CRC(f53337b7) SHA1(09a21f81016ee54f10554ae1f790415d7436afe0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20406.9", 0x2000000, 0x0400000, CRC(b677c175) SHA1(d0de7b5a29928036df0bdfced5a8021c0999eb26) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20407.10", 0x2400000, 0x0400000, CRC(58356050) SHA1(f8fb5a14f4ec516093c785891b05d55ae345754e) ) /* good */
+ROM_END
+
+/* English translation hack (bootleg): the Taiwan program, which shows the
+ English graphics of the game, with the graphics it left in Japanese
+ redrawn in English (the profiles of Hiroshi Hase and The Patriot, the VS
+ names, the DANGER body parts, the data / password panels) and the victory
+ newspapers carrying a translation of the Japanese lines. Taiwan BIOS. */
+ROM_START( znpwfve )
+ STV_BIOS /* only runs with the Taiwan BIOS: the core selects it (stv_required_bios) */
+
+ ROM_REGION32_BE( 0x2800000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr20408.13", 0x0000001, 0x0100000, CRC(1d62fcf6) SHA1(3651261aa755da27b11462f2705311b7c639a687) ) /* good */
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0100000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0100000 )
+ ROM_LOAD16_WORD_SWAP( "mpr20400.2", 0x0400000, 0x0400000, CRC(1edfbe05) SHA1(b0edd3f3d57408101ae6eb0aec742afbb4d289ca) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20401.3", 0x0800000, 0x0400000, CRC(99e98937) SHA1(e1b4d12a0b4d0fe97a62fcc085e19cce77657c99) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20402.4", 0x0c00000, 0x0400000, CRC(4572aa60) SHA1(8b2d76ea8c6e2f472c6ee7c9b6ad6e80e6a1a85a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20403.5", 0x1000000, 0x0400000, CRC(26a8e13e) SHA1(07f5564b704598e3c3580d3d620ecc4f14549dbd) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20404.6", 0x1400000, 0x0400000, CRC(0b70275d) SHA1(47b8672e19c698dc948760f7091f4c6280e728d0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20399.1", 0x1800000, 0x0400000, CRC(c178a96e) SHA1(65f4aa05187d48ba8ad4fe75ff6ffe1f8524831d) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr20405.8", 0x1c00000, 0x0400000, CRC(f53337b7) SHA1(09a21f81016ee54f10554ae1f790415d7436afe0) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "znpe20406.9", 0x2000000, 0x0400000, CRC(b73ccd2c) SHA1(75b6d5c568ed5baf594b186db782e7e9af55205b) ) /* English graphics */
+ ROM_LOAD16_WORD_SWAP( "znpe20407.10", 0x2400000, 0x0400000, CRC(d15eb928) SHA1(5217ec91daca0d9b5bc56a904ea09765567598d5) ) /* English graphics */
ROM_END
ROM_START( danchih )
STV_BIOS
- ROM_REGION32_BE( 0x1400000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD16_WORD_SWAP( "mpr21974.7", 0x0200000, 0x0200000, CRC(e7472793) SHA1(11b7b11cf492eb9cf69b50e7cfac46a5b86849ac) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21970.2", 0x0400000, 0x0400000, CRC(34dd7f4d) SHA1(d5c45da94ec5b6584049caf09516f1ad4ba3adb5) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21971.3", 0x0800000, 0x0400000, CRC(8995158c) SHA1(fbbd171d67eebf43630d6054bc1b9132f6b38183) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21972.4", 0x0c00000, 0x0400000, CRC(68a39090) SHA1(cff1b909c4191660570012eb5e4cb6a7467bc79e) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mpr21973.5", 0x1000000, 0x0400000, CRC(b0f23f14) SHA1(4e7076c29fd57bb3ef9af50a6104e39ecda94e06) )/* good*/
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "mpr21974.7", 0x0200000, 0x0200000, CRC(e7472793) SHA1(11b7b11cf492eb9cf69b50e7cfac46a5b86849ac) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21970.2", 0x0400000, 0x0400000, CRC(34dd7f4d) SHA1(d5c45da94ec5b6584049caf09516f1ad4ba3adb5) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21971.3", 0x0800000, 0x0400000, CRC(8995158c) SHA1(fbbd171d67eebf43630d6054bc1b9132f6b38183) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21972.4", 0x0c00000, 0x0400000, CRC(68a39090) SHA1(cff1b909c4191660570012eb5e4cb6a7467bc79e) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mpr21973.5", 0x1000000, 0x0400000, CRC(b0f23f14) SHA1(4e7076c29fd57bb3ef9af50a6104e39ecda94e06) )/* good */
ROM_END
ROM_START( mausuke )
STV_BIOS
- ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
- ROM_LOAD( "ic13.bin", 0x0000000, 0x0100000, CRC(b456f4cd) SHA1(91cbe703ec7c1dd45eb3b05bdfeb06e3570599d1) )
- /* mirroring is essential on this one */
- ROM_RELOAD ( 0x0100000, 0x0100000 )
- ROM_RELOAD ( 0x0200000, 0x0100000 )
- ROM_RELOAD ( 0x0300000, 0x0100000 )
+ ROM_REGION32_BE( 0x1e00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "ic13.bin", 0x0000001, 0x0100000, CRC(b456f4cd) SHA1(91cbe703ec7c1dd45eb3b05bdfeb06e3570599d1) )
+ ROM_RELOAD_PLAIN ( 0x0200000, 0x0100000 ) /* needs the rom mapped here to appear 'normal' */
+ ROM_RELOAD_PLAIN ( 0x0300000, 0x0100000 )
- ROM_LOAD16_WORD_SWAP( "mcj-00.2", 0x0400000, 0x0200000, CRC(4eeacd6f) SHA1(104ca230f22cd11cc536b34abd482e54791b4d0f) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mcj-01.3", 0x0800000, 0x0200000, CRC(365a494b) SHA1(29713dfc83a9ade63ebcc7994d14cd785c4500b9) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mcj-02.4", 0x0c00000, 0x0200000, CRC(8b8e4931) SHA1(0c94e2ccb72902d7786d1101a3958504f7151077) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mcj-03.5", 0x1000000, 0x0200000, CRC(9015a0e7) SHA1(8ba8a3723267e631169dc1e06620260fbccce4bd) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mcj-04.6", 0x1400000, 0x0200000, CRC(9d1beaee) SHA1(c63b61378860319fff2e605c7b9afaa5f1bc4cd2) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mcj-05.1", 0x1800000, 0x0200000, CRC(a7626a82) SHA1(c12a099132c5b9234a2de5674f3b8ba5fdd35289) )/* good*/
- ROM_LOAD16_WORD_SWAP( "mcj-06.8", 0x1c00000, 0x0200000, CRC(1ab8e90e) SHA1(8e22f03c1791a983eb330b2a9199e5349a0b1baa) )/* good*/
+ ROM_LOAD16_WORD_SWAP( "mcj-00.2", 0x0400000, 0x0200000, CRC(4eeacd6f) SHA1(104ca230f22cd11cc536b34abd482e54791b4d0f) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mcj-01.3", 0x0800000, 0x0200000, CRC(365a494b) SHA1(29713dfc83a9ade63ebcc7994d14cd785c4500b9) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mcj-02.4", 0x0c00000, 0x0200000, CRC(8b8e4931) SHA1(0c94e2ccb72902d7786d1101a3958504f7151077) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mcj-03.5", 0x1000000, 0x0200000, CRC(9015a0e7) SHA1(8ba8a3723267e631169dc1e06620260fbccce4bd) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mcj-04.6", 0x1400000, 0x0200000, CRC(9d1beaee) SHA1(c63b61378860319fff2e605c7b9afaa5f1bc4cd2) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mcj-05.1", 0x1800000, 0x0200000, CRC(a7626a82) SHA1(c12a099132c5b9234a2de5674f3b8ba5fdd35289) )/* good */
+ ROM_LOAD16_WORD_SWAP( "mcj-06.8", 0x1c00000, 0x0200000, CRC(1ab8e90e) SHA1(8e22f03c1791a983eb330b2a9199e5349a0b1baa) )/* good */
ROM_END
/* acclaim game, not a standard cart ... */
ROM_START( batmanfr )
STV_BIOS
- ROM_REGION32_BE( 0x3000000, REGION_USER1, 0 ) /* SH2 code */
- /* the batman forever rom test is more useless than most, i'm not really sure how
- the roms should map, it doesn't even appear to test enough roms nor the right sizes!
- everything fails for now
- range tested as
- 040 - 04f ic2
- 0c0 - 0ff ic4
- 180 - 1bf ic1
- 1c0 - 1ff ic8
- 200 - 20f ic9
- 2c0 - 2df ic12
- 000 - ? ic13
-
- */
+ ROM_REGION32_BE( 0x2000000, REGION_USER1, ROMREGION_ERASEFF )
+ /* Thanks to Runik to point this out*/
ROM_LOAD16_BYTE( "350-mpa1.u19", 0x0000000, 0x0100000, CRC(2a5a8c3a) SHA1(374ec55a39ea909cc672e4a629422681d1f2da05) )
+ ROM_RELOAD( 0x0200000, 0x0100000 )
ROM_LOAD16_BYTE( "350-mpa1.u16", 0x0000001, 0x0100000, CRC(735e23ab) SHA1(133e2284a07a611aed8ada2707248f392f4509aa) )
+ ROM_RELOAD( 0x0200001, 0x0100000 )
ROM_LOAD16_WORD_SWAP( "gfx0.u1", 0x0400000, 0x0400000, CRC(a82d0b7e) SHA1(37a7a177634d51620b1b43e58732987df166c7e6) )
- ROM_LOAD16_WORD_SWAP( "gfx1.u3", 0x0c00000, 0x0400000, CRC(a41e55d9) SHA1(b896d3a6c36d325c3cece699da54f340a4512703) )
- ROM_LOAD16_WORD_SWAP( "gfx2.u5", 0x1800000, 0x0400000, CRC(4c1ebeb7) SHA1(cdd139652d9484ae5837a39c2fd48d0a8d966d43) )
- ROM_LOAD16_WORD_SWAP( "gfx3.u8", 0x1c00000, 0x0400000, CRC(f679a3e7) SHA1(db11b033b8bbdd80b81e3bc098bd40ad3a8784f2) )
- ROM_LOAD16_WORD_SWAP( "gfx4.u12", 0x0800000, 0x0400000, CRC(52d95242) SHA1(b554a95933c2be4c72fb4226d3bc4775695da2c1) )
- ROM_LOAD16_WORD_SWAP( "gfx5.u15", 0x2000000, 0x0400000, CRC(e201f830) SHA1(5aa22fcc8f2e153d1abc3aa4050c594b3942ee67) )
- ROM_LOAD16_WORD_SWAP( "gfx6.u18", 0x2c00000, 0x0400000, CRC(c6b381a3) SHA1(46431f1e47c084a0bf85535d35af27471653b008) )
+ ROM_LOAD16_WORD_SWAP( "gfx1.u3", 0x0800000, 0x0400000, CRC(a41e55d9) SHA1(b896d3a6c36d325c3cece699da54f340a4512703) )
+ ROM_LOAD16_WORD_SWAP( "gfx2.u5", 0x0c00000, 0x0400000, CRC(4c1ebeb7) SHA1(cdd139652d9484ae5837a39c2fd48d0a8d966d43) )
+ ROM_LOAD16_WORD_SWAP( "gfx3.u8", 0x1000000, 0x0400000, CRC(f679a3e7) SHA1(db11b033b8bbdd80b81e3bc098bd40ad3a8784f2) )
+ ROM_LOAD16_WORD_SWAP( "gfx4.u12", 0x1400000, 0x0400000, CRC(52d95242) SHA1(b554a95933c2be4c72fb4226d3bc4775695da2c1) )
+ ROM_LOAD16_WORD_SWAP( "gfx5.u15", 0x1800000, 0x0400000, CRC(e201f830) SHA1(5aa22fcc8f2e153d1abc3aa4050c594b3942ee67) )
+ ROM_LOAD16_WORD_SWAP( "gfx6.u18", 0x1c00000, 0x0400000, CRC(c6b381a3) SHA1(46431f1e47c084a0bf85535d35af27471653b008) )
- /* it also has an extra adsp sound board, i guess this isn't tested */
- ROM_REGION( 0x080000, REGION_USER2, 0 ) /* ADSP code */
- ROM_LOAD( "350snda1.u52", 0x000000, 0x080000, CRC(9027e7a0) SHA1(678df530838b078964a044ce734776f391654e6c) )
-
- ROM_REGION( 0x800000, REGION_USER3, 0 ) /* Sound */
- ROM_LOAD( "snd0.u48", 0x000000, 0x200000, CRC(02b1927c) SHA1(08b21d8b31b0f15c59fb5bb7eaf425e6fe04f7b5) )
- ROM_LOAD( "snd1.u49", 0x200000, 0x200000, CRC(58b18eda) SHA1(7f3105fe04d9c0cdfd76e3323f623a4d0f7dad06) )
- ROM_LOAD( "snd2.u50", 0x400000, 0x200000, CRC(51d626d6) SHA1(0e68b79dcb653dcba48121ca2d4f692f90afa85e) )
- ROM_LOAD( "snd3.u51", 0x600000, 0x200000, CRC(31af26ae) SHA1(2c9f4c078afec55964b5c2a4d00f5c43f2661a04) )
+ /* the Acclaim RAX sound board (not emulated): its own region, not over the cart */
+ ROM_REGION( 0x1000000, REGION_USER4, 0 )
+ ROM_LOAD( "350snda1.u52", 0x000000, 0x080000, CRC(9027e7a0) SHA1(678df530838b078964a044ce734776f391654e6c) )
+ ROM_LOAD( "snd0.u48", 0x400000, 0x200000, CRC(02b1927c) SHA1(08b21d8b31b0f15c59fb5bb7eaf425e6fe04f7b5) )
+ ROM_LOAD( "snd1.u49", 0x600000, 0x200000, CRC(58b18eda) SHA1(7f3105fe04d9c0cdfd76e3323f623a4d0f7dad06) )
+ ROM_LOAD( "snd2.u50", 0x800000, 0x200000, CRC(51d626d6) SHA1(0e68b79dcb653dcba48121ca2d4f692f90afa85e) )
+ ROM_LOAD( "snd3.u51", 0xa00000, 0x200000, CRC(31af26ae) SHA1(2c9f4c078afec55964b5c2a4d00f5c43f2661a04) )
ROM_END
ROM_START( sfish2 )
@@ -4461,8 +4773,6 @@ ROM_START( sfish2 )
ROM_REGION( 0x080000, REGION_CPU2, 0 ) /* SH2 code */
ROM_COPY( REGION_CPU1,0,0,0x080000)
ROM_REGION( 0x100000, REGION_CPU3, 0 ) /* 68000 code */
- ROM_REGION( 0x100000, REGION_GFX1, 0 ) /* VDP2 GFX */
- ROM_REGION( 0x100000, REGION_GFX2, 0 ) /* VDP1 GFX */
ROM_REGION32_BE( 0x0f00000, REGION_USER1, 0 ) /* SH2 code */
ROM_LOAD( "epr18427.bin", 0x0000000, 0x0100000, CRC(3f25bec8) SHA1(43a5342b882d5aec0f35a8777cb475659f43b1c4) )
@@ -4497,8 +4807,6 @@ ROM_START( sfish2j )
ROM_REGION( 0x080000, REGION_CPU2, 0 ) /* SH2 code */
ROM_COPY( REGION_CPU1,0,0,0x080000)
ROM_REGION( 0x100000, REGION_CPU3, 0 ) /* 68000 code */
- ROM_REGION( 0x100000, REGION_GFX1, 0 ) /* VDP2 GFX */
- ROM_REGION( 0x100000, REGION_GFX2, 0 ) /* VDP1 GFX */
ROM_REGION32_BE( 0x2000000, REGION_USER1, 0 ) /* SH2 code */
ROM_LOAD( "epr18344.a", 0x0000000, 0x0100000, CRC(5a7de018) SHA1(88e0c2a9a9d4ebf699878c0aa9737af85f95ccf8) )
@@ -4529,6 +4837,206 @@ ROM_END
+/***************************************************************************
+ A-Bus protection: the 315-5881 decrypter/decompresser of the protected
+ carts, at the top of the cartridge space (0x04fffff0-0x04ffffff)
+***************************************************************************/
+
+static data32_t stv_abus[4];
+static data32_t stv_abus_protenable, stv_abus_protkey;
+
+static data32_t stv_cart_word32(offs_t byteoffs)
+{
+ if (byteoffs + 4 > memory_region_length(REGION_USER1))
+ return 0xffffffff;
+ return ((data32_t *)memory_region(REGION_USER1))[byteoffs / 4];
+}
+
+/* the cart ROM as 16-bit words, bytes swapped (as the decrypter sees them) */
+static UINT16 stv_crypt_read(UINT32 addr)
+{
+ data32_t w = stv_cart_word32((2 * addr) & ~3);
+ UINT16 dat = (addr & 1) ? (w & 0xffff) : (w >> 16);
+ return ((dat & 0xff00) >> 8) | ((dat & 0x00ff) << 8);
+}
+
+static READ32_HANDLER( stv_common_prot_r )
+{
+ if (stv_abus_protenable & 0x00010000) /* protection calculation active */
+ {
+ if (offset == 3)
+ {
+ UINT16 res = sega315_5881_do_decrypt();
+ UINT16 res2 = sega315_5881_do_decrypt();
+ res = ((res & 0xff00) >> 8) | ((res & 0x00ff) << 8);
+ res2 = ((res2 & 0xff00) >> 8) | ((res2 & 0x00ff) << 8);
+ return res2 | (res << 16);
+ }
+ return stv_abus[offset];
+ }
+ if (stv_abus[offset] != 0)
+ return stv_abus[offset];
+ return stv_cart_word32(0x02fffff0 + offset * 4);
+}
+
+static WRITE32_HANDLER( stv_common_prot_w )
+{
+ COMBINE_DATA(&stv_abus[offset]);
+
+ if (offset == 0)
+ COMBINE_DATA(&stv_abus_protenable);
+ else if (offset == 2)
+ {
+ if (!(mem_mask & 0xffff0000)) sega315_5881_set_addr_low(data >> 16);
+ if (!(mem_mask & 0x0000ffff)) sega315_5881_set_addr_high(data & 0xffff);
+ }
+ else if (offset == 3)
+ {
+ COMBINE_DATA(&stv_abus_protkey);
+ sega315_5881_set_subkey(stv_abus_protkey >> 16);
+ }
+}
+
+static void stv_install_common_protection(UINT32 key)
+{
+ install_mem_read32_handler(0, 0x04fffff0, 0x04ffffff, stv_common_prot_r);
+ install_mem_write32_handler(0, 0x04fffff0, 0x04ffffff, stv_common_prot_w);
+
+ memset(stv_abus, 0, sizeof(stv_abus));
+ stv_abus_protenable = stv_abus_protkey = 0;
+ sega315_5881_init(key, stv_crypt_read);
+ sega315_5881_reset();
+
+ state_save_register_UINT32("stv_abus", 0, "abus", stv_abus, 4);
+ state_save_register_UINT32("stv_abus", 0, "protenable", &stv_abus_protenable, 1);
+ state_save_register_UINT32("stv_abus", 0, "protkey", &stv_abus_protkey, 1);
+}
+
+/***************************************************************************
+ DecAthlete: the 315-5838 decrypter/decompresser of its graphics, as in
+ MAME (stv.cpp init_5838). The source and the tables are written at the
+ top of each 8MB bank of the cartridge, the decoded bytes are read there
+ when the control register selects the decoder.
+***************************************************************************/
+
+static UINT32 stv_5838_bank, stv_5838_source;
+static UINT16 stv_5838_control;
+
+/* the encrypted words, from the bank of the last write */
+static UINT16 stv_5838_source_r(UINT32 offset)
+{
+ UINT32 address = (stv_5838_bank << 23) | ((offset * 2) & 0x007fffff);
+ data32_t data = stv_cart_word32(address & ~3);
+ return (address & 2) ? (data & 0xffff) : (data >> 16);
+}
+
+static WRITE32_HANDLER( stv_5838_w )
+{
+ UINT32 address = offset * 4;
+
+ stv_5838_bank = (address >> 23) & 3;
+ switch (address & 0x007fffff)
+ {
+ case 0x007ffff0:
+ COMBINE_DATA(&stv_5838_source);
+ sega315_5838_source_w(stv_5838_source);
+ break;
+ case 0x007ffff4:
+ if (!(mem_mask & 0xffff0000))
+ sega315_5838_table_w(0, data >> 16);
+ if (!(mem_mask & 0x0000ffff))
+ sega315_5838_table_w(1, data & 0xffff);
+ break;
+ }
+}
+
+static WRITE32_HANDLER( stv_5838_control_w )
+{
+ /* the 16-bit register at 0x04200000 */
+ if (!(mem_mask & 0xffff0000))
+ stv_5838_control = data >> 16;
+}
+
+static data32_t stv_5838_read(int bank, data32_t mem_mask)
+{
+ data32_t result = 0;
+
+ if (!(stv_5838_control & 2)) /* the ROM */
+ return stv_cart_word32(bank * 0x00800000 + 0x007ffff8);
+
+ if (!(mem_mask & 0xffff0000))
+ result |= sega315_5838_data_r() << 16;
+ if (!(mem_mask & 0x0000ffff))
+ result |= sega315_5838_data_r();
+ return result;
+}
+
+static READ32_HANDLER( stv_5838_bank0_r ) { return stv_5838_read(0, mem_mask); }
+static READ32_HANDLER( stv_5838_bank1_r ) { return stv_5838_read(1, mem_mask); }
+static READ32_HANDLER( stv_5838_bank2_r ) { return stv_5838_read(2, mem_mask); }
+
+static DRIVER_INIT( decathlt )
+{
+ init_ic13();
+
+ install_mem_write32_handler(0, 0x02000000, 0x037fffff, stv_5838_w);
+ install_mem_read32_handler(0, 0x027ffff8, 0x027ffffb, stv_5838_bank0_r);
+ install_mem_read32_handler(0, 0x02fffff8, 0x02fffffb, stv_5838_bank1_r);
+ install_mem_read32_handler(0, 0x037ffff8, 0x037ffffb, stv_5838_bank2_r);
+ install_mem_write32_handler(0, 0x04200000, 0x04200003, stv_5838_control_w);
+
+ stv_5838_bank = stv_5838_source = 0;
+ stv_5838_control = 2; /* DecAthlete reads the decoder without writing the control */
+ sega315_5838_init(stv_5838_source_r);
+ sega315_5838_set_variant(SEGA315_5838_VARIANT_5838);
+ sega315_5838_reset();
+
+ state_save_register_UINT32("stv_5838", 0, "bank", &stv_5838_bank, 1);
+ state_save_register_UINT32("stv_5838", 0, "source", &stv_5838_source, 1);
+ state_save_register_UINT16("stv_5838", 0, "control", &stv_5838_control, 1);
+}
+
+/* the protected carts; the keys are MAME's */
+static DRIVER_INIT( rsgun ) { init_stv(); stv_install_common_protection(0x05272d01); }
+static DRIVER_INIT( ffreveng ) { init_stv(); stv_install_common_protection(0x0524ac01); }
+static DRIVER_INIT( elandore ) { init_stv(); stv_install_common_protection(0x05226d41); }
+static DRIVER_INIT( astrass ) { init_ic13(); stv_install_common_protection(0x052e2901); }
+static DRIVER_INIT( sss ) { init_ic13(); stv_install_common_protection(0x052b6901); }
+/* the data of the Korean version is bit-swapped and inverted */
+static DRIVER_INIT( sanjeon )
+{
+ UINT8 *src = memory_region(REGION_USER1);
+ int len = memory_region_length(REGION_USER1);
+ int x;
+
+ for (x = 0; x < len; x++)
+ {
+ UINT8 v = src[x] ^ 0xff;
+ v = BITSWAP8(v, 7,2,5,1, 3,6,4,0);
+ v = BITSWAP8(v, 4,6,5,7, 3,2,1,0);
+ v = BITSWAP8(v, 7,6,5,4, 2,3,1,0);
+ v = BITSWAP8(v, 7,0,5,4, 3,2,1,6);
+ v = BITSWAP8(v, 3,6,5,4, 7,2,1,0);
+ src[x] = v;
+ }
+
+ init_ic13();
+}
+
+static DRIVER_INIT( critcrsh )
+{
+ init_ic13();
+ stv_critcrsh = 1;
+}
+
+static DRIVER_INIT( stvmedal )
+{
+ init_ic13();
+ stv_hopper = 1;
+}
+
+static DRIVER_INIT( twcup98 ) { init_ic13(); stv_install_common_protection(0x05200913); }
+
DRIVER_INIT( sfish2 )
{
/* this is WRONG but works for some games */
@@ -4553,69 +5061,236 @@ DRIVER_INIT( sfish2j )
}
+ROM_START( critcrsh ) /* must use the Europe BIOS */
+ STV_BIOS
+
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr-18821.ic13", 0x0000001, 0x0080000, CRC(9a6658e2) SHA1(16dbae3d9ab584713afcb403f89fe71049609245) )
+ ROM_RELOAD ( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr-18789.ic8", 0x1c00000, 0x0400000, CRC(b388616f) SHA1(0b2c5a547c3a6a8fb9f4ca54336cf6dc9adb8c6a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr-18788.ic9", 0x2000000, 0x0400000, CRC(feae5867) SHA1(7d2e47d5ab18700a246d53fdb7872a905cdac55a) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "critcrsh.nv", 0x0000, 0x0080, CRC(3da9860e) SHA1(05b315aa71fcfc4e617266e1c5e4954eccbf7854) )
+ROM_END
+
+ROM_START( tatacot ) /* must use the Japan BIOS */
+ STV_BIOS
+
+ ROM_REGION32_BE( 0x2400000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "epr-18790.ic13", 0x0000001, 0x0080000, CRC(d95155dc) SHA1(b08b75d15aad073eecf8b04fd2d718366bb6f6bb) )
+ ROM_RELOAD ( 0x0100001, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0200000, 0x0080000 )
+ ROM_RELOAD_PLAIN( 0x0300000, 0x0080000 )
+ ROM_LOAD16_WORD_SWAP( "mpr-18789.ic8", 0x1c00000, 0x0400000, CRC(b388616f) SHA1(0b2c5a547c3a6a8fb9f4ca54336cf6dc9adb8c6a) ) /* good */
+ ROM_LOAD16_WORD_SWAP( "mpr-18788.ic9", 0x2000000, 0x0400000, CRC(feae5867) SHA1(7d2e47d5ab18700a246d53fdb7872a905cdac55a) ) /* good */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "critcrsh.nv", 0x0000, 0x0080, CRC(3da9860e) SHA1(05b315aa71fcfc4e617266e1c5e4954eccbf7854) )
+ROM_END
+
+ROM_START( danchiq )
+ STV_BIOS
+
+ ROM_REGION32_BE( 0x1600000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "ic22", 0x0200000, 0x0200000, CRC(e216bfc8) SHA1(7a08fa32281e272dbf5e7daea50a1800cc225c1b) )/*ic 7 */
+ ROM_LOAD16_WORD_SWAP( "ic24", 0x0400000, 0x0200000, CRC(b95aa5ac) SHA1(2766c5414643034a0f6d746050557516bd3753df) )/*ic 2 */
+ ROM_LOAD16_WORD_SWAP( "ic26", 0x0600000, 0x0200000, CRC(df6ebd48) SHA1(fcccafbee1b8b952b07ed0e7e86219eed9cf4a93) )
+ ROM_LOAD16_WORD_SWAP( "ic28", 0x0800000, 0x0200000, CRC(cf6a2b76) SHA1(1f7522d446d57b78d099bae553133d5e7e54ff70) )/*ic 3 */
+ ROM_LOAD16_WORD_SWAP( "ic30", 0x0a00000, 0x0200000, CRC(0b6a9901) SHA1(b4c335199d3e49a9ae5d474b10130abc4718cdf9) )
+ ROM_LOAD16_WORD_SWAP( "ic32", 0x0c00000, 0x0200000, CRC(0b4604f5) SHA1(547cba4a80baf126e87f87529aa933587643d359) )/*ic 4 */
+ ROM_LOAD16_WORD_SWAP( "ic34", 0x0e00000, 0x0200000, CRC(616e20fa) SHA1(45c175e79b5701db9726d157ff92eee368f4bbf9) )
+ ROM_LOAD16_WORD_SWAP( "ic36", 0x1000000, 0x0200000, CRC(43474e08) SHA1(30b3ede287d5de93c6e0219bfd0a5d7ed5b6a958) )/*ic 5 */
+ ROM_LOAD16_WORD_SWAP( "ic23", 0x1200000, 0x0200000, CRC(d080eb71) SHA1(9c39b887697c8872f0cb655cff24282ad3b90e9b) )
+ ROM_LOAD16_WORD_SWAP( "ic25", 0x1400000, 0x0200000, CRC(9a4109e5) SHA1(ba59caac5f5a80fc52c507d8a47f322a380aa9a1) )/*(Untested) */
+ROM_END
+
+ROM_START( micrombc ) /* set to 1p */
+ STV_BIOS
+
+ ROM_REGION32_BE( 0x1400000, REGION_USER1, ROMREGION_ERASEFF )
+
+ ROM_LOAD16_WORD_SWAP( "ic22", 0x0200000, 0x0200000, CRC(8385bc45) SHA1(0bd60d7560cb2313d68470d0572850a7b8c501fd) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic24", 0x0400000, 0x0200000, CRC(84ecb42f) SHA1(005dee9a0912d4b1b7f5157bc3cde96548c1e348) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic26", 0x0600000, 0x0200000, CRC(869bc19c) SHA1(638125007d331beef567c976ea6f4e7a21acdb64) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic28", 0x0800000, 0x0200000, CRC(0c3db354) SHA1(c4d43da7cea1b4d5ca3ac545afde10344a4a385b) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic30", 0x0a00000, 0x0200000, CRC(03b9eacf) SHA1(d69c10f7613d9f52042dd6cce64e74e2b1ecc2d8) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic32", 0x0c00000, 0x0200000, CRC(62c10626) SHA1(58cb0ca0330fa7a62b277ab0ff84bff65b81bb23) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic34", 0x1000000, 0x0200000, CRC(8d89877e) SHA1(7d76d48d64d7ac5411d714a4bb83f37e3e5b8df6) ) /* 00 Fill. OK */
+ ROM_LOAD16_WORD_SWAP( "ic36", 0x1200000, 0x0200000, CRC(8d89877e) SHA1(7d76d48d64d7ac5411d714a4bb83f37e3e5b8df6) ) /* 00 Fill, OK */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "micrombc.nv", 0x0000, 0x0080, CRC(6e89815f) SHA1(4478f614fb61859f4ee7bf55462f737387887e6f) )
+ROM_END
+
+ROM_START( patocar )
+ STV_BIOS
+
+ ROM_REGION32_BE( 0xc00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "ic22.bin", 0x0200000, 0x200000, CRC(b7e6d425) SHA1(b7496cb390fe50ee786815082415427056e4e3e1) )
+ ROM_LOAD16_WORD_SWAP( "ic24.bin", 0x0400000, 0x200000, CRC(cbbb687e) SHA1(cfc87ae6124f9978bb2432b98d77f0da07d020b7) )
+ ROM_LOAD16_WORD_SWAP( "ic26.bin", 0x0600000, 0x200000, CRC(91db9dbe) SHA1(8652fe45ce56633016403c75e8b3a7b77f279819) )
+ ROM_LOAD16_WORD_SWAP( "ic28.bin", 0x0800000, 0x200000, CRC(bff0cd9c) SHA1(3c62aa2d7f71bd6fb147fdcd8d99cd7815f3047e) )
+ ROM_LOAD16_WORD_SWAP( "ic30.bin", 0x0a00000, 0x200000, CRC(9a4109e5) SHA1(ba59caac5f5a80fc52c507d8a47f322a380aa9a1) ) /* empty / FF filled */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "patocar.nv", 0x0000, 0x0080, CRC(d9873ee8) SHA1(e74747816bba6745afd718b0beec67a884c6a31c) )
+ROM_END
+
+ROM_START( skychal )
+ STV_BIOS
+
+ ROM_REGION32_BE( 0xe00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "ic22.bin", 0x0200000, 0x200000, CRC(a12ccf64) SHA1(eb3ff0cdc10fa17e40af5bddedfa5f758c7a5623) )
+ ROM_LOAD16_WORD_SWAP( "ic24.bin", 0x0400000, 0x200000, CRC(9a929dcf) SHA1(892e491fa33cc30cbbd24feb4ea6a63f9a9e1a62) )
+ ROM_LOAD16_WORD_SWAP( "ic26.bin", 0x0600000, 0x200000, CRC(ed2183d3) SHA1(7c43171a57e070a295c191408bd1b8ffee053d9b) )
+ ROM_LOAD16_WORD_SWAP( "ic28.bin", 0x0800000, 0x200000, CRC(e7401d68) SHA1(02f77439075b6367b46dc9ef7f67023b32a68526) )
+ ROM_LOAD16_WORD_SWAP( "ic30.bin", 0x0a00000, 0x200000, CRC(950f7a2f) SHA1(1b4fd7b08eeb2fdf2cdfae7f8aa3240e8dce3b9a) )
+ ROM_LOAD16_WORD_SWAP( "ic32.bin", 0x0c00000, 0x200000, CRC(a656212b) SHA1(b2bf325cb4cf67787c836a9ac1bb7231068ffd82) )
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "skychal.nv", 0x0000, 0x0080, CRC(a6515237) SHA1(5e50cc93eb60ed67cdca408b23b80d16a398df02) )
+ROM_END
+
+ROM_START( supgoal )
+ STV_BIOS
+
+ ROM_REGION32_BE( 0xc00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "ic22.bin", 0x0200000, 0x200000, CRC(a686f7a2) SHA1(f4f9b63046d184864cfffe6ef8268a33b73298da) )
+ ROM_LOAD16_WORD_SWAP( "ic24.bin", 0x0400000, 0x200000, CRC(56fbbeea) SHA1(2c622ccc20aed0df7c611a00986ce76b84c61d70) )
+ ROM_LOAD16_WORD_SWAP( "ic26.bin", 0x0600000, 0x200000, CRC(64701c2b) SHA1(e9a426ce1882660d533b963899a8b1b6f41f85d4) )
+ ROM_LOAD16_WORD_SWAP( "ic28.bin", 0x0800000, 0x200000, CRC(d9aebe8c) SHA1(cd19cf1227d151a015c4dc3aed14bc3b2f78ce07) )
+ ROM_LOAD16_WORD_SWAP( "ic30.bin", 0x0a00000, 0x200000, CRC(26d4ade5) SHA1(6b958aa4db293c7af88a735323d19f6417d86048) )
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "supgoal.nv", 0x0000, 0x0080, CRC(63806aae) SHA1(b82f0995799e9259a1f071ea8b64a719f9e3c9e9) )
+ROM_END
+
+ROM_START( techbowl ) /* set to 1p */
+ STV_BIOS
+
+ ROM_REGION32_BE( 0xc00000, REGION_USER1, ROMREGION_ERASEFF )
+
+ ROM_LOAD16_WORD_SWAP( "ic22", 0x0200000, 0x0200000, CRC(5058db21) SHA1(eec908bbfb9ec0fdca0002e69f32c1c030086456) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic24", 0x0400000, 0x0200000, CRC(34090f6d) SHA1(b8bc344ab826d5c9584afb01dba1c720b8dbc74d) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic26", 0x0600000, 0x0200000, CRC(fb073352) SHA1(a5164aa5854ab3095f704ab73b6e4fb9ed0e0785) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic28", 0x0800000, 0x0200000, CRC(530e0ceb) SHA1(8d14eb9dbf253a4563587d256a15492384e7ca5c) ) /* OK */
+ ROM_LOAD16_WORD_SWAP( "ic30", 0x0a00000, 0x0200000, CRC(8d89877e) SHA1(7d76d48d64d7ac5411d714a4bb83f37e3e5b8df6) ) /* 00 Fill, OK */
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "techbowl.nv", 0x0000, 0x0080, CRC(5bebc2b7) SHA1(e189e891e1753059fbaad4ce82ddf191d5e8176a) )
+ROM_END
+
+ROM_START( wasafari )
+ STV_BIOS
+
+ ROM_REGION32_BE( 0xc00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "ic22.bin", 0x0200000, 0x200000, CRC(d8bb2e2c) SHA1(e55714425f8dcf01e8cb68d67c96f19a9d6f4e3a) )
+ ROM_LOAD16_WORD_SWAP( "ic24.bin", 0x0400000, 0x200000, CRC(c1b0e173) SHA1(92e5fe1f9fa70182c5bf8f087686782714cf4416) )
+ ROM_LOAD16_WORD_SWAP( "ic26.bin", 0x0600000, 0x200000, CRC(a5c0577c) SHA1(b6e19001e67c8222af6802eae7b58be65d8ca9fd) )
+ ROM_LOAD16_WORD_SWAP( "ic28.bin", 0x0800000, 0x200000, CRC(2a8cfa97) SHA1(a38ab55e88413e0df3f32f23c2a9dcccca4483be) )
+ ROM_LOAD16_WORD_SWAP( "ic30.bin", 0x0a00000, 0x200000, CRC(9a4109e5) SHA1(ba59caac5f5a80fc52c507d8a47f322a380aa9a1) )
+
+ ROM_REGION( 0x80, REGION_USER3, 0 ) /* preconfigured to 1 player */
+ ROM_LOAD( "wasafari.nv", 0x0000, 0x0080, CRC(50861c5a) SHA1(c431703d7b56185f20af1aec04cabb5f49e2d4ba) )
+ROM_END
+
+ROM_START( sanjeon )
+ STV_BIOS
+
+ ROM_REGION32_BE( 0x1c00000, REGION_USER1, ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "ic11", 0x0000001, 0x0200000, CRC(9abae8d4) SHA1(ddbe4c8fff8fa59d63e278e95f245145d2da8aeb) )
+
+ ROM_LOAD( "ic13", 0x0400000, 0x0200000, CRC(f72c1d13) SHA1(a2b168d187034024b83fbbe2f5eec78816285da9) ) /* ic2 good */
+ ROM_LOAD( "ic14", 0x0600000, 0x0200000, CRC(bcd72105) SHA1(fb88a1f2589fef5d9845027646259ec8e781771b) ) /* ic2 good */
+ ROM_LOAD( "ic15", 0x0800000, 0x0200000, CRC(8c9c8352) SHA1(312e9e6435c6e9a4a19b72e234b087d4f5b069a5) ) /* ic3 good */
+ ROM_LOAD( "ic16", 0x0a00000, 0x0200000, CRC(07e11512) SHA1(5fb5e93a167aae501bd799aba98f7dbc3762a795) ) /* ic3 good */
+ ROM_LOAD( "ic17", 0x0c00000, 0x0200000, CRC(46b7b344) SHA1(a325b724e6346f585582bb2581d3063b1c8ddee9) ) /* ic4 good */
+ ROM_LOAD( "ic18", 0x0e00000, 0x0200000, CRC(d48404e1) SHA1(e4927d17cb19f6825f41b41056b89de224cf97de) ) /* ic4 good */
+ ROM_LOAD( "ic19", 0x1000000, 0x0200000, CRC(33d23bb9) SHA1(0179438a0b14ad7eb553a24d86fae778671fcc49) ) /* ic5 good */
+ ROM_LOAD( "ic20", 0x1200000, 0x0200000, CRC(f8cc1038) SHA1(06bcb25eb5df77bd503b0692a96ec66c00976fe9) ) /* ic5 good */
+ ROM_LOAD( "ic21", 0x1400000, 0x0200000, CRC(74ceb649) SHA1(91b7eb699b7167f890528149178644a74ef3ad17) ) /* ic6 good */
+ ROM_LOAD( "ic22", 0x1600000, 0x0200000, CRC(85f31277) SHA1(277c28d44cabd9081a8151d6ec27d47b5606435a) ) /* ic6 good */
+ ROM_LOAD( "ic12", 0x1800000, 0x0400000, CRC(d5ebc84e) SHA1(f990b793cdfadbbac69c680191660f4a2f282ba2) ) /* ic1 good */
+ROM_END
+
/* TODO: add country codes */
/*GBX YEAR, NAME, PARENT, BIOS, MACH,INP, INIT, MONITOR*/
/* Playable */
GAMEBX( 1998, hanagumi, stvbios, stvbios, stv, stv, hanagumi, ROT0, "Sega", "Hanagumi Taisen Columns - Sakura Wars", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND, &generic_ctrl, NULL )
-GAMEBX( 1996, bakubaku, stvbios, stvbios, stv, stv, bakubaku, ROT0, "Sega", "Baku Baku Animal", GAME_NO_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1996, bakubaku, stvbios, stvbios, stv, stv, bakubaku, ROT0, "Sega", "Baku Baku Animal", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1997, shienryu, stvbios, stvbios, stv, stv, shienryu, ROT270, "Warashi", "Shienryu", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND, &generic_ctrl, NULL )
GAMEBX( 1995, mausuke, stvbios, stvbios, stv, stv, mausuke, ROT0, "Data East","Mausuke no Ojama the World", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1996, puyosun, stvbios, stvbios, stv, stv, puyosun, ROT0, "Compile", "Puyo Puyo Sun", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1997, cotton2, stvbios, stvbios, stv, stv, cotton2, ROT0, "Success", "Cotton 2", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1998, cottonbm, stvbios, stvbios, stv, stv, cottonbm, ROT0, "Success", "Cotton Boomerang", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
-GAMEBX( 1996, vfkids, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Virtua Fighter Kids", GAME_NO_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1996, vfkids, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Virtua Fighter Kids", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1995, ejihon, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Ejihon Tantei Jimusyo", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1996, colmns97, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Columns 97", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
-GAMEBX( 1996, dnmtdeka, diehard, stvbios, stv, stv, dnmtdeka, ROT0, "Sega", "Dynamite Deka (Japan)", GAME_NO_SOUND | GAME_IMPERFECT_GRAPHICS , &generic_ctrl, NULL )
+GAMEBX( 1996, dnmtdeka, diehard, stvbios, stv, stv, dnmtdeka, ROT0, "Sega", "Dynamite Deka (Japan)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1996, prikura, stvbios, stvbios, stv, stv, prikura, ROT0, "Atlus", "Princess Clara Daisakusen", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
-GAMEBX( 1997, winterht, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Winter Heat", GAME_NO_SOUND | GAME_IMPERFECT_GRAPHICS , &generic_ctrl, NULL )
+GAMEBX( 1997, winterht, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Winter Heat", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
/* Almost */
-GAMEBX( 1995, fhboxers, stvbios, stvbios, stv, stv, fhboxers, ROT0, "Sega", "Funky Head Boxers", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1998, othellos, stvbios, stvbios, stv, stv, stv, ROT0, "Success", "Othello Shiyouyo", GAME_NO_SOUND, &generic_ctrl, NULL )
-GAMEBX( 1995, kiwames, stvbios, stvbios, stv, stvmp,ic13, ROT0, "Athena", "Pro Mahjong Kiwame S", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1995, fhboxers, stvbios, stvbios, stv, stv, fhboxers, ROT0, "Sega", "Funky Head Boxers", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, othellos, stvbios, stvbios, stv, stv, stv, ROT0, "Success", "Othello Shiyouyo", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1995, kiwames, stvbios, stvbios, stv, stvmp,ic13, ROT0, "Athena", "Pro Mahjong Kiwame S", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
/* Doing Something.. but not enough yet */
GAMEBX( 1995, shanhigw, stvbios, stvbios, stv, stv, stv, ROT0, "Sunsoft / Activision", "Shanghai - The Great Wall - Shanghai Triple Threat", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
-GAMEBX( 1996, groovef, stvbios, stvbios, stv, stv, stv, ROT0, "Atlus", "Power Instinct 3 - Groove On Fight", GAME_IMPERFECT_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1999, danchih, stvbios, stvbios, stv, stvmp,stv, ROT0, "Altron (Tecmo license)", "Danchi de Hanafuda", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1996, groovef, stvbios, stvbios, stv, stv, stv, ROT0, "Atlus", "Power Instinct 3 - Groove On Fight", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1999, danchih, stvbios, stvbios, stv, stvmp,stv, ROT0, "Altron (Tecmo license)", "Danchi de Hanafuda", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1996, diehard, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Die Hard Arcade (US)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1998, grdforce, stvbios, stvbios, stv, stv, stv, ROT0, "Success", "Guardian Force", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND, &generic_ctrl, NULL )
-GAMEBX( 1998, elandore, stvbios, stvbios, stv, stv, stv, ROT0, "Sai-Mate", "Fighting Dragon Legend Elan Doree", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1998, myfairld, stvbios, stvbios, stv, stvmp,stv, ROT0, "Micronet", "Virtual Mahjong 2 - My Fair Lady", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1998, rsgun, stvbios, stvbios, stv, stv, stv, ROT0, "Treasure", "Radiant Silvergun", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1996, sassisu, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Taisen Tanto-R Sashissu!!", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1995, sleague, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Super Major League (US)", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1995, finlarch, sleague, stvbios, stv, stv, ic13, ROT0, "Sega", "Final Arch (Japan)", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1998, elandore, stvbios, stvbios, stv, stv, elandore, ROT0, "Sai-Mate", "Fighting Dragon Legend Elan Doree", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, myfairld, stvbios, stvbios, stv, stvmp,stv, ROT0, "Micronet", "Virtual Mahjong 2 - My Fair Lady", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, rsgun, stvbios, stvbios, stv, stv, rsgun, ROT0, "Treasure", "Radiant Silvergun", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, sasissu, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Taisen Tanto-R Sashissu!!", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1999, sanjeon, sasissu, stvbios, stv, stv, sanjeon, ROT0, "Sega / Deniam", "DaeJeon! SanJeon SuJeon", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1995, critcrsh, stvbios, stvbios, stv, critcrsh, critcrsh, ROT0, "Sega", "Critter Crusher", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1995, tatacot, critcrsh, stvbios, stv, critcrsh, critcrsh, ROT0, "Sega", "Tatacot (Japan)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 2000, danchiq, stvbios, stvbios, stv, stv, ic13, ROT0, "Altron", "Danchi de Quiz: Okusan Yontaku Desuyo!", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1999, micrombc, stvbios, stvbios, stv, stvmedal, stvmedal, ROT0, "Sega", "Microman Battle Charge", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 2001, patocar, stvbios, stvbios, stv, stvmedal, stvmedal, ROT0, "Sega", "Hashire Patrol Car", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 2000, skychal, stvbios, stvbios, stv, stvmedal, stvmedal, ROT0, "Sega", "Sky Challenger", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, supgoal, stvbios, stvbios, stv, stvmedal, stvmedal, ROT0, "Sega", "Nerae! Super Goal", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1997, techbowl, stvbios, stvbios, stv, stvmedal, stvmedal, ROT0, "Sega", "Technical Bowling", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, wasafari, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Wanpaku Safari", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1995, smleague, stvbios, stvbios, stv, stv, smleague, ROT0, "Sega", "Super Major League (US)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1995, finlarch, smleague, stvbios, stv, stv, smleague, ROT0, "Sega", "Final Arch (Japan)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
/* crashes*/
-GAMEBX( 1995, suikoenb, stvbios, stvbios, stv, stv, ic13, ROT0, "Data East", "Suikoenbu", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1995, suikoenb, stvbios, stvbios, stv, stv, ic13, ROT0, "Data East", "Suikoenbu", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
/* this needs the dsp*/
-GAMEBX( 1995, vfremix, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Virtua Fighter Remix", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1995, vfremix, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Virtua Fighter Remix", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
/* not working */
GAMEBX( 1996, stvbios, 0, stvbios, stv, stv, stv, ROT0, "Sega", "ST-V Bios", NOT_A_DRIVER, &generic_ctrl, NULL )
-GAMEBX( 1998, astrass, stvbios, stvbios, stv, stv, ic13, ROT0, "Sunsoft", "Astra SuperStars", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1996, batmanfr, stvbios, stvbios, stv, stv, ic13, ROT0, "Acclaim", "Batman Forever", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1995, decathlt, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Decathlete", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1999, ffreveng, stvbios, stvbios, stv, stv, stv, ROT0, "Capcom", "Final Fight Revenge", GAME_UNEMULATED_PROTECTION | GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1996, findlove, stvbios, stvbios, stv, stv, ic13, ROT0, "Daiki", "Find Love", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1994, gaxeduel, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Golden Axe - The Duel", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1996, introdon, stvbios, stvbios, stv, stv, ic13, ROT0, "Sunsoft / Success", "Karaoke Quiz Intro Don Don!", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1997, maruchan, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Maru-Chan de Goo!", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1995, pblbeach, stvbios, stvbios, stv, stv, ic13, ROT0, "TandE Soft", "Pebble Beach - The Great Shot", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1998, astrass, stvbios, stvbios, stv, stv, astrass, ROT0, "Sunsoft", "Astra SuperStars", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1996, batmanfr, stvbios, stvbios, stv, stv, ic13, ROT0, "Acclaim", "Batman Forever", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1996, decathlt, stvbios, stvbios, stv, stv, decathlt, ROT0, "Sega", "Decathlete", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1999, ffreveng, stvbios, stvbios, stv, stv, ffreveng, ROT0, "Capcom", "Final Fight Revenge", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1996, findlove, stvbios, stvbios, stv, stv, ic13, ROT0, "Daiki", "Find Love", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1994, gaxeduel, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Golden Axe - The Duel", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1996, introdon, stvbios, stvbios, stv, stv, ic13, ROT0, "Sunsoft / Success", "Karaoke Quiz Intro Don Don!", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1997, maruchan, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Maru-Chan de Goo!", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1995, pblbeach, stvbios, stvbios, stv, stv, ic13, ROT0, "TandE Soft", "Pebble Beach - The Great Shot", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
GAMEBX( 1995, sandor, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Sando-R", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
GAMEBX( 1995, thunt, sandor, stvbios, stv, stv, ic13, ROT0, "Sega", "Treasure Hunt", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL ) /* this one actually does something if you use the sandor gfx*/
-GAMEBX( 1998, seabass, stvbios, stvbios, stv, stv, ic13, ROT0, "A Wave inc. (Able license)", "Sea Bass Fishing", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1996, sokyugrt, stvbios, stvbios, stv, stv, ic13, ROT0, "Raizing", "Soukyugurentai - Terra Diver", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1998, sss, stvbios, stvbios, stv, stv, ic13, ROT0, "Victor / Cave / Capcom", "Steep Slope Sliders", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1998, twcup98, stvbios, stvbios, stv, stv, ic13, ROT0, "Tecmo", "Tecmo World Cup '98", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL ) /* protected?*/
-GAMEBX( 1997, vmahjong, stvbios, stvbios, stv, stvmp,stv, ROT0, "Micronet", "Virtual Mahjong", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
-GAMEBX( 1997, znpwfv, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Zen Nippon Pro-Wrestling Featuring Virtua", GAME_NO_SOUND | GAME_NOT_WORKING, &generic_ctrl, NULL )
+GAMEBX( 1998, seabass, stvbios, stvbios, stv, stv, ic13, ROT0, "A Wave inc. (Able license)", "Sea Bass Fishing", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1996, sokyugrt, stvbios, stvbios, stv, stv, ic13, ROT0, "Raizing", "Soukyugurentai - Terra Diver", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, sss, stvbios, stvbios, stv, stv, sss, ROT0, "Victor / Cave / Capcom", "Steep Slope Sliders", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1998, twcup98, stvbios, stvbios, stv, stv, twcup98, ROT0, "Tecmo", "Tecmo World Cup '98", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL ) /* protected?*/
+GAMEBX( 1997, vmahjong, stvbios, stvbios, stv, stvmp,stv, ROT0, "Micronet", "Virtual Mahjong", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1997, znpwfv, stvbios, stvbios, stv, stv, ic13, ROT0, "Sega", "Zen Nippon Pro-Wrestling Featuring Virtua", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1997, znpwfvt, znpwfv, stvbios, stv, stv, ic13, ROT0, "Sega", "All Japan Pro-Wrestling Featuring Virtua (Taiwan)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
+GAMEBX( 1997, znpwfve, znpwfv, stvbios, stv, stv, ic13, ROT0, "bootleg", "All Japan Pro-Wrestling Featuring Virtua (English translation)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS, &generic_ctrl, NULL )
/* there are probably a bunch of other games (some fishing games with cd-rom,Print Club 2 etc.) */
diff --git a/src/drivers/stvhacks.c b/src/drivers/stvhacks.c
index bd40d9e8..a375eeed 100644
--- a/src/drivers/stvhacks.c
+++ b/src/drivers/stvhacks.c
@@ -9,58 +9,34 @@ to be honest i think some of these cause more problems than they're worth ...
extern data32_t *stv_workram_h;
DRIVER_INIT ( stv );
-/* Hack the boot vectors .. not right but allows several IC13 games (which fail the checksums before hacking) to boot */
+/* the IC13 carts: their program ROM is now loaded as MAME loads it (odd
+ bytes, mirrored), so they need no boot vector patch */
DRIVER_INIT( ic13 )
{
- /* this is WRONG but works for some games */
- data32_t *rom = (data32_t *)memory_region(REGION_USER1);
- rom[0xf10/4] = (rom[0xf10/4] & 0xff000000)|((rom[0xf10/4]/2)&0x00ffffff);
- rom[0xf20/4] = (rom[0xf20/4] & 0xff000000)|((rom[0xf20/4]/2)&0x00ffffff);
- rom[0xf30/4] = (rom[0xf30/4] & 0xff000000)|((rom[0xf30/4]/2)&0x00ffffff);
-
init_stv();
}
/*
-
-06013AE8: MOV.L @($D4,PC),R5
-06013AEA: MOV.L @($D8,PC),R0
-06013AEC: MOV.W @R5,R5
-06013AEE: MOV.L @R0,R0
-06013AF0: AND R10,R5
-06013AF2: TST R0,R0
-06013AF4: BTS $06013B00
-06013AF6: EXTS.W R5,R5
-06013B00: EXTS.W R5,R5
-06013B02: TST R5,R5
-06013B04: BF $06013B0A
-06013B06: TST R4,R4
-06013B08: BT $06013AE8
-
- (loops for 375868 instructions)
-
+Super Major League / Final Arch: each frame the master queues a job for the slave
+(the depth sort of the polygons), waits for the slave to take it (the read pointer
+at 060ffc44) and then clears the "sort done" flag that the slave sets when the job
+is over. The slave is much slower than the master on the real hardware, but in
+coarse time slices it can take the job and finish it before the master looks at the
+pointer again, so the flag is lost and the game hangs. A tight interleave while the
+master polls keeps the order of the real hardware.
*/
-
-
-READ32_HANDLER( stv_speedup_r )
+static READ32_HANDLER( smleague_sync_r )
{
- if (activecpu_get_pc()==0x60154b4) cpu_spinuntil_int(); /* bios menus..*/
-
- return stv_workram_h[0x0335d0/4];
+ /* a slice of 16 SH-2 cycles is enough (a perfect one costs half the speed);
+ with 64 cycles Super Major League and Final Arch hang again */
+ cpu_boost_interleave(TIME_IN_HZ(57272720/32), TIME_IN_USEC(20));
+ return stv_workram_h[0x0ffc44/4];
}
-READ32_HANDLER( stv_speedup2_r )
+DRIVER_INIT( smleague )
{
- if (activecpu_get_pc()==0x6013af0) cpu_spinuntil_int(); /* for use in japan*/
-
- return stv_workram_h[0x0335bc/4];
-}
-
-void install_stvbios_speedups(void)
-{
-/* idle skip bios? .. not 100% sure this is safe .. we'll see */
- install_mem_read32_handler(0, 0x60335d0, 0x60335d3, stv_speedup_r );
- install_mem_read32_handler(0, 0x60335bc, 0x60335bf, stv_speedup2_r );
+ install_mem_read32_handler(0, 0x060ffc44, 0x060ffc47, smleague_sync_r);
+ init_stv();
}
static READ32_HANDLER( shienryu_slave_speedup_r )
diff --git a/src/includes/stv.h b/src/includes/stv.h
new file mode 100644
index 00000000..5006cac4
--- /dev/null
+++ b/src/includes/stv.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+
+ Sega ST-V: interface between the driver and the video (VDP1, VDP2)
+
+***************************************************************************/
+
+#ifndef STV_H
+#define STV_H
+
+/* vidhrdw/stvvid.c */
+extern UINT16 *vdp2_regs;
+extern UINT32 *vdp2_vram;
+extern UINT32 *vdp2_cram;
+extern UINT32 *vdp1_vram;
+extern UINT16 *vdp1_regs;
+
+READ32_HANDLER( stv_vdp1_regs_r );
+WRITE32_HANDLER( stv_vdp1_regs_w );
+READ32_HANDLER( stv_vdp1_vram_r );
+WRITE32_HANDLER( stv_vdp1_vram_w );
+READ32_HANDLER( stv_vdp1_framebuffer0_r );
+WRITE32_HANDLER( stv_vdp1_framebuffer0_w );
+READ32_HANDLER( stv_vdp2_vram_r );
+WRITE32_HANDLER( stv_vdp2_vram_w );
+READ32_HANDLER( stv_vdp2_cram_r );
+WRITE32_HANDLER( stv_vdp2_cram_w );
+READ32_HANDLER( stv_vdp2_regs_r );
+WRITE32_HANDLER( stv_vdp2_regs_w );
+
+VIDEO_START( stv_vdp2 );
+VIDEO_STOP( stv_vdp2 );
+VIDEO_UPDATE( stv_vdp2 );
+
+/* frame timing, from the driver's scanline interrupt */
+int stv_vdp2_vblank_start_line(void); /* the line vblank-in happens on */
+void stv_vdp2_scanline(int line); /* the start of each line, 0 to 262 */
+void stv_vdp1_video_update(void); /* at vblank-in: frame change, automatic draw */
+void stv_vdp1_vblank_erase(void); /* one line after vblank-in */
+
+#endif
diff --git a/src/machine/scudsp.c b/src/machine/scudsp.c
index 02fd1dfc..4b98f067 100644
--- a/src/machine/scudsp.c
+++ b/src/machine/scudsp.c
@@ -1,5 +1,6 @@
#include "driver.h"
#include "machine/scudsp.h"
+#include "cpu/sh2/sh2.h"
/*SCU DSP functions */
/*V0.03*/
@@ -75,10 +76,13 @@ extern data32_t* stv_scu;
static UINT32 opcode;
static UINT8 update_mul = 0;
-#define DEBUG_DSP
+/* writes dsp.log in the current directory, for debugging only */
+/*#define DEBUG_DSP*/
+#ifdef DEBUG_DSP
static char dasm_buffer[100];
static FILE *log_file = NULL;
+#endif
void dsp_dasm_opcode( UINT32 op, char *buffer );
@@ -270,8 +274,8 @@ void dsp_prg_ctrl(UINT32 data)
{
if(LEF) dsp_reg.pc = (data & 0xff);
if(EXF) dsp_execute_program();
- if(EF && (!(stv_scu[40] & 0x0020)))
- cpu_set_irq_line_and_vector(0, 0xa, HOLD_LINE , 0x45);
+ if(EF)
+ stv_scu_raise_irq(5); /* DSP end */
}
void dsp_prg_data(UINT32 data)
@@ -630,6 +634,8 @@ static void dsp_dma( void )
for ( counter = 0; counter < transfer_cnt; counter++ )
{
cpu_writemem32bedw_dword( dest, cpu_readmem32bew_word( dsp_get_mem_source_dma( dsp_mem, counter ) ) );
+ if ( sh2_jit_code_present )
+ sh2_jit_ram_written( dest, 4 );
dest += add;
}
@@ -698,6 +704,7 @@ static void dsp_loop( void )
}
}
+#ifdef DEBUG_DSP
static void dsp_dump_mem( FILE *f )
{
UINT16 i;
@@ -724,12 +731,15 @@ static void dsp_dump_mem( FILE *f )
}
fprintf( f, "}\n" );
}
+#endif
void dsp_execute_program()
{
UINT32 cycles_run = 0;
UINT8 cont = 1;
+#ifdef DEBUG_DSP
UINT16 i;
+#endif
#ifdef DEBUG_DSP
if ( log_file == NULL )
@@ -758,7 +768,9 @@ void dsp_execute_program()
dsp_reg.pc++;
}
+#ifdef DEBUG_DSP
dsp_dasm_opcode( opcode, dasm_buffer );
+#endif
switch( (opcode & 0xc0000000) >> 30 )
{
diff --git a/src/machine/scudsp.h b/src/machine/scudsp.h
index b31b2b55..09d00d01 100644
--- a/src/machine/scudsp.h
+++ b/src/machine/scudsp.h
@@ -6,3 +6,6 @@ extern void dsp_ram_addr_ctrl(UINT32 data);
extern void dsp_ram_addr_w(UINT32 data);
extern UINT32 dsp_ram_addr_r(void);
extern void dsp_execute_program(void);
+
+/* raise an SCU interrupt source (bit of the status register), drivers/stv.c */
+extern void stv_scu_raise_irq(int bit);
diff --git a/src/machine/sega315_5838.c b/src/machine/sega315_5838.c
index 25a381d4..df03abab 100644
--- a/src/machine/sega315_5838.c
+++ b/src/machine/sega315_5838.c
@@ -1,11 +1,12 @@
/***************************************************************************
Sega 315-5838 / 317-0229 compression and encryption
- (Dead or Alive startup string on Model 2)
+ (DecAthlete graphics on ST-V, Dead or Alive startup string on Model 2)
Translated to C from current MAME (sega/315-5838_317-0229_comp.cpp,
- license BSD-3-Clause), 317-0229 variant only: a fixed word substitution
- followed by a programmable prefix decompression.
+ license BSD-3-Clause): a fixed word substitution followed by a
+ programmable prefix decompression. The four variants differ only in the
+ substitution (routing, tables and affine masks).
***************************************************************************/
@@ -16,6 +17,7 @@
#define BITN(x,n) (((x)>>(n))&1)
static UINT16 (*comp_source_r)(UINT32 offset);
+static int comp_variant = SEGA315_5838_VARIANT_0229;
static UINT16 m_tree[ 24 ];
static UINT8 m_dictionary[ 256 ];
static int m_tree_words, m_dictionary_bytes, m_upload_dictionary;
@@ -25,14 +27,27 @@ static int m_bits, m_abort;
static UINT16 decipher( UINT16 c )
{
- /* 317-0229 */
- static const UINT8 routing[ 4 ] = { 3, 2, 0, 1 };
- static const UINT8 sboxes[ 4 ][ 8 ] =
+ /* routing, substitution tables and affine masks of 315-5838, 317-0229, 317-0230, 317-0231 */
+ static const UINT8 all_routing[ 4 ][ 4 ] = { { 0, 1, 2, 3 }, { 3, 2, 0, 1 }, { 2, 3, 1, 0 }, { 1, 0, 3, 2 } };
+ static const UINT8 all_sboxes[ 4 ][ 4 ][ 8 ] =
{
- { 6, 0, 5, 4, 7, 2, 1, 3 }, { 5, 6, 1, 3, 7, 0, 4, 2 },
- { 2, 6, 0, 1, 3, 4, 7, 5 }, { 6, 5, 7, 4, 1, 3, 0, 2 }
+ { { 6, 7, 2, 0, 5, 1, 3, 4 }, { 5, 3, 7, 2, 1, 6, 4, 0 },
+ { 2, 0, 6, 1, 3, 7, 4, 5 }, { 6, 5, 7, 4, 1, 3, 0, 2 } },
+ { { 6, 0, 5, 4, 7, 2, 1, 3 }, { 5, 6, 1, 3, 7, 0, 4, 2 },
+ { 2, 6, 0, 1, 3, 4, 7, 5 }, { 6, 5, 7, 4, 1, 3, 0, 2 } },
+ { { 6, 2, 7, 0, 5, 3, 1, 4 }, { 5, 3, 7, 2, 1, 6, 4, 0 },
+ { 2, 1, 3, 5, 6, 0, 4, 7 }, { 6, 1, 3, 5, 7, 0, 2, 4 } },
+ { { 6, 0, 5, 4, 7, 2, 1, 3 }, { 5, 1, 6, 3, 7, 4, 0, 2 },
+ { 2, 1, 3, 5, 6, 0, 4, 7 }, { 6, 3, 1, 5, 7, 2, 0, 4 } }
};
- static const UINT8 affine_masks[ 4 ] = { 0x12, 0x11, 0x04, 0x1a };
+ static const UINT8 all_affine[ 4 ][ 4 ] =
+ {
+ { 0x14, 0x18, 0x02, 0x15 }, { 0x12, 0x11, 0x04, 0x1a },
+ { 0x14, 0x18, 0x02, 0x15 }, { 0x12, 0x11, 0x04, 0x1a }
+ };
+ const UINT8 *routing = all_routing[ comp_variant ];
+ const UINT8 (*sboxes)[ 8 ] = all_sboxes[ comp_variant ];
+ const UINT8 *affine_masks = all_affine[ comp_variant ];
static const UINT8 output_bits[ 4 ][ 3 ] = { { 0, 1, 7 }, { 2, 5, 9 }, { 4, 10, 13 }, { 6, 11, 15 } };
static const UINT8 affine_bits[ 4 ] = { 3, 8, 12, 14 };
UINT8 lanes[ 4 ];
@@ -62,9 +77,15 @@ static UINT16 decipher( UINT16 c )
return result;
}
+void sega315_5838_set_variant( int variant )
+{
+ comp_variant = variant & 3;
+}
+
void sega315_5838_init( UINT16 (*source_r)( UINT32 offset ) )
{
comp_source_r = source_r;
+ comp_variant = SEGA315_5838_VARIANT_0229;
state_save_register_UINT16( "315_5838", 0, "tree", m_tree, 24 );
state_save_register_UINT8( "315_5838", 0, "dictionary", m_dictionary, 256 );
state_save_register_int( "315_5838", 0, "tree_words", &m_tree_words );
diff --git a/src/machine/sega315_5838.h b/src/machine/sega315_5838.h
index df850413..1a006839 100644
--- a/src/machine/sega315_5838.h
+++ b/src/machine/sega315_5838.h
@@ -1,7 +1,12 @@
#ifndef SEGA315_5838_H
#define SEGA315_5838_H
-/* Sega 315-5838 / 317-0229 compression and encryption (317-0229 variant) */
+/* Sega 315-5838 / 317-0229 compression and encryption */
+#define SEGA315_5838_VARIANT_5838 0 /* DecAthlete */
+#define SEGA315_5838_VARIANT_0229 1 /* Dead or Alive (the default) */
+#define SEGA315_5838_VARIANT_0230 2
+#define SEGA315_5838_VARIANT_0231 3
+void sega315_5838_set_variant( int variant ); /* after init */
void sega315_5838_init( UINT16 (*source_r)( UINT32 offset ) );
void sega315_5838_reset( void );
void sega315_5838_source_w( UINT32 data );
diff --git a/src/machine/sega315_5881.c b/src/machine/sega315_5881.c
index 41e2a7db..57510275 100644
--- a/src/machine/sega315_5881.c
+++ b/src/machine/sega315_5881.c
@@ -876,6 +876,31 @@ static UINT16 do_decrypt( void )
return ( base[ 0 ] << 8 ) | base[ 1 ];
}
+void sega315_5881_set_addr_low( UINT16 data )
+{
+ prot_cur_address = ( prot_cur_address & 0xffff0000 ) | data;
+ enc_ready = 0;
+}
+
+void sega315_5881_set_addr_high( UINT16 data )
+{
+ prot_cur_address = ( prot_cur_address & 0x0000ffff ) | ( (UINT32)data << 16 );
+ enc_ready = 0;
+ buffer_bit = 7;
+ buffer_bit2 = 15;
+}
+
+void sega315_5881_set_subkey( UINT16 data )
+{
+ subkey = data;
+ enc_ready = 0;
+}
+
+UINT16 sega315_5881_do_decrypt( void )
+{
+ return do_decrypt();
+}
+
/* little endian read: the decrypted word with its bytes swapped */
UINT16 sega315_5881_decrypt_r( void )
{
diff --git a/src/machine/sega315_5881.h b/src/machine/sega315_5881.h
index 82e3a5ef..e12252ba 100644
--- a/src/machine/sega315_5881.h
+++ b/src/machine/sega315_5881.h
@@ -10,4 +10,11 @@ void sega315_5881_addrhi_w( UINT16 data );
void sega315_5881_subkey_w( UINT16 data );
UINT16 sega315_5881_decrypt_r( void );
+/* ST-V A-Bus interface: the address and sub-key as the cart latches them,
+ and the decrypted stream word by word (big endian) */
+void sega315_5881_set_addr_low( UINT16 data );
+void sega315_5881_set_addr_high( UINT16 data );
+void sega315_5881_set_subkey( UINT16 data );
+UINT16 sega315_5881_do_decrypt( void );
+
#endif
diff --git a/src/mame.h b/src/mame.h
index 0d30b2af..21788cb1 100644
--- a/src/mame.h
+++ b/src/mame.h
@@ -154,7 +154,6 @@ enum /* used to index content-specific flags */
{
CONTENT_NEOGEO = 0,
CONTENT_STV,
- CONTENT_DIEHARD,
CONTENT_ALT_SOUND,
CONTENT_VECTOR,
CONTENT_DIAL,
@@ -182,6 +181,8 @@ enum /* used to index content-specific flags */
CONTENT_SH3_DYNAREC,
CONTENT_TX1_SCREENS,
CONTENT_CPU_COUNT,
+ CONTENT_SH2_DYNAREC,
+ CONTENT_STV_VIDEO_THREADS,
CONTENT_end,
};
@@ -227,6 +228,8 @@ struct GameOptions
bool adsp_dynarec; /* 1 to let drivers enable the ADSP-2100 recompiler */
bool sh3_dynarec; /* 1 to let drivers enable the SH-3 recompiler */
int tx1_screens; /* TX-1 / Buggy Boy: 3 screens side by side, or 1 (the middle one) */
+ bool sh2_dynarec; /* 1 to let drivers enable the SH-2 recompiler */
+ int stv_video_threads; /* ST-V: threads drawing the VDP2 screen in bands (0 or 1 = the main thread only) */
bool use_alt_sound; /* 1 to enable alternate ost samples */
float brightness; /* brightness of the display */
diff --git a/src/mame2003/core_options.c b/src/mame2003/core_options.c
index 0188dc0c..8bb01bb6 100644
--- a/src/mame2003/core_options.c
+++ b/src/mame2003/core_options.c
@@ -342,6 +342,25 @@ static struct retro_core_option_v2_definition option_def_neogeo_bios = {
"default"
};
+/* ST-V games that check the BIOS region and only run with one (as MAME's
+ default BIOS for them) */
+static const char *stv_required_bios(const char *name)
+{
+ static const char *const games[][2] = {
+ { "diehard", "us" },
+ { "smleague", "us" },
+ { "znpwfvt", "taiwan" },
+ { "znpwfve", "taiwan" },
+ { "critcrsh", "europe" },
+ { "tatacot", "japan" },
+ };
+ size_t i;
+ for (i = 0; i < sizeof(games) / sizeof(games[0]); i++)
+ if (strcmp(name, games[i][0]) == 0)
+ return games[i][1];
+ return NULL;
+}
+
static struct retro_core_option_v2_definition option_def_stv_bios = {
APPNAME"_stv_bios",
"Specify Sega ST-V BIOS",
@@ -781,6 +800,38 @@ static struct retro_core_option_v2_definition option_def_mips_dynarec = {
"enabled"
};
+static struct retro_core_option_v2_definition option_def_sh2_dynarec = {
+ APPNAME"_sh2_dynarec",
+ "SH-2 Dynarec",
+ NULL,
+ "Restart core required. Recompile the SH-2 code (offered only for the games that support it, on x86 and ARM hosts, 32 and 64-bit, that allow it); turn it off to use the interpreter.",
+ NULL,
+ NULL,
+ {
+ { "enabled", NULL },
+ { "disabled", NULL },
+ { NULL, NULL },
+ },
+ "disabled"
+};
+
+static struct retro_core_option_v2_definition option_def_stv_video_threads = {
+ APPNAME"_stv_video_threads",
+ "ST-V Threaded Video",
+ NULL,
+ "Draw the ST-V screen in horizontal bands on several threads (same picture, faster on multi-core hosts).",
+ NULL,
+ NULL,
+ {
+ { "disabled", NULL },
+ { "2", NULL },
+ { "3", NULL },
+ { "4", NULL },
+ { NULL, NULL },
+ },
+ "disabled"
+};
+
static struct retro_core_option_v2_definition option_def_adsp_dynarec = {
APPNAME"_adsp_dynarec",
"ADSP Dynarec",
@@ -972,6 +1023,8 @@ void init_core_options(void)
default_options[OPT_ADSP_DYNAREC] = option_def_adsp_dynarec;
default_options[OPT_SH3_DYNAREC] = option_def_sh3_dynarec;
default_options[OPT_TX1_SCREENS] = option_def_tx1_screens;
+ default_options[OPT_SH2_DYNAREC] = option_def_sh2_dynarec;
+ default_options[OPT_STV_VIDEO_THREADS] = option_def_stv_video_threads;
default_options[OPT_OVERRIDE_AD_STICK] = option_def_override_ad_stick;
default_options[OPT_INPUT_TOGGLE] = option_def_input_toggle;
#if (HAS_CYCLONE || HAS_DRZ80)
@@ -1030,6 +1083,14 @@ static void set_variables(void)
if(!options.content_flags[CONTENT_SH3_DYNAREC])
continue; /* only offered for the games that use the recompiler */
break;
+ case OPT_SH2_DYNAREC:
+ if(!options.content_flags[CONTENT_SH2_DYNAREC])
+ continue; /* only offered for the games that use the recompiler */
+ break;
+ case OPT_STV_VIDEO_THREADS:
+ if(!options.content_flags[CONTENT_STV_VIDEO_THREADS])
+ continue; /* ST-V only, where threads are compiled in */
+ break;
case OPT_NEOGEO_BIOS:
if(!options.content_flags[CONTENT_NEOGEO])
continue; /* only offer BIOS selection when it is relevant */
@@ -1203,8 +1264,8 @@ void update_variables(bool first_time)
case OPT_STV_BIOS:
if(!options.content_flags[CONTENT_STV])
break;
- if(options.content_flags[CONTENT_DIEHARD]) /* catch required bios for this one game. */
- options.bios = "us";
+ if(stv_required_bios(game_driver->name)) /* a game that only runs with one region's BIOS */
+ options.bios = stv_required_bios(game_driver->name);
else
options.bios = (strcmp(var.value, "default") == 0) ? NULL : var.value;
break;
@@ -1345,6 +1406,17 @@ void update_variables(bool first_time)
options.mips_dynarec = false;
break;
+ case OPT_SH2_DYNAREC:
+ if(strcmp(var.value, "enabled") == 0)
+ options.sh2_dynarec = true;
+ else
+ options.sh2_dynarec = false;
+ break;
+
+ case OPT_STV_VIDEO_THREADS:
+ options.stv_video_threads = atoi(var.value); /* 0 for "disabled" */
+ break;
+
case OPT_ADSP_DYNAREC:
if(strcmp(var.value, "enabled") == 0)
options.adsp_dynarec = true;
@@ -1566,6 +1638,23 @@ void set_content_flags(void)
&& strcmp(game_driver->name, "buggyboyjr") != 0)
options.content_flags[CONTENT_TX1_SCREENS] = true;
+ /************ SEGA ST-V: SH-2 RECOMPILER ************/
+ /* the option means nothing where the recompiler is compiled out */
+#if (HAS_SH2)
+ {
+ extern int sh2_jit_available(void);
+ if (game_driver->source_file && strstr(game_driver->source_file, "stv.c") && sh2_jit_available())
+ options.content_flags[CONTENT_SH2_DYNAREC] = true;
+ }
+#endif
+#if (HAS_SH2)
+ {
+ extern int stv_video_threads_available(void);
+ if (game_driver->source_file && strstr(game_driver->source_file, "stv.c") && stv_video_threads_available())
+ options.content_flags[CONTENT_STV_VIDEO_THREADS] = true;
+ }
+#endif
+
/************ DRIVERS WITH MULTIPLE BIOS OPTIONS ************/
#ifndef SPLIT_CORE
{
@@ -1594,10 +1683,6 @@ void set_content_flags(void)
options.content_flags[CONTENT_MIPS_DYNAREC] = true;
#endif
- /************ DIE HARD: ARCADE ************/
- if(strcasecmp(game_driver->name, "diehard") == 0)
- options.content_flags[CONTENT_DIEHARD] = true;
-
/************ DRIVERS WITH VECTOR VIDEO DISPLAYS ************/
if(Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
options.content_flags[CONTENT_VECTOR] = true;
@@ -1766,7 +1851,8 @@ void set_content_flags(void)
if(options.content_flags[CONTENT_NEOGEO]) log_cb(RETRO_LOG_INFO, LOGPRE "* Neo Geo BIOS required.\n");
if(options.content_flags[CONTENT_STV]) log_cb(RETRO_LOG_INFO, LOGPRE "* STV BIOS required.\n");
- if(options.content_flags[CONTENT_DIEHARD]) log_cb(RETRO_LOG_INFO, LOGPRE "* Die Hard: Arcade BIOS required.\n");
+ if(options.content_flags[CONTENT_STV] && stv_required_bios(game_driver->name))
+ log_cb(RETRO_LOG_INFO, LOGPRE "* ST-V BIOS forced: %s.\n", stv_required_bios(game_driver->name));
if(options.content_flags[CONTENT_ALT_SOUND]) log_cb(RETRO_LOG_INFO, LOGPRE "* Alternative soundtrack available.\n");
if(options.content_flags[CONTENT_VECTOR]) log_cb(RETRO_LOG_INFO, LOGPRE "* Vector display.\n");
diff --git a/src/mame2003/mame2003.h b/src/mame2003/mame2003.h
index b9750905..570e8508 100644
--- a/src/mame2003/mame2003.h
+++ b/src/mame2003/mame2003.h
@@ -247,6 +247,8 @@ enum CORE_OPTIONS /* controls the order in which core options appear. common, i
OPT_ADSP_DYNAREC,
OPT_SH3_DYNAREC,
OPT_TX1_SCREENS,
+ OPT_SH2_DYNAREC,
+ OPT_STV_VIDEO_THREADS,
#if (HAS_CYCLONE || HAS_DRZ80)
OPT_CYCLONE_MODE,
#endif
diff --git a/src/sound/scsp.c b/src/sound/scsp.c
index 2bf87339..09fff2b8 100644
--- a/src/sound/scsp.c
+++ b/src/sound/scsp.c
@@ -163,6 +163,9 @@ struct _SLOT
} udata;
data8_t active; /*this slot is currently playing*/
data8_t *base; /*samples base address*/
+ data8_t *ram; /*the sound RAM, the samples wrap in it*/
+ data32_t ram_mask;
+ data32_t sa; /*samples start, in the RAM*/
data32_t cur_addr; /*current play address (24.8)*/
data32_t step; /*pitch step (24.8)*/
struct _EG EG; /*Envelope*/
@@ -207,6 +210,7 @@ struct _SCSP
struct _SCSPDSP DSP;
int MvolSet; /* MVOL written: the output follows it */
unsigned char *SCSPRAM;
+ data32_t SCSPRAM_mask;
char Master;
void (*Int68kCB)(int irq);
int stream;
@@ -374,6 +378,9 @@ static void SCSP_StartSlot(struct _SLOT *slot)
{
slot->active=1;
slot->base=SCSP->SCSPRAM+SA(slot);
+ slot->ram=SCSP->SCSPRAM;
+ slot->ram_mask=SCSP->SCSPRAM_mask;
+ slot->sa=SA(slot);
slot->cur_addr=0;
slot->step=SCSP_Step(slot);
Compute_EG(slot);
@@ -402,7 +409,7 @@ static void SCSP_Init(int n, struct SCSPinterface *intf)
for (i = 0; i < n; i++)
{
SCSP = &SCSPs[i];
- memset(SCSP,0,sizeof(SCSP));
+ memset(SCSP,0,sizeof(*SCSP));
if (!i)
{
@@ -414,6 +421,7 @@ static void SCSP_Init(int n, struct SCSPinterface *intf)
}
SCSPs[i].SCSPRAM = memory_region(intf->region[i]);
+ SCSPs[i].SCSPRAM_mask = memory_region_length(intf->region[i]) - 1;
SCSPDSP_Init(&SCSPs[i].DSP, (UINT16 *)SCSPs[i].SCSPRAM, memory_region_length(intf->region[i]));
SCSPs[i].MvolSet=0;
}
@@ -700,10 +708,14 @@ static void SCSP_w16(unsigned int addr,unsigned short val)
}
else if(addr<0x600)
{
- *((unsigned short *) (SCSP->udata.datab+((addr&0xff)))) = val;
- if (Machine->sample_rate > 0)
+ /* the common registers end at 0x42f (writing past them would hit the slots) */
+ if((addr&0xff)udata.datab))
{
- SCSP_UpdateReg(addr&0xff);
+ *((unsigned short *) (SCSP->udata.datab+((addr&0xff)))) = val;
+ if (Machine->sample_rate > 0)
+ {
+ SCSP_UpdateReg(addr&0xff);
+ }
}
}
else if(addr>=0x700 && addr<0xc00)
@@ -739,11 +751,14 @@ static unsigned short SCSP_r16(unsigned int addr)
}
else if(addr<0x600)
{
- if (Machine->sample_rate > 0)
+ if((addr&0xff)udata.datab))
{
- SCSP_UpdateRegR(addr&0xff);
+ if (Machine->sample_rate > 0)
+ {
+ SCSP_UpdateRegR(addr&0xff);
+ }
+ v= *((unsigned short *) (SCSP->udata.datab+((addr&0xff))));
}
- v= *((unsigned short *) (SCSP->udata.datab+((addr&0xff))));
}
else if(addr>=0x700)
{
@@ -836,18 +851,18 @@ SCSPNAME(_8bit,lfo,alfo,loop)\
}\
if(_8bit)\
{\
- signed char *p=(signed char *) (slot->base+(slot->cur_addr>>SHIFT));\
+ /* the address wraps in the sound RAM (garbage slots must not read past it) */\
+ data32_t o=(slot->sa+(slot->cur_addr>>SHIFT))&slot->ram_mask;\
int s2;\
signed int fpart;\
fpart=slot->cur_addr&((1<ram[o]*((1<ram[(o+1)&slot->ram_mask]*fpart;\
sample=(s2>>SHIFT)<<8;\
}\
else\
{\
- signed short *p=(signed short *) (slot->base+((slot->cur_addr>>(SHIFT-1))&(~1)));\
- signed int fpart;\
- fpart=slot->cur_addr&((1<sa+((slot->cur_addr>>(SHIFT-1))&(~1)))&slot->ram_mask&(~1);\
+ signed short *p=(signed short *) (slot->ram+o);\
sample=p[0];\
}\
slot->cur_addr+=step;\
@@ -1032,7 +1047,7 @@ static void SCSP_DoMasterSamples(int chip, int nsamples)
static void dma_scsp()
{
- static UINT16 tmp_dma[2], *scsp_regs;
+ static UINT16 tmp_dma[3], *scsp_regs;
scsp_regs = (UINT16 *)SCSP->udata.datab;
@@ -1049,11 +1064,13 @@ static void dma_scsp()
tmp_dma[2] = scsp_regs[0x416/2];
}
+ /* the sound RAM and the registers directly: the CPU that started it may be
+ any of them (an SH-2 through the SCU), not the sound CPU */
if(scsp_ddir)
{
for(;scsp_dtlg > 0;scsp_dtlg-=2)
{
- cpu_writemem24bedw_word(scsp_dmea, cpu_readmem24bedw_word(0x100000|scsp_drga));
+ *(UINT16 *)(SCSP->SCSPRAM + (scsp_dmea & SCSP->SCSPRAM_mask & ~1)) = SCSP_r16(scsp_drga & 0xffe);
scsp_dmea+=2;
scsp_drga+=2;
}
@@ -1062,7 +1079,7 @@ static void dma_scsp()
{
for(;scsp_dtlg > 0;scsp_dtlg-=2)
{
- cpu_writemem24bedw_word(0x100000|scsp_drga,cpu_readmem24bedw_word(scsp_dmea));
+ SCSP_w16(scsp_drga & 0xffe, *(UINT16 *)(SCSP->SCSPRAM + (scsp_dmea & SCSP->SCSPRAM_mask & ~1)));
scsp_dmea+=2;
scsp_drga+=2;
}
@@ -1148,6 +1165,10 @@ static void SCSP_postload(void)
{
struct _SLOT *slot = &SCSPs[i].Slots[s];
slot->base = SCSPs[i].SCSPRAM ? SCSPs[i].SCSPRAM + SCSP_ss_base[i][s] : NULL;
+ /* the sample fetch wraps in the sound RAM: rebuild its pointers too */
+ slot->ram = SCSPs[i].SCSPRAM;
+ slot->ram_mask = SCSPs[i].SCSPRAM_mask;
+ slot->sa = SCSP_ss_base[i][s];
slot->PLFO.table = SCSP_lfo_table(SCSP_ss_lfo[i][s][0], 0);
slot->PLFO.scale = PSCALES[SCSP_ss_lfo[i][s][1] & 7];
slot->ALFO.table = SCSP_lfo_table(SCSP_ss_lfo[i][s][2], 1);
diff --git a/src/vidhrdw/stvvdp1_vidhrdw.c b/src/vidhrdw/stvvdp1_vidhrdw.c
deleted file mode 100644
index 01f92087..00000000
--- a/src/vidhrdw/stvvdp1_vidhrdw.c
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*
-
-STV - VDP1
-
-crude drawing code to support some of the basic vdp1 features
-based on what hanagumi columns needs
--- to be expanded
-
-the vdp1 draws to the FRAMEBUFFER which is mapped in memory
-
-*/
-
-
-#include "driver.h"
-
-data32_t *stv_vdp1_vram;
-data32_t *stv_vdp1_regs;
-extern data32_t *stv_scu;
-char shienryu_sprite_kludge;
-/*
-Registers:
-00
-02
-04
-06
-08 EWLR
-0a EWRR
-0c
-0e
-10 EDSR
-12
-*/
-/*Erase/Write Upper-Left register*/
-/*
-15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
- 0|X1 register |Y1 register |
-*/
-#define STV_VDP1_EWLR ((stv_vdp1_regs[0x008/4] >> 16)&0x0000ffff)
-#define STV_VDP1_EWLR_X1 ((STV_VDP1_EWLR & 0x7e00) >> 9)
-#define STV_VDP1_EWLR_Y1 ((STV_VDP1_EWLR & 0x01ff) >> 0)
-/*Erase/Write Lower-Right register*/
-/*
-15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
-X1 register |Y1 register |
-*/
-#define STV_VDP1_EWRR ((stv_vdp1_regs[0x008/4] >> 16)&0x0000ffff)
-#define STV_VDP1_EWRR_X3 ((STV_VDP1_EWLR & 0xfe00) >> 9)
-#define STV_VDP1_EWRR_Y3 ((STV_VDP1_EWLR & 0x01ff) >> 0)
-/*Transfer End Status Register*/
-/*
-15|14|13|12|11|10|09|08|07|06|05|04|03|02| 01| 00|
-0 |CEF|BEF|
-*/
-#define STV_VDP1_EDSR ((stv_vdp1_regs[0x010/4] >> 16)&0x0000ffff)
-#define STV_VDP1_CEF (STV_VDP1_EDSR & 2)
-#define STV_VDP1_BEF (STV_VDP1_EDSR & 1)
-#define SET_CEF_FROM_1_TO_0 if(STV_VDP1_CEF) stv_vdp1_regs[0x010/4]^=0x00020000
-#define SET_CEF_FROM_0_TO_1 if(!(STV_VDP1_CEF)) stv_vdp1_regs[0x010/4]^=0x00020000
-/**/
-
-#include "machine/random.h"
-
-READ32_HANDLER( stv_vdp1_regs_r )
-{
-/* static int x;*/
-
-/* x ^= 0x00020000;*/
-
- logerror ("cpu #%d (PC=%08X) VDP1: Read from Registers, Offset %04x\n",cpu_getactivecpu(), activecpu_get_pc(), offset);
-/* if (offset == 0x04) return x;*/
-
- return stv_vdp1_regs[offset];
-}
-
-
-int stv_vdp1_start ( void )
-{
- stv_vdp1_regs = auto_malloc ( 0x040000 );
- stv_vdp1_vram = auto_malloc ( 0x100000 );
-
- memset(stv_vdp1_regs, 0, 0x040000);
- memset(stv_vdp1_vram, 0, 0x100000);
-
- /* our colour calculation is broken .. must fix it */
- shienryu_sprite_kludge = 0;
- if (!strcmp(Machine->gamedrv->name,"shienryu")) shienryu_sprite_kludge = 1;
-
- return 0;
-}
-
-WRITE32_HANDLER( stv_vdp1_regs_w )
-{
- COMBINE_DATA(&stv_vdp1_regs[offset]);
-}
-
-READ32_HANDLER ( stv_vdp1_vram_r )
-{
- return stv_vdp1_vram[offset];
-}
-
-
-WRITE32_HANDLER ( stv_vdp1_vram_w )
-{
- data8_t *vdp1 = memory_region(REGION_GFX2);
-
- COMBINE_DATA (&stv_vdp1_vram[offset]);
-
-/* if (((offset * 4) > 0xdf) && ((offset * 4) < 0x140))*/
-/* {*/
-/* log_cb(RETRO_LOG_DEBUG, LOGPRE "cpu #%d (PC=%08X): VRAM dword write to %08X = %08X & %08X\n", cpu_getactivecpu(), activecpu_get_pc(), offset*4, data, mem_mask ^ 0xffffffff);*/
-/* }*/
-
- data = stv_vdp1_vram[offset];
- /* put in gfx region for easy decoding */
- vdp1[offset*4+0] = (data & 0xff000000) >> 24;
- vdp1[offset*4+1] = (data & 0x00ff0000) >> 16;
- vdp1[offset*4+2] = (data & 0x0000ff00) >> 8;
- vdp1[offset*4+3] = (data & 0x000000ff) >> 0;
-}
-
-/*
-
-there is a command every 0x20 bytes
-the first word is the control word
-the rest are data used by it
-
----
-00 CMDCTRL
- e--- ---- ---- ---- | end bit (15)
- -jjj ---- ---- ---- | jump select bits (12-14)
- ---- zzzz ---- ---- | zoom point / hotspot (8-11)
- ---- ---- 00-- ---- | UNUSED
- ---- ---- --dd ---- | character read direction (4,5)
- ---- ---- ---- cccc | command bits (0-3)
-
-02 CMDLINK
- llll llll llll ll-- | link
- ---- ---- ---- --00 | UNUSED
-
-04 CMDPMOD
- m--- ---- ---- ---- | MON (looks at MSB and apply shadows etc.)
- -00- ---- ---- ---- | UNUSED
- ---h ---- ---- ---- | HSS (High Speed Shrink)
- ---- p--- ---- ---- | PCLIP (Pre Clipping Disable)
- ---- -c-- ---- ---- | CLIP (Clipping Mode Bit)
- ---- --m- ---- ---- | CMOD (User Clipping Enable Bit)
- ---- ---M ---- ---- | MESH (Mesh Enable Bit)
- ---- ---- e--- ---- | ECD (End Code Disable)
- ---- ---- -S-- ---- | SPD (Transparent Pixel Disable)
- ---- ---- --cc c--- | Colour Mode
- ---- ---- ---- -CCC | Colour Calculation bits
-
-06 CMDCOLR
- mmmm mmmm mmmm mmmm | Colour Bank, Colour Lookup /8
-
-08 CMDSRCA (Character Address)
- aaaa aaaa aaaa aa-- | Character Address
- ---- ---- ---- --00 | UNUSED
-
-0a CMDSIZE (Character Size)
- 00-- ---- ---- ---- | UNUSED
- --xx xxxx ---- ---- | Character Size (X)
- ---- ---- yyyy yyyy | Character Size (Y)
-
-0c CMDXA (used for normal sprite)
- eeee ee-- ---- ---- | extension bits
- ---- --xx xxxx xxxx | x position
-
-0e CMDYA (used for normal sprite)
- eeee ee-- ---- ---- | extension bits
- ---- --yy yyyy yyyy | y position
-
-10 CMDXB
-12 CMDYB
-14 CMDXC
-16 CMDYC
-18 CMDXD
-1a CMDYD
-1c CMDGRDA (Gouraud Shading Table)
-1e UNUSED
----
-
-
-*/
-
-int vdp1_sprite_log = 0;
-
-static struct stv_vdp2_sprite_list
-{
-
- int CMDCTRL, CMDLINK, CMDPMOD, CMDCOLR, CMDSRCA, CMDSIZE, CMDGRDA;
- int CMDXA, CMDYA;
- int CMDXB, CMDYB;
- int CMDXC, CMDYC;
- int CMDXD, CMDYD;
-
- int ispoly;
-
-} stv2_current_sprite;
-
-int stvvdp1_local_x;
-int stvvdp1_local_y;
-
-/* we should actually draw to the framebuffer then process that with vdp.. note that if we're drawing
-to the framebuffer we CAN'T frameskip the vdp1 drawing as the hardware can READ the framebuffer
-and if we skip the drawing the content could be incorrect when it reads it, although i have no idea
-why they would want to */
-
-extern data32_t* stv_vdp2_cram;
-
-static INLINE void drawpixel(UINT16 *dest, int patterndata, int offsetcnt)
-{
- int pix,mode,transmask;
- data8_t* gfxdata = memory_region(REGION_GFX2);
- int pix2;
-
- switch (stv2_current_sprite.CMDPMOD&0x0038)
- {
- case 0x0000: /* mode 0 16 colour bank mode (4bits) (hanagumi blocks)*/
- /* most of the shienryu sprites use this mode*/
- pix = gfxdata[patterndata+offsetcnt/2];
- pix = offsetcnt&1 ? (pix & 0x0f):((pix & 0xf0)>>4) ;
- pix = pix+((stv2_current_sprite.CMDCOLR&0x0ff0));
- mode = 0;
- transmask = 0xf;
-
- if (shienryu_sprite_kludge)
- {
- pix += 0x400;
- pix &= 0x7ff;
- }
-
- break;
- case 0x0008: /* mode 1 16 colour lookup table mode (4bits)*/
- /* shienryu explosisons (and some enemies) use this mode*/
- pix2 = gfxdata[patterndata+offsetcnt/2];
- pix2 = offsetcnt&1 ? (pix2 & 0x0f):((pix2 & 0xf0)>>4);
- pix = pix2&1 ?
- ((((stv_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((pix2&0xfffe)/2)])) & 0x0000ffff) >> 0):
- ((((stv_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((pix2&0xfffe)/2)])) & 0xffff0000) >> 16);
-
-
- mode = 1;
- transmask = 0xf;
-
- if (pix2 & 0xf)
- {
- if (pix & 0x8000)
- {
- mode = 5;
- transmask = 0x7fff;
-
- }
-
-
- }
- else
- {
- pix=pix2; /* this is messy .. but just ensures that pen 0 isn't drawn*/
- }
- if (shienryu_sprite_kludge)
- {
- pix &= 0x1ff;
- pix += 0x400;
- pix &= 0x7ff;
- }
-
-
- break;
- case 0x0010: /* mode 2 64 colour bank mode (8bits) (character select portraits on hanagumi)*/
- pix = gfxdata[patterndata+offsetcnt];
- mode = 2;
- pix = pix+(stv2_current_sprite.CMDCOLR&0x0fc0);
- transmask = 0x3f;
- break;
- case 0x0018: /* mode 3 128 colour bank mode (8bits) (little characters on hanagumi use this mode)*/
- pix = gfxdata[patterndata+offsetcnt];
- pix = pix+(stv2_current_sprite.CMDCOLR&0x0f80);
- transmask = 0x7f;
- mode = 3;
- /* pix = rand();*/
- break;
- case 0x0020: /* mode 4 256 colour bank mode (8bits) (hanagumi title)*/
- pix = gfxdata[patterndata+offsetcnt];
- pix = pix+(stv2_current_sprite.CMDCOLR&0x0f00);
- transmask = 0xff;
- mode = 4;
- break;
- case 0x0028: /* mode 5 32,768 colour RGB mode (16bits)*/
- pix = gfxdata[patterndata+offsetcnt*2+1] | (gfxdata[patterndata+offsetcnt*2]<<8) ;
- mode = 5;
- transmask = 0x7fff;
- break;
- default: /* other settings illegal*/
- pix = mame_rand_video();
- mode = 0;
- transmask = 0xff;
- }
-
- if (stv2_current_sprite.ispoly)
- {
- pix = stv2_current_sprite.CMDCOLR&0xffff;
- mode = 1;
- transmask = 0xf;
-
- if (pix & 0x8000)
- {
- mode = 5;
- transmask = 0x7fff;
- }
- }
-
-
- if (mode != 5) /* mode 0-4 are 'normal'*/
- {
- if (pix & transmask)
- {
- /* there is probably a better way to do this .. it will probably have to change anyway because we'll be writing to the framebuffer instead */
- int col;
- col = (pix&1)? ((stv_vdp2_cram[(pix&0xfffe)/2] & 0x00007fff) >>0): ((stv_vdp2_cram[(pix&0xfffe)/2] & 0x7fff0000) >>16);
- col = ((col & 0x001f)*0x400) + (col & 0x03e0) + ((col & 0x7c00)/0x400);
- *dest = col;
- }
- }
- else /* mode 5 is rgb mode*/
- {
- int col;
- if (pix & 0x8000)
- {
- col = pix;
- col = ((col & 0x001f)*0x400) + (col & 0x03e0) + ((col & 0x7c00)/0x400);
- *dest = col & 0x7fff;
- }
- }
-}
-
-enum { FRAC_SHIFT = 16 };
-
-struct spoint {
- INT32 x, y;
- INT32 u, v;
-};
-
-static void vdp1_fill_slope(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int patterndata, int xsize,
- INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2,
- INT32 u1, INT32 u2, INT32 slu1, INT32 slu2, INT32 *nu1, INT32 *nu2,
- INT32 v1, INT32 v2, INT32 slv1, INT32 slv2, INT32 *nv1, INT32 *nv2,
- INT32 _y1, INT32 y2)
-{
- if(_y1 > cliprect->max_y)
- return;
-
- if(y2 <= cliprect->min_y) {
- int delta = y2-_y1;
- *nx1 = x1+delta*sl1;
- *nu1 = u1+delta*slu1;
- *nv1 = v1+delta*slv1;
- *nx2 = x2+delta*sl2;
- *nu2 = u2+delta*slu2;
- *nv2 = v2+delta*slv2;
- return;
- }
-
- if(y2 > cliprect->max_y)
- y2 = cliprect->max_y+1;
-
- if(_y1 < cliprect->min_y) {
- int delta = cliprect->min_y - _y1;
- x1 += delta*sl1;
- u1 += delta*slu1;
- v1 += delta*slv1;
- x2 += delta*sl2;
- u2 += delta*slu2;
- v2 += delta*slv2;
- _y1 = cliprect->min_y;
- }
-
- if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
- INT32 t, *tp;
- t = x1;
- x1 = x2;
- x2 = t;
- t = sl1;
- sl1 = sl2;
- sl2 = t;
- tp = nx1;
- nx1 = nx2;
- nx2 = tp;
-
- t = u1;
- u1 = u2;
- u2 = t;
- t = slu1;
- slu1 = slu2;
- slu2 = t;
- tp = nu1;
- nu1 = nu2;
- nu2 = tp;
-
- t = v1;
- v1 = v2;
- v2 = t;
- t = slv1;
- slv1 = slv2;
- slv2 = t;
- tp = nv1;
- nv1 = nv2;
- nv2 = tp;
- }
-
- while(_y1 < y2) {
- if(_y1 >= cliprect->min_y) {
- INT32 slux = 0, slvx = 0;
- int xx1 = x1>>FRAC_SHIFT;
- int xx2 = x2>>FRAC_SHIFT;
- INT32 u = u1;
- INT32 v = v1;
- if(xx1 != xx2) {
- int delta = xx2-xx1;
- slux = (u2-u1)/delta;
- slvx = (v2-v1)/delta;
- }
- if(xx1 <= cliprect->max_x || xx2 >= cliprect->min_x) {
- if(xx1 < cliprect->min_x) {
- int delta = cliprect->min_x-xx1;
- u += slux*delta;
- v += slvx*delta;
- xx1 = cliprect->min_x;
- }
- if(xx2 > cliprect->max_x)
- xx2 = cliprect->max_x;
-
- while(xx1 <= xx2) {
- drawpixel(((UINT16 *)(bitmap->line[_y1]))+xx1,
- patterndata,
- (v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
- xx1++;
- u += slux;
- v += slvx;
- }
- }
- }
-
- x1 += sl1;
- u1 += slu1;
- v1 += slv1;
- x2 += sl2;
- u2 += slu2;
- v2 += slv2;
- _y1++;
- }
- *nx1 = x1;
- *nu1 = u1;
- *nv1 = v1;
- *nx2 = x2;
- *nu2 = u2;
- *nv2 = v2;
-}
-
-static void vdp1_fill_line(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int patterndata, int xsize, INT32 y,
- INT32 x1, INT32 x2, INT32 u1, INT32 u2, INT32 v1, INT32 v2)
-{
- int xx1 = x1>>FRAC_SHIFT;
- int xx2 = x2>>FRAC_SHIFT;
-
- if(y > cliprect->max_y || y < cliprect->min_y)
- return;
-
- if(xx1 <= cliprect->max_x || xx2 >= cliprect->min_x) {
- INT32 slux = 0, slvx = 0;
- INT32 u = u1;
- INT32 v = v1;
- if(xx1 != xx2) {
- int delta = xx2-xx1;
- slux = (u2-u1)/delta;
- slvx = (v2-v1)/delta;
- }
- if(xx1 < cliprect->min_x) {
- int delta = cliprect->min_x-xx1;
- u += slux*delta;
- v += slvx*delta;
- xx1 = cliprect->min_x;
- }
- if(xx2 > cliprect->max_x)
- xx2 = cliprect->max_x;
-
- while(xx1 <= xx2) {
- drawpixel(((UINT16 *)(bitmap->line[y]))+xx1,
- patterndata,
- (v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
- xx1++;
- u += slux;
- v += slvx;
- }
- }
-}
-
-static void vdp1_fill_quad(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int patterndata, int xsize, const struct spoint *q)
-{
- INT32 sl1, sl2, slu1, slu2, slv1, slv2, cury, limy, x1, x2, u1, u2, v1, v2, delta;
- int pmin, pmax, i, ps1, ps2;
- struct spoint p[8];
-
- for(i=0; i<4; i++) {
- p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT;
- p[i].y = p[i+4].y = q[i].y;
- p[i].u = p[i+4].u = q[i].u << FRAC_SHIFT;
- p[i].v = p[i+4].v = q[i].v << FRAC_SHIFT;
- }
-
- pmin = pmax = 0;
- for(i=1; i<4; i++) {
- if(p[i].y < p[pmin].y)
- pmin = i;
- if(p[i].y > p[pmax].y)
- pmax = i;
- }
-
- cury = p[pmin].y;
- limy = p[pmax].y;
-
- if(cury == limy) {
- x1 = x2 = p[0].x;
- u1 = u2 = p[0].u;
- v1 = v2 = p[0].v;
- for(i=1; i<4; i++) {
- if(p[i].x < x1) {
- x1 = p[i].x;
- u1 = p[i].u;
- v1 = p[i].v;
- }
- if(p[i].x > x2) {
- x2 = p[i].x;
- u2 = p[i].u;
- v2 = p[i].v;
- }
- }
- vdp1_fill_line(bitmap, cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
- return;
- }
-
- if(cury > cliprect->max_y)
- return;
- if(limy <= cliprect->min_y)
- return;
-
- if(limy > cliprect->max_y)
- limy = cliprect->max_y;
-
- ps1 = pmin+4;
- ps2 = pmin;
-
- goto startup;
-
- for(;;) {
- if(p[ps1-1].y == p[ps2+1].y) {
- vdp1_fill_slope(bitmap, cliprect, patterndata, xsize,
- x1, x2, sl1, sl2, &x1, &x2,
- u1, u2, slu1, slu2, &u1, &u2,
- v1, v2, slv1, slv2, &v1, &v2,
- cury, p[ps1-1].y);
- cury = p[ps1-1].y;
- if(cury >= limy)
- break;
- ps1--;
- ps2++;
-
- startup:
- while(p[ps1-1].y == cury)
- ps1--;
- while(p[ps2+1].y == cury)
- ps2++;
- x1 = p[ps1].x;
- u1 = p[ps1].u;
- v1 = p[ps1].v;
- x2 = p[ps2].x;
- u2 = p[ps2].u;
- v2 = p[ps2].v;
-
- delta = cury-p[ps1-1].y;
- sl1 = (x1-p[ps1-1].x)/delta;
- slu1 = (u1-p[ps1-1].u)/delta;
- slv1 = (v1-p[ps1-1].v)/delta;
-
- delta = cury-p[ps2+1].y;
- sl2 = (x2-p[ps2+1].x)/delta;
- slu2 = (u2-p[ps2+1].u)/delta;
- slv2 = (v2-p[ps2+1].v)/delta;
- } else if(p[ps1-1].y < p[ps2+1].y) {
- vdp1_fill_slope(bitmap, cliprect, patterndata, xsize,
- x1, x2, sl1, sl2, &x1, &x2,
- u1, u2, slu1, slu2, &u1, &u2,
- v1, v2, slv1, slv2, &v1, &v2,
- cury, p[ps1-1].y);
- cury = p[ps1-1].y;
- if(cury >= limy)
- break;
- ps1--;
- while(p[ps1-1].y == cury)
- ps1--;
- x1 = p[ps1].x;
- u1 = p[ps1].u;
- v1 = p[ps1].v;
-
- delta = cury-p[ps1-1].y;
- sl1 = (x1-p[ps1-1].x)/delta;
- slu1 = (u1-p[ps1-1].u)/delta;
- slv1 = (v1-p[ps1-1].v)/delta;
- } else {
- vdp1_fill_slope(bitmap, cliprect, patterndata, xsize,
- x1, x2, sl1, sl2, &x1, &x2,
- u1, u2, slu1, slu2, &u1, &u2,
- v1, v2, slv1, slv2, &v1, &v2,
- cury, p[ps2+1].y);
- cury = p[ps2+1].y;
- if(cury >= limy)
- break;
- ps2++;
- while(p[ps2+1].y == cury)
- ps2++;
- x2 = p[ps2].x;
- u2 = p[ps2].u;
- v2 = p[ps2].v;
-
- delta = cury-p[ps2+1].y;
- sl2 = (x2-p[ps2+1].x)/delta;
- slu2 = (u2-p[ps2+1].u)/delta;
- slv2 = (v2-p[ps2+1].v)/delta;
- }
- }
- if(cury == limy)
- vdp1_fill_line(bitmap, cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
-}
-
-static int x2s(int v)
-{
- int r = v & 0x7ff;
- if (r & 0x400)
- r -= 0x800;
- return r + stvvdp1_local_x;
-}
-
-static int y2s(int v)
-{
- int r = v & 0x7ff;
- if (r & 0x400)
- r -= 0x800;
- return r + stvvdp1_local_y;
-}
-
-void stv_vpd1_draw_distorded_sprite(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- struct spoint q[4];
-
- int xsize, ysize;
- int direction;
- int patterndata;
-
- direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
-
- xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
- xsize = xsize * 8;
-
- ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
-
- patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
- patterndata = patterndata * 0x8;
-
- q[0].x = x2s(stv2_current_sprite.CMDXA);
- q[0].y = y2s(stv2_current_sprite.CMDYA);
- q[1].x = x2s(stv2_current_sprite.CMDXB);
- q[1].y = y2s(stv2_current_sprite.CMDYB);
- q[2].x = x2s(stv2_current_sprite.CMDXC);
- q[2].y = y2s(stv2_current_sprite.CMDYC);
- q[3].x = x2s(stv2_current_sprite.CMDXD);
- q[3].y = y2s(stv2_current_sprite.CMDYD);
-
- if(direction & 1) { /* xflip*/
- q[0].u = q[3].u = xsize-1;
- q[1].u = q[2].u = 0;
- } else {
- q[0].u = q[3].u = 0;
- q[1].u = q[2].u = xsize-1;
- }
- if(direction & 2) { /* yflip*/
- q[0].v = q[1].v = ysize-1;
- q[2].v = q[3].v = 0;
- } else {
- q[0].v = q[1].v = 0;
- q[2].v = q[3].v = ysize-1;
- }
-
- vdp1_fill_quad(bitmap, cliprect, patterndata, xsize, q);
-}
-
-void stv_vpd1_draw_scaled_sprite(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- struct spoint q[4];
-
- int xsize, ysize;
- int direction;
- int patterndata;
- int zoompoint;
- int x,y;
- int x2,y2;
- int screen_width,screen_height;
-
- direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
-
- xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
- xsize = xsize * 8;
- if (xsize == 0) return; /* setting prohibited */
-
- ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
- if (ysize == 0) return; /* setting prohibited */
-
- patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
- patterndata = patterndata * 0x8;
-
- zoompoint = (stv2_current_sprite.CMDCTRL & 0x0f00)>>8;
-
- x = stv2_current_sprite.CMDXA;
- y = stv2_current_sprite.CMDYA;
-
- screen_width = stv2_current_sprite.CMDXB;
- screen_height = stv2_current_sprite.CMDYB;
-
- x2 = stv2_current_sprite.CMDXC; /* second co-ordinate set x*/
- y2 = stv2_current_sprite.CMDYC; /* second co-ordinate set y*/
-
- switch (zoompoint)
- {
- case 0x0: /* specified co-ordinates*/
- break;
- case 0x5: /* up left*/
- break;
- case 0x6: /* up center*/
- x -= screen_width/2 ;
- break;
- case 0x7: /* up right*/
- x -= screen_width;
- break;
-
- case 0x9: /* center left*/
- y -= screen_height/2 ;
- break;
- case 0xa: /* center center*/
- y -= screen_height/2 ;
- x -= screen_width/2 ;
-
- break;
-
- case 0xb: /* center right*/
- y -= screen_height/2 ;
- x -= screen_width;
- break;
-
- case 0xd: /* center left*/
- y -= screen_height;
- break;
-
- case 0xe: /* center center*/
- y -= screen_height;
- x -= screen_width/2 ;
- break;
-
- case 0xf: /* center right*/
- y -= screen_height;
- x -= screen_width;
- break;
-
- default: /* illegal*/
- break;
-
- }
-
- /* 0----1
- | |
- | |
- 3----2 */
-
- if (zoompoint)
- {
- q[0].x = x2s(x);
- q[0].y = y2s(y);
- q[1].x = x2s(x)+screen_width;
- q[1].y = y2s(y);
- q[2].x = x2s(x)+screen_width;
- q[2].y = y2s(y)+screen_height;
- q[3].x = x2s(x);
- q[3].y = y2s(y)+screen_height;
- }
- else
- {
- q[0].x = x2s(x);
- q[0].y = y2s(y);
- q[1].x = x2s(x2);
- q[1].y = y2s(y);
- q[2].x = x2s(x2);
- q[2].y = y2s(y2);
- q[3].x = x2s(x);
- q[3].y = y2s(y2);
- }
-
-
- if(direction & 1) { /* xflip*/
- q[0].u = q[3].u = xsize-1;
- q[1].u = q[2].u = 0;
- } else {
- q[0].u = q[3].u = 0;
- q[1].u = q[2].u = xsize-1;
- }
- if(direction & 2) { /* yflip*/
- q[0].v = q[1].v = ysize-1;
- q[2].v = q[3].v = 0;
- } else {
- q[0].v = q[1].v = 0;
- q[2].v = q[3].v = ysize-1;
- }
-
- vdp1_fill_quad(bitmap, cliprect, patterndata, xsize, q);
-}
-
-
-void stv_vpd1_draw_normal_sprite(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int sprite_type)
-{
- UINT16 *destline;
-
- int y, ysize, ycnt, drawypos;
- int x, xsize, xcnt, drawxpos;
- int direction;
- int patterndata;
-
- x = x2s(stv2_current_sprite.CMDXA);
- y = y2s(stv2_current_sprite.CMDYA);
-
- direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
-
- xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
- xsize = xsize * 8;
-
- ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
-
-
- patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
- patterndata = patterndata * 0x8;
-
-
-
-
- if (vdp1_sprite_log) logerror ("Drawing Normal Sprite x %04x y %04x xsize %04x ysize %04x patterndata %06x\n",x,y,xsize,ysize,patterndata);
-
- for (ycnt = 0; ycnt != ysize; ycnt++) {
-
-
- if (direction & 0x2) /* 'yflip' (reverse direction)*/
- {
- drawypos = y+((ysize-1)-ycnt);
- }
- else
- {
- drawypos = y+ycnt;
- }
-
- if ((drawypos >= cliprect->min_y) && (drawypos <= cliprect->max_y))
- {
- destline = (UINT16 *)(bitmap->line[drawypos]);
-
- for (xcnt = 0; xcnt != xsize; xcnt ++)
- {
- if (direction & 0x1) /* 'xflip' (reverse direction)*/
- {
- drawxpos = x+((xsize-1)-xcnt);
- }
- else
- {
- drawxpos = x+xcnt;
- }
- if ((drawxpos >= cliprect->min_x) && (drawxpos <= cliprect->max_x))
- {
- int offsetcnt;
-
- offsetcnt = ycnt*xsize+xcnt;
-
- drawpixel(destline+drawxpos, patterndata, offsetcnt);
- } /* drawxpos*/
-
- } /* xcnt*/
-
- } /* if drawypos*/
-
- } /* ycny*/
-}
-
-void stv_vdp1_process_list(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- int position;
- int spritecount;
- int vdp1_nest;
-
- spritecount = 0;
- position = 0;
-
- if (vdp1_sprite_log) logerror ("Sprite List Process START\n");
-
- vdp1_nest = -1;
-
- /*Set CEF bit to 0*/
- SET_CEF_FROM_1_TO_0;
-
- while (spritecount<10000) /* if its drawn this many sprites something is probably wrong or sega were crazy ;-)*/
- {
- int draw_this_sprite;
-
- draw_this_sprite = 1;
-
- /* if (position >= ((0x80000/0x20)/4)) // safety check*/
- /* {*/
- /* if (vdp1_sprite_log) logerror ("Sprite List Position Too High!\n");*/
- /* position = 0;*/
- /* }*/
-
- stv2_current_sprite.CMDCTRL = (stv_vdp1_vram[position * (0x20/4)+0] & 0xffff0000) >> 16;
-
- if (stv2_current_sprite.CMDCTRL == 0x8000)
- {
- if (vdp1_sprite_log) logerror ("List Terminator (0x8000) Encountered, Sprite List Process END\n");
- goto end; /* end of list*/
- }
-
- stv2_current_sprite.CMDLINK = (stv_vdp1_vram[position * (0x20/4)+0] & 0x0000ffff) >> 0;
- stv2_current_sprite.CMDPMOD = (stv_vdp1_vram[position * (0x20/4)+1] & 0xffff0000) >> 16;
- stv2_current_sprite.CMDCOLR = (stv_vdp1_vram[position * (0x20/4)+1] & 0x0000ffff) >> 0;
- stv2_current_sprite.CMDSRCA = (stv_vdp1_vram[position * (0x20/4)+2] & 0xffff0000) >> 16;
- stv2_current_sprite.CMDSIZE = (stv_vdp1_vram[position * (0x20/4)+2] & 0x0000ffff) >> 0;
- stv2_current_sprite.CMDXA = (stv_vdp1_vram[position * (0x20/4)+3] & 0xffff0000) >> 16;
- stv2_current_sprite.CMDYA = (stv_vdp1_vram[position * (0x20/4)+3] & 0x0000ffff) >> 0;
- stv2_current_sprite.CMDXB = (stv_vdp1_vram[position * (0x20/4)+4] & 0xffff0000) >> 16;
- stv2_current_sprite.CMDYB = (stv_vdp1_vram[position * (0x20/4)+4] & 0x0000ffff) >> 0;
- stv2_current_sprite.CMDXC = (stv_vdp1_vram[position * (0x20/4)+5] & 0xffff0000) >> 16;
- stv2_current_sprite.CMDYC = (stv_vdp1_vram[position * (0x20/4)+5] & 0x0000ffff) >> 0;
- stv2_current_sprite.CMDXD = (stv_vdp1_vram[position * (0x20/4)+6] & 0xffff0000) >> 16;
- stv2_current_sprite.CMDYD = (stv_vdp1_vram[position * (0x20/4)+6] & 0x0000ffff) >> 0;
- stv2_current_sprite.CMDGRDA = (stv_vdp1_vram[position * (0x20/4)+7] & 0xffff0000) >> 16;
-/* stv2_current_sprite.UNUSED = (stv_vdp1_vram[position * (0x20/4)+7] & 0x0000ffff) >> 0;*/
-
- /* proecess jump / skip commands, set position for next sprite */
- switch (stv2_current_sprite.CMDCTRL & 0x7000)
- {
- case 0x0000: /* jump next*/
- if (vdp1_sprite_log) logerror ("Sprite List Process + Next (Normal)\n");
- position++;
- break;
- case 0x1000: /* jump assign*/
- if (vdp1_sprite_log) logerror ("Sprite List Process + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2));
- position= (stv2_current_sprite.CMDLINK>>2);
- break;
- case 0x2000: /* jump call*/
- if (vdp1_nest == -1)
- {
- if (vdp1_sprite_log) logerror ("Sprite List Process + Call Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2));
- vdp1_nest = position+1;
- position = (stv2_current_sprite.CMDLINK>>2);
- }
- else
- {
- if (vdp1_sprite_log) logerror ("Sprite List Nested Call, ignoring\n");
- position++;
- }
- break;
- case 0x3000:
- if (vdp1_nest != -1)
- {
- if (vdp1_sprite_log) logerror ("Sprite List Process + Return\n");
- position = vdp1_nest;
- vdp1_nest = -1;
- }
- else
- {
- if (vdp1_sprite_log) logerror ("Attempted return from no subroutine, aborting\n");
- position++;
- goto end; /* end of list*/
- }
- break;
- case 0x4000:
- draw_this_sprite = 0;
- position++;
- break;
- case 0x5000:
- if (vdp1_sprite_log) logerror ("Sprite List Skip + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2));
- draw_this_sprite = 0;
- position= (stv2_current_sprite.CMDLINK>>2);
-
- break;
- case 0x6000:
- draw_this_sprite = 0;
- if (vdp1_nest == -1)
- {
- if (vdp1_sprite_log) logerror ("Sprite List Skip + Call To Subroutine Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2));
-
- vdp1_nest = position+1;
- position = (stv2_current_sprite.CMDLINK>>2);
- }
- else
- {
- if (vdp1_sprite_log) logerror ("Sprite List Nested Call, ignoring\n");
- position++;
- }
- break;
- case 0x7000:
- draw_this_sprite = 0;
- if (vdp1_nest != -1)
- {
- if (vdp1_sprite_log) logerror ("Sprite List Skip + Return from Subroutine\n");
-
- position = vdp1_nest;
- vdp1_nest = -1;
- }
- else
- {
- if (vdp1_sprite_log) logerror ("Attempted return from no subroutine, aborting\n");
- position++;
- goto end; /* end of list*/
- }
- break;
- }
-
- /* continue to draw this sprite only if the command wasn't to skip it */
- if (draw_this_sprite ==1)
- {
- switch (stv2_current_sprite.CMDCTRL & 0x000f)
- {
- case 0x0000:
- if (vdp1_sprite_log) logerror ("Sprite List Normal Sprite\n");
- stv2_current_sprite.ispoly = 0;
- stv_vpd1_draw_normal_sprite(bitmap,cliprect, 0);
- break;
-
- case 0x0001:
- if (vdp1_sprite_log) logerror ("Sprite List Scaled Sprite\n");
- stv2_current_sprite.ispoly = 0;
- stv_vpd1_draw_scaled_sprite(bitmap,cliprect);
- break;
-
- case 0x0002:
- if (vdp1_sprite_log) logerror ("Sprite List Distorted Sprite\n");
- stv2_current_sprite.ispoly = 0;
- stv_vpd1_draw_distorded_sprite(bitmap,cliprect);
- break;
-
- case 0x0004:
- if (vdp1_sprite_log) logerror ("Sprite List Polygon\n");
- stv2_current_sprite.ispoly = 1;
- stv_vpd1_draw_distorded_sprite(bitmap,cliprect);
- break;
-
- case 0x0005:
- if (vdp1_sprite_log) logerror ("Sprite List Polyline\n");
- break;
-
- case 0x0006:
- if (vdp1_sprite_log) logerror ("Sprite List Line\n");
- break;
-
- case 0x0008:
- if (vdp1_sprite_log) logerror ("Sprite List Set Command for User Clipping\n");
- break;
-
- case 0x0009:
- if (vdp1_sprite_log) logerror ("Sprite List Set Command for System Clipping\n");
- break;
-
- case 0x000a:
- if (vdp1_sprite_log) logerror ("Sprite List Local Co-Ordinate Set\n");
- stvvdp1_local_x = stv2_current_sprite.CMDXA;
- stvvdp1_local_y = stv2_current_sprite.CMDYA;
- break;
-
- default:
- if (vdp1_sprite_log) logerror ("Sprite List Illegal!\n");
- break;
-
-
- }
-
-
- }
-
- spritecount++;
-
- }
-
-
- end:
- /*set CEF to 1*/
- SET_CEF_FROM_0_TO_1;
-
- /* not here! this is done every frame drawn even if the cpu isn't running eg in the debugger */
-/* if(!(stv_scu[40] & 0x2000)) //Sprite draw end irq*/
-/* cpu_set_irq_line_and_vector(0, 2, HOLD_LINE , 0x4d);*/
-
- if (vdp1_sprite_log) logerror ("End of list processing!\n");
-}
-
-void video_update_vdp1(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
-/* int enable;*/
-/* if (keyboard_pressed (KEYCODE_R)) vdp1_sprite_log = 1;*/
-/* if (keyboard_pressed (KEYCODE_T)) vdp1_sprite_log = 0;*/
-
-/* if (keyboard_pressed (KEYCODE_Y)) vdp1_sprite_log = 0;*/
-/* {*/
-/* FILE *fp;*/
-/**/
-/* fp=fopen("vdp1_ram.dmp", "w+b");*/
-/* if (fp)*/
-/* {*/
-/* fwrite(stv_vdp1, 0x00100000, 1, fp);*/
-/* fclose(fp);*/
-/* }*/
-/* }*/
- stv_vdp1_process_list(bitmap,cliprect);
-}
diff --git a/src/vidhrdw/stvvdp2_vidhrdw.c b/src/vidhrdw/stvvdp2_vidhrdw.c
deleted file mode 100644
index bc17a0b5..00000000
--- a/src/vidhrdw/stvvdp2_vidhrdw.c
+++ /dev/null
@@ -1,3127 +0,0 @@
-/* Sega Saturn VDP2 */
-
-/*
-
-the dirty marking stuff and tile decoding will probably be removed in the end anyway as we'll need custom
-rendering code since mame's drawgfx / tilesytem don't offer everything st-v needs
-
-this system seems far too complex to use Mame's tilemap system
-
-4 'scroll' planes (scroll screens)
-
-the scroll planes have slightly different capabilities
-
-NBG0
-NBG1
-NBG2
-NBG3
-
-2 'rotate' planes
-
-RBG0
-RBG1
-
--- other crap
-EXBG (external)
-
-------------------------------------------------------------------------------------------
-
-Notes of Interest:
-
--the test mode / bios is drawn with layer NBG3
-
--hanagumi Puts a 'RED' dragon logo in tileram (base 0x64000, 4bpp, 8x8 tiles) but
-its not displayed in gurus video.Update:It's actually not drawn because its
-priority value is 0.
-
--scrolling is screen display wise,meaning that a scrolling value is masked with the
-screen resolution size values.
-
--VDP1 "general purpose" priority isn't taken into account yet,for now we fix the priority
-value to six...
-
--AFAIK Suikoenbu & Winter Heat are the only ST-V game that use Mode 2 as the Color RAM
-format.
-
--Bitmaps USES transparency pens,examples are:
-elandore's energy bars;
-mausuke's foreground(the one used on the playfield)(I guess that this is also
-alpha-blended);
-
-for now I've removed black pixels,it isn't 100% right so there MUST BE a better way
-for this...
-
-*/
-
-#include "driver.h"
-
-data32_t* stv_vdp2_regs;
-data32_t* stv_vdp2_vram;
-/* this won't be used in the end .. */
-data8_t* stv_vdp2_vram_dirty_8x8x4;
-data8_t* stv_vdp2_vram_dirty_8x8x8;
-
-data32_t* stv_vdp2_cram;
-extern void video_update_vdp1(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
-extern int stv_vdp1_start ( void );
-static void stv_vdp2_dynamic_res_change(void);
-
-/*
-
--------------------------------------------------|-----------------------------|------------------------------
-| Function | Normal Scroll Screen | Rotation Scroll Screen |
-| |-----------------------------|-----------------------------|------------------------------
-| | NBG0 | NBG1 | NBG2 | NBG3 | RBG0 | RBG1 |
--------------------------------------------------|-----------------------------|------------------------------
-| Character Colour | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours |
-| Count | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " |
-| | 2048 " " | 2048 " " | | | 2048 " " | 2048 " " |
-| | 32768 " " | 32768 " " | | | 32768 " " | 32768 " " |
-| | 16770000 " " | | | | 16770000 " " | 16770000 " " |
--------------------------------------------------|-----------------------------|------------------------------
-| Character Size | 1x1 Cells , 2x2 Cells |
--------------------------------------------------|-----------------------------|------------------------------
-| Pattern Name | 1 word , 2 words |
-| Data Size | |
--------------------------------------------------|-----------------------------|------------------------------
-| Plane Size | 1 H x 1 V 1 Pages ; 2 H x 1 V 1 Pages ; 2 H x 2 V Pages (I don't understand ... ) |
--------------------------------------------------|-----------------------------|------------------------------
-| Plane Count | 4 | 16 |
--------------------------------------------------|-----------------------------|------------------------------
-| Bitmap Possible | Yes | No | Yes | No |
--------------------------------------------------|-----------------------------|------------------------------
-| Bitmap Size | 512 x 256 | N/A | 512x256 | N/A |
-| | 512 x 512 | | 512x512 | |
-| | 1024 x 256 | | | |
-| | 1024 x 512 | | | |
--------------------------------------------------|-----------------------------|------------------------------
-| Scale | 0.25 x - 256 x | None | Any ? |
--------------------------------------------------|-----------------------------|------------------------------
-| Rotation | No | Yes |
--------------------------------------------------|-----------------------------|-----------------------------|
-| Linescroll | Yes | No |
--------------------------------------------------|-----------------------------|------------------------------
-| Column Scroll | Yes | No |
--------------------------------------------------|-----------------------------|------------------------------
-| Mosaic | Yes | Horizontal Only |
--------------------------------------------------|-----------------------------|------------------------------
-
-*/
-
-/* 180000 - r/w - TVMD - TV Screen Mode
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | DISP | -- | -- | -- | -- | -- | -- | BDCLMD |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | LSMD1 | LSMD0 | VRESO1 | VRESO0 | -- | HRESO2 | HRESO1 | HRESO0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_TVMD ((stv_vdp2_regs[0x000/4] >> 16)&0x0000ffff)
-
- #define STV_VDP2_BDCLMD ((STV_VDP2_TVMD & 0x0100) >> 8)
- #define STV_VDP2_LSMD ((STV_VDP2_TVMD & 0x00c0) >> 6)
- #define STV_VDP2_VRES ((STV_VDP2_TVMD & 0x0030) >> 4)
- #define STV_VDP2_HRES ((STV_VDP2_TVMD & 0x0007) >> 0)
-
-/* 180002 - r/w - EXTEN - External Signal Enable Register
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | EXLTEN | EXSYEN |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | DASEL | EXBGEN |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180004 - r/o - TVSTAT - Screen Status
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | EXLTFG | EXSYFG |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | VBLANK | HBLANK | ODD | EVEN |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180006 - r/w - VRSIZE - VRAM Size
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VRAMSZ | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | VER3 | VER2 | VER1 | VER0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_VRSIZE ((stv_vdp2_regs[0x004/4] >> 0)&0x0000ffff)
-
- #define STV_VDP2_VRAMSZ ((STV_VDP2_VRSIZE & 0x8000) >> 15)
-
-/* 180008 - r/o - HCNT - H-Counter
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | HCT9 | HCT8 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | HCT7 | HCT6 | HCT5 | HCT4 | HCT3 | HCT2 | HCT1 | HCT0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_HCNT ((stv_vdp2_regs[0x008/4] >> 16)&0x000003ff)
-
-/* 18000A - r/o - VCNT - V-Counter
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | VCT9 | VCT8 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCT7 | VCT6 | VCT5 | VCT4 | VCT3 | VCT2 | VCT1 | VCT0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_VCNT ((stv_vdp2_regs[0x008/4] >> 0)&0x000003ff)
-
-/* 18000C - RESERVED
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18000E - r/w - RAMCTL - RAM Control
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | CRMD1 | CRMD0 | -- | -- | VRBMD | VRAMD |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | RDBSB11 | RDBSB10 | RDBSB01 | RDBSB00 | RDBSA11 | RDBSA10 | RDBSA01 | RDBSA00 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_RAMCTL ((stv_vdp2_regs[0x00c/4] >> 0)&0x0000ffff)
-
- #define STV_VDP2_CRMD ((STV_VDP2_RAMCTL & 0x3000) >> 12)
-
-/* 180010 - r/w - -CYCA0L - VRAM CYCLE PATTERN (BANK A0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP0A03 | VCP0A02 | VCP0A01 | VCP0A00 | VCP1A03 | VCP1A02 | VCP1A01 | VCP1A00 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP2A03 | VCP2A02 | VCP2A01 | VCP2A00 | VCP3A03 | VCP3A02 | VCP3A01 | VCP3A00 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180012 - r/w - -CYCA0U - VRAM CYCLE PATTERN (BANK A0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP4A03 | VCP4A02 | VCP4A01 | VCP4A00 | VCP5A03 | VCP5A02 | VCP5A01 | VCP5A00 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP6A03 | VCP6A02 | VCP6A01 | VCP6A00 | VCP7A03 | VCP7A02 | VCP7A01 | VCP7A00 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180014 - r/w - -CYCA1L - VRAM CYCLE PATTERN (BANK A1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP0A13 | VCP0A12 | VCP0A11 | VCP0A10 | VCP1A13 | VCP1A12 | VCP1A11 | VCP1A10 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP2A13 | VCP2A12 | VCP2A11 | VCP2A10 | VCP3A13 | VCP3A12 | VCP3A11 | VCP3A10 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180016 - r/w - -CYCA1U - VRAM CYCLE PATTERN (BANK A1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP4A13 | VCP4A12 | VCP4A11 | VCP4A10 | VCP5A13 | VCP5A12 | VCP5A11 | VCP5A10 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP6A13 | VCP6A12 | VCP6A11 | VCP6A10 | VCP7A13 | VCP7A12 | VCP7A11 | VCP7A10 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180018 - r/w - -CYCB0L - VRAM CYCLE PATTERN (BANK B0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP0B03 | VCP0B02 | VCP0B01 | VCP0B00 | VCP1B03 | VCP1B02 | VCP1B01 | VCP1B00 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP2B03 | VCP2B02 | VCP2B01 | VCP2B00 | VCP3B03 | VCP3B02 | VCP3B01 | VCP3B00 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18001A - r/w - -CYCB0U - VRAM CYCLE PATTERN (BANK B0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP4B03 | VCP4B02 | VCP4B01 | VCP4B00 | VCP5B03 | VCP5B02 | VCP5B01 | VCP5B00 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP6B03 | VCP6B02 | VCP6B01 | VCP6B00 | VCP7B03 | VCP7B02 | VCP7B01 | VCP7B00 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18001C - r/w - -CYCB1L - VRAM CYCLE PATTERN (BANK B1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP0B13 | VCP0B12 | VCP0B11 | VCP0B10 | VCP1B13 | VCP1B12 | VCP1B11 | VCP1B10 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP2B13 | VCP2B12 | VCP2B11 | VCP2B10 | VCP3B13 | VCP3B12 | VCP3B11 | VCP3B10 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18001E - r/w - -CYCB1U - VRAM CYCLE PATTERN (BANK B1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | VCP4B13 | VCP4B12 | VCP4B11 | VCP4B10 | VCP5B13 | VCP5B12 | VCP5B11 | VCP5B10 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | VCP6B13 | VCP6B12 | VCP6B11 | VCP6B10 | VCP7B13 | VCP7B12 | VCP7B11 | VCP7B10 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180020 - r/w - BGON - SCREEN DISPLAY ENABLE
-
- this register allows each tilemap to be enabled or disabled and also which layers are solid
-
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | R0TPON | N3TPON | N2TPON | N1TPON | N0TPON |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | R1ON | R0ON | N3ON | N2ON | N1ON | N0ON |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_BGON ((stv_vdp2_regs[0x020/4] >> 16)&0x0000ffff)
-
- /* NxOn - Layer Enable Register*/
- #define STV_VDP2_xxON ((STV_VDP2_BGON & 0x001f) >> 0) /* to see if anything is enabled */
-
- #define STV_VDP2_N0ON ((STV_VDP2_BGON & 0x0001) >> 0) /* N0On = NBG0 Enable */
- #define STV_VDP2_N1ON ((STV_VDP2_BGON & 0x0002) >> 1) /* N1On = NBG1 Enable */
- #define STV_VDP2_N2ON ((STV_VDP2_BGON & 0x0004) >> 2) /* N2On = NBG2 Enable */
- #define STV_VDP2_N3ON ((STV_VDP2_BGON & 0x0008) >> 3) /* N3On = NBG3 Enable */
- #define STV_VDP2_R0ON ((STV_VDP2_BGON & 0x0010) >> 4) /* R0On = RBG0 Enable */
- #define STV_VDP2_R1ON ((STV_VDP2_BGON & 0x0020) >> 5) /* R1On = RBG1 Enable */
-
- /* NxTPON - Transparency Pen Enable Registers*/
- #define STV_VDP2_N0TPON ((STV_VDP2_BGON & 0x0100) >> 8) /* N0TPON = NBG0 Draw Transparent Pen (as solid) /or/ RBG1 Draw Transparent Pen */
- #define STV_VDP2_N1TPON ((STV_VDP2_BGON & 0x0200) >> 9) /* N1TPON = NBG1 Draw Transparent Pen (as solid) /or/ EXBG Draw Transparent Pen */
- #define STV_VDP2_N2TPON ((STV_VDP2_BGON & 0x0400) >> 10)/* N2TPON = NBG2 Draw Transparent Pen (as solid) */
- #define STV_VDP2_N3TPON ((STV_VDP2_BGON & 0x0800) >> 11)/* N3TPON = NBG3 Draw Transparent Pen (as solid) */
- #define STV_VDP2_R0TPON ((STV_VDP2_BGON & 0x1000) >> 12)/* R0TPON = RBG0 Draw Transparent Pen (as solid) */
-
-/*
-180022 - MZCTL - Mosaic Control
-
-180024 - Special Function Code Select
-
-180026 - Special Function Code
-
-180028 - CHCTLA - Character Control (NBG0, NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | N1CHCN1 | N1CHCN0 | N1BMSZ1 | N1BMSZ0 | N1BMEN | N1CHSZ |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | N0CHCN2 | N0CHCN1 | N0CHCN0 | N0BMSZ1 | N0BMSZ0 | N0BMEN | N0CHSZ |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_CHCTLA ((stv_vdp2_regs[0x028/4] >> 16)&0x0000ffff)
-
-/* -------------------------- NBG0 Character Control Registers -------------------------- */
-
-/* N0CHCNx NBG0 (or RGB1) Colour Depth
- 000 - 16 Colours
- 001 - 256 Colours
- 010 - 2048 Colours
- 011 - 32768 Colours (RGB5)
- 100 - 16770000 Colours (RGB8)
- 101 - invalid
- 110 - invalid
- 111 - invalid */
- #define STV_VDP2_N0CHCN ((STV_VDP2_CHCTLA & 0x0070) >> 4)
-
-/* N0BMSZx - NBG0 Bitmap Size *guessed*
- 00 - 512 x 256
- 01 - 512 x 512
- 10 - 1024 x 256
- 11 - 1024 x 512 */
- #define STV_VDP2_N0BMSZ ((STV_VDP2_CHCTLA & 0x000c) >> 2)
-
-/* N0BMEN - NBG0 Bitmap Enable
- 0 - use cell mode
- 1 - use bitmap mode */
- #define STV_VDP2_N0BMEN ((STV_VDP2_CHCTLA & 0x0002) >> 1)
-
-/* N0CHSZ - NBG0 Character (Tile) Size
- 0 - 1 cell x 1 cell (8x8)
- 1 - 2 cells x 2 cells (16x16) */
- #define STV_VDP2_N0CHSZ ((STV_VDP2_CHCTLA & 0x0001) >> 0)
-
-/* -------------------------- NBG1 Character Control Registers -------------------------- */
-
-/* N1CHCNx - NBG1 (or EXB1) Colour Depth
- 00 - 16 Colours
- 01 - 256 Colours
- 10 - 2048 Colours
- 11 - 32768 Colours (RGB5) */
- #define STV_VDP2_N1CHCN ((STV_VDP2_CHCTLA & 0x3000) >> 12)
-
-/* N1BMSZx - NBG1 Bitmap Size *guessed*
- 00 - 512 x 256
- 01 - 512 x 512
- 10 - 1024 x 256
- 11 - 1024 x 512 */
- #define STV_VDP2_N1BMSZ ((STV_VDP2_CHCTLA & 0x0c00) >> 10)
-
-/* N1BMEN - NBG1 Bitmap Enable
- 0 - use cell mode
- 1 - use bitmap mode */
- #define STV_VDP2_N1BMEN ((STV_VDP2_CHCTLA & 0x0200) >> 9)
-
-/* N1CHSZ - NBG1 Character (Tile) Size
- 0 - 1 cell x 1 cell (8x8)
- 1 - 2 cells x 2 cells (16x16) */
- #define STV_VDP2_N1CHSZ ((STV_VDP2_CHCTLA & 0x0100) >> 8)
-
-/*
-18002A - CHCTLB - Character Control (NBG2, NBG1, RBG0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | R0CHCN2 | R0CHCN1 | R0CHCN0 | -- | R0BMSZ | R0BMEN | R0CHSZ |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | N3CHCN | N3CHSZ | -- | -- | N2CHCN | N2CHSZ |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_CHCTLB ((stv_vdp2_regs[0x028/4] >> 0)&0x0000ffff)
-
-/* -------------------------- RBG0 Character Control Registers -------------------------- */
-
-
-/* R0CHCNx RBG0 Colour Depth
- 000 - 16 Colours
- 001 - 256 Colours
- 010 - 2048 Colours
- 011 - 32768 Colours (RGB5)
- 100 - 16770000 Colours (RGB8)
- 101 - invalid
- 110 - invalid
- 111 - invalid */
- #define STV_VDP2_R0CHCN ((STV_VDP2_CHCTLB & 0x7000) >> 12)
-
-/* R0BMSZx - RBG0 Bitmap Size *guessed*
- 00 - 512 x 256
- 01 - 512 x 512 */
- #define STV_VDP2_R0BMSZ ((STV_VDP2_CHCTLB & 0x0400) >> 10)
-
-/* R0BMEN - RBG0 Bitmap Enable
- 0 - use cell mode
- 1 - use bitmap mode */
- #define STV_VDP2_R0BMEN ((STV_VDP2_CHCTLB & 0x0200) >> 9)
-
-/* R0CHSZ - NBG0 Character (Tile) Size
- 0 - 1 cell x 1 cell (8x8)
- 1 - 2 cells x 2 cells (16x16) */
- #define STV_VDP2_R0CHSZ ((STV_VDP2_CHCTLB & 0x0100) >> 8)
-
- #define STV_VDP2_N3CHCN ((STV_VDP2_CHCTLB & 0x0020) >> 5)
- #define STV_VDP2_N3CHSZ ((STV_VDP2_CHCTLB & 0x0010) >> 4)
- #define STV_VDP2_N2CHCN ((STV_VDP2_CHCTLB & 0x0002) >> 1)
- #define STV_VDP2_N2CHSZ ((STV_VDP2_CHCTLB & 0x0001) >> 0)
-
-
-/*
-18002C - BMPNA - Bitmap Palette Number (NBG0, NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_BMPNA ((stv_vdp2_regs[0x02c/4] >> 16)&0x0000ffff)
-
- #define STV_VDP2_N1BMP ((STV_VDP2_BMPNA & 0x0700) >> 8)
- #define STV_VDP2_N0BMP ((STV_VDP2_BMPNA & 0x0007) >> 0)
-
-/* 18002E - Bitmap Palette Number (RBG0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-
-/* 180030 - PNCN0 - Pattern Name Control (NBG0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | N0PNB | N0CNSM | -- | -- | -- | -- | N0SPR | N0SCC |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | N0SPLT6 | N0SPLT5 | N0SPLT4 | N0SPCN4 | N0SPCN3 | N0SPCN2 | N0SPCN1 | N0SPCN0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_PNCN0 ((stv_vdp2_regs[0x030/4] >> 16)&0x0000ffff)
-
-/* Pattern Data Size
- 0 = 2 bytes
- 1 = 1 byte */
- #define STV_VDP2_N0PNB ((STV_VDP2_PNCN0 & 0x8000) >> 15)
-
-/* Character Number Supplement (in 1 byte mode)
- 0 = Character Number = 10bits + 2bits for flip
- 1 = Character Number = 12 bits, no flip */
- #define STV_VDP2_N0CNSM ((STV_VDP2_PNCN0 & 0x4000) >> 14)
-
-/* NBG0 Special Priority Register (in 1 byte mode) */
- #define STV_VDP2_N0SPR ((STV_VDP2_PNCN0 & 0x0200) >> 9)
-
-/* NBG0 Special Colour Control Register (in 1 byte mode) */
- #define STV_VDP2_N0SCC ((STV_VDP2_PNCN0 & 0x0100) >> 8)
-
-/* Supplementary Palette Bits (in 1 byte mode) */
- #define STV_VDP2_N0SPLT ((STV_VDP2_PNCN0 & 0x00e0) >> 5)
-
-/* Supplementary Character Bits (in 1 byte mode) */
- #define STV_VDP2_N0SPCN ((STV_VDP2_PNCN0 & 0x001f) >> 0)
-
-/* 180032 - Pattern Name Control (NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_PNCN1 ((stv_vdp2_regs[0x030/4] >> 0)&0x0000ffff)
-
-/* Pattern Data Size
- 0 = 2 bytes
- 1 = 1 byte */
- #define STV_VDP2_N1PNB ((STV_VDP2_PNCN1 & 0x8000) >> 15)
-
-/* Character Number Supplement (in 1 byte mode)
- 0 = Character Number = 10bits + 2bits for flip
- 1 = Character Number = 12 bits, no flip */
- #define STV_VDP2_N1CNSM ((STV_VDP2_PNCN1 & 0x4000) >> 14)
-
-/* NBG0 Special Priority Register (in 1 byte mode) */
- #define STV_VDP2_N1SPR ((STV_VDP2_PNCN1 & 0x0200) >> 9)
-
-/* NBG0 Special Colour Control Register (in 1 byte mode) */
- #define STV_VDP2_N1SCC ((STV_VDP2_PNCN1 & 0x0100) >> 8)
-
-/* Supplementary Palette Bits (in 1 byte mode) */
- #define STV_VDP2_N1SPLT ((STV_VDP2_PNCN1 & 0x00e0) >> 5)
-
-/* Supplementary Character Bits (in 1 byte mode) */
- #define STV_VDP2_N1SPCN ((STV_VDP2_PNCN1 & 0x001f) >> 0)
-
-
-/* 180034 - Pattern Name Control (NBG2)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_PNCN2 ((stv_vdp2_regs[0x034/4] >> 16)&0x0000ffff)
-
-/* Pattern Data Size
- 0 = 2 bytes
- 1 = 1 byte */
- #define STV_VDP2_N2PNB ((STV_VDP2_PNCN2 & 0x8000) >> 15)
-
-/* Character Number Supplement (in 1 byte mode)
- 0 = Character Number = 10bits + 2bits for flip
- 1 = Character Number = 12 bits, no flip */
- #define STV_VDP2_N2CNSM ((STV_VDP2_PNCN2 & 0x4000) >> 14)
-
-/* NBG0 Special Priority Register (in 1 byte mode) */
- #define STV_VDP2_N2SPR ((STV_VDP2_PNCN2 & 0x0200) >> 9)
-
-/* NBG0 Special Colour Control Register (in 1 byte mode) */
- #define STV_VDP2_N2SCC ((STV_VDP2_PNCN2 & 0x0100) >> 8)
-
-/* Supplementary Palette Bits (in 1 byte mode) */
- #define STV_VDP2_N2SPLT ((STV_VDP2_PNCN2 & 0x00e0) >> 5)
-
-/* Supplementary Character Bits (in 1 byte mode) */
- #define STV_VDP2_N2SPCN ((STV_VDP2_PNCN2 & 0x001f) >> 0)
-
-
-/* 180036 - Pattern Name Control (NBG3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | N3PNB | N3CNSM | -- | -- | -- | -- | N3SPR | N3SCC |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | N3SPLT6 | N3SPLT5 | N3SPLT4 | N3SPCN4 | N3SPCN3 | N3SPCN2 | N3SPCN1 | N3SPCN0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_PNCN3 ((stv_vdp2_regs[0x034/4] >> 0)&0x0000ffff)
-
-/* Pattern Data Size
- 0 = 2 bytes
- 1 = 1 byte */
- #define STV_VDP2_N3PNB ((STV_VDP2_PNCN3 & 0x8000) >> 15)
-
-/* Character Number Supplement (in 1 byte mode)
- 0 = Character Number = 10bits + 2bits for flip
- 1 = Character Number = 12 bits, no flip */
- #define STV_VDP2_N3CNSM ((STV_VDP2_PNCN3 & 0x4000) >> 14)
-
-/* NBG0 Special Priority Register (in 1 byte mode) */
- #define STV_VDP2_N3SPR ((STV_VDP2_PNCN3 & 0x0200) >> 9)
-
-/* NBG0 Special Colour Control Register (in 1 byte mode) */
- #define STV_VDP2_N3SCC ((STV_VDP2_PNCN3 & 0x0100) >> 8)
-
-/* Supplementary Palette Bits (in 1 byte mode) */
- #define STV_VDP2_N3SPLT ((STV_VDP2_PNCN3 & 0x00e0) >> 5)
-
-/* Supplementary Character Bits (in 1 byte mode) */
- #define STV_VDP2_N3SPCN ((STV_VDP2_PNCN3 & 0x001f) >> 0)
-
-
-/* 180038 - Pattern Name Control (RBG0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18003A - PLSZ - Plane Size (incomplete)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | N3PLSZ1 | N3PLSZ0 | -- | -- | N1PLSZ1 | N1PLSZ0 | N0PLSZ1 | N0PLSZ0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_PLSZ ((stv_vdp2_regs[0x038/4] >> 0)&0x0000ffff)
-
- /* NBG0 Plane Size
- 00 1H Page x 1V Page
- 01 2H Pages x 1V Page
- 10 invalid
- 11 2H Pages x 2V Pages */
- #define STV_VDP2_N0PLSZ ((STV_VDP2_PLSZ & 0x0003) >> 0)
- #define STV_VDP2_N1PLSZ ((STV_VDP2_PLSZ & 0x000c) >> 2)
- #define STV_VDP2_N2PLSZ ((STV_VDP2_PLSZ & 0x0030) >> 4)
- #define STV_VDP2_N3PLSZ ((STV_VDP2_PLSZ & 0x00c0) >> 6)
-
-/* 18003C - MPOFN - Map Offset (NBG0, NBG1, NBG2, NBG3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | N3MP8 | N3MP7 | N3MP6 | -- | N2MP8 | N2MP7 | N2MP6 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | N1MP8 | N1MP7 | N1MP6 | -- | N0MP8 | N0MP7 | N0MP6 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPOFN_ ((stv_vdp2_regs[0x03c/4] >> 16)&0x0000ffff)
-
- /* Higher 3 bits of the map offset for each layer */
- #define STV_VDP2_N0MP_ ((STV_VDP2_MPOFN_ & 0x0007) >> 0)
- #define STV_VDP2_N1MP_ ((STV_VDP2_MPOFN_ & 0x0070) >> 4)
- #define STV_VDP2_N2MP_ ((STV_VDP2_MPOFN_ & 0x0700) >> 8)
- #define STV_VDP2_N3MP_ ((STV_VDP2_MPOFN_ & 0x7000) >> 12)
-
-
-
-
-/* 18003E - Map Offset (Rotation Parameter A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180040 - MPABN0 - Map (NBG0, Plane A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | N0MPB5 | N0MPB4 | N0MPB3 | N0MPB2 | N0MPB1 | N0MPB0 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | N0MPA5 | N0MPA4 | N0MPA3 | N0MPA2 | N0MPA1 | N0MPA0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPABN0 ((stv_vdp2_regs[0x040/4] >> 16)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
- #define STV_VDP2_N0MPB ((STV_VDP2_MPABN0 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
- #define STV_VDP2_N0MPA ((STV_VDP2_MPABN0 & 0x003f) >> 0)
-
-
-/* 180042 - MPCDN0 - (NBG0, Plane C,D)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | N0MPD5 | N0MPD4 | N0MPD3 | N0MPD2 | N0MPD1 | N0MPD0 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | N0MPC5 | N0MPC4 | N0MPC3 | N0MPC2 | N0MPC1 | N0MPC0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPCDN0 ((stv_vdp2_regs[0x040/4] >> 0)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
- #define STV_VDP2_N0MPD ((STV_VDP2_MPCDN0 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
- #define STV_VDP2_N0MPC ((STV_VDP2_MPCDN0 & 0x003f) >> 0)
-
-
-/* 180044 - Map (NBG1, Plane A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPABN1 ((stv_vdp2_regs[0x044/4] >> 16)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
- #define STV_VDP2_N1MPB ((STV_VDP2_MPABN1 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
- #define STV_VDP2_N1MPA ((STV_VDP2_MPABN1 & 0x003f) >> 0)
-
-/* 180046 - Map (NBG1, Plane C,D)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPCDN1 ((stv_vdp2_regs[0x044/4] >> 0)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
- #define STV_VDP2_N1MPD ((STV_VDP2_MPCDN1 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
- #define STV_VDP2_N1MPC ((STV_VDP2_MPCDN1 & 0x003f) >> 0)
-
-
-/* 180048 - Map (NBG2, Plane A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPABN2 ((stv_vdp2_regs[0x048/4] >> 16)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG2 */
- #define STV_VDP2_N2MPB ((STV_VDP2_MPABN2 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG2 */
- #define STV_VDP2_N2MPA ((STV_VDP2_MPABN2 & 0x003f) >> 0)
-
-/* 18004a - Map (NBG2, Plane C,D)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPCDN2 ((stv_vdp2_regs[0x048/4] >> 0)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG2 */
- #define STV_VDP2_N2MPD ((STV_VDP2_MPCDN2 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG2 */
- #define STV_VDP2_N2MPC ((STV_VDP2_MPCDN2 & 0x003f) >> 0)
-
-/* 18004c - Map (NBG3, Plane A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPABN3 ((stv_vdp2_regs[0x04c/4] >> 16)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
- #define STV_VDP2_N3MPB ((STV_VDP2_MPABN3 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
- #define STV_VDP2_N3MPA ((STV_VDP2_MPABN3 & 0x003f) >> 0)
-
-
-/* 18004e - Map (NBG3, Plane C,D)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_MPCDN3 ((stv_vdp2_regs[0x04c/4] >> 0)&0x0000ffff)
-
- /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
- #define STV_VDP2_N3MPD ((STV_VDP2_MPCDN3 & 0x3f00) >> 8)
-
- /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
- #define STV_VDP2_N3MPC ((STV_VDP2_MPCDN3 & 0x003f) >> 0)
-
-/* 180050 - Map (Rotation Parameter A, Plane A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180052 - Map (Rotation Parameter A, Plane C,D)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180054 - Map (Rotation Parameter A, Plane E,F)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180056 - Map (Rotation Parameter A, Plane G,H)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180058 - Map (Rotation Parameter A, Plane I,J)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18005a - Map (Rotation Parameter A, Plane K,L)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18005c - Map (Rotation Parameter A, Plane M,N)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18005e - Map (Rotation Parameter A, Plane O,P)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180060 - Map (Rotation Parameter B, Plane A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180062 - Map (Rotation Parameter B, Plane C,D)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180064 - Map (Rotation Parameter B, Plane E,F)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180066 - Map (Rotation Parameter B, Plane G,H)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180068 - Map (Rotation Parameter B, Plane I,J)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18006a - Map (Rotation Parameter B, Plane K,L)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18006c - Map (Rotation Parameter B, Plane M,N)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18006e - Map (Rotation Parameter B, Plane O,P)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180070 - SCXIN0 - Screen Scroll (NBG0, Horizontal Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCXIN0 ((stv_vdp2_regs[0x070/4] >> 16)&0x0000ffff)
-
-
-/* 180072 - Screen Scroll (NBG0, Horizontal Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180074 - SCYIN0 - Screen Scroll (NBG0, Vertical Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCYIN0 ((stv_vdp2_regs[0x074/4] >> 16)&0x0000ffff)
-
-
-/* 180076 - Screen Scroll (NBG0, Vertical Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180078 - Coordinate Inc (NBG0, Horizontal Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMXIN0 ((stv_vdp2_regs[0x078/4] >> 16)&0x0000ffff)
-
- #define STV_VDP2_N0ZMXI ((STV_VDP2_ZMXIN0 & 0x0007) >> 0)
-
-/* 18007a - Coordinate Inc (NBG0, Horizontal Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMXDN0 ((stv_vdp2_regs[0x078/4] >> 0)&0x0000ffff)
-
- #define STV_VDP2_N0ZMXD ((STV_VDP2_ZMXDN0 >> 8)& 0xff)
-
-/* 18007c - Coordinate Inc (NBG0, Vertical Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMYIN0 ((stv_vdp2_regs[0x07c/4] >> 16)&0x0000ffff)
-
- #define STV_VDP2_N0ZMYI ((STV_VDP2_ZMYIN0 & 0x0007) >> 0)
-
-/* 18007e - Coordinate Inc (NBG0, Vertical Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMYDN0 ((stv_vdp2_regs[0x07c/4] >> 0)&0x0000ffff)
-
- #define STV_VDP2_N0ZMYD ((STV_VDP2_ZMYDN0 >> 8)& 0xff)
-
-/* 180080 - SCXIN1 - Screen Scroll (NBG1, Horizontal Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCXIN1 ((stv_vdp2_regs[0x080/4] >> 16)&0x0000ffff)
-
-/* 180082 - Screen Scroll (NBG1, Horizontal Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180084 - SCYIN1 - Screen Scroll (NBG1, Vertical Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCYIN1 ((stv_vdp2_regs[0x084/4] >> 16)&0x0000ffff)
-
-/* 180086 - Screen Scroll (NBG1, Vertical Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180088 - Coordinate Inc (NBG1, Horizontal Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMXIN1 ((stv_vdp2_regs[0x088/4] >> 16)&0x0000ffff)
-
- #define STV_VDP2_N1ZMXI ((STV_VDP2_ZMXIN1 & 0x0007) >> 0)
-
-/* 18008a - Coordinate Inc (NBG1, Horizontal Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMXDN1 ((stv_vdp2_regs[0x088/4] >> 0)&0x0000ffff)
-
- #define STV_VDP2_N1ZMXD ((STV_VDP2_ZMXDN1 >> 8)& 0xff)
-
-/* 18008c - Coordinate Inc (NBG1, Vertical Integer Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMYIN1 ((stv_vdp2_regs[0x08c/4] >> 16)&0x0000ffff)
-
- #define STV_VDP2_N1ZMYI ((STV_VDP2_ZMYIN1 & 0x0007) >> 0)
-
-/* 18008e - Coordinate Inc (NBG1, Vertical Fractional Part)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_ZMYDN1 ((stv_vdp2_regs[0x08c/4] >> 0)&0x0000ffff)
-
- #define STV_VDP2_N1ZMYD ((STV_VDP2_ZMYDN1 >> 8)& 0xff)
-
-/* 180090 - SCXN2 - Screen Scroll (NBG2, Horizontal)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCXN2 ((stv_vdp2_regs[0x090/4] >> 16)&0x0000ffff)
-
-/* 180092 - SCYN2 - Screen Scroll (NBG2, Vertical)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCYN2 ((stv_vdp2_regs[0x090/4] >> 0)&0x0000ffff)
-
-/* 180094 - SCXN3 - Screen Scroll (NBG3, Horizontal)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCXN3 ((stv_vdp2_regs[0x094/4] >> 16)&0x0000ffff)
-
-/* 180096 - SCYN3 - Screen Scroll (NBG3, Vertical)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_SCYN3 ((stv_vdp2_regs[0x094/4] >> 0)&0x0000ffff)
-
-/* 180098 - Reduction Enable
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18009a - Line and Vertical Cell Scroll Control (NBG0, NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18009c - Vertical Cell Table Address (NBG0, NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18009e - Vertical Cell Table Address (NBG0, NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800a0 - Line Scroll Table Address (NBG0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800a2 - Line Scroll Table Address (NBG0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800a4 - Line Scroll Table Address (NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800a6 - Line Scroll Table Address (NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800a8 - Line Colour Screen Table Address
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800aa - Line Colour Screen Table Address
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ac - Back Screen Table Address
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | BKCLMD | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | BKTA18 | BKTA17 | BKTA16 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ae - Back Screen Table Address
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | BKTA15 | BKTA14 | BKTA13 | BKTA12 | BKTA11 | BKTA10 | BKTA9 | BKTA8 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | BKTA7 | BKTA7 | BKTA6 | BKTA5 | BKTA4 | BKTA3 | BKTA2 | BKTA0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_BKTA_UL (stv_vdp2_regs[0x0ac/4])
-
- #define STV_VDP2_BKCLMD ((STV_VDP2_BKTA_UL & 0x80000000) >> 31)
- #define STV_VDP2_BKTA ((STV_VDP2_BKTA_UL & 0x0003ffff) >> 0)
- /*MSB of this register is used when the extra RAM cart is used,ignore it for now.*/
- /* #define STV_VDP2_BKTA ((STV_VDP2_BKTA_UL & 0x0007ffff) >> 0)*/
-
-/* 1800b0 - Rotation Parameter Mode
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800b2 - Rotation Parameter Read Control
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800b4 - Coefficient Table Control
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800b6 - Coefficient Table Address Offset (Rotation Parameter A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800b8 - Screen Over Pattern Name (Rotation Parameter A)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ba - Screen Over Pattern Name (Rotation Parameter B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800bc - Rotation Parameter Table Address (Rotation Parameter A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-
-/* 1800be - Rotation Parameter Table Address (Rotation Parameter A,B)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800c0 - Window Position (W0, Horizontal Start Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800c2 - Window Position (W0, Vertical Start Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800c4 - Window Position (W0, Horizontal Emd Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800c6 - Window Position (W0, Vertical End Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800c8 - Window Position (W1, Horizontal Start Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ca - Window Position (W1, Vertical Start Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800cc - Window Position (W1, Horizontal Emd Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ce - Window Position (W1, Vertical End Point)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800d0 - Window Control (NBG0, NBG1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800d2 - Window Control (NBG2, NBG3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800d4 - Window Control (RBG0, Sprite)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800d6 - Window Control (Parameter Window, Colour Calc. Window)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800d8 - Line Window Table Address (W0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800da - Line Window Table Address (W0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800dc - Line Window Table Address (W1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800de - Line Window Table Address (W1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800e0 - Sprite Control
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800e2 - Shadow Control
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800e4 - CRAOFA - Colour Ram Address Offset (NBG0 - NBG3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | N0CAOS2 | N3CAOS1 | N3CAOS0 | -- | N2CAOS2 | N2CAOS1 | N2CAOS0 |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | N1CAOS2 | N1CAOS1 | N1CAOS0 | -- | N0CAOS2 | N0CAOS1 | N0CAOS0 |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_CRAOFA ((stv_vdp2_regs[0x0e4/4] >> 16)&0x0000ffff)
-
- /* NxCAOS = */
- #define STV_VDP2_N0CAOS ((STV_VDP2_CRAOFA & 0x0007) >> 0)
- #define STV_VDP2_N1CAOS ((STV_VDP2_CRAOFA & 0x0070) >> 4)
- #define STV_VDP2_N2CAOS ((STV_VDP2_CRAOFA & 0x0700) >> 8)
- #define STV_VDP2_N3CAOS ((STV_VDP2_CRAOFA & 0x7000) >> 12)
-
-
-/* 1800e6 - Colour Ram Address Offset (RBG0, SPRITE)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800e8 - Line Colour Screen Enable
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ea - Special Priority Mode
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ec - Colour Calculation Control
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800ee - Special Colour Calculation Mode
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800f0 - Priority Number (Sprite 0,1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800f2 - Priority Number (Sprite 2,3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800f4 - Priority Number (Sprite 4,5)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800f6 - Priority Number (Sprite 6,7)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800f8 - PRINA - Priority Number (NBG 0,1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_PRINA ((stv_vdp2_regs[0x0f8/4] >> 16)&0x0000ffff)
-
- #define STV_VDP2_N1PRIN ((STV_VDP2_PRINA & 0x0700) >> 8)
- #define STV_VDP2_N0PRIN ((STV_VDP2_PRINA & 0x0007) >> 0)
-
-/* 1800fa - PRINB - Priority Number (NBG 2,3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
- #define STV_VDP2_PRINB ((stv_vdp2_regs[0x0f8/4] >> 0)&0x0000ffff)
-
- #define STV_VDP2_N3PRIN ((STV_VDP2_PRINB & 0x0700) >> 8)
- #define STV_VDP2_N2PRIN ((STV_VDP2_PRINB & 0x0007) >> 0)
-
-/* 1800fc - Priority Number (RBG0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 1800fe - Reserved
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180100 - Colour Calculation Ratio (Sprite 0,1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180102 - Colour Calculation Ratio (Sprite 2,3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180104 - Colour Calculation Ratio (Sprite 4,5)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180106 - Colour Calculation Ratio (Sprite 6,7)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180108 - Colour Calculation Ratio (NBG 0,1)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18010a - Colour Calculation Ratio (NBG 2,3)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18010c - Colour Calculation Ratio (RBG 0)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18010e - Colour Calculation Ratio (Line Colour Screen, Back Colour Screen)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180110 - Colour Offset Enable
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180112 - Colour Offset Select
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180114 - Colour Offset A (Red)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180116 - Colour Offset A (Green)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 180118 - Colour Offset A (Blue)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18011a - Colour Offset B (Red)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18011b - Colour Offset B (Green)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* 18011c - Colour Offset B (Blue)
- bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
- | -- | -- | -- | -- | -- | -- | -- | -- |
- |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
- | -- | -- | -- | -- | -- | -- | -- | -- |
- \----------|----------|----------|----------|----------|----------|----------|---------*/
-
-/* Not sure if to use this for the rotating tilemaps as well or just use different draw functions, might add too much bloat */
-static struct stv_vdp2_tilemap_capabilities
-{
- UINT8 enabled;
- UINT8 trans_enabled;
- UINT8 colour_depth;
- UINT8 tile_size;
- UINT8 bitmap_enable;
- UINT8 bitmap_size;
- UINT8 bitmap_palette_number;
- UINT8 bitmap_map;
- UINT16 map_offset[16];
-
- UINT8 pattern_data_size;
- UINT8 character_number_supplement;
- UINT8 special_priority_register;
- UINT8 special_colour_control_register;
- UINT8 supplementary_palette_bits;
- UINT8 supplementary_character_bits;
-
- INT16 scrollx;
- INT16 scrolly;
- UINT8 scalex_i,scaley_i;
- UINT16 scalex_f,scaley_f;
-
- UINT8 plane_size;
- UINT8 colour_ram_address_offset;
-
- UINT8 real_map_offset[16];
-
- int layer_name; /* just to keep track */
-} stv2_current_tilemap;
-
-
-
-static void stv_vdp2_draw_basic_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
-/* logerror ("bitmap enable %02x size %08x depth %08x\n", stv2_current_tilemap.layer_name, stv2_current_tilemap.bitmap_size, stv2_current_tilemap.colour_depth);*/
-/* usrintf_showmessage ("bitmap enable %02x size %08x depth %08x number %02x", stv2_current_tilemap.layer_name, stv2_current_tilemap.bitmap_size, stv2_current_tilemap.colour_depth,stv2_current_tilemap.bitmap_palette_number);*/
-
- int xsize = 0;
- int ysize = 0;
- int xcnt,ycnt;
- data8_t* gfxdata = memory_region(REGION_GFX1);
- static UINT16 *destline;
-
- if (!stv2_current_tilemap.enabled) return;
-
- /* size for n0 / n1 */
- switch (stv2_current_tilemap.bitmap_size)
- {
- case 0: xsize=512; ysize=256; break;
- case 1: xsize=512; ysize=512; break;
- case 2: xsize=1024; ysize=256; break;
- case 3: xsize=1024; ysize=512; break;
- }
-
- gfxdata+=(stv2_current_tilemap.bitmap_map * 0x20000);
- stv2_current_tilemap.bitmap_palette_number+=stv2_current_tilemap.colour_ram_address_offset;
- stv2_current_tilemap.bitmap_palette_number&=7;/*safety check*/
-
- switch(stv2_current_tilemap.colour_depth)
- {
- /*Palette Format*/
- case 0:/*elandore uses this on the fight,size is wrong.*/
- {
- for (ycnt = 0; ycnt pens[((gfxdata[0] & 0x0f) >> 0) | (stv2_current_tilemap.bitmap_palette_number * 0x100)])
- plot_pixel(bitmap,xcnt+1 ,ycnt,Machine->pens[((gfxdata[0] & 0x0f) >> 0) | (stv2_current_tilemap.bitmap_palette_number * 0x100)]);
- if(Machine->pens[((gfxdata[0] & 0xf0) >> 4) | (stv2_current_tilemap.bitmap_palette_number * 0x100)])
- plot_pixel(bitmap,xcnt,ycnt,Machine->pens[((gfxdata[0] & 0xf0) >> 4) | (stv2_current_tilemap.bitmap_palette_number * 0x100)]);
-
- gfxdata++;
- }
- }
- }
- break;
- case 1:
- {
- for (ycnt = 0; ycnt pens[(gfxdata[0] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100)])
- plot_pixel(bitmap,xcnt,ycnt,Machine->pens[(gfxdata[0] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100)]);
-
- gfxdata++;
- }
- }
- }
- break;
- case 2:
- {
- for (ycnt = 0; ycnt pens[((gfxdata[0] & 0x07) * 0x100) | (gfxdata[1] & 0xff)])
- plot_pixel(bitmap,xcnt,ycnt,Machine->pens[((gfxdata[0] & 0x07) * 0x100) | (gfxdata[1] & 0xff)]);
-
- gfxdata+=2;
- }
- }
- }
- break;
- /*RGB format*/
- /*
- M L
- S S
- B B
- --------BBBBBGGGGGRRRRR
- */
- case 3:
- {
- for (ycnt = 0; ycnt line[ycnt]);
-
- for (xcnt = 0; xcnt >2);
- g = ((gfxdata[0] & 0x03) << 3) | ((gfxdata[1] & 0xe0) >> 5);
- r = ((gfxdata[1] & 0x1f));
-
- if(r||g||b)
- destline[xcnt] = b | g << 5 | r << 10;
-
- gfxdata+=2;
- }
- }
- }
- break;
- /*
- M L
- S S
- B B
- --------BBBBBBBBGGGGGGGGRRRRRRRR
- */
- case 4:
- {
- for (ycnt = 0; ycnt line[ycnt]);
-
- for (xcnt = 0; xcnt > 2) * 0x04000 |
- | | 1 word |---------------------------------------------------------------------|
- | | | 2 H x 2 V | bits 8-1 (upper mask 0x1ff) (0x1ff >> 0) * 0x01000 |
- | 2 H x 1 V -----------------------------------------------------------------------------------------------|
- | | | 1 H x 1 V | bits 5-1 (upper mask 0x03f) (0x1ff >> 3) * 0x08000 |
- | | 2 words |---------------------------------------------------------------------|
- | | | 2 H x 2 V | bits 7-1 (upper mask 0x0ff) (0x1ff >> 1) * 0x02000 |
- -------------------------------------------------------------------------------------------------------------
- lower mask = ~stv2_current_tilemap.plane_size
- -----------------------------------------------------------------------------------------------------------*/
-
- /* Precalculate bases from MAP registers */
- for (i = 0; i < 4; i++)
- {
- int shifttable[4] = {0,1,2,2};
-
- int uppermask, uppermaskshift;
-
- uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1);
- uppermask = 0x1ff >> uppermaskshift;
-
- base[i] = ((stv2_current_tilemap.map_offset[i] & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes;
-
- base[i] &= 0x7ffff; /* shienryu needs this for the text layer, is there a problem elsewhere or is it just right without the ram cart */
-
- base[i] = base[i] / 4; /* convert bytes to DWORDS*/
- }
-
- /* other bits */
- stv2_current_tilemap.trans_enabled = stv2_current_tilemap.trans_enabled ? TRANSPARENCY_NONE : TRANSPARENCY_PEN;
- stv2_current_tilemap.scrollx &= mppixels_x-1;
- stv2_current_tilemap.scrolly &= mppixels_y-1;
-
- pgsize_dwords = pgsize_bytes /4;
- plsize_dwords = plsize_bytes /4;
- mpsize_dwords = mpsize_bytes /4;
-
-/* if (stv2_current_tilemap.layer_name==3) usrintf_showmessage ("well this is a bit %08x", stv2_current_tilemap.map_offset[0]);*/
-/* if (stv2_current_tilemap.layer_name==3) usrintf_showmessage ("well this is a bit %08x %08x %08x %08x", stv2_current_tilemap.plane_size, pgtiles_x, pltiles_x, mptiles_x);*/
-
- if (!stv2_current_tilemap.enabled) return; /* stop right now if its disabled ...*/
-
- /* most things we need (or don't need) to work out are now worked out */
-
- for (y = 0; y Machine->visible_area.max_y) continue;
-
- ypageoffs = y & (pgtiles_y-1);
- yplaneoffs = y & (pltiles_y-1);
-
- if (yplaneoffs > ypageoffs) page |= 2;
- if (y > yplaneoffs) map |= 2;
-
- for (x = 0; x Machine->visible_area.max_x) continue;
-
- xpageoffs = x & (pgtiles_x-1);
- xplaneoffs = x & (pltiles_x-1);
-
- if (xplaneoffs > xpageoffs) page |= 1;
- if (x > xplaneoffs) map |= 1;
-
- newbase = base[map] + page * pgsize_dwords;
- offs = (ypageoffs * pgtiles_x) + xpageoffs;
-
-/* GET THE TILE INFO ... */
- /* 1 word per tile mode with supplement bits */
- if (stv2_current_tilemap.pattern_data_size ==1)
- {
-
- data = stv_vdp2_vram[newbase + offs/2];
- data = (offs&1) ? (data & 0x0000ffff) : ((data & 0xffff0000) >> 16);
-
- /* Supplement Mode 12 bits, no flip */
- if (stv2_current_tilemap.character_number_supplement == 1)
- {
-/* no flip */ flipyx = 0;
-/* 8x8 */ if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x0fff) + ( (stv2_current_tilemap.supplementary_character_bits&0x1c) << 10);
-/* 16x16 */ else tilecode = ((data & 0x0fff) << 2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x10) << 10);
- }
- /* Supplement Mode 10 bits, with flip */
- else
- {
-/* flip bits */ flipyx = (data & 0x0c00) >> 10;
-/* 8x8 */ if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x03ff) + ( (stv2_current_tilemap.supplementary_character_bits) << 10);
-/* 16x16 */ else tilecode = ((data & 0x03ff) <<2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x1c) << 10);
- }
-
-/*>16cols*/ if (stv2_current_tilemap.colour_depth != 0) pal = ((data & 0x7000)>>8);
-/*16 cols*/ else pal = ((data & 0xf000)>>12) +( (stv2_current_tilemap.supplementary_palette_bits) << 4);
-
- }
- /* 2 words per tile, no supplement bits */
- else
- {
-
- data = stv_vdp2_vram[newbase + offs];
- tilecode = (data & 0x00007fff);
- pal = (data & 0x007f0000)>>16;
- /* specialc = (data & 0x10000000)>>28;;*/
- flipyx = (data & 0xc0000000)>>30;
- }
-/* WE'VE GOT THE TILE INFO ... */
-
-/* DECODE ANY TILES WE NEED TO DECODE */
-
- pal += stv2_current_tilemap.colour_ram_address_offset<< 4; /* bios uses this ..*/
-
- if (stv2_current_tilemap.colour_depth != 0)
- {
- tilecode = tilecode >> 1;
- gfx = 2;
- pal = pal >>4;
-
- /* do a bit of tile decoding */
- tilecode &=0x3fff;
- if (stv2_current_tilemap.tile_size==1)
- { /* we're treating 16x16 tiles as 4 8x8's atm */
- if (stv_vdp2_vram_dirty_8x8x8[tilecode] == 1) { stv_vdp2_vram_dirty_8x8x8[tilecode] = 0; decodechar(Machine->gfx[2], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[2].gfxlayout); };
- if (stv_vdp2_vram_dirty_8x8x8[tilecode+1] == 1) { stv_vdp2_vram_dirty_8x8x8[tilecode+1] = 0; decodechar(Machine->gfx[2], tilecode+1, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[2].gfxlayout); };
- if (stv_vdp2_vram_dirty_8x8x8[tilecode+2] == 1) { stv_vdp2_vram_dirty_8x8x8[tilecode+2] = 0; decodechar(Machine->gfx[2], tilecode+2, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[2].gfxlayout); };
- if (stv_vdp2_vram_dirty_8x8x8[tilecode+3] == 1) { stv_vdp2_vram_dirty_8x8x8[tilecode+3] = 0; decodechar(Machine->gfx[2], tilecode+3, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[2].gfxlayout); };
- }
- else
- {
- if (stv_vdp2_vram_dirty_8x8x8[tilecode] == 1) { stv_vdp2_vram_dirty_8x8x8[tilecode] = 0; decodechar(Machine->gfx[2], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[2].gfxlayout); };
- }
-
- }
- else
- {
- gfx = 0;
-
- /* do a bit of tile decoding */
- tilecode &=0x7fff;
- if (stv2_current_tilemap.tile_size==1)
- { /* we're treating 16x16 tiles as 4 8x8's atm */
- if (stv_vdp2_vram_dirty_8x8x4[tilecode] == 1) { stv_vdp2_vram_dirty_8x8x4[tilecode] = 0; decodechar(Machine->gfx[0], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[0].gfxlayout); };
- if (stv_vdp2_vram_dirty_8x8x4[tilecode+1] == 1) { stv_vdp2_vram_dirty_8x8x4[tilecode+1] = 0; decodechar(Machine->gfx[0], tilecode+1, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[0].gfxlayout); };
- if (stv_vdp2_vram_dirty_8x8x4[tilecode+2] == 1) { stv_vdp2_vram_dirty_8x8x4[tilecode+2] = 0; decodechar(Machine->gfx[0], tilecode+2, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[0].gfxlayout); };
- if (stv_vdp2_vram_dirty_8x8x4[tilecode+3] == 1) { stv_vdp2_vram_dirty_8x8x4[tilecode+3] = 0; decodechar(Machine->gfx[0], tilecode+3, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[0].gfxlayout); };
- }
- else
- {
- if (stv_vdp2_vram_dirty_8x8x4[tilecode] == 1) { stv_vdp2_vram_dirty_8x8x4[tilecode] = 0; decodechar(Machine->gfx[0], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[0].gfxlayout); };
- }
- }
-/* TILES ARE NOW DECODED */
-
-/* DRAW! */
- if(stv2_current_tilemap.scalex_i != 1 || stv2_current_tilemap.scaley_i != 1)
- {
-
- if(stv2_current_tilemap.scalex_i == 0)
- scalex = stv2_current_tilemap.scalex_f /** STV_VDP2_HCNT*/ * 0x2c0*2;
- else
- scalex = 0xffff;
-
- if(stv2_current_tilemap.scaley_i == 0)
- scaley = stv2_current_tilemap.scaley_f * STV_VDP2_VCNT * 0x100;
- else
- scaley = 0xffff;
-
- /* usrintf_showmessage("%04x %04x",STV_VDP2_HCNT,stv2_current_tilemap.scalex_f); */
-
- if (stv2_current_tilemap.tile_size==1)
- {
- /* normal */
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
-
- /* this isn't very efficient .. we could probably improve it */
- if (stv2_current_tilemap.scrollx) /* wraparound x */
- {
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- }
- if (stv2_current_tilemap.scrolly) /* wraparound y */
- {
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- }
- if (stv2_current_tilemap.scrollx && stv2_current_tilemap.scrolly) /* wraparound x & y */
- {
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- }
-
- }
- else
- {
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- /* this isn't very efficient .. we could probably improve it */
- if (stv2_current_tilemap.scrollx) /* wraparound x */
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos+mppixels_x, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- if (stv2_current_tilemap.scrolly) /* wraparound y */
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- if (stv2_current_tilemap.scrollx && stv2_current_tilemap.scrolly) /* wraparound x & y */
- drawgfxzoom(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos+mppixels_x, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0,scalex,scaley);
- }
- }
- else
- {
- if (stv2_current_tilemap.tile_size==1)
- {
- /* normal */
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0);
-
- /* this isn't very efficient .. we could probably improve it */
- if (stv2_current_tilemap.scrollx) /* wraparound x */
- {
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos+8,cliprect,stv2_current_tilemap.trans_enabled,0);
- }
- if (stv2_current_tilemap.scrolly) /* wraparound y */
- {
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- }
- if (stv2_current_tilemap.scrollx && stv2_current_tilemap.scrolly) /* wraparound x & y */
- {
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+0+(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+1-(flipyx&1)+(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+2+(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+mppixels_x,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- drawgfx(bitmap,Machine->gfx[gfx],tilecode+3-(flipyx&1)-(flipyx&2),pal,flipyx&1,flipyx&2,drawxpos+8+mppixels_x,drawypos+8+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- }
- }
- else
- {
- drawgfx(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0);
-
- /* this isn't very efficient .. we could probably improve it */
- if (stv2_current_tilemap.scrollx) /* wraparound x */
- drawgfx(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos+mppixels_x, drawypos,cliprect,stv2_current_tilemap.trans_enabled,0);
- if (stv2_current_tilemap.scrolly) /* wraparound y */
- drawgfx(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- if (stv2_current_tilemap.scrollx && stv2_current_tilemap.scrolly) /* wraparound x & y */
- drawgfx(bitmap,Machine->gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos+mppixels_x, drawypos+mppixels_y,cliprect,stv2_current_tilemap.trans_enabled,0);
- }
- }
-/* DRAWN?! */
-
- }
- }
-}
-
-static void stv_vdp2_check_tilemap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- /* the idea is here we check the tilemap capabilities / whats enabled and call an appropriate tilemap drawing routine, or
- at the very list throw up a few errors if the tilemaps want to do something we don't support yet */
-
- if (stv2_current_tilemap.bitmap_enable) /* this layer is a bitmap*/
- {
- stv_vdp2_draw_basic_bitmap(bitmap, cliprect);
- }
- else
- {
- stv_vdp2_draw_basic_tilemap(bitmap, cliprect);
- }
-}
-
-
-static void stv_vdp2_draw_NBG0(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- /*
- Colours : 16, 256, 2048, 32768, 16770000
- Char Size : 1x1 cells, 2x2 cells
- Pattern Data Size : 1 word, 2 words
- Plane Layouts : 1 x 1, 2 x 1, 2 x 2
- Planes : 4
- Bitmap : Possible
- Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
- Scale : 0.25 x - 256 x
- Rotation : No
- Linescroll : Yes
- Column Scroll : Yes
- Mosaic : Yes
- */
- stv2_current_tilemap.enabled = STV_VDP2_N0ON;
-
-/* if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...*/
-
- stv2_current_tilemap.trans_enabled = STV_VDP2_N0TPON;
- stv2_current_tilemap.colour_depth = STV_VDP2_N0CHCN;
- stv2_current_tilemap.tile_size = STV_VDP2_N0CHSZ;
- stv2_current_tilemap.bitmap_enable = STV_VDP2_N0BMEN;
- stv2_current_tilemap.bitmap_size = STV_VDP2_N0BMSZ;
- stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N0BMP;
- stv2_current_tilemap.bitmap_map = STV_VDP2_N0MP_;
- stv2_current_tilemap.map_offset[0] = STV_VDP2_N0MPA | (STV_VDP2_N0MP_ << 6);
- stv2_current_tilemap.map_offset[1] = STV_VDP2_N0MPB | (STV_VDP2_N0MP_ << 6);
- stv2_current_tilemap.map_offset[2] = STV_VDP2_N0MPC | (STV_VDP2_N0MP_ << 6);
- stv2_current_tilemap.map_offset[3] = STV_VDP2_N0MPD | (STV_VDP2_N0MP_ << 6);
-
- stv2_current_tilemap.pattern_data_size = STV_VDP2_N0PNB;
- stv2_current_tilemap.character_number_supplement = STV_VDP2_N0CNSM;
- stv2_current_tilemap.special_priority_register = STV_VDP2_N0SPR;
- stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN0;
- stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N0SPLT;
- stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N0SPCN;
-
- stv2_current_tilemap.scrollx = STV_VDP2_SCXIN0;
- stv2_current_tilemap.scrolly = STV_VDP2_SCYIN0;
- stv2_current_tilemap.scalex_i = STV_VDP2_N0ZMXI;
- stv2_current_tilemap.scalex_f = STV_VDP2_N0ZMXD;
- stv2_current_tilemap.scaley_i = STV_VDP2_N0ZMYI;
- stv2_current_tilemap.scaley_f = STV_VDP2_N0ZMYD;
-
- stv2_current_tilemap.plane_size = STV_VDP2_N0PLSZ;
- stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N0CAOS;
-
- stv2_current_tilemap.layer_name=0;
-
- stv_vdp2_check_tilemap(bitmap, cliprect);
-}
-
-static void stv_vdp2_draw_NBG1(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- /*
- Colours : 16, 256, 2048, 32768
- Char Size : 1x1 cells, 2x2 cells
- Pattern Data Size : 1 word, 2 words
- Plane Layouts : 1 x 1, 2 x 1, 2 x 2
- Planes : 4
- Bitmap : Possible
- Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
- Scale : 0.25 x - 256 x
- Rotation : No
- Linescroll : Yes
- Column Scroll : Yes
- Mosaic : Yes
- */
- stv2_current_tilemap.enabled = STV_VDP2_N1ON;
-
-/* if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...*/
-
- stv2_current_tilemap.trans_enabled = STV_VDP2_N1TPON;
- stv2_current_tilemap.colour_depth = STV_VDP2_N1CHCN;
- stv2_current_tilemap.tile_size = STV_VDP2_N1CHSZ;
- stv2_current_tilemap.bitmap_enable = STV_VDP2_N1BMEN;
- stv2_current_tilemap.bitmap_size = STV_VDP2_N1BMSZ;
- stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N1BMP;
- stv2_current_tilemap.bitmap_map = STV_VDP2_N1MP_;
- stv2_current_tilemap.map_offset[0] = STV_VDP2_N1MPA | (STV_VDP2_N1MP_ << 6);
- stv2_current_tilemap.map_offset[1] = STV_VDP2_N1MPB | (STV_VDP2_N1MP_ << 6);
- stv2_current_tilemap.map_offset[2] = STV_VDP2_N1MPC | (STV_VDP2_N1MP_ << 6);
- stv2_current_tilemap.map_offset[3] = STV_VDP2_N1MPD | (STV_VDP2_N1MP_ << 6);
-
- stv2_current_tilemap.pattern_data_size = STV_VDP2_N1PNB;
- stv2_current_tilemap.character_number_supplement = STV_VDP2_N1CNSM;
- stv2_current_tilemap.special_priority_register = STV_VDP2_N1SPR;
- stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN1;
- stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N1SPLT;
- stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N1SPCN;
-
- stv2_current_tilemap.scrollx = STV_VDP2_SCXIN1;
- stv2_current_tilemap.scrolly = STV_VDP2_SCYIN1;
- stv2_current_tilemap.scalex_i = STV_VDP2_N1ZMXI;
- stv2_current_tilemap.scalex_f = STV_VDP2_N1ZMXD;
- stv2_current_tilemap.scaley_i = STV_VDP2_N1ZMYI;
- stv2_current_tilemap.scaley_f = STV_VDP2_N1ZMYD;
-
- stv2_current_tilemap.plane_size = STV_VDP2_N1PLSZ;
- stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N1CAOS;
-
- stv2_current_tilemap.layer_name=1;
-
- stv_vdp2_check_tilemap(bitmap, cliprect);
-}
-
-static void stv_vdp2_draw_NBG2(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- /*
- NBG2 is the first of the 2 more basic tilemaps, it has exactly the same capabilities as NBG3
-
- Colours : 16, 256
- Char Size : 1x1 cells, 2x2 cells
- Pattern Data Size : 1 word, 2 words
- Plane Layouts : 1 x 1, 2 x 1, 2 x 2
- Planes : 4
- Bitmap : No
- Bitmap Sizes : N/A
- Scale : No
- Rotation : No
- Linescroll : No
- Column Scroll : No
- Mosaic : Yes
- */
-
- stv2_current_tilemap.enabled = STV_VDP2_N2ON;
-
- /* these modes for N0 disable this layer */
- if (STV_VDP2_N0CHCN == 0x03) stv2_current_tilemap.enabled = 0;
- if (STV_VDP2_N0CHCN == 0x04) stv2_current_tilemap.enabled = 0;
-
-/* if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...*/
-
- stv2_current_tilemap.trans_enabled = STV_VDP2_N2TPON;
- stv2_current_tilemap.trans_enabled = STV_VDP2_N2TPON;
- stv2_current_tilemap.colour_depth = STV_VDP2_N2CHCN;
- stv2_current_tilemap.tile_size = STV_VDP2_N2CHSZ;
- /* this layer can't be a bitmap,so ignore these registers*/
- stv2_current_tilemap.bitmap_enable = 0;
- stv2_current_tilemap.bitmap_size = 0;
- stv2_current_tilemap.bitmap_palette_number = 0;
- stv2_current_tilemap.bitmap_map = 0;
- stv2_current_tilemap.map_offset[0] = STV_VDP2_N2MPA | (STV_VDP2_N2MP_ << 6);
- stv2_current_tilemap.map_offset[1] = STV_VDP2_N2MPB | (STV_VDP2_N2MP_ << 6);
- stv2_current_tilemap.map_offset[2] = STV_VDP2_N2MPC | (STV_VDP2_N2MP_ << 6);
- stv2_current_tilemap.map_offset[3] = STV_VDP2_N2MPD | (STV_VDP2_N2MP_ << 6);
-
- stv2_current_tilemap.pattern_data_size = STV_VDP2_N2PNB;
- stv2_current_tilemap.character_number_supplement = STV_VDP2_N2CNSM;
- stv2_current_tilemap.special_priority_register = STV_VDP2_N2SPR;
- stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN2;
- stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N2SPLT;
- stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N2SPCN;
-
- stv2_current_tilemap.scrollx = STV_VDP2_SCXN2;
- stv2_current_tilemap.scrolly = STV_VDP2_SCYN2;
- /*This layer can't be scaled*/
- stv2_current_tilemap.scalex_i = 1;
- stv2_current_tilemap.scalex_f = 0;
- stv2_current_tilemap.scaley_i = 1;
- stv2_current_tilemap.scaley_f = 0;
-
- stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N2CAOS;
-
- stv2_current_tilemap.layer_name=2;
-
- stv2_current_tilemap.plane_size = STV_VDP2_N2PLSZ;
- stv_vdp2_check_tilemap(bitmap, cliprect);
-}
-
-static void stv_vdp2_draw_NBG3(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- /*
- NBG3 is the second of the 2 more basic tilemaps, it has exactly the same capabilities as NBG2
-
- Colours : 16, 256
- Char Size : 1x1 cells, 2x2 cells
- Pattern Data Size : 1 word, 2 words
- Plane Layouts : 1 x 1, 2 x 1, 2 x 2
- Planes : 4
- Bitmap : No
- Bitmap Sizes : N/A
- Scale : No
- Rotation : No
- Linescroll : No
- Column Scroll : No
- Mosaic : Yes
- */
-
- stv2_current_tilemap.enabled = STV_VDP2_N3ON;
-
-/* if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...*/
-
- stv2_current_tilemap.trans_enabled = STV_VDP2_N3TPON;
- stv2_current_tilemap.trans_enabled = STV_VDP2_N3TPON;
- stv2_current_tilemap.colour_depth = STV_VDP2_N3CHCN;
- stv2_current_tilemap.tile_size = STV_VDP2_N3CHSZ;
- /* this layer can't be a bitmap,so ignore these registers*/
- stv2_current_tilemap.bitmap_enable = 0;
- stv2_current_tilemap.bitmap_size = 0;
- stv2_current_tilemap.bitmap_palette_number = 0;
- stv2_current_tilemap.bitmap_map = 0;
- stv2_current_tilemap.map_offset[0] = STV_VDP2_N3MPA | (STV_VDP2_N3MP_ << 6);
- stv2_current_tilemap.map_offset[1] = STV_VDP2_N3MPB | (STV_VDP2_N3MP_ << 6);
- stv2_current_tilemap.map_offset[2] = STV_VDP2_N3MPC | (STV_VDP2_N3MP_ << 6);
- stv2_current_tilemap.map_offset[3] = STV_VDP2_N3MPD | (STV_VDP2_N3MP_ << 6);
-
- stv2_current_tilemap.pattern_data_size = STV_VDP2_N3PNB;
- stv2_current_tilemap.character_number_supplement = STV_VDP2_N3CNSM;
- stv2_current_tilemap.special_priority_register = STV_VDP2_N3SPR;
- stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN3;
- stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N3SPLT;
- stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N3SPCN;
-
- stv2_current_tilemap.scrollx = STV_VDP2_SCXN3;
- stv2_current_tilemap.scrolly = STV_VDP2_SCYN3;
- /*This layer can't be scaled*/
- stv2_current_tilemap.scalex_i = 1;
- stv2_current_tilemap.scalex_f = 0;
- stv2_current_tilemap.scaley_i = 1;
- stv2_current_tilemap.scaley_f = 0;
-
- stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N3CAOS;
-
- stv2_current_tilemap.layer_name=3;
-
- stv2_current_tilemap.plane_size = STV_VDP2_N3PLSZ;
- stv_vdp2_check_tilemap(bitmap, cliprect);
-}
-
-static void stv_vdp2_draw_back(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
-{
- int xcnt,ycnt;
- data8_t* gfxdata = memory_region(REGION_GFX1);
- static UINT16 *destline;
-
- if(!(STV_VDP2_BDCLMD & 1))
- fillbitmap(bitmap, get_black_pen(), cliprect);
- else
- {
- #ifdef MAME_DEBUG
- /*usrintf_showmessage("Back screen enabled %08x",STV_VDP2_BKTA);*/
- #endif
- gfxdata+=(STV_VDP2_BKTA);
-
- for (ycnt = 0; ycnt <1024;ycnt++)
- {
- destline = (UINT16 *)(bitmap->line[ycnt]);
-
- for (xcnt = 0; xcnt <1024;xcnt++)
- {
- int r,g,b;
-
- b = ((gfxdata[0] & 0x7c) >> 2);
- g = ((gfxdata[0] & 0x03) << 3) | ((gfxdata[1] & 0xe0) >> 5);
- r = ((gfxdata[1] & 0x1f));
-
- destline[xcnt] = b | g << 5 | r << 10;
- }
- if(STV_VDP2_BKCLMD)
- gfxdata+=2;
- }
- }
-}
-
-
-WRITE32_HANDLER ( stv_vdp2_vram_w )
-{
- data8_t *stv_vdp2_vram_decode = memory_region(REGION_GFX1);
-
- COMBINE_DATA(&stv_vdp2_vram[offset]);
-
- data = stv_vdp2_vram[offset];
- /* put in gfx region for easy decoding */
- stv_vdp2_vram_decode[offset*4+0] = (data & 0xff000000) >> 24;
- stv_vdp2_vram_decode[offset*4+1] = (data & 0x00ff0000) >> 16;
- stv_vdp2_vram_decode[offset*4+2] = (data & 0x0000ff00) >> 8;
- stv_vdp2_vram_decode[offset*4+3] = (data & 0x000000ff) >> 0;
-
- stv_vdp2_vram_dirty_8x8x4[offset/8] = 1;
- stv_vdp2_vram_dirty_8x8x8[offset/16] = 1;
-}
-
-READ32_HANDLER ( stv_vdp2_vram_r )
-{
- return stv_vdp2_vram[offset];
-}
-
-
-WRITE32_HANDLER ( stv_vdp2_cram_w )
-{
- int r,g,b;
- COMBINE_DATA(&stv_vdp2_cram[offset]);
-
-/* usrintf_showmessage("%01x",STV_VDP2_CRMD);*/
-
- switch( STV_VDP2_CRMD )
- {
- /*Mode 2/3*/
- case 2:
- case 3:
- {
- b = ((stv_vdp2_cram[offset] & 0x00ff0000) >> 16);
- g = ((stv_vdp2_cram[offset] & 0x0000ff00) >> 8);
- r = ((stv_vdp2_cram[offset] & 0x000000ff) >> 0);
- palette_set_color(offset,r,g,b);
- }
- break;
- /*Mode 0*/
- case 0:
- {
- offset &= 0x3ff;
-
- b = ((stv_vdp2_cram[offset] & 0x00007c00) >> 10);
- g = ((stv_vdp2_cram[offset] & 0x000003e0) >> 5);
- r = ((stv_vdp2_cram[offset] & 0x0000001f) >> 0);
- b*=0x8;
- g*=0x8;
- r*=0x8;
- palette_set_color((offset*2)+1,r,g,b);
- b = ((stv_vdp2_cram[offset] & 0x7c000000) >> 26);
- g = ((stv_vdp2_cram[offset] & 0x03e00000) >> 21);
- r = ((stv_vdp2_cram[offset] & 0x001f0000) >> 16);
- b*=0x8;
- g*=0x8;
- r*=0x8;
- palette_set_color(offset*2,r,g,b);
- }
- break;
- /*Mode 1*/
- case 1:
- {
- offset &= 0x7ff;
-
- b = ((stv_vdp2_cram[offset] & 0x00007c00) >> 10);
- g = ((stv_vdp2_cram[offset] & 0x000003e0) >> 5);
- r = ((stv_vdp2_cram[offset] & 0x0000001f) >> 0);
- b*=0x8;
- g*=0x8;
- r*=0x8;
- palette_set_color((offset*2)+1,r,g,b);
- b = ((stv_vdp2_cram[offset] & 0x7c000000) >> 26);
- g = ((stv_vdp2_cram[offset] & 0x03e00000) >> 21);
- r = ((stv_vdp2_cram[offset] & 0x001f0000) >> 16);
- b*=0x8;
- g*=0x8;
- r*=0x8;
- palette_set_color(offset*2,r,g,b);
- }
- break;
- }
-}
-
-READ32_HANDLER ( stv_vdp2_cram_r )
-{
- return stv_vdp2_cram[offset];
-}
-
-WRITE32_HANDLER ( stv_vdp2_regs_w )
-{
- COMBINE_DATA(&stv_vdp2_regs[offset]);
-}
-
-extern int stv_vblank;
-READ32_HANDLER ( stv_vdp2_regs_r )
-{
-/* if (offset!=1) logerror ("VDP2: Read from Registers, Offset %04x\n",offset);*/
-
- switch(offset)
- {
- case 0x4/4:
- /*Screen Status Register*/
- /*VBLANK HBLANK ODD PAL */
- stv_vdp2_regs[offset] = (stv_vblank<<19) | ((mame_rand_int()&1)<<18) | (1 << 17) | (0 << 16);
- break;
- case 0x8/4:
- /*H/V Counter Register*/
- /*H-Counter V-Counter */
- stv_vdp2_regs[offset] = (((Machine->visible_area.max_x - 1)<<16)&0x3ff)|(((Machine->visible_area.max_y - 1)<<0)&0x3ff);
- log_cb(RETRO_LOG_DEBUG, LOGPRE "CPU #%d PC(%08x) = VDP2: H/V counter read : %08x\n",cpu_getactivecpu(),activecpu_get_pc(),stv_vdp2_regs[offset]);
- break;
- }
- return stv_vdp2_regs[offset];
-}
-
-int stv_vdp2_start ( void )
-{
- stv_vdp2_regs = auto_malloc ( 0x040000 );
- stv_vdp2_vram = auto_malloc ( 0x100000 ); /* actually we only need half of it since we don't emulate extra 4mbit ram cart.*/
- stv_vdp2_cram = auto_malloc ( 0x080000 );
- stv_vdp2_vram_dirty_8x8x4 = auto_malloc ( 0x100000 );
- stv_vdp2_vram_dirty_8x8x8 = auto_malloc ( 0x100000 );
-
- memset(stv_vdp2_regs, 0, 0x040000);
- memset(stv_vdp2_vram, 0, 0x100000);
- memset(stv_vdp2_cram, 0, 0x080000);
-
-/* Machine->gfx[0]->color_granularity=4;*/
-/* Machine->gfx[1]->color_granularity=4;*/
-
- return 0;
-}
-
-/* maybe we should move this to vidhrdw/stv.c */
-VIDEO_START( stv_vdp2 )
-{
- stv_vdp2_start();
- stv_vdp1_start();
-
- return 0;
-}
-
-static void stv_vdp2_dynamic_res_change()
-{
- static UINT16 horz,vert;
-
- switch( STV_VDP2_VRES & 3 )
- {
- case 0: vert = 224; break;
- case 1: vert = 240; break;
- case 2: vert = 256; break;
- case 3:
- log_cb(RETRO_LOG_DEBUG, LOGPRE "WARNING: V Res setting (3) not allowed!\n");
- vert = 256;
- break;
- }
-
- /*Double-density interlace mode,doubles the vertical res*/
- if((STV_VDP2_LSMD & 3) == 3) { vert*=2; }
-
- switch( STV_VDP2_HRES & 7 )
- {
- case 0: horz = 320; break;
- case 1: horz = 352; break;
- case 2: horz = 640; break;
- case 3: horz = 704; break;
- /*Exclusive modes,they sets the Vertical Resolution without considering the
- VRES register.*/
- case 4: horz = 320; vert = 480; break;
- case 5: horz = 352; vert = 480; break;
- case 6: horz = 640; vert = 480; break;
- case 7: horz = 704; vert = 480; break;
- }
-
- set_visible_area(0*8, horz-1,0*8, vert-1);
-}
-
-extern data32_t *stv_vdp1_vram;
-
-VIDEO_UPDATE( stv_vdp2 )
-{
- static UINT8 pri;
-
-/*#ifndef MAME_DEBUG*/
- stv_vdp2_dynamic_res_change();
-/*#endif*/
-
- stv_vdp2_draw_back(bitmap,cliprect);
-
- /*If a plane has a priority value of zero it isn't shown at all.*/
- for(pri=1;pri<8;pri++)
- {
- if (!(keyboard_pressed(KEYCODE_T))) {if(pri==STV_VDP2_N3PRIN) stv_vdp2_draw_NBG3(bitmap,cliprect);}
- if (!(keyboard_pressed(KEYCODE_Y))) {if(pri==STV_VDP2_N2PRIN) stv_vdp2_draw_NBG2(bitmap,cliprect);}
- if (!(keyboard_pressed(KEYCODE_U))) {if(pri==STV_VDP2_N1PRIN) stv_vdp2_draw_NBG1(bitmap,cliprect);}
- if (!(keyboard_pressed(KEYCODE_I))) {if(pri==STV_VDP2_N0PRIN) stv_vdp2_draw_NBG0(bitmap,cliprect);}
- if (!(keyboard_pressed(KEYCODE_O))) {if(pri==6) video_update_vdp1(bitmap,cliprect);}
- }
-
-#ifdef MAME_DEBUG
- if(STV_VDP2_VRAMSZ)
- usrintf_showmessage("Warning: VRAM Size = 8 MBit!");
-
- /*usrintf_showmessage("N0 %02x %04x %02x %04x N1 %02x %04x %02x %04x"
- ,STV_VDP2_N0ZMXI,STV_VDP2_N0ZMXD
- ,STV_VDP2_N0ZMYI,STV_VDP2_N0ZMYD
- ,STV_VDP2_N1ZMXI,STV_VDP2_N1ZMXD
- ,STV_VDP2_N1ZMYI,STV_VDP2_N1ZMYD);*/
-
- if ( keyboard_pressed_memory(KEYCODE_W) )
- {
- int tilecode;
-
- for (tilecode = 0;tilecode<0x8000;tilecode++)
- {
- decodechar(Machine->gfx[0], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[0].gfxlayout); ;
- }
-
- for (tilecode = 0;tilecode<0x2000;tilecode++)
- {
- decodechar(Machine->gfx[1], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[1].gfxlayout); ;
- }
-
- for (tilecode = 0;tilecode<0x4000;tilecode++)
- {
- decodechar(Machine->gfx[2], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[2].gfxlayout); ;
- }
-
- for (tilecode = 0;tilecode<0x1000;tilecode++)
- {
- decodechar(Machine->gfx[3], tilecode, (data8_t*)memory_region(REGION_GFX1), Machine->drv->gfxdecodeinfo[3].gfxlayout); ;
- }
-
- /* vdp 1 ... doesn't have to be tile based */
-
- for (tilecode = 0;tilecode<0x8000;tilecode++)
- {
- decodechar(Machine->gfx[4], tilecode, (data8_t*)memory_region(REGION_GFX2), Machine->drv->gfxdecodeinfo[4].gfxlayout); ;
- }
- for (tilecode = 0;tilecode<0x2000;tilecode++)
- {
- decodechar(Machine->gfx[5], tilecode, (data8_t*)memory_region(REGION_GFX2), Machine->drv->gfxdecodeinfo[5].gfxlayout); ;
- }
- for (tilecode = 0;tilecode<0x4000;tilecode++)
- {
- decodechar(Machine->gfx[6], tilecode, (data8_t*)memory_region(REGION_GFX2), Machine->drv->gfxdecodeinfo[6].gfxlayout); ;
- }
- for (tilecode = 0;tilecode<0x1000;tilecode++)
- {
- decodechar(Machine->gfx[7], tilecode, (data8_t*)memory_region(REGION_GFX2), Machine->drv->gfxdecodeinfo[7].gfxlayout); ;
- }
- }
-#endif
-
-#ifdef MAME_DEBUG
-
- if ( keyboard_pressed_memory(KEYCODE_K) )
- {
- FILE *fp;
-
- fp=fopen("mamevdp1", "w+b");
- if (fp)
- {
- fwrite(stv_vdp1_vram, 0x80000, 1, fp);
- fclose(fp);
- }
- }
-
- if ( keyboard_pressed_memory(KEYCODE_L) )
- {
- FILE *fp;
-
- fp=fopen("vdp1_vram.bin", "r+b");
- if (fp)
- {
- fread(stv_vdp1_vram, 0x80000, 1, fp);
- fclose(fp);
- }
- }
-
-#endif
-
-
-
-}
-
-/* below is some old code we might use .. */
-
-#if 0
-/*
-One of the features of Sega ST-V is that the Color RAM could use two+one
-different formats of Paletteram:
-(1)Mode 0:RGB up to 5 bits per color,for 1024 possible combinations.16-bit format.
-(2)Mode 1:Same as mode 0 but with 2048 possible combinations.
-(3)Mode 2:RGB up to 8 bits per color,for 1024 possible combinations.32-bit format.
-Notice that if it's currently using the mode 0/1,the first three bits (aka bits 0,1 and 2)
-aren't used in output data(they are filled with 0).
-The MSB in any mode is known to be used as "Color Calculation"(transparency).
-
-TODO: we have to refresh the entire palette when it change color mode.
-*/
-
-/**********************************************************************************
-VDP2 Registers Table
-(registers are in 16-bit format,h=high word,l=low word):
-===================================================================================
-0h 00 TV Screen Mode
-0l 02 External Signal Enable Register
-1h 04 Screen Status(VBlank)
-1l 06 Vram Size
-
-2h 08 H Counter
-2l 0a V Counter
-3h 0c < Reserved >
-3l 0e Ram Control
------------------------------------------------------------------------------------
-4h 10 Vram Cycle Pattern (Bank A0) [1/2]
-4l 12 Vram Cycle Pattern (Bank A0) [2/2]
-5h 14 Vram Cycle Pattern (Bank A1) [1/2]
-5l 16 Vram Cycle Pattern (Bank A1) [2/2]
-
-6h 18 Vram Cycle Pattern (Bank B0) [1/2]
-6l 1a Vram Cycle Pattern (Bank B0) [2/2]
-7h 1c Vram Cycle Pattern (Bank B1) [1/2]
-7l 1e Vram Cycle Pattern (Bank B1) [2/2]
------------------------------------------------------------------------------------
-8h 20 Screen Display Enable
-8l 22 Mosaic Control
-9h 24 Special Function Code Select
-9l 26 Special Function Code
-
-10h 28 Character Control (NBG0,NBG1)
-10l 2a Character Control (NBG2,NBG3,RBG0)
-11h 2c Bitmap Palette Number (NBG0, NBG1)
-11l 2e Bitmap Palette Number (RBG0)
------------------------------------------------------------------------------------
-12h 30 Pattern Name Control (NBG0)
-12l 32 Pattern Name Control (NBG1)
-13h 34 Pattern Name Control (NBG2)
-13l 36 Pattern Name Control (NBG3)
-
-14h 38 Pattern Name Control (RBG0)
-14l 3a Plane Size
-15h 3c Map Offset (NBG0-NBG3)
-15l 3e Map Offset (Rotation Parameter A,B)
------------------------------------------------------------------------------------
-16h 40 Map
-16l 42
-17h 44
-17l 46
-
-18h 48
-18l 4a
-19h 4c
-19l 4e
------------------------------------------------------------------------------------
-20h 50 Map (Rotation Parameter A)
-20l 52
-21h 54
-21l 56
-
-22h 58
-22l 5a
-23h 5c
-23l 5e
------------------------------------------------------------------------------------
-24h 60 Map (Rotation Parameter B)
-24l 62
-25h 64
-25l 66
-
-26h 68
-26l 6a
-27h 6c
-27l 6e
------------------------------------------------------------------------------------
-28h 70 Screen Scroll Value (NBG0,H integer)
-28l 72 Screen Scroll Value (NBG0,H fractional)
-29h 74 Screen Scroll Value (NBG0,V integer)
-29l 76 Screen Scroll Value (NBG0,V fractional)
-
-30h 78 Coordinate Increment (NBG0,H integer)
-30l 7a Coordinate Increment (NBG0,H fractional)
-31h 7c Coordinate Increment (NBG0,V integer)
-31l 7e Coordinate Increment (NBG0,V fractional)
------------------------------------------------------------------------------------
-32h 80 Screen Scroll Value (NBG1,H integer)
-32l 82 Screen Scroll Value (NBG1,H fractional)
-33h 84 Screen Scroll Value (NBG1,V integer)
-33l 86 Screen Scroll Value (NBG1,V fractional)
-
-34h 88 Coordinate Increment (NBG1,H integer)
-34l 8a Coordinate Increment (NBG1,H fractional)
-35h 8c Coordinate Increment (NBG1,V integer)
-35l 8e Coordinate Increment (NBG1,V fractional)
------------------------------------------------------------------------------------
-36h 90 Screen Scroll Value (NBG2,H)
-36l 92 Screen Scroll Value (NBG2,V)
-37h 94 Screen Scroll Value (NBG3,H)
-37l 96 Screen Scroll Value (NBG3,V)
-
-38h 98 Reduction Enable
-38l 9a Line and Vertical Cell Scroll Control (NBG0,NBG1)
-39h 9c Vertical Cell Scroll Table Address (NBG0,NBG1) [1/2]
-39l 9e Vertical Cell Scroll Table Address (NBG0,NBG1) [2/2]
------------------------------------------------------------------------------------
-40h a0 Line Scroll Table Address (NBG0) [1/2]
-40l a2 Line Scroll Table Address (NBG0) [2/2]
-41h a4 Line Scroll Table Address (NBG1) [1/2]
-41l a6 Line Scroll Table Address (NBG1) [2/2]
-
-42h a8 Line Color Screen Table Address [1/2]
-42l aa Line Color Screen Table Address [2/2]
-43h ac Back Screen Table Address [1/2]
-43l ae Back Screen Table Address [2/2]
------------------------------------------------------------------------------------
-44h b0 Rotation Parameter Mode
-44l b2 Rotation Parameter Read Control
-45h b4 Coefficient Table Control
-45l b6 Coefficient Table Address Offset
-
-46h b8 Screen Over Pattern Name (Rotation Parameter A)
-46l ba Screen Over Pattern Name (Rotation Parameter B)
-47h bc Rotation Parameter Table Address [1/2]
-47l be Rotation Parameter Table Address [2/2]
------------------------------------------------------------------------------------
-48h c0 Window Position (W0 H start point)
-48l c2 Window Position (W0 H end point)
-49h c4 Window Position (W0 V start point)
-49l c6 Window Position (W0 V end point)
-
-50h c8 Window Position (W1 H start point)
-50l ca Window Position (W1 H end point)
-51h cc Window Position (W1 V start point)
-51l ce Window Position (W1 V end point)
------------------------------------------------------------------------------------
-52h d0 Window Control (NBG0,NBG1)
-52l d2 Window Control (NBG2,NBG3)
-53h d4 Window Control (RBG0,SPRITE)
-53l d6 Window Control (Misc.)
-
-54h d8 Line Window Table Address (W0) [1/2]
-54l da Line Window Table Address (W0) [2/2]
-55h dc Line Window Table Address (W1) [1/2]
-55l de Line Window Table Address (W1) [2/2]
------------------------------------------------------------------------------------
-56h e0 Sprite Control
-56l e2 Shadow Control
-57h e4 Color RAM Address Offset (NBG0-NBG3)
-57l e6 Color RAM Address Offset (RBG0-SPRITE)
-
-58h e8 Line Color Screen Enable
-58l ea Special Priority Mode
-59h ec Color Calculation Control
-59l ee Special Color Calculation Mode
------------------------------------------------------------------------------------
-60h f0 Priority Number (SPRITE)
-60l f2
-61h f4
-61l f6
-
-62h f8 Priority Number (NBG0,NBG1)
-62l fa Priority Number (NBG2,NBG3)
-63h fc Priority Number (RBG0)
-63l fe < Reserved >
------------------------------------------------------------------------------------
-64h 100 Color Calculation Ratio (SPRITE)
-64l 102
-65h 104
-65l 106
-
-66h 108 Color Calculation Ratio (NBG0,NBG1)
-66l 10a Color Calculation Ratio (NBG2,NBG3)
-67h 10c Color Calculation Ratio (RBG0)
-67l 10e Color Calculation Ratio (LINE,BACK)
------------------------------------------------------------------------------------
-68h 110 Color Offset Enable
-68l 112 Color Offset Select
-69h 114 Color Offset A R
-69l 116 Color Offset A G
-
-70h 118 Color Offset A B
-70l 11a Color Offset B R
-71h 11c Color Offset B G
-71l 11e Color Offset B B
------------------------------------------------------------------------------------
-**********************************************************************************/
-
-/*An empty comment at the start of a line means *
- *that the corrispetive bit isn't used by the driver ATM. */
-static READ32_HANDLER ( stv_vdp2_regs_r32 )
-{
-/* if (offset!=1) logerror ("VDP2: Read from Registers, Offset %04x\n",offset);*/
- switch(offset)
- {
- case 1:
- /*Screen Status Register*/
- /*VBLANK & HBLANK(bit 3 & 2 of high word),fake for now*/
- /*VBLANK is always one when the DISP is 0*/
- stv_vdp2_regs[offset] ^= 0x000c0000;
- break;
- case 3:
- /*(V)RAM Control Register*/
- /*Color RAM Mode (bit 13 & 12) (CRMD1 & CRMD0) */
- CRMD = ((stv_vdp2_regs[offset] & 0x00003000) >> 12);
- break;
- }
- return stv_vdp2_regs[offset];
-}
-
-static WRITE32_HANDLER ( stv_vdp2_regs_w32 )
-{
- COMBINE_DATA(&stv_vdp2_regs[offset]);
-
- switch(offset)
- {
- /*r/w*/
- case 0:
- /*TV screen display bit*/
-/**/ DISP = ((stv_vdp2_regs[offset] & 0x80000000) >> 31);
- /*Border Color mode bit*/
- BDCLMD = ((stv_vdp2_regs[offset] & 0x01000000) >> 24);
- /*Interlace mode bit*/
-/**/ LSMD = ((stv_vdp2_regs[offset] & 0x00c00000) >> 22);
- /*Vertical/Horizontal Resolution bits*/
- VRES = ((stv_vdp2_regs[offset] & 0x00300000) >> 20);
- HRES = ((stv_vdp2_regs[offset] & 0x00070000) >> 16);
- res_change();
- break;
- case 3:
- /*Vram mode bits (partitioning)*/
- VRAMD =((stv_vdp2_regs[offset] & 0x00000300) >> 8);
- /*Color RAM mode*/
- CRMD = ((stv_vdp2_regs[offset] & 0x00003000) >> 12);
- break;
- case 4: VCPA0 = (stv_vdp2_regs[4]); break;
- case 5: VCPA1 = (stv_vdp2_regs[5]); break;
- case 6: VCPB0 = (stv_vdp2_regs[6]); break;
- case 7: VCPB1 = (stv_vdp2_regs[7]); break;
- case 8:
- /*Screen Display enable bit*/
-/**/ TPON = ((stv_vdp2_regs[offset] & 0x1f000000) >> 24);
-/**/ SDON = ((stv_vdp2_regs[offset] & 0x003f0000) >> 16);
- break;
- case 10:
- /*Character Control Register*/
- /*These needs to be added into a struct*/
- CHCTLN0 = ((stv_vdp2_regs[offset] & 0x007f0000) >> 16);
- CHCTLN1 = ((stv_vdp2_regs[offset] & 0x3f000000) >> 24);
-/**/ CHCTLN2 = ((stv_vdp2_regs[offset] & 0x00000003) >> 0);
-/**/ CHCTLN3 = ((stv_vdp2_regs[offset] & 0x00000030) >> 4);
- break;
- case 12:
- /*Pattern Name Control Register*/
-/**/ PNCN0 = ((stv_vdp2_regs[offset] & 0xffff0000) >> 16);
-/**/ PNCN1 = ((stv_vdp2_regs[offset] & 0x0000ffff) >> 0);
- break;
- case 13:
-/**/ PNCN2 = ((stv_vdp2_regs[offset] & 0xffff0000) >> 16);
-/**/ PNCN3 = ((stv_vdp2_regs[offset] & 0x0000ffff) >> 0);
- break;
- case 14:
-/**/ PLSZ = ((stv_vdp2_regs[offset] & 0x0000ffff) >> 0);
- break;
- case 43:
-/**/ BKCLMD = ((stv_vdp2_regs[offset] & 0x80000000) >> 31);
-/**/ BKTA = ((stv_vdp2_regs[offset] & 0x0007ffff) >> 0);
- break;
- /* Color Offset Enable/Select Register */
- case 68:
- CLOFEN = ((stv_vdp2_regs[offset] & 0x007f0000) >> 16);
- CLOFSL = ((stv_vdp2_regs[offset] & 0x0000007f) >> 0);
- break;
- case 69:
- /* Color Offset Registers*/
- COAR = ((stv_vdp2_regs[offset] & 0x01ff0000) >> 16);
- COAG = ((stv_vdp2_regs[offset] & 0x000001ff) >> 0);
- break;
- case 70:
- COAB = ((stv_vdp2_regs[offset] & 0x01ff0000) >> 16);
- stv_bright();
- break;
- case 71:
- break;
- }
-}
-
-/*
-**
-** Functions to emulate some aspects of the VDP-2.
-**
-*/
-
-/*This is WRONG,the actual brightness control is much more complex than this...*/
-static void stv_bright()
-{
- double brt = (COAR & 0x100) ? (COAR & 0xff) / 256.0 : (COAR + 0x100) / 256.0;
-
- /*apply only if NBG3 needs it...*/
- if(CLOFEN & 8 && (!(CLOFSL & 8)))
- palette_set_global_brightness(brt);
- else
- palette_set_global_brightness(1.00);
-}
-
-static void stv_dump_ram()
-{
- FILE *fp;
-
- fp=fopen("workraml.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_workram_l, 0x00100000, 1, fp);
- fclose(fp);
- }
- fp=fopen("workramh.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_workram_h, 0x00100000, 1, fp);
- fclose(fp);
- }
- fp=fopen("scu.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_scu, 0xd0, 1, fp);
- fclose(fp);
- }
- fp=fopen("stv_a0_vram.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_a0_vram, 0x00020000, 1, fp);
- fclose(fp);
- }
- fp=fopen("stv_a1_vram.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_a1_vram, 0x00020000, 1, fp);
- fclose(fp);
- }
- fp=fopen("stv_b0_vram.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_b0_vram, 0x00020000, 1, fp);
- fclose(fp);
- }
- fp=fopen("stv_b1_vram.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_b1_vram, 0x00020000, 1, fp);
- fclose(fp);
- }
- fp=fopen("cram.dmp", "w+b");
- if (fp)
- {
- fwrite(stv_cram, 0x00080000, 1, fp);
- fclose(fp);
- }
- fp=fopen("68k.dmp", "w+b");
- if (fp)
- {
- fwrite(memory_region(REGION_CPU3), 0x100000, 1, fp);
- fclose(fp);
- }
-}
-
-
-#endif
diff --git a/src/vidhrdw/stvvid.c b/src/vidhrdw/stvvid.c
new file mode 100644
index 00000000..234c255d
--- /dev/null
+++ b/src/vidhrdw/stvvid.c
@@ -0,0 +1,10555 @@
+/***************************************************************************
+
+ Sega ST-V (Saturn) video: VDP1 and VDP2
+
+ A C port of current MAME's Saturn video (sega/saturn.cpp, VDP1 and VDP2
+ parts, and the CRTC of saturn_vdp2.cpp), by David Haywood, Angelo
+ Salese, Olivier Galibert, Mariusz Wojcieszek and R. Belmont.
+
+ - The VDP1 draws its command list into one of two 16-bit framebuffers,
+ at vblank (automatic draw) or when the PTM register asks for it.
+ - The VDP2 draws the back screen, the normal scroll screens NBG0-3, the
+ rotation screens RBG0/RBG1 (with coefficient tables and windows), the
+ line screen and the VDP1 framebuffer as the sprite layer, by priority,
+ into a 32-bit RGB bitmap.
+ - The tiles are decoded from the VDP2 VRAM into a cache when they are
+ drawn after a write to them (MAME uses its gfx elements for this).
+
+***************************************************************************/
+
+#include "driver.h"
+#include "state.h"
+#include
+#include "includes/stv.h"
+
+
+/***************************************************************************
+ Support for the MAME code: RGB, rectangles, bitmaps, palette, tiles
+***************************************************************************/
+
+/* rgb_t, RGB_RED/GREEN/BLUE and BIT come from the core */
+#define RGB_MAKE(r,g,b) ((((UINT32)(r) & 0xff) << 16) | (((UINT32)(g) & 0xff) << 8) | ((UINT32)(b) & 0xff))
+
+/* memory handler byte lanes (a set mem_mask bit is a byte not accessed) */
+#define ACCESSING_BITS_24_31 (!(mem_mask & 0xff000000))
+#define ACCESSING_BITS_16_23 (!(mem_mask & 0x00ff0000))
+#define ACCESSING_BITS_8_15 (!(mem_mask & 0x0000ff00))
+#define ACCESSING_BITS_0_7 (!(mem_mask & 0x000000ff))
+#define ACCESSING_BITS_16_31 (!(mem_mask & 0xffff0000))
+#define ACCESSING_BITS_0_15 (!(mem_mask & 0x0000ffff))
+
+#define BMP32(bmp, y) ((UINT32 *)(bmp)->line[y])
+
+static INLINE UINT32 stv_alpha_blend_r32(UINT32 d, UINT32 s, UINT8 level)
+{
+ return ((((s & 0x00ff00ff) * level + (d & 0x00ff00ff) * (256 - level)) >> 8) & 0x00ff00ff) |
+ ((((s & 0x0000ff00) * level + (d & 0x0000ff00) * (256 - level)) >> 8) & 0x0000ff00);
+}
+
+static INLINE UINT16 stv_alpha_blend_r16(UINT16 d, UINT16 s, UINT8 level)
+{
+ return ((((s & 0x7c1f) * level + (d & 0x7c1f) * (256 - level)) >> 8) & 0x7c1f) |
+ ((((s & 0x03e0) * level + (d & 0x03e0) * (256 - level)) >> 8) & 0x03e0);
+}
+
+static INLINE UINT32 add_blend_r32(UINT32 d, UINT32 s)
+{
+ UINT32 r = RGB_RED(d) + RGB_RED(s);
+ UINT32 g = RGB_GREEN(d) + RGB_GREEN(s);
+ UINT32 b = RGB_BLUE(d) + RGB_BLUE(s);
+ if (r > 0xff) r = 0xff;
+ if (g > 0xff) g = 0xff;
+ if (b > 0xff) b = 0xff;
+ return RGB_MAKE(r, g, b);
+}
+
+static INLINE INT32 mul_32x32_shift(INT32 a, INT32 b, int shift)
+{
+ return (INT32)(((INT64)a * (INT64)b) >> shift);
+}
+
+static void rect_set(struct rectangle *r, int min_x, int max_x, int min_y, int max_y)
+{
+ r->min_x = min_x;
+ r->max_x = max_x;
+ r->min_y = min_y;
+ r->max_y = max_y;
+}
+
+static void rect_intersect(struct rectangle *r, const struct rectangle *with)
+{
+ if (r->min_x < with->min_x) r->min_x = with->min_x;
+ if (r->max_x > with->max_x) r->max_x = with->max_x;
+ if (r->min_y < with->min_y) r->min_y = with->min_y;
+ if (r->max_y > with->max_y) r->max_y = with->max_y;
+}
+
+static void rect_clip_to_bitmap(struct rectangle *r, const struct mame_bitmap *bitmap)
+{
+ struct rectangle b;
+ rect_set(&b, 0, bitmap->width - 1, 0, bitmap->height - 1);
+ rect_intersect(r, &b);
+}
+
+static void bitmap_fill32(struct mame_bitmap *bitmap, const struct rectangle *clip, UINT32 color)
+{
+ int x, y;
+ for (y = clip->min_y; y <= clip->max_y; y++)
+ {
+ UINT32 *line = BMP32(bitmap, y);
+ for (x = clip->min_x; x <= clip->max_x; x++)
+ line[x] = color;
+ }
+}
+
+#define SWAP_INT(a,b) do { INT32 swap_t_ = (a); (a) = (b); (b) = swap_t_; } while (0)
+#define SWAP_PTR(a,b) do { INT32 *swap_p_ = (a); (a) = (b); (b) = swap_p_; } while (0)
+
+static void popmessage(const char *fmt, ...) { (void)fmt; }
+static void log_masked(int mask, const char *fmt, ...) { (void)mask; (void)fmt; }
+
+#define LOG_VDP2 (1U << 1)
+#define LOG_ROZ (1U << 2)
+
+/*
+ Threaded video: the screen can be drawn in horizontal bands by
+ several threads (the "ST-V Threaded Video" core option). The state a
+ layer keeps while it draws is per thread (VDP2_TLS), the rest is only
+ read while the bands are drawn: the rotation plane caches are brought
+ up to date before, by the main thread alone (VDP2_RENDER_PREPASS).
+*/
+/*
+ As libretro-common (formats/data_transfer.c): no threaded video where
+ there is no native thread-local storage (clang's __has_feature(tls):
+ old Darwin deployment targets) or where GCC emulates it with a lookup
+ per access (the consoles, and MinGW's GCC). Nor with MSVC before 2015,
+ whose builds may run on Windows XP, where __declspec(thread) does not
+ work in a DLL loaded at run time. The state is thread local even with
+ the option off, so an emulated TLS would slow every game down.
+*/
+#if defined(HAVE_THREADS) && !defined(VITA) && !defined(PSP) && !defined(_3DS) && !defined(GEKKO) && \
+ !(defined(__MINGW32__) && !defined(__clang__)) && !(defined(_MSC_VER) && _MSC_VER < 1900)
+#define STV_VIDEO_THREADS 1
+#if defined(__has_feature)
+#if !__has_feature(tls)
+#undef STV_VIDEO_THREADS
+#endif
+#endif
+#endif
+
+#ifdef STV_VIDEO_THREADS
+#if defined(_MSC_VER)
+#define VDP2_TLS __declspec(thread)
+#elif defined(__GNUC__) && !defined(__APPLE__)
+/* static TLS: no call to look it up at each access (the core is a shared */
+/* object), it stays small (a few hundred bytes) to fit when it is loaded */
+#define VDP2_TLS __thread __attribute__((tls_model("initial-exec")))
+#else
+#define VDP2_TLS __thread
+#endif
+#else
+#define VDP2_TLS
+#endif
+
+/* for the core options: is the "ST-V Threaded Video" option of any use here */
+int stv_video_threads_available(void)
+{
+#ifdef STV_VIDEO_THREADS
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+enum
+{
+ VDP2_RENDER_NORMAL = 0, /* one pass, caches and screen */
+ VDP2_RENDER_PREPASS, /* the rotation plane caches only */
+ VDP2_RENDER_BAND /* the screen only, the caches are up to date */
+};
+static int vdp2_render_mode;
+#define VDP1_LOG 0
+
+#define FRAC_SHIFT 16
+
+#define RGB_R(color) ((color) & 0x1f)
+#define RGB_G(color) (((color) >> 5) & 0x1f)
+#define RGB_B(color) (((color) >> 10) & 0x1f)
+
+/* the palette: CRAM colours (0-0x7ff), shadowed (0x800-), highlighted (0x1000-) */
+static rgb_t stv_pens[2048 * 3];
+#define PEN(n) stv_pens[(n)]
+
+static void set_pen(int n, rgb_t color)
+{
+ stv_pens[n] = color;
+}
+
+/* tiles of the VDP2 VRAM as MAME's four gfx elements: 8x8 and 16x16, 4 and 8
+ bits per pixel, each element 32 bytes after the previous one (128 for the
+ 16x16 ones), decoded to one byte per pixel when drawn after a write */
+struct stv_gfx
+{
+ int width, height, bpp;
+ int elements;
+ int inc; /* bytes between elements */
+ int size; /* bytes of an element */
+ int granularity; /* colours per palette bank */
+ int colors; /* palette banks */
+ UINT8 *cache;
+ UINT8 *dirty;
+};
+
+static struct stv_gfx stv_gfx[4];
+
+static const UINT8 *vdp2_gfx_source;
+
+static void gfx_setup(struct stv_gfx *g, int width, int height, int bpp, int inc, int colors)
+{
+ g->width = width;
+ g->height = height;
+ g->bpp = bpp;
+ g->inc = inc;
+ g->size = width * height * bpp / 8;
+ g->elements = 0x100000 / inc;
+ g->granularity = 1 << bpp;
+ g->colors = colors;
+ g->cache = auto_malloc(g->elements * width * height);
+ g->dirty = auto_malloc(g->elements);
+ memset(g->dirty, 1, g->elements);
+}
+
+/* a VRAM byte at addr changed: the elements that contain it are stale */
+static void gfx_mark_dirty_addr(UINT32 addr)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ struct stv_gfx *g = &stv_gfx[i];
+ int last = addr / g->inc;
+ int first = ((int)addr - g->size + 1) < 0 ? 0 : ((int)addr - g->size + 1 + g->inc - 1) / g->inc;
+ int e;
+ for (e = first; e <= last && e < g->elements; e++)
+ g->dirty[e] = 1;
+ }
+}
+
+static void gfx_decode_element(struct stv_gfx *g, int code)
+{
+ const UINT8 *src = vdp2_gfx_source + code * g->inc;
+ UINT8 *dst = g->cache + code * g->width * g->height;
+ int x, y;
+
+ /* the 16x16 tiles are four 8x8 cells: left top, right top, left bottom, right bottom */
+ for (y = 0; y < g->height; y++)
+ for (x = 0; x < g->width; x++)
+ {
+ int cell = (g->width == 16) ? ((y >> 3) * 2 + (x >> 3)) : 0;
+ int cx = x & 7, cy = y & 7;
+ UINT32 offs;
+ UINT8 pix;
+
+ if (g->bpp == 4)
+ {
+ offs = cell * 32 + cy * 4 + (cx >> 1);
+ pix = src[offs & 0xfffff];
+ pix = (cx & 1) ? (pix & 0x0f) : (pix >> 4);
+ }
+ else
+ {
+ offs = cell * 64 + cy * 8 + cx;
+ pix = src[offs & 0xfffff];
+ }
+ *dst++ = pix;
+ }
+}
+
+#ifdef STV_VIDEO_THREADS
+/*
+ While the strips are drawn, a thread that finds an element stale
+ decodes it itself and leaves it marked stale: another thread that
+ reads it decodes it too, writing the same bytes, so no thread reads
+ an element another one is writing. The elements decoded are noted
+ per thread and marked clean once all the strips are drawn.
+*/
+#define VDP2_DECODED_MAX 16384
+static VDP2_TLS int vdp2_band_index = -1;
+static UINT32 *vdp2_band_decoded[4];
+static int vdp2_band_decoded_count[4];
+#endif
+
+static INLINE const UINT8 *gfx_get_data(struct stv_gfx *g, int code)
+{
+ code %= g->elements;
+ if (g->dirty[code])
+ {
+ gfx_decode_element(g, code);
+#ifdef STV_VIDEO_THREADS
+ if (vdp2_band_index >= 0)
+ {
+ int b = vdp2_band_index;
+ if (vdp2_band_decoded[b] && vdp2_band_decoded_count[b] < VDP2_DECODED_MAX)
+ vdp2_band_decoded[b][vdp2_band_decoded_count[b]++] = ((UINT32)(g - stv_gfx) << 24) | (UINT32)code;
+ }
+ else
+#endif
+ g->dirty[code] = 0;
+ }
+ return g->cache + code * g->width * g->height;
+}
+
+#define gfx_element struct stv_gfx
+
+
+/***************************************************************************
+ State
+***************************************************************************/
+
+UINT16 *vdp2_regs;
+UINT32 *vdp2_vram;
+UINT32 *vdp2_cram;
+UINT32 *vdp1_vram;
+UINT16 *vdp1_regs;
+
+struct spoint
+{
+ INT32 x, y;
+ INT32 u, v;
+};
+
+struct shaded_point
+{
+ INT32 x, y;
+ INT32 r, g, b;
+};
+
+static struct
+{
+ UINT16 **framebuffer_display_lines;
+ int framebuffer_mode;
+ int framebuffer_double_interlace;
+ int fbcr_accessed;
+ int framebuffer_width;
+ int framebuffer_height;
+ int framebuffer_current_display;
+ int framebuffer_current_draw;
+ int framebuffer_clear_on_next_frame;
+ struct rectangle system_cliprect;
+ struct rectangle user_cliprect;
+ UINT16 *framebuffer[2];
+ UINT16 **framebuffer_draw_lines;
+ UINT8 *gfx_decode;
+ UINT16 lopr;
+ UINT16 copr;
+ UINT16 ewdr;
+
+ int local_x;
+ int local_y;
+
+ void *draw_end_timer;
+} vdp1;
+
+static struct
+{
+ UINT8 *gfx_decode;
+ struct mame_bitmap *roz_bitmap[2];
+ int old_crmd;
+} vdp2l;
+
+struct vdp1_poly_scanline
+{
+ INT32 x[2];
+ INT32 b[2];
+ INT32 g[2];
+ INT32 r[2];
+ INT32 db;
+ INT32 dg;
+ INT32 dr;
+};
+
+struct vdp1_poly_scanline_data
+{
+ INT32 sy, ey;
+ struct vdp1_poly_scanline scanline[512];
+};
+
+static struct vdp1_poly_scanline_data *vdp1_shading_data;
+
+static struct
+{
+ int CMDCTRL, CMDLINK, CMDPMOD, CMDCOLR, CMDSRCA, CMDSIZE, CMDGRDA;
+ int CMDXA, CMDYA;
+ int CMDXB, CMDYB;
+ int CMDXC, CMDYC;
+ int CMDXD, CMDYD;
+
+ int ispoly;
+} current_sprite;
+
+static struct
+{
+ UINT16 GA;
+ UINT16 GB;
+ UINT16 GC;
+ UINT16 GD;
+} gouraud_shading;
+
+static UINT16 sprite_colorbank;
+
+/* VDP1 framebuffer: the priorities used */
+static VDP2_TLS int vdp1_sprite_priorities_used[8];
+static VDP2_TLS int vdp1_sprite_priorities_usage_valid;
+static UINT8 vdp1_sprite_priorities_in_fb_line[512][8];
+/* the first and last framebuffer x of the pixels of each priority seen on a line */
+static UINT16 vdp1_sprite_priorities_min_x[512][8], vdp1_sprite_priorities_max_x[512][8];
+
+/* a pixel of priority 'p' at (x, y) another pass draws */
+#define SPRITE_PRIORITY_SEEN(p, x, y) do { \
+ UINT8 sp_ = (p); \
+ vdp1_sprite_priorities_used[sp_] = 1; \
+ vdp1_sprite_priorities_in_fb_line[y][sp_] = 1; \
+ if ((x) < vdp1_sprite_priorities_min_x[y][sp_]) vdp1_sprite_priorities_min_x[y][sp_] = (x); \
+ if ((x) > vdp1_sprite_priorities_max_x[y][sp_]) vdp1_sprite_priorities_max_x[y][sp_] = (x); \
+} while (0)
+
+struct vdp2_tilemap_capabilities
+{
+ UINT8 enabled;
+ UINT8 transparency;
+ UINT8 colour_calculation_enabled;
+ UINT8 colour_depth;
+ UINT8 alpha;
+ UINT8 tile_size;
+ UINT8 bitmap_enable;
+ UINT8 bitmap_size;
+ UINT8 bitmap_palette_number;
+ UINT8 bitmap_map;
+ UINT16 map_offset[16];
+ UINT8 map_count;
+
+ UINT8 pattern_data_size;
+ UINT8 character_number_supplement;
+ UINT8 special_priority_register;
+ UINT8 special_colour_control_register;
+ UINT8 supplementary_palette_bits;
+ UINT8 supplementary_character_bits;
+
+ INT16 scrollx;
+ INT16 scrolly;
+ UINT32 incx, incy;
+
+ UINT8 linescroll_enable;
+ UINT8 linescroll_interval;
+ UINT32 linescroll_table_address;
+ UINT8 vertical_linescroll_enable;
+ UINT8 vertical_cell_scroll_enable;
+ UINT8 linezoom_enable;
+
+ UINT8 plane_size;
+ UINT8 colour_ram_address_offset;
+ UINT8 fade_control;
+ struct
+ {
+ UINT8 logic;
+ UINT8 enabled[2];
+ UINT8 area[2];
+ } window_control;
+
+ UINT8 line_screen_enabled;
+ UINT8 mosaic_screen_enabled;
+ int roz_mode3;
+
+ int layer_name; /* just to keep track */
+};
+
+static VDP2_TLS struct vdp2_tilemap_capabilities current_tilemap;
+
+static VDP2_TLS struct
+{
+ INT32 xst;
+ INT32 yst;
+ INT32 zst;
+ INT32 dxst;
+ INT32 dyst;
+ INT32 dx;
+ INT32 dy;
+ INT32 A;
+ INT32 B;
+ INT32 C;
+ INT32 D;
+ INT32 E;
+ INT32 F;
+ INT32 px;
+ INT32 py;
+ INT32 pz;
+ INT32 cx;
+ INT32 cy;
+ INT32 cz;
+ INT32 mx;
+ INT32 my;
+ INT32 kx;
+ INT32 ky;
+ UINT32 kast;
+ INT32 dkast;
+ INT32 dkax;
+} current_rotation_table;
+
+static VDP2_TLS struct
+{
+ UINT32 map_offset_min;
+ UINT32 map_offset_max;
+ UINT32 tile_offset_min;
+ UINT32 tile_offset_max;
+ UINT32 pen_min;
+ UINT32 pen_max;
+} vdp2_layer_data;
+
+static struct
+{
+ UINT8 watch_vdp2_vram_writes;
+ UINT8 is_cache_dirty;
+
+ UINT32 map_offset_min[2];
+ UINT32 map_offset_max[2];
+ UINT32 tile_offset_min[2];
+ UINT32 tile_offset_max[2];
+ UINT32 pen_min[2];
+ UINT32 pen_max[2];
+
+ /* pattern name words written since the last update, redrawn without a full rebuild */
+ UINT32 map_dirty_min[2];
+ UINT32 map_dirty_max[2];
+
+ struct vdp2_tilemap_capabilities layer_data[2];
+} RBG0_cache_data;
+
+/* set while vdp2_draw_basic_tilemap only redraws the cells whose pattern name is in [min, max) */
+static struct
+{
+ int active;
+ UINT32 min, max;
+} vdp2_cell_redraw;
+
+static UINT8 m_vdpdebug_roz;
+
+/* the VDP2 CRTC (saturn_vdp2.cpp) */
+static struct
+{
+ UINT16 tvmd, old_tvmd;
+ int disp, bdclmd, lsmd, vreso, hreso;
+ int odd_bit;
+ UINT16 exten;
+ int exlten, exsyen, dasel, exbgen;
+ int exltfg, exsyfg;
+ UINT16 hcounter_latch, vcounter_latch;
+ int vramsz;
+ int hdisplay, vdisplay;
+ int is_pal;
+} crtc;
+
+#define get_lsmd() (crtc.lsmd)
+#define get_hreso() (crtc.hreso)
+#define get_vramsz() (crtc.vramsz)
+#define get_disp() (crtc.disp)
+#define get_bdclmd() (crtc.bdclmd)
+
+static void (*drawpixel)(int x, int y, int patterndata, int offsetcnt);
+
+static void CEF_1(void) { vdp1_regs[0x010/2] |= 0x0002; }
+static void CEF_0(void) { vdp1_regs[0x010/2] &= ~0x0002; }
+static void BEF_1(void) { vdp1_regs[0x010/2] |= 0x0001; }
+static void BEF_0(void) { vdp1_regs[0x010/2] &= ~0x0001; }
+#define VDP1_TVMR() (vdp1_regs[0x000/2] & 0xffff)
+#define VDP1_VBE() ((VDP1_TVMR() & 0x0008) >> 3)
+#define VDP1_TVM() ((VDP1_TVMR() & 0x0007) >> 0)
+
+/*TV Mode Selection Register */
+/*
+ xxxx xxxx xxxx ---- | UNUSED
+ ---- ---- ---- x--- | VBlank Erase/Write (VBE)
+ ---- ---- ---- -xxx | TV Mode (TVM)
+ TV-Mode:
+ This sets the Frame Buffer size,the rotation of the Frame Buffer & the bit width.
+ bit 2 HDTV disable(0)/enable(1)
+ bit 1 non-rotation/rotation(1)
+ bit 0 16(0)/8(1) bits per pixel
+ Size of the Frame Buffer:
+ 7 invalid
+ 6 invalid
+ 5 invalid
+ 4 512x256
+ 3 512x512
+ 2 512x256
+ 1 1024x256
+ 0 512x256
+*/
+
+/*Frame Buffer Change Mode Register*/
+/*
+ xxxx xxxx xxx- ---- | UNUSED
+ ---- ---- ---x ---- | Even/Odd Coordinate Select Bit (EOS)
+ ---- ---- ---- x--- | Double Interlace Mode (DIE)
+ ---- ---- ---- -x-- | Double Interlace Draw Line (DIL)
+ ---- ---- ---- --x- | Frame Buffer Change Trigger (FCM)
+ ---- ---- ---- ---x | Frame Buffer Change Mode (FCT)
+*/
+#define VDP1_FBCR ((vdp1_regs[0x002/2] >> 0)&0xffff)
+#define VDP1_EOS ((VDP1_FBCR & 0x0010) >> 4)
+#define VDP1_DIE ((VDP1_FBCR & 0x0008) >> 3)
+#define VDP1_DIL ((VDP1_FBCR & 0x0004) >> 2)
+#define VDP1_FCM ((VDP1_FBCR & 0x0002) >> 1)
+#define VDP1_FCT ((VDP1_FBCR & 0x0001) >> 0)
+
+/*Plot Trigger Register*/
+/*
+ xxxx xxxx xxxx xx-- | UNUSED
+ ---- ---- ---- --xx | Plot Trigger Mode (PTM)
+
+ Plot Trigger Mode:
+ 3 Invalid
+ 2 Automatic draw
+ 1 VDP1 draw by request
+ 0 VDP1 Idle (no access)
+*/
+#define VDP1_PTMR ((vdp1_regs[0x004/2])&0xffff)
+#define VDP1_PTM ((VDP1_PTMR & 0x0003) >> 0)
+#define PTM_0 vdp1_regs[0x004/2]&=~0x0001
+
+/*
+ Erase/Write Data Register
+ 16 bpp = data
+ 8 bpp = erase/write data for even/odd X coordinates
+*/
+#define VDP1_EWDR ((vdp1_regs[0x006/2])&0xffff)
+
+/*Erase/Write Upper-Left register*/
+/*
+ x--- ---- ---- ---- | UNUSED
+ -xxx xxx- ---- ---- | X1 register
+ ---- ---x xxxx xxxx | Y1 register
+
+*/
+#define VDP1_EWLR ((vdp1_regs[0x008/2])&0xffff)
+#define VDP1_EWLR_X1 ((VDP1_EWLR & 0x7e00) >> 9)
+#define VDP1_EWLR_Y1 ((VDP1_EWLR & 0x01ff) >> 0)
+/*Erase/Write Lower-Right register*/
+/*
+ xxxx xxx- ---- ---- | X3 register
+ ---- ---x xxxx xxxx | Y3 register
+
+*/
+#define VDP1_EWRR ((vdp1_regs[0x00a/2])&0xffff)
+#define VDP1_EWRR_X3 ((VDP1_EWRR & 0xfe00) >> 9)
+#define VDP1_EWRR_Y3 ((VDP1_EWRR & 0x01ff) >> 0)
+/*Transfer End Status Register*/
+/*
+ xxxx xxxx xxxx xx-- | UNUSED
+ ---- ---- ---- --x- | CEF
+ ---- ---- ---- ---x | BEF
+
+*/
+#define VDP1_EDSR ((vdp1_regs[0x010/2])&0xffff)
+#define VDP1_CEF (VDP1_EDSR & 2)
+#define VDP1_BEF (VDP1_EDSR & 1)
+/**/
+
+
+
+/* bumped at each screen update, see vdp2_get_window0_coordinates */
+static int vdp2_window_cache_gen;
+
+/* prototypes */
+static void vdp2_get_window0_coordinates_calc(int *s_x, int *e_x, int *s_y, int *e_y, int y);
+static void vdp2_get_window1_coordinates_calc(int *s_x, int *e_x, int *s_y, int *e_y, int y);
+static UINT16 vdp1_regs_r(offs_t offset);
+static void vdp1_clear_framebuffer( int which_framebuffer );
+static void vdp1_prepare_framebuffers(void);
+static void vdp1_change_framebuffers(void);
+static void vdp1_set_framebuffer_config(void);
+static void vdp1_regs_w(offs_t offset, UINT16 data, UINT16 mem_mask);
+static UINT32 vdp1_vram_r(offs_t offset);
+static void vdp1_vram_w(offs_t offset, UINT32 data, UINT32 mem_mask);
+static void vdp1_framebuffer0_w(offs_t offset, UINT32 data, UINT32 mem_mask);
+static UINT32 vdp1_framebuffer0_r(offs_t offset, UINT32 mem_mask);
+static void clear_gouraud_shading(void);
+static UINT8 read_gouraud_table(void);
+static INLINE INT32 _shading( INT32 color, INT32 correction );
+static UINT16 vdp1_apply_gouraud_shading( int x, int y, UINT16 pix );
+static void vdp1_setup_shading_for_line( INT32 y, INT32 x1, INT32 x2, INT32 r1, INT32 g1, INT32 b1, INT32 r2, INT32 g2, INT32 b2);
+static void vdp1_setup_shading_for_slope( INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2, INT32 r1, INT32 r2, INT32 slr1, INT32 slr2, INT32 *nr1, INT32 *nr2, INT32 g1, INT32 g2, INT32 slg1, INT32 slg2, INT32 *ng1, INT32 *ng2, INT32 b1, INT32 b2, INT32 slb1, INT32 slb2, INT32 *nb1, INT32 *nb2, INT32 _y1, INT32 y2);
+static void vdp1_setup_shading(const struct spoint* q, const struct rectangle *cliprect);
+static void drawpixel_poly(int x, int y, int patterndata, int offsetcnt);
+static void drawpixel_8bpp_trans(int x, int y, int patterndata, int offsetcnt);
+static void drawpixel_4bpp_notrans(int x, int y, int patterndata, int offsetcnt);
+static void drawpixel_4bpp_trans(int x, int y, int patterndata, int offsetcnt);
+static void drawpixel_generic(int x, int y, int patterndata, int offsetcnt);
+static void vdp1_set_drawpixel(void);
+static void vdp1_fill_slope(const struct rectangle *cliprect, int patterndata, int xsize, INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2, INT32 u1, INT32 u2, INT32 slu1, INT32 slu2, INT32 *nu1, INT32 *nu2, INT32 v1, INT32 v2, INT32 slv1, INT32 slv2, INT32 *nv1, INT32 *nv2, INT32 _y1, INT32 y2);
+static void vdp1_fill_line(const struct rectangle *cliprect, int patterndata, int xsize, INT32 y, INT32 x1, INT32 x2, INT32 u1, INT32 u2, INT32 v1, INT32 v2);
+static void vdp1_fill_quad(const struct rectangle *cliprect, int patterndata, int xsize, const struct spoint *q);
+static int x2s(int v);
+static int y2s(int v);
+static void vdp1_draw_line(const struct rectangle *cliprect);
+static void vdp1_draw_poly_line(const struct rectangle *cliprect);
+static void vdp1_draw_distorted_sprite(const struct rectangle *cliprect);
+static void vdp1_draw_scaled_sprite(const struct rectangle *cliprect);
+static void vdp1_draw_normal_sprite(const struct rectangle *cliprect, int sprite_type);
+static void vdp1_draw_end(int param);
+static void vdp1_process_list(void);
+static void vdp1_video_update(void);
+static void vdp1_state_save_postload(void);
+static int vdp1_start(void);
+static void vdp2_fill_rotation_parameter_table( UINT8 rot_parameter );
+static UINT8 vdp2_is_rotation_applied(void);
+static UINT8 vdp2_are_map_registers_equal(void);
+static void vdp2_check_fade_control_for_layer(void);
+static UINT8 vdp2_check_vram_cycle_pattern_registers( UINT8 access_command_pnmdr, UINT8 access_command_cpdr, UINT8 bitmap_enable );
+static void vdp2_compute_color_offset( int *r, int *g, int *b, int cor );
+static void vdp2_drawgfxzoom( struct mame_bitmap *dest_bmp,const struct rectangle *clip,gfx_element *gfx, UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy, int transparency,int scalex, int scaley, int sprite_screen_width, int sprite_screen_height, int alpha);
+static void vdp2_drawgfxzoom_rgb555( struct mame_bitmap *dest_bmp,const struct rectangle *clip, UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy, int transparency,int scalex, int scaley, int sprite_screen_width, int sprite_screen_height, int alpha);
+static void vdp2_drawgfx_rgb555(struct mame_bitmap *dest_bmp, const struct rectangle *clip, UINT32 code, int flipx, int flipy, int sx, int sy, int transparency, int alpha);
+static void vdp2_drawgfx_rgb888( struct mame_bitmap *dest_bmp, const struct rectangle *clip, UINT32 code, int flipx, int flipy, int sx, int sy, int transparency, int alpha);
+static void vdp2_drawgfx_alpha(struct mame_bitmap *dest_bmp,const struct rectangle *clip,gfx_element *gfx, UINT32 code,UINT32 color, int flipx,int flipy,int offsx,int offsy, int transparency, int alpha);
+static void vdp2_drawgfx_transpen(struct mame_bitmap *dest_bmp,const struct rectangle *clip,gfx_element *gfx, UINT32 code,UINT32 color, int flipx,int flipy,int offsx,int offsy, int transparency);
+static void draw_4bpp_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void draw_8bpp_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void draw_11bpp_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void draw_rgb15_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void draw_rgb32_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_basic_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_get_map_page( int x, int y, int *_map, int *_page );
+static void vdp2_draw_basic_tilemap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_check_tilemap_with_linescroll(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_line(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_mosaic(struct mame_bitmap *bitmap, const struct rectangle *cliprect, UINT8 is_roz);
+static void vdp2_check_tilemap(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_copy_roz_bitmap(struct mame_bitmap *bitmap, struct mame_bitmap *roz_bitmap, const struct rectangle *cliprect, int iRP, int planesizex, int planesizey, int planerenderedsizex, int planerenderedsizey);
+static INLINE int get_roz_window_pixel(int s_x,int e_x,int s_y,int e_y,int x, int y,UINT8 winenable, UINT8 winarea);
+static void vdp2_draw_NBG0(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_NBG1(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_NBG2(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_NBG3(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_rotation_screen(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int iRP);
+static void vdp2_draw_RBG0(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void vdp2_draw_back(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static UINT32 vdp2_vram_r(offs_t offset);
+static void vdp2_vram_w(offs_t offset, UINT32 data, UINT32 mem_mask);
+static UINT16 vdp2_regs_r(offs_t offset);
+static UINT32 vdp2_cram_r(offs_t offset);
+static void vdp2_cram_w(offs_t offset, UINT32 data, UINT32 mem_mask);
+static void refresh_palette_data(void);
+static void vdp2_regs_w(offs_t offset, UINT16 data, UINT16 mem_mask);
+static void vdp2_state_save_postload(void);
+static int vdp2_start(void);
+static void vdp2_fade_effects(void);
+static INLINE void vdp2_get_window0_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y);
+static INLINE void vdp2_get_window1_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y);
+static INLINE int vdp2_window_process(int x,int y);
+static int vdp2_apply_window_on_layer(struct rectangle *cliprect);
+static void draw_sprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect, UINT8 pri);
+static void vdp2_render(struct mame_bitmap *bitmap, const struct rectangle *cliprect);
+static void crtc_init_vcounter_table(void);
+static int crtc_htotal(void);
+static void crtc_reconfigure(void);
+static int crtc_hpos(void);
+static int crtc_get_hcounter(void);
+static int crtc_get_vcounter(void);
+static int crtc_get_hblank(void);
+static int crtc_get_vblank(void);
+static void crtc_tvmd_w(UINT16 data, UINT16 mem_mask);
+static UINT16 crtc_regs_r(int offset);
+static void crtc_regs_w(int offset, UINT16 data, UINT16 mem_mask);
+static void crtc_state_save_postload(void);
+static void crtc_start(void);
+
+static UINT16 vdp1_regs_r(offs_t offset)
+{
+ /*logerror ("%s VDP1: Read from Registers, Offset %04x\n", machine().describe_context(), offset); */
+
+ switch(offset)
+ {
+ case 0x02/2:
+ return 0;
+ case 0x10/2:
+ break;
+ case 0x12/2: return vdp1.lopr;
+ case 0x14/2: return vdp1.copr;
+ /* MODR register, read register for the other VDP1 regs
+ (Shienryu SS version abuses of this during intro) */
+ case 0x16/2:
+ {
+ UINT16 modr;
+
+ modr = 0x1000; /*vdp1 VER */
+ modr |= (VDP1_PTM >> 1) << 8; /* PTM1 */
+ modr |= VDP1_EOS << 7; /* EOS */
+ modr |= VDP1_DIE << 6; /* DIE */
+ modr |= VDP1_DIL << 5; /* DIL */
+ modr |= VDP1_FCM << 4; /*FCM */
+ modr |= VDP1_VBE() << 3; /*VBE */
+ modr |= VDP1_TVM() & 7; /*TVM */
+
+ return modr;
+ }
+ default:
+ break;
+ }
+
+ return vdp1_regs[offset]; /*TODO: write-only regs should return open bus or zero */
+}
+
+/* TODO: TVM & 1 is just a kludgy work-around, the VDP1 actually needs to be rewritten from scratch. */
+/* Daisenryaku Strong Style (daisenss) uses it */
+static void vdp1_clear_framebuffer( int which_framebuffer )
+{
+ int y;
+ int x;
+ int start_x, end_x, start_y, end_y;
+
+ start_x = VDP1_EWLR_X1 * ((VDP1_TVM() & 1) ? 16 : 8);
+ start_y = VDP1_EWLR_Y1 * (vdp1.framebuffer_double_interlace+1);
+ end_x = VDP1_EWRR_X3 * ((VDP1_TVM() & 1) ? 16 : 8);
+ end_y = (VDP1_EWRR_Y3+1) * (vdp1.framebuffer_double_interlace+1);
+/* popmessage("%d %d %d %d %d",VDP1_EWLR_X1,VDP1_EWLR_Y1,VDP1_EWRR_X3,VDP1_EWRR_Y3,vdp1.framebuffer_double_interlace); */
+
+ if(VDP1_TVM() & 1)
+ {
+ for(y=start_y;y 0xdf) && ((offset * 4) < 0x140)) */
+/* { */
+/* logerror("%s: VRAM dword write to %08X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask); */
+/* } */
+
+ data = vdp1_vram[offset];
+ /* put in gfx region for easy decoding */
+ gfx[offset*4+0] = (data & 0xff000000) >> 24;
+ gfx[offset*4+1] = (data & 0x00ff0000) >> 16;
+ gfx[offset*4+2] = (data & 0x0000ff00) >> 8;
+ gfx[offset*4+3] = (data & 0x000000ff) >> 0;
+}
+
+static void vdp1_framebuffer0_w(offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ /*popmessage ("STV VDP1 Framebuffer 0 WRITE offset %08x data %08x",offset, data); */
+ if ( VDP1_TVM() & 1 )
+ {
+ /* 8-bit mode */
+ /*printf("VDP1 8-bit mode %08x %02x\n",offset,data); */
+ if ( ACCESSING_BITS_24_31 )
+ {
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] &= 0x00ff;
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] |= data & 0xff00;
+ }
+ if ( ACCESSING_BITS_16_23 )
+ {
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] &= 0xff00;
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] |= data & 0x00ff;
+ }
+ if ( ACCESSING_BITS_8_15 )
+ {
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1] &= 0x00ff;
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1] |= data & 0xff00;
+ }
+ if ( ACCESSING_BITS_0_7 )
+ {
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1] &= 0xff00;
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1] |= data & 0x00ff;
+ }
+ }
+ else
+ {
+ /* 16-bit mode */
+ if ( ACCESSING_BITS_16_31 )
+ {
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] = (data >> 16) & 0xffff;
+ }
+ if ( ACCESSING_BITS_0_15 )
+ {
+ vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1] = data & 0xffff;
+ }
+ }
+}
+
+static UINT32 vdp1_framebuffer0_r(offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ /*popmessage ("STV VDP1 Framebuffer 0 READ offset %08x",offset); */
+ if ( VDP1_TVM() & 1 )
+ {
+ /* 8-bit mode */
+ /*printf("VDP1 8-bit mode %08x\n",offset); */
+ if ( ACCESSING_BITS_24_31 )
+ result |= ((vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] & 0xff00) << 16);
+ if ( ACCESSING_BITS_16_23 )
+ result |= ((vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] & 0x00ff) << 16);
+ if ( ACCESSING_BITS_8_15 )
+ result |= ((vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1] & 0xff00));
+ if ( ACCESSING_BITS_0_7 )
+ result |= ((vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1] & 0x00ff));
+ }
+ else
+ {
+ /* 16-bit mode */
+ if ( ACCESSING_BITS_16_31 )
+ {
+ result |= (vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2] << 16);
+ }
+ if ( ACCESSING_BITS_0_15 )
+ {
+ result |= (vdp1.framebuffer[vdp1.framebuffer_current_draw][offset*2+1]);
+ }
+
+ }
+
+ return result;
+}
+
+
+/*
+
+there is a command every 0x20 bytes
+the first word is the control word
+the rest are data used by it
+
+---
+00 CMDCTRL
+ e--- ---- ---- ---- | end bit (15)
+ -jjj ---- ---- ---- | jump select bits (12-14)
+ ---- zzzz ---- ---- | zoom point / hotspot (8-11)
+ ---- ---- 00-- ---- | UNUSED
+ ---- ---- --dd ---- | character read direction (4,5)
+ ---- ---- ---- cccc | command bits (0-3)
+
+02 CMDLINK
+ llll llll llll ll-- | link
+ ---- ---- ---- --00 | UNUSED
+
+04 CMDPMOD
+ m--- ---- ---- ---- | MON (looks at MSB and apply shadows etc.)
+ -00- ---- ---- ---- | UNUSED
+ ---h ---- ---- ---- | HSS (High Speed Shrink)
+ ---- p--- ---- ---- | PCLIP (Pre Clipping Disable)
+ ---- -c-- ---- ---- | CLIP (Clipping Mode Bit)
+ ---- --m- ---- ---- | CMOD (User Clipping Enable Bit)
+ ---- ---M ---- ---- | MESH (Mesh Enable Bit)
+ ---- ---- e--- ---- | ECD (End Code Disable)
+ ---- ---- -S-- ---- | SPD (Transparent Pixel Disable)
+ ---- ---- --cc c--- | Colour Mode
+ ---- ---- ---- -CCC | Colour Calculation bits
+ ---- ---- ---- -1-- | Gouraud shading enable
+ ---- ---- ---- --1- | 1/2 original GFX enable
+ ---- ---- ---- ---1 | 1/2 background enable
+
+06 CMDCOLR
+ mmmm mmmm mmmm mmmm | Colour Bank, Colour Lookup /8
+
+08 CMDSRCA (Character Address)
+ aaaa aaaa aaaa aa-- | Character Address
+ ---- ---- ---- --00 | UNUSED
+
+0a CMDSIZE (Character Size)
+ 00-- ---- ---- ---- | UNUSED
+ --xx xxxx ---- ---- | Character Size (X)
+ ---- ---- yyyy yyyy | Character Size (Y)
+
+0c CMDXA (used for normal sprite)
+ eeee ee-- ---- ---- | extension bits
+ ---- --xx xxxx xxxx | x position
+
+0e CMDYA (used for normal sprite)
+ eeee ee-- ---- ---- | extension bits
+ ---- --yy yyyy yyyy | y position
+
+10 CMDXB
+12 CMDYB
+14 CMDXC
+16 CMDYC
+18 CMDXD
+1a CMDYD
+1c CMDGRDA (Gouraud Shading Table)
+1e UNUSED
+---
+
+
+*/
+
+static void clear_gouraud_shading(void)
+{
+ memset(&gouraud_shading, 0, sizeof(gouraud_shading));
+}
+
+static UINT8 read_gouraud_table(void)
+{
+ int gaddr;
+
+ if ( current_sprite.CMDPMOD & 0x4 )
+ {
+ gaddr = current_sprite.CMDGRDA * 8;
+ gouraud_shading.GA = (vdp1_vram[gaddr/4] >> 16) & 0xffff;
+ gouraud_shading.GB = (vdp1_vram[gaddr/4] >> 0) & 0xffff;
+ gouraud_shading.GC = (vdp1_vram[gaddr/4 + 1] >> 16) & 0xffff;
+ gouraud_shading.GD = (vdp1_vram[gaddr/4 + 1] >> 0) & 0xffff;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static INLINE INT32 _shading( INT32 color, INT32 correction )
+{
+ correction = (correction >> 16) & 0x1f;
+ color += (correction - 16);
+
+ if ( color < 0 ) color = 0;
+ if ( color > 0x1f ) color = 0x1f;
+
+ return color;
+}
+
+static UINT16 vdp1_apply_gouraud_shading( int x, int y, UINT16 pix )
+{
+ INT32 r,g,b, msb;
+
+ msb = pix & 0x8000;
+
+#ifdef MAME_DEBUG
+ if ( (vdp1_shading_data->scanline[y].x[0] >> 16) != x )
+ {
+ logerror( "ERROR in computing x coordinates (line %d, x = %x, %d, xc = %x, %d)\n", y, x, x, vdp1_shading_data->scanline[y].x[0], vdp1_shading_data->scanline[y].x[0] >> 16 );
+ };
+#endif
+
+ b = RGB_B(pix);
+ g = RGB_G(pix);
+ r = RGB_R(pix);
+
+ b = _shading( b, vdp1_shading_data->scanline[y].b[0] );
+ g = _shading( g, vdp1_shading_data->scanline[y].g[0] );
+ r = _shading( r, vdp1_shading_data->scanline[y].r[0] );
+
+ vdp1_shading_data->scanline[y].b[0] += vdp1_shading_data->scanline[y].db;
+ vdp1_shading_data->scanline[y].g[0] += vdp1_shading_data->scanline[y].dg;
+ vdp1_shading_data->scanline[y].r[0] += vdp1_shading_data->scanline[y].dr;
+
+ vdp1_shading_data->scanline[y].x[0] += 1 << FRAC_SHIFT;
+
+ return msb | b << 10 | g << 5 | r;
+}
+
+static void vdp1_setup_shading_for_line(
+ INT32 y, INT32 x1, INT32 x2,
+ INT32 r1, INT32 g1, INT32 b1,
+ INT32 r2, INT32 g2, INT32 b2)
+{
+ int xx1 = x1>>FRAC_SHIFT;
+ int xx2 = x2>>FRAC_SHIFT;
+
+
+ if ( xx1 > xx2 )
+ {
+ SWAP_INT(xx1, xx2);
+ SWAP_INT(r1, r2);
+ SWAP_INT(g1, g2);
+ SWAP_INT(b1, b2);
+ }
+
+ if ( (y >= 0) && (y < 512) )
+ {
+ INT32 dx;
+ INT32 gbd, ggd, grd;
+
+ dx = xx2 - xx1;
+
+ if ( dx == 0 )
+ {
+ gbd = ggd = grd = 0;
+ }
+ else
+ {
+ gbd = abs(b2 - b1) / dx;
+ if (b2 < b1) gbd = -gbd;
+ ggd = abs(g2 - g1) / dx;
+ if (g2 < g1) ggd = -ggd;
+ grd = abs(r2 - r1) / dx;
+ if (r2 < r1) grd = -grd;
+ }
+
+ vdp1_shading_data->scanline[y].x[0] = x1;
+ vdp1_shading_data->scanline[y].x[1] = x2;
+
+ vdp1_shading_data->scanline[y].b[0] = b1;
+ vdp1_shading_data->scanline[y].g[0] = g1;
+ vdp1_shading_data->scanline[y].r[0] = r1;
+ vdp1_shading_data->scanline[y].b[1] = b2;
+ vdp1_shading_data->scanline[y].g[1] = g2;
+ vdp1_shading_data->scanline[y].r[1] = r2;
+
+ vdp1_shading_data->scanline[y].db = gbd;
+ vdp1_shading_data->scanline[y].dg = ggd;
+ vdp1_shading_data->scanline[y].dr = grd;
+
+ }
+}
+
+static void vdp1_setup_shading_for_slope(
+ INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2,
+ INT32 r1, INT32 r2, INT32 slr1, INT32 slr2, INT32 *nr1, INT32 *nr2,
+ INT32 g1, INT32 g2, INT32 slg1, INT32 slg2, INT32 *ng1, INT32 *ng2,
+ INT32 b1, INT32 b2, INT32 slb1, INT32 slb2, INT32 *nb1, INT32 *nb2,
+ INT32 _y1, INT32 y2)
+{
+ if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
+ SWAP_INT(x1, x2);
+ SWAP_INT(sl1, sl2);
+ SWAP_PTR(nx1, nx2);
+ SWAP_INT(r1, r2);
+ SWAP_INT(slr1, slr2);
+ SWAP_PTR(nr1, nr2);
+ SWAP_INT(g1, g2);
+ SWAP_INT(slg1, slg2);
+ SWAP_PTR(ng1, ng2);
+ SWAP_INT(b1, b2);
+ SWAP_INT(slb1, slb2);
+ SWAP_PTR(nb1, nb2);
+ }
+
+ while(_y1 < y2)
+ {
+ vdp1_setup_shading_for_line(_y1, x1, x2, r1, g1, b1, r2, g2, b2);
+ x1 += sl1;
+ r1 += slr1;
+ g1 += slg1;
+ b1 += slb1;
+
+ x2 += sl2;
+ r2 += slr2;
+ g2 += slg2;
+ b2 += slb2;
+ _y1++;
+ }
+ *nx1 = x1;
+ *nr1 = r1;
+ *ng1 = g1;
+ *nb1 = b1;
+
+ *nx2 = x2;
+ *nr2 = r2;
+ *nb2 = b2;
+ *ng2 = g2;
+}
+
+static void vdp1_setup_shading(const struct spoint* q, const struct rectangle *cliprect)
+{
+ INT32 x1, x2, delta, cury, limy;
+ INT32 r1, g1, b1, r2, g2, b2;
+ INT32 sl1, slg1, slb1, slr1;
+ INT32 sl2, slg2, slb2, slr2;
+ int pmin, pmax, i, ps1, ps2;
+ struct shaded_point p[8];
+ UINT16 gd[4];
+
+ if ( read_gouraud_table() == 0 ) return;
+
+ gd[0] = gouraud_shading.GA;
+ gd[1] = gouraud_shading.GB;
+ gd[2] = gouraud_shading.GC;
+ gd[3] = gouraud_shading.GD;
+
+ for(i=0; i<4; i++) {
+ p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT;
+ p[i].y = p[i+4].y = q[i].y;
+ p[i].r = p[i+4].r = RGB_R(gd[i]) << FRAC_SHIFT;
+ p[i].g = p[i+4].g = RGB_G(gd[i]) << FRAC_SHIFT;
+ p[i].b = p[i+4].b = RGB_B(gd[i]) << FRAC_SHIFT;
+ }
+
+ pmin = pmax = 0;
+ for(i=1; i<4; i++) {
+ if(p[i].y < p[pmin].y)
+ pmin = i;
+ if(p[i].y > p[pmax].y)
+ pmax = i;
+ }
+
+ cury = p[pmin].y;
+ limy = p[pmax].y;
+
+ vdp1_shading_data->sy = cury;
+ vdp1_shading_data->ey = limy;
+
+ if(cury == limy) {
+ x1 = x2 = p[0].x;
+ ps1 = ps2 = 0;
+ for(i=1; i<4; i++) {
+ if(p[i].x < x1) {
+ x1 = p[i].x;
+ ps1 = i;
+ }
+ if(p[i].x > x2) {
+ x2 = p[i].x;
+ ps2 = i;
+ }
+ }
+ vdp1_setup_shading_for_line(cury, x1, x2, p[ps1].r, p[ps1].g, p[ps1].b, p[ps2].r, p[ps2].g, p[ps2].b);
+ goto finish;
+ }
+
+ ps1 = pmin+4;
+ ps2 = pmin;
+
+ goto startup;
+
+ for(;;) {
+ if(p[ps1-1].y == p[ps2+1].y) {
+ vdp1_setup_shading_for_slope(
+ x1, x2, sl1, sl2, &x1, &x2,
+ r1, r2, slr1, slr2, &r1, &r2,
+ g1, g2, slg1, slg2, &g1, &g2,
+ b1, b2, slb1, slb2, &b1, &b2,
+ cury, p[ps1-1].y);
+ cury = p[ps1-1].y;
+ if(cury >= limy)
+ break;
+ ps1--;
+ ps2++;
+
+ startup:
+ while(p[ps1-1].y == cury)
+ ps1--;
+ while(p[ps2+1].y == cury)
+ ps2++;
+ x1 = p[ps1].x;
+ r1 = p[ps1].r;
+ g1 = p[ps1].g;
+ b1 = p[ps1].b;
+ x2 = p[ps2].x;
+ r2 = p[ps2].r;
+ g2 = p[ps2].g;
+ b2 = p[ps2].b;
+
+ delta = cury-p[ps1-1].y;
+ sl1 = (x1-p[ps1-1].x)/delta;
+ slr1 = (r1-p[ps1-1].r)/delta;
+ slg1 = (g1-p[ps1-1].g)/delta;
+ slb1 = (b1-p[ps1-1].b)/delta;
+
+ delta = cury-p[ps2+1].y;
+ sl2 = (x2-p[ps2+1].x)/delta;
+ slr2 = (r2-p[ps2+1].r)/delta;
+ slg2 = (g2-p[ps2+1].g)/delta;
+ slb2 = (b2-p[ps2+1].b)/delta;
+ } else if(p[ps1-1].y < p[ps2+1].y) {
+ vdp1_setup_shading_for_slope(
+ x1, x2, sl1, sl2, &x1, &x2,
+ r1, r2, slr1, slr2, &r1, &r2,
+ g1, g2, slg1, slg2, &g1, &g2,
+ b1, b2, slb1, slb2, &b1, &b2,
+ cury, p[ps1-1].y);
+ cury = p[ps1-1].y;
+ if(cury >= limy)
+ break;
+ ps1--;
+ while(p[ps1-1].y == cury)
+ ps1--;
+ x1 = p[ps1].x;
+ r1 = p[ps1].r;
+ g1 = p[ps1].g;
+ b1 = p[ps1].b;
+
+ delta = cury-p[ps1-1].y;
+ sl1 = (x1-p[ps1-1].x)/delta;
+ slr1 = (r1-p[ps1-1].r)/delta;
+ slg1 = (g1-p[ps1-1].g)/delta;
+ slb1 = (b1-p[ps1-1].b)/delta;
+ } else {
+ vdp1_setup_shading_for_slope(
+ x1, x2, sl1, sl2, &x1, &x2,
+ r1, r2, slr1, slr2, &r1, &r2,
+ g1, g2, slg1, slg2, &g1, &g2,
+ b1, b2, slb1, slb2, &b1, &b2,
+ cury, p[ps2+1].y);
+ cury = p[ps2+1].y;
+ if(cury >= limy)
+ break;
+ ps2++;
+ while(p[ps2+1].y == cury)
+ ps2++;
+ x2 = p[ps2].x;
+ r2 = p[ps2].r;
+ g2 = p[ps2].g;
+ b2 = p[ps2].b;
+
+ delta = cury-p[ps2+1].y;
+ sl2 = (x2-p[ps2+1].x)/delta;
+ slr2 = (r2-p[ps2+1].r)/delta;
+ slg2 = (g2-p[ps2+1].g)/delta;
+ slb2 = (b2-p[ps2+1].b)/delta;
+ }
+ }
+ if(cury == limy)
+ vdp1_setup_shading_for_line(cury, x1, x2, r1, g1, b1, r2, g2, b2 );
+
+finish:
+
+ if ( vdp1_shading_data->sy < 0 ) vdp1_shading_data->sy = 0;
+ if ( vdp1_shading_data->sy >= 512 ) return;
+ if ( vdp1_shading_data->ey < 0 ) return;
+ if ( vdp1_shading_data->ey >= 512 ) vdp1_shading_data->ey = 511;
+
+ for ( cury = vdp1_shading_data->sy; cury <= vdp1_shading_data->ey; cury++ )
+ {
+ while( (vdp1_shading_data->scanline[cury].x[0] >> 16) < cliprect->min_x )
+ {
+ vdp1_shading_data->scanline[cury].x[0] += (1 << FRAC_SHIFT);
+ vdp1_shading_data->scanline[cury].b[0] += vdp1_shading_data->scanline[cury].db;
+ vdp1_shading_data->scanline[cury].g[0] += vdp1_shading_data->scanline[cury].dg;
+ vdp1_shading_data->scanline[cury].r[0] += vdp1_shading_data->scanline[cury].dr;
+ }
+ }
+
+}
+
+/* note that if we're drawing
+to the framebuffer we CAN'T frameskip the vdp1 drawing as the hardware can READ the framebuffer
+and if we skip the drawing the content could be incorrect when it reads it, although i have no idea
+why they would want to */
+
+
+
+static void drawpixel_poly(int x, int y, int patterndata, int offsetcnt)
+{
+ /* Capcom Collection Dai 4 uses a dummy polygon to clear VDP1 framebuffer that goes over our current max size ... */
+ if(x >= 1024 || y >= 512)
+ return;
+
+ vdp1.framebuffer_draw_lines[y][x] = current_sprite.CMDCOLR;
+}
+
+static void drawpixel_8bpp_trans(int x, int y, int patterndata, int offsetcnt)
+{
+ UINT16 pix;
+
+ pix = vdp1.gfx_decode[patterndata+offsetcnt] & 0xff;
+ if ( pix != 0 )
+ {
+ vdp1.framebuffer_draw_lines[y][x] = pix | sprite_colorbank;
+ }
+}
+
+static void drawpixel_4bpp_notrans(int x, int y, int patterndata, int offsetcnt)
+{
+ UINT16 pix;
+
+ pix = vdp1.gfx_decode[patterndata+offsetcnt/2];
+ pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
+ vdp1.framebuffer_draw_lines[y][x] = pix | sprite_colorbank;
+}
+
+static void drawpixel_4bpp_trans(int x, int y, int patterndata, int offsetcnt)
+{
+ UINT16 pix;
+
+ pix = vdp1.gfx_decode[patterndata+offsetcnt/2];
+ pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
+ if ( pix != 0 )
+ vdp1.framebuffer_draw_lines[y][x] = pix | sprite_colorbank;
+}
+
+static void drawpixel_generic(int x, int y, int patterndata, int offsetcnt)
+{
+ int pix,transpen, spd = current_sprite.CMDPMOD & 0x40;
+/* int mode; */
+ int mesh = current_sprite.CMDPMOD & 0x100;
+ int raw,endcode;
+
+ if ( mesh && !((x ^ y) & 1) )
+ {
+ return;
+ }
+
+ if(x >= 1024 || y >= 512)
+ return;
+
+ if ( current_sprite.ispoly )
+ {
+ raw = pix = current_sprite.CMDCOLR&0xffff;
+
+ transpen = 0;
+ endcode = 0xffff;
+ #if 0
+ if ( pix & 0x8000 )
+ {
+ mode = 5;
+ }
+ else
+ {
+ mode = 1;
+ }
+ #endif
+ }
+ else
+ {
+ switch (current_sprite.CMDPMOD&0x0038)
+ {
+ case 0x0000: /* mode 0 16 colour bank mode (4bits) (hanagumi blocks) */
+ /* most of the shienryu sprites use this mode */
+ raw = vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff];
+ raw = offsetcnt&1 ? (raw & 0x0f) : ((raw & 0xf0)>>4);
+ pix = raw+((current_sprite.CMDCOLR&0xfff0));
+ /*mode = 0; */
+ transpen = 0;
+ endcode = 0xf;
+ break;
+ case 0x0008: /* mode 1 16 colour lookup table mode (4bits) */
+ /* shienryu explosions (and some enemies) use this mode */
+ raw = vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff];
+ raw = offsetcnt&1 ? (raw & 0x0f) : ((raw & 0xf0)>>4);
+ pix = raw&1 ?
+ ((((vdp1_vram[(((current_sprite.CMDCOLR&0xffff)*8)>>2)+((raw&0xfffe)/2)])) & 0x0000ffff) >> 0):
+ ((((vdp1_vram[(((current_sprite.CMDCOLR&0xffff)*8)>>2)+((raw&0xfffe)/2)])) & 0xffff0000) >> 16);
+ /*mode = 5; */
+ transpen = 0;
+ endcode = 0xf;
+ break;
+ case 0x0010: /* mode 2 64 colour bank mode (8bits) (character select portraits on hanagumi) */
+ raw = vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff;
+ /*mode = 2; */
+ pix = raw+(current_sprite.CMDCOLR&0xffc0);
+ transpen = 0;
+ endcode = 0xff;
+ /* Notes of interest: */
+ /* Scud: the disposable assassin wants transparent pen on 0 */
+ /* sasissu: racing stage background clouds */
+ break;
+ case 0x0018: /* mode 3 128 colour bank mode (8bits) (little characters on hanagumi use this mode) */
+ raw = vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff;
+ pix = raw+(current_sprite.CMDCOLR&0xff80);
+ transpen = 0;
+ endcode = 0xff;
+ /*mode = 3; */
+ break;
+ case 0x0020: /* mode 4 256 colour bank mode (8bits) (hanagumi title) */
+ raw = vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff;
+ pix = raw+(current_sprite.CMDCOLR&0xff00);
+ transpen = 0;
+ endcode = 0xff;
+ /*mode = 4; */
+ break;
+ case 0x0028: /* mode 5 32,768 colour RGB mode (16bits) */
+ raw = vdp1.gfx_decode[(patterndata+offsetcnt*2+1) & 0xfffff] | (vdp1.gfx_decode[(patterndata+offsetcnt*2) & 0xfffff]<<8);
+ /*mode = 5; */
+ /* TODO: 0x1-0x7ffe reserved (color bank) */
+ pix = raw;
+ transpen = 0;
+ endcode = 0x7fff;
+ break;
+ case 0x0038: /* invalid */
+ /* game tengoku uses this on hi score screen (tate mode) */
+ /* according to Charles, reads from VRAM address 0 */
+ raw = pix = vdp1.gfx_decode[1] | (vdp1.gfx_decode[0]<<8) ;
+ /* TODO: check transpen */
+ transpen = 0;
+ endcode = -1;
+ break;
+ default: /* other settings illegal */
+ pix = mame_rand_video();
+ raw = pix & 0xff; /* just mimic old driver behavior */
+ /*mode = 0; */
+ transpen = 0;
+ endcode = 0xff;
+ popmessage("Illegal Sprite Mode %02x",current_sprite.CMDPMOD&0x0038);
+ }
+
+
+ /* preliminary end code disable support */
+ if ( ((current_sprite.CMDPMOD & 0x80) == 0) &&
+ (raw == endcode) )
+ {
+ return;
+ }
+ }
+
+ /* MSBON */
+ /* TODO: does this always applies to the frame buffer regardless of the mode? */
+ pix |= current_sprite.CMDPMOD & 0x8000;
+ /*
+ TODO: from docs:
+ "Except for the color calculation of replace and shadow, color calculation can only be performed when the color code of the original picture is RGB code.
+ Color calculation can be executed when the color code is color bank code, but the results are not guaranteed."
+ Currently no idea about the "result not guaranteed" part, let's disable this branch for the time being ...
+ */
+ #if 0
+ if ( mode != 5 )
+ {
+ if ( (raw != transpen) || spd )
+ {
+ vdp1.framebuffer_draw_lines[y][x] = pix;
+ }
+ }
+ else
+ #endif
+ {
+ if ( (raw != transpen) || spd )
+ {
+ if ( current_sprite.CMDPMOD & 0x4 ) /* Gouraud shading */
+ pix = vdp1_apply_gouraud_shading( x, y, pix );
+
+ switch( current_sprite.CMDPMOD & 0x3 )
+ {
+ case 0: /* replace */
+ vdp1.framebuffer_draw_lines[y][x] = pix;
+ break;
+ case 1: /* shadow */
+ if ( vdp1.framebuffer_draw_lines[y][x] & 0x8000 )
+ {
+ vdp1.framebuffer_draw_lines[y][x] = ((vdp1.framebuffer_draw_lines[y][x] & ~0x8421) >> 1) | 0x8000;
+ }
+ break;
+ case 2: /* half luminance */
+ vdp1.framebuffer_draw_lines[y][x] = ((pix & ~0x8421) >> 1) | 0x8000;
+ break;
+ case 3: /* half transparent */
+ if ( vdp1.framebuffer_draw_lines[y][x] & 0x8000 )
+ {
+ vdp1.framebuffer_draw_lines[y][x] = stv_alpha_blend_r16( vdp1.framebuffer_draw_lines[y][x], pix, 0x80 ) | 0x8000;
+ }
+ else
+ {
+ vdp1.framebuffer_draw_lines[y][x] = pix;
+ }
+ break;
+ /*case 4: Gouraud shading */
+ /* TODO: proyakts (during team creation, on PR girl select) */
+ /*case 6: */
+ /* break; */
+ /*case 7: Gouraud-shading + half-transparent */
+ /* lupinpy enemy shadows */
+ /* deathcri lives indicators */
+ /* TODO: latter looks really bad. */
+ default:
+ /* TODO: mode 5: prohibited, mode 6: gouraud shading + half-luminance, mode 7: gouraud-shading + half-transparent */
+ popmessage("VDP1 PMOD = %02x",current_sprite.CMDPMOD & 0x7);
+ vdp1.framebuffer_draw_lines[y][x] = pix;
+ break;
+ }
+ }
+ }
+}
+
+
+static void vdp1_set_drawpixel(void)
+{
+ int sprite_type = current_sprite.CMDCTRL & 0x000f;
+ int sprite_mode = current_sprite.CMDPMOD&0x0038;
+ int spd = current_sprite.CMDPMOD & 0x40;
+ int mesh = current_sprite.CMDPMOD & 0x100;
+ int ecd = current_sprite.CMDPMOD & 0x80;
+
+ if ( mesh || !ecd || ((current_sprite.CMDPMOD & 0x7) != 0) )
+ {
+ drawpixel = drawpixel_generic;
+ return;
+ }
+
+ if(current_sprite.CMDPMOD & 0x8000)
+ {
+ drawpixel = drawpixel_generic;
+ return;
+ }
+
+ /* polygon / polyline / line with replace case */
+ if (sprite_type & 4 && ((current_sprite.CMDPMOD & 0x7) == 0))
+ {
+ drawpixel = drawpixel_poly;
+ }
+ else if ( (sprite_mode == 0x20) && !spd )
+ {
+ sprite_colorbank = (current_sprite.CMDCOLR&0xff00);
+ drawpixel = drawpixel_8bpp_trans;
+ }
+ else if ((sprite_mode == 0x00) && spd)
+ {
+ sprite_colorbank = (current_sprite.CMDCOLR&0xfff0);
+ drawpixel = drawpixel_4bpp_notrans;
+ }
+ else if (sprite_mode == 0x00 && !spd )
+ {
+ sprite_colorbank = (current_sprite.CMDCOLR&0xfff0);
+ drawpixel = drawpixel_4bpp_trans;
+ }
+ else
+ {
+ drawpixel = drawpixel_generic;
+ }
+}
+
+
+static void vdp1_fill_slope(const struct rectangle *cliprect, int patterndata, int xsize,
+ INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2,
+ INT32 u1, INT32 u2, INT32 slu1, INT32 slu2, INT32 *nu1, INT32 *nu2,
+ INT32 v1, INT32 v2, INT32 slv1, INT32 slv2, INT32 *nv1, INT32 *nv2,
+ INT32 _y1, INT32 y2)
+{
+ if(_y1 > cliprect->max_y)
+ return;
+
+ if(y2 <= cliprect->min_y) {
+ int delta = y2-_y1;
+ *nx1 = x1+delta*sl1;
+ *nu1 = u1+delta*slu1;
+ *nv1 = v1+delta*slv1;
+ *nx2 = x2+delta*sl2;
+ *nu2 = u2+delta*slu2;
+ *nv2 = v2+delta*slv2;
+ return;
+ }
+
+ if(y2 > cliprect->max_y)
+ y2 = cliprect->max_y+1;
+
+ if(_y1 < cliprect->min_y) {
+ int delta = cliprect->min_y - _y1;
+ x1 += delta*sl1;
+ u1 += delta*slu1;
+ v1 += delta*slv1;
+ x2 += delta*sl2;
+ u2 += delta*slu2;
+ v2 += delta*slv2;
+ _y1 = cliprect->min_y;
+ }
+
+ if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
+ INT32 t, *tp;
+ t = x1;
+ x1 = x2;
+ x2 = t;
+ t = sl1;
+ sl1 = sl2;
+ sl2 = t;
+ tp = nx1;
+ nx1 = nx2;
+ nx2 = tp;
+
+ t = u1;
+ u1 = u2;
+ u2 = t;
+ t = slu1;
+ slu1 = slu2;
+ slu2 = t;
+ tp = nu1;
+ nu1 = nu2;
+ nu2 = tp;
+
+ t = v1;
+ v1 = v2;
+ v2 = t;
+ t = slv1;
+ slv1 = slv2;
+ slv2 = t;
+ tp = nv1;
+ nv1 = nv2;
+ nv2 = tp;
+ }
+
+ while(_y1 < y2) {
+ if(_y1 >= cliprect->min_y) {
+ INT32 slux = 0, slvx = 0;
+ int xx1 = x1>>FRAC_SHIFT;
+ int xx2 = x2>>FRAC_SHIFT;
+ INT32 u = u1;
+ INT32 v = v1;
+ if(xx1 != xx2) {
+ int delta = xx2-xx1;
+ slux = (u2-u1)/delta;
+ slvx = (v2-v1)/delta;
+ }
+ if(xx1 <= cliprect->max_x || xx2 >= cliprect->min_x) {
+ if(xx1 < cliprect->min_x) {
+ int delta = cliprect->min_x-xx1;
+ u += slux*delta;
+ v += slvx*delta;
+ xx1 = cliprect->min_x;
+ }
+ if(xx2 > cliprect->max_x)
+ xx2 = cliprect->max_x;
+
+ while(xx1 <= xx2) {
+ drawpixel(xx1,_y1, patterndata, (v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
+ xx1++;
+ u += slux;
+ v += slvx;
+ }
+ }
+ }
+
+ x1 += sl1;
+ u1 += slu1;
+ v1 += slv1;
+ x2 += sl2;
+ u2 += slu2;
+ v2 += slv2;
+ _y1++;
+ }
+ *nx1 = x1;
+ *nu1 = u1;
+ *nv1 = v1;
+ *nx2 = x2;
+ *nu2 = u2;
+ *nv2 = v2;
+}
+
+static void vdp1_fill_line(const struct rectangle *cliprect, int patterndata, int xsize, INT32 y,
+ INT32 x1, INT32 x2, INT32 u1, INT32 u2, INT32 v1, INT32 v2)
+{
+ int xx1 = x1>>FRAC_SHIFT;
+ int xx2 = x2>>FRAC_SHIFT;
+
+ if(y < cliprect->min_y || y > cliprect->max_y)
+ return;
+
+ if(xx1 <= cliprect->max_x || xx2 >= cliprect->min_x) {
+ INT32 slux = 0, slvx = 0;
+ INT32 u = u1;
+ INT32 v = v1;
+ if(xx1 != xx2) {
+ int delta = xx2-xx1;
+ slux = (u2-u1)/delta;
+ slvx = (v2-v1)/delta;
+ }
+ if(xx1 < cliprect->min_x) {
+ int delta = cliprect->min_x-xx1;
+ u += slux*delta;
+ v += slvx*delta;
+ xx1 = cliprect->min_x;
+ }
+ if(xx2 > cliprect->max_x)
+ xx2 = cliprect->max_x;
+
+ while(xx1 <= xx2) {
+ drawpixel(xx1,y,patterndata,(v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
+ xx1++;
+ u += slux;
+ v += slvx;
+ }
+ }
+}
+
+static void vdp1_fill_quad(const struct rectangle *cliprect, int patterndata, int xsize, const struct spoint *q)
+{
+ INT32 sl1, sl2, slu1, slu2, slv1, slv2, cury, limy, x1, x2, u1, u2, v1, v2, delta;
+ int pmin, pmax, i, ps1, ps2;
+ struct spoint p[8];
+
+ for(i=0; i<4; i++) {
+ p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT;
+ p[i].y = p[i+4].y = q[i].y;
+ p[i].u = p[i+4].u = q[i].u << FRAC_SHIFT;
+ p[i].v = p[i+4].v = q[i].v << FRAC_SHIFT;
+ }
+
+ pmin = pmax = 0;
+ for(i=1; i<4; i++) {
+ if(p[i].y < p[pmin].y)
+ pmin = i;
+ if(p[i].y > p[pmax].y)
+ pmax = i;
+ }
+
+ cury = p[pmin].y;
+ limy = p[pmax].y;
+
+ if(cury == limy) {
+ x1 = x2 = p[0].x;
+ u1 = u2 = p[0].u;
+ v1 = v2 = p[0].v;
+ for(i=1; i<4; i++) {
+ if(p[i].x < x1) {
+ x1 = p[i].x;
+ u1 = p[i].u;
+ v1 = p[i].v;
+ }
+ if(p[i].x > x2) {
+ x2 = p[i].x;
+ u2 = p[i].u;
+ v2 = p[i].v;
+ }
+ }
+ vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
+ return;
+ }
+
+ if(cury > cliprect->max_y)
+ return;
+ if(limy <= cliprect->min_y)
+ return;
+
+ if(limy > cliprect->max_y)
+ limy = cliprect->max_y;
+
+ ps1 = pmin+4;
+ ps2 = pmin;
+
+ goto startup;
+
+ for(;;) {
+ if(p[ps1-1].y == p[ps2+1].y) {
+ vdp1_fill_slope(cliprect, patterndata, xsize,
+ x1, x2, sl1, sl2, &x1, &x2,
+ u1, u2, slu1, slu2, &u1, &u2,
+ v1, v2, slv1, slv2, &v1, &v2,
+ cury, p[ps1-1].y);
+ cury = p[ps1-1].y;
+ if(cury >= limy)
+ break;
+ ps1--;
+ ps2++;
+
+ startup:
+ while(p[ps1-1].y == cury)
+ ps1--;
+ while(p[ps2+1].y == cury)
+ ps2++;
+ x1 = p[ps1].x;
+ u1 = p[ps1].u;
+ v1 = p[ps1].v;
+ x2 = p[ps2].x;
+ u2 = p[ps2].u;
+ v2 = p[ps2].v;
+
+ delta = cury-p[ps1-1].y;
+ sl1 = (x1-p[ps1-1].x)/delta;
+ slu1 = (u1-p[ps1-1].u)/delta;
+ slv1 = (v1-p[ps1-1].v)/delta;
+
+ delta = cury-p[ps2+1].y;
+ sl2 = (x2-p[ps2+1].x)/delta;
+ slu2 = (u2-p[ps2+1].u)/delta;
+ slv2 = (v2-p[ps2+1].v)/delta;
+ } else if(p[ps1-1].y < p[ps2+1].y) {
+ vdp1_fill_slope(cliprect, patterndata, xsize,
+ x1, x2, sl1, sl2, &x1, &x2,
+ u1, u2, slu1, slu2, &u1, &u2,
+ v1, v2, slv1, slv2, &v1, &v2,
+ cury, p[ps1-1].y);
+ cury = p[ps1-1].y;
+ if(cury >= limy)
+ break;
+ ps1--;
+ while(p[ps1-1].y == cury)
+ ps1--;
+ x1 = p[ps1].x;
+ u1 = p[ps1].u;
+ v1 = p[ps1].v;
+
+ delta = cury-p[ps1-1].y;
+ sl1 = (x1-p[ps1-1].x)/delta;
+ slu1 = (u1-p[ps1-1].u)/delta;
+ slv1 = (v1-p[ps1-1].v)/delta;
+ } else {
+ vdp1_fill_slope(cliprect, patterndata, xsize,
+ x1, x2, sl1, sl2, &x1, &x2,
+ u1, u2, slu1, slu2, &u1, &u2,
+ v1, v2, slv1, slv2, &v1, &v2,
+ cury, p[ps2+1].y);
+ cury = p[ps2+1].y;
+ if(cury >= limy)
+ break;
+ ps2++;
+ while(p[ps2+1].y == cury)
+ ps2++;
+ x2 = p[ps2].x;
+ u2 = p[ps2].u;
+ v2 = p[ps2].v;
+
+ delta = cury-p[ps2+1].y;
+ sl2 = (x2-p[ps2+1].x)/delta;
+ slu2 = (u2-p[ps2+1].u)/delta;
+ slv2 = (v2-p[ps2+1].v)/delta;
+ }
+ }
+ if(cury == limy)
+ vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
+}
+
+static int x2s(int v)
+{
+ return (INT32)(INT16)v + vdp1.local_x;
+}
+
+static int y2s(int v)
+{
+ return (INT32)(INT16)v + vdp1.local_y;
+}
+
+static void vdp1_draw_line(const struct rectangle *cliprect)
+{
+ struct spoint q[4];
+
+ q[0].x = x2s(current_sprite.CMDXA);
+ q[0].y = y2s(current_sprite.CMDYA);
+ q[1].x = x2s(current_sprite.CMDXB);
+ q[1].y = y2s(current_sprite.CMDYB);
+ q[2].x = x2s(current_sprite.CMDXA);
+ q[2].y = y2s(current_sprite.CMDYA);
+ q[3].x = x2s(current_sprite.CMDXB);
+ q[3].y = y2s(current_sprite.CMDYB);
+
+ q[0].u = q[3].u = q[1].u = q[2].u = 0;
+ q[0].v = q[1].v = q[2].v = q[3].v = 0;
+
+ vdp1_fill_quad(cliprect, 0, 1, q);
+}
+
+static void vdp1_draw_poly_line(const struct rectangle *cliprect)
+{
+ struct spoint q[4];
+
+ q[0].x = x2s(current_sprite.CMDXA);
+ q[0].y = y2s(current_sprite.CMDYA);
+ q[1].x = x2s(current_sprite.CMDXB);
+ q[1].y = y2s(current_sprite.CMDYB);
+ q[2].x = x2s(current_sprite.CMDXA);
+ q[2].y = y2s(current_sprite.CMDYA);
+ q[3].x = x2s(current_sprite.CMDXB);
+ q[3].y = y2s(current_sprite.CMDYB);
+
+ q[0].u = q[3].u = q[1].u = q[2].u = 0;
+ q[0].v = q[1].v = q[2].v = q[3].v = 0;
+
+ vdp1_fill_quad(cliprect, 0, 1, q);
+
+ q[0].x = x2s(current_sprite.CMDXB);
+ q[0].y = y2s(current_sprite.CMDYB);
+ q[1].x = x2s(current_sprite.CMDXC);
+ q[1].y = y2s(current_sprite.CMDYC);
+ q[2].x = x2s(current_sprite.CMDXB);
+ q[2].y = y2s(current_sprite.CMDYB);
+ q[3].x = x2s(current_sprite.CMDXC);
+ q[3].y = y2s(current_sprite.CMDYC);
+
+ q[0].u = q[3].u = q[1].u = q[2].u = 0;
+ q[0].v = q[1].v = q[2].v = q[3].v = 0;
+
+ vdp1_fill_quad(cliprect, 0, 1, q);
+
+ q[0].x = x2s(current_sprite.CMDXC);
+ q[0].y = y2s(current_sprite.CMDYC);
+ q[1].x = x2s(current_sprite.CMDXD);
+ q[1].y = y2s(current_sprite.CMDYD);
+ q[2].x = x2s(current_sprite.CMDXC);
+ q[2].y = y2s(current_sprite.CMDYC);
+ q[3].x = x2s(current_sprite.CMDXD);
+ q[3].y = y2s(current_sprite.CMDYD);
+
+ q[0].u = q[3].u = q[1].u = q[2].u = 0;
+ q[0].v = q[1].v = q[2].v = q[3].v = 0;
+
+ vdp1_fill_quad(cliprect, 0, 1, q);
+
+ q[0].x = x2s(current_sprite.CMDXD);
+ q[0].y = y2s(current_sprite.CMDYD);
+ q[1].x = x2s(current_sprite.CMDXA);
+ q[1].y = y2s(current_sprite.CMDYA);
+ q[2].x = x2s(current_sprite.CMDXD);
+ q[2].y = y2s(current_sprite.CMDYD);
+ q[3].x = x2s(current_sprite.CMDXA);
+ q[3].y = y2s(current_sprite.CMDYA);
+
+ q[0].u = q[3].u = q[1].u = q[2].u = 0;
+ q[0].v = q[1].v = q[2].v = q[3].v = 0;
+
+ vdp1_setup_shading(q, cliprect);
+ vdp1_fill_quad(cliprect, 0, 1, q);
+
+}
+
+static void vdp1_draw_distorted_sprite(const struct rectangle *cliprect)
+{
+ struct spoint q[4];
+
+ int xsize, ysize;
+ int direction;
+ int patterndata;
+
+ direction = (current_sprite.CMDCTRL & 0x0030)>>4;
+
+ if ( current_sprite.ispoly )
+ {
+ xsize = ysize = 1;
+ patterndata = 0;
+ }
+ else
+ {
+ xsize = (current_sprite.CMDSIZE & 0x3f00) >> 8;
+ xsize = xsize * 8;
+ if (xsize == 0) return; /* setting prohibited */
+
+ ysize = (current_sprite.CMDSIZE & 0x00ff);
+ if (ysize == 0) return; /* setting prohibited */
+
+ patterndata = (current_sprite.CMDSRCA) & 0xffff;
+ patterndata = patterndata * 0x8;
+
+ }
+
+
+ q[0].x = x2s(current_sprite.CMDXA);
+ q[0].y = y2s(current_sprite.CMDYA);
+ q[1].x = x2s(current_sprite.CMDXB);
+ q[1].y = y2s(current_sprite.CMDYB);
+ q[2].x = x2s(current_sprite.CMDXC);
+ q[2].y = y2s(current_sprite.CMDYC);
+ q[3].x = x2s(current_sprite.CMDXD);
+ q[3].y = y2s(current_sprite.CMDYD);
+
+ if(direction & 1) { /* xflip */
+ q[0].u = q[3].u = xsize-1;
+ q[1].u = q[2].u = 0;
+ } else {
+ q[0].u = q[3].u = 0;
+ q[1].u = q[2].u = xsize-1;
+ }
+ if(direction & 2) { /* yflip */
+ q[0].v = q[1].v = ysize-1;
+ q[2].v = q[3].v = 0;
+ } else {
+ q[0].v = q[1].v = 0;
+ q[2].v = q[3].v = ysize-1;
+ }
+
+ vdp1_setup_shading(q, cliprect);
+ vdp1_fill_quad(cliprect, patterndata, xsize, q);
+}
+
+static void vdp1_draw_scaled_sprite(const struct rectangle *cliprect)
+{
+ struct spoint q[4];
+
+ int xsize, ysize;
+ int direction;
+ int patterndata;
+ int zoompoint;
+ int x,y;
+ int x2,y2;
+ int screen_width,screen_height,screen_height_negative = 0;
+
+ direction = (current_sprite.CMDCTRL & 0x0030)>>4;
+
+ xsize = (current_sprite.CMDSIZE & 0x3f00) >> 8;
+ xsize = xsize * 8;
+
+ ysize = (current_sprite.CMDSIZE & 0x00ff);
+
+ patterndata = (current_sprite.CMDSRCA) & 0xffff;
+ patterndata = patterndata * 0x8;
+
+ zoompoint = (current_sprite.CMDCTRL & 0x0f00)>>8;
+
+ x = current_sprite.CMDXA;
+ y = current_sprite.CMDYA;
+
+ screen_width = (INT16)current_sprite.CMDXB;
+ if ( (screen_width < 0) && zoompoint)
+ {
+ screen_width = -screen_width;
+ direction |= 1;
+ }
+
+ screen_height = (INT16)current_sprite.CMDYB;
+ if ( (screen_height < 0) && zoompoint )
+ {
+ screen_height_negative = 1;
+ screen_height = -screen_height;
+ direction |= 2;
+ }
+
+ x2 = current_sprite.CMDXC; /* second co-ordinate set x */
+ y2 = current_sprite.CMDYC; /* second co-ordinate set y */
+
+ switch (zoompoint)
+ {
+ case 0x0: /* specified co-ordinates */
+ break;
+ case 0x5: /* up left */
+ break;
+ case 0x6: /* up center */
+ x -= screen_width/2 ;
+ break;
+ case 0x7: /* up right */
+ x -= screen_width;
+ break;
+
+ case 0x9: /* center left */
+ y -= screen_height/2 ;
+ break;
+ case 0xa: /* center center */
+ y -= screen_height/2 ;
+ x -= screen_width/2 ;
+
+ break;
+
+ case 0xb: /* center right */
+ y -= screen_height/2 ;
+ x -= screen_width;
+ break;
+
+ case 0xd: /* center left */
+ y -= screen_height;
+ break;
+
+ case 0xe: /* center center */
+ y -= screen_height;
+ x -= screen_width/2 ;
+ break;
+
+ case 0xf: /* center right */
+ y -= screen_height;
+ x -= screen_width;
+ break;
+
+ default: /* illegal */
+ break;
+
+ }
+
+ /* 0----1
+ | |
+ | |
+ 3----2 */
+
+ if (zoompoint)
+ {
+ q[0].x = x2s(x);
+ q[0].y = y2s(y);
+ q[1].x = x2s(x)+screen_width;
+ q[1].y = y2s(y);
+ q[2].x = x2s(x)+screen_width;
+ q[2].y = y2s(y)+screen_height;
+ q[3].x = x2s(x);
+ q[3].y = y2s(y)+screen_height;
+
+ if ( screen_height_negative )
+ {
+ q[0].y += screen_height;
+ q[1].y += screen_height;
+ q[2].y += screen_height;
+ q[3].y += screen_height;
+ }
+ }
+ else
+ {
+ q[0].x = x2s(x);
+ q[0].y = y2s(y);
+ q[1].x = x2s(x2);
+ q[1].y = y2s(y);
+ q[2].x = x2s(x2);
+ q[2].y = y2s(y2);
+ q[3].x = x2s(x);
+ q[3].y = y2s(y2);
+ }
+
+
+ if(direction & 1) { /* xflip */
+ q[0].u = q[3].u = xsize-1;
+ q[1].u = q[2].u = 0;
+ } else {
+ q[0].u = q[3].u = 0;
+ q[1].u = q[2].u = xsize-1;
+ }
+ if(direction & 2) { /* yflip */
+ q[0].v = q[1].v = ysize-1;
+ q[2].v = q[3].v = 0;
+ } else {
+ q[0].v = q[1].v = 0;
+ q[2].v = q[3].v = ysize-1;
+ }
+
+ vdp1_setup_shading(q, cliprect);
+ vdp1_fill_quad(cliprect, patterndata, xsize, q);
+}
+
+
+
+
+static void vdp1_draw_normal_sprite(const struct rectangle *cliprect, int sprite_type)
+{
+ int y, ysize, drawypos;
+ int x, xsize, drawxpos;
+ int direction;
+ int patterndata;
+ UINT8 shading;
+ int su, u, dux, duy;
+ int maxdrawypos, maxdrawxpos;
+
+ x = x2s(current_sprite.CMDXA);
+ y = y2s(current_sprite.CMDYA);
+
+ direction = (current_sprite.CMDCTRL & 0x0030)>>4;
+
+ xsize = (current_sprite.CMDSIZE & 0x3f00) >> 8;
+ xsize = xsize * 8;
+
+ ysize = (current_sprite.CMDSIZE & 0x00ff);
+
+ patterndata = (current_sprite.CMDSRCA) & 0xffff;
+ patterndata = patterndata * 0x8;
+
+ if (VDP1_LOG) logerror ("Drawing Normal Sprite x %04x y %04x xsize %04x ysize %04x patterndata %06x\n",x,y,xsize,ysize,patterndata);
+
+ if ( x > cliprect->max_x ) return;
+ if ( y > cliprect->max_y ) return;
+
+ shading = read_gouraud_table();
+ if ( shading )
+ {
+ struct spoint q[4];
+ q[0].x = x; q[0].y = y;
+ q[1].x = x + xsize; q[1].y = y;
+ q[2].x = x + xsize; q[2].y = y + ysize;
+ q[3].x = x; q[3].y = y + ysize;
+
+ vdp1_setup_shading( q, cliprect );
+ }
+
+ u = 0;
+ dux = 1;
+ duy = xsize;
+ if ( direction & 0x1 ) /*xflip */
+ {
+ dux = -1;
+ u = xsize - 1;
+ }
+ if ( direction & 0x2 ) /*yflip */
+ {
+ duy = -xsize;
+ u += xsize*(ysize-1);
+ }
+ if ( y < cliprect->min_y ) /*clip y */
+ {
+ /* draculax user clips a 320x240 sprite for inverted castle map (obviously x & y flipped) */
+ /* we need to adjust U calculation only to make it align properly, */
+ /* adjusting ysize will already glitch out flipped doors in gameplay. */
+ const int adjust_y = (direction & 2) ? (y - cliprect->min_y) : (cliprect->min_y - y);
+ u += xsize * (adjust_y);
+ ysize -= (cliprect->min_y - y);
+ y = cliprect->min_y;
+ }
+ if ( x < cliprect->min_x ) /*clip x */
+ {
+ u += dux*(cliprect->min_x - x);
+ xsize -= (cliprect->min_x - x);
+ x = cliprect->min_x;
+ }
+ maxdrawypos = MIN(y + ysize - 1, cliprect->max_y);
+ maxdrawxpos = MIN(x + xsize - 1, cliprect->max_x);
+ for (drawypos = y; drawypos <= maxdrawypos; drawypos++ )
+ {
+ /*destline = vdp1.framebuffer_draw_lines[drawypos]; */
+ su = u;
+ for (drawxpos = x; drawxpos <= maxdrawxpos; drawxpos++ )
+ {
+ drawpixel( drawxpos, drawypos, patterndata, u );
+ u += dux;
+ }
+ u = su + duy;
+ }
+}
+
+static void vdp1_draw_end(int param)
+{
+ /* set CEF to 1*/
+ CEF_1();
+
+ /* TODO: temporary for Batman Forever, presumably anonymous timer not behaving well. */
+ #if 0
+ if(!(m_scu.ism & IRQ_VDP1_END))
+ {
+ m_maincpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d); /* SH2 */
+ scu_do_transfer(6);
+ }
+ else
+ m_scu.ist |= (IRQ_VDP1_END);
+ #endif
+}
+
+
+static void vdp1_process_list(void)
+{
+ int position;
+ int spritecount;
+ int vdp1_nest;
+ struct rectangle *cliprect;
+
+ spritecount = 0;
+ position = 0;
+
+ if (VDP1_LOG) logerror ("Sprite List Process START\n");
+
+ vdp1_nest = -1;
+
+ clear_gouraud_shading();
+
+ /*Set CEF bit to 0*/
+ CEF_0();
+
+ /* TODO: is there an actual limit for this? */
+ while (spritecount < 16383) /* max 16383 with texture or max 16384 without texture - virtually unlimited */
+ {
+ int draw_this_sprite;
+
+ draw_this_sprite = 1;
+
+ /* if (position >= ((0x80000/0x20)/4)) // safety check */
+ /* { */
+ /* if (VDP1_LOG) logerror ("Sprite List Position Too High!\n"); */
+ /* position = 0; */
+ /* } */
+
+ spritecount++;
+
+ current_sprite.CMDCTRL = (vdp1_vram[position * (0x20/4)+0] & 0xffff0000) >> 16;
+
+ /* The END bit terminates the list regardless of the other bits. */
+ /* (SGL terminates its sorted list with 0xffff) */
+ if (current_sprite.CMDCTRL & 0x8000)
+ {
+ if (VDP1_LOG) logerror ("List Terminator (0x8000) Encountered, Sprite List Process END\n");
+ goto end; /* end of list */
+ }
+
+ current_sprite.CMDLINK = (vdp1_vram[position * (0x20/4)+0] & 0x0000ffff) >> 0;
+ current_sprite.CMDPMOD = (vdp1_vram[position * (0x20/4)+1] & 0xffff0000) >> 16;
+ current_sprite.CMDCOLR = (vdp1_vram[position * (0x20/4)+1] & 0x0000ffff) >> 0;
+ current_sprite.CMDSRCA = (vdp1_vram[position * (0x20/4)+2] & 0xffff0000) >> 16;
+ current_sprite.CMDSIZE = (vdp1_vram[position * (0x20/4)+2] & 0x0000ffff) >> 0;
+ current_sprite.CMDXA = (vdp1_vram[position * (0x20/4)+3] & 0xffff0000) >> 16;
+ current_sprite.CMDYA = (vdp1_vram[position * (0x20/4)+3] & 0x0000ffff) >> 0;
+ current_sprite.CMDXB = (vdp1_vram[position * (0x20/4)+4] & 0xffff0000) >> 16;
+ current_sprite.CMDYB = (vdp1_vram[position * (0x20/4)+4] & 0x0000ffff) >> 0;
+ current_sprite.CMDXC = (vdp1_vram[position * (0x20/4)+5] & 0xffff0000) >> 16;
+ current_sprite.CMDYC = (vdp1_vram[position * (0x20/4)+5] & 0x0000ffff) >> 0;
+ current_sprite.CMDXD = (vdp1_vram[position * (0x20/4)+6] & 0xffff0000) >> 16;
+ current_sprite.CMDYD = (vdp1_vram[position * (0x20/4)+6] & 0x0000ffff) >> 0;
+ current_sprite.CMDGRDA = (vdp1_vram[position * (0x20/4)+7] & 0xffff0000) >> 16;
+/* current_sprite.UNUSED = (vdp1_vram[position * (0x20/4)+7] & 0x0000ffff) >> 0; */
+
+ /* proecess jump / skip commands, set position for next sprite */
+ switch (current_sprite.CMDCTRL & 0x7000)
+ {
+ case 0x0000: /* jump next */
+ if (VDP1_LOG) logerror ("Sprite List Process + Next (Normal)\n");
+ position++;
+ break;
+ case 0x1000: /* jump assign */
+ if (VDP1_LOG) logerror ("Sprite List Process + Jump Old %06x New %06x\n", position, (current_sprite.CMDLINK>>2));
+ position= (current_sprite.CMDLINK>>2);
+ break;
+ case 0x2000: /* jump call */
+ if (vdp1_nest == -1)
+ {
+ if (VDP1_LOG) logerror ("Sprite List Process + Call Old %06x New %06x\n",position, (current_sprite.CMDLINK>>2));
+ vdp1_nest = position+1;
+ position = (current_sprite.CMDLINK>>2);
+ }
+ else
+ {
+ if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n");
+ position++;
+ }
+ break;
+ case 0x3000:
+ if (vdp1_nest != -1)
+ {
+ if (VDP1_LOG) logerror ("Sprite List Process + Return\n");
+ position = vdp1_nest;
+ vdp1_nest = -1;
+ }
+ else
+ {
+ /* A return with no subroutine is a NOP (Yabause and Mednafen agree) */
+ if (VDP1_LOG) logerror ("Attempted return from no subroutine, continuing\n");
+ position++;
+ }
+ break;
+ case 0x4000:
+ draw_this_sprite = 0;
+ position++;
+ break;
+ case 0x5000:
+ if (VDP1_LOG) logerror ("Sprite List Skip + Jump Old %06x New %06x\n", position, (current_sprite.CMDLINK>>2));
+ draw_this_sprite = 0;
+ position= (current_sprite.CMDLINK>>2);
+
+ break;
+ case 0x6000:
+ draw_this_sprite = 0;
+ if (vdp1_nest == -1)
+ {
+ if (VDP1_LOG) logerror ("Sprite List Skip + Call To Subroutine Old %06x New %06x\n",position, (current_sprite.CMDLINK>>2));
+
+ vdp1_nest = position+1;
+ position = (current_sprite.CMDLINK>>2);
+ }
+ else
+ {
+ if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n");
+ position++;
+ }
+ break;
+ case 0x7000:
+ draw_this_sprite = 0;
+ if (vdp1_nest != -1)
+ {
+ if (VDP1_LOG) logerror ("Sprite List Skip + Return from Subroutine\n");
+
+ position = vdp1_nest;
+ vdp1_nest = -1;
+ }
+ else
+ {
+ if (VDP1_LOG) logerror ("Attempted return from no subroutine, continuing\n");
+ position++;
+ }
+ break;
+ }
+
+ /* continue to draw this sprite only if the command wasn't to skip it */
+ if (draw_this_sprite == 1)
+ {
+ if ( current_sprite.CMDPMOD & 0x0400 )
+ {
+ /*if(current_sprite.CMDPMOD & 0x0200) TODO: Bio Hazard inventory screen uses outside cliprect */
+ /* cliprect = &vdp1.system_cliprect; */
+ /*else */
+ cliprect = &vdp1.user_cliprect;
+ }
+ else
+ {
+ cliprect = &vdp1.system_cliprect;
+ }
+
+ vdp1_set_drawpixel();
+
+ switch (current_sprite.CMDCTRL & 0x000f)
+ {
+ case 0x0000:
+ if (VDP1_LOG) logerror ("Sprite List Normal Sprite (%d %d)\n",current_sprite.CMDXA,current_sprite.CMDYA);
+ current_sprite.ispoly = 0;
+ vdp1_draw_normal_sprite(cliprect, 0);
+ break;
+
+ case 0x0001:
+ if (VDP1_LOG) logerror ("Sprite List Scaled Sprite (%d %d)\n",current_sprite.CMDXA,current_sprite.CMDYA);
+ current_sprite.ispoly = 0;
+ vdp1_draw_scaled_sprite(cliprect);
+ break;
+
+ case 0x0002:
+ case 0x0003: /* used by Hardcore 4x4 */
+ if (VDP1_LOG) logerror ("Sprite List Distorted Sprite\n");
+ if (VDP1_LOG) logerror ("(A: %d %d)\n",current_sprite.CMDXA,current_sprite.CMDYA);
+ if (VDP1_LOG) logerror ("(B: %d %d)\n",current_sprite.CMDXB,current_sprite.CMDYB);
+ if (VDP1_LOG) logerror ("(C: %d %d)\n",current_sprite.CMDXC,current_sprite.CMDYC);
+ if (VDP1_LOG) logerror ("(D: %d %d)\n",current_sprite.CMDXD,current_sprite.CMDYD);
+ if (VDP1_LOG) logerror ("CMDPMOD = %04x\n",current_sprite.CMDPMOD);
+
+ current_sprite.ispoly = 0;
+ vdp1_draw_distorted_sprite(cliprect);
+ break;
+
+ case 0x0004:
+ if (VDP1_LOG) logerror ("Sprite List Polygon\n");
+ current_sprite.ispoly = 1;
+ vdp1_draw_distorted_sprite(cliprect);
+ break;
+
+ case 0x0005:
+ case 0x0007: /* mirror? baroque/samsho4 */
+ if (VDP1_LOG) logerror ("Sprite List Polyline\n");
+ current_sprite.ispoly = 1;
+ vdp1_draw_poly_line(cliprect);
+ break;
+
+ case 0x0006:
+ if (VDP1_LOG) logerror ("Sprite List Line\n");
+ current_sprite.ispoly = 1;
+ vdp1_draw_line(cliprect);
+ break;
+
+ case 0x0008:
+/* case 0x000b: // mirror? Bug 2 */
+ if (VDP1_LOG) logerror ("Sprite List Set Command for User Clipping (%d,%d),(%d,%d)\n", current_sprite.CMDXA, current_sprite.CMDYA, current_sprite.CMDXC, current_sprite.CMDYC);
+ rect_set(&vdp1.user_cliprect, current_sprite.CMDXA, current_sprite.CMDXC, current_sprite.CMDYA, current_sprite.CMDYC);
+ break;
+
+ case 0x0009:
+ if (VDP1_LOG) logerror ("Sprite List Set Command for System Clipping (0,0),(%d,%d)\n", current_sprite.CMDXC, current_sprite.CMDYC);
+ rect_set(&vdp1.system_cliprect, 0, current_sprite.CMDXC, 0, current_sprite.CMDYC);
+ break;
+
+ case 0x000a:
+ if (VDP1_LOG) logerror ("Sprite List Local Co-Ordinate Set (%d %d)\n",(INT16)current_sprite.CMDXA,(INT16)current_sprite.CMDYA);
+ vdp1.local_x = (INT16)current_sprite.CMDXA;
+ vdp1.local_y = (INT16)current_sprite.CMDYA;
+ break;
+
+ default:
+ /* asenna 0x0c or 0x0d (transition from title screen) */
+ /* raymanj 0x0d (at startup) */
+ /* choroqpk 0x0e (when selecting island in main menu) */
+ /* albodysj 0x0f (always) */
+ if ((current_sprite.CMDCTRL & 0x000f) < 0xc)
+ popmessage ("VDP1: Sprite List Illegal %02x (%d)",current_sprite.CMDCTRL & 0xf,spritecount);
+ vdp1.lopr = (position * 0x20) >> 3;
+ /*vdp1.copr = (position * 0x20) >> 3; */
+ /* prematurely kill the VDP1 process if an illegal opcode is executed */
+ /* sexyparo calls multiple illegals and expects VDP1 irq to be fired anyway! */
+ goto end;
+ }
+ }
+
+ }
+
+
+ end:
+ vdp1.copr = (position * 0x20) >> 3;
+
+
+ /* TODO: what's the exact formula? Guess it should be a mix between number of pixels written and actual command data fetched. */
+ /* if spritecount = 10000 don't send a vdp1 draw end */
+/* if(spritecount < 10000) */
+ timer_adjust(vdp1.draw_end_timer, TIME_IN_CYCLES(spritecount*16, 0), 0, 0);
+
+ if (VDP1_LOG) logerror ("End of list processing!\n");
+}
+
+static void vdp1_video_update(void)
+{
+ int framebuffer_changed = 0;
+
+/* int enable; */
+/* if (machine.input().code_pressed (KEYCODE_R)) VDP1_LOG = 1; */
+/* if (machine.input().code_pressed (KEYCODE_T)) VDP1_LOG = 0; */
+
+/* if (machine.input().code_pressed (KEYCODE_Y)) VDP1_LOG = 0; */
+/* { */
+/* FILE *fp; */
+
+/* fp=fopen("vdp1_ram.dmp", "w+b"); */
+/* if (fp) */
+/* { */
+/* fwrite(stv_vdp1, 0x00100000, 1, fp); */
+/* fclose(fp); */
+/* } */
+/* } */
+ if (VDP1_LOG) logerror("vdp1_video_update called\n");
+ if (VDP1_LOG) logerror( "FBCR = %0x, accessed = %d\n", VDP1_FBCR, vdp1.fbcr_accessed );
+
+ if(VDP1_CEF)
+ BEF_1();
+ else
+ BEF_0();
+
+ if ( vdp1.framebuffer_clear_on_next_frame )
+ {
+ if ( ((VDP1_FBCR & 0x3) == 3) &&
+ vdp1.fbcr_accessed )
+ {
+ vdp1_clear_framebuffer(vdp1.framebuffer_current_display);
+ vdp1.framebuffer_clear_on_next_frame = 0;
+ }
+ }
+
+ switch( VDP1_FBCR & 0x3 )
+ {
+ case 0: /* Automatic mode */
+ vdp1_change_framebuffers();
+ vdp1_clear_framebuffer(vdp1.framebuffer_current_draw);
+ framebuffer_changed = 1;
+ break;
+ case 1: /* Setting prohibited */
+ break;
+ case 2: /* Manual mode - erase */
+ if (vdp1.fbcr_accessed)
+ {
+ vdp1.framebuffer_clear_on_next_frame = 1;
+ }
+ break;
+ case 3: /* Manual mode - change */
+ if (vdp1.fbcr_accessed)
+ {
+ vdp1_change_framebuffers();
+ if (VDP1_VBE())
+ {
+ vdp1_clear_framebuffer(vdp1.framebuffer_current_draw);
+ }
+ /* TODO: Slam n Jam 96 & Cross Romance doesn't like this, investigate. */
+ framebuffer_changed = 1;
+ }
+ /* framebuffer_changed = 1; */
+ break;
+ }
+ vdp1.fbcr_accessed = 0;
+
+ if (VDP1_LOG) logerror("PTM = %0x, TVM = %x\n", VDP1_PTM, VDP1_TVM());
+ /*Set CEF bit to 0*/
+ /*CEF_0(); */
+ switch (VDP1_PTM & 3)
+ {
+ case 0:/*Idle Mode*/
+ /*Set CEF bit to 0*/
+ /*CEF_0(); */
+ break;
+ case 1:/*Draw by request*/
+ /*Set CEF bit to 0*/
+ /*CEF_0(); */
+ break;
+ case 2:/*Automatic Draw*/
+ if ( framebuffer_changed || VDP1_LOG )
+ {
+ /*set CEF to 1*/
+ vdp1_process_list();
+ }
+ break;
+ case 3: /**/
+ logerror("Warning: Invalid PTM mode set for VDP1!\n");
+ break;
+ }
+ /*popmessage("%04x %04x",VDP1_EWRR_X3,VDP1_EWRR_Y3); */
+}
+
+static void vdp1_state_save_postload(void)
+{
+ UINT8 *gfx = vdp1.gfx_decode;
+ int offset;
+ UINT32 data;
+ int draw = vdp1.framebuffer_current_draw;
+
+ vdp1.framebuffer_mode = -1;
+ vdp1.framebuffer_double_interlace = -1;
+
+ vdp1_set_framebuffer_config();
+
+ /* the configuration starts from framebuffer 0: back to the saved one */
+ vdp1.framebuffer_current_draw = draw;
+ vdp1.framebuffer_current_display = draw ^ 1;
+ vdp1_prepare_framebuffers();
+
+ for (offset = 0; offset < 0x80000/4; offset++ )
+ {
+ data = vdp1_vram[offset];
+ /* put in gfx region for easy decoding */
+ gfx[offset*4+0] = (data & 0xff000000) >> 24;
+ gfx[offset*4+1] = (data & 0x00ff0000) >> 16;
+ gfx[offset*4+2] = (data & 0x0000ff00) >> 8;
+ gfx[offset*4+3] = (data & 0x000000ff) >> 0;
+ }
+}
+
+static int vdp1_start(void)
+{
+ vdp1_regs = auto_malloc(0x020);
+ vdp1_vram = auto_malloc(0x100000);
+ vdp1.gfx_decode = auto_malloc(0x100000);
+ memset(vdp1_regs, 0, 0x020);
+ memset(vdp1_vram, 0, 0x100000);
+ memset(vdp1.gfx_decode, 0, 0x100000);
+
+ vdp1_shading_data = auto_malloc(sizeof(struct vdp1_poly_scanline_data));
+ memset(vdp1_shading_data, 0, sizeof(struct vdp1_poly_scanline_data));
+
+ vdp1.framebuffer[0] = auto_malloc(1024 * 256 * 2 * sizeof(UINT16)); /* *2 is for double interlace */
+ vdp1.framebuffer[1] = auto_malloc(1024 * 256 * 2 * sizeof(UINT16));
+ memset(vdp1.framebuffer[0], 0, 1024 * 256 * 2 * sizeof(UINT16));
+ memset(vdp1.framebuffer[1], 0, 1024 * 256 * 2 * sizeof(UINT16));
+
+ vdp1.framebuffer_display_lines = auto_malloc(512 * sizeof(UINT16 *));
+ vdp1.framebuffer_draw_lines = auto_malloc(512 * sizeof(UINT16 *));
+
+ vdp1.framebuffer_width = vdp1.framebuffer_height = 0;
+ vdp1.framebuffer_mode = -1;
+ vdp1.framebuffer_double_interlace = -1;
+ vdp1.fbcr_accessed = 0;
+ vdp1.framebuffer_current_display = 0;
+ vdp1.framebuffer_current_draw = 1;
+ vdp1_clear_framebuffer(vdp1.framebuffer_current_draw);
+ vdp1.framebuffer_clear_on_next_frame = 0;
+
+ rect_set(&vdp1.system_cliprect, 0, 0, 0, 0);
+ /* Kidou Senshi Z Gundam - Zenpen Zeta no Kodou loves to use the user cliprect vars in an undefined state ... */
+ rect_set(&vdp1.user_cliprect, 0, 512, 0, 256);
+
+ vdp1.draw_end_timer = timer_alloc(vdp1_draw_end);
+
+ /* save state (with the framebuffers, unlike MAME, so a state goes on frame for frame) */
+ state_save_register_UINT16("stv_vdp1", 0, "regs", vdp1_regs, 0x020/2);
+ state_save_register_UINT32("stv_vdp1", 0, "vram", vdp1_vram, 0x100000/4);
+ state_save_register_UINT16("stv_vdp1", 0, "fb0", vdp1.framebuffer[0], 1024 * 256 * 2);
+ state_save_register_UINT16("stv_vdp1", 0, "fb1", vdp1.framebuffer[1], 1024 * 256 * 2);
+ state_save_register_int("stv_vdp1", 0, "fbcr_accessed", &vdp1.fbcr_accessed);
+ state_save_register_int("stv_vdp1", 0, "fb_display", &vdp1.framebuffer_current_display);
+ state_save_register_int("stv_vdp1", 0, "fb_draw", &vdp1.framebuffer_current_draw);
+ state_save_register_int("stv_vdp1", 0, "fb_clear", &vdp1.framebuffer_clear_on_next_frame);
+ state_save_register_int("stv_vdp1", 0, "local_x", &vdp1.local_x);
+ state_save_register_int("stv_vdp1", 0, "local_y", &vdp1.local_y);
+ state_save_register_UINT16("stv_vdp1", 0, "lopr", &vdp1.lopr, 1);
+ state_save_register_UINT16("stv_vdp1", 0, "copr", &vdp1.copr, 1);
+ state_save_register_UINT16("stv_vdp1", 0, "ewdr", &vdp1.ewdr, 1);
+ state_save_register_func_postload(vdp1_state_save_postload);
+ return 0;
+}
+
+
+/**********************************************************************************************************************/
+
+/* Sega Saturn VDP2 */
+
+/*
+
+-------------------------- WARNING WARNING WARNING --------------------------
+This is a legacy core, all game based notes are for a future device rewrite.
+Please don't remove them if for no reason you truly want to mess with this.
+-------------------------- WARNING WARNING WARNING --------------------------
+
+the dirty marking stuff and tile decoding will probably be removed in the end anyway as we'll need custom
+rendering code since mame's drawgfx / tilesytem don't offer everything st-v needs
+
+this system seems far too complex to use Mame's tilemap system
+
+4 'scroll' planes (scroll screens)
+
+the scroll planes have slightly different capabilities
+
+NBG0
+NBG1
+NBG2
+NBG3
+
+2 'rotate' planes
+
+RBG0
+RBG1
+
+-- other crap
+EXBG (external)
+
+-----------------------------------------------------------------------------------------------------------
+
+Video emulation TODO:
+-all games:
+ \-priorities (check myfairld,thunt)
+ \-complete windows effects
+ \-mosaic effect
+ \-ODD bit/H/V Counter not yet emulated properly
+ \-Reduction enable bits (zooming limiters)
+ \-Check if there are any remaining video registers that are yet to be macroized & added to the rumble.
+-batmanfr:
+ \-If you reset the game after the character selection screen,when you get again to it there's garbage
+ floating behind Batman.
+-elandore:
+ \-(BTANB) priorities at the VS. screen apparently is wrong,but it's like this on the Saturn version too.
+-hanagumi:
+ \-ending screens have corrupt graphics. (*untested*)
+-kiwames:
+ \-(fixed) incorrect color emulation for the alpha blended flames on the title screen,it's caused by a schizoid
+ linescroll emulation quirk.
+ \-the VDP1 sprites refresh is too slow,causing the "Draw by request" mode to
+ flicker. Moved back to default ATM.
+-pblbeach:
+ \-Sprites are offset, because it doesn't clear vdp1 local coordinates set by bios,
+ I guess that they are cleared when some vdp1 register is written (kludged for now)
+-prikura:
+ \-Attract mode presentation has corrupted graphics in various places,probably caused by incomplete
+ framebuffer data delete.
+-seabass:
+ \-(fixed) Player sprite is corrupt/missing during movements,caused by incomplete framebuffer switching.
+-shienryu:
+ \-level 2 background colors on statues, caused by special color calculation usage (per dot);
+(Saturn games)
+- scud the disposable assassin:
+ \- when zooming on melee attack background gets pink, color calculation issue?
+- virtual hydlide:
+ \- transparent pens usage on most vdp1 items should be black instead.
+ \- likewise "press start button" is the other way around, i.e. black pen where it should be transparent instead.
+
+Notes of Interest & Unclear features:
+
+-the test mode / bios is drawn with layer NBG3;
+-hanagumi puts a 'RED' dragon logo in tileram (base 0x64000, 4bpp, 8x8 tiles) but
+its not displayed because its priority value is 0.Left-over?
+
+-scrolling is screen display wise,meaning that a scrolling value is masked with the
+screen resolution size values;
+
+-H-Blank bit is INDIPENDENT of the V-Blank bit...trying to fix enable/disable it during V-Blank period
+ causes wrong gameplay speed in Golden Axe:The Duel.
+
+-Bitmaps uses transparency pens,examples are:
+\-elandore's energy bars;
+\-mausuke's foreground(the one used on the playfield)
+\-shanhigw's tile-based sprites;
+The transparency pen table is like this:
+
+|------------------|---------------------|
+| Character count | Transparency code |
+|------------------|---------------------|
+| 16 colors |=0x0 (4 bits) |
+| 256 colors |=0x00 (8 bits) |
+| 2048 colors |=0x000 (11 bits) |
+| 32,768 colors |MSB=0 (bit 15) |
+| 16,770,000 colors|MSB=0 (bit 31) |
+|------------------|---------------------|
+In other words,the first three types uses the offset and not the color allocated.
+
+-double density interlace setting (LSMD == 3) apparently does a lot of fancy stuff in the graphics sizes.
+
+-Debug key list(only if you enable the debug mode on top of this file):
+ \-T: NBG3 layer toggle
+ \-Y: NBG2 layer toggle
+ \-U: NBG1 layer toggle
+ \-I: NBG0 layer toggle
+ \-O: SPRITE toggle
+ \-K: RBG0 layer toggle
+ \-W Decodes the graphics for F4 menu.
+ \-M Stores VDP1 ram contents from a file.
+ \-N Stores VDP1 ram contents into a file.
+*/
+
+#define TEST_FUNCTIONS 0
+#define POPMESSAGE_DEBUG 0
+
+
+enum
+{
+ STV_TRANSPARENCY_PEN = 0x0,
+ STV_TRANSPARENCY_NONE = 0x1,
+ STV_TRANSPARENCY_ADD_BLEND = 0x2,
+ STV_TRANSPARENCY_ALPHA = 0x4
+};
+
+#define DEBUG_DRAW_ROZ (0)
+
+/*
+
+-------------------------------------------------|-----------------------------|------------------------------
+| Function | Normal Scroll Screen | Rotation Scroll Screen |
+| |-----------------------------|-----------------------------|------------------------------
+| | NBG0 | NBG1 | NBG2 | NBG3 | RBG0 | RBG1 |
+-------------------------------------------------|-----------------------------|------------------------------
+| Character Colour | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours |
+| Count | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " |
+| | 2048 " " | 2048 " " | | | 2048 " " | 2048 " " |
+| | 32768 " " | 32768 " " | | | 32768 " " | 32768 " " |
+| | 16770000 " " | | | | 16770000 " " | 16770000 " " |
+-------------------------------------------------|-----------------------------|------------------------------
+| Character Size | 1x1 Cells , 2x2 Cells |
+-------------------------------------------------|-----------------------------|------------------------------
+| Pattern Name | 1 word , 2 words |
+| Data Size | |
+-------------------------------------------------|-----------------------------|------------------------------
+| Plane Size | 1 H x 1 V 1 Pages ; 2 H x 1 V 1 Pages ; 2 H x 2 V Pages |
+-------------------------------------------------|-----------------------------|------------------------------
+| Plane Count | 4 | 16 |
+-------------------------------------------------|-----------------------------|------------------------------
+| Bitmap Possible | Yes | No | Yes | No |
+-------------------------------------------------|-----------------------------|------------------------------
+| Bitmap Size | 512 x 256 | N/A | 512x256 | N/A |
+| | 512 x 512 | | 512x512 | |
+| | 1024 x 256 | | | |
+| | 1024 x 512 | | | |
+-------------------------------------------------|-----------------------------|------------------------------
+| Scale | 0.25 x - 256 x | None | Any ? |
+-------------------------------------------------|-----------------------------|------------------------------
+| Rotation | No | Yes |
+-------------------------------------------------|-----------------------------|-----------------------------|
+| Linescroll | Yes | No |
+-------------------------------------------------|-----------------------------|------------------------------
+| Column Scroll | Yes | No |
+-------------------------------------------------|-----------------------------|------------------------------
+| Mosaic | Yes | Horizontal Only |
+-------------------------------------------------|-----------------------------|------------------------------
+
+*/
+
+
+
+/* 18000C - RESERVED
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+/* 18000E - r/w - RAMCTL - RAM Control
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | CRKTE | -- | CRMD1 | CRMD0 | -- | -- | VRBMD | VRAMD |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | RDBSB11 | RDBSB10 | RDBSB01 | RDBSB00 | RDBSA11 | RDBSA10 | RDBSA01 | RDBSA00 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_RAMCTL (vdp2_regs[0x00e/2])
+
+ #define VDP2_CRKTE ((VDP2_RAMCTL & 0x8000) >> 15)
+ #define VDP2_CRMD ((VDP2_RAMCTL & 0x3000) >> 12)
+ #define VDP2_RDBSB1 ((VDP2_RAMCTL & 0x00c0) >> 6)
+ #define VDP2_RDBSB0 ((VDP2_RAMCTL & 0x0030) >> 4)
+ #define VDP2_RDBSA1 ((VDP2_RAMCTL & 0x000c) >> 2)
+ #define VDP2_RDBSA0 ((VDP2_RAMCTL & 0x0003) >> 0)
+
+
+/* 180010 - r/w - -CYCA0L - VRAM CYCLE PATTERN (BANK A0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP0A03 | VCP0A02 | VCP0A01 | VCP0A00 | VCP1A03 | VCP1A02 | VCP1A01 | VCP1A00 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP2A03 | VCP2A02 | VCP2A01 | VCP2A00 | VCP3A03 | VCP3A02 | VCP3A01 | VCP3A00 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA0L (vdp2_regs[0x010/2])
+
+/* 180012 - r/w - -CYCA0U - VRAM CYCLE PATTERN (BANK A0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP4A03 | VCP4A02 | VCP4A01 | VCP4A00 | VCP5A03 | VCP5A02 | VCP5A01 | VCP5A00 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP6A03 | VCP6A02 | VCP6A01 | VCP6A00 | VCP7A03 | VCP7A02 | VCP7A01 | VCP7A00 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA0U (vdp2_regs[0x012/2])
+
+/* 180014 - r/w - -CYCA1L - VRAM CYCLE PATTERN (BANK A1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP0A13 | VCP0A12 | VCP0A11 | VCP0A10 | VCP1A13 | VCP1A12 | VCP1A11 | VCP1A10 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP2A13 | VCP2A12 | VCP2A11 | VCP2A10 | VCP3A13 | VCP3A12 | VCP3A11 | VCP3A10 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA1L (vdp2_regs[0x014/2])
+
+/* 180016 - r/w - -CYCA1U - VRAM CYCLE PATTERN (BANK A1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP4A13 | VCP4A12 | VCP4A11 | VCP4A10 | VCP5A13 | VCP5A12 | VCP5A11 | VCP5A10 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP6A13 | VCP6A12 | VCP6A11 | VCP6A10 | VCP7A13 | VCP7A12 | VCP7A11 | VCP7A10 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA1U (vdp2_regs[0x016/2])
+
+/* 180018 - r/w - -CYCB0L - VRAM CYCLE PATTERN (BANK B0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP0B03 | VCP0B02 | VCP0B01 | VCP0B00 | VCP1B03 | VCP1B02 | VCP1B01 | VCP1B00 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP2B03 | VCP2B02 | VCP2B01 | VCP2B00 | VCP3B03 | VCP3B02 | VCP3B01 | VCP3B00 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA2L (vdp2_regs[0x018/2])
+
+/* 18001A - r/w - -CYCB0U - VRAM CYCLE PATTERN (BANK B0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP4B03 | VCP4B02 | VCP4B01 | VCP4B00 | VCP5B03 | VCP5B02 | VCP5B01 | VCP5B00 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP6B03 | VCP6B02 | VCP6B01 | VCP6B00 | VCP7B03 | VCP7B02 | VCP7B01 | VCP7B00 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA2U (vdp2_regs[0x01a/2])
+
+/* 18001C - r/w - -CYCB1L - VRAM CYCLE PATTERN (BANK B1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP0B13 | VCP0B12 | VCP0B11 | VCP0B10 | VCP1B13 | VCP1B12 | VCP1B11 | VCP1B10 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP2B13 | VCP2B12 | VCP2B11 | VCP2B10 | VCP3B13 | VCP3B12 | VCP3B11 | VCP3B10 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA3L (vdp2_regs[0x01c/2])
+
+/* 18001E - r/w - -CYCB1U - VRAM CYCLE PATTERN (BANK B1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | VCP4B13 | VCP4B12 | VCP4B11 | VCP4B10 | VCP5B13 | VCP5B12 | VCP5B11 | VCP5B10 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | VCP6B13 | VCP6B12 | VCP6B11 | VCP6B10 | VCP7B13 | VCP7B12 | VCP7B11 | VCP7B10 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CYCA3U (vdp2_regs[0x01e/2])
+
+/* 180020 - r/w - BGON - SCREEN DISPLAY ENABLE
+
+ this register allows each tilemap to be enabled or disabled and also which layers are solid
+
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | R0TPON | N3TPON | N2TPON | N1TPON | N0TPON |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | R1ON | R0ON | N3ON | N2ON | N1ON | N0ON |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_BGON (vdp2_regs[0x020/2])
+
+ /* NxOn - Layer Enable Register */
+ #define VDP2_xxON ((VDP2_BGON & 0x001f) >> 0) /* to see if anything is enabled */
+
+ #define VDP2_N0ON ((VDP2_BGON & 0x0001) >> 0) /* N0On = NBG0 Enable */
+ #define VDP2_N1ON ((VDP2_BGON & 0x0002) >> 1) /* N1On = NBG1 Enable */
+ #define VDP2_N2ON ((VDP2_BGON & 0x0004) >> 2) /* N2On = NBG2 Enable */
+ #define VDP2_N3ON ((VDP2_BGON & 0x0008) >> 3) /* N3On = NBG3 Enable */
+ #define VDP2_R0ON ((VDP2_BGON & 0x0010) >> 4) /* R0On = RBG0 Enable */
+ #define VDP2_R1ON ((VDP2_BGON & 0x0020) >> 5) /* R1On = RBG1 Enable */
+
+ /* NxTPON - Transparency Pen Enable Registers */
+ #define VDP2_N0TPON ((VDP2_BGON & 0x0100) >> 8) /* N0TPON = NBG0 Draw Transparent Pen (as solid) /or/ RBG1 Draw Transparent Pen */
+ #define VDP2_N1TPON ((VDP2_BGON & 0x0200) >> 9) /* N1TPON = NBG1 Draw Transparent Pen (as solid) /or/ EXBG Draw Transparent Pen */
+ #define VDP2_N2TPON ((VDP2_BGON & 0x0400) >> 10)/* N2TPON = NBG2 Draw Transparent Pen (as solid) */
+ #define VDP2_N3TPON ((VDP2_BGON & 0x0800) >> 11)/* N3TPON = NBG3 Draw Transparent Pen (as solid) */
+ #define VDP2_R0TPON ((VDP2_BGON & 0x1000) >> 12)/* R0TPON = RBG0 Draw Transparent Pen (as solid) */
+
+/*
+180022 - MZCTL - Mosaic Control
+bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MZCTL (vdp2_regs[0x022/2])
+
+ #define VDP2_MZSZV ((VDP2_MZCTL & 0xf000) >> 12)
+ #define VDP2_MZSZH ((VDP2_MZCTL & 0x0f00) >> 8)
+ #define VDP2_R0MZE ((VDP2_MZCTL & 0x0010) >> 4)
+ #define VDP2_N3MZE ((VDP2_MZCTL & 0x0008) >> 3)
+ #define VDP2_N2MZE ((VDP2_MZCTL & 0x0004) >> 2)
+ #define VDP2_N1MZE ((VDP2_MZCTL & 0x0002) >> 1)
+ #define VDP2_N0MZE ((VDP2_MZCTL & 0x0001) >> 0)
+
+/*180024 - Special Function Code Select
+
+*/
+
+ #define VDP2_SFSEL (vdp2_regs[0x024/2])
+
+/*180026 - Special Function Code
+
+*/
+
+ #define VDP2_SFCODE (vdp2_regs[0x026/2])
+
+
+/*
+180028 - CHCTLA - Character Control (NBG0, NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | N1CHCN1 | N1CHCN0 | N1BMSZ1 | N1BMSZ0 | N1BMEN | N1CHSZ |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | N0CHCN2 | N0CHCN1 | N0CHCN0 | N0BMSZ1 | N0BMSZ0 | N0BMEN | N0CHSZ |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CHCTLA (vdp2_regs[0x028/2])
+
+/* -------------------------- NBG0 Character Control Registers -------------------------- */
+
+/* N0CHCNx NBG0 (or RGB1) Colour Depth
+ 000 - 16 Colours
+ 001 - 256 Colours
+ 010 - 2048 Colours
+ 011 - 32768 Colours (RGB5)
+ 100 - 16770000 Colours (RGB8)
+ 101 - invalid
+ 110 - invalid
+ 111 - invalid */
+ #define VDP2_N0CHCN ((VDP2_CHCTLA & 0x0070) >> 4)
+
+/* N0BMSZx - NBG0 Bitmap Size *guessed*
+ 00 - 512 x 256
+ 01 - 512 x 512
+ 10 - 1024 x 256
+ 11 - 1024 x 512 */
+ #define VDP2_N0BMSZ ((VDP2_CHCTLA & 0x000c) >> 2)
+
+/* N0BMEN - NBG0 Bitmap Enable
+ 0 - use cell mode
+ 1 - use bitmap mode */
+ #define VDP2_N0BMEN ((VDP2_CHCTLA & 0x0002) >> 1)
+
+/* N0CHSZ - NBG0 Character (Tile) Size
+ 0 - 1 cell x 1 cell (8x8)
+ 1 - 2 cells x 2 cells (16x16) */
+ #define VDP2_N0CHSZ ((VDP2_CHCTLA & 0x0001) >> 0)
+
+/* -------------------------- NBG1 Character Control Registers -------------------------- */
+
+/* N1CHCNx - NBG1 (or EXB1) Colour Depth
+ 00 - 16 Colours
+ 01 - 256 Colours
+ 10 - 2048 Colours
+ 11 - 32768 Colours (RGB5) */
+ #define VDP2_N1CHCN ((VDP2_CHCTLA & 0x3000) >> 12)
+
+/* N1BMSZx - NBG1 Bitmap Size *guessed*
+ 00 - 512 x 256
+ 01 - 512 x 512
+ 10 - 1024 x 256
+ 11 - 1024 x 512 */
+ #define VDP2_N1BMSZ ((VDP2_CHCTLA & 0x0c00) >> 10)
+
+/* N1BMEN - NBG1 Bitmap Enable
+ 0 - use cell mode
+ 1 - use bitmap mode */
+ #define VDP2_N1BMEN ((VDP2_CHCTLA & 0x0200) >> 9)
+
+/* N1CHSZ - NBG1 Character (Tile) Size
+ 0 - 1 cell x 1 cell (8x8)
+ 1 - 2 cells x 2 cells (16x16) */
+ #define VDP2_N1CHSZ ((VDP2_CHCTLA & 0x0100) >> 8)
+
+/*
+18002A - CHCTLB - Character Control (NBG2, NBG1, RBG0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | R0CHCN2 | R0CHCN1 | R0CHCN0 | -- | R0BMSZ | R0BMEN | R0CHSZ |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | N3CHCN | N3CHSZ | -- | -- | N2CHCN | N2CHSZ |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CHCTLB (vdp2_regs[0x02a/2])
+
+/* -------------------------- RBG0 Character Control Registers -------------------------- */
+
+
+/* R0CHCNx RBG0 Colour Depth
+ 000 - 16 Colours
+ 001 - 256 Colours
+ 010 - 2048 Colours
+ 011 - 32768 Colours (RGB5)
+ 100 - 16770000 Colours (RGB8)
+ 101 - invalid
+ 110 - invalid
+ 111 - invalid */
+ #define VDP2_R0CHCN ((VDP2_CHCTLB & 0x7000) >> 12)
+
+/* R0BMSZx - RBG0 Bitmap Size *guessed*
+ 00 - 512 x 256
+ 01 - 512 x 512 */
+ #define VDP2_R0BMSZ ((VDP2_CHCTLB & 0x0400) >> 10)
+
+/* R0BMEN - RBG0 Bitmap Enable
+ 0 - use cell mode
+ 1 - use bitmap mode */
+ #define VDP2_R0BMEN ((VDP2_CHCTLB & 0x0200) >> 9)
+
+/* R0CHSZ - RBG0 Character (Tile) Size
+ 0 - 1 cell x 1 cell (8x8)
+ 1 - 2 cells x 2 cells (16x16) */
+ #define VDP2_R0CHSZ ((VDP2_CHCTLB & 0x0100) >> 8)
+
+ #define VDP2_N3CHCN ((VDP2_CHCTLB & 0x0020) >> 5)
+ #define VDP2_N3CHSZ ((VDP2_CHCTLB & 0x0010) >> 4)
+ #define VDP2_N2CHCN ((VDP2_CHCTLB & 0x0002) >> 1)
+ #define VDP2_N2CHSZ ((VDP2_CHCTLB & 0x0001) >> 0)
+
+
+/*
+18002C - BMPNA - Bitmap Palette Number (NBG0, NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_BMPNA (vdp2_regs[0x02c/2])
+
+ #define VDP2_N1BMP ((VDP2_BMPNA & 0x0700) >> 8)
+ #define VDP2_N0BMP ((VDP2_BMPNA & 0x0007) >> 0)
+
+/* 18002E - Bitmap Palette Number (RBG0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_BMPNB (vdp2_regs[0x02e/2])
+
+ #define VDP2_R0BMP ((VDP2_BMPNB & 0x0007) >> 0)
+
+/* 180030 - PNCN0 - Pattern Name Control (NBG0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | N0PNB | N0CNSM | -- | -- | -- | -- | N0SPR | N0SCC |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | N0SPLT6 | N0SPLT5 | N0SPLT4 | N0SPCN4 | N0SPCN3 | N0SPCN2 | N0SPCN1 | N0SPCN0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PNCN0 (vdp2_regs[0x030/2])
+
+/* Pattern Data Size
+ 0 = 2 bytes
+ 1 = 1 byte */
+ #define VDP2_N0PNB ((VDP2_PNCN0 & 0x8000) >> 15)
+
+/* Character Number Supplement (in 1 byte mode)
+ 0 = Character Number = 10bits + 2bits for flip
+ 1 = Character Number = 12 bits, no flip */
+ #define VDP2_N0CNSM ((VDP2_PNCN0 & 0x4000) >> 14)
+
+/* NBG0 Special Priority Register (in 1 byte mode) */
+ #define VDP2_N0SPR ((VDP2_PNCN0 & 0x0200) >> 9)
+
+/* NBG0 Special Colour Control Register (in 1 byte mode) */
+ #define VDP2_N0SCC ((VDP2_PNCN0 & 0x0100) >> 8)
+
+/* Supplementary Palette Bits (in 1 byte mode) */
+ #define VDP2_N0SPLT ((VDP2_PNCN0 & 0x00e0) >> 5)
+
+/* Supplementary Character Bits (in 1 byte mode) */
+ #define VDP2_N0SPCN ((VDP2_PNCN0 & 0x001f) >> 0)
+
+/* 180032 - Pattern Name Control (NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PNCN1 (vdp2_regs[0x032/2])
+
+/* Pattern Data Size
+ 0 = 2 bytes
+ 1 = 1 byte */
+ #define VDP2_N1PNB ((VDP2_PNCN1 & 0x8000) >> 15)
+
+/* Character Number Supplement (in 1 byte mode)
+ 0 = Character Number = 10bits + 2bits for flip
+ 1 = Character Number = 12 bits, no flip */
+ #define VDP2_N1CNSM ((VDP2_PNCN1 & 0x4000) >> 14)
+
+/* NBG0 Special Priority Register (in 1 byte mode) */
+ #define VDP2_N1SPR ((VDP2_PNCN1 & 0x0200) >> 9)
+
+/* NBG0 Special Colour Control Register (in 1 byte mode) */
+ #define VDP2_N1SCC ((VDP2_PNCN1 & 0x0100) >> 8)
+
+/* Supplementary Palette Bits (in 1 byte mode) */
+ #define VDP2_N1SPLT ((VDP2_PNCN1 & 0x00e0) >> 5)
+
+/* Supplementary Character Bits (in 1 byte mode) */
+ #define VDP2_N1SPCN ((VDP2_PNCN1 & 0x001f) >> 0)
+
+
+/* 180034 - Pattern Name Control (NBG2)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PNCN2 (vdp2_regs[0x034/2])
+
+/* Pattern Data Size
+ 0 = 2 bytes
+ 1 = 1 byte */
+ #define VDP2_N2PNB ((VDP2_PNCN2 & 0x8000) >> 15)
+
+/* Character Number Supplement (in 1 byte mode)
+ 0 = Character Number = 10bits + 2bits for flip
+ 1 = Character Number = 12 bits, no flip */
+ #define VDP2_N2CNSM ((VDP2_PNCN2 & 0x4000) >> 14)
+
+/* NBG0 Special Priority Register (in 1 byte mode) */
+ #define VDP2_N2SPR ((VDP2_PNCN2 & 0x0200) >> 9)
+
+/* NBG0 Special Colour Control Register (in 1 byte mode) */
+ #define VDP2_N2SCC ((VDP2_PNCN2 & 0x0100) >> 8)
+
+/* Supplementary Palette Bits (in 1 byte mode) */
+ #define VDP2_N2SPLT ((VDP2_PNCN2 & 0x00e0) >> 5)
+
+/* Supplementary Character Bits (in 1 byte mode) */
+ #define VDP2_N2SPCN ((VDP2_PNCN2 & 0x001f) >> 0)
+
+
+/* 180036 - Pattern Name Control (NBG3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | N3PNB | N3CNSM | -- | -- | -- | -- | N3SPR | N3SCC |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | N3SPLT6 | N3SPLT5 | N3SPLT4 | N3SPCN4 | N3SPCN3 | N3SPCN2 | N3SPCN1 | N3SPCN0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PNCN3 (vdp2_regs[0x036/2])
+
+/* Pattern Data Size
+ 0 = 2 bytes
+ 1 = 1 byte */
+ #define VDP2_N3PNB ((VDP2_PNCN3 & 0x8000) >> 15)
+
+/* Character Number Supplement (in 1 byte mode)
+ 0 = Character Number = 10bits + 2bits for flip
+ 1 = Character Number = 12 bits, no flip */
+ #define VDP2_N3CNSM ((VDP2_PNCN3 & 0x4000) >> 14)
+
+/* NBG0 Special Priority Register (in 1 byte mode) */
+ #define VDP2_N3SPR ((VDP2_PNCN3 & 0x0200) >> 9)
+
+/* NBG0 Special Colour Control Register (in 1 byte mode) */
+ #define VDP2_N3SCC ((VDP2_PNCN3 & 0x0100) >> 8)
+
+/* Supplementary Palette Bits (in 1 byte mode) */
+ #define VDP2_N3SPLT ((VDP2_PNCN3 & 0x00e0) >> 5)
+
+/* Supplementary Character Bits (in 1 byte mode) */
+ #define VDP2_N3SPCN ((VDP2_PNCN3 & 0x001f) >> 0)
+
+
+/* 180038 - Pattern Name Control (RBG0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PNCR (vdp2_regs[0x038/2])
+
+/* Pattern Data Size
+ 0 = 2 bytes
+ 1 = 1 byte */
+ #define VDP2_R0PNB ((VDP2_PNCR & 0x8000) >> 15)
+
+/* Character Number Supplement (in 1 byte mode)
+ 0 = Character Number = 10bits + 2bits for flip
+ 1 = Character Number = 12 bits, no flip */
+ #define VDP2_R0CNSM ((VDP2_PNCR & 0x4000) >> 14)
+
+/* NBG0 Special Priority Register (in 1 byte mode) */
+ #define VDP2_R0SPR ((VDP2_PNCR & 0x0200) >> 9)
+
+/* NBG0 Special Colour Control Register (in 1 byte mode) */
+ #define VDP2_R0SCC ((VDP2_PNCR & 0x0100) >> 8)
+
+/* Supplementary Palette Bits (in 1 byte mode) */
+ #define VDP2_R0SPLT ((VDP2_PNCR & 0x00e0) >> 5)
+
+/* Supplementary Character Bits (in 1 byte mode) */
+ #define VDP2_R0SPCN ((VDP2_PNCR & 0x001f) >> 0)
+
+/* 18003A - PLSZ - Plane Size
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | N3PLSZ1 | N3PLSZ0 | -- | -- | N1PLSZ1 | N1PLSZ0 | N0PLSZ1 | N0PLSZ0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PLSZ (vdp2_regs[0x03a/2])
+
+ /* NBG0 Plane Size
+ 00 1H Page x 1V Page
+ 01 2H Pages x 1V Page
+ 10 invalid
+ 11 2H Pages x 2V Pages */
+ #define VDP2_RBOVR ((VDP2_PLSZ & 0xc000) >> 14)
+ #define VDP2_RBPLSZ ((VDP2_PLSZ & 0x3000) >> 12)
+ #define VDP2_RAOVR ((VDP2_PLSZ & 0x0c00) >> 10)
+ #define VDP2_RAPLSZ ((VDP2_PLSZ & 0x0300) >> 8)
+ #define VDP2_N3PLSZ ((VDP2_PLSZ & 0x00c0) >> 6)
+ #define VDP2_N2PLSZ ((VDP2_PLSZ & 0x0030) >> 4)
+ #define VDP2_N1PLSZ ((VDP2_PLSZ & 0x000c) >> 2)
+ #define VDP2_N0PLSZ ((VDP2_PLSZ & 0x0003) >> 0)
+
+/* 18003C - MPOFN - Map Offset (NBG0, NBG1, NBG2, NBG3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | N3MP8 | N3MP7 | N3MP6 | -- | N2MP8 | N2MP7 | N2MP6 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | N1MP8 | N1MP7 | N1MP6 | -- | N0MP8 | N0MP7 | N0MP6 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPOFN_ (vdp2_regs[0x03c/2])
+
+ /* Higher 3 bits of the map offset for each layer */
+ #define VDP2_N3MP_ ((VDP2_MPOFN_ & 0x3000) >> 12)
+ #define VDP2_N2MP_ ((VDP2_MPOFN_ & 0x0300) >> 8)
+ #define VDP2_N1MP_ ((VDP2_MPOFN_ & 0x0030) >> 4)
+ #define VDP2_N0MP_ ((VDP2_MPOFN_ & 0x0003) >> 0)
+
+
+
+
+/* 18003E - Map Offset (Rotation Parameter A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPOFR_ (vdp2_regs[0x03e/2])
+
+ #define VDP2_RBMP_ ((VDP2_MPOFR_ & 0x0030) >> 4)
+ #define VDP2_RAMP_ ((VDP2_MPOFR_ & 0x0003) >> 0)
+
+/* 180040 - MPABN0 - Map (NBG0, Plane A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | N0MPB5 | N0MPB4 | N0MPB3 | N0MPB2 | N0MPB1 | N0MPB0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | N0MPA5 | N0MPA4 | N0MPA3 | N0MPA2 | N0MPA1 | N0MPA0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPABN0 (vdp2_regs[0x040/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
+ #define VDP2_N0MPB ((VDP2_MPABN0 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
+ #define VDP2_N0MPA ((VDP2_MPABN0 & 0x003f) >> 0)
+
+
+/* 180042 - MPCDN0 - (NBG0, Plane C,D)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | N0MPD5 | N0MPD4 | N0MPD3 | N0MPD2 | N0MPD1 | N0MPD0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | N0MPC5 | N0MPC4 | N0MPC3 | N0MPC2 | N0MPC1 | N0MPC0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPCDN0 (vdp2_regs[0x042/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
+ #define VDP2_N0MPD ((VDP2_MPCDN0 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
+ #define VDP2_N0MPC ((VDP2_MPCDN0 & 0x003f) >> 0)
+
+
+/* 180044 - Map (NBG1, Plane A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPABN1 (vdp2_regs[0x044/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
+ #define VDP2_N1MPB ((VDP2_MPABN1 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
+ #define VDP2_N1MPA ((VDP2_MPABN1 & 0x003f) >> 0)
+
+/* 180046 - Map (NBG1, Plane C,D)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPCDN1 (vdp2_regs[0x046/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
+ #define VDP2_N1MPD ((VDP2_MPCDN1 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
+ #define VDP2_N1MPC ((VDP2_MPCDN1 & 0x003f) >> 0)
+
+
+/* 180048 - Map (NBG2, Plane A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPABN2 (vdp2_regs[0x048/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG2 */
+ #define VDP2_N2MPB ((VDP2_MPABN2 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG2 */
+ #define VDP2_N2MPA ((VDP2_MPABN2 & 0x003f) >> 0)
+
+/* 18004a - Map (NBG2, Plane C,D)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPCDN2 (vdp2_regs[0x04a/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG2 */
+ #define VDP2_N2MPD ((VDP2_MPCDN2 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG2 */
+ #define VDP2_N2MPC ((VDP2_MPCDN2 & 0x003f) >> 0)
+
+/* 18004c - Map (NBG3, Plane A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPABN3 (vdp2_regs[0x04c/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
+ #define VDP2_N3MPB ((VDP2_MPABN3 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
+ #define VDP2_N3MPA ((VDP2_MPABN3 & 0x003f) >> 0)
+
+
+/* 18004e - Map (NBG3, Plane C,D)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPCDN3 (vdp2_regs[0x04e/2])
+
+ /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
+ #define VDP2_N3MPD ((VDP2_MPCDN3 & 0x3f00) >> 8)
+
+ /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
+ #define VDP2_N3MPC ((VDP2_MPCDN3 & 0x003f) >> 0)
+
+/* 180050 - Map (Rotation Parameter A, Plane A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPABRA (vdp2_regs[0x050/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */
+ #define VDP2_RAMPB ((VDP2_MPABRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */
+ #define VDP2_RAMPA ((VDP2_MPABRA & 0x003f) >> 0)
+
+
+
+/* 180052 - Map (Rotation Parameter A, Plane C,D)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_MPCDRA (vdp2_regs[0x052/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */
+ #define VDP2_RAMPD ((VDP2_MPCDRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */
+ #define VDP2_RAMPC ((VDP2_MPCDRA & 0x003f) >> 0)
+
+/* 180054 - Map (Rotation Parameter A, Plane E,F)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_MPEFRA (vdp2_regs[0x054/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */
+ #define VDP2_RAMPF ((VDP2_MPEFRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
+ #define VDP2_RAMPE ((VDP2_MPEFRA & 0x003f) >> 0)
+
+/* 180056 - Map (Rotation Parameter A, Plane G,H)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_MPGHRA (vdp2_regs[0x056/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */
+ #define VDP2_RAMPH ((VDP2_MPGHRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */
+ #define VDP2_RAMPG ((VDP2_MPGHRA & 0x003f) >> 0)
+
+/* 180058 - Map (Rotation Parameter A, Plane I,J)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_MPIJRA (vdp2_regs[0x058/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */
+ #define VDP2_RAMPJ ((VDP2_MPIJRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane I of Tilemap RBG0 */
+ #define VDP2_RAMPI ((VDP2_MPIJRA & 0x003f) >> 0)
+
+/* 18005a - Map (Rotation Parameter A, Plane K,L)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_MPKLRA (vdp2_regs[0x05a/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */
+ #define VDP2_RAMPL ((VDP2_MPKLRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */
+ #define VDP2_RAMPK ((VDP2_MPKLRA & 0x003f) >> 0)
+
+/* 18005c - Map (Rotation Parameter A, Plane M,N)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_MPMNRA (vdp2_regs[0x05c/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */
+ #define VDP2_RAMPN ((VDP2_MPMNRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */
+ #define VDP2_RAMPM ((VDP2_MPMNRA & 0x003f) >> 0)
+
+/* 18005e - Map (Rotation Parameter A, Plane O,P)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_MPOPRA (vdp2_regs[0x05e/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */
+ #define VDP2_RAMPP ((VDP2_MPOPRA & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */
+ #define VDP2_RAMPO ((VDP2_MPOPRA & 0x003f) >> 0)
+
+/* 180060 - Map (Rotation Parameter B, Plane A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPABRB (vdp2_regs[0x060/2])
+
+ /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */
+ #define VDP2_RBMPB ((VDP2_MPABRB & 0x3f00) >> 8)
+
+ /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */
+ #define VDP2_RBMPA ((VDP2_MPABRB & 0x003f) >> 0)
+
+
+/* 180062 - Map (Rotation Parameter B, Plane C,D)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPCDRB (vdp2_regs[0x062/2])
+
+ /* R0MPD5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */
+ #define VDP2_RBMPD ((VDP2_MPCDRB & 0x3f00) >> 8)
+
+ /* R0MPc5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */
+ #define VDP2_RBMPC ((VDP2_MPCDRB & 0x003f) >> 0)
+
+/* 180064 - Map (Rotation Parameter B, Plane E,F)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPEFRB (vdp2_regs[0x064/2])
+
+ /* R0MPF5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */
+ #define VDP2_RBMPF ((VDP2_MPEFRB & 0x3f00) >> 8)
+
+ /* R0MPE5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
+ #define VDP2_RBMPE ((VDP2_MPEFRB & 0x003f) >> 0)
+
+/* 180066 - Map (Rotation Parameter B, Plane G,H)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPGHRB (vdp2_regs[0x066/2])
+
+ /* R0MPH5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */
+ #define VDP2_RBMPH ((VDP2_MPGHRB & 0x3f00) >> 8)
+
+ /* R0MPG5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */
+ #define VDP2_RBMPG ((VDP2_MPGHRB & 0x003f) >> 0)
+
+/* 180068 - Map (Rotation Parameter B, Plane I,J)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPIJRB (vdp2_regs[0x068/2])
+
+ /* R0MPJ5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */
+ #define VDP2_RBMPJ ((VDP2_MPIJRB & 0x3f00) >> 8)
+
+ /* R0MPI5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
+ #define VDP2_RBMPI ((VDP2_MPIJRB & 0x003f) >> 0)
+
+/* 18006a - Map (Rotation Parameter B, Plane K,L)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPKLRB (vdp2_regs[0x06a/2])
+
+ /* R0MPL5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */
+ #define VDP2_RBMPL ((VDP2_MPKLRB & 0x3f00) >> 8)
+
+ /* R0MPK5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */
+ #define VDP2_RBMPK ((VDP2_MPKLRB & 0x003f) >> 0)
+
+/* 18006c - Map (Rotation Parameter B, Plane M,N)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPMNRB (vdp2_regs[0x06c/2])
+
+ /* R0MPN5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */
+ #define VDP2_RBMPN ((VDP2_MPMNRB & 0x3f00) >> 8)
+
+ /* R0MPM5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */
+ #define VDP2_RBMPM ((VDP2_MPMNRB & 0x003f) >> 0)
+
+/* 18006e - Map (Rotation Parameter B, Plane O,P)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_MPOPRB (vdp2_regs[0x06e/2])
+
+ /* R0MPP5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */
+ #define VDP2_RBMPP ((VDP2_MPOPRB & 0x3f00) >> 8)
+
+ /* R0MPO5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */
+ #define VDP2_RBMPO ((VDP2_MPOPRB & 0x003f) >> 0)
+
+/* 180070 - SCXIN0 - Screen Scroll (NBG0, Horizontal Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCXIN0 (vdp2_regs[0x070/2])
+
+
+/* 180072 - Screen Scroll (NBG0, Horizontal Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCXDN0 (vdp2_regs[0x072/2])
+
+/* 180074 - SCYIN0 - Screen Scroll (NBG0, Vertical Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_SCYIN0 (vdp2_regs[0x074/2])
+
+
+/* 180076 - Screen Scroll (NBG0, Vertical Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCYDN0 (vdp2_regs[0x076/2])
+
+/* 180078 - Coordinate Inc (NBG0, Horizontal Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMXIN0 (vdp2_regs[0x078/2])
+
+ #define VDP2_N0ZMXI ((VDP2_ZMXIN0 & 0x0007) >> 0)
+
+/* 18007a - Coordinate Inc (NBG0, Horizontal Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMXDN0 (vdp2_regs[0x07a/2])
+
+ #define VDP2_N0ZMXD ((VDP2_ZMXDN0 >> 8)& 0xff)
+ #define VDP2_ZMXN0 (((VDP2_N0ZMXI<<16) | (VDP2_N0ZMXD<<8)) & 0x0007ff00)
+
+
+/* 18007c - Coordinate Inc (NBG0, Vertical Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMYIN0 (vdp2_regs[0x07c/2])
+
+ #define VDP2_N0ZMYI ((VDP2_ZMYIN0 & 0x0007) >> 0)
+
+/* 18007e - Coordinate Inc (NBG0, Vertical Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMYDN0 (vdp2_regs[0x07e/2])
+
+ #define VDP2_N0ZMYD ((VDP2_ZMYDN0 >> 8)& 0xff)
+ #define VDP2_ZMYN0 (((VDP2_N0ZMYI<<16) | (VDP2_N0ZMYD<<8)) & 0x0007ff00)
+
+/* 180080 - SCXIN1 - Screen Scroll (NBG1, Horizontal Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCXIN1 (vdp2_regs[0x080/2])
+
+/* 180082 - Screen Scroll (NBG1, Horizontal Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCXDN1 (vdp2_regs[0x082/2])
+
+/* 180084 - SCYIN1 - Screen Scroll (NBG1, Vertical Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCYIN1 (vdp2_regs[0x084/2])
+
+/* 180086 - Screen Scroll (NBG1, Vertical Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCYDN1 (vdp2_regs[0x086/2])
+
+/* 180088 - Coordinate Inc (NBG1, Horizontal Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMXIN1 (vdp2_regs[0x088/2])
+
+ #define VDP2_N1ZMXI ((VDP2_ZMXIN1 & 0x0007) >> 0)
+
+/* 18008a - Coordinate Inc (NBG1, Horizontal Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMXDN1 (vdp2_regs[0x08a/2])
+
+ #define VDP2_N1ZMXD ((VDP2_ZMXDN1 >> 8)& 0xff)
+ #define VDP2_ZMXN1 (((VDP2_N1ZMXI<<16) | (VDP2_N1ZMXD<<8)) & 0x0007ff00)
+
+/* 18008c - Coordinate Inc (NBG1, Vertical Integer Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMYIN1 (vdp2_regs[0x08c/2])
+
+ #define VDP2_N1ZMYI ((VDP2_ZMYIN1 & 0x0007) >> 0)
+
+/* 18008e - Coordinate Inc (NBG1, Vertical Fractional Part)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMYDN1 (vdp2_regs[0x08e/2])
+
+ #define VDP2_N1ZMYD ((VDP2_ZMYDN1 >> 8)& 0xff)
+ #define VDP2_ZMYN1 (((VDP2_N1ZMYI<<16) | (VDP2_N1ZMYD<<8)) & 0x007ff00)
+
+/* 180090 - SCXN2 - Screen Scroll (NBG2, Horizontal)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCXN2 (vdp2_regs[0x090/2])
+
+/* 180092 - SCYN2 - Screen Scroll (NBG2, Vertical)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCYN2 (vdp2_regs[0x092/2])
+
+/* 180094 - SCXN3 - Screen Scroll (NBG3, Horizontal)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCXN3 (vdp2_regs[0x094/2])
+
+/* 180096 - SCYN3 - Screen Scroll (NBG3, Vertical)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCYN3 (vdp2_regs[0x096/2])
+
+/* 180098 - Reduction Enable
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | N1ZMQT | N1ZMHF |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | N0ZMQT | N0ZMHF |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_ZMCTL (vdp2_regs[0x098/2])
+
+ #define VDP2_N1ZMQT ((VDP2_ZMCTL & 0x0200) >> 9)
+ #define VDP2_N1ZMHF ((VDP2_ZMCTL & 0x0100) >> 8)
+ #define VDP2_N0ZMQT ((VDP2_ZMCTL & 0x0002) >> 1)
+ #define VDP2_N0ZMHF ((VDP2_ZMCTL & 0x0001) >> 0)
+
+/* 18009a - Line and Vertical Cell Scroll Control (NBG0, NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SCRCTL (vdp2_regs[0x09a/2])
+
+ #define VDP2_N1LSS ((VDP2_SCRCTL & 0x3000) >> 12)
+ #define VDP2_N1LZMX ((VDP2_SCRCTL & 0x0800) >> 11)
+ #define VDP2_N1LSCY ((VDP2_SCRCTL & 0x0400) >> 10)
+ #define VDP2_N1LSCX ((VDP2_SCRCTL & 0x0200) >> 9)
+ #define VDP2_N1VCSC ((VDP2_SCRCTL & 0x0100) >> 8)
+ #define VDP2_N0LSS ((VDP2_SCRCTL & 0x0030) >> 4)
+ #define VDP2_N0LZMX ((VDP2_SCRCTL & 0x0008) >> 3)
+ #define VDP2_N0LSCY ((VDP2_SCRCTL & 0x0004) >> 2)
+ #define VDP2_N0LSCX ((VDP2_SCRCTL & 0x0002) >> 1)
+ #define VDP2_N0VCSC ((VDP2_SCRCTL & 0x0001) >> 0)
+
+/* 18009c - Vertical Cell Table Address (NBG0, NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_VCSTAU (vdp2_regs[0x09c/2] & 7)
+
+
+/* 18009e - Vertical Cell Table Address (NBG0, NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_VCSTAL (vdp2_regs[0x09e/2])
+
+/* 1800a0 - LSTA0U - Line Scroll Table Address (NBG0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ /*bit 2 unused when VRAM = 4 Mbits*/
+ #define VDP2_LSTA0U (vdp2_regs[0x0a0/2] & 7)
+
+/* 1800a2 - LSTA0L - Line Scroll Table Address (NBG0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LSTA0L (vdp2_regs[0x0a2/2])
+
+/* 1800a4 - LSTA1U - Line Scroll Table Address (NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ /*bit 2 unused when VRAM = 4 Mbits*/
+ #define VDP2_LSTA1U (vdp2_regs[0x0a4/2] & 7)
+
+/* 1800a6 - LSTA1L - Line Scroll Table Address (NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LSTA1L (vdp2_regs[0x0a6/2])
+
+/* 1800a8 - LCTAU - Line Colour Screen Table Address
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LCTAU (vdp2_regs[0x0a8/2])
+ #define VDP2_LCCLMD ((VDP2_LCTAU & 0x8000) >> 15)
+
+/* 1800aa - LCTAL - Line Colour Screen Table Address
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_LCTAL (vdp2_regs[0x0aa/2])
+
+ #define VDP2_LCTA (((VDP2_LCTAU & 0x0007) << 16) | (VDP2_LCTAL & 0xffff))
+
+/* 1800ac - Back Screen Table Address
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | BKCLMD | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | BKTA18 | BKTA17 | BKTA16 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_BKTAU (vdp2_regs[0x0ac/2])
+
+ #define VDP2_BKCLMD ((VDP2_BKTAU & 0x8000) >> 15)
+
+
+/* 1800ae - Back Screen Table Address
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | BKTA15 | BKTA14 | BKTA13 | BKTA12 | BKTA11 | BKTA10 | BKTA9 | BKTA8 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | BKTA7 | BKTA7 | BKTA6 | BKTA5 | BKTA4 | BKTA3 | BKTA2 | BKTA0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_BKTAL (vdp2_regs[0x0ae/2])
+
+ #define VDP2_BKTA (((VDP2_BKTAU & 0x0007) << 16) | (VDP2_BKTAL & 0xffff))
+
+/* 1800b0 - RPMD - Rotation Parameter Mode
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_RPMD ((vdp2_regs[0x0b0/2]) & 0x0003)
+
+/* 1800b2 - RPRCTL - Rotation Parameter Read Control
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | RBKASTRE | RBYSTRE | RBXSTRE |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | RAKASTRE | RAYSTRE | RBXSTRE |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_RPRCTL (vdp2_regs[0x0b2/2])
+ #define VDP2_RBKASTRE ((VDP2_RPRCTL & 0x0400) >> 10)
+ #define VDP2_RBYSTRE ((VDP2_RPRCTL & 0x0200) >> 9)
+ #define VDP2_RBXSTRE ((VDP2_RPRCTL & 0x0100) >> 8)
+ #define VDP2_RAKASTRE ((VDP2_RPRCTL & 0x0004) >> 2)
+ #define VDP2_RAYSTRE ((VDP2_RPRCTL & 0x0002) >> 1)
+ #define VDP2_RAXSTRE ((VDP2_RPRCTL & 0x0001) >> 0)
+
+/* 1800b4 - KTCTL - Coefficient Table Control
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | RBKLCE | RBKMD1 | RBKMD0 | RBKDBS | RBKTE |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | RAKLCE | RAKMD1 | RAKMD0 | RAKDBS | RAKTE |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_KTCTL (vdp2_regs[0x0b4/2])
+ #define VDP2_RBUNK ((VDP2_KTCTL & 0x6000) >> 13)
+ #define VDP2_RBKLCE ((VDP2_KTCTL & 0x1000) >> 12)
+ #define VDP2_RBKMD ((VDP2_KTCTL & 0x0c00) >> 10)
+ #define VDP2_RBKDBS ((VDP2_KTCTL & 0x0200) >> 9)
+ #define VDP2_RBKTE ((VDP2_KTCTL & 0x0100) >> 8)
+ #define VDP2_RAUNK ((VDP2_KTCTL & 0x0060) >> 5)
+ #define VDP2_RAKLCE ((VDP2_KTCTL & 0x0010) >> 4)
+ #define VDP2_RAKMD ((VDP2_KTCTL & 0x000c) >> 2)
+ #define VDP2_RAKDBS ((VDP2_KTCTL & 0x0002) >> 1)
+ #define VDP2_RAKTE ((VDP2_KTCTL & 0x0001) >> 0)
+
+/* 1800b6 - KTAOF - Coefficient Table Address Offset (Rotation Parameter A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | RBKTAOS2 | RBKTAOS1 | RBKTAOS0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | RAKTAOS2 | RAKTAOS1 | RAKTAOS0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_KTAOF (vdp2_regs[0x0b6/2])
+ #define VDP2_RBKTAOS ((VDP2_KTAOF & 0x0700) >> 8)
+ #define VDP2_RAKTAOS ((VDP2_KTAOF & 0x0007) >> 0)
+
+/* 1800b8 - OVPNRA - Screen Over Pattern Name (Rotation Parameter A)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_OVPNRA (vdp2_regs[0x0b8/2])
+
+/* 1800ba - Screen Over Pattern Name (Rotation Parameter B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_OVPNRB (vdp2_regs[0x0ba/2])
+
+/* 1800bc - RPTAU - Rotation Parameter Table Address (Rotation Parameter A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | RPTA18 | RPTA17 | RPTA16 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_RPTAU (vdp2_regs[0x0bc/2] & 7)
+
+/* 1800be - RPTAL - Rotation Parameter Table Address (Rotation Parameter A,B)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | RPTA15 | RPTA14 | RPTA13 | RPTA12 | RPTA11 | RPTA10 | RPTA9 | RPTA8 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | RPTA7 | RPTA6 | RPTA5 | RPTA4 | RPTA3 | RPTA2 | RPTA1 | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_RPTAL (vdp2_regs[0x0be/2] & 0x0000ffff)
+
+/* 1800c0 - Window Position (W0, Horizontal Start Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPSX0 (vdp2_regs[0x0c0/2])
+
+ #define VDP2_W0SX ((VDP2_WPSX0 & 0x03ff) >> 0)
+
+/* 1800c2 - Window Position (W0, Vertical Start Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPSY0 (vdp2_regs[0x0c2/2])
+
+ #define VDP2_W0SY ((VDP2_WPSY0 & 0x07ff) >> 0)
+
+/* 1800c4 - Window Position (W0, Horizontal End Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPEX0 (vdp2_regs[0x0c4/2])
+
+ #define VDP2_W0EX ((VDP2_WPEX0 & 0x03ff) >> 0)
+
+/* 1800c6 - Window Position (W0, Vertical End Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPEY0 (vdp2_regs[0x0c6/2])
+
+ #define VDP2_W0EY ((VDP2_WPEY0 & 0x07ff) >> 0)
+
+/* 1800c8 - Window Position (W1, Horizontal Start Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPSX1 (vdp2_regs[0x0c8/2])
+
+ #define VDP2_W1SX ((VDP2_WPSX1 & 0x03ff) >> 0)
+
+/* 1800ca - Window Position (W1, Vertical Start Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPSY1 (vdp2_regs[0x0ca/2])
+
+ #define VDP2_W1SY ((VDP2_WPSY1 & 0x07ff) >> 0)
+
+/* 1800cc - Window Position (W1, Horizontal End Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPEX1 (vdp2_regs[0x0cc/2])
+
+ #define VDP2_W1EX ((VDP2_WPEX1 & 0x03ff) >> 0)
+
+/* 1800ce - Window Position (W1, Vertical End Point)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WPEY1 (vdp2_regs[0x0ce/2])
+
+ #define VDP2_W1EY ((VDP2_WPEY1 & 0x07ff) >> 0)
+
+/* 1800d0 - Window Control (NBG0, NBG1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WCTLA (vdp2_regs[0x0d0/2])
+ #define VDP2_N1LOG ((VDP2_WCTLA & 0x8000) >> 15)
+ #define VDP2_N1SWE ((VDP2_WCTLA & 0x2000) >> 13)
+ #define VDP2_N1SWA ((VDP2_WCTLA & 0x1000) >> 12)
+ #define VDP2_N1W1E ((VDP2_WCTLA & 0x0800) >> 11)
+ #define VDP2_N1W1A ((VDP2_WCTLA & 0x0400) >> 10)
+ #define VDP2_N1W0E ((VDP2_WCTLA & 0x0200) >> 9)
+ #define VDP2_N1W0A ((VDP2_WCTLA & 0x0100) >> 8)
+ #define VDP2_N0LOG ((VDP2_WCTLA & 0x0080) >> 7)
+ #define VDP2_N0SWE ((VDP2_WCTLA & 0x0020) >> 5)
+ #define VDP2_N0SWA ((VDP2_WCTLA & 0x0010) >> 4)
+ #define VDP2_N0W1E ((VDP2_WCTLA & 0x0008) >> 3)
+ #define VDP2_N0W1A ((VDP2_WCTLA & 0x0004) >> 2)
+ #define VDP2_N0W0E ((VDP2_WCTLA & 0x0002) >> 1)
+ #define VDP2_N0W0A ((VDP2_WCTLA & 0x0001) >> 0)
+
+/* 1800d2 - Window Control (NBG2, NBG3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WCTLB (vdp2_regs[0x0d2/2])
+ #define VDP2_N3LOG ((VDP2_WCTLB & 0x8000) >> 15)
+ #define VDP2_N3SWE ((VDP2_WCTLB & 0x2000) >> 13)
+ #define VDP2_N3SWA ((VDP2_WCTLB & 0x1000) >> 12)
+ #define VDP2_N3W1E ((VDP2_WCTLB & 0x0800) >> 11)
+ #define VDP2_N3W1A ((VDP2_WCTLB & 0x0400) >> 10)
+ #define VDP2_N3W0E ((VDP2_WCTLB & 0x0200) >> 9)
+ #define VDP2_N3W0A ((VDP2_WCTLB & 0x0100) >> 8)
+ #define VDP2_N2LOG ((VDP2_WCTLB & 0x0080) >> 7)
+ #define VDP2_N2SWE ((VDP2_WCTLB & 0x0020) >> 5)
+ #define VDP2_N2SWA ((VDP2_WCTLB & 0x0010) >> 4)
+ #define VDP2_N2W1E ((VDP2_WCTLB & 0x0008) >> 3)
+ #define VDP2_N2W1A ((VDP2_WCTLB & 0x0004) >> 2)
+ #define VDP2_N2W0E ((VDP2_WCTLB & 0x0002) >> 1)
+ #define VDP2_N2W0A ((VDP2_WCTLB & 0x0001) >> 0)
+
+/* 1800d4 - Window Control (RBG0, Sprite)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WCTLC (vdp2_regs[0x0d4/2])
+ #define VDP2_SPLOG ((VDP2_WCTLC & 0x8000) >> 15)
+ #define VDP2_SPSWE ((VDP2_WCTLC & 0x2000) >> 13)
+ #define VDP2_SPSWA ((VDP2_WCTLC & 0x1000) >> 12)
+ #define VDP2_SPW1E ((VDP2_WCTLC & 0x0800) >> 11)
+ #define VDP2_SPW1A ((VDP2_WCTLC & 0x0400) >> 10)
+ #define VDP2_SPW0E ((VDP2_WCTLC & 0x0200) >> 9)
+ #define VDP2_SPW0A ((VDP2_WCTLC & 0x0100) >> 8)
+ #define VDP2_R0LOG ((VDP2_WCTLC & 0x0080) >> 7)
+ #define VDP2_R0SWE ((VDP2_WCTLC & 0x0020) >> 5)
+ #define VDP2_R0SWA ((VDP2_WCTLC & 0x0010) >> 4)
+ #define VDP2_R0W1E ((VDP2_WCTLC & 0x0008) >> 3)
+ #define VDP2_R0W1A ((VDP2_WCTLC & 0x0004) >> 2)
+ #define VDP2_R0W0E ((VDP2_WCTLC & 0x0002) >> 1)
+ #define VDP2_R0W0A ((VDP2_WCTLC & 0x0001) >> 0)
+
+/* 1800d6 - Window Control (Parameter Window, Colour Calc. Window)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_WCTLD (vdp2_regs[0x0d6/2])
+ #define VDP2_CCLOG ((VDP2_WCTLD & 0x8000) >> 15)
+ #define VDP2_CCSWE ((VDP2_WCTLD & 0x2000) >> 13)
+ #define VDP2_CCSWA ((VDP2_WCTLD & 0x1000) >> 12)
+ #define VDP2_CCW1E ((VDP2_WCTLD & 0x0800) >> 11)
+ #define VDP2_CCW1A ((VDP2_WCTLD & 0x0400) >> 10)
+ #define VDP2_CCW0E ((VDP2_WCTLD & 0x0200) >> 9)
+ #define VDP2_CCW0A ((VDP2_WCTLD & 0x0100) >> 8)
+ #define VDP2_RPLOG ((VDP2_WCTLD & 0x0080) >> 7)
+ #define VDP2_RPW1E ((VDP2_WCTLD & 0x0008) >> 3)
+ #define VDP2_RPW1A ((VDP2_WCTLD & 0x0004) >> 2)
+ #define VDP2_RPW0E ((VDP2_WCTLD & 0x0002) >> 1)
+ #define VDP2_RPW0A ((VDP2_WCTLD & 0x0001) >> 0)
+
+/* 1800d8 - Line Window Table Address (W0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LWTA0U (vdp2_regs[0x0d8/2])
+
+ #define VDP2_W0LWE ((VDP2_LWTA0U & 0x8000) >> 15)
+
+/* 1800da - Line Window Table Address (W0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LWTA0L (vdp2_regs[0x0da/2])
+
+ /* bit 19 isn't used when VRAM = 4 Mbit */
+ #define VDP2_W0LWTA (((VDP2_LWTA0U & 0x0007) << 16) | (VDP2_LWTA0L & 0xfffe))
+
+
+/* 1800dc - Line Window Table Address (W1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LWTA1U (vdp2_regs[0x0dc/2])
+
+ #define VDP2_W1LWE ((VDP2_LWTA1U & 0x8000) >> 15)
+
+
+/* 1800de - Line Window Table Address (W1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LWTA1L (vdp2_regs[0x0de/2])
+
+ /* bit 19 isn't used when VRAM = 4 Mbit */
+ #define VDP2_W1LWTA (((VDP2_LWTA1U & 0x0007) << 16) | (VDP2_LWTA1L & 0xfffe))
+
+
+/* 1800e0 - Sprite Control
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | SPCCCS1 | SPCCCS0 | -- | SPCCN2 | SPCCN1 | SPCCN0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | SPCLMD | SPWINEN | SPTYPE3 | SPTYPE2 | SPTYPE1 | SPTYPE0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SPCTL (vdp2_regs[0x0e0/2])
+ #define VDP2_SPCCCS ((VDP2_SPCTL & 0x3000) >> 12)
+ #define VDP2_SPCCN ((VDP2_SPCTL & 0x700) >> 8)
+ #define VDP2_SPCLMD ((VDP2_SPCTL & 0x20) >> 5)
+ #define VDP2_SPWINEN ((VDP2_SPCTL & 0x10) >> 4)
+ #define VDP2_SPTYPE (VDP2_SPCTL & 0xf)
+
+/* 1800e2 - Shadow Control
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SDCTL (vdp2_regs[0x0e2/2])
+
+/* 1800e4 - CRAOFA - Colour Ram Address Offset (NBG0 - NBG3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | N0CAOS2 | N3CAOS1 | N3CAOS0 | -- | N2CAOS2 | N2CAOS1 | N2CAOS0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | N1CAOS2 | N1CAOS1 | N1CAOS0 | -- | N0CAOS2 | N0CAOS1 | N0CAOS0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CRAOFA (vdp2_regs[0x0e4/2])
+
+ /* NxCAOS = */
+ #define VDP2_N0CAOS ((VDP2_CRAOFA & 0x0007) >> 0)
+ #define VDP2_N1CAOS ((VDP2_CRAOFA & 0x0070) >> 4)
+ #define VDP2_N2CAOS ((VDP2_CRAOFA & 0x0700) >> 8)
+ #define VDP2_N3CAOS ((VDP2_CRAOFA & 0x7000) >> 12)
+
+
+/* 1800e6 - Colour Ram Address Offset (RBG0, SPRITE)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_CRAOFB (vdp2_regs[0x0e6/2])
+ #define VDP2_R0CAOS ((VDP2_CRAOFB & 0x0007) >> 0)
+ #define VDP2_SPCAOS ((VDP2_CRAOFB & 0x0070) >> 4)
+
+/* 1800e8 - LNCLEN - Line Colour Screen Enable
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | SPLCEN | R0LCEN | N3LCEN | N2LCEN | N1LCEN | N0LCEN |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_LNCLEN (vdp2_regs[0x0e8/2])
+ #define VDP2_SPLCEN ((VDP2_LNCLEN & 0x0020) >> 5)
+ #define VDP2_R0LCEN ((VDP2_LNCLEN & 0x0010) >> 4)
+ #define VDP2_N3LCEN ((VDP2_LNCLEN & 0x0008) >> 3)
+ #define VDP2_N2LCEN ((VDP2_LNCLEN & 0x0004) >> 2)
+ #define VDP2_N1LCEN ((VDP2_LNCLEN & 0x0002) >> 1)
+ #define VDP2_N0LCEN ((VDP2_LNCLEN & 0x0001) >> 0)
+
+/* 1800ea - Special Priority Mode
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SFPRMD (vdp2_regs[0x0ea/2])
+
+
+/* 1800ec - Colour Calculation Control
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | BOKEN | BOKN2 | BOKN1 | BOKN0 | -- | EXCCEN | CCRTMD | CCMD |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | SPCCEN | LCCCEN | R0CCEN | N3CCEN | N2CCEN | N1CCEN | N0CCEN |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCCR (vdp2_regs[0x0ec/2])
+ #define VDP2_CCMD ((VDP2_CCCR & 0x100) >> 8)
+ #define VDP2_SPCCEN ((VDP2_CCCR & 0x40) >> 6)
+ #define VDP2_LCCCEN ((VDP2_CCCR & 0x20) >> 5)
+ #define VDP2_R0CCEN ((VDP2_CCCR & 0x10) >> 4)
+ #define VDP2_N3CCEN ((VDP2_CCCR & 0x8) >> 3)
+ #define VDP2_N2CCEN ((VDP2_CCCR & 0x4) >> 2)
+ #define VDP2_N1CCEN ((VDP2_CCCR & 0x2) >> 1)
+ #define VDP2_N0CCEN ((VDP2_CCCR & 0x1) >> 0)
+
+
+/* 1800ee - Special Colour Calculation Mode
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_SFCCMD (vdp2_regs[0x0ee/2])
+
+/* 1800f0 - Priority Number (Sprite 0,1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | S1PRIN2 | S1PRIN1 | S1PRIN0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | S0PRIN2 | S0PRIN1 | S0PRIN0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PRISA (vdp2_regs[0x0f0/2])
+ #define VDP2_S1PRIN ((VDP2_PRISA & 0x0700) >> 8)
+ #define VDP2_S0PRIN ((VDP2_PRISA & 0x0007) >> 0)
+
+/* 1800f2 - Priority Number (Sprite 2,3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | S3PRIN2 | S3PRIN1 | S3PRIN0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | S2PRIN2 | S2PRIN1 | S2PRIN0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PRISB (vdp2_regs[0x0f2/2])
+ #define VDP2_S3PRIN ((VDP2_PRISB & 0x0700) >> 8)
+ #define VDP2_S2PRIN ((VDP2_PRISB & 0x0007) >> 0)
+
+/* 1800f4 - Priority Number (Sprite 4,5)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | S5PRIN2 | S5PRIN1 | S5PRIN0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | S4PRIN2 | S4PRIN1 | S4PRIN0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PRISC (vdp2_regs[0x0f4/2])
+ #define VDP2_S5PRIN ((VDP2_PRISC & 0x0700) >> 8)
+ #define VDP2_S4PRIN ((VDP2_PRISC & 0x0007) >> 0)
+
+/* 1800f6 - Priority Number (Sprite 6,7)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | S7PRIN2 | S7PRIN1 | S7PRIN0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | S6PRIN2 | S6PRIN1 | S6PRIN0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PRISD (vdp2_regs[0x0f6/2])
+ #define VDP2_S7PRIN ((VDP2_PRISD & 0x0700) >> 8)
+ #define VDP2_S6PRIN ((VDP2_PRISD & 0x0007) >> 0)
+
+
+/* 1800f8 - PRINA - Priority Number (NBG 0,1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PRINA (vdp2_regs[0x0f8/2])
+
+ #define VDP2_N1PRIN ((VDP2_PRINA & 0x0700) >> 8)
+ #define VDP2_N0PRIN ((VDP2_PRINA & 0x0007) >> 0)
+
+/* 1800fa - PRINB - Priority Number (NBG 2,3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_PRINB (vdp2_regs[0x0fa/2])
+
+ #define VDP2_N3PRIN ((VDP2_PRINB & 0x0700) >> 8)
+ #define VDP2_N2PRIN ((VDP2_PRINB & 0x0007) >> 0)
+
+/* 1800fc - Priority Number (RBG0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_PRIR (vdp2_regs[0x0fc/2])
+
+ #define VDP2_R0PRIN ((VDP2_PRIR & 0x0007) >> 0)
+
+/* 1800fe - Reserved
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+/* 180100 - Colour Calculation Ratio (Sprite 0,1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | S1CCRT4 | S1CCRT3 | S1CCRT2 | S1CCRT1 | S1CCRT0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | S0CCRT4 | S0CCRT3 | S0CCRT2 | S0CCRT1 | S0CCRT0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRSA (vdp2_regs[0x100/2])
+ #define VDP2_S1CCRT ((VDP2_CCRSA & 0x1f00) >> 8)
+ #define VDP2_S0CCRT ((VDP2_CCRSA & 0x001f) >> 0)
+
+/* 180102 - Colour Calculation Ratio (Sprite 2,3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | S3CCRT4 | S3CCRT3 | S3CCRT2 | S3CCRT1 | S3CCRT0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | S2CCRT4 | S2CCRT3 | S2CCRT2 | S2CCRT1 | S2CCRT0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRSB (vdp2_regs[0x102/2])
+ #define VDP2_S3CCRT ((VDP2_CCRSB & 0x1f00) >> 8)
+ #define VDP2_S2CCRT ((VDP2_CCRSB & 0x001f) >> 0)
+
+/* 180104 - Colour Calculation Ratio (Sprite 4,5)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | S5CCRT4 | S5CCRT3 | S5CCRT2 | S5CCRT1 | S5CCRT0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | S4CCRT4 | S4CCRT3 | S4CCRT2 | S4CCRT1 | S4CCRT0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRSC (vdp2_regs[0x104/2])
+ #define VDP2_S5CCRT ((VDP2_CCRSC & 0x1f00) >> 8)
+ #define VDP2_S4CCRT ((VDP2_CCRSC & 0x001f) >> 0)
+
+/* 180106 - Colour Calculation Ratio (Sprite 6,7)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | S7CCRT4 | S7CCRT3 | S7CCRT2 | S7CCRT1 | S7CCRT0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | S6CCRT4 | S6CCRT3 | S6CCRT2 | S6CCRT1 | S6CCRT0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRSD (vdp2_regs[0x106/2])
+ #define VDP2_S7CCRT ((VDP2_CCRSD & 0x1f00) >> 8)
+ #define VDP2_S6CCRT ((VDP2_CCRSD & 0x001f) >> 0)
+
+/* 180108 - Colour Calculation Ratio (NBG 0,1)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | N1CCRT4 | N1CCRT3 | N1CCRT2 | N1CCRT1 | N1CCRT0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | N0CCRT4 | N0CCRT3 | N0CCRT2 | N0CCRT1 | N0CCRT0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRNA (vdp2_regs[0x108/2])
+ #define VDP2_N1CCRT ((VDP2_CCRNA & 0x1f00) >> 8)
+ #define VDP2_N0CCRT (VDP2_CCRNA & 0x1f)
+
+/* 18010a - Colour Calculation Ratio (NBG 2,3)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | N3CCRT4 | N3CCRT3 | N3CCRT2 | N3CCRT1 | N3CCRT0 |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | N2CCRT4 | N2CCRT3 | N2CCRT2 | N2CCRT1 | N2CCRT0 |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRNB (vdp2_regs[0x10a/2])
+ #define VDP2_N3CCRT ((VDP2_CCRNB & 0x1f00) >> 8)
+ #define VDP2_N2CCRT (VDP2_CCRNB & 0x1f)
+
+/* 18010c - Colour Calculation Ratio (RBG 0)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRR (vdp2_regs[0x10c/2])
+ #define VDP2_R0CCRT (VDP2_CCRR & 0x1f)
+
+/* 18010e - Colour Calculation Ratio (Line Colour Screen, Back Colour Screen)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CCRLB (vdp2_regs[0x10e/2])
+
+
+/* 180110 - Colour Offset Enable
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CLOFEN (vdp2_regs[0x110/2])
+ #define VDP2_N0COEN ((VDP2_CLOFEN & 0x01) >> 0)
+ #define VDP2_N1COEN ((VDP2_CLOFEN & 0x02) >> 1)
+ #define VDP2_N2COEN ((VDP2_CLOFEN & 0x04) >> 2)
+ #define VDP2_N3COEN ((VDP2_CLOFEN & 0x08) >> 3)
+ #define VDP2_R0COEN ((VDP2_CLOFEN & 0x10) >> 4)
+ #define VDP2_BKCOEN ((VDP2_CLOFEN & 0x20) >> 5)
+ #define VDP2_SPCOEN ((VDP2_CLOFEN & 0x40) >> 6)
+
+/* 180112 - Colour Offset Select
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_CLOFSL (vdp2_regs[0x112/2])
+ #define VDP2_N0COSL ((VDP2_CLOFSL & 0x01) >> 0)
+ #define VDP2_N1COSL ((VDP2_CLOFSL & 0x02) >> 1)
+ #define VDP2_N2COSL ((VDP2_CLOFSL & 0x04) >> 2)
+ #define VDP2_N3COSL ((VDP2_CLOFSL & 0x08) >> 3)
+ #define VDP2_R0COSL ((VDP2_CLOFSL & 0x10) >> 4)
+ #define VDP2_BKCOSL ((VDP2_CLOFSL & 0x20) >> 5)
+ #define VDP2_SPCOSL ((VDP2_CLOFSL & 0x40) >> 6)
+
+/* 180114 - Colour Offset A (Red)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_COAR (vdp2_regs[0x114/2])
+
+/* 180116 - Colour Offset A (Green)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_COAG (vdp2_regs[0x116/2])
+
+/* 180118 - Colour Offset A (Blue)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+
+ #define VDP2_COAB (vdp2_regs[0x118/2])
+
+/* 18011a - Colour Offset B (Red)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_COBR (vdp2_regs[0x11a/2])
+
+/* 18011c - Colour Offset B (Green)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_COBG (vdp2_regs[0x11c/2])
+
+/* 18011e - Colour Offset B (Blue)
+ bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
+ | -- | -- | -- | -- | -- | -- | -- | -- |
+ \----------|----------|----------|----------|----------|----------|----------|---------*/
+ #define VDP2_COBB (vdp2_regs[0x11e/2])
+
+
+#define VDP2_RBG_ROTATION_PARAMETER_A 1
+#define VDP2_RBG_ROTATION_PARAMETER_B 2
+
+
+#define mul_fixed32( a, b ) mul_32x32_shift( a, b, 16 )
+
+static void vdp2_fill_rotation_parameter_table( UINT8 rot_parameter )
+{
+ UINT32 address;
+
+ address = (((VDP2_RPTAU << 16) | VDP2_RPTAL) << 1);
+ if ( rot_parameter == 1 )
+ {
+ address &= ~0x00000080;
+ }
+ else if ( rot_parameter == 2 )
+ {
+ address |= 0x00000080;
+ }
+
+ current_rotation_table.xst = (vdp2_vram[address/4] & 0x1fffffc0) | ((vdp2_vram[address/4] & 0x10000000) ? 0xe0000000 : 0x00000000 );
+ current_rotation_table.yst = (vdp2_vram[address/4 + 1] & 0x1fffffc0) | ((vdp2_vram[address/4 + 1] & 0x10000000) ? 0xe0000000 : 0x00000000 );
+ current_rotation_table.zst = (vdp2_vram[address/4 + 2] & 0x1fffffc0) | ((vdp2_vram[address/4 + 2] & 0x10000000) ? 0xe0000000 : 0x00000000 );
+ current_rotation_table.dxst = (vdp2_vram[address/4 + 3] & 0x0007ffc0) | ((vdp2_vram[address/4 + 3] & 0x00040000) ? 0xfff80000 : 0x00000000 );
+ current_rotation_table.dyst = (vdp2_vram[address/4 + 4] & 0x0007ffc0) | ((vdp2_vram[address/4 + 4] & 0x00040000) ? 0xfff80000 : 0x00000000 );
+ current_rotation_table.dx = (vdp2_vram[address/4 + 5] & 0x0007ffc0) | ((vdp2_vram[address/4 + 5] & 0x00040000) ? 0xfff80000 : 0x00000000 );
+ current_rotation_table.dy = (vdp2_vram[address/4 + 6] & 0x0007ffc0) | ((vdp2_vram[address/4 + 6] & 0x00040000) ? 0xfff80000 : 0x00000000 );
+ current_rotation_table.A = (vdp2_vram[address/4 + 7] & 0x000fffc0) | ((vdp2_vram[address/4 + 7] & 0x00080000) ? 0xfff00000 : 0x00000000 );
+ current_rotation_table.B = (vdp2_vram[address/4 + 8] & 0x000fffc0) | ((vdp2_vram[address/4 + 8] & 0x00080000) ? 0xfff00000 : 0x00000000 );
+ current_rotation_table.C = (vdp2_vram[address/4 + 9] & 0x000fffc0) | ((vdp2_vram[address/4 + 9] & 0x00080000) ? 0xfff00000 : 0x00000000 );
+ current_rotation_table.D = (vdp2_vram[address/4 + 10] & 0x000fffc0) | ((vdp2_vram[address/4 + 10] & 0x00080000) ? 0xfff00000 : 0x00000000 );
+ current_rotation_table.E = (vdp2_vram[address/4 + 11] & 0x000fffc0) | ((vdp2_vram[address/4 + 11] & 0x00080000) ? 0xfff00000 : 0x00000000 );
+ current_rotation_table.F = (vdp2_vram[address/4 + 12] & 0x000fffc0) | ((vdp2_vram[address/4 + 12] & 0x00080000) ? 0xfff00000 : 0x00000000 );
+ current_rotation_table.px = (vdp2_vram[address/4 + 13] & 0x3fff0000) | ((vdp2_vram[address/4 + 13] & 0x30000000) ? 0xc0000000 : 0x00000000 );
+ current_rotation_table.py = (vdp2_vram[address/4 + 13] & 0x00003fff) << 16;
+ if ( current_rotation_table.py & 0x20000000 ) current_rotation_table.py |= 0xc0000000;
+ current_rotation_table.pz = (vdp2_vram[address/4 + 14] & 0x3fff0000) | ((vdp2_vram[address/4 + 14] & 0x20000000) ? 0xc0000000 : 0x00000000 );
+ current_rotation_table.cx = (vdp2_vram[address/4 + 15] & 0x3fff0000) | ((vdp2_vram[address/4 + 15] & 0x20000000) ? 0xc0000000 : 0x00000000 );
+ current_rotation_table.cy = (vdp2_vram[address/4 + 15] & 0x00003fff) << 16;
+ if ( current_rotation_table.cy & 0x20000000 ) current_rotation_table.cy |= 0xc0000000;
+ current_rotation_table.cz = (vdp2_vram[address/4 + 16] & 0x3fff0000) | ((vdp2_vram[address/4 + 16] & 0x20000000) ? 0xc0000000 : 0x00000000 );
+ current_rotation_table.mx = (vdp2_vram[address/4 + 17] & 0x3fffffc0) | ((vdp2_vram[address/4 + 17] & 0x20000000) ? 0xc0000000 : 0x00000000 );
+ current_rotation_table.my = (vdp2_vram[address/4 + 18] & 0x3fffffc0) | ((vdp2_vram[address/4 + 18] & 0x20000000) ? 0xc0000000 : 0x00000000 );
+ current_rotation_table.kx = (vdp2_vram[address/4 + 19] & 0x00ffffff) | ((vdp2_vram[address/4 + 19] & 0x00800000) ? 0xff000000 : 0x00000000 );
+ current_rotation_table.ky = (vdp2_vram[address/4 + 20] & 0x00ffffff) | ((vdp2_vram[address/4 + 20] & 0x00800000) ? 0xff000000 : 0x00000000 );
+ current_rotation_table.kast = (vdp2_vram[address/4 + 21] & 0xffffffc0);
+ current_rotation_table.dkast= (vdp2_vram[address/4 + 22] & 0x03ffffc0) | ((vdp2_vram[address/4 + 22] & 0x02000000) ? 0xfc000000 : 0x00000000 );
+ current_rotation_table.dkax = (vdp2_vram[address/4 + 23] & 0x03ffffc0) | ((vdp2_vram[address/4 + 23] & 0x02000000) ? 0xfc000000 : 0x00000000 );
+
+ /* check rotation parameter read control, override if specific bits are disabled */
+ /* (Batman Forever The Riddler stage relies on this) */
+ switch(rot_parameter)
+ {
+ case 1:
+ /* TODO: disable read control if these undocumented bits are on (Radiant Silvergun Xiga final boss) */
+ if(!VDP2_RAUNK)
+ {
+ if(!VDP2_RAXSTRE)
+ current_rotation_table.xst = 0;
+
+ if(!VDP2_RAYSTRE)
+ current_rotation_table.yst = 0;
+
+ if(!VDP2_RAKASTRE)
+ current_rotation_table.dkax = 0;
+ }
+ break;
+ case 2:
+ /* same as above */
+ if(!VDP2_RBUNK)
+ {
+ if(!VDP2_RBXSTRE)
+ current_rotation_table.xst = 0;
+
+ if(!VDP2_RBYSTRE)
+ current_rotation_table.yst = 0;
+
+ if(!VDP2_RBKASTRE)
+ current_rotation_table.dkax = 0;
+ }
+ break;
+ }
+
+#define RP current_rotation_table
+
+ log_masked(LOG_ROZ, "Rotation parameter table (%d)\n", rot_parameter);
+ log_masked(LOG_ROZ, "xst = %x, yst = %x, zst = %x\n", RP.xst, RP.yst, RP.zst);
+ log_masked(LOG_ROZ, "dxst = %x, dyst = %x\n", RP.dxst, RP.dyst);
+ log_masked(LOG_ROZ, "dx = %x, dy = %x\n", RP.dx, RP.dy);
+ log_masked(LOG_ROZ, "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x\n", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F);
+ log_masked(LOG_ROZ, "px = %x, py = %x, pz = %x\n", RP.px, RP.py, RP.pz);
+ log_masked(LOG_ROZ, "cx = %x, cy = %x, cz = %x\n", RP.cx, RP.cy, RP.cz);
+ log_masked(LOG_ROZ, "mx = %x, my = %x\n", RP.mx, RP.my);
+ log_masked(LOG_ROZ, "kx = %x, ky = %x\n", RP.kx, RP.ky);
+ log_masked(LOG_ROZ, "kast = %x, dkast = %x, dkax = %x\n", RP.kast, RP.dkast, RP.dkax);
+
+ /*Attempt to show on screen the rotation table*/
+ if (DEBUG_DRAW_ROZ)
+ {
+ if(0)
+ m_vdpdebug_roz++;
+
+ if(0)
+ m_vdpdebug_roz--;
+
+ if(m_vdpdebug_roz > 10)
+ m_vdpdebug_roz = 10;
+
+ switch(m_vdpdebug_roz)
+ {
+ case 0: popmessage( "Rotation parameter Table (%d)", rot_parameter ); break;
+ case 1: popmessage( "xst = %x, yst = %x, zst = %x", RP.xst, RP.yst, RP.zst ); break;
+ case 2: popmessage( "dxst = %x, dyst = %x", RP.dxst, RP.dyst ); break;
+ case 3: popmessage( "dx = %x, dy = %x", RP.dx, RP.dy ); break;
+ case 4: popmessage( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F ); break;
+ case 5: popmessage( "px = %x, py = %x, pz = %x", RP.px, RP.py, RP.pz ); break;
+ case 6: popmessage( "cx = %x, cy = %x, cz = %x", RP.cx, RP.cy, RP.cz ); break;
+ case 7: popmessage( "mx = %x, my = %x", RP.mx, RP.my ); break;
+ case 8: popmessage( "kx = %x, ky = %x", RP.kx, RP.ky ); break;
+ case 9: popmessage( "kast = %x, dkast = %x, dkax = %x", RP.kast, RP.dkast, RP.dkax ); break;
+ case 10: break;
+ }
+ }
+}
+
+/* check if RGB layer has rotation applied */
+static UINT8 vdp2_is_rotation_applied(void)
+{
+#define _FIXED_1 (0x00010000)
+#define _FIXED_0 (0x00000000)
+
+ if ( RP.A == _FIXED_1 &&
+ RP.B == _FIXED_0 &&
+ RP.C == _FIXED_0 &&
+ RP.D == _FIXED_0 &&
+ RP.E == _FIXED_1 &&
+ RP.F == _FIXED_0 &&
+ RP.dxst == _FIXED_0 &&
+ RP.dyst == _FIXED_1 &&
+ RP.dx == _FIXED_1 &&
+ RP.dy == _FIXED_0 &&
+ RP.kx == _FIXED_1 &&
+ RP.ky == _FIXED_1 &&
+ VDP2_RPMD < 2) /* disable optimizations if roz mode is 2 or 3 */
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+static UINT8 vdp2_are_map_registers_equal(void)
+{
+ int i;
+
+ for ( i = 1; i < current_tilemap.map_count; i++ )
+ {
+ if ( current_tilemap.map_offset[i] != current_tilemap.map_offset[0] )
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void vdp2_check_fade_control_for_layer(void)
+{
+ if ( current_tilemap.fade_control & 1 )
+ {
+ if ( current_tilemap.fade_control & 2 )
+ {
+ if ((VDP2_COBR & 0x1ff) == 0 &&
+ (VDP2_COBG & 0x1ff) == 0 &&
+ (VDP2_COBB & 0x1ff) == 0 )
+ {
+ current_tilemap.fade_control = 0;
+ }
+ }
+ else
+ {
+ if ((VDP2_COAR & 0x1ff) == 0 &&
+ (VDP2_COAG & 0x1ff) == 0 &&
+ (VDP2_COAB & 0x1ff) == 0 )
+ {
+ current_tilemap.fade_control = 0;
+ }
+ }
+ }
+}
+
+#define VDP2_CP_NBG0_PNMDR 0x0
+#define VDP2_CP_NBG1_PNMDR 0x1
+#define VDP2_CP_NBG2_PNMDR 0x2
+#define VDP2_CP_NBG3_PNMDR 0x3
+#define VDP2_CP_NBG0_CPDR 0x4
+#define VDP2_CP_NBG1_CPDR 0x5
+#define VDP2_CP_NBG2_CPDR 0x6
+#define VDP2_CP_NBG3_CPDR 0x7
+
+static UINT8 vdp2_check_vram_cycle_pattern_registers( UINT8 access_command_pnmdr, UINT8 access_command_cpdr, UINT8 bitmap_enable )
+{
+ int i;
+ UINT8 access_command_ok = 0;
+ UINT16 cp_regs[8];
+ cp_regs[0] = VDP2_CYCA0L;
+ cp_regs[1] = VDP2_CYCA0U;
+ cp_regs[2] = VDP2_CYCA1L;
+ cp_regs[3] = VDP2_CYCA1U;
+ cp_regs[4] = VDP2_CYCA2L;
+ cp_regs[5] = VDP2_CYCA2U;
+ cp_regs[6] = VDP2_CYCA3L;
+ cp_regs[7] = VDP2_CYCA3U;
+
+ if ( bitmap_enable ) access_command_ok = 1;
+
+ for ( i = 0; i < 8; i++ )
+ {
+ if ( ((cp_regs[i] >> 12) & 0xf) == access_command_pnmdr )
+ {
+ access_command_ok |= 1;
+ }
+ if ( ((cp_regs[i] >> 12) & 0xf) == access_command_cpdr )
+ {
+ access_command_ok |= 2;
+ }
+ if ( ((cp_regs[i] >> 8) & 0xf) == access_command_pnmdr )
+ {
+ access_command_ok |= 1;
+ }
+ if ( ((cp_regs[i] >> 8) & 0xf) == access_command_cpdr )
+ {
+ access_command_ok |= 2;
+ }
+ if ( ((cp_regs[i] >> 4) & 0xf) == access_command_pnmdr )
+ {
+ access_command_ok |= 1;
+ }
+ if ( ((cp_regs[i] >> 4) & 0xf) == access_command_cpdr )
+ {
+ access_command_ok |= 2;
+ }
+ if ( ((cp_regs[i] >> 0) & 0xf) == access_command_pnmdr )
+ {
+ access_command_ok |= 1;
+ }
+ if ( ((cp_regs[i] >> 0) & 0xf) == access_command_cpdr )
+ {
+ access_command_ok |= 2;
+ }
+ }
+ return access_command_ok == 3 ? 1 : 0;
+}
+
+
+static void vdp2_compute_color_offset( int *r, int *g, int *b, int cor )
+{
+ if ( cor == 0 )
+ {
+ *r = (VDP2_COAR & 0x100) ? (*r - (0x100 - (VDP2_COAR & 0xff))) : ((VDP2_COAR & 0xff) + *r);
+ *g = (VDP2_COAG & 0x100) ? (*g - (0x100 - (VDP2_COAG & 0xff))) : ((VDP2_COAG & 0xff) + *g);
+ *b = (VDP2_COAB & 0x100) ? (*b - (0x100 - (VDP2_COAB & 0xff))) : ((VDP2_COAB & 0xff) + *b);
+ }
+ else
+ {
+ *r = (VDP2_COBR & 0x100) ? (*r - (0xff - (VDP2_COBR & 0xff))) : ((VDP2_COBR & 0xff) + *r);
+ *g = (VDP2_COBG & 0x100) ? (*g - (0xff - (VDP2_COBG & 0xff))) : ((VDP2_COBG & 0xff) + *g);
+ *b = (VDP2_COBB & 0x100) ? (*b - (0xff - (VDP2_COBB & 0xff))) : ((VDP2_COBB & 0xff) + *b);
+ }
+ if(*r < 0) { *r = 0; }
+ if(*r > 0xff) { *r = 0xff; }
+ if(*g < 0) { *g = 0; }
+ if(*g > 0xff) { *g = 0xff; }
+ if(*b < 0) { *b = 0; }
+ if(*b > 0xff) { *b = 0xff; }
+}
+
+/*
+ The color offset of a whole screen at once: the signed offsets of
+ set A (cor == 0) or B for the three components, then each pixel only
+ adds and clamps.
+*/
+static void vdp2_color_offset_values(int cor, int *r, int *g, int *b)
+{
+ if ( cor == 0 )
+ {
+ *r = (VDP2_COAR & 0x100) ? -(0x100 - (VDP2_COAR & 0xff)) : (VDP2_COAR & 0xff);
+ *g = (VDP2_COAG & 0x100) ? -(0x100 - (VDP2_COAG & 0xff)) : (VDP2_COAG & 0xff);
+ *b = (VDP2_COAB & 0x100) ? -(0x100 - (VDP2_COAB & 0xff)) : (VDP2_COAB & 0xff);
+ }
+ else
+ {
+ *r = (VDP2_COBR & 0x100) ? -(0xff - (VDP2_COBR & 0xff)) : (VDP2_COBR & 0xff);
+ *g = (VDP2_COBG & 0x100) ? -(0xff - (VDP2_COBG & 0xff)) : (VDP2_COBG & 0xff);
+ *b = (VDP2_COBB & 0x100) ? -(0xff - (VDP2_COBB & 0xff)) : (VDP2_COBB & 0xff);
+ }
+}
+
+static INLINE rgb_t vdp2_apply_color_offset(rgb_t rgb, int ro, int go, int bo)
+{
+ int r = (int)RGB_RED(rgb) + ro;
+ int g = (int)RGB_GREEN(rgb) + go;
+ int b = (int)RGB_BLUE(rgb) + bo;
+ if (r < 0) r = 0; else if (r > 0xff) r = 0xff;
+ if (g < 0) g = 0; else if (g > 0xff) g = 0xff;
+ if (b < 0) b = 0; else if (b > 0xff) b = 0xff;
+ return RGB_MAKE(r, g, b);
+}
+
+static void vdp2_drawgfxzoom(
+ struct mame_bitmap *dest_bmp,const struct rectangle *clip,gfx_element *gfx,
+ UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy,
+ int transparency,int scalex, int scaley,
+ int sprite_screen_width, int sprite_screen_height, int alpha)
+{
+ int y;
+ int x;
+ struct rectangle myclip;
+
+ if (!scalex || !scaley) return;
+
+ /* (MAME skips here the tiles its pen usage shows all transparent: the same output) */
+
+ /*
+ scalex and scaley are 16.16 fixed point numbers
+ 1<<15 : shrink to 50%
+ 1<<16 : uniform scale
+ 1<<17 : double to 200%
+ */
+
+ /* force clip to bitmap boundary */
+ myclip = *clip;
+ rect_clip_to_bitmap(&myclip, dest_bmp);
+
+ if (gfx)
+ {
+ const pen_t *pal = &PEN(0 + gfx->granularity * (color % gfx->colors));
+ const UINT8 *source_base = gfx_get_data(gfx, code % gfx->elements);
+
+ /*int sprite_screen_height = (scaley*gfx->height+0x8000)>>16; */
+ /*int sprite_screen_width = (scalex*gfx->width+0x8000)>>16; */
+
+ if (sprite_screen_width && sprite_screen_height)
+ {
+ /* compute sprite increment per screen pixel */
+ /*int dx = (gfx->width<<16)/sprite_screen_width; */
+ /*int dy = (gfx->height<<16)/sprite_screen_height; */
+ int dx = current_tilemap.incx;
+ int dy = current_tilemap.incy;
+
+ int ex = sx+sprite_screen_width;
+ int ey = sy+sprite_screen_height;
+
+ int x_index_base;
+ int y_index;
+
+ if (flipx)
+ {
+ x_index_base = (sprite_screen_width-1)*dx;
+ dx = -dx;
+ }
+ else
+ {
+ x_index_base = 0;
+ }
+
+ if (flipy)
+ {
+ y_index = (sprite_screen_height-1)*dy;
+ dy = -dy;
+ }
+ else
+ {
+ y_index = 0;
+ }
+
+ if (sx < myclip.min_x)
+ {
+ /* clip left */
+ int pixels = myclip.min_x-sx;
+ sx += pixels;
+ x_index_base += pixels*dx;
+ }
+ if (sy < myclip.min_y )
+ {
+ /* clip top */
+ int pixels = myclip.min_y-sy;
+ sy += pixels;
+ y_index += pixels*dy;
+ }
+ if (ex > myclip.max_x+1)
+ {
+ /* clip right */
+ int pixels = ex-myclip.max_x-1;
+ ex -= pixels;
+ }
+ if (ey > myclip.max_y+1)
+ {
+ /* clip bottom */
+ int pixels = ey-myclip.max_y-1;
+ ey -= pixels;
+ }
+
+ /* skip if inner loop doesn't draw anything */
+ if (ex > sx )
+ {
+ if (transparency & STV_TRANSPARENCY_ALPHA)
+ {
+ /* case : STV_TRANSPARENCY_ALPHA */
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = source_base + (y_index>>16) * gfx->width;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+ for( x=sx; x>16];
+ if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0))
+ dest[x] = stv_alpha_blend_r32(dest[x], pal[c], alpha);
+ }
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+ }
+ else if (transparency & STV_TRANSPARENCY_ADD_BLEND)
+ {
+ /* case : STV_TRANSPARENCY_ADD_BLEND */
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = source_base + (y_index>>16) * gfx->width;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+ for (x = sx; x < ex; x++)
+ {
+ if (vdp2_window_process(x, y))
+ {
+ int c = source[x_index>>16];
+ if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0))
+ dest[x] = add_blend_r32(dest[x],pal[c]);
+ }
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+ }
+ else
+ {
+ /* case : STV_TRANSPARENCY_PEN */
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = source_base + (y_index>>16) * gfx->width;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+ for (x = sx; x < ex; x++)
+ {
+ if (vdp2_window_process(x, y))
+ {
+ int c = source[x_index>>16];
+ if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0))
+ dest[x] = pal[c];
+ }
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void vdp2_drawgfxzoom_rgb555(
+ struct mame_bitmap *dest_bmp,const struct rectangle *clip,
+ UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy,
+ int transparency,int scalex, int scaley,
+ int sprite_screen_width, int sprite_screen_height, int alpha)
+{
+ int y;
+ int x;
+ struct rectangle myclip;
+ UINT8* gfxdata;
+
+ gfxdata = vdp2l.gfx_decode + code * 0x20;
+
+ if(current_tilemap.window_control.enabled[0] ||
+ current_tilemap.window_control.enabled[1])
+ popmessage("Window Enabled for RGB555 Zoom");
+
+ if (!scalex || !scaley) return;
+
+ #if 0
+ if (0 && !(transparency & STV_TRANSPARENCY_NONE))
+ {
+ int transmask = 0;
+
+ transmask = 1 << (0 & 0xff);
+
+ if ((gfx->pen_usage(code) & ~transmask) == 0)
+ /* character is totally transparent, no need to draw */
+ return;
+ else if ((gfx->pen_usage(code) & transmask) == 0)
+ /* character is totally opaque, can disable transparency */
+ transparency |= STV_TRANSPARENCY_NONE;
+ }
+ #endif
+
+ /*
+ scalex and scaley are 16.16 fixed point numbers
+ 1<<15 : shrink to 50%
+ 1<<16 : uniform scale
+ 1<<17 : double to 200%
+ */
+
+ /* force clip to bitmap boundary */
+ myclip = *clip;
+ rect_clip_to_bitmap(&myclip, dest_bmp);
+
+/* if( gfx ) */
+ {
+/* const UINT8 *source_base = gfx_get_data(gfx, code % gfx->elements); */
+
+ /*int sprite_screen_height = (scaley*gfx->height+0x8000)>>16; */
+ /*int sprite_screen_width = (scalex*gfx->width+0x8000)>>16; */
+
+ if (sprite_screen_width && sprite_screen_height)
+ {
+ /* compute sprite increment per screen pixel */
+ /*int dx = (gfx->width<<16)/sprite_screen_width; */
+ /*int dy = (gfx->height<<16)/sprite_screen_height; */
+ int dx = current_tilemap.incx;
+ int dy = current_tilemap.incy;
+
+ int ex = sx+sprite_screen_width;
+ int ey = sy+sprite_screen_height;
+
+ int x_index_base;
+ int y_index;
+
+ if (flipx)
+ {
+ x_index_base = (sprite_screen_width-1)*dx;
+ dx = -dx;
+ }
+ else
+ {
+ x_index_base = 0;
+ }
+
+ if (flipy)
+ {
+ y_index = (sprite_screen_height-1)*dy;
+ dy = -dy;
+ }
+ else
+ {
+ y_index = 0;
+ }
+
+ if (sx < myclip.min_x)
+ {
+ /* clip left */
+ int pixels = myclip.min_x-sx;
+ sx += pixels;
+ x_index_base += pixels*dx;
+ }
+ if (sy < myclip.min_y)
+ {
+ /* clip top */
+ int pixels = myclip.min_y-sy;
+ sy += pixels;
+ y_index += pixels*dy;
+ }
+ if (ex > myclip.max_x+1)
+ {
+ /* clip right */
+ int pixels = ex-myclip.max_x-1;
+ ex -= pixels;
+ }
+ if (ey > myclip.max_y+1)
+ {
+ /* clip bottom */
+ int pixels = ey-myclip.max_y-1;
+ ey -= pixels;
+ }
+
+ /* skip if inner loop doesn't draw anything */
+ if (ex > sx)
+ {
+ if (transparency & STV_TRANSPARENCY_ALPHA)
+ {
+ /* case : STV_TRANSPARENCY_ALPHA */
+ for(y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = gfxdata + (y_index>>16)*16;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+ for (x = sx; x < ex; x++)
+ {
+ int data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
+ int b = pal5bit((data & 0x7c00) >> 10);
+ int g = pal5bit((data & 0x03e0) >> 5);
+ int r = pal5bit( data & 0x001f);
+ if(current_tilemap.fade_control & 1)
+ vdp2_compute_color_offset(&r,&g,&b,current_tilemap.fade_control & 2);
+
+ if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000))
+ dest[x] = stv_alpha_blend_r32(dest[x], RGB_MAKE(r, g, b), alpha);
+
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+ }
+ else if (transparency & STV_TRANSPARENCY_ADD_BLEND)
+ {
+ /* case : STV_TRANSPARENCY_ADD_BLEND */
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = gfxdata + (y_index>>16)*16;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+ for (x = sx; x < ex; x++)
+ {
+ int data = (source[(x_index*2+0)>>16]<<0)|(source[(x_index*2+1)>>16]<<8);
+ int b = pal5bit((data & 0x7c00) >> 10);
+ int g = pal5bit((data & 0x03e0) >> 5);
+ int r = pal5bit( data & 0x001f);
+ if(current_tilemap.fade_control & 1)
+ vdp2_compute_color_offset(&r,&g,&b,current_tilemap.fade_control & 2);
+
+ if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000))
+ dest[x] = add_blend_r32(dest[x], RGB_MAKE(r, g, b));
+
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+ }
+ else
+ {
+ /* case : STV_TRANSPARENCY_PEN */
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = gfxdata + (y_index>>16)*16;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+ for (x = sx; x < ex; x++)
+ {
+ int data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
+ int b = pal5bit((data & 0x7c00) >> 10);
+ int g = pal5bit((data & 0x03e0) >> 5);
+ int r = pal5bit( data & 0x001f);
+ if (current_tilemap.fade_control & 1)
+ vdp2_compute_color_offset(&r,&g,&b,current_tilemap.fade_control & 2);
+
+ if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000))
+ dest[x] = RGB_MAKE(r, g, b);
+
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+ }
+ }
+ }
+ }
+
+}
+
+
+static void vdp2_drawgfx_rgb555(struct mame_bitmap *dest_bmp, const struct rectangle *clip, UINT32 code, int flipx, int flipy, int sx, int sy, int transparency, int alpha)
+{
+ int y;
+ int x;
+ struct rectangle myclip;
+ UINT8* gfxdata;
+ int sprite_screen_width, sprite_screen_height;
+
+ gfxdata = vdp2l.gfx_decode + code * 0x20;
+ sprite_screen_width = sprite_screen_height = 8;
+
+ if(current_tilemap.window_control.enabled[0] ||
+ current_tilemap.window_control.enabled[1])
+ popmessage("Window Enabled for RGB555 tiles");
+
+ /* force clip to bitmap boundary */
+ myclip = *clip;
+ rect_clip_to_bitmap(&myclip, dest_bmp);
+
+ {
+ int dx = current_tilemap.incx;
+ int dy = current_tilemap.incy;
+
+ int ex = sx+sprite_screen_width;
+ int ey = sy+sprite_screen_height;
+
+ int x_index_base;
+ int y_index;
+
+ if (flipx)
+ {
+ x_index_base = (sprite_screen_width-1)*dx;
+ dx = -dx;
+ }
+ else
+ {
+ x_index_base = 0;
+ }
+
+ if (flipy)
+ {
+ y_index = (sprite_screen_height-1)*dy;
+ dy = -dy;
+ }
+ else
+ {
+ y_index = 0;
+ }
+
+ if (sx < myclip.min_x)
+ {
+ /* clip left */
+ int pixels = myclip.min_x-sx;
+ sx += pixels;
+ x_index_base += pixels*dx;
+ }
+ if (sy < myclip.min_y)
+ {
+ /* clip top */
+ int pixels = myclip.min_y-sy;
+ sy += pixels;
+ y_index += pixels*dy;
+ }
+ if (ex > myclip.max_x+1)
+ {
+ /* clip right */
+ int pixels = ex-myclip.max_x-1;
+ ex -= pixels;
+ }
+ if (ey > myclip.max_y+1)
+ {
+ /* clip bottom */
+ int pixels = ey-myclip.max_y-1;
+ ey -= pixels;
+ }
+
+ /* skip if inner loop doesn't draw anything */
+ if (ex > sx)
+ {
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = gfxdata + (y_index>>16)*16;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+ for (x = sx; x < ex; x++)
+ {
+ UINT16 data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
+ if ((data & 0x8000) || (transparency & STV_TRANSPARENCY_NONE))
+ {
+ int b = pal5bit((data & 0x7c00) >> 10);
+ int g = pal5bit((data & 0x03e0) >> 5);
+ int r = pal5bit( data & 0x001f);
+ if (current_tilemap.fade_control & 1)
+ vdp2_compute_color_offset(&r,&g,&b,current_tilemap.fade_control & 2);
+
+ if (transparency & STV_TRANSPARENCY_ALPHA)
+ dest[x] = stv_alpha_blend_r32( dest[x], RGB_MAKE(r, g, b), alpha );
+ else
+ dest[x] = RGB_MAKE(r, g, b);
+ }
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+
+ }
+
+ }
+
+}
+
+
+static void vdp2_drawgfx_rgb888( struct mame_bitmap *dest_bmp, const struct rectangle *clip, UINT32 code, int flipx, int flipy,
+ int sx, int sy, int transparency, int alpha)
+{
+ int y;
+ int x;
+ struct rectangle myclip;
+ UINT8* gfxdata;
+ int sprite_screen_width, sprite_screen_height;
+
+ gfxdata = vdp2l.gfx_decode + code * 0x20;
+ sprite_screen_width = sprite_screen_height = 8;
+
+ if(current_tilemap.window_control.enabled[0] ||
+ current_tilemap.window_control.enabled[1])
+ popmessage("Window Enabled for RGB888 tiles");
+
+ /* force clip to bitmap boundary */
+ myclip = *clip;
+ rect_clip_to_bitmap(&myclip, dest_bmp);
+
+ {
+ int dx = current_tilemap.incx;
+ int dy = current_tilemap.incy;
+
+ int ex = sx+sprite_screen_width;
+ int ey = sy+sprite_screen_height;
+
+ int x_index_base;
+ int y_index;
+
+ if( flipx )
+ {
+ x_index_base = (sprite_screen_width-1)*dx;
+ dx = -dx;
+ }
+ else
+ {
+ x_index_base = 0;
+ }
+
+ if( flipy )
+ {
+ y_index = (sprite_screen_height-1)*dy;
+ dy = -dy;
+ }
+ else
+ {
+ y_index = 0;
+ }
+
+ if( sx < myclip.min_x)
+ {
+ /* clip left */
+ int pixels = myclip.min_x-sx;
+ sx += pixels;
+ x_index_base += pixels*dx;
+ }
+ if( sy < myclip.min_y )
+ {
+ /* clip top */
+ int pixels = myclip.min_y-sy;
+ sy += pixels;
+ y_index += pixels*dy;
+ }
+ if( ex > myclip.max_x+1 )
+ {
+ /* clip right */
+ int pixels = ex-myclip.max_x-1;
+ ex -= pixels;
+ }
+ if( ey > myclip.max_y+1 )
+ {
+ /* clip bottom */
+ int pixels = ey-myclip.max_y-1;
+ ey -= pixels;
+ }
+
+ /* skip if inner loop doesn't draw anything */
+ if( ex > sx )
+ {
+ for( y=sy; y>16)*32;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+
+ int x_index = x_index_base;
+
+ for( x=sx; x>16)*4+0] << 24) | (source[(x_index>>16)*4+1] << 16) | (source[(x_index>>16)*4+2] << 8) | (source[(x_index>>16)*4+3] << 0);
+ if ((data & 0x80000000) || (transparency & STV_TRANSPARENCY_NONE))
+ {
+ int b = (data & 0xff0000) >> 16;
+ int g = (data & 0x00ff00) >> 8;
+ int r = (data & 0x0000ff);
+
+ if(current_tilemap.fade_control & 1)
+ vdp2_compute_color_offset(&r,&g,&b,current_tilemap.fade_control & 2);
+
+ if (transparency & STV_TRANSPARENCY_ALPHA)
+ dest[x] = stv_alpha_blend_r32( dest[x], RGB_MAKE(r, g, b), alpha );
+ else
+ dest[x] = RGB_MAKE(r, g, b);
+ }
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+
+ }
+
+ }
+}
+
+static void vdp2_drawgfx_alpha(struct mame_bitmap *dest_bmp,const struct rectangle *clip,gfx_element *gfx,
+ UINT32 code,UINT32 color, int flipx,int flipy,int offsx,int offsy,
+ int transparency, int alpha)
+{
+ int y;
+ int x;
+ const pen_t *pal = &PEN(0 + gfx->granularity * (color % gfx->colors));
+ const UINT8 *source_base = gfx_get_data(gfx, code % gfx->elements);
+ int x_index_base, y_index, sx, sy, ex, ey;
+ int xinc, yinc;
+
+ xinc = flipx ? -1 : 1;
+ yinc = flipy ? -1 : 1;
+
+ x_index_base = flipx ? gfx->width-1 : 0;
+ y_index = flipy ? gfx->height-1 : 0;
+
+ /* start coordinates */
+ sx = offsx;
+ sy = offsy;
+
+ /* end coordinates */
+ ex = sx + gfx->width;
+ ey = sy + gfx->height;
+
+ if (sx < clip->min_x)
+ {
+ /* clip left */
+ int pixels = clip->min_x-sx;
+ sx += pixels;
+ x_index_base += xinc*pixels;
+ }
+ if (sy < clip->min_y)
+ {
+ /* clip top */
+ int pixels = clip->min_y-sy;
+ sy += pixels;
+ y_index += yinc*pixels;
+ }
+ if (ex > clip->max_x+1)
+ {
+ /* clip right */
+ ex = clip->max_x+1;
+ }
+ if (ey > clip->max_y+1)
+ {
+ /* clip bottom */
+ ey = clip->max_y+1;
+ }
+
+ /* skip if inner loop doesn't draw anything */
+ if (ex > sx)
+ {
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = source_base + y_index*gfx->width;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+ int x_index = x_index_base;
+ for (x = sx; x < ex; x++)
+ {
+ if(vdp2_window_process(x,y))
+ {
+ int c = (source[x_index]);
+ if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0))
+ dest[x] = stv_alpha_blend_r32( dest[x], pal[c], alpha );
+ }
+
+ x_index += xinc;
+ }
+ y_index += yinc;
+ }
+ }
+}
+
+/* the windows of a line for the current layer settings, refreshed when they change */
+static VDP2_TLS struct
+{
+ int gen, y, key;
+ int s0, e0, in0; /* window 0: x range, line inside */
+ int s1, e1, in1; /* window 1 */
+} vdp2_wline;
+static void vdp2_window_line(int y, int key);
+
+static void vdp2_drawgfx_transpen(struct mame_bitmap *dest_bmp,const struct rectangle *clip,gfx_element *gfx,
+ UINT32 code,UINT32 color, int flipx,int flipy,int offsx,int offsy,
+ int transparency)
+{
+ int y;
+ int x;
+ const pen_t *pal = &PEN(0 + gfx->granularity * (color % gfx->colors));
+ const UINT8 *source_base = gfx_get_data(gfx, code % gfx->elements);
+ int x_index_base, y_index, sx, sy, ex, ey;
+ int xinc, yinc;
+
+ xinc = flipx ? -1 : 1;
+ yinc = flipy ? -1 : 1;
+
+ x_index_base = flipx ? gfx->width-1 : 0;
+ y_index = flipy ? gfx->height-1 : 0;
+
+ /* start coordinates */
+ sx = offsx;
+ sy = offsy;
+
+ /* end coordinates */
+ ex = sx + gfx->width;
+ ey = sy + gfx->height;
+
+ if (sx < clip->min_x)
+ {
+ /* clip left */
+ int pixels = clip->min_x-sx;
+ sx += pixels;
+ x_index_base += xinc*pixels;
+ }
+ if (sy < clip->min_y)
+ {
+ /* clip top */
+ int pixels = clip->min_y-sy;
+ sy += pixels;
+ y_index += yinc*pixels;
+ }
+ if (ex > clip->max_x+1)
+ {
+ /* clip right */
+ ex = clip->max_x+1;
+ }
+ if (ey > clip->max_y+1)
+ {
+ /* clip bottom */
+ ey = clip->max_y+1;
+ }
+
+ /* skip if inner loop doesn't draw anything */
+ if (ex <= sx)
+ return;
+
+ /* no window on this layer: plain copy loops (the RBG0 cache is drawn this way) */
+ if (!current_tilemap.window_control.enabled[0] && !current_tilemap.window_control.enabled[1])
+ {
+ const int opaque = (transparency & STV_TRANSPARENCY_NONE) ? 1 : 0;
+ const int width = ex - sx;
+
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *source = source_base + y_index*gfx->width + x_index_base;
+ UINT32 *dest = BMP32(dest_bmp, y) + sx;
+ int n;
+
+ if (opaque)
+ {
+ for (n = 0; n < width; n++, source += xinc)
+ dest[n] = pal[*source];
+ }
+ else
+ {
+ for (n = 0; n < width; n++, source += xinc)
+ {
+ const int c = *source;
+ if (c != 0)
+ dest[n] = pal[c];
+ }
+ }
+ y_index += yinc;
+ }
+ return;
+ }
+
+ /* vdp2_window_process with the line's windows read once per row */
+ {
+ const int en0 = current_tilemap.window_control.enabled[0];
+ const int en1 = current_tilemap.window_control.enabled[1];
+ const int out0 = !current_tilemap.window_control.area[0];
+ const int out1 = !current_tilemap.window_control.area[1];
+ const int logic_or = current_tilemap.window_control.logic & 1;
+ const int key = (en0 ? 1 : 0) | (en1 ? 2 : 0) | (out0 ? 0 : 4) | (out1 ? 0 : 8);
+ const int opaque = (transparency & STV_TRANSPARENCY_NONE) ? 1 : 0;
+
+ for (y = sy; y < ey; y++)
+ {
+ UINT8 const *const source = source_base + y_index*gfx->width;
+ UINT32 *const dest = BMP32(dest_bmp, y);
+ int x_index = x_index_base;
+ int s0, e0, in0, s1, e1, in1;
+
+ if (vdp2_wline.gen != vdp2_window_cache_gen || vdp2_wline.y != y || vdp2_wline.key != key)
+ vdp2_window_line(y, key);
+ s0 = vdp2_wline.s0; e0 = vdp2_wline.e0; in0 = vdp2_wline.in0;
+ s1 = vdp2_wline.s1; e1 = vdp2_wline.e1; in1 = vdp2_wline.in1;
+
+ for (x = sx; x < ex; x++, x_index += xinc)
+ {
+ int w0 = 1, w1 = 1, c;
+ if (en0)
+ w0 = (in0 && x >= s0 && x <= e0) ^ out0;
+ if (en1)
+ w1 = (in1 && x >= s1 && x <= e1) ^ out1;
+ if (!(logic_or ? (w0 | w1) : (w0 & w1)))
+ continue;
+ c = source[x_index];
+ if (opaque || c != 0)
+ dest[x] = pal[c];
+ }
+ y_index += yinc;
+ }
+ }
+}
+
+/* - arcadegh uses incy zoom for most games but Joust */
+static void draw_4bpp_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int xsize, ysize, xsize_mask, ysize_mask;
+ int xsrc,ysrc,xdst,ydst;
+ int src_offs;
+ UINT8* vram = vdp2l.gfx_decode;
+ UINT32 map_offset = current_tilemap.bitmap_map * 0x20000;
+ int scrollx = current_tilemap.scrollx;
+ int scrolly = current_tilemap.scrolly;
+ UINT16 dot_data;
+ UINT16 pal_bank;
+ int xf, yf;
+
+ xsize = (current_tilemap.bitmap_size & 2) ? 1024 : 512;
+ ysize = (current_tilemap.bitmap_size & 1) ? 512 : 256;
+
+ xsize_mask = (current_tilemap.linescroll_enable) ? 1024 : xsize;
+ ysize_mask = (current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
+
+ pal_bank = current_tilemap.bitmap_palette_number;
+ pal_bank+= current_tilemap.colour_ram_address_offset;
+ pal_bank&= 7;
+ pal_bank<<=8;
+ if(current_tilemap.fade_control & 1)
+ pal_bank += ((current_tilemap.fade_control & 2) ? (2*2048) : (2048));
+
+ for(ydst=cliprect->min_y;ydst<=cliprect->max_y;ydst++)
+ {
+ for(xdst=cliprect->min_x;xdst<=cliprect->max_x;xdst++)
+ {
+ if(!vdp2_window_process(xdst,ydst))
+ continue;
+
+ xf = current_tilemap.incx * xdst;
+ xf>>=16;
+ yf = current_tilemap.incy * ydst;
+ yf>>=16;
+
+ xsrc = (xf + scrollx) & (xsize_mask-1);
+ ysrc = (yf + scrolly) & (ysize_mask-1);
+ src_offs = (xsrc + (ysrc*xsize));
+ src_offs/= 2;
+ src_offs += map_offset;
+ src_offs &= 0x7ffff;
+
+ dot_data = vram[src_offs] >> ((xsrc & 1) ? 0 : 4);
+ dot_data&= 0xf;
+
+ if ((dot_data != 0) || (current_tilemap.transparency & STV_TRANSPARENCY_NONE))
+ {
+ dot_data += pal_bank;
+
+ if ( current_tilemap.colour_calculation_enabled == 0 )
+ BMP32(bitmap, ydst)[xdst] = PEN(dot_data);
+ else
+ BMP32(bitmap, ydst)[xdst] = stv_alpha_blend_r32(BMP32(bitmap, ydst)[xdst], PEN(dot_data), current_tilemap.alpha);
+ }
+ }
+ }
+}
+
+
+static void draw_8bpp_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int xsize, ysize, xsize_mask, ysize_mask;
+ int xsrc,ysrc,xdst,ydst;
+ int src_offs;
+ UINT8* vram = vdp2l.gfx_decode;
+ UINT32 map_offset = current_tilemap.bitmap_map * 0x20000;
+ int scrollx = current_tilemap.scrollx;
+ int scrolly = current_tilemap.scrolly;
+ UINT16 dot_data;
+ UINT16 pal_bank;
+ int xf, yf;
+
+ xsize = (current_tilemap.bitmap_size & 2) ? 1024 : 512;
+ ysize = (current_tilemap.bitmap_size & 1) ? 512 : 256;
+
+ xsize_mask = (current_tilemap.linescroll_enable) ? 1024 : xsize;
+ ysize_mask = (current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
+
+ pal_bank = current_tilemap.bitmap_palette_number;
+ pal_bank+= current_tilemap.colour_ram_address_offset;
+ pal_bank&= 7;
+ pal_bank<<=8;
+ if(current_tilemap.fade_control & 1)
+ pal_bank += ((current_tilemap.fade_control & 2) ? (2*2048) : (2048));
+
+ for(ydst=cliprect->min_y;ydst<=cliprect->max_y;ydst++)
+ {
+ for(xdst=cliprect->min_x;xdst<=cliprect->max_x;xdst++)
+ {
+ if(!vdp2_window_process(xdst,ydst))
+ continue;
+
+ xf = current_tilemap.incx * xdst;
+ xf>>=16;
+ yf = current_tilemap.incy * ydst;
+ yf>>=16;
+
+ xsrc = (xf + scrollx) & (xsize_mask-1);
+ ysrc = (yf + scrolly) & (ysize_mask-1);
+ src_offs = (xsrc + (ysrc*xsize));
+ src_offs += map_offset;
+ src_offs &= 0x7ffff;
+
+ dot_data = vram[src_offs];
+
+ if ((dot_data != 0) || (current_tilemap.transparency & STV_TRANSPARENCY_NONE))
+ {
+ dot_data += pal_bank;
+
+ if ( current_tilemap.colour_calculation_enabled == 0 )
+ BMP32(bitmap, ydst)[xdst] = PEN(dot_data);
+ else
+ BMP32(bitmap, ydst)[xdst] = stv_alpha_blend_r32(BMP32(bitmap, ydst)[xdst], PEN(dot_data), current_tilemap.alpha);
+ }
+ }
+ }
+}
+
+static void draw_11bpp_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int xsize, ysize, xsize_mask, ysize_mask;
+ int xsrc,ysrc,xdst,ydst;
+ int src_offs;
+ UINT8* vram = vdp2l.gfx_decode;
+ UINT32 map_offset = current_tilemap.bitmap_map * 0x20000;
+ int scrollx = current_tilemap.scrollx;
+ int scrolly = current_tilemap.scrolly;
+ UINT16 dot_data;
+ UINT16 pal_bank;
+ int xf, yf;
+
+ xsize = (current_tilemap.bitmap_size & 2) ? 1024 : 512;
+ ysize = (current_tilemap.bitmap_size & 1) ? 512 : 256;
+
+ xsize_mask = (current_tilemap.linescroll_enable) ? 1024 : xsize;
+ ysize_mask = (current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
+
+ pal_bank = 0;
+ if(current_tilemap.fade_control & 1)
+ pal_bank = ((current_tilemap.fade_control & 2) ? (2*2048) : (2048));
+
+ for(ydst=cliprect->min_y;ydst<=cliprect->max_y;ydst++)
+ {
+ for(xdst=cliprect->min_x;xdst<=cliprect->max_x;xdst++)
+ {
+ if(!vdp2_window_process(xdst,ydst))
+ continue;
+
+ xf = current_tilemap.incx * xdst;
+ xf>>=16;
+ yf = current_tilemap.incy * ydst;
+ yf>>=16;
+
+ xsrc = (xf + scrollx) & (xsize_mask-1);
+ ysrc = (yf + scrolly) & (ysize_mask-1);
+ src_offs = (xsrc + (ysrc*xsize));
+ src_offs *= 2;
+ src_offs += map_offset;
+ src_offs &= 0x7ffff;
+
+ dot_data = ((vram[src_offs]<<8)|(vram[src_offs+1]<<0)) & 0x7ff;
+
+ if ((dot_data != 0) || (current_tilemap.transparency & STV_TRANSPARENCY_NONE))
+ {
+ dot_data += pal_bank;
+
+ if ( current_tilemap.colour_calculation_enabled == 0 )
+ BMP32(bitmap, ydst)[xdst] = PEN(dot_data);
+ else
+ BMP32(bitmap, ydst)[xdst] = stv_alpha_blend_r32(BMP32(bitmap, ydst)[xdst], PEN(dot_data), current_tilemap.alpha);
+ }
+ }
+ }
+}
+
+
+static void draw_rgb15_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int xsize, ysize, xsize_mask, ysize_mask;
+ int xsrc,ysrc,xdst,ydst;
+ int src_offs;
+ UINT8* vram = vdp2l.gfx_decode;
+ UINT32 map_offset = current_tilemap.bitmap_map * 0x20000;
+ int scrollx = current_tilemap.scrollx;
+ int scrolly = current_tilemap.scrolly;
+ int r,g,b;
+ UINT16 dot_data;
+ int xf, yf;
+
+ xsize = (current_tilemap.bitmap_size & 2) ? 1024 : 512;
+ ysize = (current_tilemap.bitmap_size & 1) ? 512 : 256;
+
+ xsize_mask = (current_tilemap.linescroll_enable) ? 1024 : xsize;
+ ysize_mask = (current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
+
+ for(ydst=cliprect->min_y;ydst<=cliprect->max_y;ydst++)
+ {
+ for(xdst=cliprect->min_x;xdst<=cliprect->max_x;xdst++)
+ {
+ if(!vdp2_window_process(xdst,ydst))
+ continue;
+
+ xf = current_tilemap.incx * xdst;
+ xf>>=16;
+ yf = current_tilemap.incy * ydst;
+ yf>>=16;
+
+ xsrc = (xf + scrollx) & (xsize_mask-1);
+ ysrc = (yf + scrolly) & (ysize_mask-1);
+ src_offs = (xsrc + (ysrc*xsize));
+ src_offs *= 2;
+ src_offs += map_offset;
+ src_offs &= 0x7ffff;
+
+ dot_data =(vram[src_offs]<<8)|(vram[src_offs+1]<<0);
+
+ if ((dot_data & 0x8000) || (current_tilemap.transparency & STV_TRANSPARENCY_NONE))
+ {
+ b = pal5bit((dot_data & 0x7c00) >> 10);
+ g = pal5bit((dot_data & 0x03e0) >> 5);
+ r = pal5bit((dot_data & 0x001f) >> 0);
+
+ if(current_tilemap.fade_control & 1)
+ vdp2_compute_color_offset(&r,&g,&b,current_tilemap.fade_control & 2);
+
+ if ( current_tilemap.colour_calculation_enabled == 0 )
+ BMP32(bitmap, ydst)[xdst] = RGB_MAKE(r, g, b);
+ else
+ BMP32(bitmap, ydst)[xdst] = stv_alpha_blend_r32( BMP32(bitmap, ydst)[xdst], RGB_MAKE(r, g, b), current_tilemap.alpha );
+ }
+ }
+ }
+}
+
+static void draw_rgb32_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int xsize, ysize, xsize_mask, ysize_mask;
+ int xsrc,ysrc,xdst,ydst;
+ int src_offs;
+ UINT8* vram = vdp2l.gfx_decode;
+ UINT32 map_offset = current_tilemap.bitmap_map * 0x20000;
+ int scrollx = current_tilemap.scrollx;
+ int scrolly = current_tilemap.scrolly;
+ int r,g,b;
+ UINT32 dot_data;
+ int xf, yf;
+
+ xsize = (current_tilemap.bitmap_size & 2) ? 1024 : 512;
+ ysize = (current_tilemap.bitmap_size & 1) ? 512 : 256;
+
+ xsize_mask = (current_tilemap.linescroll_enable) ? 1024 : xsize;
+ ysize_mask = (current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
+
+ for(ydst=cliprect->min_y;ydst<=cliprect->max_y;ydst++)
+ {
+ for(xdst=cliprect->min_x;xdst<=cliprect->max_x;xdst++)
+ {
+ if(!vdp2_window_process(xdst,ydst))
+ continue;
+
+ xf = current_tilemap.incx * xdst;
+ xf>>=16;
+ yf = current_tilemap.incy * ydst;
+ yf>>=16;
+
+ xsrc = (xf + scrollx) & (xsize_mask-1);
+ ysrc = (yf + scrolly) & (ysize_mask-1);
+ src_offs = (xsrc + (ysrc*xsize));
+ src_offs *= 4;
+ src_offs += map_offset;
+ src_offs &= 0x7ffff;
+
+ dot_data = (vram[src_offs+0]<<24)|(vram[src_offs+1]<<16)|(vram[src_offs+2]<<8)|(vram[src_offs+3]<<0);
+
+ if ((dot_data & 0x80000000) || (current_tilemap.transparency & STV_TRANSPARENCY_NONE))
+ {
+ b = ((dot_data & 0x00ff0000) >> 16);
+ g = ((dot_data & 0x0000ff00) >> 8);
+ r = ((dot_data & 0x000000ff) >> 0);
+
+ if(current_tilemap.fade_control & 1)
+ vdp2_compute_color_offset(&r,&g,&b,current_tilemap.fade_control & 2);
+
+ if ( current_tilemap.colour_calculation_enabled == 0 )
+ BMP32(bitmap, ydst)[xdst] = RGB_MAKE(r, g, b);
+ else
+ BMP32(bitmap, ydst)[xdst] = stv_alpha_blend_r32( BMP32(bitmap, ydst)[xdst], RGB_MAKE(r, g, b), current_tilemap.alpha );
+ }
+ }
+ }
+}
+
+
+static void vdp2_draw_basic_bitmap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ if (!current_tilemap.enabled) return;
+
+ /* new bitmap code, supposed to rewrite the old one. Not supposed to be clean, but EFFICIENT! */
+ if(current_tilemap.incx == 0x10000 && current_tilemap.incy == 0x10000)
+ {
+ switch(current_tilemap.colour_depth)
+ {
+ case 0: draw_4bpp_bitmap(bitmap,cliprect); return;
+ case 1: draw_8bpp_bitmap(bitmap,cliprect); return;
+ case 2: draw_11bpp_bitmap(bitmap, cliprect); return;
+ case 3: draw_rgb15_bitmap(bitmap,cliprect); return;
+ case 4: draw_rgb32_bitmap(bitmap,cliprect); return;
+ }
+
+ /* intentional fall-through*/
+ popmessage("%d %s %s %s",current_tilemap.colour_depth,
+ current_tilemap.transparency & STV_TRANSPARENCY_NONE ? "no trans" : "trans",
+ current_tilemap.colour_calculation_enabled ? "cc" : "no cc",
+ (current_tilemap.incx == 0x10000 && current_tilemap.incy == 0x10000) ? "no zoom" : "zoom");
+ }
+ else
+ {
+ switch(current_tilemap.colour_depth)
+ {
+ case 0: draw_4bpp_bitmap(bitmap,cliprect); return;
+ case 1: draw_8bpp_bitmap(bitmap,cliprect); return;
+ /* case 2: draw_11bpp_bitmap(bitmap,cliprect); return; */
+ case 3: draw_rgb15_bitmap(bitmap,cliprect); return;
+ case 4: draw_rgb32_bitmap(bitmap,cliprect); return;
+ }
+
+ /* intentional fall-through*/
+ popmessage("%d %s %s %s",current_tilemap.colour_depth,
+ current_tilemap.transparency & STV_TRANSPARENCY_NONE ? "no trans" : "trans",
+ current_tilemap.colour_calculation_enabled ? "cc" : "no cc",
+ (current_tilemap.incx == 0x10000 && current_tilemap.incy == 0x10000) ? "no zoom" : "zoom");
+ }
+}
+
+ /*---------------------------------------------------------------------------
+ | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
+ ----------------------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 6-0 * 0x02000 |
+ | | 1 word |-------------------------------------|
+ | | | 2 H x 2 V | bits 8-0 * 0x00800 |
+ | 1 H x 1 V ---------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 5-0 * 0x04000 |
+ | | 2 words |-------------------------------------|
+ | | | 2 H x 2 V | bits 7-0 * 0x01000 |
+ -----------------------------------------------------------------------------
+ | | | 1 H x 1 V | bits 6-1 * 0x04000 |
+ | | 1 word |-------------------------------------|
+ | | | 2 H x 2 V | bits 8-1 * 0x01000 |
+ | 2 H x 1 V ---------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 5-1 * 0x08000 |
+ | | 2 words |-------------------------------------|
+ | | | 2 H x 2 V | bits 7-1 * 0x02000 |
+ -----------------------------------------------------------------------------
+ | | | 1 H x 1 V | bits 6-2 * 0x08000 |
+ | | 1 word |-------------------------------------|
+ | | | 2 H x 2 V | bits 8-2 * 0x02000 |
+ | 2 H x 2 V ---------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 5-2 * 0x10000 |
+ | | 2 words |-------------------------------------|
+ | | | 2 H x 2 V | bits 7-2 * 0x04000 |
+ --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/
+
+
+/*
+4.2 Sega's Cell / Character Pattern / Page / Plane / Map system, aka a rather annoying thing that makes optimizations hard
+ (this is only for the normal tilemaps at the moment, i haven't even thought about the ROZ ones)
+
+Tiles:
+
+Cells are 8x8 gfx stored in video ram, they can be of various colour depths
+
+Character Patterns can be 8x8 or 16x16 (1 hcell x 1 vcell or 2 hcell x 2 vcell)
+ (a 16x16 character pattern is 4 8x8 cells put together)
+
+A page is made up of 64x64 cells, thats 64x64 character patterns in 8x8 mode or 32x32 character patterns in 16x16 mode.
+ 64 * 8 = 512 (0x200)
+ 32 * 16 = 512 (0x200)
+A page is _always_ 512 (0x200) pixels in each direction
+
+in 1 word mode a 32*16 x 32*16 page is 0x0800 bytes
+in 1 word mode a 64*8 x 64*8 page is 0x2000 bytes
+in 2 word mode a 32*16 x 32*16 page is 0x1000 bytes
+in 2 word mode a 64*8 x 64*8 page is 0x4000 bytes
+
+either 1, 2 or 4 pages make each plane depending on the plane size register (per tilemap)
+ therefore each plane is either
+ 64 * 8 * 1 x 64 * 8 * 1 (512 x 512)
+ 64 * 8 * 2 x 64 * 8 * 1 (1024 x 512)
+ 64 * 8 * 2 x 64 * 8 * 2 (1024 x 1024)
+
+ 32 * 16 * 1 x 32 * 16 * 1 (512 x 512)
+ 32 * 16 * 2 x 32 * 16 * 1 (1024 x 512)
+ 32 * 16 * 2 x 32 * 16 * 2 (1024 x 1024)
+
+map is always enabled?
+ map is a 2x2 arrangement of planes, all 4 of the planes can be the same.
+
+*/
+
+static void vdp2_get_map_page( int x, int y, int *_map, int *_page )
+{
+ int page = 0;
+ int map;
+
+ if ( current_tilemap.map_count == 4 )
+ {
+ if ( current_tilemap.tile_size == 0 )
+ {
+ if ( current_tilemap.plane_size & 1 )
+ {
+ page = ((x >> 6) & 1);
+ map = (x >> 7) & 1;
+ }
+ else
+ {
+ map = (x >> 6) & 1;
+ }
+
+ if ( current_tilemap.plane_size & 2 )
+ {
+ page |= ((y >> (6-1)) & 2);
+ map |= ((y >> (7-1)) & 2);
+ }
+ else
+ {
+ map |= ((y >> (6-1)) & 2);
+ }
+ }
+ else
+ {
+ if ( current_tilemap.plane_size & 1 )
+ {
+ page = ((x >> 5) & 1);
+ map = (x >> 6) & 1;
+ }
+ else
+ {
+ map = (x >> 5) & 1;
+ }
+
+ if ( current_tilemap.plane_size & 2 )
+ {
+ page |= ((y >> (5 - 1)) & 2);
+ map |= ((y >> (6-1)) & 2);
+ }
+ else
+ {
+ map |= ((y >> (5-1)) & 2);
+ }
+ }
+ }
+ else /*16 */
+ {
+ if ( current_tilemap.tile_size == 0 )
+ {
+ if ( current_tilemap.plane_size & 1 )
+ {
+ page = ((x >> 6) & 1);
+ map = (x >> 7) & 3;
+ }
+ else
+ {
+ map = (x >> 6) & 3;
+ }
+
+ if ( current_tilemap.plane_size & 2 )
+ {
+ page |= ((y >> (6-1)) & 2);
+ map |= ((y >> (7-2)) & 12);
+ }
+ else
+ {
+ map |= ((y >> (6-2)) & 12);
+ }
+ }
+ else
+ {
+ if ( current_tilemap.plane_size & 1 )
+ {
+ page = ((x >> 5) & 1);
+ map = (x >> 6) & 3;
+ }
+ else
+ {
+ map = (x >> 5) & 3;
+ }
+
+ if ( current_tilemap.plane_size & 2 )
+ {
+ page |= ((y >> (5 - 1)) & 2);
+ map |= ((y >> (6-2)) & 12);
+ }
+ else
+ {
+ map |= ((y >> (5-2)) & 12);
+ }
+ }
+ }
+ *_page = page;
+ *_map = map;
+}
+
+static void vdp2_draw_basic_tilemap(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ /* hopefully this is easier to follow than it is efficient .. */
+
+ /* I call character patterns tiles .. even if they represent up to 4 tiles */
+
+ /* Page variables */
+ int pgtiles_x, pgpixels_x;
+ int pgtiles_y, pgpixels_y;
+ int pgsize_bytes, pgsize_dwords;
+
+ /* Plane Variables */
+ int pltiles_x, plpixels_x;
+ int pltiles_y, plpixels_y;
+ int plsize_bytes/*, plsize_dwords*/;
+
+ /* Map Variables */
+ int mptiles_x, mppixels_x;
+ int mptiles_y, mppixels_y;
+ int mpsize_bytes, mpsize_dwords;
+
+ /* work Variables */
+ int i, x, y;
+ int base[16];
+
+ int scalex,scaley;
+ int tilesizex, tilesizey;
+ int drawypos, drawxpos;
+
+ int tilecodemin = 0x10000000, tilecodemax = 0;
+ int palmin = 0x10000000, palmax = 0;
+
+ if ( current_tilemap.incx == 0 || current_tilemap.incy == 0 ) return;
+
+ if ( current_tilemap.colour_calculation_enabled == 1 )
+ {
+ if ( VDP2_CCMD )
+ {
+ current_tilemap.transparency |= STV_TRANSPARENCY_ADD_BLEND;
+ }
+ else
+ {
+ current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA;
+ }
+ }
+
+ scalex = (INT32)(((INT64)1 << 32) / (INT64)current_tilemap.incx);
+ scaley = (INT32)(((INT64)1 << 32) / (INT64)current_tilemap.incy);
+ tilesizex = scalex * 8;
+ tilesizey = scaley * 8;
+ drawypos = drawxpos = 0;
+
+ /* Calculate the Number of tiles for x / y directions of each page (actually these will be the same */
+ /* (2-current_tilemap.tile_size) << 5) */
+ pgtiles_x = ((2-current_tilemap.tile_size) << 5); /* 64 (8x8 mode) or 32 (16x16 mode) */
+ pgtiles_y = ((2-current_tilemap.tile_size) << 5); /* 64 (8x8 mode) or 32 (16x16 mode) */
+
+ /* Calculate the Page Size in BYTES */
+ /* 64 * 64 * (1 * 2) = 0x2000 bytes
+ 32 * 32 * (1 * 2) = 0x0800 bytes
+ 64 * 64 * (2 * 2) = 0x4000 bytes
+ 32 * 32 * (2 * 2) = 0x1000 bytes */
+
+ pgsize_bytes = (pgtiles_x * pgtiles_y) * ((2-current_tilemap.pattern_data_size)*2);
+
+ /*---------------------------------------------------------------------------
+ | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
+ ----------------------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 6-0 * 0x02000 |
+ | | 1 word |-------------------------------------|
+ | | | 2 H x 2 V | bits 8-0 * 0x00800 |
+ | 1 H x 1 V ---------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 5-0 * 0x04000 |
+ | | 2 words |-------------------------------------|
+ | | | 2 H x 2 V | bits 7-0 * 0x01000 |
+ ---------------------------------------------------------------------------*/
+
+
+ /* Page Dimensions are always 0x200 pixes (512x512) */
+ pgpixels_x = 0x200;
+ pgpixels_y = 0x200;
+
+ /* Work out the Plane Size in tiles and Plane Dimensions (pixels) */
+ switch (current_tilemap.plane_size & 3)
+ {
+ case 0: /* 1 page * 1 page */
+ pltiles_x = pgtiles_x;
+ plpixels_x = pgpixels_x;
+ pltiles_y = pgtiles_y;
+ plpixels_y = pgpixels_y;
+ break;
+
+ case 1: /* 2 pages * 1 page */
+ pltiles_x = pgtiles_x * 2;
+ plpixels_x = pgpixels_x * 2;
+ pltiles_y = pgtiles_y;
+ plpixels_y = pgpixels_y;
+ break;
+
+ case 3: /* 2 pages * 2 pages */
+ pltiles_x = pgtiles_x * 2;
+ plpixels_x = pgpixels_x * 2;
+ pltiles_y = pgtiles_y * 2;
+ plpixels_y = pgpixels_y * 2;
+ break;
+
+ default:
+ /* illegal */
+ pltiles_x = pgtiles_x;
+ plpixels_x = pgpixels_x;
+ pltiles_y = pgtiles_y * 2;
+ plpixels_y = pgpixels_y * 2;
+ break;
+ }
+
+ /* Plane Size in BYTES */
+ /* still the same as before
+ (64 * 1) * (64 * 1) * (1 * 2) = 0x02000 bytes
+ (32 * 1) * (32 * 1) * (1 * 2) = 0x00800 bytes
+ (64 * 1) * (64 * 1) * (2 * 2) = 0x04000 bytes
+ (32 * 1) * (32 * 1) * (2 * 2) = 0x01000 bytes
+ changed
+ (64 * 2) * (64 * 1) * (1 * 2) = 0x04000 bytes
+ (32 * 2) * (32 * 1) * (1 * 2) = 0x01000 bytes
+ (64 * 2) * (64 * 1) * (2 * 2) = 0x08000 bytes
+ (32 * 2) * (32 * 1) * (2 * 2) = 0x02000 bytes
+ changed
+ (64 * 2) * (64 * 1) * (1 * 2) = 0x08000 bytes
+ (32 * 2) * (32 * 1) * (1 * 2) = 0x02000 bytes
+ (64 * 2) * (64 * 1) * (2 * 2) = 0x10000 bytes
+ (32 * 2) * (32 * 1) * (2 * 2) = 0x04000 bytes
+ */
+
+ plsize_bytes = (pltiles_x * pltiles_y) * ((2-current_tilemap.pattern_data_size)*2);
+
+ /*---------------------------------------------------------------------------
+ | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
+ -----------------------------------------------------------------------------
+ | 1 H x 1 V see above, nothing has changed |
+ -----------------------------------------------------------------------------
+ | | | 1 H x 1 V | bits 6-1 * 0x04000 |
+ | | 1 word |-------------------------------------|
+ | | | 2 H x 2 V | bits 8-1 * 0x01000 |
+ | 2 H x 1 V ---------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 5-1 * 0x08000 |
+ | | 2 words |-------------------------------------|
+ | | | 2 H x 2 V | bits 7-1 * 0x02000 |
+ -----------------------------------------------------------------------------
+ | | | 1 H x 1 V | bits 6-2 * 0x08000 |
+ | | 1 word |-------------------------------------|
+ | | | 2 H x 2 V | bits 8-2 * 0x02000 |
+ | 2 H x 2 V ---------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 5-2 * 0x10000 |
+ | | 2 words |-------------------------------------|
+ | | | 2 H x 2 V | bits 7-2 * 0x04000 |
+ --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/
+
+
+ /* Work out the Map Sizes in tiles, Map Dimensions */
+ /* maps are always enabled? */
+ if ( current_tilemap.map_count == 4 )
+ {
+ mptiles_x = pltiles_x * 2;
+ mptiles_y = pltiles_y * 2;
+ mppixels_x = plpixels_x * 2;
+ mppixels_y = plpixels_y * 2;
+ }
+ else
+ {
+ mptiles_x = pltiles_x * 4;
+ mptiles_y = pltiles_y * 4;
+ mppixels_x = plpixels_x * 4;
+ mppixels_y = plpixels_y * 4;
+ }
+
+ /* Map Size in BYTES */
+ mpsize_bytes = (mptiles_x * mptiles_y) * ((2-current_tilemap.pattern_data_size)*2);
+
+
+ /*-----------------------------------------------------------------------------------------------------------
+ | | | 1 H x 1 V | bits 6-1 (upper mask 0x07f) (0x1ff >> 2) * 0x04000 |
+ | | 1 word |---------------------------------------------------------------------|
+ | | | 2 H x 2 V | bits 8-1 (upper mask 0x1ff) (0x1ff >> 0) * 0x01000 |
+ | 2 H x 1 V -----------------------------------------------------------------------------------------------|
+ | | | 1 H x 1 V | bits 5-1 (upper mask 0x03f) (0x1ff >> 3) * 0x08000 |
+ | | 2 words |---------------------------------------------------------------------|
+ | | | 2 H x 2 V | bits 7-1 (upper mask 0x0ff) (0x1ff >> 1) * 0x02000 |
+ -------------------------------------------------------------------------------------------------------------
+ lower mask = ~current_tilemap.plane_size
+ -----------------------------------------------------------------------------------------------------------*/
+
+ /* Precalculate bases from MAP registers */
+ for (i = 0; i < current_tilemap.map_count; i++)
+ {
+ static const int shifttable[4] = {0,1,2,2};
+
+ int uppermask, uppermaskshift;
+
+ uppermaskshift = (1-current_tilemap.pattern_data_size) | ((1-current_tilemap.tile_size)<<1);
+ uppermask = 0x1ff >> uppermaskshift;
+
+ base[i] = ((current_tilemap.map_offset[i] & uppermask) >> shifttable[current_tilemap.plane_size]) * plsize_bytes;
+
+ base[i] &= 0x7ffff; /* shienryu needs this for the text layer, is there a problem elsewhere or is it just right without the ram cart */
+
+ base[i] = base[i] / 4; /* convert bytes to DWORDS */
+ }
+
+ /* other bits */
+ /*current_tilemap.trans_enabled = current_tilemap.trans_enabled ? STV_TRANSPARENCY_NONE : STV_TRANSPARENCY_PEN; */
+ current_tilemap.scrollx &= mppixels_x-1;
+ current_tilemap.scrolly &= mppixels_y-1;
+
+ pgsize_dwords = pgsize_bytes /4;
+ /*plsize_dwords = plsize_bytes /4; */
+ mpsize_dwords = mpsize_bytes /4;
+
+ if (!current_tilemap.enabled) return; /* stop right now if its disabled ... */
+
+ /* most things we need (or don't need) to work out are now worked out */
+
+ for (y = 0; y> 16) < cliprect->min_y )
+ {
+ drawypos += drawyposinc;
+ y++;
+ }
+ mptiles_y += y;
+ }
+ else
+ {
+ drawypos += tilesizey*(current_tilemap.tile_size ? 2 : 1);
+ }
+ if ((drawypos >> 16) > cliprect->max_y) break;
+
+ ypageoffs = y & (pgtiles_y-1);
+
+ for (x = 0; x> 16) < cliprect->min_x )
+ {
+ drawxpos += drawxposinc;
+ x++;
+ }
+ mptiles_x += x;
+ }
+ else
+ {
+ drawxpos+=tilesizex*(current_tilemap.tile_size ? 2 : 1);
+ }
+ if ( (drawxpos >> 16) > cliprect->max_x ) break;
+
+ xpageoffs = x & (pgtiles_x-1);
+
+ vdp2_get_map_page(x,y,&map,&page);
+
+ newbase = base[map] + page * pgsize_dwords;
+ offs = (ypageoffs * pgtiles_x) + xpageoffs;
+
+ if (vdp2_cell_redraw.active)
+ {
+ /* only the cells with a rewritten pattern name, cleared first like a full rebuild */
+ const UINT32 addr = newbase + ((current_tilemap.pattern_data_size == 1) ? (offs / 2) : offs);
+ const int cellsize = current_tilemap.tile_size ? 16 : 8;
+ struct rectangle cell;
+
+ if (addr < vdp2_cell_redraw.min || addr >= vdp2_cell_redraw.max)
+ continue;
+
+ cell.min_x = drawxpos >> 16;
+ cell.min_y = drawypos >> 16;
+ cell.max_x = cell.min_x + cellsize - 1;
+ cell.max_y = cell.min_y + cellsize - 1;
+ if (cell.min_x < cliprect->min_x) cell.min_x = cliprect->min_x;
+ if (cell.min_y < cliprect->min_y) cell.min_y = cliprect->min_y;
+ if (cell.max_x > cliprect->max_x) cell.max_x = cliprect->max_x;
+ if (cell.max_y > cliprect->max_y) cell.max_y = cliprect->max_y;
+ if (cell.min_x <= cell.max_x && cell.min_y <= cell.max_y)
+ bitmap_fill32(bitmap, &cell, 0);
+ }
+
+/* GET THE TILE INFO ... */
+ /* 1 word per tile mode with supplement bits */
+ if (current_tilemap.pattern_data_size ==1)
+ {
+ data = vdp2_vram[newbase + offs/2];
+ data = (offs&1) ? (data & 0x0000ffff) : ((data & 0xffff0000) >> 16);
+
+ /* Supplement Mode 12 bits, no flip */
+ if (current_tilemap.character_number_supplement == 1)
+ {
+/* no flip */ flipyx = 0;
+/* 8x8 */ if (current_tilemap.tile_size==0) tilecode = (data & 0x0fff) + ( (current_tilemap.supplementary_character_bits&0x1c) << 10);
+/* 16x16 */ else tilecode = ((data & 0x0fff) << 2) + (current_tilemap.supplementary_character_bits&0x03) + ((current_tilemap.supplementary_character_bits&0x10) << 10);
+ }
+ /* Supplement Mode 10 bits, with flip */
+ else
+ {
+/* flip bits */ flipyx = (data & 0x0c00) >> 10;
+/* 8x8 */ if (current_tilemap.tile_size==0) tilecode = (data & 0x03ff) + ( (current_tilemap.supplementary_character_bits) << 10);
+/* 16x16 */ else tilecode = ((data & 0x03ff) <<2) + (current_tilemap.supplementary_character_bits&0x03) + ((current_tilemap.supplementary_character_bits&0x1c) << 10);
+ }
+
+/*>16cols*/ if (current_tilemap.colour_depth != 0) pal = ((data & 0x7000)>>8);
+/*16 cols*/ else pal = ((data & 0xf000)>>12) +( (current_tilemap.supplementary_palette_bits) << 4);
+
+ }
+ /* 2 words per tile, no supplement bits */
+ else
+ {
+ data = vdp2_vram[newbase + offs];
+ tilecode = (data & 0x00007fff);
+ pal = (data & 0x007f0000)>>16;
+ /* specialc = (data & 0x10000000)>>28; */
+ flipyx = (data & 0xc0000000)>>30;
+ }
+/* WE'VE GOT THE TILE INFO ... */
+
+ if ( tilecode < tilecodemin ) tilecodemin = tilecode;
+ if ( tilecode > tilecodemax ) tilecodemax = tilecode;
+
+/* DECODE ANY TILES WE NEED TO DECODE */
+
+ pal += current_tilemap.colour_ram_address_offset<< 4; /* bios uses this .. */
+
+ if ( pal < palmin )
+ {
+ palmin = pal;
+ }
+ if ( pal > palmax )
+ {
+ palmax = pal;
+ }
+
+ /*Enable fading bit*/
+ if(current_tilemap.fade_control & 1)
+ {
+ /*Select fading bit*/
+ pal += ((current_tilemap.fade_control & 2) ? (0x100) : (0x80));
+ }
+
+ if (current_tilemap.colour_depth == 1)
+ {
+ gfx = 2;
+ pal = pal >>4;
+ tilecode &=0x7fff;
+ if (tilecode == 0x7fff) tilecode--; /* prevents crash but unsure what should happen; wrapping? */
+ tilecodespacing = 2;
+ }
+ else if (current_tilemap.colour_depth == 0)
+ {
+ gfx = 0;
+ tilecode &=0x7fff;
+ tilecodespacing = 1;
+ }
+/* TILES ARE NOW DECODED */
+
+ if(!get_vramsz())
+ tilecode &= 0x3fff;
+
+/* DRAW! */
+ if(current_tilemap.incx != 0x10000 ||
+ current_tilemap.incy != 0x10000 ||
+ current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND )
+ {
+#define SCR_TILESIZE_X (((drawxpos + tilesizex) >> 16) - (drawxpos >> 16))
+#define SCR_TILESIZE_X1(startx) (((drawxpos + (startx) + tilesizex) >> 16) - ((drawxpos + (startx))>>16))
+#define SCR_TILESIZE_Y (((drawypos + tilesizey) >> 16) - (drawypos >> 16))
+#define SCR_TILESIZE_Y1(starty) (((drawypos + (starty) + tilesizey) >> 16) - ((drawypos + (starty))>>16))
+ if (current_tilemap.tile_size==1)
+ {
+ if ( current_tilemap.colour_depth == 4 )
+ {
+ popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 1");
+ }
+ else if ( current_tilemap.colour_depth == 3 )
+ {
+ /* RGB555 */
+ vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,current_tilemap.alpha);
+ vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,current_tilemap.alpha);
+ vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),current_tilemap.alpha);
+ vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),current_tilemap.alpha);
+ }
+ else
+ {
+ /* normal */
+ vdp2_drawgfxzoom(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,current_tilemap.alpha);
+ vdp2_drawgfxzoom(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,current_tilemap.alpha);
+ vdp2_drawgfxzoom(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),current_tilemap.alpha);
+ vdp2_drawgfxzoom(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),current_tilemap.alpha);
+ }
+ }
+ else
+ {
+ if ( current_tilemap.colour_depth == 4 )
+ popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 0");
+ else if ( current_tilemap.colour_depth == 3)
+ {
+ vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,current_tilemap.alpha);
+ }
+ else
+ vdp2_drawgfxzoom(bitmap,cliprect,(&stv_gfx[gfx]),tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,current_tilemap.alpha);
+ }
+ }
+ else
+ {
+ int olddrawxpos, olddrawypos;
+ olddrawxpos = drawxpos; drawxpos >>= 16;
+ olddrawypos = drawypos; drawypos >>= 16;
+ if (current_tilemap.tile_size==1)
+ {
+ if ( current_tilemap.colour_depth == 4 )
+ {
+ /* normal, an 8x8 RGB888 cell takes 8 character number units (32 bytes each) */
+ vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*8,flipyx&1,flipyx&2,drawxpos, drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*8,flipyx&1,flipyx&2,drawxpos+8,drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*8,flipyx&1,flipyx&2,drawxpos,drawypos+8,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*8,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,current_tilemap.transparency,current_tilemap.alpha);
+ }
+ else if ( current_tilemap.colour_depth == 3 )
+ {
+ /* normal */
+ vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,current_tilemap.transparency,current_tilemap.alpha);
+ }
+ else if (current_tilemap.transparency & STV_TRANSPARENCY_ALPHA)
+ {
+ /* alpha */
+ vdp2_drawgfx_alpha(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_alpha(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_alpha(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,current_tilemap.transparency,current_tilemap.alpha);
+ vdp2_drawgfx_alpha(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,current_tilemap.transparency,current_tilemap.alpha);
+ }
+ else
+ {
+ /* normal */
+ vdp2_drawgfx_transpen(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,current_tilemap.transparency);
+ vdp2_drawgfx_transpen(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,current_tilemap.transparency);
+ vdp2_drawgfx_transpen(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,current_tilemap.transparency);
+ vdp2_drawgfx_transpen(bitmap,cliprect,(&stv_gfx[gfx]),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,current_tilemap.transparency);
+ }
+ }
+ else
+ {
+ if ( current_tilemap.colour_depth == 4)
+ {
+ vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ }
+ else if ( current_tilemap.colour_depth == 3)
+ {
+ vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ }
+ else
+ {
+ if (current_tilemap.transparency & STV_TRANSPARENCY_ALPHA)
+ vdp2_drawgfx_alpha(bitmap,cliprect,(&stv_gfx[gfx]),tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,current_tilemap.transparency,current_tilemap.alpha);
+ else
+ vdp2_drawgfx_transpen(bitmap,cliprect,(&stv_gfx[gfx]),tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,current_tilemap.transparency);
+ }
+ }
+ drawxpos = olddrawxpos;
+ drawypos = olddrawypos;
+ }
+/* DRAWN?! */
+
+ }
+ }
+ if ( current_tilemap.layer_name & 0x80 )
+ {
+ static const int shifttable[4] = {0,1,2,2};
+ int uppermask, uppermaskshift;
+ int mapsize;
+ uppermaskshift = (1-current_tilemap.pattern_data_size) | ((1-current_tilemap.tile_size)<<1);
+ uppermask = 0x1ff >> uppermaskshift;
+
+ log_masked(LOG_VDP2, "Layer RBG%d, size %d x %d\n", current_tilemap.layer_name & 0x7f, cliprect->max_x + 1, cliprect->max_y + 1);
+ log_masked(LOG_VDP2, "Tiles: min %08X, max %08X\n", tilecodemin, tilecodemax);
+ log_masked(LOG_VDP2, "MAP size in dwords %08X\n", mpsize_dwords);
+ for (i = 0; i < current_tilemap.map_count; i++)
+ {
+ log_masked(LOG_VDP2, "Map register %d: base %08X\n", current_tilemap.map_offset[i], base[i]);
+ }
+
+ /* store map information */
+ vdp2_layer_data.map_offset_min = 0x7fffffff;
+ vdp2_layer_data.map_offset_max = 0x00000000;
+
+ for (i = 0; i < current_tilemap.map_count; i++)
+ {
+ UINT32 max_base;
+
+ if ( base[i] < vdp2_layer_data.map_offset_min )
+ vdp2_layer_data.map_offset_min = base[i];
+
+ /* Head On in Sega Memorial Collection 1 cares (uses RBG0 with all map regs equal to 0x20) */
+ max_base = (base[i] + plsize_bytes/4);
+ if ( max_base > vdp2_layer_data.map_offset_max )
+ vdp2_layer_data.map_offset_max = max_base;
+ }
+
+
+ mapsize = ((1 & uppermask) >> shifttable[current_tilemap.plane_size]) * plsize_bytes -
+ ((0 & uppermask) >> shifttable[current_tilemap.plane_size]) * plsize_bytes;
+ mapsize /= 4;
+
+ vdp2_layer_data.map_offset_max += mapsize;
+
+ vdp2_layer_data.tile_offset_min = tilecodemin * 0x20 / 4;
+ vdp2_layer_data.tile_offset_max = (tilecodemax + 1) * 0x20 / 4;
+
+ /* store the colours used as well, the RBG cache has them baked in */
+ switch ( current_tilemap.colour_depth )
+ {
+ case 0:
+ vdp2_layer_data.pen_min = palmin * 16;
+ vdp2_layer_data.pen_max = (palmax + 1) * 16;
+ break;
+ case 1:
+ vdp2_layer_data.pen_min = (palmin & ~0xf) * 16;
+ vdp2_layer_data.pen_max = ((palmax & ~0xf) + 0x10) * 16;
+ break;
+ case 2:
+ vdp2_layer_data.pen_min = 0;
+ vdp2_layer_data.pen_max = 0x800;
+ break;
+ default:
+ /* RGB, no palette */
+ vdp2_layer_data.pen_min = 0;
+ vdp2_layer_data.pen_max = 0;
+ break;
+ }
+ if ( palmin > palmax )
+ {
+ vdp2_layer_data.pen_min = vdp2_layer_data.pen_max = 0;
+ }
+ }
+
+}
+
+#define VDP2_READ_VERTICAL_LINESCROLL( _val, _address ) \
+ { \
+ _val = (INT32)((vdp2_vram[ _address ] & 0x07ffff00) << 5) >> 5; \
+ }
+
+
+static void vdp2_check_tilemap_with_linescroll(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ struct rectangle mycliprect;
+ int cur_line = cliprect->min_y;
+ int address;
+ int active_functions = 0;
+ INT32 scroll_values[3], prev_scroll_values[3];
+ int i;
+ int scroll_values_equal;
+ int lines;
+ INT16 main_scrollx, main_scrolly;
+/* INT32 incx; */
+ int linescroll_enable, vertical_linescroll_enable, linezoom_enable;
+ int vertical_linescroll_index = -1;
+
+ /* read original scroll values */
+ main_scrollx = current_tilemap.scrollx;
+ main_scrolly = current_tilemap.scrolly;
+/* incx = current_tilemap.incx; */
+
+ /* prepare linescroll flags */
+ linescroll_enable = current_tilemap.linescroll_enable;
+/* current_tilemap.linescroll_enable = 0; */
+ vertical_linescroll_enable = current_tilemap.vertical_linescroll_enable;
+/* current_tilemap.vertical_linescroll_enable = 0; */
+ linezoom_enable = current_tilemap.linezoom_enable;
+/* current_tilemap.linezoom_enable = 0; */
+
+ /* prepare working clipping rectangle */
+ memcpy( &mycliprect, cliprect, sizeof(struct rectangle) );
+
+ /* calculate the number of active functions */
+ if ( linescroll_enable ) active_functions++;
+ if ( vertical_linescroll_enable )
+ {
+ vertical_linescroll_index = active_functions;
+ active_functions++;
+ }
+ if ( linezoom_enable ) active_functions++;
+
+ /* address of data table: one entry per linescroll_interval lines (the threaded */
+ /* strips start on a multiple of 16 lines, so on a multiple of the interval) */
+ address = current_tilemap.linescroll_table_address + active_functions*4*(cliprect->min_y / (current_tilemap.linescroll_interval ? current_tilemap.linescroll_interval : 1));
+
+ /* get the first scroll values */
+ for ( i = 0; i < active_functions; i++ )
+ {
+ if ( i == vertical_linescroll_index )
+ {
+ VDP2_READ_VERTICAL_LINESCROLL( prev_scroll_values[i], (address / 4) + i );
+ prev_scroll_values[i] -= (cur_line * current_tilemap.incy);
+ }
+ else
+ {
+ prev_scroll_values[i] = vdp2_vram[ (address / 4) + i ];
+ }
+ }
+
+ while( cur_line <= cliprect->max_y )
+ {
+ lines = 0;
+ do
+ {
+ /* update address */
+ address += active_functions*4;
+
+ /* update lines count */
+ lines += current_tilemap.linescroll_interval;
+
+ /* get scroll values */
+ for ( i = 0; i < active_functions; i++ )
+ {
+ if ( i == vertical_linescroll_index )
+ {
+ VDP2_READ_VERTICAL_LINESCROLL( scroll_values[i], (address/4) + i );
+ scroll_values[i] -= (cur_line + lines) * current_tilemap.incy;
+ }
+ else
+ {
+ scroll_values[i] = vdp2_vram[ (address / 4) + i ];
+ }
+ }
+
+ /* compare scroll values */
+ scroll_values_equal = 1;
+ for ( i = 0; i < active_functions; i++ )
+ {
+ scroll_values_equal &= (scroll_values[i] == prev_scroll_values[i]);
+ }
+ } while( scroll_values_equal && ((cur_line + lines) <= cliprect->max_y) );
+
+ /* determined how many lines can be drawn */
+ /* prepare clipping rectangle */
+ mycliprect.min_y = cur_line; mycliprect.max_y = cur_line + lines - 1;
+
+ /* prepare scroll values */
+ i = 0;
+ /* linescroll */
+ if ( linescroll_enable )
+ {
+ prev_scroll_values[i] = (INT32)((prev_scroll_values[i] & 0x07ffff00) << 5) >> 5;
+ current_tilemap.scrollx = main_scrollx + (prev_scroll_values[i] >> 16);
+ i++;
+ }
+ /* vertical line scroll */
+ if ( vertical_linescroll_enable )
+ {
+ current_tilemap.scrolly = main_scrolly + (prev_scroll_values[i] >> 16);
+ i++;
+ }
+
+ /* linezooom */
+ if ( linezoom_enable )
+ {
+ prev_scroll_values[i] = (INT32)((prev_scroll_values[i] & 0x0007ff00) << 13) >> 13;
+ current_tilemap.incx = prev_scroll_values[i];
+ i++;
+ }
+
+/* log_masked(LOG_VDP2, "Linescroll: y < %d, %d >, scrollx = %d, scrolly = %d, incx = %f\n", mycliprect.min_y, mycliprect.max_y, current_tilemap.scrollx, current_tilemap.scrolly, (float)current_tilemap.incx/65536.0); */
+ /* render current tilemap portion */
+ if (current_tilemap.bitmap_enable) /* this layer is a bitmap */
+ {
+ vdp2_draw_basic_bitmap(bitmap, &mycliprect);
+ }
+ else
+ {
+ /*vdp2_apply_window_on_layer(mycliprect); */
+ vdp2_draw_basic_tilemap(bitmap, &mycliprect);
+ }
+
+ /* update parameters for next iteration */
+ memcpy( prev_scroll_values, scroll_values, sizeof(scroll_values));
+ cur_line += lines;
+ }
+}
+
+static void vdp2_draw_line(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int x,y;
+ UINT8* gfxdata = vdp2l.gfx_decode;
+ UINT32 base_offs,base_mask;
+ UINT32 pix;
+ UINT8 interlace;
+
+ interlace = (get_lsmd() == 3) + 1;
+
+ {
+ base_mask = get_vramsz() ? 0x7ffff : 0x3ffff;
+
+ for(y=cliprect->min_y;y<=cliprect->max_y;y++)
+ {
+ base_offs = (VDP2_LCTA & base_mask) << 1;
+
+ if(VDP2_LCCLMD)
+ base_offs += (y / interlace) << 1;
+
+ for(x=cliprect->min_x;x<=cliprect->max_x;x++)
+ {
+ UINT16 pen;
+
+ pen = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1];
+ pix = BMP32(bitmap, y)[x];
+
+ BMP32(bitmap, y)[x] = add_blend_r32(PEN(pen & 0x7ff),pix);
+ }
+ }
+ }
+}
+
+static void vdp2_draw_mosaic(struct mame_bitmap *bitmap, const struct rectangle *cliprect, UINT8 is_roz)
+{
+ int y;
+ int x;
+ int yi;
+ int xi;
+ UINT8 h_size = VDP2_MZSZH+1;
+ UINT8 v_size = VDP2_MZSZV+1;
+
+ if(is_roz)
+ v_size = 1;
+
+ if(h_size == 1 && v_size == 1)
+ return; /* don't bother */
+
+ if(get_lsmd() == 3)
+ v_size <<= 1;
+
+ for(y=cliprect->min_y;y<=cliprect->max_y;y+=v_size)
+ {
+ for(x=cliprect->min_x;x<=cliprect->max_x;x+=h_size)
+ {
+ UINT32 pix = BMP32(bitmap, y)[x];
+
+ for(yi=0;yi>= 2;
+
+ base_offset = 0;
+ base_multiplier = 1;
+ /* offset for both enabled */
+ if(VDP2_N0VCSC && VDP2_N1VCSC)
+ {
+ /* NBG1 */
+ if(current_tilemap.layer_name & 1)
+ base_offset = 1;
+
+ base_multiplier = 2;
+ }
+
+ base_scrollx = current_tilemap.scrollx;
+ base_scrolly = current_tilemap.scrolly;
+ /*base_incx = current_tilemap.incx; */
+ /*base_incy = current_tilemap.incy; */
+
+ while(cur_char <= cliprect->max_x)
+ {
+ UINT32 cur_address;
+ INT16 char_scroll;
+
+ mycliprect.min_x = cur_char;
+ mycliprect.max_x = cur_char + 8 - 1;
+
+ cur_address = vcsc_address;
+ cur_address += ((cur_char >> 3) * base_multiplier) + base_offset;
+
+ char_scroll = vdp2_vram[ cur_address ] >> 16;
+ char_scroll &= 0x07ff;
+ if ( char_scroll & 0x0400 ) char_scroll |= 0xf800;
+ current_tilemap.scrollx = base_scrollx;
+ current_tilemap.scrolly = base_scrolly + (char_scroll);
+ /*current_tilemap.incx = base_incx; */
+ /*current_tilemap.incy = base_incy; */
+
+ vdp2_check_tilemap_with_linescroll(bitmap, &mycliprect);
+
+ /* TODO: + 16 for tilemap and char size = 16? */
+ cur_char += 8;
+
+ }
+
+ return;
+ }
+ else if ( current_tilemap.linescroll_enable ||
+ current_tilemap.vertical_linescroll_enable ||
+ current_tilemap.linezoom_enable)
+ {
+ vdp2_check_tilemap_with_linescroll(bitmap, cliprect);
+
+ return;
+ }
+
+ if (current_tilemap.bitmap_enable) /* this layer is a bitmap */
+ {
+ vdp2_draw_basic_bitmap(bitmap, &mycliprect);
+ }
+ else
+ {
+ /*vdp2_apply_window_on_layer(mycliprect); */
+ vdp2_draw_basic_tilemap(bitmap, &mycliprect);
+ }
+
+ /* post-processing functions */
+ /* (TODO: needs layer bitmaps to be individual planes to work correctly) */
+ if(current_tilemap.line_screen_enabled && TEST_FUNCTIONS)
+ vdp2_draw_line(bitmap,cliprect);
+
+ if(current_tilemap.mosaic_screen_enabled && TEST_FUNCTIONS)
+ vdp2_draw_mosaic(bitmap,cliprect,current_tilemap.layer_name & 0x80);
+
+
+ {
+ if(current_tilemap.colour_depth == 2 && !current_tilemap.bitmap_enable)
+ popmessage("2048 color mode used on a non-bitmap plane");
+
+/* if(VDP2_SCXDN0 || VDP2_SCXDN1 || VDP2_SCYDN0 || VDP2_SCYDN1) */
+/* popmessage("Fractional part scrolling write"); */
+
+ /* capgen2 - Choh Makaimura (obviously) */
+ if(VDP2_MZCTL & 0x1f && POPMESSAGE_DEBUG)
+ popmessage("Mosaic control enabled = %04x\n",VDP2_MZCTL);
+
+ /* revil/biohaz bit 1 */
+ /* airsadve 0x3e */
+ /* bakhunt */
+ if(VDP2_LNCLEN & ~2 && POPMESSAGE_DEBUG)
+ popmessage("Line Colour screen enabled %04x %08x",VDP2_LNCLEN,VDP2_LCTAU<<16|VDP2_LCTAL);
+
+ /* revil/biohaz 0x400 = extended color calculation enabled */
+ /* aww 0x200 = color calculation ratio mode */
+ /* whizz/whizzj = 0x8100 */
+ /* darksavu = 0x9051 on save select screen (the one with a Saturn in the background) */
+ if(VDP2_CCCR & 0x6000)
+ popmessage("Gradation enabled %04x",VDP2_CCCR);
+
+ /* Advanced VG, Shining Force III */
+ if(VDP2_SFCCMD && POPMESSAGE_DEBUG)
+ popmessage("Special Color Calculation enable %04x",VDP2_SFCCMD);
+
+ /* cleopatr Transparent Shadow */
+ /* prettyx Back & Transparent Shadow*/
+ /*if(VDP2_SDCTL & 0x0120) */
+ /* popmessage("%s shadow select bit enabled",VDP2_SDCTL & 0x100 ? "Transparent" : "Back"); */
+
+ /* lengris3 bit 3 normal, bit 1 during battle field */
+ /* mslug bit 0 during gameplay */
+ /* bugu Sega Away Logo onward 0x470 */
+ /* cncu 0x0004 0xc000, azelpanztai 0x0004 0x0000 (FMV) */
+ if(VDP2_SFSEL & ~0x47f)
+ popmessage("Special Function Code Select enable %04x %04x",VDP2_SFSEL,VDP2_SFCODE);
+
+ /* albodys 0x0001 */
+ /* asuka120 0x0101 */
+ /* slamnjamu 0x0003 */
+ if(VDP2_ZMCTL & 0x0200)
+ popmessage("Reduction enable %04x",VDP2_ZMCTL);
+
+ /* burningru based FMVs, jltsuk backgrounds */
+ if(VDP2_SCRCTL & 0x0101 && POPMESSAGE_DEBUG)
+ popmessage("Vertical cell scroll enable %04x",VDP2_SCRCTL);
+
+ /* magdrop3 0x200 -> color calculation window */
+ /* ideyusmj 0x0303 */
+ /* decathlt 0x088 */
+ /* sexyparo 0x2300 */
+/* if(VDP2_WCTLD & 0x2000) */
+/* popmessage("Special window enabled %04x",VDP2_WCTLD); */
+
+ /* shinfrc3u, aburner2 (doesn't make a proper use tho?) */
+ /* layersec */
+ /*if(VDP2_W0LWE || VDP2_W1LWE) */
+ /* popmessage("Line Window %s %08x enabled",VDP2_W0LWE ? "0" : "1",VDP2_W0LWTA); */
+
+ /* draculax bits 2-4 */
+ /* acstrike bit 5 */
+ /* capgen2 - Choh Makaimura 0x0055 */
+ /* srallycu 0x0155 */
+ /* findlove 0x4400 */
+ /* dbzsbuto 0x3800 - 0x2c00 */
+ /* leynos2 0x0200*/
+ /* bugu 0x8800 */
+ /* wonder3 0x0018 */
+ if(VDP2_SFPRMD & ~0xff7f)
+ popmessage("Special Priority Mode enabled %04x",VDP2_SFPRMD);
+ }
+}
+
+
+#define ROZ_PREFETCH 8
+
+/*
+ The rotation windows of line y for x in [min_x, max_x]: 1 where the
+ pixel goes through (the rotation windows of R0W0E/R0W1E, and the
+ rotation parameter windows of RPW0E/RPW1E in mode 3), with the window coordinates and
+ settings read once for the line. Returns 0 when no window is enabled
+ (all the pixels go through), without filling the mask.
+*/
+static int vdp2_roz_window_line(UINT8 *mask, int min_x, int max_x, int y, int mode3, int rot_parameter)
+{
+ int s0 = 0, e0 = 0, sy0 = 0, ey0 = 0, s1 = 0, e1 = 0, sy1 = 0, ey1 = 0, x;
+ UINT8 logic = VDP2_R0LOG, w0e = VDP2_R0W0E, w1e = VDP2_R0W1E, w0a = VDP2_R0W0A, w1a = VDP2_R0W1A;
+ UINT8 mlogic = VDP2_RPLOG, mw0e = VDP2_RPW0E, mw1e = VDP2_RPW1E, mw0a = VDP2_RPW0A, mw1a = VDP2_RPW1A;
+ int roz = (w0e || w1e), m3 = mode3 && (mw0e || mw1e);
+
+ if (!roz && !mode3)
+ return 0;
+ if (roz || m3)
+ {
+ vdp2_get_window0_coordinates(&s0, &e0, &sy0, &ey0, y);
+ vdp2_get_window1_coordinates(&s1, &e1, &sy1, &ey1, y);
+ }
+ for (x = min_x; x <= max_x; x++)
+ {
+ int pass = 1;
+ if (roz)
+ {
+ int w0 = get_roz_window_pixel(s0, e0, sy0, ey0, x, y, w0e, w0a);
+ int w1 = get_roz_window_pixel(s1, e1, sy1, ey1, x, y, w1e, w1a);
+ pass = logic & 1 ? (w0 | w1) : (w0 & w1);
+ }
+ if (pass && mode3)
+ {
+ if (m3)
+ {
+ int w0 = get_roz_window_pixel(s0, e0, sy0, ey0, x, y, mw0e, mw0a);
+ int w1 = get_roz_window_pixel(s1, e1, sy1, ey1, x, y, mw1e, mw1a);
+ pass = (mlogic & 1 ? (w0 | w1) : (w0 & w1)) ^ rot_parameter;
+ }
+ else
+ pass = rot_parameter ^ 1;
+ }
+ mask[x] = pass;
+ }
+ return 1;
+}
+
+static void vdp2_copy_roz_bitmap(struct mame_bitmap *bitmap,
+ struct mame_bitmap *roz_bitmap,
+ const struct rectangle *cliprect,
+ int iRP,
+ int planesizex,
+ int planesizey,
+ int planerenderedsizex,
+ int planerenderedsizey)
+{
+ INT32 xsp, ysp, xp, yp, dx, dy, x, y, xs, ys, dxs, dys;
+ INT32 vcnt, hcnt;
+ INT32 kx, ky;
+ INT8 use_coeff_table, coeff_table_mode, coeff_table_size, coeff_table_shift;
+ INT8 screen_over_process;
+ UINT8 vcnt_shift, hcnt_shift;
+ UINT8 coeff_msb;
+ UINT32 *coeff_table_base, coeff_table_offset;
+ INT32 coeff_table_val;
+ UINT32 address;
+ UINT32 *line;
+ rgb_t pix;
+ /*UINT32 coeff_line_color_screen_data; */
+ INT32 clipxmask = 0, clipymask = 0;
+ int co_r = 0, co_g = 0, co_b = 0;
+ UINT8 winmask[1024];
+ int use_winmask;
+ /* the plane's pixels without the line table (one dependent load less per pixel) */
+ const UINT32 *rozbase = (const UINT32 *)roz_bitmap->base;
+ const int rozpitch = roz_bitmap->rowpixels;
+
+
+ if (current_tilemap.fade_control & 1)
+ vdp2_color_offset_values(current_tilemap.fade_control & 2, &co_r, &co_g, &co_b);
+ vcnt_shift = get_lsmd() == 3;
+ hcnt_shift = BIT(get_hreso(), 1);
+
+ planesizex--;
+ planesizey--;
+ planerenderedsizex--;
+ planerenderedsizey--;
+
+ kx = RP.kx;
+ ky = RP.ky;
+
+ use_coeff_table = coeff_table_mode = coeff_table_size = coeff_table_shift = 0;
+ coeff_table_offset = 0;
+ coeff_table_val = 0;
+ coeff_table_base = NULL;
+
+ log_masked(LOG_ROZ, "Rendering RBG with parameter %s\n", iRP == 1 ? "A" : "B");
+ log_masked(LOG_ROZ, "RPMD (parameter mode) = %x\n", VDP2_RPMD);
+ log_masked(LOG_ROZ, "RPRCTL (parameter read control) = %04x\n", VDP2_RPRCTL);
+ log_masked(LOG_ROZ, "KTCTL (coefficient table control) = %04x\n", VDP2_KTCTL);
+ log_masked(LOG_ROZ, "KTAOF (coefficient table address offset) = %04x\n", VDP2_KTAOF);
+ log_masked(LOG_ROZ, "RAOVR (screen-over process) = %x\n", VDP2_RAOVR);
+ if ( iRP == 1 )
+ {
+ use_coeff_table = VDP2_RAKTE;
+ if ( use_coeff_table == 1 )
+ {
+ coeff_table_mode = VDP2_RAKMD;
+ coeff_table_size = VDP2_RAKDBS;
+ coeff_table_offset = VDP2_RAKTAOS;
+ }
+ screen_over_process = VDP2_RAOVR;
+ }
+ else
+ {
+ use_coeff_table = VDP2_RBKTE;
+ if ( use_coeff_table == 1 )
+ {
+ coeff_table_mode = VDP2_RBKMD;
+ coeff_table_size = VDP2_RBKDBS;
+ coeff_table_offset = VDP2_RBKTAOS;
+ }
+ screen_over_process = VDP2_RBOVR;
+ }
+ if ( use_coeff_table )
+ {
+ if ( VDP2_CRKTE == 0 )
+ {
+ coeff_table_base = vdp2_vram;
+ }
+ else
+ {
+ coeff_table_base = vdp2_cram;
+ }
+ if ( coeff_table_size == 0 )
+ {
+ coeff_table_offset = (coeff_table_offset & 0x0003) * 0x40000;
+ coeff_table_shift = 2;
+ }
+ else
+ {
+ coeff_table_offset = (coeff_table_offset & 0x0007) * 0x20000;
+ coeff_table_shift = 1;
+ }
+ }
+
+ if ( current_tilemap.colour_calculation_enabled == 1 )
+ {
+ if ( VDP2_CCMD )
+ {
+ current_tilemap.transparency |= STV_TRANSPARENCY_ADD_BLEND;
+ }
+ else
+ {
+ current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA;
+ }
+ }
+
+ /* clipping */
+ switch( screen_over_process )
+ {
+ case 0:
+ /* repeated */
+ clipxmask = clipymask = 0;
+ break;
+ case 1:
+ /* screen over pattern */
+ /* TODO: not supported, cfr. VDP2_OVPNRA / VDP2_OVPNRB */
+ /* D-Xhird uses this on practice stage */
+ clipxmask = ~planesizex;
+ clipymask = ~planesizey;
+ break;
+ case 2:
+ /* outside display area, scroll screen is transparent */
+ clipxmask = ~planesizex;
+ clipymask = ~planesizey;
+ break;
+ case 3:
+ /* display area is 512x512, outside is transparent */
+ clipxmask = ~511;
+ clipymask = ~511;
+ break;
+ }
+
+ /*dx = (RP.A * RP.dx) + (RP.B * RP.dy); */
+ /*dy = (RP.D * RP.dx) + (RP.E * RP.dy); */
+ dx = mul_fixed32( RP.A, RP.dx ) + mul_fixed32( RP.B, RP.dy );
+ dy = mul_fixed32( RP.D, RP.dx ) + mul_fixed32( RP.E, RP.dy );
+
+ /*xp = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx; */
+ /*yp = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my; */
+ xp = mul_fixed32( RP.A, RP.px - RP.cx ) + mul_fixed32( RP.B, RP.py - RP.cy ) + mul_fixed32( RP.C, RP.pz - RP.cz ) + RP.cx + RP.mx;
+ yp = mul_fixed32( RP.D, RP.px - RP.cx ) + mul_fixed32( RP.E, RP.py - RP.cy ) + mul_fixed32( RP.F, RP.pz - RP.cz ) + RP.cy + RP.my;
+
+ for (vcnt = cliprect->min_y; vcnt <= cliprect->max_y; vcnt++ )
+ {
+ /*xsp = RP.A * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) +
+ RP.B * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) +
+ RP.C * ( RP.zst - RP.pz);
+ ysp = RP.D * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) +
+ RP.E * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) +
+ RP.F * ( RP.zst - RP.pz );*/
+ xsp = mul_fixed32( RP.A, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) +
+ mul_fixed32( RP.B, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) +
+ mul_fixed32( RP.C, RP.zst - RP.pz );
+ ysp = mul_fixed32( RP.D, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) +
+ mul_fixed32( RP.E, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) +
+ mul_fixed32( RP.F, RP.zst - RP.pz );
+ /*xp = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx; */
+ /*yp = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my; */
+ /*dx = (RP.A * RP.dx) + (RP.B * RP.dy); */
+ /*dy = (RP.D * RP.dx) + (RP.E * RP.dy); */
+
+ line = BMP32(bitmap, vcnt);
+
+ /* TODO: nuke this spaghetti code */
+ if ( !use_coeff_table || RP.dkax == 0 )
+ {
+ if ( use_coeff_table )
+ {
+ switch( coeff_table_size )
+ {
+ case 0:
+ address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 4;
+ coeff_table_val = coeff_table_base[ address / 4 ];
+ /*coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24; */
+ coeff_msb = (coeff_table_val & 0x80000000) > 0;
+ if ( coeff_table_val & 0x00800000 )
+ {
+ coeff_table_val |= 0xff000000;
+ }
+ else
+ {
+ coeff_table_val &= 0x007fffff;
+ }
+ break;
+ case 1:
+ address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 2;
+ coeff_table_val = coeff_table_base[ address / 4 ];
+ if ( (address & 2) == 0 )
+ {
+ coeff_table_val >>= 16;
+ }
+ coeff_table_val &= 0xffff;
+ /*coeff_line_color_screen_data = 0; */
+ coeff_msb = (coeff_table_val & 0x8000) > 0;
+ if ( coeff_table_val & 0x4000 )
+ {
+ coeff_table_val |= 0xffff8000;
+ }
+ else
+ {
+ coeff_table_val &= 0x3fff;
+ }
+ coeff_table_val <<= 6; /* to form 16.16 fixed point val */
+ break;
+ default:
+ coeff_msb = 1;
+ break;
+ }
+ if ( coeff_msb ) continue;
+
+ switch( coeff_table_mode )
+ {
+ case 0:
+ kx = ky = coeff_table_val;
+ break;
+ case 1:
+ kx = coeff_table_val;
+ break;
+ case 2:
+ ky = coeff_table_val;
+ break;
+ case 3:
+ xp = coeff_table_val;
+ break;
+ }
+ }
+
+ /*x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp; */
+ /*y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp; */
+ xs = mul_fixed32( kx, xsp ) + xp;
+ ys = mul_fixed32( ky, ysp ) + yp;
+ dxs = mul_fixed32( kx, mul_fixed32( dx, 1 << (16-hcnt_shift)));
+ dys = mul_fixed32( ky, mul_fixed32( dy, 1 << (16-hcnt_shift)));
+
+ use_winmask = vdp2_roz_window_line(winmask, cliprect->min_x, cliprect->max_x, vcnt, current_tilemap.roz_mode3 == 1, iRP - 1);
+ for (hcnt = cliprect->min_x; hcnt <= cliprect->max_x; xs+=dxs, ys+=dys, hcnt++ )
+ {
+#ifdef __GNUC__
+ /* the plane is up to 64MB: fetch the pixel needed a few steps ahead */
+ __builtin_prefetch(&rozbase[(((ys + dys * ROZ_PREFETCH) >> 16) & planerenderedsizey) * rozpitch + (((xs + dxs * ROZ_PREFETCH) >> 16) & planerenderedsizex)]);
+#endif
+ x = xs >> 16;
+ y = ys >> 16;
+
+ if ( x & clipxmask || y & clipymask ) continue;
+ if ( use_winmask && !winmask[hcnt] )
+ continue;
+
+ pix = rozbase[(y & planerenderedsizey) * rozpitch + (x & planerenderedsizex)];
+ if (current_tilemap.transparency & STV_TRANSPARENCY_ALPHA)
+ {
+ if ((current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff))
+ {
+ if(current_tilemap.fade_control & 1)
+ pix = vdp2_apply_color_offset(pix, co_r, co_g, co_b);
+
+ line[hcnt] = stv_alpha_blend_r32( line[hcnt], pix, current_tilemap.alpha );
+ }
+ }
+ else if (current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND)
+ {
+ if ((current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff))
+ {
+ if(current_tilemap.fade_control & 1)
+ pix = vdp2_apply_color_offset(pix, co_r, co_g, co_b);
+
+ line[hcnt] = add_blend_r32( line[hcnt], pix );
+ }
+ }
+ else
+ {
+ if ((current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff))
+ {
+ if(current_tilemap.fade_control & 1)
+ pix = vdp2_apply_color_offset(pix, co_r, co_g, co_b);
+
+ line[hcnt] = pix;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (hcnt = cliprect->min_x; hcnt <= cliprect->max_x; hcnt++ )
+ {
+ switch( coeff_table_size )
+ {
+ case 0:
+ address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 4;
+ coeff_table_val = coeff_table_base[ address / 4 ];
+ /*coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24; */
+ coeff_msb = (coeff_table_val & 0x80000000) > 0;
+ if ( coeff_table_val & 0x00800000 )
+ {
+ coeff_table_val |= 0xff000000;
+ }
+ else
+ {
+ coeff_table_val &= 0x007fffff;
+ }
+ break;
+ case 1:
+ address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 2;
+ coeff_table_val = coeff_table_base[ address / 4 ];
+ if ( (address & 2) == 0 )
+ {
+ coeff_table_val >>= 16;
+ }
+ coeff_table_val &= 0xffff;
+ /*coeff_line_color_screen_data = 0; */
+ coeff_msb = (coeff_table_val & 0x8000) > 0;
+ if ( coeff_table_val & 0x4000 )
+ {
+ coeff_table_val |= 0xffff8000;
+ }
+ else
+ {
+ coeff_table_val &= 0x3fff;
+ }
+ coeff_table_val <<= 6; /* to form 16.16 fixed point val */
+ break;
+ default:
+ coeff_msb = 1;
+ break;
+ }
+ if ( coeff_msb ) continue;
+ switch( coeff_table_mode )
+ {
+ case 0:
+ kx = ky = coeff_table_val;
+ break;
+ case 1:
+ kx = coeff_table_val;
+ break;
+ case 2:
+ ky = coeff_table_val;
+ break;
+ case 3:
+ xp = coeff_table_val;
+ break;
+ }
+
+ /*x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp; */
+ /*y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp; */
+ x = mul_fixed32( kx, xsp + mul_fixed32( dx, (hcnt>>hcnt_shift) << 16 ) ) + xp;
+ y = mul_fixed32( ky, ysp + mul_fixed32( dy, (hcnt>>hcnt_shift) << 16 ) ) + yp;
+
+ x >>= 16;
+ y >>= 16;
+
+ if ( x & clipxmask || y & clipymask ) continue;
+
+ pix = rozbase[(y & planerenderedsizey) * rozpitch + (x & planerenderedsizex)];
+ if (current_tilemap.transparency & STV_TRANSPARENCY_ALPHA)
+ {
+ if ((current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff))
+ {
+ if(current_tilemap.fade_control & 1)
+ pix = vdp2_apply_color_offset(pix, co_r, co_g, co_b);
+
+ line[hcnt] = stv_alpha_blend_r32( line[hcnt], pix, current_tilemap.alpha );
+ }
+ }
+ else if (current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND)
+ {
+ if ((current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff))
+ {
+ if(current_tilemap.fade_control & 1)
+ pix = vdp2_apply_color_offset(pix, co_r, co_g, co_b);
+
+ line[hcnt] = add_blend_r32( line[hcnt], pix );
+ }
+ }
+ else
+ {
+ if ((current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff))
+ {
+ if(current_tilemap.fade_control & 1)
+ pix = vdp2_apply_color_offset(pix, co_r, co_g, co_b);
+
+ line[hcnt] = pix;
+ }
+ }
+ }
+ }
+ }
+}
+
+static INLINE int get_roz_window_pixel(int s_x,int e_x,int s_y,int e_y,int x, int y,UINT8 winenable, UINT8 winarea)
+{
+ int res;
+
+ res = 1;
+ if(winenable)
+ {
+ if(winarea)
+ res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x);
+ else
+ res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x) ^ 1;
+ }
+
+ return res;
+}
+
+
+static void vdp2_draw_NBG0(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ UINT32 base_mask;
+
+ base_mask = get_vramsz() ? 0x7ffff : 0x3ffff;
+
+ /*
+ Colours : 16, 256, 2048, 32768, 16770000
+ Char Size : 1x1 cells, 2x2 cells
+ Pattern Data Size : 1 word, 2 words
+ Plane Layouts : 1 x 1, 2 x 1, 2 x 2
+ Planes : 4
+ Bitmap : Possible
+ Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
+ Scale : 0.25 x - 256 x
+ Rotation : No
+ Linescroll : Yes
+ Column Scroll : Yes
+ Mosaic : Yes
+ */
+
+ current_tilemap.enabled = VDP2_N0ON | VDP2_R1ON;
+
+/* if (!current_tilemap.enabled) return; // stop right now if its disabled ... */
+
+ /*current_tilemap.trans_enabled = VDP2_N0TPON; */
+ if ( VDP2_N0CCEN )
+ {
+ current_tilemap.colour_calculation_enabled = 1;
+ current_tilemap.alpha = ((UINT16)(0x1f-VDP2_N0CCRT)*0xff)/0x1f;
+ }
+ else
+ {
+ current_tilemap.colour_calculation_enabled = 0;
+ }
+ if ( VDP2_N0TPON == 0 )
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_PEN;
+ }
+ else
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_NONE;
+ }
+ current_tilemap.colour_depth = VDP2_N0CHCN;
+ current_tilemap.tile_size = VDP2_N0CHSZ;
+ current_tilemap.bitmap_enable = VDP2_N0BMEN;
+ current_tilemap.bitmap_size = VDP2_N0BMSZ;
+ current_tilemap.bitmap_palette_number = VDP2_N0BMP;
+ current_tilemap.bitmap_map = VDP2_N0MP_;
+ current_tilemap.map_offset[0] = VDP2_N0MPA | (VDP2_N0MP_ << 6);
+ current_tilemap.map_offset[1] = VDP2_N0MPB | (VDP2_N0MP_ << 6);
+ current_tilemap.map_offset[2] = VDP2_N0MPC | (VDP2_N0MP_ << 6);
+ current_tilemap.map_offset[3] = VDP2_N0MPD | (VDP2_N0MP_ << 6);
+ current_tilemap.map_count = 4;
+
+ current_tilemap.pattern_data_size = VDP2_N0PNB;
+ current_tilemap.character_number_supplement = VDP2_N0CNSM;
+ current_tilemap.special_priority_register = VDP2_N0SPR;
+ current_tilemap.special_colour_control_register = VDP2_PNCN0;
+ current_tilemap.supplementary_palette_bits = VDP2_N0SPLT;
+ current_tilemap.supplementary_character_bits = VDP2_N0SPCN;
+
+ current_tilemap.scrollx = VDP2_SCXIN0;
+ current_tilemap.scrolly = VDP2_SCYIN0;
+ current_tilemap.incx = VDP2_ZMXN0;
+ current_tilemap.incy = VDP2_ZMYN0;
+
+ current_tilemap.linescroll_enable = VDP2_N0LSCX;
+ current_tilemap.linescroll_interval = ((get_lsmd() == 2) ? (2) : (1)) << (VDP2_N0LSS);
+ current_tilemap.linescroll_table_address = (((VDP2_LSTA0U << 16) | VDP2_LSTA0L) & base_mask) * 2;
+ current_tilemap.vertical_linescroll_enable = VDP2_N0LSCY;
+ current_tilemap.linezoom_enable = VDP2_N0LZMX;
+ current_tilemap.vertical_cell_scroll_enable = VDP2_N0VCSC;
+
+ current_tilemap.plane_size = (VDP2_R1ON) ? VDP2_RBPLSZ : VDP2_N0PLSZ;
+ current_tilemap.colour_ram_address_offset = VDP2_N0CAOS;
+ current_tilemap.fade_control = (VDP2_N0COEN * 1) | (VDP2_N0COSL * 2);
+ vdp2_check_fade_control_for_layer();
+ current_tilemap.window_control.logic = VDP2_N0LOG;
+ current_tilemap.window_control.enabled[0] = VDP2_N0W0E;
+ current_tilemap.window_control.enabled[1] = VDP2_N0W1E;
+/* current_tilemap.window_control.? = VDP2_N0SWE; */
+ current_tilemap.window_control.area[0] = VDP2_N0W0A;
+ current_tilemap.window_control.area[1] = VDP2_N0W1A;
+/* current_tilemap.window_control.? = VDP2_N0SWA; */
+
+ current_tilemap.line_screen_enabled = VDP2_N0LCEN;
+ current_tilemap.mosaic_screen_enabled = VDP2_N0MZE;
+
+ current_tilemap.layer_name=(VDP2_R1ON) ? 0x81 : 0;
+
+ if ( current_tilemap.enabled && (!(VDP2_R1ON))) /* TODO: check cycle pattern for RBG1 */
+ {
+ current_tilemap.enabled = vdp2_check_vram_cycle_pattern_registers( VDP2_CP_NBG0_PNMDR, VDP2_CP_NBG0_CPDR, current_tilemap.bitmap_enable );
+ }
+
+ if(VDP2_R1ON)
+ vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
+ else
+ vdp2_check_tilemap(bitmap, cliprect);
+}
+
+static void vdp2_draw_NBG1(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ UINT32 base_mask;
+
+ base_mask = get_vramsz() ? 0x7ffff : 0x3ffff;
+
+ /*
+ Colours : 16, 256, 2048, 32768
+ Char Size : 1x1 cells, 2x2 cells
+ Pattern Data Size : 1 word, 2 words
+ Plane Layouts : 1 x 1, 2 x 1, 2 x 2
+ Planes : 4
+ Bitmap : Possible
+ Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
+ Scale : 0.25 x - 256 x
+ Rotation : No
+ Linescroll : Yes
+ Column Scroll : Yes
+ Mosaic : Yes
+ */
+ current_tilemap.enabled = VDP2_N1ON;
+
+/* if (!current_tilemap.enabled) return; // stop right now if its disabled ... */
+
+ /*current_tilemap.trans_enabled = VDP2_N1TPON; */
+ if ( VDP2_N1CCEN )
+ {
+ current_tilemap.colour_calculation_enabled = 1;
+ current_tilemap.alpha = ((UINT16)(0x1f-VDP2_N1CCRT)*0xff)/0x1f;
+ }
+ else
+ {
+ current_tilemap.colour_calculation_enabled = 0;
+ }
+ if ( VDP2_N1TPON == 0 )
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_PEN;
+ }
+ else
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_NONE;
+ }
+ current_tilemap.colour_depth = VDP2_N1CHCN;
+ current_tilemap.tile_size = VDP2_N1CHSZ;
+ current_tilemap.bitmap_enable = VDP2_N1BMEN;
+ current_tilemap.bitmap_size = VDP2_N1BMSZ;
+ current_tilemap.bitmap_palette_number = VDP2_N1BMP;
+ current_tilemap.bitmap_map = VDP2_N1MP_;
+ current_tilemap.map_offset[0] = VDP2_N1MPA | (VDP2_N1MP_ << 6);
+ current_tilemap.map_offset[1] = VDP2_N1MPB | (VDP2_N1MP_ << 6);
+ current_tilemap.map_offset[2] = VDP2_N1MPC | (VDP2_N1MP_ << 6);
+ current_tilemap.map_offset[3] = VDP2_N1MPD | (VDP2_N1MP_ << 6);
+ current_tilemap.map_count = 4;
+
+ current_tilemap.pattern_data_size = VDP2_N1PNB;
+ current_tilemap.character_number_supplement = VDP2_N1CNSM;
+ current_tilemap.special_priority_register = VDP2_N1SPR;
+ current_tilemap.special_colour_control_register = VDP2_PNCN1;
+ current_tilemap.supplementary_palette_bits = VDP2_N1SPLT;
+ current_tilemap.supplementary_character_bits = VDP2_N1SPCN;
+
+ current_tilemap.scrollx = VDP2_SCXIN1;
+ current_tilemap.scrolly = VDP2_SCYIN1;
+ current_tilemap.incx = VDP2_ZMXN1;
+ current_tilemap.incy = VDP2_ZMYN1;
+
+ current_tilemap.linescroll_enable = VDP2_N1LSCX;
+ current_tilemap.linescroll_interval = ((get_lsmd() == 2) ? (2) : (1)) << (VDP2_N1LSS);
+ current_tilemap.linescroll_table_address = (((VDP2_LSTA1U << 16) | VDP2_LSTA1L) & base_mask) * 2;
+ current_tilemap.vertical_linescroll_enable = VDP2_N1LSCY;
+ current_tilemap.linezoom_enable = VDP2_N1LZMX;
+ current_tilemap.vertical_cell_scroll_enable = VDP2_N1VCSC;
+
+ current_tilemap.plane_size = VDP2_N1PLSZ;
+ current_tilemap.colour_ram_address_offset = VDP2_N1CAOS;
+ current_tilemap.fade_control = (VDP2_N1COEN * 1) | (VDP2_N1COSL * 2);
+ vdp2_check_fade_control_for_layer();
+ current_tilemap.window_control.logic = VDP2_N1LOG;
+ current_tilemap.window_control.enabled[0] = VDP2_N1W0E;
+ current_tilemap.window_control.enabled[1] = VDP2_N1W1E;
+/* current_tilemap.window_control.? = VDP2_N1SWE; */
+ current_tilemap.window_control.area[0] = VDP2_N1W0A;
+ current_tilemap.window_control.area[1] = VDP2_N1W1A;
+/* current_tilemap.window_control.? = VDP2_N1SWA; */
+
+ current_tilemap.line_screen_enabled = VDP2_N1LCEN;
+ current_tilemap.mosaic_screen_enabled = VDP2_N1MZE;
+
+ current_tilemap.layer_name=1;
+
+ if ( current_tilemap.enabled )
+ {
+ current_tilemap.enabled = vdp2_check_vram_cycle_pattern_registers( VDP2_CP_NBG1_PNMDR, VDP2_CP_NBG1_CPDR, current_tilemap.bitmap_enable );
+ }
+
+ vdp2_check_tilemap(bitmap, cliprect);
+}
+
+static void vdp2_draw_NBG2(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ /*
+ NBG2 is the first of the 2 more basic tilemaps, it has exactly the same capabilities as NBG3
+
+ Colours : 16, 256
+ Char Size : 1x1 cells, 2x2 cells
+ Pattern Data Size : 1 word, 2 words
+ Plane Layouts : 1 x 1, 2 x 1, 2 x 2
+ Planes : 4
+ Bitmap : No
+ Bitmap Sizes : N/A
+ Scale : No
+ Rotation : No
+ Linescroll : No
+ Column Scroll : No
+ Mosaic : Yes
+ */
+
+ current_tilemap.enabled = VDP2_N2ON;
+
+ /* these modes for N0 disable this layer */
+ if (VDP2_N0CHCN == 0x03) current_tilemap.enabled = 0;
+ if (VDP2_N0CHCN == 0x04) current_tilemap.enabled = 0;
+
+/* if (!current_tilemap.enabled) return; // stop right now if its disabled ... */
+
+ /*current_tilemap.trans_enabled = VDP2_N2TPON; */
+ if ( VDP2_N2CCEN )
+ {
+ current_tilemap.colour_calculation_enabled = 1;
+ current_tilemap.alpha = ((UINT16)(0x1f-VDP2_N2CCRT)*0xff)/0x1f;
+ }
+ else
+ {
+ current_tilemap.colour_calculation_enabled = 0;
+ }
+ if ( VDP2_N2TPON == 0 )
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_PEN;
+ }
+ else
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_NONE;
+ }
+ current_tilemap.colour_depth = VDP2_N2CHCN;
+ current_tilemap.tile_size = VDP2_N2CHSZ;
+ /* this layer can't be a bitmap,so ignore these registers*/
+ current_tilemap.bitmap_enable = 0;
+ current_tilemap.bitmap_size = 0;
+ current_tilemap.bitmap_palette_number = 0;
+ current_tilemap.bitmap_map = 0;
+ current_tilemap.map_offset[0] = VDP2_N2MPA | (VDP2_N2MP_ << 6);
+ current_tilemap.map_offset[1] = VDP2_N2MPB | (VDP2_N2MP_ << 6);
+ current_tilemap.map_offset[2] = VDP2_N2MPC | (VDP2_N2MP_ << 6);
+ current_tilemap.map_offset[3] = VDP2_N2MPD | (VDP2_N2MP_ << 6);
+ current_tilemap.map_count = 4;
+
+ current_tilemap.pattern_data_size = VDP2_N2PNB;
+ current_tilemap.character_number_supplement = VDP2_N2CNSM;
+ current_tilemap.special_priority_register = VDP2_N2SPR;
+ current_tilemap.special_colour_control_register = VDP2_PNCN2;
+ current_tilemap.supplementary_palette_bits = VDP2_N2SPLT;
+ current_tilemap.supplementary_character_bits = VDP2_N2SPCN;
+
+ current_tilemap.scrollx = VDP2_SCXN2;
+ current_tilemap.scrolly = VDP2_SCYN2;
+ /*This layer can't be scaled*/
+ current_tilemap.incx = 0x10000;
+ current_tilemap.incy = 0x10000;
+
+ current_tilemap.linescroll_enable = 0;
+ current_tilemap.linescroll_interval = 0;
+ current_tilemap.linescroll_table_address = 0;
+ current_tilemap.vertical_linescroll_enable = 0;
+ current_tilemap.linezoom_enable = 0;
+ current_tilemap.vertical_cell_scroll_enable = 0;
+
+ current_tilemap.colour_ram_address_offset = VDP2_N2CAOS;
+ current_tilemap.fade_control = (VDP2_N2COEN * 1) | (VDP2_N2COSL * 2);
+ vdp2_check_fade_control_for_layer();
+ current_tilemap.window_control.logic = VDP2_N2LOG;
+ current_tilemap.window_control.enabled[0] = VDP2_N2W0E;
+ current_tilemap.window_control.enabled[1] = VDP2_N2W1E;
+/* current_tilemap.window_control.? = VDP2_N2SWE; */
+ current_tilemap.window_control.area[0] = VDP2_N2W0A;
+ current_tilemap.window_control.area[1] = VDP2_N2W1A;
+/* current_tilemap.window_control.? = VDP2_N2SWA; */
+
+ current_tilemap.line_screen_enabled = VDP2_N2LCEN;
+ current_tilemap.mosaic_screen_enabled = VDP2_N2MZE;
+
+ current_tilemap.layer_name=2;
+
+ current_tilemap.plane_size = VDP2_N2PLSZ;
+
+ if ( current_tilemap.enabled )
+ {
+ current_tilemap.enabled = vdp2_check_vram_cycle_pattern_registers( VDP2_CP_NBG2_PNMDR, VDP2_CP_NBG2_CPDR, current_tilemap.bitmap_enable );
+ }
+
+ vdp2_check_tilemap(bitmap, cliprect);
+}
+
+static void vdp2_draw_NBG3(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ /*
+ NBG3 is the second of the 2 more basic tilemaps, it has exactly the same capabilities as NBG2
+
+ Colours : 16, 256
+ Char Size : 1x1 cells, 2x2 cells
+ Pattern Data Size : 1 word, 2 words
+ Plane Layouts : 1 x 1, 2 x 1, 2 x 2
+ Planes : 4
+ Bitmap : No
+ Bitmap Sizes : N/A
+ Scale : No
+ Rotation : No
+ Linescroll : No
+ Column Scroll : No
+ Mosaic : Yes
+ */
+
+ current_tilemap.enabled = VDP2_N3ON;
+
+/* if (!current_tilemap.enabled) return; // stop right now if its disabled ... */
+
+ /* these modes for N1 disable this layer */
+ if (VDP2_N1CHCN == 0x03) current_tilemap.enabled = 0;
+ if (VDP2_N1CHCN == 0x04) current_tilemap.enabled = 0;
+
+ /*current_tilemap.trans_enabled = VDP2_N3TPON; */
+ if ( VDP2_N3CCEN )
+ {
+ current_tilemap.colour_calculation_enabled = 1;
+ current_tilemap.alpha = ((UINT16)(0x1f-VDP2_N3CCRT)*0xff)/0x1f;
+ }
+ else
+ {
+ current_tilemap.colour_calculation_enabled = 0;
+ }
+ if ( VDP2_N3TPON == 0 )
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_PEN;
+ }
+ else
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_NONE;
+ }
+ current_tilemap.colour_depth = VDP2_N3CHCN;
+ current_tilemap.tile_size = VDP2_N3CHSZ;
+ /* this layer can't be a bitmap,so ignore these registers*/
+ current_tilemap.bitmap_enable = 0;
+ current_tilemap.bitmap_size = 0;
+ current_tilemap.bitmap_palette_number = 0;
+ current_tilemap.bitmap_map = 0;
+ current_tilemap.map_offset[0] = VDP2_N3MPA | (VDP2_N3MP_ << 6);
+ current_tilemap.map_offset[1] = VDP2_N3MPB | (VDP2_N3MP_ << 6);
+ current_tilemap.map_offset[2] = VDP2_N3MPC | (VDP2_N3MP_ << 6);
+ current_tilemap.map_offset[3] = VDP2_N3MPD | (VDP2_N3MP_ << 6);
+ current_tilemap.map_count = 4;
+
+ current_tilemap.pattern_data_size = VDP2_N3PNB;
+ current_tilemap.character_number_supplement = VDP2_N3CNSM;
+ current_tilemap.special_priority_register = VDP2_N3SPR;
+ current_tilemap.special_colour_control_register = VDP2_N3SCC;
+ current_tilemap.supplementary_palette_bits = VDP2_N3SPLT;
+ current_tilemap.supplementary_character_bits = VDP2_N3SPCN;
+
+ current_tilemap.scrollx = VDP2_SCXN3;
+ current_tilemap.scrolly = VDP2_SCYN3;
+ /*This layer can't be scaled*/
+ current_tilemap.incx = 0x10000;
+ current_tilemap.incy = 0x10000;
+
+ current_tilemap.linescroll_enable = 0;
+ current_tilemap.linescroll_interval = 0;
+ current_tilemap.linescroll_table_address = 0;
+ current_tilemap.vertical_linescroll_enable = 0;
+ current_tilemap.linezoom_enable = 0;
+ current_tilemap.vertical_cell_scroll_enable = 0;
+
+ current_tilemap.colour_ram_address_offset = VDP2_N3CAOS;
+ current_tilemap.fade_control = (VDP2_N3COEN * 1) | (VDP2_N3COSL * 2);
+ vdp2_check_fade_control_for_layer();
+ current_tilemap.window_control.logic = VDP2_N3LOG;
+ current_tilemap.window_control.enabled[0] = VDP2_N3W0E;
+ current_tilemap.window_control.enabled[1] = VDP2_N3W1E;
+/* current_tilemap.window_control.? = VDP2_N3SWE; */
+ current_tilemap.window_control.area[0] = VDP2_N3W0A;
+ current_tilemap.window_control.area[1] = VDP2_N3W1A;
+/* current_tilemap.window_control.? = VDP2_N3SWA; */
+
+ current_tilemap.line_screen_enabled = VDP2_N3LCEN;
+ current_tilemap.mosaic_screen_enabled = VDP2_N3MZE;
+
+ current_tilemap.layer_name=3;
+
+ current_tilemap.plane_size = VDP2_N3PLSZ;
+
+ if ( current_tilemap.enabled )
+ {
+ current_tilemap.enabled = vdp2_check_vram_cycle_pattern_registers( VDP2_CP_NBG3_PNMDR, VDP2_CP_NBG3_CPDR, current_tilemap.bitmap_enable );
+ }
+
+ vdp2_check_tilemap(bitmap, cliprect);
+}
+
+
+static void vdp2_draw_rotation_screen(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int iRP)
+{
+ int planesizex = 0, planesizey = 0;
+ struct rectangle mycliprect;
+
+ if (iRP == 1)
+ {
+ current_tilemap.bitmap_map = VDP2_RAMP_;
+ current_tilemap.map_offset[0] = VDP2_RAMPA | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[1] = VDP2_RAMPB | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[2] = VDP2_RAMPC | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[3] = VDP2_RAMPD | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[4] = VDP2_RAMPE | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[5] = VDP2_RAMPF | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[6] = VDP2_RAMPG | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[7] = VDP2_RAMPH | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[8] = VDP2_RAMPI | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[9] = VDP2_RAMPJ | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[10] = VDP2_RAMPK | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[11] = VDP2_RAMPL | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[12] = VDP2_RAMPM | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[13] = VDP2_RAMPN | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[14] = VDP2_RAMPO | (VDP2_RAMP_ << 6);
+ current_tilemap.map_offset[15] = VDP2_RAMPP | (VDP2_RAMP_ << 6);
+ current_tilemap.map_count = 16;
+ }
+ else
+ {
+ current_tilemap.bitmap_map = VDP2_RBMP_;
+ current_tilemap.map_offset[0] = VDP2_RBMPA | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[1] = VDP2_RBMPB | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[2] = VDP2_RBMPC | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[3] = VDP2_RBMPD | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[4] = VDP2_RBMPE | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[5] = VDP2_RBMPF | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[6] = VDP2_RBMPG | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[7] = VDP2_RBMPH | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[8] = VDP2_RBMPI | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[9] = VDP2_RBMPJ | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[10] = VDP2_RBMPK | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[11] = VDP2_RBMPL | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[12] = VDP2_RBMPM | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[13] = VDP2_RBMPN | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[14] = VDP2_RBMPO | (VDP2_RBMP_ << 6);
+ current_tilemap.map_offset[15] = VDP2_RBMPP | (VDP2_RBMP_ << 6);
+ current_tilemap.map_count = 16;
+ }
+
+ vdp2_fill_rotation_parameter_table(iRP);
+
+ if ( iRP == 1 )
+ {
+ current_tilemap.plane_size = VDP2_RAPLSZ;
+ }
+ else
+ {
+ current_tilemap.plane_size = VDP2_RBPLSZ;
+ }
+
+ if (current_tilemap.bitmap_enable)
+ {
+ switch (current_tilemap.bitmap_size)
+ {
+ case 0: planesizex=512; planesizey=256; break;
+ case 1: planesizex=512; planesizey=512; break;
+ case 2: planesizex=1024; planesizey=256; break;
+ case 3: planesizex=1024; planesizey=512; break;
+ }
+ }
+ else
+ {
+ switch( current_tilemap.plane_size )
+ {
+ case 0:
+ planesizex = planesizey = 2048;
+ break;
+ case 1:
+ planesizex = 4096;
+ planesizey = 2048;
+ break;
+ case 2:
+ planesizex = 0;
+ planesizey = 0;
+ break;
+ case 3:
+ planesizex = planesizey = 4096;
+ break;
+ }
+ }
+
+ if ( vdp2_is_rotation_applied() == 0 )
+ {
+ current_tilemap.scrollx = current_rotation_table.mx >> 16;
+ current_tilemap.scrolly = current_rotation_table.my >> 16;
+
+ if(current_tilemap.roz_mode3 == 1)
+ {
+ /* TODO: Cotton 2 enables mode 3 without an actual RP window enabled */
+ /* Technically you could use split screen effect without rotation applied, */
+ /* which will be annoying to emulate with this video structure. */
+ /* Let's see if anything will do it ... */
+ if(VDP2_RPW0E || VDP2_RPW1E)
+ popmessage("ROZ Mode 3 window enabled without zooming");
+
+ if(iRP == 2)
+ return;
+ }
+
+ /* TODO: legacy code, to be removed */
+ current_tilemap.window_control.logic = VDP2_R0LOG;
+ current_tilemap.window_control.enabled[0] = VDP2_R0W0E;
+ current_tilemap.window_control.enabled[1] = VDP2_R0W1E;
+/* current_tilemap.window_control.? = VDP2_R0SWE; */
+ current_tilemap.window_control.area[0] = VDP2_R0W0A;
+ current_tilemap.window_control.area[1] = VDP2_R0W1A;
+/* current_tilemap.window_control.? = VDP2_R0SWA; */
+
+ mycliprect = *cliprect;
+
+ if ( current_tilemap.window_control.enabled[0] || current_tilemap.window_control.enabled[1] )
+ {
+ /*popmessage("Window control for RBG"); */
+ vdp2_apply_window_on_layer(&mycliprect);
+ current_tilemap.window_control.enabled[0] = 0;
+ current_tilemap.window_control.enabled[1] = 0;
+ }
+
+ vdp2_check_tilemap(bitmap,&mycliprect);
+ }
+ else
+ {
+ struct rectangle roz_clip_rect;
+ int planerenderedsizex, planerenderedsizey;
+ UINT8 colour_calculation_enabled, fade_control;
+
+ /* the rotation plane cache, allocated on first use (64MB each) */
+ if ( !vdp2l.roz_bitmap[iRP-1] )
+ vdp2l.roz_bitmap[iRP-1] = bitmap_alloc_depth(4096, 4096, 32);
+
+ roz_clip_rect.min_x = roz_clip_rect.min_y = 0;
+ if ( (iRP == 1 && VDP2_RAOVR == 3) ||
+ (iRP == 2 && VDP2_RBOVR == 3) )
+ {
+ roz_clip_rect.max_x = roz_clip_rect.max_y = 511;
+ planerenderedsizex = planerenderedsizey = 512;
+ }
+ else if (vdp2_are_map_registers_equal() &&
+ !current_tilemap.bitmap_enable)
+ {
+ roz_clip_rect.max_x = (planesizex / 4) - 1;
+ roz_clip_rect.max_y = (planesizey / 4) - 1;
+ planerenderedsizex = planesizex / 4;
+ planerenderedsizey = planesizey / 4;
+ }
+ else
+ {
+ roz_clip_rect.max_x = planesizex - 1;
+ roz_clip_rect.max_y = planesizey - 1;
+ planerenderedsizex = planesizex;
+ planerenderedsizey = planesizey;
+ }
+
+
+ colour_calculation_enabled = current_tilemap.colour_calculation_enabled;
+ current_tilemap.colour_calculation_enabled = 0;
+/* window_control = current_tilemap.window_control; */
+/* current_tilemap.window_control = 0; */
+ fade_control = current_tilemap.fade_control;
+ current_tilemap.fade_control = 0;
+ /* the bands only read the caches the prepass updated */
+ if (vdp2_render_mode != VDP2_RENDER_BAND)
+ {
+ const int same_layer = !(RBG0_cache_data.is_cache_dirty & iRP) &&
+ memcmp(&RBG0_cache_data.layer_data[iRP-1],¤t_tilemap,sizeof(current_tilemap)) == 0;
+ const int map_dirty = RBG0_cache_data.map_dirty_max[iRP-1] > RBG0_cache_data.map_dirty_min[iRP-1];
+
+ if ( same_layer && map_dirty && !current_tilemap.bitmap_enable &&
+ !current_tilemap.linescroll_enable && !current_tilemap.vertical_linescroll_enable &&
+ !current_tilemap.linezoom_enable &&
+ current_tilemap.incx == 0x10000 && current_tilemap.incy == 0x10000 &&
+ !(current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND) )
+ {
+ /* - diehard rewrites a few pattern names of its RBG0 map every frame */
+ vdp2_cell_redraw.active = 1;
+ vdp2_cell_redraw.min = RBG0_cache_data.map_dirty_min[iRP-1];
+ vdp2_cell_redraw.max = RBG0_cache_data.map_dirty_max[iRP-1];
+ vdp2_check_tilemap(vdp2l.roz_bitmap[iRP-1], &roz_clip_rect);
+ vdp2_cell_redraw.active = 0;
+
+ /* the redrawn cells may use more characters and colours than the cache watches */
+ if ( vdp2_layer_data.tile_offset_max > vdp2_layer_data.tile_offset_min )
+ {
+ if ( vdp2_layer_data.tile_offset_min < RBG0_cache_data.tile_offset_min[iRP-1] )
+ RBG0_cache_data.tile_offset_min[iRP-1] = vdp2_layer_data.tile_offset_min;
+ if ( vdp2_layer_data.tile_offset_max > RBG0_cache_data.tile_offset_max[iRP-1] )
+ RBG0_cache_data.tile_offset_max[iRP-1] = vdp2_layer_data.tile_offset_max;
+ }
+ if ( vdp2_layer_data.pen_max > 0x800 )
+ {
+ vdp2_layer_data.pen_min = 0;
+ vdp2_layer_data.pen_max = 0x800;
+ }
+ if ( vdp2_layer_data.pen_max > vdp2_layer_data.pen_min )
+ {
+ if ( RBG0_cache_data.pen_max[iRP-1] <= RBG0_cache_data.pen_min[iRP-1] )
+ {
+ RBG0_cache_data.pen_min[iRP-1] = vdp2_layer_data.pen_min;
+ RBG0_cache_data.pen_max[iRP-1] = vdp2_layer_data.pen_max;
+ }
+ else
+ {
+ if ( vdp2_layer_data.pen_min < RBG0_cache_data.pen_min[iRP-1] )
+ RBG0_cache_data.pen_min[iRP-1] = vdp2_layer_data.pen_min;
+ if ( vdp2_layer_data.pen_max > RBG0_cache_data.pen_max[iRP-1] )
+ RBG0_cache_data.pen_max[iRP-1] = vdp2_layer_data.pen_max;
+ }
+ }
+ RBG0_cache_data.map_dirty_min[iRP-1] = RBG0_cache_data.map_dirty_max[iRP-1] = 0;
+ }
+ else if ( !same_layer || map_dirty )
+ {
+ RBG0_cache_data.map_dirty_min[iRP-1] = RBG0_cache_data.map_dirty_max[iRP-1] = 0;
+ bitmap_fill32(vdp2l.roz_bitmap[iRP-1], &roz_clip_rect, 0);
+ vdp2_check_tilemap(vdp2l.roz_bitmap[iRP-1], &roz_clip_rect);
+ if ( current_tilemap.bitmap_enable )
+ {
+ /* a bitmap is read straight out of VRAM, so the tilemap path didn't set up the ranges to watch */
+ /* - vkyoute2 water kept stale contents */
+ static const int bits_per_dot[8] = { 4, 8, 16, 16, 32, 32, 32, 32 };
+ static const UINT32 colours[8] = { 16, 256, 0x800, 0, 0, 0, 0, 0 };
+ const UINT32 dots = ((current_tilemap.bitmap_size & 2) ? 1024 : 512) * ((current_tilemap.bitmap_size & 1) ? 512 : 256);
+ const UINT32 start = (current_tilemap.bitmap_map * 0x20000 / 4) & 0x1ffff;
+ const UINT32 end = start + dots * bits_per_dot[current_tilemap.colour_depth & 7] / 32;
+ UINT32 pal_bank;
+
+ /* watch all of VRAM if the bitmap wraps around its end */
+ vdp2_layer_data.map_offset_min = (end > 0x20000) ? 0 : start;
+ vdp2_layer_data.map_offset_max = (end > 0x20000) ? 0x20000 : end;
+ vdp2_layer_data.tile_offset_min = 0;
+ vdp2_layer_data.tile_offset_max = 0;
+
+ /* same palette selection as the draw_*_bitmap functions, fading is off while caching */
+ pal_bank = (current_tilemap.colour_depth == 2) ? 0 : (((current_tilemap.bitmap_palette_number + current_tilemap.colour_ram_address_offset) & 7) << 8);
+ vdp2_layer_data.pen_min = pal_bank;
+ vdp2_layer_data.pen_max = pal_bank + colours[current_tilemap.colour_depth & 7];
+ }
+ /* the colour RAM address wraps, watch all of it if the range goes past its end */
+ if ( vdp2_layer_data.pen_max > 0x800 )
+ {
+ vdp2_layer_data.pen_min = 0;
+ vdp2_layer_data.pen_max = 0x800;
+ }
+ /* prepare cache data */
+ RBG0_cache_data.watch_vdp2_vram_writes |= iRP;
+ RBG0_cache_data.is_cache_dirty &= ~iRP;
+ memcpy(&RBG0_cache_data.layer_data[iRP-1], ¤t_tilemap, sizeof(current_tilemap));
+ RBG0_cache_data.map_offset_min[iRP-1] = vdp2_layer_data.map_offset_min;
+ RBG0_cache_data.map_offset_max[iRP-1] = vdp2_layer_data.map_offset_max;
+ RBG0_cache_data.tile_offset_min[iRP-1] = vdp2_layer_data.tile_offset_min;
+ RBG0_cache_data.tile_offset_max[iRP-1] = vdp2_layer_data.tile_offset_max;
+ RBG0_cache_data.pen_min[iRP-1] = vdp2_layer_data.pen_min;
+ RBG0_cache_data.pen_max[iRP-1] = vdp2_layer_data.pen_max;
+ log_masked(LOG_VDP2, "Cache watch: map = %06X - %06X, tile = %06X - %06X\n", RBG0_cache_data.map_offset_min[iRP-1],
+ RBG0_cache_data.map_offset_max[iRP-1], RBG0_cache_data.tile_offset_min[iRP-1], RBG0_cache_data.tile_offset_max[iRP-1]);
+ }
+ /* stop profiling USER1 */
+ }
+
+ current_tilemap.colour_calculation_enabled = colour_calculation_enabled;
+ if ( colour_calculation_enabled )
+ {
+ current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA;
+ }
+
+#if 0
+ /* old reference code */
+ mycliprect = cliprect;
+
+ if ( current_tilemap.window_control.enabled[0] || current_tilemap.window_control.enabled[1] )
+ {
+ /*popmessage("Window control for RBG"); */
+ vdp2_apply_window_on_layer(mycliprect);
+ current_tilemap.window_control.enabled[0] = 0;
+ current_tilemap.window_control.enabled[1] = 0;
+ }
+#endif
+
+ current_tilemap.fade_control = fade_control;
+
+ if (vdp2_render_mode != VDP2_RENDER_PREPASS)
+ vdp2_copy_roz_bitmap(bitmap, vdp2l.roz_bitmap[iRP-1], cliprect, iRP, planesizex, planesizey, planerenderedsizex, planerenderedsizey );
+ }
+
+}
+
+static void vdp2_draw_RBG0(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ /*
+ Colours : 16, 256, 2048, 32768, 16770000
+ Char Size : 1x1 cells, 2x2 cells
+ Pattern Data Size : 1 word, 2 words
+ Plane Layouts : 1 x 1, 2 x 1, 2 x 2
+ Planes : 4
+ Bitmap : Possible
+ Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
+ Scale : 0.25 x - 256 x
+ Rotation : Yes
+ Linescroll : Yes
+ Column Scroll : Yes
+ Mosaic : Yes
+ */
+
+ current_tilemap.enabled = VDP2_R0ON;
+
+/* if (!current_tilemap.enabled) return; // stop right now if its disabled ... */
+
+ /*current_tilemap.trans_enabled = VDP2_R0TPON; */
+ if ( VDP2_R0CCEN )
+ {
+ current_tilemap.colour_calculation_enabled = 1;
+ current_tilemap.alpha = ((UINT16)(0x1f-VDP2_R0CCRT)*0xff)/0x1f;
+ }
+ else
+ {
+ current_tilemap.colour_calculation_enabled = 0;
+ }
+ if ( VDP2_R0TPON == 0 )
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_PEN;
+ }
+ else
+ {
+ current_tilemap.transparency = STV_TRANSPARENCY_NONE;
+ }
+ current_tilemap.colour_depth = VDP2_R0CHCN;
+ current_tilemap.tile_size = VDP2_R0CHSZ;
+ current_tilemap.bitmap_enable = VDP2_R0BMEN;
+ current_tilemap.bitmap_size = VDP2_R0BMSZ;
+ current_tilemap.bitmap_palette_number = VDP2_R0BMP;
+
+ current_tilemap.pattern_data_size = VDP2_R0PNB;
+ current_tilemap.character_number_supplement = VDP2_R0CNSM;
+ current_tilemap.special_priority_register = VDP2_R0SPR;
+ current_tilemap.special_colour_control_register = VDP2_R0SCC;
+ current_tilemap.supplementary_palette_bits = VDP2_R0SPLT;
+ current_tilemap.supplementary_character_bits = VDP2_R0SPCN;
+
+ current_tilemap.colour_ram_address_offset = VDP2_R0CAOS;
+ current_tilemap.fade_control = (VDP2_R0COEN * 1) | (VDP2_R0COSL * 2);
+ vdp2_check_fade_control_for_layer();
+ /* disable these, we apply them in the roz routines (they were interfering with vdp2_roz_window() ?) */
+ current_tilemap.window_control.logic = 0; /*VDP2_R0LOG; */
+ current_tilemap.window_control.enabled[0] = 0; /*VDP2_R0W0E; */
+ current_tilemap.window_control.enabled[1] = 0; /*VDP2_R0W1E; */
+/* current_tilemap.window_control.? = VDP2_R0SWE; */
+ current_tilemap.window_control.area[0] = 0; /*VDP2_R0W0A; */
+ current_tilemap.window_control.area[1] = 0; /*VDP2_R0W1A; */
+/* current_tilemap.window_control.? = VDP2_R0SWA; */
+
+ current_tilemap.scrollx = 0;
+ current_tilemap.scrolly = 0;
+ current_tilemap.incx = 0x10000;
+ current_tilemap.incy = 0x10000;
+
+ current_tilemap.linescroll_enable = 0;
+ current_tilemap.linescroll_interval = 0;
+ current_tilemap.linescroll_table_address = 0;
+ current_tilemap.vertical_linescroll_enable = 0;
+ current_tilemap.linezoom_enable = 0;
+ current_tilemap.vertical_cell_scroll_enable = 0;
+
+ current_tilemap.line_screen_enabled = VDP2_R0LCEN;
+ current_tilemap.mosaic_screen_enabled = VDP2_R0MZE;
+
+ /*Use 0x80 as a normal/rotate switch*/
+ current_tilemap.layer_name=0x80;
+
+ if ( !current_tilemap.enabled ) return;
+
+ switch(VDP2_RPMD)
+ {
+ case 0:/*Rotation Parameter A */
+ current_tilemap.roz_mode3 = 0;
+ vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
+ break;
+ case 1:/*Rotation Parameter B */
+ /*case 2: */
+ current_tilemap.roz_mode3 = 0;
+ vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
+ break;
+ case 2:/*Rotation Parameter A & B CKTE */
+ current_tilemap.roz_mode3 = 0;
+ vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
+ vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
+ break;
+ case 3:/*Rotation Parameter A & B Window */
+ current_tilemap.roz_mode3 = 1;
+ vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
+ vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
+ break;
+ }
+
+}
+
+static void vdp2_draw_back(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int y;
+ int x;
+ UINT8 const *const gfxdata = vdp2l.gfx_decode;
+
+ UINT8 interlace = (get_lsmd() == 3)+1;
+
+/* popmessage("Back screen %08x %08x %08x",get_bdclmd(),VDP2_BKCLMD,VDP2_BKTA); */
+
+ /* draw black if BDCLMD and DISP are cleared */
+ if(!(get_bdclmd()) && !(get_disp()))
+ bitmap_fill32(bitmap, cliprect, 0);
+ else
+ {
+ UINT32 base_mask = get_vramsz() ? 0x7ffff : 0x3ffff;
+
+ for(y=cliprect->min_y;y<=cliprect->max_y;y++)
+ {
+ UINT32 base_offs = ((VDP2_BKTA ) & base_mask) << 1;
+ UINT16 dot;
+ int r, g, b;
+ UINT32 pix, *line = BMP32(bitmap, y);
+
+ /* the back screen is one colour per line */
+ if(VDP2_BKCLMD)
+ base_offs += ((y / interlace) << 1);
+ dot = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1];
+ b = pal5bit((dot & 0x7c00) >> 10);
+ g = pal5bit((dot & 0x03e0) >> 5);
+ r = pal5bit( dot & 0x001f);
+ if(VDP2_BKCOEN)
+ vdp2_compute_color_offset( &r, &g, &b, VDP2_BKCOSL );
+ pix = RGB_MAKE(r, g, b);
+
+ for(x=cliprect->min_x;x<=cliprect->max_x;x++)
+ line[x] = pix;
+ }
+ }
+}
+
+static UINT32 vdp2_vram_r(offs_t offset)
+{
+ return vdp2_vram[offset];
+}
+
+static void vdp2_vram_w(offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ UINT8* gfxdata = vdp2l.gfx_decode;
+ const UINT32 old_data = vdp2_vram[offset];
+
+ COMBINE_DATA(&vdp2_vram[offset]);
+
+ /* rewriting the same value leaves the decoded tiles and the RBG0 cache valid */
+ if (vdp2_vram[offset] == old_data)
+ return;
+
+ data = vdp2_vram[offset];
+ /* put in gfx region for easy decoding */
+ gfxdata[offset*4+0] = (data & 0xff000000) >> 24;
+ gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16;
+ gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8;
+ gfxdata[offset*4+3] = (data & 0x000000ff) >> 0;
+
+ /* the tiles with these bytes (the 8-bit ones overlap the previous one) */
+ gfx_mark_dirty_addr(offset*4);
+
+ if ( RBG0_cache_data.watch_vdp2_vram_writes )
+ {
+ int i;
+ for (i = 0; i < 2; i++)
+ {
+ if ( !(RBG0_cache_data.watch_vdp2_vram_writes & (1 << i)) )
+ continue;
+
+ if ( offset >= RBG0_cache_data.tile_offset_min[i] &&
+ offset < RBG0_cache_data.tile_offset_max[i] )
+ {
+ /* character data changed, rebuild everything */
+ log_masked(LOG_VDP2, "RBG Cache: dirtying for RP = %d, write at offset = %06X\n", i + 1, offset);
+ RBG0_cache_data.is_cache_dirty |= 1 << i;
+ RBG0_cache_data.watch_vdp2_vram_writes &= ~(1 << i);
+ }
+ else if ( offset >= RBG0_cache_data.map_offset_min[i] &&
+ offset < RBG0_cache_data.map_offset_max[i] )
+ {
+ /* a pattern name changed, only its cells need redrawing */
+ if ( RBG0_cache_data.map_dirty_max[i] <= RBG0_cache_data.map_dirty_min[i] )
+ {
+ RBG0_cache_data.map_dirty_min[i] = offset;
+ RBG0_cache_data.map_dirty_max[i] = offset + 1;
+ }
+ else if ( offset < RBG0_cache_data.map_dirty_min[i] )
+ RBG0_cache_data.map_dirty_min[i] = offset;
+ else if ( offset >= RBG0_cache_data.map_dirty_max[i] )
+ RBG0_cache_data.map_dirty_max[i] = offset + 1;
+ }
+ }
+ }
+}
+
+static UINT16 vdp2_regs_r(offs_t offset)
+{
+ return vdp2_regs[offset];
+}
+
+/* TODO: mode 0 handling */
+static UINT32 vdp2_cram_r(offs_t offset)
+{
+ offset &= (0xfff) >> (2);
+ return vdp2_cram[offset];
+}
+
+/* TODO: byte writes are goofy */
+static void vdp2_cram_w(offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ int i, j;
+ int r,g,b;
+ UINT8 cmode0;
+ UINT32 old_data;
+
+ cmode0 = (VDP2_CRMD & 3) == 0;
+
+ offset &= (0xfff) >> (2);
+ old_data = vdp2_cram[offset];
+ COMBINE_DATA(&vdp2_cram[offset]);
+
+ /* the RBG0 cache holds rendered colours, so changing one it used makes it stale */
+ /* (colour RAM mode 0 mirrors the palette at 0x400, so check both halves) */
+ if (vdp2_cram[offset] != old_data)
+ {
+ const UINT32 pen = ((VDP2_CRMD & 2) ? offset : (offset * 2)) & 0x3ff;
+ const UINT32 count = (VDP2_CRMD & 2) ? 1 : 2;
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ const UINT32 p = j ? (pen | 0x400) : pen;
+ if ((p < RBG0_cache_data.pen_max[i]) && ((p + count) > RBG0_cache_data.pen_min[i]))
+ {
+ RBG0_cache_data.is_cache_dirty |= 1 << i;
+ }
+ }
+ }
+ }
+
+ switch( VDP2_CRMD )
+ {
+ /*Mode 2/3*/
+ case 2:
+ case 3:
+ {
+ /*offset &= (0xfff) >> 2; */
+
+ b = ((vdp2_cram[offset] & 0x00ff0000) >> 16);
+ g = ((vdp2_cram[offset] & 0x0000ff00) >> 8);
+ r = ((vdp2_cram[offset] & 0x000000ff) >> 0);
+ set_pen(offset,RGB_MAKE(r,g,b));
+ set_pen(offset^0x400,RGB_MAKE(r,g,b));
+ }
+ break;
+ /*Mode 0*/
+ case 0:
+ case 1:
+ {
+ offset &= (0xfff) >> (cmode0+2);
+
+ b = ((vdp2_cram[offset] & 0x00007c00) >> 10);
+ g = ((vdp2_cram[offset] & 0x000003e0) >> 5);
+ r = ((vdp2_cram[offset] & 0x0000001f) >> 0);
+ set_pen((offset*2)+1, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+ if(cmode0)
+ set_pen(((offset*2)+1)^0x400, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+
+ b = ((vdp2_cram[offset] & 0x7c000000) >> 26);
+ g = ((vdp2_cram[offset] & 0x03e00000) >> 21);
+ r = ((vdp2_cram[offset] & 0x001f0000) >> 16);
+ set_pen(offset*2, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+ if(cmode0)
+ set_pen((offset*2)^0x400, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+ }
+ break;
+ }
+}
+
+static void refresh_palette_data(void)
+{
+ int r,g,b;
+ int c_i;
+ UINT8 bank;
+
+ RBG0_cache_data.is_cache_dirty |= 3;
+
+ switch( VDP2_CRMD )
+ {
+ case 2:
+ case 3:
+ {
+ for(c_i=0;c_i<0x400;c_i++)
+ {
+ b = ((vdp2_cram[c_i] & 0x00ff0000) >> 16);
+ g = ((vdp2_cram[c_i] & 0x0000ff00) >> 8);
+ r = ((vdp2_cram[c_i] & 0x000000ff) >> 0);
+ set_pen(c_i,RGB_MAKE(r,g,b));
+ set_pen(c_i+0x400,RGB_MAKE(r,g,b));
+ }
+ }
+ break;
+ case 0:
+ {
+ for(bank=0;bank<2;bank++)
+ {
+ for(c_i=0;c_i<0x400;c_i++)
+ {
+ b = ((vdp2_cram[c_i] & 0x00007c00) >> 10);
+ g = ((vdp2_cram[c_i] & 0x000003e0) >> 5);
+ r = ((vdp2_cram[c_i] & 0x0000001f) >> 0);
+ set_pen((c_i*2)+1+bank*0x400, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+ b = ((vdp2_cram[c_i] & 0x7c000000) >> 26);
+ g = ((vdp2_cram[c_i] & 0x03e00000) >> 21);
+ r = ((vdp2_cram[c_i] & 0x001f0000) >> 16);
+ set_pen(c_i*2+bank*0x400, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+ }
+ }
+ }
+ break;
+ case 1:
+ {
+ for(c_i=0;c_i<0x800;c_i++)
+ {
+ b = ((vdp2_cram[c_i] & 0x00007c00) >> 10);
+ g = ((vdp2_cram[c_i] & 0x000003e0) >> 5);
+ r = ((vdp2_cram[c_i] & 0x0000001f) >> 0);
+ set_pen((c_i*2)+1, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+ b = ((vdp2_cram[c_i] & 0x7c000000) >> 26);
+ g = ((vdp2_cram[c_i] & 0x03e00000) >> 21);
+ r = ((vdp2_cram[c_i] & 0x001f0000) >> 16);
+ set_pen(c_i*2, RGB_MAKE(pal5bit(r), pal5bit(g), pal5bit(b)));
+ }
+ }
+ break;
+ }
+}
+
+static void vdp2_regs_w(offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ COMBINE_DATA(&vdp2_regs[offset]);
+
+ if(vdp2l.old_crmd != VDP2_CRMD)
+ {
+ vdp2l.old_crmd = VDP2_CRMD;
+ refresh_palette_data();
+ }
+}
+
+
+static void vdp2_state_save_postload(void)
+{
+ UINT8 *gfxdata = vdp2l.gfx_decode;
+ int offset;
+ UINT32 data;
+
+ for ( offset = 0; offset < 0x100000/4; offset++ )
+ {
+ data = vdp2_vram[offset];
+ /* put in gfx region for easy decoding */
+ gfxdata[offset*4+0] = (data & 0xff000000) >> 24;
+ gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16;
+ gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8;
+ gfxdata[offset*4+3] = (data & 0x000000ff) >> 0;
+
+
+ }
+ for ( offset = 0; offset < 4; offset++ )
+ memset(stv_gfx[offset].dirty, 1, stv_gfx[offset].elements);
+
+ memset(&RBG0_cache_data, 0, sizeof(RBG0_cache_data));
+ RBG0_cache_data.is_cache_dirty = 3;
+ memset(&vdp2_layer_data, 0, sizeof(vdp2_layer_data));
+
+ refresh_palette_data();
+}
+
+static int vdp2_start(void)
+{
+ vdp2_regs = auto_malloc(0x040000);
+ vdp2_vram = auto_malloc(0x100000);
+ vdp2_cram = auto_malloc(0x080000);
+ vdp2l.gfx_decode = auto_malloc(0x100000);
+ if (!vdp2_regs || !vdp2_vram || !vdp2_cram || !vdp2l.gfx_decode)
+ return 1;
+ memset(vdp2_regs, 0, 0x040000);
+ memset(vdp2_vram, 0, 0x100000);
+ memset(vdp2_cram, 0, 0x080000);
+ memset(vdp2l.gfx_decode, 0, 0x100000);
+ vdp2l.roz_bitmap[0] = vdp2l.roz_bitmap[1] = NULL;
+ vdp2l.old_crmd = -1;
+
+ /* the tiles: 8x8 and 16x16, 4 and 8 bits per pixel (the 8x8 8-bit ones every 32 bytes) */
+ vdp2_gfx_source = vdp2l.gfx_decode;
+ gfx_setup(&stv_gfx[0], 8, 8, 4, 32, 0x80*3);
+ gfx_setup(&stv_gfx[1], 16, 16, 4, 128, 0x80*3);
+ gfx_setup(&stv_gfx[2], 8, 8, 8, 32, 0x08*3);
+ gfx_setup(&stv_gfx[3], 16, 16, 8, 256, 0x08*3);
+
+ memset(&RBG0_cache_data, 0, sizeof(RBG0_cache_data));
+ RBG0_cache_data.is_cache_dirty = 3;
+ memset(&vdp2_layer_data, 0, sizeof(vdp2_layer_data));
+
+ state_save_register_UINT16("stv_vdp2", 0, "regs", vdp2_regs, 0x040000/2);
+ state_save_register_UINT32("stv_vdp2", 0, "vram", vdp2_vram, 0x100000/4);
+ state_save_register_UINT32("stv_vdp2", 0, "cram", vdp2_cram, 0x080000/4);
+ state_save_register_func_postload(vdp2_state_save_postload);
+
+ return 0;
+}
+
+/*This is for calculating the rgb brightness*/
+/*TODO: Optimize this...*/
+static void vdp2_fade_effects(void)
+{
+ /*
+ Note:We have to use temporary storages because palette_get_color must use
+ variables setted with unsigned int8
+ */
+ INT16 t_r,t_g,t_b;
+ UINT8 r,g,b;
+ rgb_t color;
+ int i;
+ /*popmessage("%04x %04x",VDP2_CLOFEN,VDP2_CLOFSL); */
+ for(i=0;i<2048;i++)
+ {
+ /*Fade A*/
+ color = PEN(i);
+ t_r = (VDP2_COAR & 0x100) ? (RGB_RED(color) - (0x100 - (VDP2_COAR & 0xff))) : ((VDP2_COAR & 0xff) + RGB_RED(color));
+ t_g = (VDP2_COAG & 0x100) ? (RGB_GREEN(color) - (0x100 - (VDP2_COAG & 0xff))) : ((VDP2_COAG & 0xff) + RGB_GREEN(color));
+ t_b = (VDP2_COAB & 0x100) ? (RGB_BLUE(color) - (0x100 - (VDP2_COAB & 0xff))) : ((VDP2_COAB & 0xff) + RGB_BLUE(color));
+ if(t_r < 0) { t_r = 0; }
+ if(t_r > 0xff) { t_r = 0xff; }
+ if(t_g < 0) { t_g = 0; }
+ if(t_g > 0xff) { t_g = 0xff; }
+ if(t_b < 0) { t_b = 0; }
+ if(t_b > 0xff) { t_b = 0xff; }
+ r = t_r;
+ g = t_g;
+ b = t_b;
+ set_pen(i+(2048*1),RGB_MAKE(r,g,b));
+
+ /*Fade B*/
+ color = PEN(i);
+ t_r = (VDP2_COBR & 0x100) ? (RGB_RED(color) - (0xff - (VDP2_COBR & 0xff))) : ((VDP2_COBR & 0xff) + RGB_RED(color));
+ t_g = (VDP2_COBG & 0x100) ? (RGB_GREEN(color) - (0xff - (VDP2_COBG & 0xff))) : ((VDP2_COBG & 0xff) + RGB_GREEN(color));
+ t_b = (VDP2_COBB & 0x100) ? (RGB_BLUE(color) - (0xff - (VDP2_COBB & 0xff))) : ((VDP2_COBB & 0xff) + RGB_BLUE(color));
+ if(t_r < 0) { t_r = 0; }
+ if(t_r > 0xff) { t_r = 0xff; }
+ if(t_g < 0) { t_g = 0; }
+ if(t_g > 0xff) { t_g = 0xff; }
+ if(t_b < 0) { t_b = 0; }
+ if(t_b > 0xff) { t_b = 0xff; }
+ r = t_r;
+ g = t_g;
+ b = t_b;
+ set_pen(i+(2048*2),RGB_MAKE(r,g,b));
+ }
+ /*popmessage("%04x %04x %04x %04x %04x %04x",VDP2_COAR,VDP2_COAG,VDP2_COAB,VDP2_COBR,VDP2_COBG,VDP2_COBB); */
+}
+
+static void vdp2_get_window0_coordinates_calc(int *s_x, int *e_x, int *s_y, int *e_y, int y)
+{
+ /*W0*/
+ switch(get_lsmd())
+ {
+ case 0:
+ case 1:
+ case 2:
+ *s_y = ((VDP2_W0SY & 0x3ff) >> 0);
+ *e_y = ((VDP2_W0EY & 0x3ff) >> 0);
+ break;
+ case 3:
+ *s_y = ((VDP2_W0SY & 0x7ff) >> 0);
+ *e_y = ((VDP2_W0EY & 0x7ff) >> 0);
+ break;
+ }
+ /* check if line window is enabled */
+ if(VDP2_W0LWE)
+ {
+ UINT32 base_mask = get_vramsz() ? 0x7ffff : 0x3ffff;
+ UINT32 address = (VDP2_W0LWTA & base_mask) * 2;
+ /* double density makes the line window to fetch data every two lines */
+ UINT8 interlace = (get_lsmd() == 3);
+ UINT32 vram_data = vdp2_vram[(address >> 2)+(y >> interlace)];
+
+ *s_x = (vram_data >> 16) & 0x3ff;
+ *e_x = (vram_data & 0x3ff);
+ }
+ else
+ {
+ switch(get_hreso() & 6)
+ {
+ /*Normal*/
+ case 0:
+ *s_x = ((VDP2_W0SX & 0x3fe) >> 1);
+ *e_x = ((VDP2_W0EX & 0x3fe) >> 1);
+ break;
+ /*Hi-Res*/
+ case 2:
+ *s_x = ((VDP2_W0SX & 0x3ff) >> 0);
+ *e_x = ((VDP2_W0EX & 0x3ff) >> 0);
+ break;
+ /*Exclusive Normal*/
+ case 4:
+ *s_x = ((VDP2_W0SX & 0x1ff) >> 0);
+ *e_x = ((VDP2_W0EX & 0x1ff) >> 0);
+ *s_y = ((VDP2_W0SY & 0x3ff) >> 0);
+ *e_y = ((VDP2_W0EY & 0x3ff) >> 0);
+ break;
+ /*Exclusive Hi-Res*/
+ case 6:
+ *s_x = ((VDP2_W0SX & 0x1ff) << 1);
+ *e_x = ((VDP2_W0EX & 0x1ff) << 1);
+ *s_y = ((VDP2_W0SY & 0x3ff) >> 0);
+ *e_y = ((VDP2_W0EY & 0x3ff) >> 0);
+ break;
+ }
+ }
+}
+
+/* the window of a line doesn't change during a screen update, but the rotation
+ screens ask for it on every pixel */
+static INLINE void vdp2_get_window0_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y)
+{
+ static VDP2_TLS int cache_gen = -1, cache_y, c_sx, c_ex, c_sy, c_ey;
+ if (cache_gen != vdp2_window_cache_gen || cache_y != y)
+ {
+ vdp2_get_window0_coordinates_calc(&c_sx, &c_ex, &c_sy, &c_ey, y);
+ cache_gen = vdp2_window_cache_gen;
+ cache_y = y;
+ }
+ *s_x = c_sx; *e_x = c_ex; *s_y = c_sy; *e_y = c_ey;
+}
+
+static void vdp2_get_window1_coordinates_calc(int *s_x, int *e_x, int *s_y, int *e_y, int y)
+{
+ /*W1*/
+ switch(get_lsmd())
+ {
+ case 0:
+ case 1:
+ case 2:
+ *s_y = ((VDP2_W1SY & 0x3ff) >> 0);
+ *e_y = ((VDP2_W1EY & 0x3ff) >> 0);
+ break;
+ case 3:
+ *s_y = ((VDP2_W1SY & 0x7ff) >> 0);
+ *e_y = ((VDP2_W1EY & 0x7ff) >> 0);
+ break;
+ }
+ /* check if line window is enabled */
+ if(VDP2_W1LWE)
+ {
+ UINT32 base_mask = get_vramsz() ? 0x7ffff : 0x3ffff;
+ UINT32 address = (VDP2_W1LWTA & base_mask) * 2;
+ /* double density makes the line window to fetch data every two lines */
+ UINT8 interlace = (get_lsmd() == 3);
+ UINT32 vram_data = vdp2_vram[(address >> 2)+(y >> interlace)];
+
+ *s_x = (vram_data >> 16) & 0x3ff;
+ *e_x = (vram_data & 0x3ff);
+ }
+ else
+ {
+ switch(get_hreso() & 6)
+ {
+ /*Normal*/
+ case 0:
+ *s_x = ((VDP2_W1SX & 0x3fe) >> 1);
+ *e_x = ((VDP2_W1EX & 0x3fe) >> 1);
+ break;
+ /*Hi-Res*/
+ case 2:
+ *s_x = ((VDP2_W1SX & 0x3ff) >> 0);
+ *e_x = ((VDP2_W1EX & 0x3ff) >> 0);
+ break;
+ /*Exclusive Normal*/
+ case 4:
+ *s_x = ((VDP2_W1SX & 0x1ff) >> 0);
+ *e_x = ((VDP2_W1EX & 0x1ff) >> 0);
+ *s_y = ((VDP2_W1SY & 0x3ff) >> 0);
+ *e_y = ((VDP2_W1EY & 0x3ff) >> 0);
+ break;
+ /*Exclusive Hi-Res*/
+ case 6:
+ *s_x = ((VDP2_W1SX & 0x1ff) << 1);
+ *e_x = ((VDP2_W1EX & 0x1ff) << 1);
+ *s_y = ((VDP2_W1SY & 0x3ff) >> 0);
+ *e_y = ((VDP2_W1EY & 0x3ff) >> 0);
+ break;
+ }
+ }
+}
+
+/* the window of a line doesn't change during a screen update, but the rotation
+ screens ask for it on every pixel */
+static INLINE void vdp2_get_window1_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y)
+{
+ static VDP2_TLS int cache_gen = -1, cache_y, c_sx, c_ex, c_sy, c_ey;
+ if (cache_gen != vdp2_window_cache_gen || cache_y != y)
+ {
+ vdp2_get_window1_coordinates_calc(&c_sx, &c_ex, &c_sy, &c_ey, y);
+ cache_gen = vdp2_window_cache_gen;
+ cache_y = y;
+ }
+ *s_x = c_sx; *e_x = c_ex; *s_y = c_sy; *e_y = c_ey;
+}
+
+
+static void vdp2_window_line(int y, int key)
+{
+ int s_x = 0, e_x = 0, s_y = 0, e_y = 0;
+
+ vdp2_wline.gen = vdp2_window_cache_gen;
+ vdp2_wline.y = y;
+ vdp2_wline.key = key;
+ if (current_tilemap.window_control.enabled[0])
+ {
+ vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, y);
+ vdp2_wline.s0 = s_x; vdp2_wline.e0 = e_x;
+ vdp2_wline.in0 = (y >= s_y && y <= e_y);
+ }
+ if (current_tilemap.window_control.enabled[1])
+ {
+ vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, y);
+ vdp2_wline.s1 = s_x; vdp2_wline.e1 = e_x;
+ vdp2_wline.in1 = (y >= s_y && y <= e_y);
+ }
+}
+
+/* same result as get_window_pixel() on both windows, a disabled window counts as 1 */
+static INLINE int vdp2_window_process(int x,int y)
+{
+ int en0 = current_tilemap.window_control.enabled[0];
+ int en1 = current_tilemap.window_control.enabled[1];
+ int key, w0_pix = 1, w1_pix = 1;
+
+ if (!en0 && !en1)
+ return 1;
+
+ key = (en0 ? 1 : 0) | (en1 ? 2 : 0) | (current_tilemap.window_control.area[0] ? 4 : 0) | (current_tilemap.window_control.area[1] ? 8 : 0);
+ if (vdp2_wline.gen != vdp2_window_cache_gen || vdp2_wline.y != y || vdp2_wline.key != key)
+ vdp2_window_line(y, key);
+
+ if (en0)
+ {
+ w0_pix = vdp2_wline.in0 && x >= vdp2_wline.s0 && x <= vdp2_wline.e0;
+ if (!current_tilemap.window_control.area[0])
+ w0_pix ^= 1;
+ }
+ if (en1)
+ {
+ w1_pix = vdp2_wline.in1 && x >= vdp2_wline.s1 && x <= vdp2_wline.e1;
+ if (!current_tilemap.window_control.area[1])
+ w1_pix ^= 1;
+ }
+
+ return current_tilemap.window_control.logic & 1 ? (w0_pix | w1_pix) : (w0_pix & w1_pix);
+}
+
+/* TODO: remove this crap. */
+static int vdp2_apply_window_on_layer(struct rectangle *cliprect)
+{
+ int s_x=0,e_x=0,s_y=0,e_y=0;
+
+ if ( current_tilemap.window_control.enabled[0] && (!current_tilemap.window_control.area[0]))
+ {
+ /* w0, transparent outside supported */
+ vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, 0);
+
+ if ( s_x > cliprect->min_x ) cliprect->min_x = s_x;
+ if ( e_x < cliprect->max_x ) cliprect->max_x = e_x;
+ if ( s_y > cliprect->min_y ) cliprect->min_y = s_y;
+ if ( e_y < cliprect->max_y ) cliprect->max_y = e_y;
+
+ return 1;
+ }
+ else if ( current_tilemap.window_control.enabled[1] && (!current_tilemap.window_control.area[1]) )
+ {
+ /* w1, transparent outside supported */
+ vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, 0);
+
+ if ( s_x > cliprect->min_x ) cliprect->min_x = s_x;
+ if ( e_x < cliprect->max_x ) cliprect->max_x = e_x;
+ if ( s_y > cliprect->min_y ) cliprect->min_y = s_y;
+ if ( e_y < cliprect->max_y ) cliprect->max_y = e_y;
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static void draw_sprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect, UINT8 pri)
+{
+ int x,y,r,g,b;
+ int i;
+ UINT16 pix;
+ UINT16 *framebuffer_line;
+ UINT32 *bitmap_line, *bitmap_line2 = NULL;
+ UINT8 interlace_framebuffer;
+ UINT8 double_x;
+ static const UINT16 sprite_colormask_table[] = {
+ 0x07ff, 0x07ff, 0x07ff, 0x07ff, 0x03ff, 0x07ff, 0x03ff, 0x01ff,
+ 0x007f, 0x003f, 0x003f, 0x003f, 0x00ff, 0x00ff, 0x00ff, 0x00ff
+ };
+ static const UINT16 priority_shift_table[] = { 14, 13, 14, 13, 13, 12, 12, 12, 7, 7, 6, 0, 7, 7, 6, 0 };
+ static const UINT16 priority_mask_table[] = { 3, 7, 1, 3, 3, 7, 7, 7, 1, 1, 3, 0, 1, 1, 3, 0 };
+ static const UINT16 ccrr_shift_table[] = { 11, 11, 11, 11, 10, 11, 10, 9, 0, 6, 0, 6, 0, 6, 0, 6 };
+ static const UINT16 ccrr_mask_table[] = { 7, 3, 7, 3, 7, 1, 3, 7, 0, 1, 0, 3, 0, 1, 0, 3 };
+ static const UINT16 shadow_mask_table[] = { 0, 0, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0 };
+ UINT16 alpha_enabled;
+
+ int sprite_type;
+ int sprite_colormask;
+ int color_offset_pal;
+ int sprite_shadow;
+ UINT16 sprite_priority_shift, sprite_priority_mask, sprite_ccrr_shift, sprite_ccrr_mask;
+ UINT8 priority;
+ UINT8 ccr = 0;
+ UINT8 sprite_priorities[8];
+ UINT8 sprite_ccr[8];
+ int sprite_color_mode = VDP2_SPCLMD;
+ int sprite_window;
+
+ if ( (vdp1_sprite_priorities_usage_valid == 1) && (vdp1_sprite_priorities_used[pri] == 0) )
+ return;
+
+ sprite_priorities[0] = VDP2_S0PRIN;
+ sprite_priorities[1] = VDP2_S1PRIN;
+ sprite_priorities[2] = VDP2_S2PRIN;
+ sprite_priorities[3] = VDP2_S3PRIN;
+ sprite_priorities[4] = VDP2_S4PRIN;
+ sprite_priorities[5] = VDP2_S5PRIN;
+ sprite_priorities[6] = VDP2_S6PRIN;
+ sprite_priorities[7] = VDP2_S7PRIN;
+
+ sprite_ccr[0] = VDP2_S0CCRT;
+ sprite_ccr[1] = VDP2_S1CCRT;
+ sprite_ccr[2] = VDP2_S2CCRT;
+ sprite_ccr[3] = VDP2_S3CCRT;
+ sprite_ccr[4] = VDP2_S4CCRT;
+ sprite_ccr[5] = VDP2_S5CCRT;
+ sprite_ccr[6] = VDP2_S6CCRT;
+ sprite_ccr[7] = VDP2_S7CCRT;
+
+ sprite_type = VDP2_SPTYPE;
+ sprite_colormask = sprite_colormask_table[sprite_type];
+ sprite_priority_shift = priority_shift_table[sprite_type];
+ sprite_priority_mask = priority_mask_table[sprite_type];
+ sprite_ccrr_shift = ccrr_shift_table[sprite_type];
+ sprite_ccrr_mask = ccrr_mask_table[sprite_type];
+ sprite_shadow = shadow_mask_table[sprite_type];
+
+ for ( i = 0; i < (sprite_priority_mask+1); i++ ) if ( sprite_priorities[i] == pri ) break;
+ if ( i == (sprite_priority_mask+1) ) return;
+
+ /* color offset (RGB brightness) */
+ color_offset_pal = 0;
+ if ( VDP2_SPCOEN )
+ {
+ if ( VDP2_SPCOSL == 0 )
+ { color_offset_pal = 2048; }
+ else
+ { color_offset_pal = 2048*2; }
+ }
+
+ /* color calculation (alpha blending)*/
+ if ( VDP2_SPCCEN )
+ {
+ alpha_enabled = 0;
+ switch( VDP2_SPCCCS )
+ {
+ case 0x0: if ( pri <= VDP2_SPCCN ) alpha_enabled = 1; break;
+ case 0x1: if ( pri == VDP2_SPCCN ) alpha_enabled = 1; break;
+ case 0x2: if ( pri >= VDP2_SPCCN ) alpha_enabled = 1; break;
+ case 0x3: alpha_enabled = 2; sprite_shadow = 0; break;
+ }
+ }
+ else
+ {
+ alpha_enabled = 0;
+ }
+
+ /* framebuffer interlace */
+ if ( (get_lsmd() == 3) && vdp1.framebuffer_double_interlace == 0 )
+ interlace_framebuffer = 1;
+ else
+ interlace_framebuffer = 0;
+
+ /*Guess:Some games needs that the horizontal sprite size to be doubled
+ (TODO: understand the proper settings,it might not work like this)*/
+ if(VDP1_TVM() == 0 && BIT(get_hreso(), 1)) /* astrass & findlove */
+ double_x = 1;
+ else
+ double_x = 0;
+
+ /* window control */
+ current_tilemap.window_control.logic = VDP2_SPLOG;
+ current_tilemap.window_control.enabled[0] = VDP2_SPW0E;
+ current_tilemap.window_control.enabled[1] = VDP2_SPW1E;
+/* current_tilemap.window_control.? = VDP2_SPSWE; */
+ current_tilemap.window_control.area[0] = VDP2_SPW0A;
+ current_tilemap.window_control.area[1] = VDP2_SPW1A;
+/* current_tilemap.window_control.? = VDP2_SPSWA; */
+
+ /* several games attempt to use sprite window with an illegal type 1 */
+ /* even if document explicitly states they won't work. */
+ /* (reportedly seen with a SPCTL of 0x30f1, and bits 7 & 6 are there). */
+ /* - kingbox (gameplay, sets 0x3031) */
+ /* - raymanj (corrupted tiles when showing stage intro) */
+ /* - sandor (player feet during attract intro) */
+ /* - samsho4 (character select & gameplay) */
+ /* TODO: document also states that color mode must be zero */
+ /* - but pukunpa (already) uses mode 1 and wants this enabled, mistake? */
+ sprite_window = VDP2_SPWINEN && sprite_type >= 2 && sprite_type <= 7;
+
+/* vdp2_apply_window_on_layer(mycliprect); */
+
+ /*if (VDP2_SPWINEN) */
+ /* popmessage("(%d %d) enable mask %d type %d | color %d alpha %d shadow %d", interlace_framebuffer, double_x, sprite_window, sprite_type, sprite_color_mode, alpha_enabled, sprite_shadow); */
+
+ /* TODO: reminder that this is an unfollowable snippet ... */
+ if (interlace_framebuffer == 0 && double_x == 0 )
+ {
+ if ( alpha_enabled == 0 )
+ {
+ for ( y = cliprect->min_y; y <= cliprect->max_y; y++ )
+ {
+ int x0 = cliprect->min_x, x1 = cliprect->max_x;
+ if ( vdp1_sprite_priorities_usage_valid )
+ {
+ if (vdp1_sprite_priorities_in_fb_line[y][pri] == 0)
+ continue;
+ /* the other pixels of the line only belong to other passes */
+ if (x0 < vdp1_sprite_priorities_min_x[y][pri]) x0 = vdp1_sprite_priorities_min_x[y][pri];
+ if (x1 > vdp1_sprite_priorities_max_x[y][pri]) x1 = vdp1_sprite_priorities_max_x[y][pri];
+ }
+
+ framebuffer_line = vdp1.framebuffer_display_lines[y];
+ bitmap_line = BMP32(bitmap, y);
+
+ for ( x = x0; x <= x1; x++ )
+ {
+ pix = framebuffer_line[x];
+ /* a zero pixel draws nothing in any pass: it does not mark its priority either */
+ if (pix == 0)
+ continue;
+ if(!vdp2_window_process(x,y))
+ continue;
+
+ /* pukunpa, no alpha no framebuffer bumps */
+ if(sprite_window && pix == 0x8000)
+ continue;
+
+ if ( (pix & 0x8000) && sprite_color_mode)
+ {
+ if ( sprite_priorities[0] != pri )
+ {
+ SPRITE_PRIORITY_SEEN(sprite_priorities[0], x, y);
+ continue;
+ };
+
+ b = pal5bit((pix & 0x7c00) >> 10);
+ g = pal5bit((pix & 0x03e0) >> 5);
+ r = pal5bit( pix & 0x001f);
+ if ( color_offset_pal )
+ {
+ vdp2_compute_color_offset( &r, &g, &b, VDP2_SPCOSL );
+ }
+
+ bitmap_line[x] = RGB_MAKE(r, g, b);
+ }
+ else
+ {
+ priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
+ if ( priority != pri )
+ {
+ SPRITE_PRIORITY_SEEN(priority, x, y);
+ continue;
+ };
+
+ /* Pretty Fighter X, Game Tengoku shadows */
+ /* TODO: Pretty Fighter X doesn't read what's behind on title screen, VDP1 bug? */
+ /* TODO: seldomly Game Tengoku shadows aren't drawn properly */
+ /* TODO: allegedly can't enable this with sprite window (verify) */
+ if(pix & 0x8000 && VDP2_SDCTL & 0x100 && !sprite_window)
+ {
+ rgb_t p = bitmap_line[x];
+ bitmap_line[x] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ else
+ {
+ pix &= sprite_colormask;
+ if ( pix == (sprite_colormask - 1) )
+ {
+ /*shadow - in reality, we should check from what layer pixel beneath comes...*/
+ if ( VDP2_SDCTL & 0x3f )
+ {
+ rgb_t p = bitmap_line[x];
+ bitmap_line[x] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ /* note that when shadows are disabled, "shadow" palette entries are not drawn */
+ }
+ else if ( pix )
+ {
+ pix += (VDP2_SPCAOS << 8);
+ pix &= 0x7ff;
+ pix += color_offset_pal;
+ bitmap_line[x] = PEN( pix );
+
+ }
+ }
+
+ /* TODO: I don't think this one makes much sense ... (1) */
+ if ( pix & sprite_shadow )
+ {
+ if ( pix & ~sprite_shadow )
+ {
+ rgb_t p = bitmap_line[x];
+ bitmap_line[x] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ else /*alpha_enabled == 1 */
+ {
+ for ( y = cliprect->min_y; y <= cliprect->max_y; y++ )
+ {
+ int x0 = cliprect->min_x, x1 = cliprect->max_x;
+ if ( vdp1_sprite_priorities_usage_valid )
+ {
+ if (vdp1_sprite_priorities_in_fb_line[y][pri] == 0)
+ continue;
+ /* the other pixels of the line only belong to other passes */
+ if (x0 < vdp1_sprite_priorities_min_x[y][pri]) x0 = vdp1_sprite_priorities_min_x[y][pri];
+ if (x1 > vdp1_sprite_priorities_max_x[y][pri]) x1 = vdp1_sprite_priorities_max_x[y][pri];
+ }
+
+ framebuffer_line = vdp1.framebuffer_display_lines[y];
+ bitmap_line = BMP32(bitmap, y);
+
+ for ( x = x0; x <= x1; x++ )
+ {
+ pix = framebuffer_line[x];
+ /* a zero pixel draws nothing in any pass: it does not mark its priority either */
+ if (pix == 0)
+ continue;
+ if(!vdp2_window_process(x,y))
+ continue;
+
+ /* raymanj on FMV, alpha enabled (no noticeable difference?) */
+ if(sprite_window && pix == 0x8000)
+ continue;
+
+ if ( (pix & 0x8000) && sprite_color_mode)
+ {
+ if ( sprite_priorities[0] != pri )
+ {
+ SPRITE_PRIORITY_SEEN(sprite_priorities[0], x, y);
+ continue;
+ };
+
+
+ b = pal5bit((pix & 0x7c00) >> 10);
+ g = pal5bit((pix & 0x03e0) >> 5);
+ r = pal5bit( pix & 0x001f);
+ if ( color_offset_pal )
+ {
+ vdp2_compute_color_offset( &r, &g, &b, VDP2_SPCOSL );
+ }
+ ccr = sprite_ccr[0];
+ if ( VDP2_CCMD )
+ {
+ bitmap_line[x] = add_blend_r32( bitmap_line[x], RGB_MAKE(r, g, b));
+ }
+ else
+ {
+ bitmap_line[x] = stv_alpha_blend_r32( bitmap_line[x], RGB_MAKE(r, g ,b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
+ }
+ }
+ else
+ {
+ priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
+ if ( priority != pri )
+ {
+ SPRITE_PRIORITY_SEEN(priority, x, y);
+ continue;
+ };
+
+ ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ];
+ if ( alpha_enabled == 2 )
+ {
+ if ( ( pix & 0x8000 ) == 0 )
+ {
+ ccr = 0;
+ }
+ }
+
+
+ {
+ pix &= sprite_colormask;
+ if ( pix == (sprite_colormask - 1) )
+ {
+ /*shadow - in reality, we should check from what layer pixel beneath comes...*/
+ if ( VDP2_SDCTL & 0x3f )
+ {
+ rgb_t p = bitmap_line[x];
+ bitmap_line[x] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ /* note that when shadows are disabled, "shadow" palette entries are not drawn */
+ } else if ( pix )
+ {
+ pix += (VDP2_SPCAOS << 8);
+ pix &= 0x7ff;
+ pix += color_offset_pal;
+ if ( ccr > 0 )
+ {
+ if ( VDP2_CCMD )
+ {
+ bitmap_line[x] = add_blend_r32( bitmap_line[x], PEN(pix) );
+ }
+ else
+ {
+ bitmap_line[x] = stv_alpha_blend_r32( bitmap_line[x], PEN(pix), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ }
+ }
+ else
+ bitmap_line[x] = PEN(pix);
+ }
+ }
+
+ /* TODO: (1) */
+ if ( pix & sprite_shadow )
+ {
+ if ( pix & ~sprite_shadow )
+ {
+ rgb_t p = bitmap_line[x];
+ bitmap_line[x] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* framebuffer line y is drawn on screen lines 2y and 2y + 1 when interlaced */
+ for ( y = cliprect->min_y / (interlace_framebuffer+1); y <= cliprect->max_y / (interlace_framebuffer+1); y++ )
+ {
+ if ( vdp1_sprite_priorities_usage_valid )
+ if (vdp1_sprite_priorities_in_fb_line[y][pri] == 0)
+ continue;
+
+ framebuffer_line = vdp1.framebuffer_display_lines[y];
+ if ( interlace_framebuffer == 0 )
+ {
+ bitmap_line = BMP32(bitmap, y);
+ }
+ else
+ {
+ bitmap_line = BMP32(bitmap, 2*y);
+ bitmap_line2 = BMP32(bitmap, 2*y + 1);
+ }
+
+ for ( x = cliprect->min_x; x <= cliprect->max_x /(double_x+1) ; x++ )
+ {
+ pix = framebuffer_line[x];
+ /* a zero pixel draws nothing in any pass: it does not mark its priority either */
+ if (pix == 0)
+ continue;
+ if(!vdp2_window_process(x,y))
+ continue;
+
+ /* amoudan, interlaced case */
+ if(sprite_window && pix == 0x8000)
+ continue;
+
+ if ( (pix & 0x8000) && sprite_color_mode)
+ {
+ if ( sprite_priorities[0] != pri )
+ {
+ SPRITE_PRIORITY_SEEN(sprite_priorities[0], x, y);
+ continue;
+ };
+
+ b = pal5bit((pix & 0x7c00) >> 10);
+ g = pal5bit((pix & 0x03e0) >> 5);
+ r = pal5bit( pix & 0x001f);
+ if ( color_offset_pal )
+ {
+ vdp2_compute_color_offset( &r, &g, &b, VDP2_SPCOSL );
+ }
+ if ( alpha_enabled == 0 )
+ {
+ if(double_x)
+ {
+ bitmap_line[x*2] = RGB_MAKE(r, g, b);
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = RGB_MAKE(r, g, b);
+ bitmap_line[x*2+1] = RGB_MAKE(r, g, b);
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = RGB_MAKE(r, g, b);
+ }
+ else
+ {
+ bitmap_line[x] = RGB_MAKE(r, g, b);
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x] = RGB_MAKE(r, g, b);
+ }
+ }
+ else /* alpha_blend == 1 */
+ {
+ ccr = sprite_ccr[0];
+
+ if ( VDP2_CCMD )
+ {
+ if(double_x)
+ {
+ bitmap_line[x*2] = add_blend_r32( bitmap_line[x*2], RGB_MAKE(r, g, b) );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = add_blend_r32( bitmap_line2[x*2], RGB_MAKE(r, g, b) );
+ bitmap_line[x*2+1] = add_blend_r32( bitmap_line[x*2+1], RGB_MAKE(r, g, b) );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = add_blend_r32( bitmap_line2[x*2+1], RGB_MAKE(r, g, b) );
+ }
+ else
+ {
+ bitmap_line[x] = add_blend_r32( bitmap_line[x], RGB_MAKE(r, g, b) );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x] = add_blend_r32( bitmap_line2[x], RGB_MAKE(r, g, b) );
+ }
+ }
+ else
+ {
+ if(double_x)
+ {
+ bitmap_line[x*2] = stv_alpha_blend_r32( bitmap_line[x*2], RGB_MAKE(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = stv_alpha_blend_r32( bitmap_line2[x*2], RGB_MAKE(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ bitmap_line[x*2+1] = stv_alpha_blend_r32( bitmap_line[x*2+1], RGB_MAKE(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = stv_alpha_blend_r32( bitmap_line2[x*2+1], RGB_MAKE(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
+ }
+ else
+ {
+ bitmap_line[x] = stv_alpha_blend_r32( bitmap_line[x], RGB_MAKE(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x] = stv_alpha_blend_r32( bitmap_line2[x], RGB_MAKE(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
+ }
+ }
+ }
+ }
+ else
+ {
+ priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
+ if ( priority != pri )
+ {
+ SPRITE_PRIORITY_SEEN(priority, x, y);
+ continue;
+ };
+
+ if ( alpha_enabled )
+ ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ];
+
+ if ( alpha_enabled == 2 )
+ {
+ if ( ( pix & 0x8000 ) == 0 )
+ {
+ ccr = 0;
+ }
+ }
+
+ {
+ pix &= sprite_colormask;
+ if ( pix == (sprite_colormask - 1) )
+ {
+ /*shadow - in reality, we should check from what layer pixel beneath comes...*/
+ if ( VDP2_SDCTL & 0x3f )
+ {
+ rgb_t p = bitmap_line[x];
+ if(double_x)
+ {
+ p = bitmap_line[x*2];
+ bitmap_line[x*2] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ p = bitmap_line[x*2+1];
+ bitmap_line[x*2+1] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ else
+ bitmap_line[x] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ /* note that when shadows are disabled, "shadow" palette entries are not drawn */
+ } else if ( pix )
+ {
+ pix += (VDP2_SPCAOS << 8);
+ pix &= 0x7ff;
+ pix += color_offset_pal;
+ if ( alpha_enabled == 0 )
+ {
+ if(double_x)
+ {
+ bitmap_line[x*2] = PEN( pix );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = PEN( pix );
+ bitmap_line[x*2+1] = PEN( pix );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = PEN( pix );
+ }
+ else
+ {
+ bitmap_line[x] = PEN( pix );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x] = PEN( pix );
+ }
+ }
+ else /* alpha_blend == 1 */
+ {
+ if ( VDP2_CCMD )
+ {
+ if(double_x)
+ {
+ bitmap_line[x*2] = add_blend_r32( bitmap_line[x*2], PEN(pix) );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = add_blend_r32( bitmap_line2[x], PEN(pix) );
+ bitmap_line[x*2+1] = add_blend_r32( bitmap_line[x*2+1], PEN(pix) );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = add_blend_r32( bitmap_line2[x], PEN(pix) );
+ }
+ else
+ {
+ bitmap_line[x] = add_blend_r32( bitmap_line[x], PEN(pix) );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x] = add_blend_r32( bitmap_line2[x], PEN(pix) );
+ }
+ }
+ else
+ {
+ if(double_x)
+ {
+ bitmap_line[x*2] = stv_alpha_blend_r32( bitmap_line[x*2], PEN(pix), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = stv_alpha_blend_r32( bitmap_line2[x], PEN(pix), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ bitmap_line[x*2+1] = stv_alpha_blend_r32( bitmap_line[x*2+1], PEN(pix), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = stv_alpha_blend_r32( bitmap_line2[x], PEN(pix), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ }
+ else
+ {
+ bitmap_line[x] = stv_alpha_blend_r32( bitmap_line[x], PEN(pix), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ if ( interlace_framebuffer == 1 ) bitmap_line2[x] = stv_alpha_blend_r32( bitmap_line2[x], PEN(pix), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
+ }
+ }
+ }
+ }
+ }
+
+ /* TODO: (1) */
+ if ( pix & sprite_shadow )
+ {
+ if ( pix & ~sprite_shadow )
+ {
+ rgb_t p = bitmap_line[x];
+ if(double_x)
+ {
+ p = bitmap_line[x*2];
+ bitmap_line[x*2] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ p = bitmap_line[x*2+1];
+ bitmap_line[x*2+1] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ else
+ bitmap_line[x] = RGB_MAKE(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ vdp1_sprite_priorities_usage_valid = 1;
+}
+
+/* the layers and sprites by priority (with the sprites when 'sprites' is set) */
+static void vdp2_render_layers(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int sprites)
+{
+ UINT8 pri;
+
+ vdp1_sprite_priorities_usage_valid = 0;
+ memset(vdp1_sprite_priorities_used, 0, sizeof(vdp1_sprite_priorities_used));
+
+ /*If a plane has a priority value of zero it isn't shown at all.*/
+ for(pri=1;pri<8;pri++)
+ {
+ if(pri==VDP2_N3PRIN) { vdp2_draw_NBG3(bitmap,cliprect); }
+ if(pri==VDP2_N2PRIN) { vdp2_draw_NBG2(bitmap,cliprect); }
+ if(pri==VDP2_N1PRIN) { vdp2_draw_NBG1(bitmap,cliprect); }
+ if(pri==VDP2_N0PRIN) { vdp2_draw_NBG0(bitmap,cliprect); }
+ if(pri==VDP2_R0PRIN) { vdp2_draw_RBG0(bitmap,cliprect); }
+ if (sprites) { draw_sprites(bitmap,cliprect,pri); }
+ }
+}
+
+#ifdef STV_VIDEO_THREADS
+#include
+
+#define VDP2_MAX_THREADS 4
+
+/* the band workers: band 0 is the main thread's, worker i draws band i */
+static struct
+{
+ sthread_t *thread[VDP2_MAX_THREADS];
+ int index[VDP2_MAX_THREADS];
+ slock_t *lock;
+ scond_t *start, *done;
+ int workers; /* threads started */
+ int gen; /* job number */
+ int bands; /* bands of the job */
+ int pending; /* worker bands not drawn yet */
+ int quit;
+ struct mame_bitmap *bitmap;
+ struct rectangle band[VDP2_MAX_THREADS];
+} vdp2_mt;
+
+/*
+ Thread i draws the strips i, i + n, i + 2n... of VDP2_STRIP lines:
+ the layers are not spread evenly over the screen (a field at the
+ bottom, a sky at the top), strips keep the threads equally busy.
+*/
+#define VDP2_STRIP 16
+
+static void vdp2_render_band(struct mame_bitmap *bitmap, const struct rectangle *screen, int i, int n)
+{
+ int y;
+ vdp2_band_index = i;
+ vdp2_band_decoded_count[i] = 0;
+ for (y = screen->min_y + i * VDP2_STRIP; y <= screen->max_y; y += n * VDP2_STRIP)
+ {
+ struct rectangle strip = *screen;
+ strip.min_y = y;
+ strip.max_y = y + VDP2_STRIP - 1;
+ if (strip.max_y > screen->max_y)
+ strip.max_y = screen->max_y;
+ vdp2_render_layers(bitmap, &strip, 1);
+ }
+ vdp2_band_index = -1;
+}
+
+static void vdp2_band_worker(void *arg)
+{
+ const int i = *(const int *)arg;
+ int seen = 0;
+
+ slock_lock(vdp2_mt.lock);
+ for (;;)
+ {
+ while (vdp2_mt.gen == seen && !vdp2_mt.quit)
+ scond_wait(vdp2_mt.start, vdp2_mt.lock);
+ if (vdp2_mt.quit)
+ break;
+ seen = vdp2_mt.gen;
+ if (i < vdp2_mt.bands)
+ {
+ struct rectangle screen = vdp2_mt.band[0];
+ struct mame_bitmap *bitmap = vdp2_mt.bitmap;
+ int bands = vdp2_mt.bands;
+ slock_unlock(vdp2_mt.lock);
+ vdp2_render_band(bitmap, &screen, i, bands);
+ slock_lock(vdp2_mt.lock);
+ if (--vdp2_mt.pending == 0)
+ scond_signal(vdp2_mt.done);
+ }
+ }
+ slock_unlock(vdp2_mt.lock);
+}
+
+static void vdp2_threads_stop(void)
+{
+ int i;
+ if (!vdp2_mt.lock)
+ return;
+ slock_lock(vdp2_mt.lock);
+ vdp2_mt.quit = 1;
+ scond_broadcast(vdp2_mt.start);
+ slock_unlock(vdp2_mt.lock);
+ for (i = 1; i < vdp2_mt.workers + 1; i++)
+ sthread_join(vdp2_mt.thread[i]);
+ scond_free(vdp2_mt.start);
+ scond_free(vdp2_mt.done);
+ slock_free(vdp2_mt.lock);
+ memset(&vdp2_mt, 0, sizeof(vdp2_mt));
+ for (i = 0; i < VDP2_MAX_THREADS; i++)
+ {
+ free(vdp2_band_decoded[i]);
+ vdp2_band_decoded[i] = NULL;
+ vdp2_band_decoded_count[i] = 0;
+ }
+}
+
+/* the screen in bands, 0 if the threads are not there (then the caller draws it alone) */
+static int vdp2_render_threaded(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ int bands = options.stv_video_threads, i;
+
+ if (bands > VDP2_MAX_THREADS)
+ bands = VDP2_MAX_THREADS;
+ if (!vdp2_mt.lock)
+ {
+ vdp2_mt.lock = slock_new();
+ vdp2_mt.start = scond_new();
+ vdp2_mt.done = scond_new();
+ if (!vdp2_mt.lock || !vdp2_mt.start || !vdp2_mt.done)
+ return 0;
+ }
+ while (vdp2_mt.workers < bands - 1)
+ {
+ i = vdp2_mt.workers + 1;
+ vdp2_mt.index[i] = i;
+ vdp2_mt.thread[i] = sthread_create(vdp2_band_worker, &vdp2_mt.index[i]);
+ if (!vdp2_mt.thread[i])
+ break;
+ vdp2_mt.workers++;
+ }
+ if (bands > vdp2_mt.workers + 1)
+ bands = vdp2_mt.workers + 1;
+ if (bands < 2)
+ return 0;
+ for (i = 0; i < bands; i++)
+ if (!vdp2_band_decoded[i])
+ {
+ vdp2_band_decoded[i] = malloc(VDP2_DECODED_MAX * sizeof(UINT32));
+ if (!vdp2_band_decoded[i])
+ return 0;
+ }
+
+ /* the rotation plane caches first, alone */
+ vdp2_render_mode = VDP2_RENDER_PREPASS;
+ vdp2_render_layers(bitmap, cliprect, 0);
+
+ /* then the bands */
+ vdp2_render_mode = VDP2_RENDER_BAND;
+ vdp2_mt.band[0] = *cliprect;
+ slock_lock(vdp2_mt.lock);
+ vdp2_mt.bitmap = bitmap;
+ vdp2_mt.bands = bands;
+ vdp2_mt.pending = bands - 1;
+ vdp2_mt.gen++;
+ scond_broadcast(vdp2_mt.start);
+ slock_unlock(vdp2_mt.lock);
+
+ vdp2_render_band(bitmap, cliprect, 0, bands);
+
+ slock_lock(vdp2_mt.lock);
+ while (vdp2_mt.pending)
+ scond_wait(vdp2_mt.done, vdp2_mt.lock);
+ slock_unlock(vdp2_mt.lock);
+
+ /* the elements the strips decoded are up to date now */
+ for (i = 0; i < bands; i++)
+ {
+ int k;
+ for (k = 0; k < vdp2_band_decoded_count[i]; k++)
+ {
+ UINT32 e = vdp2_band_decoded[i][k];
+ stv_gfx[e >> 24].dirty[e & 0xffffff] = 0;
+ }
+ vdp2_band_decoded_count[i] = 0;
+ }
+ vdp2_render_mode = VDP2_RENDER_NORMAL;
+ return 1;
+}
+#endif
+
+/* the VDP2 screen, drawn at the end of the active display as MAME does */
+static void vdp2_render(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
+{
+ vdp2_window_cache_gen++;
+ vdp2_fade_effects();
+
+ vdp2_draw_back(bitmap,cliprect);
+
+ if(get_disp())
+ {
+ memset(vdp1_sprite_priorities_in_fb_line, 0, sizeof(vdp1_sprite_priorities_in_fb_line));
+ memset(vdp1_sprite_priorities_min_x, 0xff, sizeof(vdp1_sprite_priorities_min_x));
+ memset(vdp1_sprite_priorities_max_x, 0, sizeof(vdp1_sprite_priorities_max_x));
+
+#ifdef STV_VIDEO_THREADS
+ /* strips of lines (of an even number of lines from an even one: an interlaced framebuffer line is two) */
+ if (options.stv_video_threads > 1 && !(cliprect->min_y & 1) && cliprect->max_y - cliprect->min_y >= 64 &&
+ vdp2_render_threaded(bitmap, cliprect))
+ return;
+#endif
+ vdp2_render_layers(bitmap, cliprect, 1);
+ }
+}
+
+
+/***************************************************************************
+ VDP2 CRTC (MAME's saturn_vdp2.cpp): TV mode, status, H/V counters
+***************************************************************************/
+
+#define STV_LINES_PER_FRAME 263
+#define STV_FRAMES_PER_SECOND 60
+
+static int crtc_line; /* the current line, from the driver */
+static double crtc_line_time; /* when it started */
+static UINT8 true_vcount[263][4];
+static UINT16 true_vcount_hi[263][4];
+static struct mame_bitmap *vdp2_screen;
+static struct rectangle vdp2_visarea;
+
+static void crtc_init_vcounter_table(void)
+{
+ int i;
+
+ /* 224 mode */
+ for (i = 0; i < 263; i++)
+ {
+ int v = i;
+ if (i > 0xec)
+ v += 0xf9;
+ true_vcount[i][0] = v & 0xff;
+ true_vcount_hi[i][0] = v;
+ }
+ /* 240 mode */
+ for (i = 0; i < 263; i++)
+ {
+ int v = i;
+ if (i > 0xf5)
+ v += 0xf9;
+ true_vcount[i][1] = v & 0xff;
+ true_vcount_hi[i][1] = v;
+ }
+ /* 256 modes (PAL only) */
+ for (i = 0; i < 263; i++)
+ {
+ true_vcount_hi[i][2] = i;
+ true_vcount_hi[i][3] = i;
+ }
+}
+
+static int crtc_htotal(void)
+{
+ int res = BIT(crtc.hreso, 0) ? 455 : 427;
+
+ /* x2 horizontal resolution in 640/704 modes */
+ if (BIT(crtc.hreso, 1))
+ res <<= 1;
+ return res;
+}
+
+static void crtc_reconfigure(void)
+{
+ static const int d_vres[4] = { 224, 240, 256, 256 };
+ static const int d_hres[4] = { 320, 352, 640, 704 };
+ int vres_mask = (crtc.is_pal << 1) | 1;
+ int horz_res, vert_res;
+
+ /* reset odd bit if a dynamic resolution change occurs, stv:seabass cares */
+ crtc.odd_bit = 1;
+
+ vert_res = d_vres[crtc.vreso & vres_mask];
+
+ /* double density interlace */
+ if (crtc.lsmd == 3)
+ vert_res *= 2;
+
+ horz_res = d_hres[crtc.hreso & 3];
+
+ /* exclusive modes (31kHz and Hi-Vision) are 480 lines whatever VRESO says */
+ if (BIT(crtc.hreso, 2))
+ vert_res = 480;
+
+ crtc.hdisplay = horz_res;
+ crtc.vdisplay = vert_res;
+
+ rect_set(&vdp2_visarea, 0, horz_res - 1, 0, vert_res - 1);
+}
+
+/* the horizontal position in pixel clocks of the current mode */
+static int crtc_hpos(void)
+{
+ double line_period = 1.0 / (STV_FRAMES_PER_SECOND * STV_LINES_PER_FRAME);
+ double elapsed = timer_get_time() - crtc_line_time;
+ int htotal = crtc_htotal();
+ int hpos = (int)(elapsed / line_period * htotal);
+
+ if (hpos < 0)
+ hpos = 0;
+ if (hpos >= htotal)
+ hpos = htotal - 1;
+ return hpos;
+}
+
+static int crtc_get_hcounter(void)
+{
+ int hcount = crtc_hpos();
+
+ switch (crtc.hreso & 6)
+ {
+ case 0: hcount &= 0x1ff; hcount <<= 1; break; /* normal */
+ case 2: hcount &= 0x3ff; break; /* hi-res */
+ case 4: hcount &= 0x1ff; break; /* exclusive normal */
+ case 6: hcount >>= 1; hcount &= 0x1ff; break; /* exclusive hi-res */
+ }
+ return hcount;
+}
+
+static int crtc_get_vcounter(void)
+{
+ int vcount = crtc_line;
+
+ /* exclusive monitor */
+ if (BIT(crtc.hreso, 2))
+ return vcount & 0x3ff;
+
+ /* double density interlace: the field is the low bit */
+ if (crtc.lsmd == 3)
+ return ((vcount << 1) & ~1) | (crtc.odd_bit ^ 1);
+
+ return true_vcount_hi[vcount % 263][crtc.vreso & 3];
+}
+
+static int crtc_get_hblank(void)
+{
+ return crtc_hpos() > crtc.hdisplay - 1;
+}
+
+int stv_vdp2_vblank_start_line(void)
+{
+ /* the first setting is at 240, the 16 lines are border overscan */
+ static const int d_vres[4] = { 240, 240, 256, 256 };
+ return d_vres[crtc.vreso & ((crtc.is_pal << 1) | 1)];
+}
+
+static int crtc_get_vblank(void)
+{
+ return crtc_line >= stv_vdp2_vblank_start_line();
+}
+
+static void crtc_tvmd_w(UINT16 data, UINT16 mem_mask)
+{
+ COMBINE_DATA(&crtc.tvmd);
+ crtc.disp = BIT(crtc.tvmd, 15);
+ crtc.bdclmd = BIT(crtc.tvmd, 8);
+ crtc.lsmd = (crtc.tvmd >> 6) & 3;
+ crtc.vreso = (crtc.tvmd >> 4) & 3;
+ crtc.hreso = (crtc.tvmd >> 0) & 7;
+ if (!(mem_mask & 0x00ff) && (crtc.tvmd & 0xff) != (crtc.old_tvmd & 0xff))
+ crtc_reconfigure();
+ crtc.old_tvmd = crtc.tvmd;
+}
+
+static UINT16 crtc_regs_r(int offset)
+{
+ switch (offset)
+ {
+ case 0x00/2: /* TVMD */
+ return crtc.tvmd;
+
+ case 0x02/2: /* EXTEN: reading it latches the H/V counters */
+ if (!crtc.exlten)
+ {
+ crtc.hcounter_latch = crtc_get_hcounter();
+ crtc.vcounter_latch = crtc_get_vcounter();
+ crtc.exltfg |= 1;
+ }
+ return crtc.exten;
+
+ case 0x04/2: /* TVSTAT */
+ {
+ /* exclusive modes force the odd bit; vblank reads 1 with the display off */
+ int odd_flag = crtc.odd_bit | BIT(crtc.hreso, 2);
+ int vblank_flag = crtc_get_vblank() | (!crtc.disp);
+ UINT16 res = (crtc.exltfg << 9) | (crtc.exsyfg << 8) | (vblank_flag << 3)
+ | (crtc_get_hblank() << 2) | (odd_flag << 1) | crtc.is_pal;
+
+ crtc.exltfg &= ~1;
+ crtc.exsyfg &= ~1;
+ return res;
+ }
+
+ case 0x06/2: /* VRSIZE */
+ return (crtc.vramsz << 15) | 0;
+
+ case 0x08/2: /* HCNT */
+ return crtc.hcounter_latch;
+
+ case 0x0a/2: /* VCNT */
+ return crtc.vcounter_latch;
+ }
+ return vdp2_regs_r(offset);
+}
+
+static void crtc_regs_w(int offset, UINT16 data, UINT16 mem_mask)
+{
+ switch (offset)
+ {
+ case 0x00/2:
+ crtc_tvmd_w(data, mem_mask);
+ break;
+
+ case 0x02/2:
+ COMBINE_DATA(&crtc.exten);
+ crtc.exlten = BIT(crtc.exten, 9);
+ crtc.exsyen = BIT(crtc.exten, 8);
+ crtc.dasel = BIT(crtc.exten, 1);
+ crtc.exbgen = BIT(crtc.exten, 0);
+ break;
+
+ case 0x06/2:
+ if (!(mem_mask & 0xff00))
+ crtc.vramsz = BIT(data, 15);
+ break;
+ }
+ /* the VDP2 code also reads the registers */
+ vdp2_regs_w(offset, data, mem_mask);
+}
+
+static void crtc_state_save_postload(void)
+{
+ crtc_reconfigure();
+}
+
+static void crtc_start(void)
+{
+ memset(&crtc, 0, sizeof(crtc));
+ crtc_init_vcounter_table();
+ crtc.odd_bit = 1;
+ crtc.old_tvmd = 0xffff;
+ crtc.is_pal = 0;
+ crtc_line = 0;
+ crtc_line_time = 0;
+ crtc_reconfigure();
+
+ state_save_register_UINT16("stv_crtc", 0, "tvmd", &crtc.tvmd, 1);
+ state_save_register_UINT16("stv_crtc", 0, "old_tvmd", &crtc.old_tvmd, 1);
+ state_save_register_int("stv_crtc", 0, "disp", &crtc.disp);
+ state_save_register_int("stv_crtc", 0, "bdclmd", &crtc.bdclmd);
+ state_save_register_int("stv_crtc", 0, "lsmd", &crtc.lsmd);
+ state_save_register_int("stv_crtc", 0, "vreso", &crtc.vreso);
+ state_save_register_int("stv_crtc", 0, "hreso", &crtc.hreso);
+ state_save_register_int("stv_crtc", 0, "odd_bit", &crtc.odd_bit);
+ state_save_register_UINT16("stv_crtc", 0, "exten", &crtc.exten, 1);
+ state_save_register_int("stv_crtc", 0, "exlten", &crtc.exlten);
+ state_save_register_int("stv_crtc", 0, "exsyen", &crtc.exsyen);
+ state_save_register_int("stv_crtc", 0, "dasel", &crtc.dasel);
+ state_save_register_int("stv_crtc", 0, "exbgen", &crtc.exbgen);
+ state_save_register_int("stv_crtc", 0, "exltfg", &crtc.exltfg);
+ state_save_register_int("stv_crtc", 0, "exsyfg", &crtc.exsyfg);
+ state_save_register_UINT16("stv_crtc", 0, "hcnt", &crtc.hcounter_latch, 1);
+ state_save_register_UINT16("stv_crtc", 0, "vcnt", &crtc.vcounter_latch, 1);
+ state_save_register_int("stv_crtc", 0, "vramsz", &crtc.vramsz);
+ state_save_register_func_postload(crtc_state_save_postload);
+}
+
+
+/***************************************************************************
+ Frame timing, from the driver
+***************************************************************************/
+
+/* the start of a line (0 to 262) */
+void stv_vdp2_scanline(int line)
+{
+ crtc_line = line;
+ crtc_line_time = timer_get_time();
+
+ /* the screen is drawn at the end of the active display */
+ {
+ int last = crtc.vdisplay;
+ if (crtc.lsmd == 3 || BIT(crtc.hreso, 2))
+ last /= 2;
+ if (last > STV_LINES_PER_FRAME - 1)
+ last = STV_LINES_PER_FRAME - 1;
+ if (line == last)
+ vdp2_render(vdp2_screen, &vdp2_visarea);
+ }
+
+ /* the odd bit flips at vblank-in */
+ if (line == stv_vdp2_vblank_start_line())
+ crtc.odd_bit ^= 1;
+}
+
+void stv_vdp1_video_update(void)
+{
+ vdp1_video_update();
+}
+
+void stv_vdp1_vblank_erase(void)
+{
+ /* the docs say VBE happens one line after vblank-in */
+ if (VDP1_VBE())
+ vdp1.framebuffer_clear_on_next_frame = 1;
+}
+
+
+/***************************************************************************
+ Memory handlers (the 16-bit registers as 32-bit pairs, big endian)
+***************************************************************************/
+
+READ32_HANDLER( stv_vdp1_regs_r )
+{
+ UINT32 res = 0;
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ res |= vdp1_regs_r(offset*2) << 16;
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ res |= vdp1_regs_r(offset*2+1);
+ return res;
+}
+
+WRITE32_HANDLER( stv_vdp1_regs_w )
+{
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ vdp1_regs_w(offset*2, data >> 16, mem_mask >> 16);
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ vdp1_regs_w(offset*2+1, data & 0xffff, mem_mask & 0xffff);
+}
+
+READ32_HANDLER( stv_vdp1_vram_r )
+{
+ return vdp1_vram_r(offset);
+}
+
+WRITE32_HANDLER( stv_vdp1_vram_w )
+{
+ vdp1_vram_w(offset, data, mem_mask);
+}
+
+READ32_HANDLER( stv_vdp1_framebuffer0_r )
+{
+ return vdp1_framebuffer0_r(offset, mem_mask);
+}
+
+WRITE32_HANDLER( stv_vdp1_framebuffer0_w )
+{
+ vdp1_framebuffer0_w(offset, data, mem_mask);
+}
+
+READ32_HANDLER( stv_vdp2_vram_r )
+{
+ return vdp2_vram_r(offset & 0x7ffff/4);
+}
+
+WRITE32_HANDLER( stv_vdp2_vram_w )
+{
+ vdp2_vram_w(offset & 0x7ffff/4, data, mem_mask);
+}
+
+READ32_HANDLER( stv_vdp2_cram_r )
+{
+ return vdp2_cram_r(offset);
+}
+
+WRITE32_HANDLER( stv_vdp2_cram_w )
+{
+ vdp2_cram_w(offset, data, mem_mask);
+}
+
+READ32_HANDLER( stv_vdp2_regs_r )
+{
+ UINT32 res = 0;
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ res |= crtc_regs_r(offset*2) << 16;
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ res |= crtc_regs_r(offset*2+1);
+ return res;
+}
+
+WRITE32_HANDLER( stv_vdp2_regs_w )
+{
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ crtc_regs_w(offset*2, data >> 16, mem_mask >> 16);
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ crtc_regs_w(offset*2+1, data & 0xffff, mem_mask & 0xffff);
+}
+
+
+/***************************************************************************
+ Video start, stop and update
+***************************************************************************/
+
+VIDEO_START( stv_vdp2 )
+{
+ if (vdp2_start() || vdp1_start())
+ return 1;
+ crtc_start();
+ m_vdpdebug_roz = 0;
+
+ /* the screen is drawn here during the frame, then copied */
+ vdp2_screen = auto_bitmap_alloc_depth(704, 512, 32);
+ if (!vdp2_screen)
+ return 1;
+ return 0;
+}
+
+VIDEO_STOP( stv_vdp2 )
+{
+ int i;
+#ifdef STV_VIDEO_THREADS
+ vdp2_threads_stop();
+#endif
+ for (i = 0; i < 2; i++)
+ if (vdp2l.roz_bitmap[i])
+ {
+ bitmap_free(vdp2l.roz_bitmap[i]);
+ vdp2l.roz_bitmap[i] = NULL;
+ }
+}
+
+VIDEO_UPDATE( stv_vdp2 )
+{
+ if (Machine->visible_area.max_x != vdp2_visarea.max_x || Machine->visible_area.max_y != vdp2_visarea.max_y)
+ set_visible_area(0, vdp2_visarea.max_x, 0, vdp2_visarea.max_y);
+
+ copybitmap(bitmap, vdp2_screen, 0, 0, 0, 0, &vdp2_visarea, TRANSPARENCY_NONE, 0);
+}