[PATCH] Add savestate handling

Some notes to consider:
- consider this wip. some vars might not be necessary.
- only for C68K cpu core
- minimally tested. it works on HD files, and multi-disks but have not
  tested on anything that switches to another disk yet or drive letter.
- M3U/CMD platlist format is necessary to keep track of what content the
  state is for (filename for .statex tracking for example). Switching
  disk or switching to another game through ingame menu will break
  currently loaded state.
- in core is use to run in content-less mode, the savestate will be
  universal or system state (PX68K.state) and will not be based on what
  content is loaded.
- MIDI: Loading patchsets and other midi params from a state file is not
  implemented. It may take a while to refresh instruments sets until
  next time MIDI sends new data. Its also required that only load a
  state after selecting the correct MIDI device from the ingame menu.
- requires new px68k_libretro.info file, with savestate support enabled
This commit is contained in:
libretroadmin committed 2024-09-09 04:11:18 +02:00
1 parent 7dd315c624
commit 3bb967da25
60 files changed
+1614 -47

No files matched your search

+2
View File
@@ -69,6 +69,7 @@ SOURCES_C += \
$(CORE_DIR)/libretro/dosio.c \
$(CORE_DIR)/libretro/fake.c \
$(CORE_DIR)/libretro/peace.c \
$(CORE_DIR)/libretro/state.c \
$(CORE_DIR)/libretro.c
SOURCES_CXX += \
@@ -84,6 +85,7 @@ SOURCES_C += \
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
$(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
$(LIBRETRO_COMM_DIR)/compat/compat_snprintf.c \
$(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
$(LIBRETRO_COMM_DIR)/file/file_path.c \
+2 -1
View File
@@ -426,7 +426,8 @@ WARNINGS :=
FLAGS += -D__LIBRETRO__ $(ENDIANNESS_DEFINES) $(WARNINGS) $(fpic)
CXXFLAGS += $(FLAGS) $(CPU_FLAGS) -fpermissive
CFLAGS += $(FLAGS) -std=c99 $(CPU_FLAGS) -D_GNU_SOURCE
#CFLAGS += $(FLAGS) -std=c99 $(CPU_FLAGS) -D_GNU_SOURCE
CFLAGS += $(FLAGS) $(CPU_FLAGS)
$(TARGET): $(OBJECTS)
ifeq ($(STATIC_LINKING), 1)
+30 -3
View File
@@ -21,10 +21,15 @@ public:
virtual ~MyOPM() {}
void WriteIO(uint32_t adr, uint8_t data);
void Count2(uint32_t clock);
private:
virtual void Intr(bool);
public:
int CurReg;
uint32_t CurCount;
int StateAction(StateMem *sm, int load, int data_only);
};
@@ -33,6 +38,22 @@ MyOPM::MyOPM()
CurReg = 0;
}
int MyOPM::StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVARN(CurReg, "CurReg"),
SFVARN(CurCount, "CurCount"),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "MYOPM", false);
ret &= FM::OPM::StateAction(sm, load, data_only);
return(1);
}
void MyOPM::WriteIO(uint32_t adr, uint8_t data)
{
if( adr&1 )
@@ -52,7 +73,6 @@ void MyOPM::Intr(bool f)
if ( f ) ::MFP_Int(12);
}
void MyOPM::Count2(uint32_t clock)
{
CurCount += clock;
@@ -60,9 +80,16 @@ void MyOPM::Count2(uint32_t clock)
CurCount %= 10;
}
static MyOPM* opm = NULL;
int OPM_StateAction(StateMem *sm, int load, int data_only)
{
if (opm)
return opm->StateAction(sm, load, data_only);
return 1;
}
int OPM_Init(int clock)
{
opm = new MyOPM();
@@ -121,7 +148,7 @@ void OPM_SetVolume(uint8_t vol)
// ----------------------------------------------------------
// ---------------------------- YMF288 (満開版ま~きゅり~)
// ---------------------------- YMF288 (満開版ま~きゅり~)
// ----------------------------------------------------------
// TODO : ROMEOの288を叩くの
+1
View File
@@ -11,6 +11,7 @@ void FASTCALL OPM_Write(uint32_t r, uint8_t v);
uint8_t FASTCALL OPM_Read(void);
void FASTCALL OPM_Timer(uint32_t step);
void OPM_SetVolume(uint8_t vol);
int OPM_StateAction(StateMem *sm, int load, int data_only);
int M288_Init(int clock, const char* path);
void M288_Cleanup(void);
+107 -1
View File
@@ -222,6 +222,26 @@ void MakeLFOTable()
}
}
//
//
//
int Chip::StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT ChipStateRegs[] =
{
SFVAR(ratio_),
SFVAR(aml_),
SFVAR(pml_),
SFVAR(pmv_),
SFVAR(optype_),
SFARRAY32(multable_, 4 * 16),
SFEND
};
return PX68KSS_StateAction(sm, load, data_only, ChipStateRegs, "CHIP", false);
}
// ---------------------------------------------------------------------------
// チップ内で共通な部分
@@ -266,6 +286,60 @@ bool FM::Operator::tablehasmade = false;
uint32_t FM::Operator::sinetable[1024];
int32_t FM::Operator::cltable[FM_CLENTS];
int Operator::StateAction(StateMem *sm, int load, int data_only, const char *sname)
{
SFORMAT StateRegs[] =
{
SFVAR(out_),
SFVAR(out2_),
SFVAR(dp_),
SFVAR(detune_),
SFVAR(detune2_),
SFVAR(multiple_),
SFVAR(pg_count_),
SFVAR(pg_diff_),
SFVAR(pg_diff_lfo_),
SFVAR(type_),
SFVAR(bn_),
SFVAR(eg_level_),
SFVAR(eg_level_on_next_phase_),
SFVAR(eg_count_),
SFVAR(eg_count_diff_),
SFVAR(eg_out_),
SFVAR(tl_out_),
SFVAR(eg_rate_),
SFVAR(eg_curve_count_),
SFVAR(ssg_offset_),
SFVAR(ssg_vector_),
SFVAR(ssg_phase_),
SFVAR(key_scale_rate_),
SFVAR(eg_phase_),
SFVAR(ms_),
SFVAR(tl_),
SFVAR(tl_latch_),
SFVAR(ar_),
SFVAR(dr_),
SFVAR(sr_),
SFVAR(sl_),
SFVAR(rr_),
SFVAR(ks_),
SFVAR(ssg_type_),
SFVAR(keyon_),
SFVAR(amon_),
SFVAR(param_changed_),
SFVAR(mute_),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, sname, false);
if (load)
ams_ = amtable[type_][amon_ ? (ms_ >> 4) & 3 : 0];
return ret;
}
// 構築
FM::Operator::Operator()
: chip_(0)
@@ -681,7 +755,6 @@ int Channel4::kftable[64];
bool Channel4::tablehasmade = false;
Channel4::Channel4()
{
if (!tablehasmade)
@@ -691,6 +764,39 @@ Channel4::Channel4()
pms = pmtable[0][0];
}
int Channel4::StateAction(StateMem *sm, int load, int data_only, const char *sname)
{
SFORMAT StateRegs[] =
{
SFVAR(fb),
SFVAR(algo_),
SFARRAY32(buf, 4),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, sname, false);
for (int i = 0; i < 4; i++)
{
char tmpstr[10] = "x";
char tmpstr2[5] = "OPx";
tmpstr2[2] = '0' + i;
strcpy(tmpstr, sname);
strcat(tmpstr, tmpstr2);
ret &= op[i].StateAction(sm, load, data_only, tmpstr);
}
if (load)
{
SetAlgorithm(algo_);
pms = pmtable[op[0].type_][op[0].ms_ & 7];
}
return ret;
}
void Channel4::MakeTable()
{
// 100/64 cent = 2^(i*100/64*1200)
+12 -5
View File
@@ -32,7 +32,8 @@ namespace FM
// Types ----------------------------------------------------------------
typedef int32_t ISample;
enum OpType { TYPE_N = 0, TYPE_M = 1 };
enum OpType { TYPE_N = 0, TYPE_M = 1 };
enum EGPhase { NEXT, ATTACK, DECAY, SUSTAIN, RELEASE, OFF };
void StoreSample(ISample& dest, int data);
@@ -75,6 +76,9 @@ namespace FM
void Mute(bool);
int Out() { return out_; }
int StateAction(StateMem *sm, int load, int data_only, const char *sname);
private:
Chip* chip_;
ISample out_, out2_;
@@ -92,8 +96,6 @@ namespace FM
int32_t pg_diff_lfo_; // Phase 差分値 >> x
// Envelop Generator ---------------------------------------------------
enum EGPhase { NEXT, ATTACK, DECAY, SUSTAIN, RELEASE, OFF };
void EGCalc();
void EGStep();
void ShiftPhase(EGPhase nextphase);
@@ -101,7 +103,7 @@ namespace FM
void SetEGRate(uint32_t);
void EGUpdate();
ISample LogToLin(uint32_t a);
OpType type_; // OP の種類 (M, N...)
uint32_t bn_; // Block/Note
int eg_level_; // EG の出力値
@@ -182,6 +184,8 @@ namespace FM
void SetMS(uint32_t ms);
void Mute(bool);
int StateAction(StateMem *mem, int load, int data_only, const char *sname);
private:
static const uint8_t fbtable[8];
uint32_t fb;
@@ -189,8 +193,9 @@ namespace FM
int* in[3]; // 各 OP の入力ポインタ
int* out[3]; // 各 OP の出力ポインタ
int* pms;
int algo_;
Chip* chip_;
int algo_;
static void MakeTable();
@@ -218,6 +223,8 @@ namespace FM
int GetPMV() { return pmv_; }
uint32_t GetRatio() { return ratio_; }
int StateAction(StateMem *sm, int load, int data_pnly);
private:
void MakeTable();
+21
View File
@@ -10,6 +10,27 @@
using namespace FM;
int Timer::StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(status),
SFVAR(regtc),
SFVARN(regta[0], "regta0"),
SFVARN(regta[1], "regta1"),
SFVAR(timera),
SFVAR(timera_count),
SFVAR(timerb),
SFVAR(timerb_count),
SFVAR(timer_step),
SFEND
};
return PX68KSS_StateAction(sm, load, data_only, StateRegs, "TIMER", false);
}
// ---------------------------------------------------------------------------
// タイマー制御
//
+4 -2
View File
@@ -16,6 +16,7 @@ namespace FM
public:
void Reset();
bool Count(int32_t us);
int StateAction(StateMem *st, int load, int data_only);
protected:
virtual void SetStatus(uint32_t bit) = 0;
@@ -25,12 +26,13 @@ namespace FM
void SetTimerA(uint32_t addr, uint32_t data);
void SetTimerB(uint32_t data);
void SetTimerControl(uint32_t data);
uint8_t status;
uint8_t regtc;
private:
virtual void TimerA() {}
uint8_t regta[2];
int32_t timera, timera_count;
+53
View File
@@ -29,6 +29,59 @@ OPM::OPM()
}
}
int OPM::StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT OPMStateRegs[] =
{
SFVAR(fmvolume),
SFVAR(clock),
SFVAR(rate),
SFVAR(pmd),
SFVAR(amd),
SFVAR(lfocount),
SFVAR(lfodcount),
SFVAR(lfo_count_),
SFVAR(lfo_count_diff_),
SFVAR(lfo_step_),
SFVAR(lfo_count_prev_),
SFVAR(lfowaveform),
SFVAR(rateratio),
SFVAR(noise),
SFVAR(noisecount),
SFVAR(noisedelta),
SFVAR(lfofreq),
SFVAR(status),
SFVAR(reg01),
SFARRAY(kc, 8),
SFARRAY(kf, 8),
SFARRAY(pan, 8),
SFEND
};
int ret = Timer::StateAction(sm, load, data_only);
ret &= PX68KSS_StateAction(sm, load, data_only, OPMStateRegs, "OPM", false);
ret &= ch[0].StateAction(sm, load, data_only, "SCH0");
ret &= ch[1].StateAction(sm, load, data_only, "SCH1");
ret &= ch[2].StateAction(sm, load, data_only, "SCH2");
ret &= ch[3].StateAction(sm, load, data_only, "SCH3");
ret &= ch[4].StateAction(sm, load, data_only, "SCH4");
ret &= ch[5].StateAction(sm, load, data_only, "SCH5");
ret &= ch[6].StateAction(sm, load, data_only, "SCH6");
ret &= ch[7].StateAction(sm, load, data_only, "SCH7");
ret &= chip.StateAction(sm, load, data_only);
return ret;
}
// ---------------------------------------------------------------------------
// 初期化
//
+2
View File
@@ -33,6 +33,8 @@ namespace FM
void SetVolume(int db);
void SetChannelMask(uint32_t mask);
int StateAction(StateMem *sm, int load, int data_only);
private:
virtual void Intr(bool) {}
+121 -6
View File
@@ -781,12 +781,12 @@ static int WinX68k_Init(void)
MEM = (uint8_t*)malloc(MEM_SIZE);
FONT = (uint8_t*)malloc(0xc0000);
if (MEM)
if (MEM)
memset(MEM, 0, MEM_SIZE);
if (MEM && FONT && IPL)
{
m68000_init();
/* m68000_init(); */
return 1;
}
return 0;
@@ -976,12 +976,17 @@ static int pmain(int argc, char *argv[])
StatBar_Show(Config.WindowFDDStat);
WinUI_Init();
#if 0
/* TODO: CLean this up */
if (!WinX68k_Init())
{
WinX68k_Cleanup();
WinDraw_Cleanup();
return 1;
}
#endif
m68000_init();
if (!WinX68k_LoadROMs())
{
@@ -995,7 +1000,10 @@ static int pmain(int argc, char *argv[])
WinDraw_Init();
ADPCM_Init();
#if 0
/* TODO: CLean this up */
OPM_Init(4000000/*3579545*/);
#endif
#ifndef NO_MERCURY
Mcry_Init(winx68k_dir);
#endif
@@ -1093,7 +1101,7 @@ run_pmain:
if (PARAMCOUNT)
xargv_cmd[PARAMCOUNT - 2] = NULL;
return 0;
}
@@ -1558,9 +1566,108 @@ static void setup_frame_time_cb(void)
}
/* TODO/FIXME - implement savestates */
size_t retro_serialize_size(void) { return 0; }
bool retro_serialize(void *data, size_t size) { return false; }
bool retro_unserialize(const void *data, size_t size) { return false; }
int StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAYN(MEM, MEM_SIZE, "RAM"),
SFARRAYN(SRAM, 16384, "SRAM"),
SFVAR(ICount),
SFVAR(ClkUsed),
SFVAR(VLINE),
SFVAR(VLINE_TOTAL),
SFVAR(tick),
SFVAR(timercnt),
SFEND
};
int ret = 0, count = 0;
ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "MAIN", false);
ret &= m68000_StateAction(sm, load, data_only);
ret &= GVRAM_StateAction(sm, load, data_only);
ret &= TVRAM_StateAction(sm, load, data_only);
ret &= CRTC_StateAction(sm, load, data_only);
ret &= Pal_StateAction(sm, load, data_only);
ret &= BG_StateAction(sm, load, data_only);
ret &= DMAC_StateAction(sm, load, data_only);
ret &= MFP_StateAction(sm, load, data_only);
ret &= IRQH_StateAction(sm, load, data_only);
ret &= SCC_StateAction(sm, load, data_only);
ret &= FDC_StateAction(sm, load, data_only);
ret &= FDD_StateAction(sm, load, data_only);
ret &= SASI_StateAction(sm, load, data_only);
ret &= RTC_StateAction(sm, load, data_only);
ret &= PIA_StateAction(sm, load, data_only);
ret &= SysPort_StateAction(sm, load, data_only);
ret &= IOC_StateAction(sm, load, data_only);
ret &= SRAM_StateAction(sm, load, data_only);
/* sound-related states */
ret &= dswin_StateAction(sm, load, data_only);
ret &= ADPCM_StateAction(sm, load, data_only);
ret &= MIDI_StateAction(sm, load, data_only);
ret &= OPM_StateAction(sm, load, data_only);
return ret;
}
size_t retro_serialize_size(void)
{
StateMem st;
st.data = NULL;
st.loc = 0;
st.len = 0;
st.malloced = 0;
st.initial_malloc = 0;
if (!PX68KSS_SaveSM(&st, 0, 0, NULL, NULL, NULL))
return 0;
free(st.data);
return st.len;
}
bool retro_serialize(void *data, size_t size)
{
StateMem st;
bool ret = false;
uint8_t *_dat = (uint8_t*)malloc(size);
if (!_dat)
return false;
st.data = _dat;
st.loc = 0;
st.len = 0;
st.malloced = size;
st.initial_malloc = 0;
ret = PX68KSS_SaveSM(&st, 0, 0, NULL, NULL, NULL);
memcpy(data, st.data, size);
free(st.data);
return ret;
}
bool retro_unserialize(const void *data, size_t size)
{
StateMem st;
st.data = (uint8_t*)data;
st.loc = 0;
st.len = size;
st.malloced = 0;
st.initial_malloc = 0;
return PX68KSS_LoadSM(&st, 0, 0);
}
/* TODO/FIXME - implement cheats */
void retro_cheat_reset(void) { }
@@ -1582,6 +1689,14 @@ bool retro_load_game(const struct retro_game_info *info)
return false;
}
/* alloc memory pointers */
if (!WinX68k_Init())
return false;
/* alloc OPM-related pointers */
if (!OPM_Init(4000000/*3579545*/))
return false;
return true;
}
+3
View File
@@ -8,6 +8,9 @@
#include <libretro.h>
extern retro_log_printf_t log_cb;
#include "state.h"
#include "state_inline.h"
#undef FASTCALL
#define FASTCALL
+14
View File
@@ -41,6 +41,20 @@ uint8_t *pbsp = pcmbuffer;
uint8_t *pbrp = pcmbuffer, *pbwp = pcmbuffer;
uint8_t *pbep = &pcmbuffer[PCMBUF_SIZE];
int dswin_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(snd_precounter),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_DSND", false);
return ret;
}
void DSound_Play(void)
{
ADPCM_SetVolume((uint8_t)Config.PCM_VOL);
+1
View File
@@ -10,5 +10,6 @@ void DSound_Send0(int32_t clock);
int audio_samples_avail(void);
void audio_samples_discard(int discard);
void raudio_callback(void *userdata, unsigned char *stream, int len);
int dswin_StateAction(StateMem *sm, int load, int data_only);
#endif /* _DSWIN_H */
+519
View File
@@ -0,0 +1,519 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <boolean.h>
#include <retro_inline.h>
#include <compat/msvc.h>
#include <compat/strl.h>
#include "common.h"
#include "state.h"
#define SSEEK_END 2
#define SSEEK_CUR 1
#define SSEEK_SET 0
#define RLSB PX68KSTATE_RLSB //0x80000000
/* Forward declaration */
int StateAction(StateMem *sm, int load, int data_only);
static INLINE void PX68K_en32lsb(uint8_t *buf, uint32_t morp)
{
buf[0]=morp;
buf[1]=morp>>8;
buf[2]=morp>>16;
buf[3]=morp>>24;
}
static INLINE uint32_t PX68K_de32lsb(const uint8_t *morp)
{
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
}
#ifdef MSB_FIRST
static INLINE void Endian_A64_Swap(void *src, uint32_t nelements)
{
uint32_t i;
uint8_t *nsrc = (uint8_t *)src;
for(i = 0; i < nelements; i++)
{
unsigned z;
uint8_t *base = &nsrc[i * 8];
for(z = 0; z < 4; z++)
{
uint8_t tmp = base[z];
base[z] = base[7 - z];
base[7 - z] = tmp;
}
}
}
static INLINE void Endian_A32_Swap(void *src, uint32_t nelements)
{
uint32_t i;
uint8_t *nsrc = (uint8_t *)src;
for(i = 0; i < nelements; i++)
{
uint8_t tmp1 = nsrc[i * 4];
uint8_t tmp2 = nsrc[i * 4 + 1];
nsrc[i * 4] = nsrc[i * 4 + 3];
nsrc[i * 4 + 1] = nsrc[i * 4 + 2];
nsrc[i * 4 + 2] = tmp2;
nsrc[i * 4 + 3] = tmp1;
}
}
void Endian_A16_Swap(void *src, uint32_t nelements)
{
uint32_t i;
uint8_t *nsrc = (uint8_t *)src;
for(i = 0; i < nelements; i++)
{
uint8_t tmp = nsrc[i * 2];
nsrc[i * 2] = nsrc[i * 2 + 1];
nsrc[i * 2 + 1] = tmp;
}
}
static INLINE void FlipByteOrder(uint8_t *src, uint32_t count)
{
uint8_t *start=src;
uint8_t *end=src+count-1;
if((count&1) || !count)
return; /* This shouldn't happen. */
count >>= 1;
while(count--)
{
uint8_t tmp;
tmp=*end;
*end=*start;
*start=tmp;
end--;
start++;
}
}
#endif
static int32_t smem_read(StateMem *st, void *buffer, uint32_t len)
{
if ((len + st->loc) > st->len)
return 0;
memcpy(buffer, st->data + st->loc, len);
st->loc += len;
return(len);
}
static int32_t smem_write(StateMem *st, void *buffer, uint32_t len)
{
if ((len + st->loc) > st->malloced)
{
uint32_t newsize = (st->malloced >= 32768) ? st->malloced : (st->initial_malloc ? st->initial_malloc : 32768);
while(newsize < (len + st->loc))
newsize *= 2;
st->data = (uint8_t *)realloc(st->data, newsize);
st->malloced = newsize;
}
memcpy(st->data + st->loc, buffer, len);
st->loc += len;
if (st->loc > st->len)
st->len = st->loc;
return(len);
}
static int32_t smem_seek(StateMem *st, uint32_t offset, int whence)
{
switch(whence)
{
case SSEEK_SET:
st->loc = offset;
break;
case SSEEK_END:
st->loc = st->len - offset;
break;
case SSEEK_CUR:
st->loc += offset;
break;
}
if(st->loc > st->len)
{
st->loc = st->len;
return(-1);
}
return(0);
}
static int smem_write32le(StateMem *st, uint32_t b)
{
uint8_t s[4];
s[0]=b;
s[1]=b>>8;
s[2]=b>>16;
s[3]=b>>24;
return((smem_write(st, s, 4)<4)?0:4);
}
static int smem_read32le(StateMem *st, uint32_t *b)
{
uint8_t s[4];
if(smem_read(st, s, 4) < 4)
return(0);
*b = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
return(4);
}
static bool SubWrite(StateMem *st, SFORMAT *sf)
{
/* Size can sometimes be zero, so also check for the text name.
* These two should both be zero only at the end of a struct. */
while(sf->size || sf->name)
{
int32_t bytesize;
char nameo[1 + 256];
if(!sf->size || !sf->v)
{
sf++;
continue;
}
/* Link to another struct. */
if(sf->size == (uint32_t)~0)
{
if(!SubWrite(st, (SFORMAT *)sf->v))
return(0);
sf++;
continue;
}
bytesize = sf->size;
nameo[0] = strlcpy(nameo + 1, sf->name, 256);
smem_write(st, nameo, 1 + nameo[0]);
smem_write32le(st, bytesize);
#ifdef MSB_FIRST
/* Flip the byte order... */
if(sf->flags & PX68KSTATE_BOOL) { }
else if(sf->flags & PX68KSTATE_RLSB64)
Endian_A64_Swap(sf->v, bytesize / sizeof(uint64_t));
else if(sf->flags & PX68KSTATE_RLSB32)
Endian_A32_Swap(sf->v, bytesize / sizeof(uint32_t));
else if(sf->flags & PX68KSTATE_RLSB16)
Endian_A16_Swap(sf->v, bytesize / sizeof(uint16_t));
else if(sf->flags & RLSB)
FlipByteOrder((uint8_t*)sf->v, bytesize);
#endif
/* Special case for the evil bool type,
* to convert bool to 1-byte elements.
* Don't do it if we're only saving the raw data. */
if(sf->flags & PX68KSTATE_BOOL)
{
int32_t bool_monster;
for (bool_monster = 0; bool_monster < bytesize; bool_monster++)
{
uint8_t tmp_bool = ((bool *)sf->v)[bool_monster];
smem_write(st, &tmp_bool, 1);
}
}
else
smem_write(st, (uint8_t *)sf->v, bytesize);
#ifdef MSB_FIRST
/* Now restore the original byte order. */
if(sf->flags & PX68KSTATE_BOOL)
{
}
else if(sf->flags & PX68KSTATE_RLSB64)
Endian_A64_Swap(sf->v, bytesize / sizeof(uint64_t));
else if(sf->flags & PX68KSTATE_RLSB32)
Endian_A32_Swap(sf->v, bytesize / sizeof(uint32_t));
else if(sf->flags & PX68KSTATE_RLSB16)
Endian_A16_Swap(sf->v, bytesize / sizeof(uint16_t));
else if(sf->flags & RLSB)
FlipByteOrder((uint8_t*)sf->v, bytesize);
#endif
sf++;
}
return true;
}
static int WriteStateChunk(StateMem *st, const char *sname, SFORMAT *sf)
{
int32_t data_start_pos;
int32_t end_pos;
uint8_t sname_tmp[32];
size_t sname_len = strlen(sname);
memset(sname_tmp, 0, sizeof(sname_tmp));
memcpy((char *)sname_tmp, sname, (sname_len < 32) ? sname_len : 32);
smem_write(st, sname_tmp, 32);
smem_write32le(st, 0); // We'll come back and write this later.
data_start_pos = st->loc;
if(!SubWrite(st, sf))
return(0);
end_pos = st->loc;
smem_seek(st, data_start_pos - 4, SSEEK_SET);
smem_write32le(st, end_pos - data_start_pos);
smem_seek(st, end_pos, SSEEK_SET);
return(end_pos - data_start_pos);
}
static SFORMAT *FindSF(const char *name, SFORMAT *sf)
{
/* Size can sometimes be zero, so also check for the text name.
* These two should both be zero only at the end of a struct. */
while(sf->size || sf->name)
{
if(!sf->size || !sf->v)
{
sf++;
continue;
}
/* Link to another SFORMAT structure. */
if (sf->size == (uint32_t)~0)
{
SFORMAT *temp_sf = FindSF(name, (SFORMAT*)sf->v);
if (temp_sf)
return temp_sf;
}
else
{
if (!strcmp(sf->name, name))
return sf;
}
sf++;
}
return NULL;
}
static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size)
{
int temp = st->loc;
while (st->loc < (temp + size))
{
/* Don't change to char unless cast
* toa[0] to unsigned to smem_read()
* and other places. */
uint8_t toa[1 + 256];
uint32_t recorded_size = 0; /* In bytes */
SFORMAT *tmp = NULL;
if(smem_read(st, toa, 1) != 1)
return(0);
if(smem_read(st, toa + 1, toa[0]) != toa[0])
return 0;
toa[1 + toa[0]] = 0;
smem_read32le(st, &recorded_size);
tmp = FindSF((char*)toa + 1, sf);
if(tmp)
{
uint32_t expected_size = tmp->size; /* In bytes */
if(recorded_size != expected_size)
{
if(smem_seek(st, recorded_size, SSEEK_CUR) < 0)
return(0);
}
else
{
smem_read(st, (uint8_t *)tmp->v, expected_size);
if(tmp->flags & PX68KSTATE_BOOL)
{
int32_t bool_monster;
/* Converting downwards is necessary
* for the case of sizeof(bool) > 1 */
for(bool_monster = expected_size - 1; bool_monster >= 0; bool_monster--)
((bool *)tmp->v)[bool_monster] = ((uint8_t *)tmp->v)[bool_monster];
}
#ifdef MSB_FIRST
if(tmp->flags & PX68KSTATE_RLSB64)
Endian_A64_Swap(tmp->v, expected_size / sizeof(uint64_t));
else if(tmp->flags & PX68KSTATE_RLSB32)
Endian_A32_Swap(tmp->v, expected_size / sizeof(uint32_t));
else if(tmp->flags & PX68KSTATE_RLSB16)
Endian_A16_Swap(tmp->v, expected_size / sizeof(uint16_t));
else if(tmp->flags & RLSB)
FlipByteOrder((uint8_t*)tmp->v, expected_size);
#endif
}
}
else
{
if(smem_seek(st, recorded_size, SSEEK_CUR) < 0)
return(0);
}
}
return 1;
}
static int PX68KSS_StateAction_internal(StateMem *st, int load, int data_only,
struct SSDescriptor *section)
{
if(load)
{
char sname[32];
uint32_t tmp_size = 0;
int found = 0;
uint32_t total = 0;
while(smem_read(st, (uint8_t *)sname, 32) == 32)
{
if(smem_read32le(st, &tmp_size) != 4)
{
return(0);
}
total += tmp_size + 32 + 4;
// Yay, we found the section
if(!strncmp(sname, section->name, 32))
{
if(!ReadStateChunk(st, section->sf, tmp_size))
{
return(0);
}
found = 1;
break;
}
else
{
if(smem_seek(st, tmp_size, SSEEK_CUR) < 0)
{
return(0);
}
}
}
if(smem_seek(st, -total, SSEEK_CUR) < 0)
{
return(0);
}
if(!found) // Not found. We are sad!
{
return(0);
}
}
else
{
if(!WriteStateChunk(st, section->name, section->sf))
return(0);
}
return(1);
}
int PX68KSS_StateAction(void *st_p, int load, int data_only, SFORMAT *sf, const char *name, bool optional)
{
struct SSDescriptor love;
StateMem *st = (StateMem*)st_p;
love.sf = sf;
love.name = name;
return PX68KSS_StateAction_internal(st, load, 0, &love);
}
int PX68KSS_SaveSM(void *st_p, int a, int b, const void*c, const void*d, const void*e)
{
uint32_t sizy;
uint8_t header[32];
StateMem *st = (StateMem*)st_p;
static const char *header_magic = "PX68KSVST";
memset(header, 0, sizeof(header));
memcpy(header, header_magic, 9);
PX68K_en32lsb(header + 16, PX68K_VERSION_NUMERIC);
smem_write(st, header, 32);
if(!StateAction(st, 0, 0))
return(0);
sizy = st->loc;
smem_seek(st, 16 + 4, SSEEK_SET);
smem_write32le(st, sizy);
return(1);
}
int PX68KSS_LoadSM(void *st_p, int a, int b)
{
uint8_t header[32];
uint32_t stateversion;
StateMem *st = (StateMem*)st_p;
smem_read(st, header, 32);
if(memcmp(header, "PX68KSVESTATE", 13) && memcmp(header, "PX68KSVST", 9))
return(0);
stateversion = PX68K_de32lsb(header + 16);
return(StateAction(st, stateversion, 0));
}
+69
View File
@@ -0,0 +1,69 @@
#ifndef _STATE_H
#define _STATE_H
#include <stdint.h>
#include <boolean.h>
#include <retro_inline.h>
#define PX68K_VERSION_MAJOR 0
#define PX68K_VERSION_MINOR 15
#define PX68K_VERSION_PATCH 0
#define PX68K_VERSION_NUMERIC ((PX68K_VERSION_MAJOR * 10000) + (PX68K_VERSION_MINOR * 100) + (PX68K_VERSION_PATCH))
typedef struct
{
uint8_t *data;
uint32_t loc;
uint32_t len;
uint32_t malloced;
uint32_t initial_malloc; /* A setting! */
} StateMem;
#ifdef __cplusplus
extern "C" {
#endif
int PX68KSS_SaveSM(void *st, int, int, const void*, const void*, const void*);
int PX68KSS_LoadSM(void *st, int, int);
/* Flag for a single, >= 1 byte native-endian variable */
#define PX68KSTATE_RLSB 0x80000000
/* 32-bit native-endian elements */
#define PX68KSTATE_RLSB32 0x40000000
/* 16-bit native-endian elements */
#define PX68KSTATE_RLSB16 0x20000000
/* 64-bit native-endian elements */
#define PX68KSTATE_RLSB64 0x10000000
#define PX68KSTATE_BOOL 0x08000000
typedef struct
{
void *v; /* Pointer to the variable/array */
uint32_t size; /* Length, in bytes, of the data to be saved EXCEPT:
* In the case of PX68KSTATE_BOOL, it is the number
* of bool elements to save(bool is not always 1-byte).
*
* If 0, the subchunk isn't saved.
*/
uint32_t flags; /* Flags */
const char *name; /* Name */
} SFORMAT;
/* State-Section Descriptor */
struct SSDescriptor
{
SFORMAT *sf;
const char *name;
};
int PX68KSS_StateAction(void *st, int load, int data_only, SFORMAT *sf, const char *name, bool optional);
#ifdef __cplusplus
}
#endif
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef _STATE_IN_HPP
#define _STATE_IN_HPP
#define SFVARN_BOOL(x, n) { &(x), 1, PX68KSTATE_RLSB | PX68KSTATE_BOOL, n }
#define SFVARN(x, n) { &(x), (uint32_t)sizeof(x), PX68KSTATE_RLSB, n }
#define SFVAR(x) SFVARN((x), #x)
#define SFARRAYN(x, l, n) { (x), (uint32_t)(l), 0, n }
#define SFARRAY(x, l) SFARRAYN((x), (l), #x)
#define SFARRAY16N(x, l, n) { (x), (uint32_t)((l) * sizeof(uint16_t)), PX68KSTATE_RLSB16, n }
#define SFARRAY16(x, l) SFARRAY16N((x), (l), #x)
#define SFARRAY32N(x, l, n) { (x), (uint32_t)((l) * sizeof(uint32_t)), PX68KSTATE_RLSB32, n }
#define SFARRAY32(x, l) SFARRAY32N((x), (l), #x)
#define SFARRAY64N(x, l, n) { (x), (uint32_t)((l) * sizeof(uint64_t)), PX68KSTATE_RLSB64, n }
#define SFARRAY64(x, l) SFARRAY64N((x), (l), #x)
#define SFEND { 0, 0, 0, 0 }
#endif
+2 -2
View File
@@ -5,7 +5,8 @@
#include "crtc.h"
#include "mfp.h"
static uint32_t tick = 0;
uint32_t tick = 0;
uint32_t timercnt = 0;
/* Get elapsed time from libretro frontend by way of its frame time callback,
* if available. Only provides per frame granularity, enough for this case
@@ -27,7 +28,6 @@ void Timer_Init(void)
uint16_t Timer_GetCount(void)
{
static uint32_t timercnt = 0;
uint32_t ticknow = timeGetUsec();
uint32_t dif = ticknow-tick;
uint32_t TIMEBASE = ((CRTC_Regs[0x29]&0x10)?VSYNC_HIGH:VSYNC_NORM);
+3
View File
@@ -1,6 +1,9 @@
#ifndef _WINXL_TIMER_H
#define _WINXL_TIMER_H
extern uint32_t tick;
extern uint32_t timercnt;
void Timer_Init(void);
uint16_t Timer_GetCount(void);
+57
View File
@@ -22,6 +22,63 @@ struct Cyclone m68k;
int m68000_ICountBk;
int ICount;
int m68000_StateAction(StateMem *sm, int load, int data_only)
{
int ret = 0;
uint32_t pc = 0;
SFORMAT StateRegs[] =
{
SFVARN(C68K.D[0], "D0"),
SFVARN(C68K.D[1], "D1"),
SFVARN(C68K.D[2], "D2"),
SFVARN(C68K.D[3], "D3"),
SFVARN(C68K.D[4], "D4"),
SFVARN(C68K.D[5], "D5"),
SFVARN(C68K.D[6], "D6"),
SFVARN(C68K.D[7], "D7"),
SFVARN(C68K.A[0], "A0"),
SFVARN(C68K.A[1], "A1"),
SFVARN(C68K.A[2], "A2"),
SFVARN(C68K.A[3], "A3"),
SFVARN(C68K.A[4], "A4"),
SFVARN(C68K.A[5], "A5"),
SFVARN(C68K.A[6], "A6"),
SFVARN(C68K.A[7], "A7"),
SFVARN(C68K.flag_C, "flag_C"),
SFVARN(C68K.flag_V, "flag_V"),
SFVARN(C68K.flag_notZ, "flag_notZ"),
SFVARN(C68K.flag_X, "flag_X"),
SFVARN(C68K.flag_I, "flag_I"),
SFVARN(C68K.flag_S, "flag_S"),
SFVARN(C68K.USP, "USP"),
SFVARN(pc, "PC"),
SFVARN(C68K.Status, "status"),
SFVARN(C68K.IRQLine, "IRQLine"),
SFVARN(C68K.CycleToDo, "CycleToDo"),
SFVARN(C68K.CycleIO, "CycleIO"),
SFVARN(C68K.CycleSup, "CycleSup"),
SFVARN(C68K.dirty1, "dirtyflag"),
SFEND
};
if (!load)
pc = m68000_get_reg(M68K_PC);
ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_CPU", false);
if (load)
m68000_set_reg(M68K_PC, pc);
return ret;
}
#if defined (HAVE_CYCLONE)
unsigned int read8(unsigned int a) {
+1
View File
@@ -42,6 +42,7 @@ int m68000_execute(int cycles);
void m68000_set_irq_line(int irqline, int state);
uint32_t m68000_get_reg(int regnum);
void m68000_set_reg(int regnum, uint32_t val);
int m68000_StateAction(StateMem *sm, int load, int data_only);
#ifdef SAVE_STATE
STATE_SAVE( m68000 );
+39
View File
@@ -59,6 +59,45 @@ static int OutsIp[4];
static int OutsIpR[4];
static int OutsIpL[4];
int ADPCM_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
/* TODO: Some of the vars might not be necessary */
SFARRAY16(ADPCM_BufL, 96000),
SFARRAY16(ADPCM_BufR, 96000),
SFVAR(ADPCM_VolumeShift),
SFVAR(ADPCM_WrPtr),
SFVAR(ADPCM_RdPtr),
SFVAR(ADPCM_ClockRate),
SFVAR(ADPCM_Count),
SFVAR(ADPCM_Step),
SFVAR(ADPCM_Out),
SFVAR(ADPCM_Playing),
SFVAR(ADPCM_Clock),
SFVAR(ADPCM_PreCounter),
SFVAR(ADPCM_DifBuf),
SFVAR(ADPCM_Pan),
SFVAR(OldR),
SFVAR(OldL),
SFARRAY32(Outs, 8),
SFARRAY32(OutsIp, 4),
SFARRAY32(OutsIpR, 4),
SFARRAY32(OutsIpL, 4),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_ADPC", false);
return ret;
}
static void ADPCM_InitTable(void)
{
int step, n;
+1
View File
@@ -14,5 +14,6 @@ void ADPCM_SetPan(int n);
void ADPCM_SetClock(int n);
void ADPCM_Init(void);
int ADPCM_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_ADPCM_H */
+38
View File
@@ -34,6 +34,44 @@ uint16_t BG_PriBuf[1600];
uint32_t VLINEBG = 0;
int BG_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAY(BG, 0x8000),
SFARRAY(Sprite_Regs, 0x800),
SFARRAY(BG_Regs, 0x12),
SFVAR(BG_CHREND),
SFVAR(BG_BG0TOP),
SFVAR(BG_BG0END),
SFVAR(BG_BG1TOP),
SFVAR(BG_BG1END),
SFVAR(BG_CHRSIZE),
SFVAR(BG_AdrMask),
SFVAR(BG0ScrollX),
SFVAR(BG0ScrollY),
SFVAR(BG1ScrollX),
SFVAR(BG1ScrollY),
SFARRAY(BGCHR8, (8 * 8 * 256)),
SFARRAY(BGCHR16, (16 * 16 * 256)),
SFARRAY16(BG_PriBuf, 1600),
SFARRAY16(BG_LineBuf, 1600),
SFVAR(BG_HAdjust),
SFVAR(BG_VLINE),
SFVAR(VLINEBG),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_BG", false);
return ret;
}
void BG_Init(void)
{
uint32_t i;
+2
View File
@@ -21,4 +21,6 @@ void FASTCALL BG_Write(uint32_t adr, uint8_t data);
void FASTCALL BG_DrawLine(int opaq, int gd);
int BG_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_BG_H */
+39
View File
@@ -37,6 +37,45 @@ uint8_t CRTC_RCFlag[2] = {0, 0};
int HSYNC_CLK = 324;
extern int VID_MODE, CHANGEAV_TIMING;
int CRTC_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAY(CRTC_Regs, 48),
SFVAR(CRTC_Mode),
SFVAR(TextDotX),
SFVAR(TextDotY),
SFVAR(CRTC_VSTART),
SFVAR(CRTC_VEND),
SFVAR(CRTC_HSTART),
SFVAR(CRTC_HEND),
SFVAR(TextScrollX),
SFVAR(TextScrollY),
SFARRAY32(GrphScrollX, 4),
SFARRAY32(GrphScrollY, 4),
SFVAR(CRTC_FastClr),
SFVAR(CRTC_FastClrMask),
SFVAR(CRTC_IntLine),
SFVAR(CRTC_VStep),
SFARRAY(CRTC_RCFlag, 2),
SFVAR(HSYNC_CLK),
/* video control regs */
SFARRAY(VCReg0, 2),
SFARRAY(VCReg1, 2),
SFARRAY(VCReg2, 2),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_CRTC_VCTRL", false);
return ret;
}
void CRTC_RasterCopy(void)
{
uint32_t line = (((uint32_t)CRTC_Regs[0x2d])<<2);
+1
View File
@@ -36,5 +36,6 @@ void FASTCALL CRTC_Write(uint32_t adr, uint8_t data);
uint8_t FASTCALL VCtrl_Read(uint32_t adr);
void FASTCALL VCtrl_Write(uint32_t adr, uint8_t data);
int CRTC_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_CRTC_H */
+113 -22
View File
@@ -24,6 +24,97 @@ static uint32_t FASTCALL DMA_Int(uint8_t irq);
DMA[ch].CCR &= 0x7f; \
DMAINT(ch)
int DMAC_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVARN(DMA[0].CSR, "CSR0"),
SFVARN(DMA[0].CER, "CER0"),
SFVARN(DMA[0].DCR, "DCR0"),
SFVARN(DMA[0].OCR, "OCR0"),
SFVARN(DMA[0].SCR, "SCR0"),
SFVARN(DMA[0].CCR, "CCR0"),
SFVARN(DMA[0].MTC, "MTC0"),
SFVARN(DMA[0].MAR, "MAR0"),
SFVARN(DMA[0].DAR, "DAR0"),
SFVARN(DMA[0].BTC, "BTC0"),
SFVARN(DMA[0].BAR, "BAR0"),
SFVARN(DMA[0].NIV, "NIV0"),
SFVARN(DMA[0].EIV, "EIV0"),
SFVARN(DMA[0].MFC, "MFC0"),
SFVARN(DMA[0].CPR, "CPR0"),
SFVARN(DMA[0].DFC, "DFC0"),
SFVARN(DMA[0].BFC, "BFC0"),
SFVARN(DMA[0].GCR, "GCR0"),
SFVARN(DMA[1].CSR, "CSR1"),
SFVARN(DMA[1].CER, "CER1"),
SFVARN(DMA[1].DCR, "DCR1"),
SFVARN(DMA[1].OCR, "OCR1"),
SFVARN(DMA[1].SCR, "SCR1"),
SFVARN(DMA[1].CCR, "CCR1"),
SFVARN(DMA[1].MTC, "MTC1"),
SFVARN(DMA[1].MAR, "MAR1"),
SFVARN(DMA[1].DAR, "DAR1"),
SFVARN(DMA[1].BTC, "BTC1"),
SFVARN(DMA[1].BAR, "BAR1"),
SFVARN(DMA[1].NIV, "NIV1"),
SFVARN(DMA[1].EIV, "EIV1"),
SFVARN(DMA[1].MFC, "MFC1"),
SFVARN(DMA[1].CPR, "CPR1"),
SFVARN(DMA[1].DFC, "DFC1"),
SFVARN(DMA[1].BFC, "BFC1"),
SFVARN(DMA[1].GCR, "GCR1"),
SFVARN(DMA[2].CSR, "CSR2"),
SFVARN(DMA[2].CER, "CER2"),
SFVARN(DMA[2].DCR, "DCR2"),
SFVARN(DMA[2].OCR, "OCR2"),
SFVARN(DMA[2].SCR, "SCR2"),
SFVARN(DMA[2].CCR, "CCR2"),
SFVARN(DMA[2].MTC, "MTC2"),
SFVARN(DMA[2].MAR, "MAR2"),
SFVARN(DMA[2].DAR, "DAR2"),
SFVARN(DMA[2].BTC, "BTC2"),
SFVARN(DMA[2].BAR, "BAR2"),
SFVARN(DMA[2].NIV, "NIV2"),
SFVARN(DMA[2].EIV, "EIV2"),
SFVARN(DMA[2].MFC, "MFC2"),
SFVARN(DMA[2].CPR, "CPR2"),
SFVARN(DMA[2].DFC, "DFC2"),
SFVARN(DMA[2].BFC, "BFC2"),
SFVARN(DMA[2].GCR, "GCR2"),
SFVARN(DMA[3].CSR, "CSR3"),
SFVARN(DMA[3].CER, "CER3"),
SFVARN(DMA[3].DCR, "DCR3"),
SFVARN(DMA[3].OCR, "OCR3"),
SFVARN(DMA[3].SCR, "SCR3"),
SFVARN(DMA[3].CCR, "CCR3"),
SFVARN(DMA[3].MTC, "MTC3"),
SFVARN(DMA[3].MAR, "MAR3"),
SFVARN(DMA[3].DAR, "DAR3"),
SFVARN(DMA[3].BTC, "BTC3"),
SFVARN(DMA[3].BAR, "BAR3"),
SFVARN(DMA[3].NIV, "NIV3"),
SFVARN(DMA[3].EIV, "EIV3"),
SFVARN(DMA[3].MFC, "MFC3"),
SFVARN(DMA[3].CPR, "CPR3"),
SFVARN(DMA[3].DFC, "DFC3"),
SFVARN(DMA[3].BFC, "BFC3"),
SFVARN(DMA[3].GCR, "GCR3"),
SFVAR(DMA_IntCH),
SFVAR(DMA_LastInt),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_DMAC", false);
return ret;
}
static int ADPCM_IsReady(void) { return 1; }
static int DMA_DummyIsReady(void) { return 0; }
@@ -63,7 +154,7 @@ uint8_t FASTCALL DMA_Read(uint32_t adr)
int ch = (adr >> 6) & 0x03;
if (adr >= 0xe84100)
return 0; /* 真真真 */
return 0;
switch (off)
{
@@ -146,7 +237,7 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
uint8_t old = 0;
if (adr >= 0xe84100)
return; /* 真真真 */
return;
switch (off)
{
@@ -172,7 +263,7 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
case 0x07:
old = DMA[ch].CCR;
DMA[ch].CCR = (data & 0xef) | (DMA[ch].CCR & 0x80); /* CCR�STR真真真真真真 */
DMA[ch].CCR = (data & 0xef) | (DMA[ch].CCR & 0x80); /* CCR STR cannot be dropped by writing */
if ((data & 0x10) && (DMA[ch].CCR & 0x80))
{
/* Software Abort */
@@ -181,16 +272,16 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
}
if (data & 0x20) /* Halt */
{
/* 真真真真�Nemesis'90真真真真 */
/* Should be correct, but Nemesis'90 will not work properly with it so... */
/* DMA[ch].CSR &= 0xf7; */
break;
}
if (data & 0x80)
{
/* 真真 */
/* Start DMA */
if (old & 0x20)
{
/* Halt真 */
/* Halt release */
DMA[ch].CSR |= 0x08;
DMA_Exec(ch);
}
@@ -198,14 +289,14 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
{
if (DMA[ch].CSR & 0xf8)
{
/* 真真真真 */
/* Timing errors */
DMAERR(ch, 0x02)
break;
}
DMA[ch].CSR |= 0x08;
if ((DMA[ch].OCR & 8) /*&&(!DMA[ch].MTC)*/)
{
/* 真真真真真真真 */
/* Array/Link Array Chain */
DMA[ch].MAR = dma_readmem24_dword(DMA[ch].BAR) & 0xffffff;
DMA[ch].MTC = dma_readmem24_word(DMA[ch].BAR + 4);
if (DMA[ch].OCR & 4)
@@ -217,7 +308,7 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
DMA[ch].BAR += 6;
if (!DMA[ch].BTC)
{
/* 真真真真真 */
/* This is also a counting error */
DMAERR(ch, 0x0f)
break;
}
@@ -225,12 +316,12 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
}
if (!DMA[ch].MTC)
{
/* 真真真� */
/* Counting error */
DMAERR(ch, 0x0d)
break;
}
DMA[ch].CER = 0x00;
DMA_Exec(ch); /* 真真真真真真真真真真真真真真真真真真真 */
DMA_Exec(ch); /* Since you may need to check the counter immediately after starting, run it for a little while. */
}
}
if ((data & 0x40) && (!DMA[ch].MTC))
@@ -244,7 +335,7 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
}
else if (DMA[ch].OCR & 8)
{
/* 真真真真真真真 */
/* Array/Link Array Chain */
DMAERR(ch, 0x01)
}
else
@@ -256,7 +347,7 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
DMA[ch].BTC = 0;
if (!DMA[ch].MAR)
{
DMA[ch].CSR |= 0x40; /* 真真真真真真真真 ? */
DMA[ch].CSR |= 0x40; /* Block transfer end bit/interrupt? */
DMAINT(ch)
break;
}
@@ -271,7 +362,7 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data)
}
else
{
/* �Active真CNT真真真真真真真 */
/* The CNT bit in non-active mode indicates an operation timing error */
DMAERR(ch, 0x02)
}
}
@@ -463,9 +554,9 @@ int FASTCALL DMA_Exec(int ch)
}
DMA[ch].MTC--;
if ( !DMA[ch].MTC ) { /* 指定分のバイト数転送終了 */
if ( DMA[ch].OCR&8 ) { /* チェインモードで動いている場合 */
if ( DMA[ch].OCR&4 ) { /* リンクアレイチェイン */
if ( !DMA[ch].MTC ) { /* Transfer of specified number of bytes completed */
if ( DMA[ch].OCR&8 ) { /* If running in chained mode */
if ( DMA[ch].OCR&4 ) { /* If running in chained mode */
if ( DMA[ch].BAR ) {
DMA[ch].MAR = dma_readmem24_dword(DMA[ch].BAR);
DMA[ch].MTC = dma_readmem24_word(DMA[ch].BAR+4);
@@ -482,9 +573,9 @@ int FASTCALL DMA_Exec(int ch)
break;
}
}
} else { /* アレイチェイン */
} else { /* Array chain */
DMA[ch].BTC--;
if ( DMA[ch].BTC ) { /* 次のブロックがある */
if ( DMA[ch].BTC ) { /* Next block exists */
DMA[ch].MAR = dma_readmem24_dword(DMA[ch].BAR);
DMA[ch].MTC = dma_readmem24_word(DMA[ch].BAR+4);
DMA[ch].BAR += 6;
@@ -501,9 +592,9 @@ int FASTCALL DMA_Exec(int ch)
}
}
}
} else { /* 通常モード(1ブロックのみ)終了 */
if ( DMA[ch].CCR&0x40 ) { /* Countinuous動作中 */
DMA[ch].CSR |= 0x40; /* ブロック転送終了ビット/割り込み */
} else { /* Normal mode (only one block) finished */
if ( DMA[ch].CCR&0x40 ) { /* Countinuous action */
DMA[ch].CSR |= 0x40; /* Block transfer end bit/interrupt */
DMAINT(ch)
if ( DMA[ch].BAR ) {
DMA[ch].MAR = DMA[ch].BAR;
+1
View File
@@ -45,5 +45,6 @@ void FASTCALL DMA_Write(uint32_t adr, uint8_t data);
int FASTCALL DMA_Exec(int ch);
void DMA_Init(void);
int DMAC_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_DMAC_H */
+34
View File
@@ -84,6 +84,40 @@ typedef struct {
static FDC fdc;
int FDC_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(fdc.cmd),
SFVAR(fdc.cyl),
SFVAR(fdc.drv),
SFVAR(fdc.ready),
SFVAR(fdc.ctrl),
SFVAR(fdc.wexec),
SFVAR(fdc.rdptr),
SFVAR(fdc.wrptr),
SFVAR(fdc.rdnum),
SFVAR(fdc.wrnum),
SFVAR(fdc.bufnum),
SFVAR(fdc.st0),
SFVAR(fdc.st1),
SFVAR(fdc.st2),
SFARRAY(fdc.RspBuf, 10),
SFARRAY(fdc.PrmBuf, 10),
SFARRAY(fdc.DataBuf, 0x8000),
SFARRAY(fdc.ScanBuf, 0x8000),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_FDC", false);
return ret;
}
#define US(p) (p->us&3)
#define HD(p) ((p->us>>2)&1)
+1
View File
@@ -10,5 +10,6 @@ void FASTCALL FDC_Write(uint32_t adr, uint8_t data);
int16_t FDC_Flush(void);
void FDC_SetForceReady(int n);
int FDC_IsDataReady(void);
int FDC_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_FDC_H */
+20
View File
@@ -37,6 +37,26 @@ static int (*GetCurrentID[4])(int, FDCID*) = { 0, XDF_GetCur
int FDD_IsReading = 0;
int FDD_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAY32(fdd.SetDelay, 4),
SFARRAY32(fdd.Types, 4),
SFARRAY32(fdd.ROnly, 4),
SFARRAY32(fdd.EMask, 4),
SFARRAY32(fdd.Blink, 4),
SFVAR(fdd.Access),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_FDD", false);
return ret;
}
static void ConvertCapital(char* buf)
{
for ( ; *buf; buf++)
+1
View File
@@ -39,6 +39,7 @@ void FDD_SetReadOnly(int drv);
void FDD_SetEMask(int drive, int emask);
void FDD_SetAccess(int drive);
void FDD_SetBlink(int drive, int blink);
int FDD_StateAction(StateMem *sm, int load, int data_only);
/* Misc: Used to trigger rumble when FDD is reading data.
* Reset at every frame */
+22 -3
View File
@@ -14,11 +14,30 @@
uint8_t GVRAM[0x80000];
uint16_t Grp_LineBuf[1024];
uint16_t Grp_LineBufSP[1024]; /* ¿ü¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿å¿¿ */
uint16_t Grp_LineBufSP[1024]; /* ¿?¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿å¿¿ */
uint16_t Grp_LineBufSP2[1024]; /* ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿å¿¿¿¿¿¿¿¿¿¿¿¿å¿¿¿¿¿ */
static uint16_t Grp_LineBufSP_Tr[1024];
static uint16_t Pal16Adr[256]; /* 16bit color ¿¿¿å¿¿¿¿¿¿¿¿¿¿ */
int GVRAM_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAYN(GVRAM, 524288, "MEM_GVRAM"),
SFARRAY16(Grp_LineBuf, 1024),
SFARRAY16(Grp_LineBufSP, 1024),
SFARRAY16(Grp_LineBufSP2, 1024),
SFARRAY16(Grp_LineBufSP_Tr, 1024),
SFARRAY16(Pal16Adr, 256),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_GVRAM", false);
return ret;
}
#ifdef MSB_FIRST
#define GET_WORD_W8(src) (*(uint16_t *)(src))
#else
@@ -225,7 +244,7 @@ void FASTCALL GVRAM_Write(uint32_t adr, uint8_t data)
/*
* ¿¿¿ä¿¿¿¿¿¿¿¿ñ¿¿¿¿¿¿¿¿¿¿¿¿
* ¿¿¿ä¿¿¿¿¿¿¿¿?¿¿¿¿¿¿¿¿¿¿¿
*/
void Grp_DrawLine16(void)
{
@@ -513,7 +532,7 @@ void FASTCALL Grp_DrawLine4h(void)
/*
* --- ¿¿¿¿¿¿¿ü¿Pri¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿ ---
* --- ¿¿¿¿¿¿¿?¿Pri¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿ ---
*/
void FASTCALL Grp_DrawLine16SP(void)
{
+1
View File
@@ -27,5 +27,6 @@ void FASTCALL Grp_DrawLine4hSP(void);
void FASTCALL Grp_DrawLine8TR(int page, int opaq);
void FASTCALL Grp_DrawLine8TR_GT(int page, int opaq);
void FASTCALL Grp_DrawLine4TR(uint32_t page, int opaq);
int GVRAM_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_GVRAM_H */
+15
View File
@@ -8,6 +8,21 @@
uint8_t IOC_IntStat = 0;
uint8_t IOC_IntVect = 0;
int IOC_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(IOC_IntStat),
SFVAR(IOC_IntVect),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_IOC", false);
return ret;
}
void IOC_Init(void)
{
IOC_IntStat = 0;
+1
View File
@@ -10,5 +10,6 @@ extern uint8_t IOC_IntVect;
void IOC_Init(void);
uint8_t FASTCALL IOC_Read(uint32_t adr);
void FASTCALL IOC_Write(uint32_t adr, uint8_t data);
int IOC_StateAction(StateMem *sm, int load, int data_only);
#endif /* WINX68K_IOC_H */
+14
View File
@@ -16,6 +16,20 @@ typedef int32_t FASTCALL C68K_INT_CALLBACK(int32_t level);
static uint8_t IRQH_IRQ[8];
static void *IRQH_CallBack[8];
int IRQH_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAY(IRQH_IRQ, 8),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_IRQH", false);
return ret;
}
void IRQH_Init(void)
{
memset(IRQH_IRQ, 0, 8);
+1
View File
@@ -7,5 +7,6 @@
void IRQH_Init(void);
void IRQH_IRQCallBack(uint8_t irq);
void IRQH_Int(uint8_t irq, void* handler);
int IRQH_StateAction(StateMem *sm, int load, int data_only);
#endif /* WINX68K_IRQ_H */
+18
View File
@@ -16,6 +16,24 @@ static uint8_t Timer_Reload[4] = {0, 0, 0, 0};
static int32_t Timer_Tick[4] = {0, 0, 0, 0};
static const int Timer_Prescaler[8] = {1, 10, 25, 40, 125, 160, 250, 500};
int MFP_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAY(MFP, 24),
SFVAR(LastKey),
SFARRAY(Timer_Reload, 4),
SFARRAY32(Timer_Tick, 4),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_MFP", false);
return ret;
}
uint32_t FASTCALL MFP_IntCallback(uint8_t irq)
{
uint8_t flag;
+1
View File
@@ -39,5 +39,6 @@ void FASTCALL MFP_Write(uint32_t adr, uint8_t data);
void FASTCALL MFP_Timer(int32_t clock);
void FASTCALL MFP_TimerA(void);
void MFP_Int(int irq);
int MFP_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_MFP_H */
+39
View File
@@ -112,6 +112,45 @@ static uint8_t EXCV_XGRESET[] = { 0xf0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00
#define MIDIOUTS(a,b,c) (((size_t)c << 16) | ((size_t)b << 8) | (size_t)a)
int MIDI_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(MIDI_CTRL),
SFVAR(MIDI_POS),
SFVAR(MIDI_SYSCOUNT),
SFVAR(MIDI_LAST),
SFARRAY(MIDI_BUF, 1024),
SFARRAY(MIDI_EXCVBUF, 1024),
SFVAR(MIDI_RegHigh),
SFVAR(MIDI_Vector),
SFVAR(MIDI_IntEnable),
SFVAR(MIDI_IntVect),
SFVAR(MIDI_IntFlag),
SFVAR(MIDI_Buffered),
SFVAR(MIDI_BufTimer),
SFVAR(MIDI_R05),
SFVAR(MIDI_GTimerMax),
SFVAR(MIDI_MTimerMax),
SFVAR(MIDI_GTimerVal),
SFVAR(MIDI_MTimerVal),
SFVAR(MIDI_MODULE),
SFARRAY(DelayBuf, ((4 + 1) * MIDIDELAYBUF)),
SFVAR(DBufPtrW),
SFVAR(DBufPtrR),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_MIDI", false);
return ret;
}
static uint32_t FASTCALL MIDI_Int(uint8_t irq)
{
IRQH_IRQCallBack(irq);
+1
View File
@@ -13,5 +13,6 @@ void FASTCALL MIDI_Timer(uint32_t clk);
int MIDI_SetMimpiMap(char *filename);
int MIDI_EnableMimpiDef(int enable);
void MIDI_DelayOut(unsigned int delay);
int MIDI_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_MIDI_H */
+17
View File
@@ -20,6 +20,23 @@ uint16_t Ibit;
uint16_t Pal_HalfMask, Pal_Ix2;
uint16_t Pal_R, Pal_G, Pal_B;
int Pal_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAY(Pal_Regs, 1024),
SFARRAY16(TextPal, 256),
SFARRAY16(GrphPal, 256),
SFARRAY16(Pal16, 65536),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_Palette", false);
return ret;
}
void Pal_SetColor(void)
{
int i;
+1
View File
@@ -15,6 +15,7 @@ void Pal_Init(void);
uint8_t FASTCALL Pal_Read(uint32_t adr);
void FASTCALL Pal_Write(uint32_t adr, uint8_t data);
void Pal_ChangeContrast(int num);
int Pal_StateAction(StateMem *sm, int load, int data_only);
extern uint16_t Ibit, Pal_HalfMask, Pal_Ix2;
+17
View File
@@ -17,6 +17,23 @@ typedef struct {
static PIA pia;
int PIA_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(pia.PortA),
SFVAR(pia.PortB),
SFVAR(pia.PortC),
SFVAR(pia.Ctrl),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_PIA", false);
return ret;
}
void PIA_Init(void)
{
pia.PortA = 0xff;
+1
View File
@@ -7,5 +7,6 @@
void PIA_Init(void);
uint8_t FASTCALL PIA_Read(uint32_t adr);
void FASTCALL PIA_Write(uint32_t adr, uint8_t data);
int PIA_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_PIA_H */
+18
View File
@@ -12,6 +12,24 @@ static uint8_t RTC_Bank = 0;
static int RTC_Timer1 = 0;
static int RTC_Timer16 = 0;
int RTC_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAYN(RTC_Regs[0], 16, "RTCRegs0"),
SFARRAYN(RTC_Regs[1], 16, "RTCRegs1"),
SFVAR(RTC_Bank), /* never changed since alarm is not implemented, but whatever */
SFVAR(RTC_Timer1),
SFVAR(RTC_Timer16),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_RTC", false);
return ret;
}
void RTC_Init(void)
{
memset(&RTC_Regs[1][0], 0, 16);
+1
View File
@@ -7,5 +7,6 @@ void RTC_Init(void);
uint8_t FASTCALL RTC_Read(uint32_t adr);
void FASTCALL RTC_Write(uint32_t adr, uint8_t data);
void RTC_Timer(int clock);
int RTC_StateAction(StateMem *sm, int load, int data_only);
#endif /* _X68K_RTC_H */
+27
View File
@@ -26,6 +26,33 @@ static uint8_t SASI_Error = 0;
static uint8_t SASI_SenseStatBuf[4];
static uint8_t SASI_SenseStatPtr = 0;
int SASI_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAY(SASI_Cmd, 6),
SFARRAY(SASI_Buf, 256),
SFVAR(SASI_Phase),
SFVAR(SASI_Sector),
SFVAR(SASI_Blocks),
SFVAR(SASI_CmdPtr),
SFVAR(SASI_Device),
SFVAR(SASI_Unit),
SFVAR(SASI_BufPtr),
SFVAR(SASI_RW),
SFVAR(SASI_Stat),
SFVAR(SASI_Error),
SFARRAY(SASI_SenseStatBuf, 4),
SFVAR(SASI_SenseStatPtr),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_SASI", false);
return ret;
}
int SASI_IsReady(void)
{
if ( (SASI_Phase==2)||(SASI_Phase==3)||(SASI_Phase==9) )
+1
View File
@@ -8,5 +8,6 @@ void SASI_Init(void);
uint8_t FASTCALL SASI_Read(uint32_t adr);
void FASTCALL SASI_Write(uint32_t adr, uint8_t data);
int SASI_IsReady(void);
int SASI_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_SASI_H */
+25
View File
@@ -21,6 +21,31 @@ static uint8_t SCC_Vector = 0;
static uint8_t SCC_Dat[3] = {0, 0, 0};
static uint8_t SCC_DatNum = 0;
int SCC_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(MouseX),
SFVAR(MouseY),
SFVAR(MouseSt),
SFVAR(SCC_RegNumA),
SFVAR(SCC_RegSetA),
SFARRAY(SCC_RegsB, 16),
SFVAR(SCC_RegNumB),
SFVAR(SCC_RegSetB),
SFVAR(SCC_Vector),
SFARRAY(SCC_Dat, 3),
SFVAR(SCC_DatNum),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_SCC", false);
return ret;
}
static uint32_t FASTCALL SCC_Int(uint8_t irq)
{
IRQH_IRQCallBack(irq);
+1
View File
@@ -8,6 +8,7 @@ void SCC_IntCheck(void);
void SCC_Init(void);
uint8_t FASTCALL SCC_Read(uint32_t adr);
void FASTCALL SCC_Write(uint32_t adr, uint8_t data);
int SCC_StateAction(StateMem *sm, int load, int data_only);
extern int8_t MouseX;
extern int8_t MouseY;
+15
View File
@@ -13,6 +13,21 @@
static int write_enabled = 0;
uint8_t SRAM[0x4000];
int SRAM_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAYN(SRAM, 0x4000, "MEM_SRAM"),
SFVAR(write_enabled),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_SRAM", false);
return ret;
}
void SRAM_VirusCheck(void)
{
if ( (cpu_readmem24_dword(0xed3f60)==0x60000002)
+1
View File
@@ -14,5 +14,6 @@ void SRAM_WriteEnable(int enable);
uint8_t FASTCALL SRAM_Read(uint32_t adr);
void FASTCALL SRAM_Write(uint32_t adr, uint8_t data);
int SRAM_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_SRAM_H */
+17
View File
@@ -18,6 +18,23 @@ typedef struct
static SYSPORT sysport;
int SysPort_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFVAR(sysport.contrast),
SFVAR(sysport.monitor),
SFVAR(sysport.keyctrl),
SFVAR(sysport.cputype),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_SysPort", false);
return ret;
}
void SysPort_Init(void)
{
static uint8_t cputype[] = {
+1
View File
@@ -9,5 +9,6 @@ extern uint8_t SysPort[7];
void SysPort_Init(void);
uint8_t FASTCALL SysPort_Read(uint32_t adr);
void FASTCALL SysPort_Write(uint32_t adr, uint8_t data);
int SysPort_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_SYSPORT_H */
+20 -1
View File
@@ -14,10 +14,29 @@
uint8_t TVRAM[0x80000];
static uint8_t TextDrawWork[1024*1024];
uint8_t TextDirtyLine[1024];
uint8_t Text_TrFlag[1024];
/* pattern table */
static uint8_t TextDrawPattern[2048*4];
uint8_t Text_TrFlag[1024];
int TVRAM_StateAction(StateMem *sm, int load, int data_only)
{
SFORMAT StateRegs[] =
{
SFARRAYN(TVRAM, 524288, "MEM_TVRAM"),
SFARRAY(TextDrawWork, (1024 * 1024)),
SFARRAY(TextDirtyLine, 1024),
SFARRAY(Text_TrFlag, 1024),
SFEND
};
int ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_TVRAM", false);
if (load)
TVRAM_SetAllDirty();
return ret;
}
void TVRAM_SetAllDirty(void) { memset(TextDirtyLine, 1, 1024); }
void TVRAM_Cleanup(void) { }
+1
View File
@@ -17,5 +17,6 @@ uint8_t FASTCALL TVRAM_Read(uint32_t adr);
void FASTCALL TVRAM_Write(uint32_t adr, uint8_t data);
void FASTCALL TVRAM_RCUpdate(void);
void FASTCALL Text_DrawLine(int opaq);
int TVRAM_StateAction(StateMem *sm, int load, int data_only);
#endif /* _WINX68K_TVRAM_H */
+1 -1
View File
@@ -5,7 +5,7 @@
#include "../libretro/common.h"
extern uint8_t* IPL;
extern uint8_t* MEM;
extern uint8_t* MEM;
extern uint8_t* FONT;
extern uint8_t SCSIIPL[0x2000];
extern uint8_t SRAM[0x4000];