mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 04:16:07 -10:00
ST-V and Model 2: save states, run-ahead and netplay; SCSP slot allocation (#2202)
Save states on ST-V were broken on master: a loaded state, a run-ahead rewind or a netplay resync did not continue the emulation the same way. Model 2 was almost right (hpyagu98 differed after a rewind). Core: - SH-2: each CPU registers its own state (both used to register the boot buffer), and the rest of the CPU is saved: delay slot, divider, interrupt queue and lines, on-chip registers, FRT, DMA timers. - Memory banks are registered after the driver init, where the drivers point them (ST-V work RAM was saved from the wrong buffer). - cpu_spinuntil_time / cpu_yielduntil_time trigger counters are saved. - The crosshair idle timer is saved (the crosshair hid at another frame after a load or a rewind). ST-V: - SMPC, SCU registers and interrupts, SCU DSP, I/O, sound CPU control, CD block scalars, VDP1 clipping, CRTC line counter are saved. - The RTC starts from the host date and time at boot and then follows the emulated time (it read the host clock at every query, so two runs from the same state could read different times). SH-2 recompiler: the polling loop skip counted a whole chain of blocks that came back to the loop start as one loop iteration, skipping the writes and calls in between. It now only skips when the block ran one turn of the loop. Results with a warm or a cold block cache are now the same. Model 2: the polygon count of the last display list is saved. SCSP (issue #2194, regression of #2198): a key off on a slot that had already stopped (a one-shot sample past its end) left its envelope at the level it stopped at, because a stopped slot no longer updates it. The monitor register (0x408) then showed the slot as still sounding, the sound drivers took it for busy and, after a while, put every new note on the one slot left. Cotton Boomerang lost all but the drums at the first boss, Winter Heat's voices cut each other from the first attract demo on. Such a slot now ends its release at once. Claude-Session: https://claude.ai/code/session_013Vje3pEtpLHubqCGwCgoQX Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
7ed1af5370
commit
ab52620ee4
18 files changed
+359
-37
No files matched your search
+25
-1
@@ -3154,7 +3154,7 @@ 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);
|
||||
sh2p = (SH2 *)cpunum_get_context_buffer(cpu);
|
||||
if (!sh2p)
|
||||
sh2p = &sh2_boot;
|
||||
memset(sh2p, 0, sizeof(SH2));
|
||||
@@ -3199,5 +3199,29 @@ void sh2_init(void)
|
||||
state_save_register_UINT32("sh2", cpu, "R13", &sh2.r[13], 1);
|
||||
state_save_register_UINT32("sh2", cpu, "R14", &sh2.r[14], 1);
|
||||
state_save_register_UINT32("sh2", cpu, "EA", &sh2.ea, 1);
|
||||
/* the rest of the CPU: the delay slot, the divider, the interrupts and
|
||||
the on-chip modules (their registers, the free running timer, the DMA) */
|
||||
state_save_register_UINT32("sh2", cpu, "PPC", &sh2.ppc, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "delay", &sh2.delay, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "cpu_off", &sh2.cpu_off, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "dvsr", &sh2.dvsr, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "dvdnth", &sh2.dvdnth, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "dvdntl", &sh2.dvdntl, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "dvcr", &sh2.dvcr, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "pending_irq", &sh2.pending_irq, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "test_irq", &sh2.test_irq, 1);
|
||||
state_save_register_INT32("sh2", cpu, "irq_queue", (INT32 *)sh2.irq_queue, 16 * 2);
|
||||
state_save_register_INT8("sh2", cpu, "irq_line_state", sh2.irq_line_state, 16);
|
||||
state_save_register_INT8("sh2", cpu, "nmi_line_state", &sh2.nmi_line_state, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "m", sh2.m, 0x200 / 4);
|
||||
state_save_register_UINT16("sh2", cpu, "frc", &sh2.frc, 1);
|
||||
state_save_register_UINT16("sh2", cpu, "ocra", &sh2.ocra, 1);
|
||||
state_save_register_UINT16("sh2", cpu, "ocrb", &sh2.ocrb, 1);
|
||||
state_save_register_UINT16("sh2", cpu, "icr", &sh2.icr, 1);
|
||||
state_save_register_UINT32("sh2", cpu, "frc_base", &sh2.frc_base, 1);
|
||||
state_save_register_int("sh2", cpu, "frt_input", &sh2.frt_input);
|
||||
state_save_register_int("sh2", cpu, "internal_irq_level", &sh2.internal_irq_level);
|
||||
state_save_register_int("sh2", cpu, "internal_irq_vector", &sh2.internal_irq_vector);
|
||||
state_save_register_INT32("sh2", cpu, "dma_timer_active", (INT32 *)sh2.dma_timer_active, 2);
|
||||
return;
|
||||
}
|
||||
+10
-3
@@ -85,6 +85,7 @@ struct jit_block
|
||||
UINT8 len; /* instructions */
|
||||
UINT8 idle; /* the SGL idle counting loop starts here (see jit_idle_skip) */
|
||||
UINT8 spin; /* a polling loop that only reads: see jit_spin_skip */
|
||||
UINT16 spincost; /* cycles of one iteration of that loop */
|
||||
UINT16 op0; /* first opcode, to retry an untranslatable block once it changes */
|
||||
};
|
||||
|
||||
@@ -1942,12 +1943,13 @@ static int jit_spin_block(const UINT16 *ops, UINT32 count, UINT32 pc)
|
||||
{
|
||||
UINT32 i;
|
||||
/* the loop: from the start to a BT or BF back to it; the rest of the
|
||||
block only runs once the loop is left */
|
||||
block only runs once the loop is left. Returns the instructions of
|
||||
the loop, 0 if the block does not start with one */
|
||||
for (i = 0; i < count && i < JIT_SPIN_MAX; i++)
|
||||
{
|
||||
UINT16 op = ops[i];
|
||||
if ((op & 0xfd00) == 0x8900) /* BT or BF, no delay slot */
|
||||
return i > 0 && pc + i * 2 + 4 + (INT8)(op & 0xff) * 2 == pc;
|
||||
return (i > 0 && pc + i * 2 + 4 + (INT8)(op & 0xff) * 2 == pc) ? (int)i + 1 : 0;
|
||||
if (!jit_spin_op(op))
|
||||
return 0;
|
||||
}
|
||||
@@ -1971,7 +1973,9 @@ static void jit_spin_save(void)
|
||||
static void jit_spin_skip(const struct jit_block *block, int before)
|
||||
{
|
||||
int cost = before - sh2_icount, k;
|
||||
if (cost <= 0 || jit_spin_io || sh2.pc != block->pc || sh2.delay || sh2.test_irq
|
||||
/* only one turn of the loop itself: a block chained after it may come
|
||||
back to the start with the same registers, having done anything */
|
||||
if (cost != block->spincost || jit_spin_io || sh2.pc != block->pc || sh2.delay || sh2.test_irq
|
||||
|| memcmp(jit_spin_regs.r, sh2.r, sizeof(jit_spin_regs.r)) || jit_spin_regs.sr != sh2.sr
|
||||
|| jit_spin_regs.gbr != sh2.gbr || jit_spin_regs.mach != sh2.mach || jit_spin_regs.macl != sh2.macl
|
||||
|| jit_spin_regs.pr != sh2.pr)
|
||||
@@ -2000,6 +2004,7 @@ static void jit_compile(struct jit_block *block, UINT32 pc)
|
||||
block->entry = NULL;
|
||||
block->idle = 0;
|
||||
block->spin = 0;
|
||||
block->spincost = 0;
|
||||
block->op0 = jit_fetch(pc);
|
||||
|
||||
/* code must sit in one fast RAM region, below the special areas */
|
||||
@@ -2049,6 +2054,8 @@ static void jit_compile(struct jit_block *block, UINT32 pc)
|
||||
ctx.pre[i + 1] = ctx.pre[i] + dec[i].acct;
|
||||
cost += dec[i].cost;
|
||||
}
|
||||
/* the loop branch taken: 3 cycles */
|
||||
block->spincost = block->spin ? ctx.pre[block->spin - 1] + 3 : 0;
|
||||
|
||||
C = sljit_create_compiler(NULL);
|
||||
if (!C)
|
||||
|
||||
+12
-10
@@ -189,6 +189,9 @@ static UINT32 saved_cycles[MAX_CPU * 2];
|
||||
#define EXACT_PER_CPU 7
|
||||
static INT32 saved_exact[MAX_CPU * EXACT_PER_CPU];
|
||||
static INT32 saved_exact_globals[3];
|
||||
/* the triggers of cpu_spinuntil_time() and cpu_yielduntil_time(): numbered in
|
||||
turn, the number is in the state (the CPU waits on it, a timer pulls it) */
|
||||
static INT32 spin_timetrig, yield_timetrig;
|
||||
static int vblank;
|
||||
static int current_frame;
|
||||
static int vblank_countdown;
|
||||
@@ -363,6 +366,9 @@ int cpu_init(void)
|
||||
state_save_register_UINT32("cpu", 0, "totalcycles", saved_cycles, cpu_gettotalcpu() * 2);
|
||||
state_save_register_INT32("cpu", 0, "exact", saved_exact, cpu_gettotalcpu() * EXACT_PER_CPU);
|
||||
state_save_register_INT32("cpu", 0, "exact globals", saved_exact_globals, 3);
|
||||
spin_timetrig = yield_timetrig = 0;
|
||||
state_save_register_INT32("cpu", 0, "spin timetrig", &spin_timetrig, 1);
|
||||
state_save_register_INT32("cpu", 0, "yield timetrig", &yield_timetrig, 1);
|
||||
state_save_register_func_presave(cpu_suspend_presave);
|
||||
state_save_register_func_postload(cpu_suspend_postload);
|
||||
|
||||
@@ -1470,21 +1476,17 @@ void cpu_yield(void)
|
||||
|
||||
void cpu_spinuntil_time(double duration)
|
||||
{
|
||||
static int timetrig = 0;
|
||||
|
||||
cpu_spinuntil_trigger(TRIGGER_SUSPENDTIME + timetrig);
|
||||
cpu_triggertime(duration, TRIGGER_SUSPENDTIME + timetrig);
|
||||
timetrig = (timetrig + 1) & 255;
|
||||
cpu_spinuntil_trigger(TRIGGER_SUSPENDTIME + spin_timetrig);
|
||||
cpu_triggertime(duration, TRIGGER_SUSPENDTIME + spin_timetrig);
|
||||
spin_timetrig = (spin_timetrig + 1) & 255;
|
||||
}
|
||||
|
||||
|
||||
void cpu_yielduntil_time(double duration)
|
||||
{
|
||||
static int timetrig = 0;
|
||||
|
||||
cpu_yielduntil_trigger(TRIGGER_YIELDTIME + timetrig);
|
||||
cpu_triggertime(duration, TRIGGER_YIELDTIME + timetrig);
|
||||
timetrig = (timetrig + 1) & 255;
|
||||
cpu_yielduntil_trigger(TRIGGER_YIELDTIME + yield_timetrig);
|
||||
cpu_triggertime(duration, TRIGGER_YIELDTIME + yield_timetrig);
|
||||
yield_timetrig = (yield_timetrig + 1) & 255;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1286,6 +1286,15 @@ void *cpunum_get_context_ptr(int cpunum)
|
||||
return (cpu_active_context[cpu[cpunum].family] == cpunum) ? NULL : cpu[cpunum].context;
|
||||
}
|
||||
|
||||
/* the context buffer of a CPU, also from its init function (when the CPU
|
||||
does not count in totalcpu yet), whether it is active or not */
|
||||
void *cpunum_get_context_buffer(int cpunum)
|
||||
{
|
||||
if (cpunum < 0 || cpunum >= MAX_CPU)
|
||||
return NULL;
|
||||
return cpu[cpunum].context;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Get/set cycle table
|
||||
|
||||
@@ -636,6 +636,7 @@ void cpunum_write_bytes(int cpunum, offs_t address, const UINT8 *data, UINT32 co
|
||||
/* return a pointer to the saved context of a given CPU, or NULL if the
|
||||
context is active (and contained within the CPU core */
|
||||
void *cpunum_get_context_ptr(int cpunum);
|
||||
void *cpunum_get_context_buffer(int cpunum);
|
||||
|
||||
/* return a pointer to the active cycle count table for a given CPU */
|
||||
const void *cpunum_get_cycle_table(int cpunum, int which);
|
||||
|
||||
+11
-1
@@ -1,6 +1,7 @@
|
||||
#ifndef DECLARE
|
||||
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
|
||||
|
||||
#ifdef MSB_FIRST
|
||||
@@ -3516,11 +3517,20 @@ static INLINE void plotclip(struct mame_bitmap *bitmap,int x,int y,int pen,const
|
||||
plot_pixel(bitmap,x,y,pen);
|
||||
}
|
||||
|
||||
/* where each crosshair was and since which frame: in the save states, so a
|
||||
crosshair hides at the same frame after a load or a run-ahead rewind */
|
||||
static INT32 inactive_xy [MAX_PLAYER_COUNT][3];
|
||||
|
||||
void crosshair_state_save_register(void)
|
||||
{
|
||||
memset(inactive_xy, 0, sizeof(inactive_xy));
|
||||
state_save_register_INT32("crosshair", 0, "inactive", &inactive_xy[0][0], MAX_PLAYER_COUNT * 3);
|
||||
}
|
||||
|
||||
void draw_crosshair(int player_number, struct mame_bitmap *bitmap,int x,int y,const struct rectangle *clip)
|
||||
{
|
||||
unsigned long color,black,white;
|
||||
int i;
|
||||
static int inactive_xy [MAX_PLAYER_COUNT][3];
|
||||
|
||||
if (!options.crosshair_enable)
|
||||
{
|
||||
|
||||
@@ -272,6 +272,7 @@ void mdrawgfxzoom( struct mame_bitmap *dest_bmp,const struct GfxElement *gfx,
|
||||
|
||||
void drawgfx_toggle_crosshair(void);
|
||||
void draw_crosshair(int player_number, struct mame_bitmap *bitmap,int x,int y,const struct rectangle *clip);
|
||||
void crosshair_state_save_register(void);
|
||||
|
||||
static INLINE void sect_rect(struct rectangle *dst, const struct rectangle *src)
|
||||
{
|
||||
|
||||
+97
-21
@@ -156,6 +156,7 @@ int minit_boost,sinit_boost;
|
||||
|
||||
|
||||
static int scanline;
|
||||
static int scsp_last_line = 0; /* the SCSP interrupt level last raised on the 68000 */
|
||||
|
||||
|
||||
/**************************************************************************************/
|
||||
@@ -1863,23 +1864,70 @@ static void smpc_intback_continue(int param)
|
||||
smpc_ram[0x63] = 0x00;
|
||||
}
|
||||
|
||||
static void smpc_intback_resolve(int param)
|
||||
/*
|
||||
The RTC: the local date and time of the host when the machine started,
|
||||
moved on by the emulated time (not the host clock: a save state, the
|
||||
run-ahead and the netplay peers must read the same time)
|
||||
*/
|
||||
static INT32 smpc_rtc_days; /* days from 1970-01-01 */
|
||||
static INT32 smpc_rtc_secs; /* seconds of that day */
|
||||
|
||||
static INT32 smpc_days_from_civil(int y, int m, int d)
|
||||
{
|
||||
int era, yoe, doy, doe;
|
||||
y -= m <= 2;
|
||||
era = (y >= 0 ? y : y - 399) / 400;
|
||||
yoe = y - era * 400;
|
||||
doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
|
||||
doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
|
||||
return era * 146097 + doe - 719468;
|
||||
}
|
||||
|
||||
static void smpc_rtc_start(void)
|
||||
{
|
||||
time_t ltime;
|
||||
struct tm *today;
|
||||
time(<ime);
|
||||
today = localtime(<ime);
|
||||
smpc_rtc_days = smpc_days_from_civil(today->tm_year + 1900, today->tm_mon + 1, today->tm_mday);
|
||||
smpc_rtc_secs = today->tm_hour * 3600 + today->tm_min * 60 + today->tm_sec;
|
||||
}
|
||||
|
||||
static void smpc_rtc_fill(void)
|
||||
{
|
||||
double now = timer_get_time();
|
||||
INT32 total = smpc_rtc_secs + (INT32)now;
|
||||
INT32 days = smpc_rtc_days + total / 86400;
|
||||
INT32 secs = total % 86400;
|
||||
int era, doe, yoe, y, doy, mp, d, m;
|
||||
|
||||
/* civil from days (H. Hinnant) */
|
||||
days += 719468;
|
||||
era = (days >= 0 ? days : days - 146096) / 146097;
|
||||
doe = days - era * 146097;
|
||||
yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
y = yoe + era * 400;
|
||||
doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
mp = (5 * doy + 2) / 153;
|
||||
d = doy - (153 * mp + 2) / 5 + 1;
|
||||
m = mp + (mp < 10 ? 3 : -9);
|
||||
y += m <= 2;
|
||||
|
||||
smpc_ram[0x23] = DectoBCD(y / 100);
|
||||
smpc_ram[0x25] = DectoBCD(y % 100);
|
||||
smpc_ram[0x27] = (((days - 719468 + 4) % 7) << 4) | m; /* 1970-01-01 was a Thursday */
|
||||
smpc_ram[0x29] = DectoBCD(d);
|
||||
smpc_ram[0x2b] = DectoBCD(secs / 3600);
|
||||
smpc_ram[0x2d] = DectoBCD((secs / 60) % 60);
|
||||
smpc_ram[0x2f] = DectoBCD(secs % 60);
|
||||
}
|
||||
|
||||
static void smpc_intback_resolve(int param)
|
||||
{
|
||||
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_rtc_fill();
|
||||
smpc_ram[0x31]=0x00;
|
||||
smpc_ram[0x35]=0x00;
|
||||
smpc_ram[0x37]=0x00;
|
||||
@@ -3850,15 +3898,47 @@ static READ32_HANDLER( stv_cart_unmapped_r )
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
/* the state of the board around the CPUs: SMPC, SCU (its registers, the
|
||||
interrupts, the DSP), the I/O chip and the sound CPU control */
|
||||
static void stv_state_save_register(void)
|
||||
{
|
||||
state_save_register_UINT8 ("stv", 0, "smpc_ram", smpc_ram, 0x80);
|
||||
state_save_register_UINT8 ("stv", 0, "smpc_sr", &smpc_sr, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "smpc_intback_stage", &smpc_intback_stage, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "smpc_intback_buf", smpc_intback_buf, 3);
|
||||
state_save_register_UINT8 ("stv", 0, "smpc_pmode", &smpc_pmode, 1);
|
||||
state_save_register_INT32 ("stv", 0, "smpc_rtc_days", &smpc_rtc_days, 1);
|
||||
state_save_register_INT32 ("stv", 0, "smpc_rtc_secs", &smpc_rtc_secs, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "IOSEL1", &IOSEL1, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "IOSEL2", &IOSEL2, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "EXLE1", &EXLE1, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "EXLE2", &EXLE2, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "PDR1", &PDR1, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "PDR2", &PDR2, 1);
|
||||
state_save_register_UINT32("stv", 0, "scu", stv_scu, 0x100 / 4);
|
||||
state_save_register_UINT32("stv", 0, "scu_ist", &scu_ist, 1);
|
||||
state_save_register_int ("stv", 0, "scu_irq_level", &scu_irq_level);
|
||||
state_save_register_int ("stv", 0, "scu_irq_vector", &scu_irq_vector);
|
||||
state_save_register_int ("stv", 0, "scu_timer0_count", &scu_timer0_count);
|
||||
state_save_register_int ("stv", 0, "slave_irl", &slave_irl);
|
||||
state_save_register_UINT8 ("stv", 0, "port_sel", &port_sel, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "mux_data", &mux_data, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "ioga_mode", &ioga_mode, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "ioga_portg", &ioga_portg, 1);
|
||||
state_save_register_UINT16("stv", 0, "ioga_count", ioga_count, 2);
|
||||
state_save_register_int ("stv", 0, "hopper_power", &hopper_power);
|
||||
state_save_register_int ("stv", 0, "hopper_status", &hopper_status);
|
||||
state_save_register_UINT8 ("stv", 0, "SCSP_reset", &SCSP_reset, 1);
|
||||
state_save_register_UINT8 ("stv", 0, "en_68k", &en_68k, 1);
|
||||
state_save_register_int ("stv", 0, "scsp_last_line", &scsp_last_line);
|
||||
scudsp_state_save_register();
|
||||
stvcd_state_save_register();
|
||||
}
|
||||
|
||||
DRIVER_INIT ( stv )
|
||||
{
|
||||
unsigned char *ROM = memory_region(REGION_USER1);
|
||||
|
||||
time_t ltime;
|
||||
struct tm *today;
|
||||
time(<ime);
|
||||
today = localtime(<ime);
|
||||
|
||||
cpu_setbank(1,&ROM[0x000000]);
|
||||
stv_hopper = 0;
|
||||
stv_critcrsh = 0;
|
||||
@@ -3880,6 +3960,8 @@ DRIVER_INIT ( stv )
|
||||
cpu_setbank(4,&stv_workram_l[0x000000]);
|
||||
cpu_setbank(5,&stv_backupram[0x000000]);
|
||||
|
||||
stv_state_save_register();
|
||||
|
||||
/* 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);
|
||||
@@ -3915,13 +3997,8 @@ DRIVER_INIT ( stv )
|
||||
install_mem_write32_handler(1, 0x60ffc44, 0x60ffc47, w60ffc44_write );
|
||||
install_mem_write32_handler(1, 0x60ffc48, 0x60ffc4b, w60ffc48_write );
|
||||
|
||||
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_rtc_start();
|
||||
smpc_rtc_fill();
|
||||
smpc_ram[0x31] = 0x00; /*CTG1=0 CTG0=0 (correct??)*/
|
||||
/* smpc_ram[0x33] = readinputport(7);*/
|
||||
smpc_ram[0x5f] = 0x10;
|
||||
@@ -4009,7 +4086,6 @@ static data16_t stv_opcode_read(offs_t pc)
|
||||
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;
|
||||
|
||||
/* the SCSP raises and drops each level on its own (a negative level drops it);
|
||||
0 drops the last raised level, as in current MAME */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
#include "machine/scudsp.h"
|
||||
#include "cpu/sh2/sh2.h"
|
||||
|
||||
@@ -270,6 +271,55 @@ static UINT32 dsp_get_mem_source_dma( UINT32 memcode, UINT32 counter )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the save state: the 48-bit MUL and ALU go as two 32-bit halves */
|
||||
static UINT32 dsp_ss_mul[2], dsp_ss_alu[2];
|
||||
|
||||
static void scudsp_presave(void)
|
||||
{
|
||||
dsp_ss_mul[0] = (UINT32)(dsp_reg.mul >> 32);
|
||||
dsp_ss_mul[1] = (UINT32)dsp_reg.mul;
|
||||
dsp_ss_alu[0] = (UINT32)(dsp_reg.alu >> 32);
|
||||
dsp_ss_alu[1] = (UINT32)dsp_reg.alu;
|
||||
}
|
||||
|
||||
static void scudsp_postload(void)
|
||||
{
|
||||
dsp_reg.mul = ((UINT64)dsp_ss_mul[0] << 32) | dsp_ss_mul[1];
|
||||
dsp_reg.alu = ((UINT64)dsp_ss_alu[0] << 32) | dsp_ss_alu[1];
|
||||
}
|
||||
|
||||
void scudsp_state_save_register(void)
|
||||
{
|
||||
state_save_register_UINT8 ("scudsp", 0, "pc", &dsp_reg.pc, 1);
|
||||
state_save_register_UINT8 ("scudsp", 0, "delay", &dsp_reg.delay, 1);
|
||||
state_save_register_UINT8 ("scudsp", 0, "top", &dsp_reg.top, 1);
|
||||
state_save_register_UINT16("scudsp", 0, "lop", &dsp_reg.lop, 1);
|
||||
state_save_register_UINT8 ("scudsp", 0, "ct0", &dsp_reg.ct0, 1);
|
||||
state_save_register_UINT8 ("scudsp", 0, "ct1", &dsp_reg.ct1, 1);
|
||||
state_save_register_UINT8 ("scudsp", 0, "ct2", &dsp_reg.ct2, 1);
|
||||
state_save_register_UINT8 ("scudsp", 0, "ct3", &dsp_reg.ct3, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "md0", dsp_reg.md0, 0x40);
|
||||
state_save_register_UINT32("scudsp", 0, "md1", dsp_reg.md1, 0x40);
|
||||
state_save_register_UINT32("scudsp", 0, "md2", dsp_reg.md2, 0x40);
|
||||
state_save_register_UINT32("scudsp", 0, "md3", dsp_reg.md3, 0x40);
|
||||
state_save_register_UINT8 ("scudsp", 0, "ra", &dsp_reg.ra, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "rx", &dsp_reg.rx, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "mul", dsp_ss_mul, 2);
|
||||
state_save_register_UINT32("scudsp", 0, "ry", &dsp_reg.ry, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "alu", dsp_ss_alu, 2);
|
||||
state_save_register_UINT16("scudsp", 0, "ph", &dsp_reg.ph, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "pl", &dsp_reg.pl, 1);
|
||||
state_save_register_UINT16("scudsp", 0, "ach", &dsp_reg.ach, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "acl", &dsp_reg.acl, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "ra0", &dsp_reg.ra0, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "wa0", &dsp_reg.wa0, 1);
|
||||
state_save_register_UINT32("scudsp", 0, "internal_prg", dsp_reg.internal_prg, 0x100);
|
||||
state_save_register_UINT32("scudsp", 0, "opcode", &opcode, 1);
|
||||
state_save_register_UINT8 ("scudsp", 0, "update_mul", &update_mul, 1);
|
||||
state_save_register_func_presave(scudsp_presave);
|
||||
state_save_register_func_postload(scudsp_postload);
|
||||
}
|
||||
|
||||
void dsp_prg_ctrl(UINT32 data)
|
||||
{
|
||||
if(LEF) dsp_reg.pc = (data & 0xff);
|
||||
|
||||
@@ -6,6 +6,7 @@ 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);
|
||||
extern void scudsp_state_save_register(void);
|
||||
|
||||
/* raise an SCU interrupt source (bit of the status register), drivers/stv.c */
|
||||
extern void stv_scu_raise_irq(int bit);
|
||||
@@ -12,6 +12,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
#include "machine/stvcd.h"
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1065,3 +1066,96 @@ void CD_com_update(UINT32 count){
|
||||
}
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "CD block update\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The save state of the CD block: its registers and the state of the
|
||||
commands. ST-V has no CD drive (Sports Fishing 2 needs one and isn't
|
||||
dumped completely): the games only reach the registers, so the sector
|
||||
buffer and the disc are left out. The info transfer pointer goes as
|
||||
the buffer it points into.
|
||||
*/
|
||||
static INT32 cd_ss_info_buf;
|
||||
|
||||
static void stvcd_presave(void)
|
||||
{
|
||||
if (CD_info_ptr == CD_sat_toc) cd_ss_info_buf = 1;
|
||||
else if (CD_info_ptr == CD_sat_subq) cd_ss_info_buf = 2;
|
||||
else if (CD_info_ptr == CD_sat_subrw) cd_ss_info_buf = 3;
|
||||
else if (CD_info_ptr == cdb_sat_file_info) cd_ss_info_buf = 4;
|
||||
else cd_ss_info_buf = 0;
|
||||
}
|
||||
|
||||
static void stvcd_postload(void)
|
||||
{
|
||||
switch (cd_ss_info_buf)
|
||||
{
|
||||
case 1: CD_info_ptr = CD_sat_toc; break;
|
||||
case 2: CD_info_ptr = CD_sat_subq; break;
|
||||
case 3: CD_info_ptr = CD_sat_subrw; break;
|
||||
case 4: CD_info_ptr = cdb_sat_file_info; break;
|
||||
default: CD_info_ptr = NULL; break;
|
||||
}
|
||||
}
|
||||
|
||||
void stvcd_state_save_register(void)
|
||||
{
|
||||
state_save_register_UINT8 ("stvcd", 0, "cr_first", &CD_cr_first, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "cr_writing", &CD_cr_writing, 1);
|
||||
state_save_register_UINT16("stvcd", 0, "CR1", &CR1, 1);
|
||||
state_save_register_UINT16("stvcd", 0, "CR2", &CR2, 1);
|
||||
state_save_register_UINT16("stvcd", 0, "CR3", &CR3, 1);
|
||||
state_save_register_UINT16("stvcd", 0, "CR4", &CR4, 1);
|
||||
state_save_register_UINT16("stvcd", 0, "hirq", &CD_hirq, 1);
|
||||
state_save_register_UINT16("stvcd", 0, "hirq_i", &CD_hirq_i, 1);
|
||||
state_save_register_UINT16("stvcd", 0, "mask", &CD_mask, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "status", &CD_status, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "fad", &CD_fad, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "track", &CD_track, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "control", &CD_control, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "index", &CD_index, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "fn", &fn, 1);
|
||||
state_save_register_INT32 ("stvcd", 0, "com", &CD_com, 1);
|
||||
state_save_register_INT32 ("stvcd", 0, "com_play", &CD_com_play, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "stat", &CD_stat, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "flag", &CD_flag, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "last_part", &CD_last_part, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "play_fad", &CD_play_fad, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "play_range", &CD_play_range, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "seek_target", &CD_seek_target, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "scan_dir", &CD_scan_dir, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "search_pn", &CD_search_pn, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "search_sp", &CD_search_sp, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "search_fad", &CD_search_fad, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "file_scope_first", &CD_file_scope_first, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "file_scope_last", &CD_file_scope_last, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "data_pn", &CD_data_pn, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "data_sp", &CD_data_sp, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "data_sn", &CD_data_sn, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "data_count", &CD_data_count, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "data_delete", &CD_data_delete, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "data_size", &CD_data_size, 1);
|
||||
state_save_register_INT32 ("stvcd", 0, "info_buf", &cd_ss_info_buf, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "info_count", &CD_info_count, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "info_size", &CD_info_size, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "trans_type", &CD_trans_type, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "actual_size", &CD_actual_size, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "free_space", &CD_free_space, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "filt_num", &CD_filt_num, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "mpeg_filt_num", &CD_mpeg_filt_num, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "cur_fad", &CD_cur_fad, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "cur_track", &CD_cur_track, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "cur_ctrl", &CD_cur_ctrl, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "cur_idx", &CD_cur_idx, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "cur_fid", &CD_cur_fid, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "init_flag", &CD_init_flag, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "repeat", &CD_repeat, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "standby", &CD_standby, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "repeat_max", &CD_repeat_max, 1);
|
||||
state_save_register_UINT8 ("stvcd", 0, "ecc", &CD_ecc, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "drive_speed", &CD_drive_speed, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "get_sect_size", &cdb_get_sect_size, 1);
|
||||
state_save_register_UINT32("stvcd", 0, "put_sect_size", &cdb_put_sect_size, 1);
|
||||
state_save_register_func_presave(stvcd_presave);
|
||||
state_save_register_func_postload(stvcd_postload);
|
||||
}
|
||||
@@ -245,3 +245,5 @@ extern UINT32 CD_drive_speed; /* 0 = noop, 1 = 1x, 2 = 2x*/
|
||||
|
||||
extern UINT8 cdda_buff[8192]; /* CD-DA buffer for SCSP communication*/
|
||||
extern UINT32 cdda_pos;
|
||||
|
||||
void stvcd_state_save_register(void);
|
||||
+10
-1
@@ -259,7 +259,8 @@ int memory_init(void)
|
||||
if (!populate_ports())
|
||||
return 0;
|
||||
|
||||
register_banks();
|
||||
/* the banks are registered for the save states by memory_register_banks(),
|
||||
after the driver init: a driver often points them at its own RAM there */
|
||||
|
||||
#ifdef MEM_DUMP
|
||||
/* dump the final memory configuration */
|
||||
@@ -3136,3 +3137,11 @@ static void verify_masks(void)
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "mame-memory: Busted entries that are static = %d\n", static_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* the save state entries of the memory banks, once the driver init has
|
||||
pointed them where it wants them (see memory_init) */
|
||||
void memory_register_banks(void)
|
||||
{
|
||||
register_banks();
|
||||
}
|
||||
@@ -370,6 +370,10 @@ static int init_machine(void)
|
||||
if (gamedrv->driver_init)
|
||||
(*gamedrv->driver_init)();
|
||||
|
||||
/* the memory banks in the save states, where the driver init left them */
|
||||
memory_register_banks();
|
||||
crosshair_state_save_register();
|
||||
|
||||
return 0;
|
||||
|
||||
cant_init_memory:
|
||||
|
||||
@@ -808,6 +808,7 @@ DECLARE_PORT_HANDLERS_32BIT_LE(32)
|
||||
int memory_init(void);
|
||||
void memory_shutdown(void);
|
||||
void memory_set_context(int activecpu);
|
||||
void memory_register_banks(void);
|
||||
void memory_set_unmap_value(data32_t value);
|
||||
|
||||
/* ----- dynamic bank handlers ----- */
|
||||
|
||||
@@ -404,7 +404,17 @@ static void SCSP_StartSlot(struct _SLOT *slot)
|
||||
static void SCSP_StopSlot(struct _SLOT *slot,int keyoff)
|
||||
{
|
||||
if(keyoff)
|
||||
{
|
||||
slot->EG.state=RELEASE;
|
||||
/* a slot that already stopped (a one-shot sample past its end) no longer
|
||||
updates its envelope: its release is over at once. Left at the level
|
||||
it stopped at, the monitor (0x408) showed it as still sounding, the
|
||||
sound drivers took it for busy and, after a while, put every new note
|
||||
on the one slot left (the Cotton Boomerang boss music lost all but the
|
||||
drums, the Winter Heat voices cut each other from the first demo on) */
|
||||
if(!slot->active)
|
||||
slot->EG.volume=0;
|
||||
}
|
||||
else
|
||||
slot->active=0;
|
||||
slot->udata.data[0]&=~0x800;
|
||||
|
||||
@@ -3093,6 +3093,11 @@ VIDEO_START( model2 )
|
||||
state_save_register_float( "model2video", 0, "texture_parameters", &m_geo->texture_parameters[ 0 ].diffuse, sizeof( m_geo->texture_parameters ) / ( sizeof( float ) ) ); /* all 32-bit fields */
|
||||
state_save_register_UINT32( "model2video", 0, "polygon_ram0", m_geo->polygon_ram0, 0x8000 );
|
||||
state_save_register_UINT32( "model2video", 0, "polygon_ram1", m_geo->polygon_ram1, 0x8000 );
|
||||
/* the polygons of the last display list: their count is read by the games
|
||||
(model2_polygon_count_r); the list itself has been drawn when the frame
|
||||
ends, the next display list starts a new one */
|
||||
state_save_register_UINT32( "model2video", 0, "poly_list_index", &m_raster->poly_list_index, 1 );
|
||||
state_save_register_int( "model2video", 0, "render_done", &m_render_done );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2909,6 +2909,16 @@ static int vdp1_start(void)
|
||||
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);
|
||||
/* the clipping set by the command lists: a list without clipping
|
||||
commands keeps the last one */
|
||||
state_save_register_int("stv_vdp1", 0, "system_clip_min_x", &vdp1.system_cliprect.min_x);
|
||||
state_save_register_int("stv_vdp1", 0, "system_clip_max_x", &vdp1.system_cliprect.max_x);
|
||||
state_save_register_int("stv_vdp1", 0, "system_clip_min_y", &vdp1.system_cliprect.min_y);
|
||||
state_save_register_int("stv_vdp1", 0, "system_clip_max_y", &vdp1.system_cliprect.max_y);
|
||||
state_save_register_int("stv_vdp1", 0, "user_clip_min_x", &vdp1.user_cliprect.min_x);
|
||||
state_save_register_int("stv_vdp1", 0, "user_clip_max_x", &vdp1.user_cliprect.max_x);
|
||||
state_save_register_int("stv_vdp1", 0, "user_clip_min_y", &vdp1.user_cliprect.min_y);
|
||||
state_save_register_int("stv_vdp1", 0, "user_clip_max_y", &vdp1.user_cliprect.max_y);
|
||||
state_save_register_func_postload(vdp1_state_save_postload);
|
||||
return 0;
|
||||
}
|
||||
@@ -10695,7 +10705,10 @@ static void crtc_regs_w(int offset, UINT16 data, UINT16 mem_mask)
|
||||
|
||||
static void crtc_state_save_postload(void)
|
||||
{
|
||||
/* the resolution again, not a resolution change: the field is the saved one */
|
||||
int odd_bit = crtc.odd_bit;
|
||||
crtc_reconfigure();
|
||||
crtc.odd_bit = odd_bit;
|
||||
}
|
||||
|
||||
static void crtc_start(void)
|
||||
@@ -10727,6 +10740,9 @@ static void crtc_start(void)
|
||||
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);
|
||||
/* the current line and when it started: the H and V counters */
|
||||
state_save_register_int("stv_crtc", 0, "line", &crtc_line);
|
||||
state_save_register_double("stv_crtc", 0, "line_time", &crtc_line_time, 1);
|
||||
state_save_register_func_postload(crtc_state_save_postload);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user