SCAN_VAR(Pico.m ,"misc")\r
SCAN_VAR(Pico.video,"video")\r
\r
- // notaz: save/load z80, YM2612, sn76496 states instead of Pico.s (which is unused anyway)\r
- if(PicoOpt&7) {\r
+ if (PicoOpt&7) {\r
if((PmovAction&3)==1) z80_pack(cpu_z80);\r
ret = SCAN_VAR(cpu_z80,"cpu_z80")\r
// do not unpack if we fail to load z80 state\r
else z80_unpack(cpu_z80);\r
}\r
}\r
- if(PicoOpt&3)\r
+ if (PicoOpt&3)\r
ScanVar(sn76496_regs,28*4,"SN76496state", PmovFile, PmovAction); // regs and other stuff\r
- if(PicoOpt&1) {\r
+ if (PicoOpt&1) {\r
+ if((PmovAction&3)==1) ym2612_pack_state();\r
ScanVar(ym2612_regs, 0x200+4, "YM2612state", PmovFile, PmovAction); // regs + addr line\r
if((PmovAction&3)==2) ym2612_unpack_state(); // reload YM2612 state from it's regs\r
}\r
{\r
//elprintf(EL_STATUS, "timer a set %i", TAnew);\r
ym2612.OPN.ST.TA = TAnew;\r
- //ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
+ ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
//ym2612.OPN.ST.TAT = 0;\r
//\r
timer_a_step = timer_a_offset = 16466 * (1024 - TAnew);\r
if (ym2612.OPN.ST.TB != d) {\r
//elprintf(EL_STATUS, "timer b set %i", d);\r
ym2612.OPN.ST.TB = d;\r
- //ym2612.OPN.ST.TBC = (256-d)<<4;\r
- //ym2612.OPN.ST.TBC *= 18;\r
+ ym2612.OPN.ST.TBC = (256-d) * 288;\r
//ym2612.OPN.ST.TBT = 0;\r
timer_b_step = timer_b_offset = 262800 * (256 - d); // 262881\r
if (ym2612.OPN.ST.mode & 2) {\r
return ym2612.OPN.ST.status;\r
}\r
\r
-// TODO: new ym2612 savestates, also save timers\r
+void ym2612_pack_state(void)\r
+{\r
+ // TODO timers\r
+#ifdef __GP2X__\r
+ if (PicoOpt & POPT_EXT_FM)\r
+ /*YM2612PicoStateSave2_940(0, 0)*/;\r
+ else\r
+#endif\r
+ YM2612PicoStateSave2(0, 0);\r
+}\r
+\r
void ym2612_unpack_state(void)\r
{\r
- int i;\r
+ int i, ret, tat, tbt;\r
YM2612PicoStateLoad();\r
\r
// feed all the registers and update internal state\r
- for (i = 0x20; i < 0xC0; i++) {\r
+ for (i = 0x20; i < 0xB8; i++) {\r
ym2612_write_local(0, i, 0);\r
ym2612_write_local(1, ym2612.REGS[i], 0);\r
}\r
- for (i = 0x30; i < 0xC0; i++) {\r
+ for (i = 0x30; i < 0xB8; i++) {\r
ym2612_write_local(2, i, 0);\r
ym2612_write_local(3, ym2612.REGS[i|0x100], 0);\r
}\r
+\r
+#ifdef __GP2X__\r
+ if (PicoOpt & POPT_EXT_FM)\r
+ /*ret = YM2612PicoStateLoad2_940(&tat, &tbt)*/;\r
+ else\r
+#endif\r
+ ret = YM2612PicoStateLoad2(&tat, &tbt);\r
}\r
\r
// -----------------------------------------------------------------\r
extern int timer_b_next_oflow, timer_b_step, timer_b_offset;\r
\r
void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new);\r
+void ym2612_pack_state(void);\r
void ym2612_unpack_state(void);\r
\r
#define timers_cycle() \\r
}
if (PicoOpt&3)
CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);
- if (PicoOpt&1)
+ if (PicoOpt&1) {
+ ym2612_pack_state();
CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs);
+ }
if (PicoAHW & PAHW_MCD)
{
\r
static chan_rend_context crct;\r
\r
+static void chan_render_prep(void)\r
+{\r
+ crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r
+ crct.lfo_inc = ym2612.OPN.lfo_inc;\r
+}\r
+\r
+static void chan_render_finish(void)\r
+{\r
+ ym2612.OPN.eg_cnt = crct.eg_cnt;\r
+ ym2612.OPN.eg_timer = crct.eg_timer;\r
+ g_lfo_ampm = crct.pack >> 16; // need_save\r
+ ym2612.OPN.lfo_cnt = crct.lfo_cnt;\r
+}\r
+\r
static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l\r
{\r
crct.CH = &ym2612.CH[c];\r
crct.mem = crct.CH->mem_value; /* one sample delay memory */\r
crct.lfo_cnt = ym2612.OPN.lfo_cnt;\r
- crct.lfo_inc = ym2612.OPN.lfo_inc;\r
\r
flags &= 0x35;\r
\r
\r
crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */\r
crct.eg_timer = ym2612.OPN.eg_timer;\r
- crct.eg_timer_add = ym2612.OPN.eg_timer_add;\r
\r
/* precalculate phase modulation incr */\r
crct.phase1 = crct.CH->SLOT[SLOT1].phase;\r
else\r
ym2612.slot_mask &= ~(0xf << (c*4));\r
\r
- // if this the last call, write back persistent stuff:\r
- if ((ym2612.slot_mask >> ((c+1)*4)) == 0)\r
- {\r
- ym2612.OPN.eg_cnt = crct.eg_cnt;\r
- ym2612.OPN.eg_timer = crct.eg_timer;\r
- g_lfo_ampm = crct.pack >> 16;\r
- ym2612.OPN.lfo_cnt = crct.lfo_cnt;\r
- }\r
-\r
return (crct.algo & 8) >> 3; // had output\r
}\r
\r
SLOT->ksr = ksr;\r
\r
/* calculate envelope generator rates */\r
- if ((SLOT->ar + SLOT->ksr) < 32+62)\r
+ if ((SLOT->ar + ksr) < 32+62)\r
{\r
- eg_sh = eg_rate_shift [SLOT->ar + SLOT->ksr ];\r
- eg_sel = eg_rate_select[SLOT->ar + SLOT->ksr ];\r
+ eg_sh = eg_rate_shift [SLOT->ar + ksr ];\r
+ eg_sel = eg_rate_select[SLOT->ar + ksr ];\r
}\r
else\r
{\r
\r
SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
\r
- eg_sh = eg_rate_shift [SLOT->d1r + SLOT->ksr];\r
- eg_sel = eg_rate_select[SLOT->d1r + SLOT->ksr];\r
+ eg_sh = eg_rate_shift [SLOT->d1r + ksr];\r
+ eg_sel = eg_rate_select[SLOT->d1r + ksr];\r
\r
SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
\r
- eg_sh = eg_rate_shift [SLOT->d2r + SLOT->ksr];\r
- eg_sel = eg_rate_select[SLOT->d2r + SLOT->ksr];\r
+ eg_sh = eg_rate_shift [SLOT->d2r + ksr];\r
+ eg_sel = eg_rate_select[SLOT->d2r + ksr];\r
\r
SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
\r
- eg_sh = eg_rate_shift [SLOT->rr + SLOT->ksr];\r
- eg_sel = eg_rate_select[SLOT->rr + SLOT->ksr];\r
+ eg_sh = eg_rate_shift [SLOT->rr + ksr];\r
+ eg_sel = eg_rate_select[SLOT->rr + ksr];\r
\r
SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24);\r
}\r
\r
/* mix to 32bit dest */\r
// flags: stereo, ?, disabled, ?, pan_r, pan_l\r
+ chan_render_prep();\r
if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;\r
if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;\r
if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030) )) << 2;\r
if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;\r
if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;\r
if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;\r
+ chan_render_finish();\r
\r
return active_chs; // 1 if buffer updated\r
}\r
void YM2612PicoStateLoad_(void)\r
{\r
reset_channels( &ym2612.CH[0] );\r
+ ym2612.slot_mask = 0xffffff;\r
+}\r
+\r
+typedef struct\r
+{\r
+ UINT32 state_phase;\r
+ INT16 volume;\r
+} ym_save_addon_slot;\r
+\r
+typedef struct\r
+{\r
+ UINT32 magic;\r
+ UINT8 address;\r
+ UINT8 status;\r
+ UINT8 addr_A1;\r
+ UINT8 unused;\r
+ int TAT;\r
+ int TBT;\r
+ UINT32 eg_cnt;\r
+ UINT32 eg_timer;\r
+ UINT32 lfo_cnt;\r
+ UINT16 lfo_ampm;\r
+ UINT16 unused2;\r
+} ym_save_addon;\r
+\r
+void YM2612PicoStateSave2(int tat, int tbt)\r
+{\r
+ ym_save_addon_slot ss;\r
+ ym_save_addon sa;\r
+ unsigned char *ptr;\r
+ int c, s;\r
+\r
+ // chans 1,2,3\r
+ ptr = &ym2612.REGS[0x0b8];\r
+ for (c = 0; c < 3; c++)\r
+ {\r
+ for (s = 0; s < 4; s++) {\r
+ ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
+ ss.volume = ym2612.CH[c].SLOT[s].volume;\r
+ memcpy(ptr, &ss, 6);\r
+ ptr += 6;\r
+ }\r
+ }\r
+ // chans 4,5,6\r
+ ptr = &ym2612.REGS[0x1b8];\r
+ for (; c < 6; c++)\r
+ {\r
+ for (s = 0; s < 4; s++) {\r
+ ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3);\r
+ ss.volume = ym2612.CH[c].SLOT[s].volume;\r
+ memcpy(ptr, &ss, 6);\r
+ ptr += 6;\r
+ }\r
+ }\r
+ // other things\r
+ ptr = &ym2612.REGS[0x100];\r
+ sa.magic = 0x41534d59; // 'YMSA'\r
+ sa.address = ym2612.OPN.ST.address;\r
+ sa.status = ym2612.OPN.ST.status;\r
+ sa.addr_A1 = ym2612.addr_A1;\r
+ sa.unused = 0;\r
+ sa.TAT = tat;\r
+ sa.TBT = tbt;\r
+ sa.eg_cnt = ym2612.OPN.eg_cnt;\r
+ sa.eg_timer = ym2612.OPN.eg_timer;\r
+ sa.lfo_cnt = ym2612.OPN.lfo_cnt;\r
+ sa.lfo_ampm = g_lfo_ampm;\r
+ sa.unused2 = 0;\r
+ memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r
+}\r
+\r
+int YM2612PicoStateLoad2(int *tat, int *tbt)\r
+{\r
+ ym_save_addon_slot ss;\r
+ ym_save_addon sa;\r
+ unsigned char *ptr;\r
+ int c, s;\r
+\r
+ ptr = &ym2612.REGS[0x100];\r
+ memcpy(&sa, ptr, sizeof(sa)); // 0x30 max\r
+ if (sa.magic != 0x41534d59) return -1;\r
+\r
+ ym2612.OPN.ST.address = sa.address;\r
+ ym2612.OPN.ST.status = sa.status;\r
+ ym2612.addr_A1 = sa.addr_A1;\r
+ ym2612.OPN.eg_cnt = sa.eg_cnt;\r
+ ym2612.OPN.eg_timer = sa.eg_timer;\r
+ ym2612.OPN.lfo_cnt = sa.lfo_cnt;\r
+ g_lfo_ampm = sa.lfo_ampm;\r
+ if (tat != NULL) *tat = sa.TAT;\r
+ if (tbt != NULL) *tbt = sa.TBT;\r
+\r
+ // chans 1,2,3\r
+ ptr = &ym2612.REGS[0x0b8];\r
+ for (c = 0; c < 3; c++)\r
+ {\r
+ for (s = 0; s < 4; s++) {\r
+ memcpy(&ss, ptr, 6);\r
+ ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
+ ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
+ ym2612.CH[c].SLOT[s].volume = ss.volume;\r
+ ptr += 6;\r
+ }\r
+ }\r
+ // chans 4,5,6\r
+ ptr = &ym2612.REGS[0x1b8];\r
+ for (; c < 6; c++)\r
+ {\r
+ for (s = 0; s < 4; s++) {\r
+ memcpy(&ss, ptr, 6);\r
+ ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29;\r
+ ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
+ ym2612.CH[c].SLOT[s].volume = ss.volume;\r
+ ptr += 6;\r
+ }\r
+ }\r
+\r
+ return 0;\r
}\r
\r
#ifndef EXTERNAL_YM2612\r
typedef struct\r
{\r
INT32 *DT; /* #0x00 detune :dt_tab[DT] */\r
- UINT8 ar; /* #0x04 attack rate */\r
+ UINT8 ar; /* #0x04 attack rate */\r
UINT8 d1r; /* #0x05 decay rate */\r
UINT8 d2r; /* #0x06 sustain rate */\r
- UINT8 rr; /* #0x07 release rate */\r
+ UINT8 rr; /* #0x07 release rate */\r
UINT32 mul; /* #0x08 multiple :ML_TABLE[ML] */\r
\r
/* Phase Generator */\r
- UINT32 phase; /* #0x0c phase counter */\r
- UINT32 Incr; /* #0x10 phase step */\r
+ UINT32 phase; /* #0x0c phase counter | need_save */\r
+ UINT32 Incr; /* #0x10 phase step | need_save */\r
\r
UINT8 KSR; /* #0x14 key scale rate :3-KSR */\r
UINT8 ksr; /* #0x15 key scale rate :kcode>>(3-KSR) */\r
UINT8 key; /* #0x16 0=last key was KEY OFF, 1=KEY ON */\r
\r
/* Envelope Generator */\r
- UINT8 state; /* #0x17 phase type: EG_OFF=0, EG_REL, EG_SUS, EG_DEC, EG_ATT */\r
- UINT16 tl; /* #0x18 total level: TL << 3 */\r
- INT16 volume; /* #0x1a envelope counter */\r
- UINT32 sl; /* #0x1c sustain level:sl_table[SL] */\r
+ UINT8 state; /* #0x17 phase type: EG_OFF=0, EG_REL, EG_SUS, EG_DEC, EG_ATT | need_save */\r
+ UINT16 tl; /* #0x18 total level: TL << 3 */\r
+ INT16 volume; /* #0x1a envelope counter | need_save */\r
+ UINT32 sl; /* #0x1c sustain level:sl_table[SL] */\r
\r
- UINT32 eg_pack_ar; /* #0x20 (attack state) */\r
+ UINT32 eg_pack_ar; /* #0x20 (attack state) */\r
UINT32 eg_pack_d1r; /* #0x24 (decay state) */\r
UINT32 eg_pack_d2r; /* #0x28 (sustain state) */\r
- UINT32 eg_pack_rr; /* #0x2c (release state) */\r
+ UINT32 eg_pack_rr; /* #0x2c (release state) */\r
} FM_SLOT;\r
\r
\r
FM_SLOT SLOT[4]; /* four SLOTs (operators) */\r
\r
UINT8 ALGO; /* algorithm */\r
- UINT8 FB; /* feedback shift */\r
+ UINT8 FB; /* feedback shift */\r
INT32 op1_out; /* op1 output for feedback */\r
\r
INT32 mem_value; /* delayed sample (MEM) value */\r
UINT8 ams; /* channel AMS */\r
\r
UINT8 kcode; /* key code: */\r
- UINT32 fc; /* fnum,blk:adjusted to sample rate */\r
+ UINT32 fc; /* fnum,blk:adjusted to sample rate */\r
UINT32 block_fnum; /* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */\r
\r
/* LFO */\r
int clock; /* master clock (Hz) */\r
int rate; /* sampling rate (Hz) */\r
double freqbase; /* 08 frequency base */\r
- UINT8 address; /* 10 address register */\r
- UINT8 status; /* 11 status flag */\r
+ UINT8 address; /* 10 address register | need_save */\r
+ UINT8 status; /* 11 status flag | need_save */\r
UINT8 mode; /* mode CSM / 3SLOT */\r
UINT8 fn_h; /* freq latch */\r
int TA; /* timer a */\r
int TAC; /* timer a maxval */\r
- int TAT; /* timer a ticker */\r
+ int TAT; /* timer a ticker | need_save */\r
UINT8 TB; /* timer b */\r
UINT8 pad[3];\r
int TBC; /* timer b maxval */\r
- int TBT; /* timer b ticker */\r
+ int TBT; /* timer b ticker | need_save */\r
/* local time tables */\r
INT32 dt_tab[8][32];/* DeTune table */\r
} FM_ST;\r
FM_3SLOT SL3; /* 3 slot mode state */\r
UINT32 pan; /* fm channels output mask (bit 1 = enable) */\r
\r
- UINT32 eg_cnt; /* #0xb38 global envelope generator counter */\r
- UINT32 eg_timer; /* #0xb3c global envelope generator counter works at frequency = chipclock/64/3 */\r
- UINT32 eg_timer_add; /* #0xb40 step of eg_timer */\r
+ UINT32 eg_cnt; /* #0xb38 global envelope generator counter | need_save */\r
+ UINT32 eg_timer; /* #0xb3c global envelope generator counter works at frequency = chipclock/64/3 | need_save */\r
+ UINT32 eg_timer_add; /* #0xb40 step of eg_timer */\r
\r
/* LFO */\r
- UINT32 lfo_cnt;\r
+ UINT32 lfo_cnt; /* need_save */\r
UINT32 lfo_inc;\r
\r
UINT32 lfo_freq[8]; /* LFO FREQ table */\r
/* here's the virtual YM2612 */\r
typedef struct\r
{\r
- UINT8 REGS[0x200]; /* registers (for save states) */\r
- INT32 addr_A1; /* address line A1 */\r
+ UINT8 REGS[0x200]; /* registers (for save states) */\r
+ INT32 addr_A1; /* address line A1 | need_save */\r
\r
FM_CH CH[6]; /* channel state (0x168 bytes each)? */\r
\r
/* dac output (YM2612) */\r
- int dacen;\r
+ int dacen;\r
INT32 dacout;\r
\r
FM_OPN OPN; /* OPN state */\r
void YM2612PicoStateLoad_(void);\r
\r
void *YM2612GetRegs(void);\r
+void YM2612PicoStateSave2(int tat, int tbt);\r
+int YM2612PicoStateLoad2(int *tat, int *tbt);\r
\r
#ifndef __GP2X__\r
#define YM2612Init YM2612Init_\r