This commit is contained in:
twinaphex 2015-07-24 05:26:14 +02:00
parent 0889b15c0b
commit b8709827d4
2 changed files with 629 additions and 635 deletions

View File

@ -96,271 +96,276 @@ static uint32 last_ts;
void WSwan_SoundUpdate(void)
{
int32 run_time;
int32 run_time;
//printf("%d\n", v30mz_timestamp);
//printf("%02x %02x\n", control, noise_control);
run_time = v30mz_timestamp - last_ts;
//printf("%d\n", v30mz_timestamp);
//printf("%02x %02x\n", control, noise_control);
run_time = v30mz_timestamp - last_ts;
for(unsigned int ch = 0; ch < 4; ch++)
{
// Channel is disabled?
if(!(control & (1 << ch)))
continue;
if(ch == 1 && (control & 0x20)) // Direct D/A mode?
{
int32 neoval = (volume[ch] - 0x80) * voice_volume;
VoiceSynth.offset(v30mz_timestamp, neoval - last_v_val, sbuf[0]);
VoiceSynth.offset(v30mz_timestamp, neoval - last_v_val, sbuf[1]);
last_v_val = neoval;
}
else if(ch == 2 && (control & 0x40) && sweep_value) // Sweep
{
uint32 tmp_pt = 2048 - period[ch];
uint32 meow_timestamp = v30mz_timestamp - run_time;
uint32 tmp_run_time = run_time;
while(tmp_run_time)
for(unsigned int ch = 0; ch < 4; ch++)
{
int32 sub_run_time = tmp_run_time;
// Channel is disabled?
if(!(control & (1 << ch)))
continue;
if(sub_run_time > sweep_8192_divider)
sub_run_time = sweep_8192_divider;
if(ch == 1 && (control & 0x20)) // Direct D/A mode?
{
int32 neoval = (volume[ch] - 0x80) * voice_volume;
sweep_8192_divider -= sub_run_time;
if(sweep_8192_divider <= 0)
{
sweep_8192_divider += 8192;
sweep_counter--;
if(sweep_counter <= 0)
{
sweep_counter = sweep_step + 1;
period[ch] = (period[ch] + (int8)sweep_value) & 0x7FF;
}
}
VoiceSynth.offset(v30mz_timestamp, neoval - last_v_val, sbuf[0]);
VoiceSynth.offset(v30mz_timestamp, neoval - last_v_val, sbuf[1]);
meow_timestamp += sub_run_time;
if(tmp_pt > 4)
{
period_counter[ch] -= sub_run_time;
while(period_counter[ch] <= 0)
{
sample_pos[ch] = (sample_pos[ch] + 1) & 0x1F;
last_v_val = neoval;
}
else if(ch == 2 && (control & 0x40) && sweep_value) // Sweep
{
uint32 tmp_pt = 2048 - period[ch];
uint32 meow_timestamp = v30mz_timestamp - run_time;
uint32 tmp_run_time = run_time;
MK_SAMPLE_CACHE;
SYNCSAMPLE(meow_timestamp + period_counter[ch]);
period_counter[ch] += tmp_pt;
}
}
tmp_run_time -= sub_run_time;
while(tmp_run_time)
{
int32 sub_run_time = tmp_run_time;
if(sub_run_time > sweep_8192_divider)
sub_run_time = sweep_8192_divider;
sweep_8192_divider -= sub_run_time;
if(sweep_8192_divider <= 0)
{
sweep_8192_divider += 8192;
sweep_counter--;
if(sweep_counter <= 0)
{
sweep_counter = sweep_step + 1;
period[ch] = (period[ch] + (int8)sweep_value) & 0x7FF;
}
}
meow_timestamp += sub_run_time;
if(tmp_pt > 4)
{
period_counter[ch] -= sub_run_time;
while(period_counter[ch] <= 0)
{
sample_pos[ch] = (sample_pos[ch] + 1) & 0x1F;
MK_SAMPLE_CACHE;
SYNCSAMPLE(meow_timestamp + period_counter[ch]);
period_counter[ch] += tmp_pt;
}
}
tmp_run_time -= sub_run_time;
}
}
else if(ch == 3 && (noise_control & 0x10)) //(control & 0x80)) // Noise
{
uint32 tmp_pt = 2048 - period[ch];
period_counter[ch] -= run_time;
while(period_counter[ch] <= 0)
{
// Yay, random numbers, so let's use totally wrong numbers to make them!
const int bstab1[8] = { 14, 13, 12, 14, 12, 13, 14, 14 };
const int bstab2[8] = { 13, 12, 9, 12, 1, 1, 5, 11 };
//const int bstab1[8] = { 14, 13, 12, 14, 10, 9, 8, 13 };
//const int bstab2[8] = { 13, 12, 9, 12, 1, 6, 4, 11 };
nreg = (~((nreg << 1) | ( ((nreg >> bstab1[noise_control & 0x7]) & 1) ^ ((nreg >> bstab2[noise_control & 0x7]) & 1)))) & 0x7FFF;
if(control & 0x80)
{
MK_SAMPLE_CACHE_NOISE;
SYNCSAMPLE_NOISE(v30mz_timestamp + period_counter[ch]);
}
else if(tmp_pt > 4)
{
sample_pos[ch] = (sample_pos[ch] + 1) & 0x1F;
MK_SAMPLE_CACHE;
SYNCSAMPLE(v30mz_timestamp + period_counter[ch]);
}
period_counter[ch] += tmp_pt;
}
}
else
{
uint32 tmp_pt = 2048 - period[ch];
if(tmp_pt > 4)
{
period_counter[ch] -= run_time;
while(period_counter[ch] <= 0)
{
sample_pos[ch] = (sample_pos[ch] + 1) & 0x1F;
MK_SAMPLE_CACHE;
SYNCSAMPLE(v30mz_timestamp + period_counter[ch]); // - period_counter[ch]);
period_counter[ch] += tmp_pt;
}
}
}
}
}
else if(ch == 3 && (noise_control & 0x10)) //(control & 0x80)) // Noise
{
uint32 tmp_pt = 2048 - period[ch];
period_counter[ch] -= run_time;
while(period_counter[ch] <= 0)
{
// Yay, random numbers, so let's use totally wrong numbers to make them!
const int bstab1[8] = { 14, 13, 12, 14, 12, 13, 14, 14 };
const int bstab2[8] = { 13, 12, 9, 12, 1, 1, 5, 11 };
//const int bstab1[8] = { 14, 13, 12, 14, 10, 9, 8, 13 };
//const int bstab2[8] = { 13, 12, 9, 12, 1, 6, 4, 11 };
nreg = (~((nreg << 1) | ( ((nreg >> bstab1[noise_control & 0x7]) & 1) ^ ((nreg >> bstab2[noise_control & 0x7]) & 1)))) & 0x7FFF;
if(control & 0x80)
{
MK_SAMPLE_CACHE_NOISE;
SYNCSAMPLE_NOISE(v30mz_timestamp + period_counter[ch]);
}
else if(tmp_pt > 4)
{
sample_pos[ch] = (sample_pos[ch] + 1) & 0x1F;
MK_SAMPLE_CACHE;
SYNCSAMPLE(v30mz_timestamp + period_counter[ch]);
}
period_counter[ch] += tmp_pt;
int32 tmphv = HyperVoice;
if(tmphv - last_hv_val)
{
WaveSynth.offset_inline(v30mz_timestamp, tmphv - last_hv_val, sbuf[0]);
WaveSynth.offset_inline(v30mz_timestamp, tmphv - last_hv_val, sbuf[1]);
last_hv_val = tmphv;
}
}
}
else
{
uint32 tmp_pt = 2048 - period[ch];
if(tmp_pt > 4)
{
period_counter[ch] -= run_time;
while(period_counter[ch] <= 0)
{
sample_pos[ch] = (sample_pos[ch] + 1) & 0x1F;
MK_SAMPLE_CACHE;
SYNCSAMPLE(v30mz_timestamp + period_counter[ch]); // - period_counter[ch]);
period_counter[ch] += tmp_pt;
}
}
}
}
{
int32 tmphv = HyperVoice;
if(tmphv - last_hv_val)
{
WaveSynth.offset_inline(v30mz_timestamp, tmphv - last_hv_val, sbuf[0]);
WaveSynth.offset_inline(v30mz_timestamp, tmphv - last_hv_val, sbuf[1]);
last_hv_val = tmphv;
}
}
last_ts = v30mz_timestamp;
last_ts = v30mz_timestamp;
}
void WSwan_SoundWrite(uint32 A, uint8 V)
{
WSwan_SoundUpdate();
WSwan_SoundUpdate();
if(A >= 0x80 && A <= 0x87)
{
int ch = (A - 0x80) >> 1;
if(A & 1)
period[ch] = (period[ch] & 0x00FF) | ((V & 0x07) << 8);
else
period[ch] = (period[ch] & 0x0700) | ((V & 0xFF) << 0);
}
else if(A >= 0x88 && A <= 0x8B)
{
volume[A - 0x88] = V;
}
else if(A == 0x8C)
sweep_value = V;
else if(A == 0x8D)
{
sweep_step = V;
sweep_counter = sweep_step + 1;
sweep_8192_divider = 8192;
}
else if(A == 0x8E)
{
noise_control = V;
if(V & 0x8) nreg = 1;
//printf("NOISECONTROL: %02x\n", V);
}
else if(A == 0x90)
{
for(int n = 0; n < 4; n++)
if(!(control & (1 << n)) && (V & (1 << n)))
if(A >= 0x80 && A <= 0x87)
{
period_counter[n] = 0;
sample_pos[n] = 0x1F;
int ch = (A - 0x80) >> 1;
if(A & 1)
period[ch] = (period[ch] & 0x00FF) | ((V & 0x07) << 8);
else
period[ch] = (period[ch] & 0x0700) | ((V & 0xFF) << 0);
}
control = V;
//printf("Sound Control: %02x\n", V);
}
else if(A == 0x91)
{
output_control = V & 0xF;
//printf("%02x, %02x\n", V, (V >> 1) & 3);
}
else if(A == 0x92)
nreg = (nreg & 0xFF00) | (V << 0);
else if(A == 0x93)
nreg = (nreg & 0x00FF) | ((V & 0x7F) << 8);
else if(A == 0x94)
{
voice_volume = V & 0xF;
//printf("%02x\n", V);
}
else switch(A)
{
case 0x8F: SampleRAMPos = V; break;
case 0x95: HyperVoice = V; break; // Pick a port, any port?!
//default: printf("%04x:%02x\n", A, V); break;
}
WSwan_SoundUpdate();
else if(A >= 0x88 && A <= 0x8B)
{
volume[A - 0x88] = V;
}
else if(A == 0x8C)
sweep_value = V;
else if(A == 0x8D)
{
sweep_step = V;
sweep_counter = sweep_step + 1;
sweep_8192_divider = 8192;
}
else if(A == 0x8E)
{
noise_control = V;
if(V & 0x8) nreg = 1;
//printf("NOISECONTROL: %02x\n", V);
}
else if(A == 0x90)
{
for(int n = 0; n < 4; n++)
if(!(control & (1 << n)) && (V & (1 << n)))
{
period_counter[n] = 0;
sample_pos[n] = 0x1F;
}
control = V;
//printf("Sound Control: %02x\n", V);
}
else if(A == 0x91)
{
output_control = V & 0xF;
//printf("%02x, %02x\n", V, (V >> 1) & 3);
}
else if(A == 0x92)
nreg = (nreg & 0xFF00) | (V << 0);
else if(A == 0x93)
nreg = (nreg & 0x00FF) | ((V & 0x7F) << 8);
else if(A == 0x94)
{
voice_volume = V & 0xF;
//printf("%02x\n", V);
}
else switch(A)
{
case 0x8F: SampleRAMPos = V; break;
case 0x95: HyperVoice = V; break; // Pick a port, any port?!
//default: printf("%04x:%02x\n", A, V); break;
}
WSwan_SoundUpdate();
}
uint8 WSwan_SoundRead(uint32 A)
{
WSwan_SoundUpdate();
WSwan_SoundUpdate();
if(A >= 0x80 && A <= 0x87)
{
int ch = (A - 0x80) >> 1;
if(A >= 0x80 && A <= 0x87)
{
int ch = (A - 0x80) >> 1;
if(A & 1)
return(period[ch] >> 8);
else
return(period[ch]);
}
else if(A >= 0x88 && A <= 0x8B)
return(volume[A - 0x88]);
else switch(A)
{
default: printf("SoundRead: %04x\n", A); return(0);
case 0x8C: return(sweep_value);
case 0x8D: return(sweep_step);
case 0x8E: return(noise_control);
case 0x8F: return(SampleRAMPos);
case 0x90: return(control);
case 0x91: return(output_control | 0x80);
case 0x92: return((nreg >> 0) & 0xFF);
case 0x93: return((nreg >> 8) & 0xFF);
case 0x94: return(voice_volume);
}
if(A & 1)
return(period[ch] >> 8);
else
return(period[ch]);
}
else if(A >= 0x88 && A <= 0x8B)
return(volume[A - 0x88]);
else switch(A)
{
default:
printf("SoundRead: %04x\n", A);
break;
case 0x8C: return(sweep_value);
case 0x8D: return(sweep_step);
case 0x8E: return(noise_control);
case 0x8F: return(SampleRAMPos);
case 0x90: return(control);
case 0x91: return(output_control | 0x80);
case 0x92: return((nreg >> 0) & 0xFF);
case 0x93: return((nreg >> 8) & 0xFF);
case 0x94: return(voice_volume);
}
return(0);
}
int32 WSwan_SoundFlush(int16 *SoundBuf, const int32 MaxSoundFrames)
{
int32 FrameCount = 0;
int32 FrameCount = 0;
WSwan_SoundUpdate();
WSwan_SoundUpdate();
if(SoundBuf)
{
for(int y = 0; y < 2; y++)
{
sbuf[y]->end_frame(v30mz_timestamp);
FrameCount = sbuf[y]->read_samples(SoundBuf + y, MaxSoundFrames, true);
}
}
if(SoundBuf)
{
for(int y = 0; y < 2; y++)
{
sbuf[y]->end_frame(v30mz_timestamp);
FrameCount = sbuf[y]->read_samples(SoundBuf + y, MaxSoundFrames, true);
}
}
last_ts = 0;
last_ts = 0;
return(FrameCount);
return(FrameCount);
}
// Call before wsRAM is updated
void WSwan_SoundCheckRAMWrite(uint32 A)
{
if((A >> 6) == SampleRAMPos)
WSwan_SoundUpdate();
if((A >> 6) == SampleRAMPos)
WSwan_SoundUpdate();
}
static void RedoVolume(void)
{
double eff_volume = 1.0 / 4;
double eff_volume = 1.0 / 4;
WaveSynth.volume(eff_volume);
NoiseSynth.volume(eff_volume);
VoiceSynth.volume(eff_volume);
WaveSynth.volume(eff_volume);
NoiseSynth.volume(eff_volume);
VoiceSynth.volume(eff_volume);
}
void WSwan_SoundInit(void)
{
for(int i = 0; i < 2; i++)
{
sbuf[i] = new Blip_Buffer();
unsigned i;
for(i = 0; i < 2; i++)
{
sbuf[i] = new Blip_Buffer();
sbuf[i]->set_sample_rate(0 ? 0 : 44100, 60);
sbuf[i]->clock_rate((long)(3072000));
sbuf[i]->bass_freq(20);
}
sbuf[i]->set_sample_rate(0 ? 0 : 44100, 60);
sbuf[i]->clock_rate((long)(3072000));
sbuf[i]->bass_freq(20);
}
RedoVolume();
RedoVolume();
}
void WSwan_SoundKill(void)
@ -378,10 +383,11 @@ void WSwan_SoundKill(void)
bool WSwan_SetSoundRate(uint32 rate)
{
for(int i = 0; i < 2; i++)
sbuf[i]->set_sample_rate(rate?rate:44100, 60);
unsigned i;
for(i = 0; i < 2; i++)
sbuf[i]->set_sample_rate(rate?rate:44100, 60);
return(TRUE);
return(TRUE);
}
int WSwan_SoundStateAction(StateMem *sm, int load, int data_only)
@ -414,29 +420,31 @@ int WSwan_SoundStateAction(StateMem *sm, int load, int data_only)
void WSwan_SoundReset(void)
{
memset(period, 0, sizeof(period));
memset(volume, 0, sizeof(volume));
voice_volume = 0;
sweep_step = 0;
sweep_value = 0;
noise_control = 0;
control = 0;
output_control = 0;
unsigned y;
sweep_8192_divider = 8192;
sweep_counter = 0;
SampleRAMPos = 0;
memset(period_counter, 0, sizeof(period_counter));
memset(sample_pos, 0, sizeof(sample_pos));
nreg = 1;
memset(period, 0, sizeof(period));
memset(volume, 0, sizeof(volume));
voice_volume = 0;
sweep_step = 0;
sweep_value = 0;
noise_control = 0;
control = 0;
output_control = 0;
memset(sample_cache, 0, sizeof(sample_cache));
memset(last_val, 0, sizeof(last_val));
last_v_val = 0;
sweep_8192_divider = 8192;
sweep_counter = 0;
SampleRAMPos = 0;
memset(period_counter, 0, sizeof(period_counter));
memset(sample_pos, 0, sizeof(sample_pos));
nreg = 1;
HyperVoice = 0;
last_hv_val = 0;
memset(sample_cache, 0, sizeof(sample_cache));
memset(last_val, 0, sizeof(last_val));
last_v_val = 0;
for(int y = 0; y < 2; y++)
sbuf[y]->clear();
HyperVoice = 0;
last_hv_val = 0;
for(y = 0; y < 2; y++)
sbuf[y]->clear();
}

View File

@ -60,524 +60,510 @@ extern uint16 WSButtonStatus;
void WSwan_writemem20(uint32 A, uint8 V)
{
uint32 offset, bank;
uint32 offset = A & 0xffff;
uint32 bank = (A>>16) & 0xF;
offset = A & 0xffff;
bank = (A>>16) & 0xF;
if(!bank) /*RAM*/
{
WSwan_SoundCheckRAMWrite(offset);
wsRAM[offset] = V;
if(!bank) /*RAM*/
{
WSwan_SoundCheckRAMWrite(offset);
wsRAM[offset] = V;
WSWan_TCacheInvalidByAddr(offset);
WSWan_TCacheInvalidByAddr(offset);
if(offset>=0xfe00) /*WSC palettes*/
WSwan_GfxWSCPaletteRAMWrite(offset, V);
}
else if(bank == 1) /* SRAM */
{
if(sram_size)
{
wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)] = V;
}
}
if(offset>=0xfe00) /*WSC palettes*/
WSwan_GfxWSCPaletteRAMWrite(offset, V);
}
else if(bank == 1) /* SRAM */
{
if(sram_size)
wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)] = V;
}
}
uint8 WSwan_readmem20(uint32 A)
{
uint32 offset, bank;
uint8 bank_num;
uint32 offset = A & 0xFFFF;
uint32 bank = (A >> 16) & 0xF;
offset = A & 0xFFFF;
bank = (A >> 16) & 0xF;
switch(bank)
{
case 0: return wsRAM[offset];
case 1: if(sram_size)
{
return wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)];
}
else
return(0);
switch(bank)
{
case 0:
return wsRAM[offset];
case 1:
if(sram_size)
return wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)];
return(0);
case 2:
case 3:
return wsCartROM[offset+((BankSelector[bank]&((rom_size>>16)-1))<<16)];
default:
break;
}
case 2:
case 3: return wsCartROM[offset+((BankSelector[bank]&((rom_size>>16)-1))<<16)];
bank_num = ((BankSelector[0] & 0xF) << 4) | (bank & 0xf);
bank_num &= (rom_size >> 16) - 1;
default:
{
uint8 bank_num = ((BankSelector[0] & 0xF) << 4) | (bank & 0xf);
bank_num &= (rom_size >> 16) - 1;
return(wsCartROM[(bank_num << 16) | offset]);
}
}
return(wsCartROM[(bank_num << 16) | offset]);
}
static void ws_CheckDMA(void)
{
if(DMAControl & 0x80)
{
while(DMALength)
{
WSwan_writemem20(DMADest, WSwan_readmem20(DMASource));
if(DMAControl & 0x80)
{
while(DMALength)
{
WSwan_writemem20(DMADest, WSwan_readmem20(DMASource));
DMASource++; // = ((DMASource + 1) & 0xFFFF) | (DMASource & 0xFF0000);
//if(!(DMASource & 0xFFFF)) puts("Warning: DMA source bank crossed.");
DMADest = ((DMADest + 1) & 0xFFFF) | (DMADest & 0xFF0000);
DMALength--;
}
}
DMAControl &= ~0x80;
DMASource++; // = ((DMASource + 1) & 0xFFFF) | (DMASource & 0xFF0000);
//if(!(DMASource & 0xFFFF)) puts("Warning: DMA source bank crossed.");
DMADest = ((DMADest + 1) & 0xFFFF) | (DMADest & 0xFF0000);
DMALength--;
}
}
DMAControl &= ~0x80;
}
void WSwan_CheckSoundDMA(void)
{
if(SoundDMAControl & 0x80)
{
if(SoundDMALength)
{
uint8 zebyte = WSwan_readmem20(SoundDMASource);
if(SoundDMAControl & 0x80)
{
if(SoundDMALength)
{
uint8 zebyte = WSwan_readmem20(SoundDMASource);
if(SoundDMAControl & 0x08)
zebyte ^= 0x80;
if(SoundDMAControl & 0x08)
zebyte ^= 0x80;
if(SoundDMAControl & 0x10)
WSwan_SoundWrite(0x95, zebyte); // Pick a port, any port?!
else
WSwan_SoundWrite(0x89, zebyte);
if(SoundDMAControl & 0x10)
WSwan_SoundWrite(0x95, zebyte); // Pick a port, any port?!
else
WSwan_SoundWrite(0x89, zebyte);
SoundDMASource++; // = ((SoundDMASource + 1) & 0xFFFF) | (SoundDMASource & 0xFF0000);
//if(!(SoundDMASource & 0xFFFF)) puts("Warning: Sound DMA source bank crossed.");
SoundDMALength--;
}
if(!SoundDMALength)
SoundDMAControl &= ~0x80;
}
SoundDMASource++; // = ((SoundDMASource + 1) & 0xFFFF) | (SoundDMASource & 0xFF0000);
//if(!(SoundDMASource & 0xFFFF)) puts("Warning: Sound DMA source bank crossed.");
SoundDMALength--;
}
if(!SoundDMALength)
SoundDMAControl &= ~0x80;
}
}
uint8 WSwan_readport(uint32 number)
{
number &= 0xFF;
number &= 0xFF;
if(number >= 0x80 && number <= 0x9F)
return(WSwan_SoundRead(number));
else if(number <= 0x3F || (number >= 0xA0 && number <= 0xAF) || (number == 0x60))
return(WSwan_GfxRead(number));
else if((number >= 0xBA && number <= 0xBE) || (number >= 0xC4 && number <= 0xC8))
return(WSwan_EEPROMRead(number));
else if(number >= 0xCA && number <= 0xCB)
return(WSwan_RTCRead(number));
else switch(number)
{
//default: printf("Read: %04x\n", number); break;
case 0x40: return(DMASource >> 0);
case 0x41: return(DMASource >> 8);
case 0x42: return(DMASource >> 16);
if(number >= 0x80 && number <= 0x9F)
return(WSwan_SoundRead(number));
else if(number <= 0x3F || (number >= 0xA0 && number <= 0xAF) || (number == 0x60))
return(WSwan_GfxRead(number));
else if((number >= 0xBA && number <= 0xBE) || (number >= 0xC4 && number <= 0xC8))
return(WSwan_EEPROMRead(number));
else if(number >= 0xCA && number <= 0xCB)
return(WSwan_RTCRead(number));
else switch(number)
{
//default: printf("Read: %04x\n", number); break;
case 0x40: return(DMASource >> 0);
case 0x41: return(DMASource >> 8);
case 0x42: return(DMASource >> 16);
case 0x43: return(DMADest >> 16);
case 0x44: return(DMADest >> 0);
case 0x45: return(DMADest >> 8);
case 0x43: return(DMADest >> 16);
case 0x44: return(DMADest >> 0);
case 0x45: return(DMADest >> 8);
case 0x46: return(DMALength >> 0);
case 0x47: return(DMALength >> 8);
case 0x46: return(DMALength >> 0);
case 0x47: return(DMALength >> 8);
case 0x48: return(DMAControl);
case 0x48: return(DMAControl);
case 0xB0:
case 0xB2:
case 0xB6: return(WSwan_InterruptRead(number));
case 0xB0:
case 0xB2:
case 0xB6: return(WSwan_InterruptRead(number));
case 0xC0: return(BankSelector[0] | 0x20);
case 0xC1: return(BankSelector[1]);
case 0xC2: return(BankSelector[2]);
case 0xC3: return(BankSelector[3]);
case 0xC0: return(BankSelector[0] | 0x20);
case 0xC1: return(BankSelector[1]);
case 0xC2: return(BankSelector[2]);
case 0xC3: return(BankSelector[3]);
case 0x4a: return(SoundDMASource >> 0);
case 0x4b: return(SoundDMASource >> 8);
case 0x4c: return(SoundDMASource >> 16);
case 0x4e: return(SoundDMALength >> 0);
case 0x4f: return(SoundDMALength >> 8);
case 0x52: return(SoundDMAControl);
case 0x4a: return(SoundDMASource >> 0);
case 0x4b: return(SoundDMASource >> 8);
case 0x4c: return(SoundDMASource >> 16);
case 0x4e: return(SoundDMALength >> 0);
case 0x4f: return(SoundDMALength >> 8);
case 0x52: return(SoundDMAControl);
case 0xB1: return(CommData);
case 0xB1: return(CommData);
case 0xb3:
{
uint8 ret = CommControl & 0xf0;
case 0xb3:
{
uint8 ret = CommControl & 0xf0;
if(CommControl & 0x80)
ret |= 0x4; // Send complete
if(CommControl & 0x80)
ret |= 0x4; // Send complete
return(ret);
}
case 0xb5:
{
uint8 ret = (ButtonWhich << 4) | ButtonReadLatch;
return(ret);
}
}
return(ret);
}
case 0xb5:
{
uint8 ret = (ButtonWhich << 4) | ButtonReadLatch;
return(ret);
}
}
if(number >= 0xC8)
return(0xD0 | language);
if(number >= 0xC8)
return(0xD0 | language);
return(0);
return(0);
}
void WSwan_writeport(uint32 IOPort, uint8 V)
{
IOPort &= 0xFF;
IOPort &= 0xFF;
if(IOPort >= 0x80 && IOPort <= 0x9F)
{
WSwan_SoundWrite(IOPort, V);
}
else if((IOPort >= 0x00 && IOPort <= 0x3F) || (IOPort >= 0xA0 && IOPort <= 0xAF) || (IOPort == 0x60))
{
WSwan_GfxWrite(IOPort, V);
}
else if((IOPort >= 0xBA && IOPort <= 0xBE) || (IOPort >= 0xC4 && IOPort <= 0xC8))
WSwan_EEPROMWrite(IOPort, V);
else if(IOPort >= 0xCA && IOPort <= 0xCB)
WSwan_RTCWrite(IOPort, V);
else switch(IOPort)
{
//default: printf("%04x %02x\n", IOPort, V); break;
if(IOPort >= 0x80 && IOPort <= 0x9F)
WSwan_SoundWrite(IOPort, V);
else if((IOPort >= 0x00 && IOPort <= 0x3F) || (IOPort >= 0xA0 && IOPort <= 0xAF) || (IOPort == 0x60))
WSwan_GfxWrite(IOPort, V);
else if((IOPort >= 0xBA && IOPort <= 0xBE) || (IOPort >= 0xC4 && IOPort <= 0xC8))
WSwan_EEPROMWrite(IOPort, V);
else if(IOPort >= 0xCA && IOPort <= 0xCB)
WSwan_RTCWrite(IOPort, V);
else switch(IOPort)
{
//default: printf("%04x %02x\n", IOPort, V); break;
case 0x40: DMASource &= 0xFFFF00; DMASource |= (V << 0); break;
case 0x41: DMASource &= 0xFF00FF; DMASource |= (V << 8); break;
case 0x42: DMASource &= 0x00FFFF; DMASource |= ((V & 0x0F) << 16); break;
case 0x40: DMASource &= 0xFFFF00; DMASource |= (V << 0); break;
case 0x41: DMASource &= 0xFF00FF; DMASource |= (V << 8); break;
case 0x42: DMASource &= 0x00FFFF; DMASource |= ((V & 0x0F) << 16); break;
case 0x43: DMADest &= 0x00FFFF; DMADest |= ((V & 0x0F) << 16); break;
case 0x44: DMADest &= 0xFFFF00; DMADest |= (V << 0); break;
case 0x45: DMADest &= 0xFF00FF; DMADest |= (V << 8); break;
case 0x43: DMADest &= 0x00FFFF; DMADest |= ((V & 0x0F) << 16); break;
case 0x44: DMADest &= 0xFFFF00; DMADest |= (V << 0); break;
case 0x45: DMADest &= 0xFF00FF; DMADest |= (V << 8); break;
case 0x46: DMALength &= 0xFF00; DMALength |= (V << 0); break;
case 0x47: DMALength &= 0x00FF; DMALength |= (V << 8); break;
case 0x46: DMALength &= 0xFF00; DMALength |= (V << 0); break;
case 0x47: DMALength &= 0x00FF; DMALength |= (V << 8); break;
case 0x48: DMAControl = V;
//if(V&0x80)
// printf("DMA%02x: %08x %08x %08x\n", V, DMASource, DMADest, DMALength);
ws_CheckDMA();
break;
case 0x48: DMAControl = V;
//if(V&0x80)
// printf("DMA%02x: %08x %08x %08x\n", V, DMASource, DMADest, DMALength);
ws_CheckDMA();
break;
case 0x4a: SoundDMASource &= 0xFFFF00; SoundDMASource |= (V << 0); break;
case 0x4b: SoundDMASource &= 0xFF00FF; SoundDMASource |= (V << 8); break;
case 0x4c: SoundDMASource &= 0x00FFFF; SoundDMASource |= (V << 16); break;
//case 0x4d: break; // Unused?
case 0x4e: SoundDMALength &= 0xFF00; SoundDMALength |= (V << 0); break;
case 0x4f: SoundDMALength &= 0x00FF; SoundDMALength |= (V << 8); break;
//case 0x50: break; // Unused?
//case 0x51: break; // Unused?
case 0x52: SoundDMAControl = V;
//if(V & 0x80) printf("Sound DMA: %02x, %08x %08x\n", V, SoundDMASource, SoundDMALength);
break;
case 0x4a: SoundDMASource &= 0xFFFF00; SoundDMASource |= (V << 0); break;
case 0x4b: SoundDMASource &= 0xFF00FF; SoundDMASource |= (V << 8); break;
case 0x4c: SoundDMASource &= 0x00FFFF; SoundDMASource |= (V << 16); break;
//case 0x4d: break; // Unused?
case 0x4e: SoundDMALength &= 0xFF00; SoundDMALength |= (V << 0); break;
case 0x4f: SoundDMALength &= 0x00FF; SoundDMALength |= (V << 8); break;
//case 0x50: break; // Unused?
//case 0x51: break; // Unused?
case 0x52: SoundDMAControl = V;
//if(V & 0x80) printf("Sound DMA: %02x, %08x %08x\n", V, SoundDMASource, SoundDMALength);
break;
case 0xB0:
case 0xB2:
case 0xB6: WSwan_InterruptWrite(IOPort, V); break;
case 0xB0:
case 0xB2:
case 0xB6: WSwan_InterruptWrite(IOPort, V); break;
case 0xB1: CommData = V; break;
case 0xB3: CommControl = V & 0xF0; break;
case 0xB1: CommData = V; break;
case 0xB3: CommControl = V & 0xF0; break;
case 0xb5: ButtonWhich = V >> 4;
ButtonReadLatch = 0;
case 0xb5: ButtonWhich = V >> 4;
ButtonReadLatch = 0;
if(ButtonWhich & 0x4) /*buttons*/
ButtonReadLatch |= ((WSButtonStatus >> 8) << 1) & 0xF;
if(ButtonWhich & 0x4) /*buttons*/
ButtonReadLatch |= ((WSButtonStatus >> 8) << 1) & 0xF;
if(ButtonWhich & 0x2) /* H/X cursors */
ButtonReadLatch |= WSButtonStatus & 0xF;
if(ButtonWhich & 0x2) /* H/X cursors */
ButtonReadLatch |= WSButtonStatus & 0xF;
if(ButtonWhich & 0x1) /* V/Y cursors */
ButtonReadLatch |= (WSButtonStatus >> 4) & 0xF;
break;
if(ButtonWhich & 0x1) /* V/Y cursors */
ButtonReadLatch |= (WSButtonStatus >> 4) & 0xF;
break;
case 0xC0: BankSelector[0] = V & 0xF; break;
case 0xC1: BankSelector[1] = V; break;
case 0xC2: BankSelector[2] = V; break;
case 0xC3: BankSelector[3] = V; break;
}
case 0xC0: BankSelector[0] = V & 0xF; break;
case 0xC1: BankSelector[1] = V; break;
case 0xC2: BankSelector[2] = V; break;
case 0xC3: BankSelector[3] = V; break;
}
}
#ifdef WANT_DEBUGGER
static void GetAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint8 *Buffer)
{
if(!strcmp(name, "ram"))
{
while(Length--)
{
Address &= wsRAMSize - 1;
*Buffer = wsRAM[Address];
Address++;
Buffer++;
}
}
else if(!strcmp(name, "physical"))
{
while(Length--)
{
Address &= 0xFFFFF;
*Buffer = WSwan_readmem20(Address);
Address++;
Buffer++;
}
}
else if(!strcmp(name, "cs") || !strcmp(name, "ds") || !strcmp(name, "ss") || !strcmp(name, "es"))
{
uint32 segment;
uint32 phys_address;
if(!strcmp(name, "ram"))
{
while(Length--)
{
Address &= wsRAMSize - 1;
*Buffer = wsRAM[Address];
Address++;
Buffer++;
}
}
else if(!strcmp(name, "physical"))
{
while(Length--)
{
Address &= 0xFFFFF;
*Buffer = WSwan_readmem20(Address);
Address++;
Buffer++;
}
}
else if(!strcmp(name, "cs") || !strcmp(name, "ds") || !strcmp(name, "ss") || !strcmp(name, "es"))
{
uint32 segment;
uint32 phys_address;
if(!strcmp(name, "cs"))
segment = v30mz_get_reg(NEC_PS);
else if(!strcmp(name, "ss"))
segment = v30mz_get_reg(NEC_SS);
else if(!strcmp(name, "ds"))
segment = v30mz_get_reg(NEC_DS0);
else if(!strcmp(name, "es"))
segment = v30mz_get_reg(NEC_DS1);
if(!strcmp(name, "cs"))
segment = v30mz_get_reg(NEC_PS);
else if(!strcmp(name, "ss"))
segment = v30mz_get_reg(NEC_SS);
else if(!strcmp(name, "ds"))
segment = v30mz_get_reg(NEC_DS0);
else if(!strcmp(name, "es"))
segment = v30mz_get_reg(NEC_DS1);
phys_address = (Address + (segment << 4)) & 0xFFFFF;
phys_address = (Address + (segment << 4)) & 0xFFFFF;
GetAddressSpaceBytes("physical", phys_address, Length, Buffer);
}
GetAddressSpaceBytes("physical", phys_address, Length, Buffer);
}
}
static void PutAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer)
{
if(!strcmp(name, "ram"))
{
while(Length--)
{
Address &= wsRAMSize - 1;
wsRAM[Address] = *Buffer;
WSWan_TCacheInvalidByAddr(Address);
if(Address >= 0xfe00)
WSwan_GfxWSCPaletteRAMWrite(Address, *Buffer);
Address++;
Buffer++;
}
}
else if(!strcmp(name, "physical"))
{
while(Length--)
{
uint32 offset, bank;
Address &= 0xFFFFF;
offset = Address & 0xFFFF;
bank = (Address >> 16) & 0xF;
switch(bank)
if(!strcmp(name, "ram"))
{
case 0: wsRAM[offset & (wsRAMSize - 1)] = *Buffer;
WSWan_TCacheInvalidByAddr(offset & (wsRAMSize - 1));
if(Address >= 0xfe00)
WSwan_GfxWSCPaletteRAMWrite(offset & (wsRAMSize - 1), *Buffer);
break;
case 1: if(sram_size)
wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)] = *Buffer;
break;
case 2:
case 3: wsCartROM[offset+((BankSelector[bank]&((rom_size>>16)-1))<<16)] = *Buffer;
break;
while(Length--)
{
Address &= wsRAMSize - 1;
wsRAM[Address] = *Buffer;
WSWan_TCacheInvalidByAddr(Address);
if(Address >= 0xfe00)
WSwan_GfxWSCPaletteRAMWrite(Address, *Buffer);
default:
{
uint8 bank_num = ((BankSelector[0] & 0xF) << 4) | (bank & 0xf);
bank_num &= (rom_size >> 16) - 1;
wsCartROM[(bank_num << 16) | offset] = *Buffer;
}
break;
Address++;
Buffer++;
}
}
else if(!strcmp(name, "physical"))
{
while(Length--)
{
uint32 offset, bank;
Address++;
Buffer++;
}
}
else if(!strcmp(name, "cs") || !strcmp(name, "ds") || !strcmp(name, "ss") || !strcmp(name, "es"))
{
uint32 segment;
uint32 phys_address;
Address &= 0xFFFFF;
if(!strcmp(name, "cs"))
segment = v30mz_get_reg(NEC_PS);
else if(!strcmp(name, "ss"))
segment = v30mz_get_reg(NEC_SS);
else if(!strcmp(name, "ds"))
segment = v30mz_get_reg(NEC_DS0);
else if(!strcmp(name, "es"))
segment = v30mz_get_reg(NEC_DS1);
offset = Address & 0xFFFF;
bank = (Address >> 16) & 0xF;
phys_address = (Address + (segment << 4)) & 0xFFFFF;
switch(bank)
{
case 0: wsRAM[offset & (wsRAMSize - 1)] = *Buffer;
WSWan_TCacheInvalidByAddr(offset & (wsRAMSize - 1));
if(Address >= 0xfe00)
WSwan_GfxWSCPaletteRAMWrite(offset & (wsRAMSize - 1), *Buffer);
break;
case 1: if(sram_size)
wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)] = *Buffer;
break;
case 2:
case 3: wsCartROM[offset+((BankSelector[bank]&((rom_size>>16)-1))<<16)] = *Buffer;
break;
PutAddressSpaceBytes("physical", phys_address, Length, Granularity, hl, Buffer);
}
default:
{
uint8 bank_num = ((BankSelector[0] & 0xF) << 4) | (bank & 0xf);
bank_num &= (rom_size >> 16) - 1;
wsCartROM[(bank_num << 16) | offset] = *Buffer;
}
break;
}
Address++;
Buffer++;
}
}
else if(!strcmp(name, "cs") || !strcmp(name, "ds") || !strcmp(name, "ss") || !strcmp(name, "es"))
{
uint32 segment;
uint32 phys_address;
if(!strcmp(name, "cs"))
segment = v30mz_get_reg(NEC_PS);
else if(!strcmp(name, "ss"))
segment = v30mz_get_reg(NEC_SS);
else if(!strcmp(name, "ds"))
segment = v30mz_get_reg(NEC_DS0);
else if(!strcmp(name, "es"))
segment = v30mz_get_reg(NEC_DS1);
phys_address = (Address + (segment << 4)) & 0xFFFFF;
PutAddressSpaceBytes("physical", phys_address, Length, Granularity, hl, Buffer);
}
}
uint32 WSwan_MemoryGetRegister(const unsigned int id, char *special, const uint32 special_len)
{
uint32 ret = 0;
uint32 ret = 0;
switch(id)
{
case MEMORY_GSREG_ROMBBSLCT:
ret = BankSelector[0];
switch(id)
{
case MEMORY_GSREG_ROMBBSLCT:
ret = BankSelector[0];
if(special)
{
trio_snprintf(special, special_len, "((0x%02x * 0x100000) %% 0x%08x) + 20 bit address = 0x%08x + 20 bit address", BankSelector[0], rom_size, (BankSelector[0] * 0x100000) & (rom_size - 1));
}
break;
if(special)
{
trio_snprintf(special, special_len, "((0x%02x * 0x100000) %% 0x%08x) + 20 bit address = 0x%08x + 20 bit address", BankSelector[0], rom_size, (BankSelector[0] * 0x100000) & (rom_size - 1));
}
break;
case MEMORY_GSREG_BNK1SLCT:
ret = BankSelector[1];
break;
case MEMORY_GSREG_BNK1SLCT:
ret = BankSelector[1];
break;
case MEMORY_GSREG_BNK2SLCT:
ret = BankSelector[2];
break;
case MEMORY_GSREG_BNK2SLCT:
ret = BankSelector[2];
break;
case MEMORY_GSREG_BNK3SLCT:
ret = BankSelector[3];
break;
}
case MEMORY_GSREG_BNK3SLCT:
ret = BankSelector[3];
break;
}
return(ret);
return(ret);
}
void WSwan_MemorySetRegister(const unsigned int id, uint32 value)
{
switch(id)
{
case MEMORY_GSREG_ROMBBSLCT:
BankSelector[0] = value;
break;
switch(id)
{
case MEMORY_GSREG_ROMBBSLCT:
BankSelector[0] = value;
break;
case MEMORY_GSREG_BNK1SLCT:
BankSelector[1] = value;
break;
case MEMORY_GSREG_BNK1SLCT:
BankSelector[1] = value;
break;
case MEMORY_GSREG_BNK2SLCT:
BankSelector[2] = value;
break;
case MEMORY_GSREG_BNK2SLCT:
BankSelector[2] = value;
break;
case MEMORY_GSREG_BNK3SLCT:
BankSelector[3] = value;
break;
}
case MEMORY_GSREG_BNK3SLCT:
BankSelector[3] = value;
break;
}
}
#endif
void WSwan_MemoryKill(void)
{
if((sram_size || eeprom_size) && !SkipSL)
{
std::vector<PtrLengthPair> EvilRams;
if((sram_size || eeprom_size) && !SkipSL)
{
std::vector<PtrLengthPair> EvilRams;
if(eeprom_size)
EvilRams.push_back(PtrLengthPair(wsEEPROM, eeprom_size));
if(eeprom_size)
EvilRams.push_back(PtrLengthPair(wsEEPROM, eeprom_size));
if(sram_size)
EvilRams.push_back(PtrLengthPair(wsSRAM, sram_size));
if(sram_size)
EvilRams.push_back(PtrLengthPair(wsSRAM, sram_size));
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, EvilRams);
}
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, EvilRams);
}
if(wsSRAM)
{
free(wsSRAM);
wsSRAM = NULL;
}
if(wsSRAM)
free(wsSRAM);
wsSRAM = NULL;
}
void WSwan_MemoryInit(bool lang, bool IsWSC, uint32 ssize, bool SkipSaveLoad)
{
const uint16 byear = MDFN_GetSettingUI("wswan.byear");
const uint8 bmonth = MDFN_GetSettingUI("wswan.bmonth");
const uint8 bday = MDFN_GetSettingUI("wswan.bday");
const uint8 sex = MDFN_GetSettingI("wswan.sex");
const uint8 blood = MDFN_GetSettingI("wswan.blood");
const uint16 byear = MDFN_GetSettingUI("wswan.byear");
const uint8 bmonth = MDFN_GetSettingUI("wswan.bmonth");
const uint8 bday = MDFN_GetSettingUI("wswan.bday");
const uint8 sex = MDFN_GetSettingI("wswan.sex");
const uint8 blood = MDFN_GetSettingI("wswan.blood");
language = lang;
SkipSL = SkipSaveLoad;
language = lang;
SkipSL = SkipSaveLoad;
wsRAMSize = 65536;
sram_size = ssize;
wsRAMSize = 65536;
sram_size = ssize;
#ifdef WANT_DEBUGGER
{
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "physical", "CPU Physical", 20);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ram", "RAM", (int)(log(wsRAMSize) / log(2)));
#ifdef WANT_DEBUGGER
{
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "physical", "CPU Physical", 20);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ram", "RAM", (int)(log(wsRAMSize) / log(2)));
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "cs", "Code Segment", 16);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ss", "Stack Segment", 16);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ds", "Data Segment", 16);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "es", "Extra Segment", 16);
}
#endif
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "cs", "Code Segment", 16);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ss", "Stack Segment", 16);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ds", "Data Segment", 16);
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "es", "Extra Segment", 16);
}
#endif
// WSwan_EEPROMInit() will also clear wsEEPROM
WSwan_EEPROMInit(MDFN_GetSettingS("wswan.name").c_str(), byear, bmonth, bday, sex, blood);
// WSwan_EEPROMInit() will also clear wsEEPROM
WSwan_EEPROMInit(MDFN_GetSettingS("wswan.name").c_str(), byear, bmonth, bday, sex, blood);
if(sram_size)
{
wsSRAM = (uint8*)malloc(sram_size);
memset(wsSRAM, 0, sram_size);
}
if((sram_size || eeprom_size) && !SkipSL)
{
FILE *savegame_fp;
savegame_fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb");
if(savegame_fp)
{
if(eeprom_size)
gzread(savegame_fp, wsEEPROM, eeprom_size);
if(sram_size)
gzread(savegame_fp, wsSRAM, sram_size);
gzclose(savegame_fp);
}
}
{
wsSRAM = (uint8*)malloc(sram_size);
memset(wsSRAM, 0, sram_size);
}
MDFNMP_AddRAM(wsRAMSize, 0x00000, wsRAM);
if((sram_size || eeprom_size) && !SkipSL)
{
FILE *savegame_fp;
if(sram_size)
MDFNMP_AddRAM(sram_size, 0x10000, wsSRAM);
savegame_fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb");
if(savegame_fp)
{
if(eeprom_size)
gzread(savegame_fp, wsEEPROM, eeprom_size);
if(sram_size)
gzread(savegame_fp, wsSRAM, sram_size);
gzclose(savegame_fp);
}
}
MDFNMP_AddRAM(wsRAMSize, 0x00000, wsRAM);
if(sram_size)
MDFNMP_AddRAM(sram_size, 0x10000, wsSRAM);
}
void WSwan_MemoryReset(void)
{
memset(wsRAM, 0, 65536);
memset(wsRAM, 0, 65536);
wsRAM[0x75AC] = 0x41;
wsRAM[0x75AD] = 0x5F;
wsRAM[0x75AE] = 0x43;
wsRAM[0x75AF] = 0x31;
wsRAM[0x75B0] = 0x6E;
wsRAM[0x75B1] = 0x5F;
wsRAM[0x75B2] = 0x63;
wsRAM[0x75B3] = 0x31;
wsRAM[0x75AC] = 0x41;
wsRAM[0x75AD] = 0x5F;
wsRAM[0x75AE] = 0x43;
wsRAM[0x75AF] = 0x31;
wsRAM[0x75B0] = 0x6E;
wsRAM[0x75B1] = 0x5F;
wsRAM[0x75B2] = 0x63;
wsRAM[0x75B3] = 0x31;
memset(BankSelector, 0, sizeof(BankSelector));
ButtonWhich = 0;
ButtonReadLatch = 0;
DMASource = 0;
DMADest = 0;
DMALength = 0;
DMAControl = 0;
memset(BankSelector, 0, sizeof(BankSelector));
ButtonWhich = 0;
ButtonReadLatch = 0;
DMASource = 0;
DMADest = 0;
DMALength = 0;
DMAControl = 0;
SoundDMASource = 0;
SoundDMALength = 0;
SoundDMAControl = 0;
SoundDMASource = 0;
SoundDMALength = 0;
SoundDMAControl = 0;
CommControl = 0;
CommData = 0;
CommControl = 0;
CommData = 0;
}
int WSwan_MemoryStateAction(StateMem *sm, int load, int data_only)