UINT32 eg_timer;\r
UINT32 eg_timer_add;\r
UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r
- UINT32 algo; /* 50: algo[3], was_update, unsued, upd_cnt[2], dac */\r
+ UINT32 algo; /* 50: algo[3], was_update, unused, upd_cnt[2], dac */\r
INT32 op1_out;\r
#ifdef _MIPS_ARCH_ALLEGREX\r
UINT32 pad1[3+8];\r
typedef struct\r
{\r
UINT32 state_phase;\r
- INT16 volume;\r
+ INT16 ssg_volume;\r
} ym_save_addon_slot;\r
\r
typedef struct\r
UINT8 address;\r
UINT8 status;\r
UINT8 addr_A1;\r
- UINT8 unused;\r
- int TAT;\r
- int TBT;\r
+ UINT8 version;\r
+ INT32 TAT;\r
+ INT32 TBT;\r
UINT32 eg_cnt; // 10\r
UINT32 eg_timer;\r
UINT32 lfo_cnt;\r
UINT16 lfo_ampm;\r
INT16 busy_timer;\r
UINT32 keyon_field; // 20\r
- UINT32 kcode_fc_sl3_3;\r
- UINT32 reserved[2];\r
+ INT16 mem_value[6];\r
} ym_save_addon;\r
\r
typedef struct\r
{\r
- UINT16 block_fnum[6];\r
- UINT16 block_fnum_sl3[3];\r
- UINT16 reserved[7];\r
+ UINT16 op1_out_l[6];\r
+ UINT16 unused_sl3[3];\r
+ UINT16 op1_out_h[6];\r
+ UINT16 fn_h;\r
} ym_save_addon2;\r
+#define _block_fnum op1_out_l\r
+#define _block_fnum_sl3 unused_sl3\r
\r
\r
void YM2612PicoStateSave2(int tat, int tbt, int busy)\r
{\r
ym_save_addon_slot ss;\r
- ym_save_addon2 sa2;\r
- ym_save_addon sa;\r
+ ym_save_addon2 sa2 = { 0 };\r
+ ym_save_addon sa = { 0 };\r
unsigned char *ptr;\r
int c, s;\r
\r
- memset(&sa, 0, sizeof(sa));\r
- memset(&sa2, 0, sizeof(sa2));\r
+ sa.magic = 0x41534d59; // 'YMSA'\r
+ sa.version = 1;\r
\r
// chans 1,2,3\r
ptr = &ym2612.REGS[0x0b8];\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
+ ss.ssg_volume = (ym2612.CH[c].SLOT[s].volume & 0x7ff);\r
+ if (sa.version)\r
+ ss.ssg_volume |= (ym2612.CH[c].SLOT[s].ssg << 11) | (ym2612.CH[c].SLOT[s].ssgn << 13);\r
if (ym2612.CH[c].SLOT[s].key)\r
sa.keyon_field |= 1 << (c*4 + s);\r
memcpy(ptr, &ss, 6);\r
ptr += 6;\r
}\r
- sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
+ if (sa.version) {\r
+ sa2.op1_out_h[c] = ym2612.CH[c].op1_out >> 16;\r
+ sa2.op1_out_l[c] = ym2612.CH[c].op1_out;\r
+ sa.mem_value[c] = ym2612.CH[c].mem_value;\r
+ } else {\r
+ sa2._block_fnum[c] = ym2612.CH[c].block_fnum;\r
+ sa2._block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];\r
+ }\r
+ ym2612.REGS[0x63 + 4*c] = ym2612.CH[c].upd_cnt;\r
+ ym2612.REGS[0x43 + 4*c] = ym2612.CH[c].block_fnum >> 8;\r
+ ym2612.REGS[0x33 + 4*c] = ym2612.OPN.SL3.block_fnum[c] >> 8;\r
}\r
// chans 4,5,6\r
ptr = &ym2612.REGS[0x1b8];\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
+ ss.ssg_volume = (ym2612.CH[c].SLOT[s].volume & 0x7ff);\r
+ if (sa.version)\r
+ ss.ssg_volume |= (ym2612.CH[c].SLOT[s].ssg << 11) | (ym2612.CH[c].SLOT[s].ssgn << 13);\r
if (ym2612.CH[c].SLOT[s].key)\r
sa.keyon_field |= 1 << (c*4 + s);\r
memcpy(ptr, &ss, 6);\r
ptr += 6;\r
}\r
- sa2.block_fnum[c] = ym2612.CH[c].block_fnum;\r
- }\r
- for (c = 0; c < 3; c++)\r
- {\r
- sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c];\r
+ if (sa.version) {\r
+ sa2.op1_out_h[c] = ym2612.CH[c].op1_out >> 16;\r
+ sa2.op1_out_l[c] = ym2612.CH[c].op1_out;\r
+ sa.mem_value[c] = ym2612.CH[c].mem_value;\r
+ } else {\r
+ sa2._block_fnum[c] = ym2612.CH[c].block_fnum;\r
+ }\r
+ ym2612.REGS[0x63 + 4*c] = ym2612.CH[c].upd_cnt;\r
+ ym2612.REGS[0x43 + 4*c] = ym2612.CH[c].block_fnum >> 8;\r
}\r
+ sa2.fn_h = ym2612.OPN.ST.fn_h | (ym2612.OPN.SL3.fn_h<<8);\r
\r
memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max\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.lfo_cnt = ym2612.OPN.lfo_cnt;\r
sa.lfo_ampm = g_lfo_ampm;\r
sa.busy_timer = busy;\r
+ //sa.keyon_field = ym2612.slot_mask;\r
memcpy(ptr, &sa, sizeof(sa)); // 0x30 max\r
}\r
\r
ym_save_addon2 sa2;\r
ym_save_addon sa;\r
unsigned char *ptr;\r
- UINT32 fn;\r
- UINT8 blk;\r
int c, s;\r
+ UINT8 fn_h, fn_h_sl3;\r
\r
ptr = &ym2612.REGS[0x100];\r
memcpy(&sa, ptr, sizeof(sa)); // 0x30 max\r
ym2612.OPN.eg_timer = sa.eg_timer;\r
ym2612.OPN.lfo_cnt = sa.lfo_cnt;\r
g_lfo_ampm = sa.lfo_ampm;\r
+ ym2612.slot_mask = sa.keyon_field;\r
if (tat != NULL) *tat = sa.TAT;\r
if (tbt != NULL) *tbt = sa.TBT;\r
if (busy != NULL) *busy = sa.busy_timer;\r
\r
+ fn_h = ym2612.OPN.ST.fn_h;\r
+ fn_h_sl3 = ym2612.OPN.SL3.fn_h;\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].state = (ss.state_phase >> 29) & 7;\r
ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
- ym2612.CH[c].SLOT[s].volume = ss.volume;\r
+ ym2612.CH[c].SLOT[s].volume = ss.ssg_volume & 0x7ff;\r
+ ym2612.CH[c].SLOT[s].ssg = (ss.ssg_volume >> 11) & 0xf;\r
+ ym2612.CH[c].SLOT[s].ssgn = (ss.ssg_volume >> 13) & 0x4;\r
ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
+ recalc_volout( &ym2612.CH[c].SLOT[s] );\r
ptr += 6;\r
}\r
ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
- ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
- fn = ym2612.CH[c].block_fnum & 0x7ff;\r
- blk = ym2612.CH[c].block_fnum >> 11;\r
- ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
- ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
- refresh_fc_eg_chan( &ym2612.CH[c] );\r
+ if (sa.version) {\r
+ ym2612.CH[c].op1_out = (sa2.op1_out_h[c] << 16) | sa2.op1_out_l[c];\r
+ ym2612.CH[c].mem_value = sa.mem_value[c];\r
+ ym2612.CH[c].upd_cnt = ym2612.REGS[0x63 + 4*c] & 3;\r
+ ym2612.OPN.ST.fn_h = ym2612.REGS[0x43 + 4*c] & 0x3f;\r
+ ym2612.OPN.SL3.fn_h = ym2612.REGS[0x33 + 4*c] & 0x3f;\r
+ } else {\r
+ ym2612.OPN.ST.fn_h = sa2._block_fnum[c] >> 8;\r
+ ym2612.OPN.SL3.fn_h = sa2._block_fnum_sl3[c] >> 8;\r
+ }\r
+\r
+ OPNWriteReg(0xa0 + (c&3), ym2612.REGS[0xa0 + (c&3)]);\r
+ OPNWriteReg(0xa8 + (c&3), ym2612.REGS[0xa8 + (c&3)]);\r
}\r
// chans 4,5,6\r
ptr = &ym2612.REGS[0x1b8];\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].state = (ss.state_phase >> 29) & 7;\r
ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3;\r
- ym2612.CH[c].SLOT[s].volume = ss.volume;\r
+ ym2612.CH[c].SLOT[s].volume = ss.ssg_volume & 0x7ff;\r
+ ym2612.CH[c].SLOT[s].ssg = (ss.ssg_volume >> 11) & 0xf;\r
+ ym2612.CH[c].SLOT[s].ssgn = (ss.ssg_volume >> 13) & 0x4;\r
ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0;\r
ym2612.CH[c].SLOT[s].ksr = (UINT8)-1;\r
+ recalc_volout( &ym2612.CH[c].SLOT[s] );\r
ptr += 6;\r
}\r
ym2612.CH[c].SLOT[SLOT1].Incr=-1;\r
- ym2612.CH[c].block_fnum = sa2.block_fnum[c];\r
- fn = ym2612.CH[c].block_fnum & 0x7ff;\r
- blk = ym2612.CH[c].block_fnum >> 11;\r
- ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];\r
- ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);\r
- refresh_fc_eg_chan( &ym2612.CH[c] );\r
+ if (sa.version) {\r
+ ym2612.CH[c].op1_out = (sa2.op1_out_h[c] << 16) | sa2.op1_out_l[c];\r
+ ym2612.CH[c].mem_value = sa.mem_value[c];\r
+ ym2612.CH[c].upd_cnt = ym2612.REGS[0x63 + 4*c] & 3;\r
+ ym2612.OPN.ST.fn_h = ym2612.REGS[0x43 + 4*c] & 0x3f;\r
+ } else {\r
+ ym2612.OPN.ST.fn_h = sa2._block_fnum[c] >> 8;\r
+ }\r
+\r
+ OPNWriteReg(0x1a0 + ((c-3)&3), ym2612.REGS[0x1a0 + ((c-3)&3)]);\r
}\r
- for (c = 0; c < 3; c++)\r
- {\r
- ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c];\r
- fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff;\r
- blk = ym2612.OPN.SL3.block_fnum[c] >> 11;\r
- ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\r
- ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk);\r
+ if (sa.version) {\r
+ ym2612.OPN.ST.fn_h = sa2.fn_h;\r
+ ym2612.OPN.SL3.fn_h = sa2.fn_h >> 8;\r
+ } else {\r
+ ym2612.OPN.ST.fn_h = fn_h;\r
+ ym2612.OPN.SL3.fn_h = fn_h_sl3;\r
}\r
\r
return 0;\r