GBHawk: more transformation work
This commit is contained in:
parent
373a05dcb4
commit
79fecef41b
|
@ -1,442 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace GBHawk
|
||||
{
|
||||
class AY_3_8910
|
||||
{
|
||||
public:
|
||||
|
||||
#pragma region AY_3_8910
|
||||
|
||||
AY_3_8910()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool A_on, B_on, C_on;
|
||||
bool A_up, B_up, C_up;
|
||||
bool A_noise, B_noise, C_noise;
|
||||
bool env_vol_A, env_vol_B, env_vol_C;
|
||||
|
||||
uint8_t env_shape;
|
||||
uint8_t port_sel;
|
||||
uint8_t vol_A, vol_B, vol_C;
|
||||
uint8_t Register[16] = {};
|
||||
|
||||
uint32_t psg_clock;
|
||||
uint32_t sq_per_A, sq_per_B, sq_per_C;
|
||||
uint32_t clock_A, clock_B, clock_C;
|
||||
|
||||
uint32_t env_per;
|
||||
uint32_t env_clock;
|
||||
|
||||
int32_t env_E;
|
||||
int32_t E_up_down;
|
||||
|
||||
uint32_t noise_clock;
|
||||
uint32_t noise_per;
|
||||
uint32_t noise = 0x1;
|
||||
|
||||
int32_t old_sample;
|
||||
|
||||
// non stated if only on frame boundaries
|
||||
bool sound_out_A;
|
||||
bool sound_out_B;
|
||||
bool sound_out_C;
|
||||
|
||||
uint8_t Clock_Divider;
|
||||
|
||||
int32_t current_sample;
|
||||
uint32_t sampleclock;
|
||||
uint32_t num_samples;
|
||||
int32_t samples[9000] = {};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
clock_A = clock_B = clock_C = 0x1000;
|
||||
noise_clock = 0x20;
|
||||
port_sel = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
Register[i] = 0x0;
|
||||
}
|
||||
sync_psg_state();
|
||||
}
|
||||
|
||||
short Sample()
|
||||
{
|
||||
return current_sample;
|
||||
}
|
||||
|
||||
const uint32_t VolumeTable[16] =
|
||||
{
|
||||
0x0000, 0x0055, 0x0079, 0x00AB, 0x00F1, 0x0155, 0x01E3, 0x02AA,
|
||||
0x03C5, 0x0555, 0x078B, 0x0AAB, 0x0F16, 0x1555, 0x1E2B, 0x2AAA
|
||||
};
|
||||
|
||||
uint8_t ReadReg()
|
||||
{
|
||||
return Register[port_sel];
|
||||
}
|
||||
|
||||
void sync_psg_state()
|
||||
{
|
||||
sq_per_A = (Register[0] & 0xFF) | (((Register[1] & 0xF) << 8));
|
||||
if (sq_per_A == 0)
|
||||
{
|
||||
sq_per_A = 0x1000;
|
||||
}
|
||||
|
||||
sq_per_B = (Register[2] & 0xFF) | (((Register[3] & 0xF) << 8));
|
||||
if (sq_per_B == 0)
|
||||
{
|
||||
sq_per_B = 0x1000;
|
||||
}
|
||||
|
||||
sq_per_C = (Register[4] & 0xFF) | (((Register[5] & 0xF) << 8));
|
||||
if (sq_per_C == 0)
|
||||
{
|
||||
sq_per_C = 0x1000;
|
||||
}
|
||||
|
||||
env_per = (Register[11] & 0xFF) | (((Register[12] & 0xFF) << 8));
|
||||
if (env_per == 0)
|
||||
{
|
||||
env_per = 0x10000;
|
||||
}
|
||||
|
||||
env_per *= 2;
|
||||
|
||||
A_on = (Register[7] & 0x1) > 0;
|
||||
B_on = (Register[7] & 0x2) > 0;
|
||||
C_on = (Register[7] & 0x4) > 0;
|
||||
A_noise = (Register[7] & 0x8) > 0;
|
||||
B_noise = (Register[7] & 0x10) > 0;
|
||||
C_noise = (Register[7] & 0x20) > 0;
|
||||
|
||||
noise_per = Register[6] & 0x1F;
|
||||
if (noise_per == 0)
|
||||
{
|
||||
noise_per = 0x20;
|
||||
}
|
||||
|
||||
uint8_t shape_select = Register[13] & 0xF;
|
||||
|
||||
if (shape_select < 4) { env_shape = 0; }
|
||||
else if (shape_select < 8) { env_shape = 1; }
|
||||
else { env_shape = 2 + (shape_select - 8); }
|
||||
|
||||
vol_A = Register[8] & 0xF;
|
||||
env_vol_A = ((Register[8] >> 4) & 0x1) > 0;
|
||||
|
||||
vol_B = Register[9] & 0xF;
|
||||
env_vol_B = ((Register[9] >> 4) & 0x1) > 0;
|
||||
|
||||
vol_C = Register[10] & 0xF;
|
||||
env_vol_C = ((Register[10] >> 4) & 0x1) > 0;
|
||||
}
|
||||
|
||||
void WriteReg(uint8_t value)
|
||||
{
|
||||
value &= 0xFF;
|
||||
|
||||
if (port_sel != 0xE) { Register[port_sel] = value; }
|
||||
|
||||
|
||||
sync_psg_state();
|
||||
|
||||
if (port_sel == 13)
|
||||
{
|
||||
env_clock = env_per;
|
||||
|
||||
if (env_shape == 0 || env_shape == 2 || env_shape == 3 || env_shape == 4 || env_shape == 5)
|
||||
{
|
||||
env_E = 15;
|
||||
E_up_down = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
env_E = 0;
|
||||
E_up_down = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generate_sound()
|
||||
{
|
||||
// there are 8 cpu cycles for every psg cycle
|
||||
clock_A--;
|
||||
clock_B--;
|
||||
clock_C--;
|
||||
|
||||
noise_clock--;
|
||||
env_clock--;
|
||||
|
||||
// clock noise
|
||||
if (noise_clock == 0)
|
||||
{
|
||||
noise = (noise >> 1) ^ (((noise &0x1) > 0) ? 0x10004 : 0);
|
||||
noise_clock = noise_per;
|
||||
}
|
||||
|
||||
if (env_clock == 0)
|
||||
{
|
||||
env_clock = env_per;
|
||||
|
||||
env_E += E_up_down;
|
||||
|
||||
if (env_E == 16 || env_E == -1)
|
||||
{
|
||||
// we just completed a period of the envelope, determine what to do now based on the envelope shape
|
||||
if (env_shape == 0 || env_shape == 1 || env_shape == 3 || env_shape == 9)
|
||||
{
|
||||
E_up_down = 0;
|
||||
env_E = 0;
|
||||
}
|
||||
else if (env_shape == 5 || env_shape == 7)
|
||||
{
|
||||
E_up_down = 0;
|
||||
env_E = 15;
|
||||
}
|
||||
else if (env_shape == 4 || env_shape == 8)
|
||||
{
|
||||
if (env_E == 16)
|
||||
{
|
||||
env_E = 15;
|
||||
E_up_down = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
env_E = 0;
|
||||
E_up_down = 1;
|
||||
}
|
||||
}
|
||||
else if (env_shape == 2)
|
||||
{
|
||||
env_E = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
env_E = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clock_A == 0)
|
||||
{
|
||||
A_up = !A_up;
|
||||
clock_A = sq_per_A;
|
||||
}
|
||||
|
||||
if (clock_B == 0)
|
||||
{
|
||||
B_up = !B_up;
|
||||
clock_B = sq_per_B;
|
||||
}
|
||||
|
||||
if (clock_C == 0)
|
||||
{
|
||||
C_up = !C_up;
|
||||
clock_C = sq_per_C;
|
||||
}
|
||||
|
||||
sound_out_A = (((noise & 0x1) > 0) | A_noise) & (A_on | A_up);
|
||||
sound_out_B = (((noise & 0x1) > 0) | B_noise) & (B_on | B_up);
|
||||
sound_out_C = (((noise & 0x1) > 0) | C_noise) & (C_on | C_up);
|
||||
|
||||
// now calculate the volume of each channel and add them together
|
||||
current_sample = 0;
|
||||
|
||||
if (env_vol_A)
|
||||
{
|
||||
current_sample = (sound_out_A ? VolumeTable[env_E] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_sample = (sound_out_A ? VolumeTable[vol_A] : 0);
|
||||
}
|
||||
|
||||
if (env_vol_B)
|
||||
{
|
||||
current_sample += (sound_out_B ? VolumeTable[env_E] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_sample += (sound_out_B ? VolumeTable[vol_B] : 0);
|
||||
}
|
||||
|
||||
if (env_vol_C)
|
||||
{
|
||||
current_sample += (sound_out_C ? VolumeTable[env_E] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_sample += (sound_out_C ? VolumeTable[vol_C] : 0);
|
||||
}
|
||||
|
||||
current_sample *= 2;
|
||||
|
||||
if ((current_sample != old_sample) && (num_samples < 4500))
|
||||
{
|
||||
samples[num_samples * 2] = sampleclock;
|
||||
samples[num_samples * 2 + 1] = current_sample - old_sample;
|
||||
num_samples++;
|
||||
old_sample = current_sample;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region State Save / Load
|
||||
|
||||
uint8_t* SaveState(uint8_t* saver)
|
||||
{
|
||||
*saver = (uint8_t)(A_on ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(B_on ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(C_on ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(A_up ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(B_up ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(C_up ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(A_noise ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(B_noise ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(C_noise ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(env_vol_A ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(env_vol_B ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(env_vol_C ? 1 : 0); saver++;
|
||||
|
||||
*saver = env_shape; saver++;
|
||||
*saver = port_sel; saver++;
|
||||
*saver = vol_A; saver++;
|
||||
*saver = vol_B; saver++;
|
||||
*saver = vol_C; saver++;
|
||||
|
||||
for (int i = 0; i < 16; i++) { *saver = Register[i]; saver++; }
|
||||
|
||||
*saver = (uint8_t)(psg_clock & 0xFF); saver++; *saver = (uint8_t)((psg_clock >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((psg_clock >> 16) & 0xFF); saver++; *saver = (uint8_t)((psg_clock >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(sq_per_A & 0xFF); saver++; *saver = (uint8_t)((sq_per_A >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((sq_per_A >> 16) & 0xFF); saver++; *saver = (uint8_t)((sq_per_A >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(sq_per_B & 0xFF); saver++; *saver = (uint8_t)((sq_per_B >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((sq_per_B >> 16) & 0xFF); saver++; *saver = (uint8_t)((sq_per_B >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(sq_per_C & 0xFF); saver++; *saver = (uint8_t)((sq_per_C >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((sq_per_C >> 16) & 0xFF); saver++; *saver = (uint8_t)((sq_per_C >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(clock_A & 0xFF); saver++; *saver = (uint8_t)((clock_A >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((clock_A >> 16) & 0xFF); saver++; *saver = (uint8_t)((clock_A >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(clock_B & 0xFF); saver++; *saver = (uint8_t)((clock_B >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((clock_B >> 16) & 0xFF); saver++; *saver = (uint8_t)((clock_B >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(clock_C & 0xFF); saver++; *saver = (uint8_t)((clock_C >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((clock_C >> 16) & 0xFF); saver++; *saver = (uint8_t)((clock_C >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(env_per & 0xFF); saver++; *saver = (uint8_t)((env_per >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((env_per >> 16) & 0xFF); saver++; *saver = (uint8_t)((env_per >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(env_clock & 0xFF); saver++; *saver = (uint8_t)((env_clock >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((env_clock >> 16) & 0xFF); saver++; *saver = (uint8_t)((env_clock >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(env_E & 0xFF); saver++; *saver = (uint8_t)((env_E >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((env_E >> 16) & 0xFF); saver++; *saver = (uint8_t)((env_E >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(E_up_down & 0xFF); saver++; *saver = (uint8_t)((E_up_down >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((E_up_down >> 16) & 0xFF); saver++; *saver = (uint8_t)((E_up_down >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(noise_clock & 0xFF); saver++; *saver = (uint8_t)((noise_clock >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((noise_clock >> 16) & 0xFF); saver++; *saver = (uint8_t)((noise_clock >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(noise_per & 0xFF); saver++; *saver = (uint8_t)((noise_per >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((noise_per >> 16) & 0xFF); saver++; *saver = (uint8_t)((noise_per >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(noise & 0xFF); saver++; *saver = (uint8_t)((noise >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((noise >> 16) & 0xFF); saver++; *saver = (uint8_t)((noise >> 24) & 0xFF); saver++;
|
||||
|
||||
*saver = (uint8_t)(old_sample & 0xFF); saver++; *saver = (uint8_t)((old_sample >> 8) & 0xFF); saver++;
|
||||
*saver = (uint8_t)((old_sample >> 16) & 0xFF); saver++; *saver = (uint8_t)((old_sample >> 24) & 0xFF); saver++;
|
||||
|
||||
return saver;
|
||||
}
|
||||
|
||||
uint8_t* LoadState(uint8_t* loader)
|
||||
{
|
||||
A_on = *loader == 1; loader++;
|
||||
B_on = *loader == 1; loader++;
|
||||
C_on = *loader == 1; loader++;
|
||||
A_up = *loader == 1; loader++;
|
||||
B_up = *loader == 1; loader++;
|
||||
C_up = *loader == 1; loader++;
|
||||
A_noise = *loader == 1; loader++;
|
||||
B_noise = *loader == 1; loader++;
|
||||
C_noise = *loader == 1; loader++;
|
||||
env_vol_A = *loader == 1; loader++;
|
||||
env_vol_B = *loader == 1; loader++;
|
||||
env_vol_C = *loader == 1; loader++;
|
||||
|
||||
env_shape = *loader; loader++;
|
||||
port_sel = *loader; loader++;
|
||||
vol_A = *loader; loader++;
|
||||
vol_B = *loader; loader++;
|
||||
vol_C = *loader; loader++;
|
||||
|
||||
for (int i = 0; i < 16; i++) { Register[i] = *loader; loader++; }
|
||||
|
||||
psg_clock = *loader; loader++; psg_clock |= (*loader << 8); loader++;
|
||||
psg_clock |= (*loader << 16); loader++; psg_clock |= (*loader << 24); loader++;
|
||||
|
||||
sq_per_A = *loader; loader++; sq_per_A |= (*loader << 8); loader++;
|
||||
sq_per_A |= (*loader << 16); loader++; sq_per_A |= (*loader << 24); loader++;
|
||||
|
||||
sq_per_B = *loader; loader++; sq_per_B |= (*loader << 8); loader++;
|
||||
sq_per_B |= (*loader << 16); loader++; sq_per_B |= (*loader << 24); loader++;
|
||||
|
||||
sq_per_C = *loader; loader++; sq_per_C |= (*loader << 8); loader++;
|
||||
sq_per_C |= (*loader << 16); loader++; sq_per_C |= (*loader << 24); loader++;
|
||||
|
||||
clock_A = *loader; loader++; clock_A |= (*loader << 8); loader++;
|
||||
clock_A |= (*loader << 16); loader++; clock_A |= (*loader << 24); loader++;
|
||||
|
||||
clock_B = *loader; loader++; clock_B |= (*loader << 8); loader++;
|
||||
clock_B |= (*loader << 16); loader++; clock_B |= (*loader << 24); loader++;
|
||||
|
||||
clock_C = *loader; loader++; clock_C |= (*loader << 8); loader++;
|
||||
clock_C |= (*loader << 16); loader++; clock_C |= (*loader << 24); loader++;
|
||||
|
||||
env_per = *loader; loader++; env_per |= (*loader << 8); loader++;
|
||||
env_per |= (*loader << 16); loader++; env_per |= (*loader << 24); loader++;
|
||||
|
||||
env_clock = *loader; loader++; env_clock |= (*loader << 8); loader++;
|
||||
env_clock |= (*loader << 16); loader++; env_clock |= (*loader << 24); loader++;
|
||||
|
||||
env_E = *loader; loader++; env_E |= (*loader << 8); loader++;
|
||||
env_E |= (*loader << 16); loader++; env_E |= (*loader << 24); loader++;
|
||||
|
||||
E_up_down = *loader; loader++; E_up_down |= (*loader << 8); loader++;
|
||||
E_up_down |= (*loader << 16); loader++; E_up_down |= (*loader << 24); loader++;
|
||||
|
||||
noise_clock = *loader; loader++; noise_clock |= (*loader << 8); loader++;
|
||||
noise_clock |= (*loader << 16); loader++; noise_clock |= (*loader << 24); loader++;
|
||||
|
||||
noise_per = *loader; loader++; noise_per |= (*loader << 8); loader++;
|
||||
noise_per |= (*loader << 16); loader++; noise_per |= (*loader << 24); loader++;
|
||||
|
||||
noise = *loader; loader++; noise |= (*loader << 8); loader++;
|
||||
noise |= (*loader << 16); loader++; noise |= (*loader << 24); loader++;
|
||||
|
||||
old_sample = *loader; loader++; old_sample |= (*loader << 8); loader++;
|
||||
old_sample |= (*loader << 16); loader++; old_sample |= (*loader << 24); loader++;
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
};
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "LR35902.h"
|
||||
#include "AY_3_8910.h"
|
||||
#include "GBAudio.h"
|
||||
#include "TMS9918A.h"
|
||||
#include "Memory.h"
|
||||
|
||||
|
@ -21,13 +21,12 @@ namespace GBHawk
|
|||
cpu.mem_ctrl = &MemMap;
|
||||
vdp.IRQ_PTR = &cpu.FlagI;
|
||||
vdp.SHOW_BG = vdp.SHOW_SPRITES = true;
|
||||
psg.Clock_Divider = 16;
|
||||
sl_case = 0;
|
||||
};
|
||||
|
||||
TMS9918A vdp;
|
||||
Z80A cpu;
|
||||
AY_3_8910 psg;
|
||||
LR35902 cpu;
|
||||
GBAudio psg;
|
||||
MemoryManager MemMap;
|
||||
|
||||
uint8_t sl_case = 0;
|
||||
|
@ -44,14 +43,6 @@ namespace GBHawk
|
|||
|
||||
bool FrameAdvance(uint8_t controller_1, uint8_t controller_2, uint8_t* kb_rows_ptr, bool render, bool rendersound)
|
||||
{
|
||||
if ((MemMap.psg_pntr->Register[0xF] & 0x40) > 0)
|
||||
{
|
||||
MemMap.psg_pntr->Register[0xE] = controller_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemMap.psg_pntr->Register[0xE] = controller_1;
|
||||
}
|
||||
|
||||
MemMap.controller_byte_1 = controller_1;
|
||||
MemMap.controller_byte_2 = controller_2;
|
||||
|
@ -62,83 +53,6 @@ namespace GBHawk
|
|||
uint32_t scanlinesPerFrame = 262;
|
||||
vdp.SpriteLimit = true;
|
||||
|
||||
psg.num_samples = 0;
|
||||
psg.sampleclock = 0;
|
||||
|
||||
for (uint32_t i = 0; i < scanlinesPerFrame; i++)
|
||||
{
|
||||
vdp.ScanLine = i;
|
||||
|
||||
vdp.RenderScanline(i);
|
||||
|
||||
if (vdp.ScanLine == 192)
|
||||
{
|
||||
vdp.InterruptPendingSet(true);
|
||||
|
||||
if (vdp.EnableInterrupts()) { cpu.FlagI = true; }
|
||||
}
|
||||
|
||||
switch (sl_case)
|
||||
{
|
||||
case 0:
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
cpu.ExecuteOne(16);
|
||||
psg.sampleclock+=16;
|
||||
psg.generate_sound();
|
||||
}
|
||||
cpu.ExecuteOne(4);
|
||||
psg.sampleclock += 4;
|
||||
sl_case = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
cpu.ExecuteOne(12);
|
||||
psg.sampleclock += 12;
|
||||
psg.generate_sound();
|
||||
|
||||
for (int i = 0; i < 13; i++)
|
||||
{
|
||||
cpu.ExecuteOne(16);
|
||||
psg.sampleclock += 16;
|
||||
psg.generate_sound();
|
||||
}
|
||||
cpu.ExecuteOne(8);
|
||||
psg.sampleclock += 8;
|
||||
sl_case = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
cpu.ExecuteOne(8);
|
||||
psg.sampleclock += 8;
|
||||
psg.generate_sound();
|
||||
|
||||
for (int i = 0; i < 13; i++)
|
||||
{
|
||||
cpu.ExecuteOne(16);
|
||||
psg.sampleclock += 16;
|
||||
psg.generate_sound();
|
||||
}
|
||||
cpu.ExecuteOne(12);
|
||||
psg.sampleclock += 12;
|
||||
sl_case = 3;
|
||||
break;
|
||||
case 3:
|
||||
cpu.ExecuteOne(4);
|
||||
psg.sampleclock += 4;
|
||||
psg.generate_sound();
|
||||
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
cpu.ExecuteOne(16);
|
||||
psg.sampleclock += 16;
|
||||
psg.generate_sound();
|
||||
}
|
||||
sl_case = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return MemMap.lagged;
|
||||
}
|
||||
|
||||
|
@ -150,15 +64,21 @@ namespace GBHawk
|
|||
std::memcpy(dst, src, sizeof uint32_t * 256 * 192);
|
||||
}
|
||||
|
||||
uint32_t GetAudio(int32_t* dest, int32_t* n_samp)
|
||||
uint32_t GetAudio(int32_t* dest_L, int32_t* n_samp_L, int32_t* dest_R, int32_t* n_samp_R)
|
||||
{
|
||||
int32_t* src = psg.samples;
|
||||
int32_t* dst = dest;
|
||||
int32_t* src = psg.samples_L;
|
||||
int32_t* dst = dest_L;
|
||||
|
||||
std::memcpy(dst, src, sizeof int32_t * psg.num_samples * 2);
|
||||
n_samp[0] = psg.num_samples;
|
||||
std::memcpy(dst, src, sizeof int32_t * psg.num_samples_L * 2);
|
||||
n_samp_L[0] = psg.num_samples_L;
|
||||
|
||||
return psg.sampleclock;
|
||||
src = psg.samples_R;
|
||||
dst = dest_R;
|
||||
|
||||
std::memcpy(dst, src, sizeof int32_t * psg.num_samples_R * 2);
|
||||
n_samp_R[0] = psg.num_samples_R;
|
||||
|
||||
return psg.master_audio_clock;
|
||||
}
|
||||
|
||||
#pragma region State Save / Load
|
||||
|
@ -189,11 +109,7 @@ namespace GBHawk
|
|||
|
||||
uint8_t GetSysBus(uint32_t addr)
|
||||
{
|
||||
cpu.bank_num = cpu.bank_offset = addr & 0xFFFF;
|
||||
cpu.bank_offset &= cpu.low_mask;
|
||||
cpu.bank_num = (cpu.bank_num >> cpu.bank_shift)& cpu.high_mask;
|
||||
|
||||
return cpu.MemoryMap[cpu.bank_num][cpu.bank_offset];
|
||||
return cpu.PeekMemory(addr);
|
||||
}
|
||||
|
||||
uint8_t GetVRAM(uint32_t addr)
|
||||
|
@ -257,11 +173,15 @@ namespace GBHawk
|
|||
}
|
||||
else if (t == 1)
|
||||
{
|
||||
memcpy(d, cpu.NMI_event, l);
|
||||
memcpy(d, cpu.Un_halt_event, l);
|
||||
}
|
||||
else if (t == 2)
|
||||
{
|
||||
memcpy(d, cpu.IRQ_event, l);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(d, cpu.IRQ_event, l);
|
||||
memcpy(d, cpu.Un_halt_event, l);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -53,9 +53,9 @@ GBHawk_EXPORT void GB_get_video(GBCore* p, uint32_t* dest)
|
|||
}
|
||||
|
||||
// send audio data to external audio provider
|
||||
GBHawk_EXPORT uint32_t GB_get_audio(GBCore* p, int32_t* dest, int32_t* n_samp)
|
||||
GBHawk_EXPORT uint32_t GB_get_audio(GBCore* p, int32_t* dest_L, int32_t* n_samp_L, int32_t* dest_R, int32_t* n_samp_R)
|
||||
{
|
||||
return p->GetAudio(dest, n_samp);
|
||||
return p->GetAudio(dest_L, n_samp_L, dest_R, n_samp_R);
|
||||
}
|
||||
|
||||
#pragma region State Save / Load
|
||||
|
|
|
@ -151,7 +151,7 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AY_3_8910.h" />
|
||||
<ClInclude Include="GBAudio.h" />
|
||||
<ClInclude Include="Core.h" />
|
||||
<ClInclude Include="GBHawk.h" />
|
||||
<ClInclude Include="Memory.h" />
|
||||
|
|
|
@ -11,10 +11,7 @@ namespace GBHawk
|
|||
{
|
||||
void LR35902::WriteMemory(uint32_t addr, uint8_t value)
|
||||
{
|
||||
if ((addr & 0xFFFF) >= 0xFFFC)
|
||||
{
|
||||
mem_ctrl->MemoryWrite(addr, value);
|
||||
}
|
||||
mem_ctrl->MemoryWrite(addr, value);
|
||||
}
|
||||
|
||||
uint8_t LR35902::ReadMemory(uint32_t addr)
|
||||
|
@ -22,6 +19,11 @@ namespace GBHawk
|
|||
return mem_ctrl->HardwareRead(addr);
|
||||
}
|
||||
|
||||
uint8_t LR35902::PeekMemory(uint32_t addr)
|
||||
{
|
||||
return mem_ctrl->HardwareRead(addr);
|
||||
}
|
||||
|
||||
uint8_t LR35902::SpeedFunc(uint32_t addr)
|
||||
{
|
||||
return mem_ctrl->HardwareRead(addr);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,7 @@
|
|||
#include "Memory.h"
|
||||
#include "LR35902.h"
|
||||
#include "TMS9918A.h"
|
||||
#include "AY_3_8910.h"
|
||||
#include "GBAudio.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -14,216 +14,12 @@ namespace GBHawk
|
|||
{
|
||||
uint8_t MemoryManager::HardwareRead(uint32_t port)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
if (port == 0x98) // VDP
|
||||
{
|
||||
return vdp_pntr->ReadData();
|
||||
}
|
||||
else if (port == 0x99) // VDP
|
||||
{
|
||||
return vdp_pntr->ReadVdpStatus();
|
||||
}
|
||||
else if (port == 0xA2)
|
||||
{
|
||||
if (psg_pntr->port_sel == 0xE) { lagged = false; }
|
||||
return psg_pntr->ReadReg();
|
||||
}
|
||||
else if (port == 0xA8)
|
||||
{
|
||||
return PortA8;
|
||||
}
|
||||
else if (port == 0xA9)
|
||||
{
|
||||
lagged = false;
|
||||
return ~kb_rows[kb_rows_sel];
|
||||
}
|
||||
else if (port == 0xAA)
|
||||
{
|
||||
// TODO: casette, caps lamp, keyboard sound click
|
||||
return kb_rows_sel;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void MemoryManager::HardwareWrite(uint32_t port, uint8_t value)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
if (port == 0x98) // VDP
|
||||
{
|
||||
vdp_pntr->WriteVdpData(value);
|
||||
}
|
||||
else if(port == 0x99) // VDP
|
||||
{
|
||||
vdp_pntr->WriteVdpControl(value);
|
||||
}
|
||||
else if (port == 0xA0)
|
||||
{
|
||||
psg_pntr->port_sel = (value & 0xF);
|
||||
}
|
||||
else if (port == 0xA1)
|
||||
{
|
||||
psg_pntr->WriteReg(value);
|
||||
|
||||
// update controller port data if port F is written to
|
||||
if (psg_pntr->port_sel == 0xF)
|
||||
{
|
||||
if ((psg_pntr->Register[0xF] & 0x40) > 0)
|
||||
{
|
||||
psg_pntr->Register[0xE] = controller_byte_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
psg_pntr->Register[0xE] = controller_byte_1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (port == 0xA8)
|
||||
{
|
||||
PortA8 = value;
|
||||
remap();
|
||||
}
|
||||
else if (port == 0xAA)
|
||||
{
|
||||
kb_rows_sel = value & 0xF;
|
||||
remap();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::remap()
|
||||
{
|
||||
if ((PortA8 & 3) == 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i] = &bios_rom[(0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i] = 0;
|
||||
}
|
||||
}
|
||||
else if ((PortA8 & 3) == 1)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i] = &rom_1[(0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i] = 0;
|
||||
}
|
||||
}
|
||||
else if ((PortA8 & 3) == 2)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i] = &rom_2[(0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i] = 0;
|
||||
}
|
||||
}
|
||||
else if ((PortA8 & 3) == 3)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i] = &ram[(0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (((PortA8 >> 2) & 3) == 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 16] = &basic_rom[(0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 16] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 2) & 3) == 1)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 16] = &rom_1[0x4000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 16] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 2) & 3) == 2)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 16] = &rom_2[0x4000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 16] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 2) & 3) == 3)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 16] = &ram[0x4000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 16] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (((PortA8 >> 4) & 3) == 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 32] = &unmapped[0];
|
||||
cpu_pntr->MemoryMapMask[i + 32] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 4) & 3) == 1)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 32] = &rom_1[0x8000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 32] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 4) & 3) == 2)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 32] = &rom_2[0x8000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 32] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 4) & 3) == 3)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 32] = &ram[0x8000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 32] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (((PortA8 >> 6) & 3) == 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 48] = &unmapped[0];
|
||||
cpu_pntr->MemoryMapMask[i + 48] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 6) & 3) == 1)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 48] = &rom_1[0xC000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 48] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 6) & 3) == 2)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 48] = &rom_2[0xC000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 48] = 0;
|
||||
}
|
||||
}
|
||||
else if (((PortA8 >> 6) & 3) == 3)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu_pntr->MemoryMap[i + 48] = &ram[0xC000 + (0x400 * i)];
|
||||
cpu_pntr->MemoryMapMask[i + 48] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,17 +7,17 @@ using namespace std;
|
|||
|
||||
namespace GBHawk
|
||||
{
|
||||
class Z80A;
|
||||
class LR35902;
|
||||
class TMS9918A;
|
||||
class AY_3_8910;
|
||||
class GBAudio;
|
||||
|
||||
class MemoryManager
|
||||
{
|
||||
public:
|
||||
|
||||
TMS9918A* vdp_pntr = nullptr;
|
||||
AY_3_8910* psg_pntr = nullptr;
|
||||
Z80A* cpu_pntr = nullptr;
|
||||
GBAudio* psg_pntr = nullptr;
|
||||
LR35902* cpu_pntr = nullptr;
|
||||
uint8_t* rom_1 = nullptr;
|
||||
uint8_t* rom_2 = nullptr;
|
||||
uint8_t* bios_rom = nullptr;
|
||||
|
@ -54,8 +54,6 @@ namespace GBHawk
|
|||
|
||||
void HardwareWrite(uint32_t addr, uint8_t value);
|
||||
|
||||
void remap();
|
||||
|
||||
// NOTE: only called from source when both are available and of correct size (0x4000)
|
||||
void Load_BIOS(uint8_t* bios, uint8_t* basic)
|
||||
{
|
||||
|
@ -82,8 +80,6 @@ namespace GBHawk
|
|||
|
||||
// default memory map setup
|
||||
PortA8 = 0;
|
||||
|
||||
remap();
|
||||
}
|
||||
|
||||
void MemoryWrite(uint32_t addr, uint8_t value)
|
||||
|
@ -128,8 +124,6 @@ namespace GBHawk
|
|||
std::memcpy(&ram, loader, 0x10000); loader += 0x10000;
|
||||
std::memcpy(&cart_ram, loader, 0x8000); loader += 0x8000;
|
||||
|
||||
remap();
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue