mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 04:16:07 -10:00
Sega ST-V: driver, VDP1/VDP2 video and SCU from current MAME, optional SH-2 recompiler and threaded video (#2124)
- Driver, SCU (DMA, interrupts, timers, DSP), SMPC, MINIT/SINIT, EEPROM and the protection chips as current MAME; the current MAME sets. - VDP1/VDP2 video as current MAME's (one stvvid.c), with exact speedups: partial redraw of the rotation plane cache, rotation copy, sprite passes, window evaluation once per line. - SH-2 recompiler on the bundled sljit (x86, x86-64, ARM32, ARM64; the "SH-2 Dynarec" core option, off by default): blocks with chaining, page tables for direct memory access, memory handlers called from the blocks; the SGL idle loop is skipped exactly; context switch by pointer. Same output as the interpreter on all the sets. - "ST-V Threaded Video" core option (off by default): the screen drawn in strips by 2-4 threads (libretro-common rthreads, where thread-local storage is native), same output. Two more sets of Zen Nippon Pro-Wrestling Featuring Virtua, both on the Taiwan BIOS (the core selects it): - znpwfvt: All Japan Pro-Wrestling Featuring Virtua (Taiwan), as in current MAME. - znpwfve: English translation (bootleg) on the Taiwan program, with the graphics the English mode left in Japanese redrawn; the ROMs are built from the original ones by https://github.com/zanac/znpwfvt Claude-Session: https://claude.ai/code/session_013Vje3pEtpLHubqCGwCgoQX Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
df60f6466d
commit
273f904d7d
24 files changed
+15978
-5395
No files matched your search
@@ -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
|
||||
|
||||
+7
-1
@@ -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 += \
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1300
-133
File diff suppressed because it is too large.
Load diff
+156
-97
@@ -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();
|
||||
}
|
||||
case 0x41: /* DVDNT: a 32-bit division, the dividend sign-extended into DVDNTH */
|
||||
sh2_divu_start((INT32)sh2.m[0x41]);
|
||||
break;
|
||||
}
|
||||
case 0x42: /* DVCR*/
|
||||
sh2.m[0x42] = (sh2.m[0x42] & ~0x00001000) | (old & sh2.m[0x42] & 0x00010000);
|
||||
sh2_recalc_irq();
|
||||
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();
|
||||
}
|
||||
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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+14
-2
@@ -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 )
|
||||
|
||||
+1516
-841
File diff suppressed because it is too large.
Load diff
+17
-41
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
+15
-3
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
+4
-1
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+30
-9
@@ -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;
|
||||
}
|
||||
@@ -699,6 +707,9 @@ static void SCSP_w16(unsigned int addr,unsigned short val)
|
||||
}
|
||||
}
|
||||
else if(addr<0x600)
|
||||
{
|
||||
/* the common registers end at 0x42f (writing past them would hit the slots) */
|
||||
if((addr&0xff)<sizeof(SCSP->udata.datab))
|
||||
{
|
||||
*((unsigned short *) (SCSP->udata.datab+((addr&0xff)))) = val;
|
||||
if (Machine->sample_rate > 0)
|
||||
@@ -706,6 +717,7 @@ static void SCSP_w16(unsigned int addr,unsigned short val)
|
||||
SCSP_UpdateReg(addr&0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(addr>=0x700 && addr<0xc00)
|
||||
{
|
||||
/* DSP: COEF, MADRS, microprogram. 0x7c0-0x7ff is not a mirror of
|
||||
@@ -738,6 +750,8 @@ static unsigned short SCSP_r16(unsigned int addr)
|
||||
v=*((unsigned short *) (SCSP->Slots[slot].udata.datab+(addr)));
|
||||
}
|
||||
else if(addr<0x600)
|
||||
{
|
||||
if((addr&0xff)<sizeof(SCSP->udata.datab))
|
||||
{
|
||||
if (Machine->sample_rate > 0)
|
||||
{
|
||||
@@ -745,6 +759,7 @@ static unsigned short SCSP_r16(unsigned int addr)
|
||||
}
|
||||
v= *((unsigned short *) (SCSP->udata.datab+((addr&0xff))));
|
||||
}
|
||||
}
|
||||
else if(addr>=0x700)
|
||||
{
|
||||
/* DSP */
|
||||
@@ -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<<SHIFT)-1);\
|
||||
s2=(int) p[0]*((1<<SHIFT)-fpart)+(int) p[1]*fpart;\
|
||||
s2=(int) (signed char) slot->ram[o]*((1<<SHIFT)-fpart)+(int) (signed char) slot->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<<SHIFT)-1);\
|
||||
data32_t o=(slot->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);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+10555
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user