2006-02-25 20:50:29 +00:00
|
|
|
#pragma once
|
|
|
|
|
2023-01-28 18:15:28 +00:00
|
|
|
#include "6522.h"
|
|
|
|
#include "AY8910.h"
|
2019-12-19 19:42:30 +00:00
|
|
|
#include "Card.h"
|
2023-01-28 18:15:28 +00:00
|
|
|
#include "SoundCore.h"
|
|
|
|
#include "SSI263.h"
|
|
|
|
#include "SynchronousEventManager.h"
|
2019-12-19 19:42:30 +00:00
|
|
|
|
2023-01-28 18:15:28 +00:00
|
|
|
class MockingboardCard : public Card
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
MockingboardCard(UINT slot, SS_CARDTYPE type);
|
|
|
|
virtual ~MockingboardCard(void);
|
2021-03-23 22:01:41 +00:00
|
|
|
|
2023-01-28 18:15:28 +00:00
|
|
|
virtual void InitializeIO(LPBYTE pCxRomPeripheral);
|
|
|
|
virtual void Destroy();
|
|
|
|
virtual void Reset(const bool powerCycle);
|
|
|
|
virtual void Update(const ULONG executedCycles);
|
|
|
|
virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
|
|
|
|
virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
|
|
|
|
|
|
|
|
static BYTE __stdcall IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
|
|
|
|
static BYTE __stdcall IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
|
|
|
|
static BYTE __stdcall PhasorIO(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nExecutedCycles);
|
|
|
|
|
|
|
|
BYTE IOReadInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nExecutedCycles);
|
|
|
|
BYTE IOWriteInternal(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
|
|
|
|
BYTE PhasorIOInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nExecutedCycles);
|
|
|
|
|
|
|
|
void ReinitializeClock(void);
|
|
|
|
void MuteControl(bool mute);
|
|
|
|
void UpdateCycles(ULONG executedCycles);
|
|
|
|
bool IsActive(void);
|
|
|
|
void SetVolume(DWORD dwVolume, DWORD dwVolumeMax);
|
|
|
|
void SetCumulativeCycles(void);
|
|
|
|
UINT MB_Update(void);
|
|
|
|
short** GetVoiceBuffers(void) { return m_ppAYVoiceBuffer; }
|
|
|
|
int GetNumSamplesError(void) { return m_numSamplesError; }
|
|
|
|
void SetNumSamplesError(int numSamplesError) { m_numSamplesError = numSamplesError; }
|
2019-12-24 13:58:20 +00:00
|
|
|
#ifdef _DEBUG
|
2023-01-28 18:15:28 +00:00
|
|
|
void CheckCumulativeCycles(void);
|
|
|
|
void Get6522IrqDescription(std::string& desc);
|
2019-12-24 13:58:20 +00:00
|
|
|
#endif
|
2023-01-28 18:15:28 +00:00
|
|
|
|
2023-01-29 13:32:55 +00:00
|
|
|
bool Is6522IRQ(void);
|
2023-01-28 18:15:28 +00:00
|
|
|
UINT64 GetLastCumulativeCycles(void);
|
|
|
|
void UpdateIFR(BYTE nDevice, BYTE clr_mask, BYTE set_mask);
|
|
|
|
BYTE GetPCR(BYTE nDevice);
|
|
|
|
bool IsAnyTimer1Active(void);
|
2024-09-25 19:58:59 +00:00
|
|
|
void UseBad6522A(void) { m_MBSubUnit[0].sy6522.InitBadState(true); }
|
|
|
|
void UseBad6522B(void) { m_MBSubUnit[1].sy6522.InitBadState(true); }
|
2023-01-28 18:15:28 +00:00
|
|
|
|
2023-03-09 20:16:21 +00:00
|
|
|
struct DEBUGGER_MB_SUBUNIT
|
|
|
|
{
|
|
|
|
BYTE regsSY6522[SY6522::SIZE_6522_REGS];
|
|
|
|
bool timer1Active;
|
|
|
|
bool timer2Active;
|
|
|
|
BYTE regsAY8913[NUM_AY8913_PER_SUBUNIT][16];
|
|
|
|
BYTE nAYCurrentRegister[NUM_AY8913_PER_SUBUNIT];
|
2023-03-11 13:56:44 +00:00
|
|
|
char szState[NUM_AY8913_PER_SUBUNIT][3]; // "--"(INACTIVE), "RD", "WR", "LA"
|
2023-03-09 20:16:21 +00:00
|
|
|
bool isAYLatchedAddressValid[NUM_AY8913_PER_SUBUNIT];
|
|
|
|
};
|
|
|
|
struct DEBUGGER_MB_CARD
|
|
|
|
{
|
2023-03-09 22:53:09 +00:00
|
|
|
SS_CARDTYPE type;
|
2023-03-09 20:16:21 +00:00
|
|
|
DEBUGGER_MB_SUBUNIT subUnit[NUM_SUBUNITS_PER_MB];
|
|
|
|
};
|
|
|
|
void GetSnapshotForDebugger(DEBUGGER_MB_CARD* const pMBForDebugger);
|
2023-01-28 18:15:28 +00:00
|
|
|
|
|
|
|
static std::string GetSnapshotCardName(void);
|
|
|
|
static std::string GetSnapshotCardNamePhasor(void);
|
2023-04-12 17:19:18 +00:00
|
|
|
static std::string GetSnapshotCardNameMegaAudio(void);
|
2023-04-28 15:41:22 +00:00
|
|
|
static std::string GetSnapshotCardNameSDMusic(void);
|
2023-01-28 18:15:28 +00:00
|
|
|
|
2023-05-05 20:49:26 +00:00
|
|
|
static const unsigned short NUM_MB_CHANNELS = 2;
|
|
|
|
static const DWORD SAMPLE_RATE = 44100; // Use a base freq so that DirectX (or sound h/w) doesn't have to up/down-sample
|
|
|
|
|
2023-01-28 18:15:28 +00:00
|
|
|
private:
|
|
|
|
enum MockingboardUnitState_e { AY_NOP0, AY_NOP1, AY_INACTIVE, AY_READ, AY_NOP4, AY_NOP5, AY_WRITE, AY_LATCH };
|
|
|
|
|
|
|
|
struct MB_SUBUNIT
|
|
|
|
{
|
|
|
|
SY6522 sy6522;
|
2023-03-09 20:16:21 +00:00
|
|
|
AY8913 ay8913[NUM_AY8913_PER_SUBUNIT]; // Phasor has 2x AY per 6522
|
2023-01-28 18:15:28 +00:00
|
|
|
SSI263 ssi263;
|
|
|
|
BYTE nAY8910Number;
|
2023-03-09 20:16:21 +00:00
|
|
|
BYTE nAYCurrentRegister[NUM_AY8913_PER_SUBUNIT];
|
|
|
|
MockingboardUnitState_e state[NUM_AY8913_PER_SUBUNIT]; // AY's PSG function
|
|
|
|
bool isAYLatchedAddressValid[NUM_AY8913_PER_SUBUNIT];
|
|
|
|
bool isChipSelected[NUM_AY8913_PER_SUBUNIT];
|
2024-01-06 18:20:33 +00:00
|
|
|
bool isBusDriven;
|
2023-01-28 18:15:28 +00:00
|
|
|
|
2023-04-12 17:19:18 +00:00
|
|
|
MB_SUBUNIT(UINT slot, SS_CARDTYPE type) : sy6522(slot, type == CT_MegaAudio), ssi263(slot)
|
2023-01-28 18:15:28 +00:00
|
|
|
{
|
|
|
|
nAY8910Number = 0;
|
2023-03-04 18:14:00 +00:00
|
|
|
// sy6522 & ssi263 have already been default constructed
|
2023-03-05 15:37:52 +00:00
|
|
|
// Reset() called from MockingboardCard ctor
|
2023-03-04 18:14:00 +00:00
|
|
|
}
|
|
|
|
|
2023-03-05 15:37:52 +00:00
|
|
|
void Reset(SS_CARDTYPE type)
|
2023-03-04 18:14:00 +00:00
|
|
|
{
|
|
|
|
nAYCurrentRegister[0] = nAYCurrentRegister[1] = 0; // not valid
|
2023-03-04 22:41:07 +00:00
|
|
|
state[0] = state[1] = AY_INACTIVE;
|
2023-03-01 21:01:59 +00:00
|
|
|
isAYLatchedAddressValid[0] = isAYLatchedAddressValid[1] = false; // after AY reset
|
2023-04-12 17:19:18 +00:00
|
|
|
isChipSelected[0] = type == CT_Phasor ? false : true; // Only Phasor is false, all other MB variants are true
|
2023-03-05 15:37:52 +00:00
|
|
|
isChipSelected[1] = false;
|
2024-01-06 18:20:33 +00:00
|
|
|
SetBusState(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetBusState(bool state)
|
|
|
|
{
|
|
|
|
isBusDriven = state;
|
|
|
|
sy6522.SetBusBeingDriven(state);
|
2023-01-28 18:15:28 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-04-28 15:41:22 +00:00
|
|
|
void WriteToORB(BYTE subunit, BYTE subunitForAY=0);
|
2023-09-07 20:40:13 +00:00
|
|
|
void AY8913_Reset(BYTE subunit);
|
|
|
|
void AY8913_Write(BYTE subunit, BYTE ay, BYTE value);
|
2023-01-28 18:15:28 +00:00
|
|
|
void UpdateIFRandIRQ(MB_SUBUNIT* pMB, BYTE clr_mask, BYTE set_mask);
|
|
|
|
|
|
|
|
void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
|
|
|
|
bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
|
|
|
|
|
|
|
|
static int MB_SyncEventCallback(int id, int /*cycles*/, ULONG uExecutedCycles);
|
|
|
|
int MB_SyncEventCallbackInternal(int id, int /*cycles*/, ULONG uExecutedCycles);
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
// MAME interface
|
|
|
|
BYTE AYReadReg(BYTE subunit, BYTE ay, int r);
|
|
|
|
void _AYWriteReg(BYTE subunit, BYTE ay, int r, int v);
|
|
|
|
void AY8910_reset(BYTE subunit, BYTE ay);
|
|
|
|
void AY8910Update(BYTE subunit, BYTE ay, INT16** buffer, int nNumSamples);
|
|
|
|
|
|
|
|
void AY8910_InitAll(int nClock, int nSampleRate);
|
|
|
|
void AY8910_InitClock(int nClock);
|
|
|
|
BYTE* AY8910_GetRegsPtr(BYTE subunit, BYTE ay);
|
|
|
|
|
|
|
|
void AY8910UpdateSetCycles();
|
|
|
|
|
|
|
|
UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, BYTE subunit, BYTE ay, const std::string& suffix);
|
|
|
|
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, BYTE subunit, BYTE ay, const std::string& suffix);
|
|
|
|
|
|
|
|
UINT64 m_lastAYUpdateCycle;
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
static const UINT SY6522_DEVICE_A = 0;
|
|
|
|
static const UINT SY6522_DEVICE_B = 1;
|
|
|
|
|
|
|
|
static const UINT AY8913_DEVICE_A = 0;
|
|
|
|
static const UINT AY8913_DEVICE_B = 1; // Phasor only
|
|
|
|
|
|
|
|
// Chip offsets from card base:
|
|
|
|
static const UINT SY6522A_Offset = 0x00;
|
|
|
|
static const UINT SY6522B_Offset = 0x80;
|
|
|
|
static const UINT SSI263B_Offset = 0x20;
|
|
|
|
static const UINT SSI263A_Offset = 0x40;
|
|
|
|
|
|
|
|
// MB has 2x (1x SY6522 + 1x AY8913), Phasor has 2x (1x SY6522 + 2x AY8913)
|
|
|
|
MB_SUBUNIT m_MBSubUnit[NUM_SUBUNITS_PER_MB];
|
|
|
|
|
|
|
|
static const UINT kNumSyncEvents = NUM_SY6522 * SY6522::kNumTimersPer6522;
|
|
|
|
SyncEvent* m_syncEvent[kNumSyncEvents];
|
|
|
|
|
|
|
|
UINT64 m_lastCumulativeCycle;
|
|
|
|
|
|
|
|
short* m_ppAYVoiceBuffer[NUM_VOICES];
|
|
|
|
|
|
|
|
UINT64 m_inActiveCycleCount;
|
|
|
|
bool m_regAccessedFlag;
|
|
|
|
bool m_isActive;
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
bool m_phasorEnable;
|
|
|
|
PHASOR_MODE m_phasorMode;
|
|
|
|
UINT m_phasorClockScaleFactor;
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
UINT64 m_lastMBUpdateCycle;
|
|
|
|
int m_numSamplesError;
|
|
|
|
};
|