2022-02-05 18:48:36 +00:00
# pragma once
class SY6522
{
public :
2023-04-12 17:19:18 +00:00
SY6522 ( UINT slot , bool isMegaAudio ) : m_slot ( slot ) , m_isMegaAudio ( isMegaAudio )
2022-02-05 18:48:36 +00:00
{
for ( UINT i = 0 ; i < kNumTimersPer6522 ; i + + )
m_syncEvent [ i ] = NULL ;
2022-02-12 17:29:49 +00:00
Reset ( true ) ;
2022-02-05 18:48:36 +00:00
}
~ SY6522 ( void )
{
}
void InitSyncEvents ( class SyncEvent * event0 , class SyncEvent * event1 )
{
m_syncEvent [ 0 ] = event0 ;
m_syncEvent [ 1 ] = event1 ;
}
void Reset ( const bool powerCycle ) ;
void StartTimer1 ( void ) ;
void StopTimer1 ( void ) ;
bool IsTimer1Active ( void ) { return m_timer1Active ; }
void StopTimer2 ( void ) ;
bool IsTimer2Active ( void ) { return m_timer2Active ; }
2023-03-05 15:37:52 +00:00
void UpdatePortAForHiZ ( void ) ;
2022-02-05 18:48:36 +00:00
void UpdateIFR ( BYTE clr_ifr , BYTE set_ifr = 0 ) ;
void UpdateTimer1 ( USHORT clocks ) ;
void UpdateTimer2 ( USHORT clocks ) ;
enum { rORB = 0 , rORA , rDDRB , rDDRA , rT1CL , rT1CH , rT1LL , rT1LH , rT2CL , rT2CH , rSR , rACR , rPCR , rIFR , rIER , rORA_NO_HS , SIZE_6522_REGS } ;
BYTE GetReg ( BYTE reg )
{
switch ( reg )
{
case rDDRA : return m_regs . DDRA ;
case rORA : return m_regs . ORA ;
case rACR : return m_regs . ACR ;
case rPCR : return m_regs . PCR ;
case rIFR : return m_regs . IFR ;
}
_ASSERT ( 0 ) ;
return 0 ;
}
2023-12-29 10:16:51 +00:00
BYTE GetBusViewOfORB ( void ) { return m_regs . ORB & m_regs . DDRB ; } // Return how the AY8913 sees ORB on the bus (ie. not CPU's view which will be OR'd with !DDRB)
2022-02-05 18:48:36 +00:00
USHORT GetRegT1C ( void ) { return m_regs . TIMER1_COUNTER . w ; }
USHORT GetRegT2C ( void ) { return m_regs . TIMER2_COUNTER . w ; }
void GetRegs ( BYTE regs [ SIZE_6522_REGS ] ) { memcpy ( & regs [ 0 ] , ( BYTE * ) & m_regs , SIZE_6522_REGS ) ; } // For debugger
void SetRegORA ( BYTE reg ) { m_regs . ORA = reg ; }
2023-02-04 12:09:19 +00:00
bool IsTimer1IrqDelay ( void ) { return m_timer1IrqDelay ? true : false ; }
2022-02-05 18:48:36 +00:00
BYTE Read ( BYTE nReg ) ;
void Write ( BYTE nReg , BYTE nValue ) ;
void SaveSnapshot ( class YamlSaveHelper & yamlSaveHelper ) ;
void LoadSnapshot ( class YamlLoadHelper & yamlLoadHelper , UINT version ) ;
void SetTimersActiveFromSnapshot ( bool timer1Active , bool timer2Active , UINT version ) ;
// ACR
static const BYTE ACR_RUNMODE = 1 < < 6 ;
static const BYTE ACR_RM_ONESHOT = 0 < < 6 ;
static const BYTE ACR_RM_FREERUNNING = 1 < < 6 ;
// IFR & IER:
static const BYTE IxR_SSI263 = 1 < < 1 ;
static const BYTE IxR_VOTRAX = 1 < < 4 ;
static const BYTE IxR_TIMER2 = 1 < < 5 ;
static const BYTE IxR_TIMER1 = 1 < < 6 ;
static const BYTE IFR_IRQ = 1 < < 7 ;
static const UINT kExtraTimerCycles = 2 ; // Rockwell, Fig.16: period = N+2 cycles
static const UINT kNumTimersPer6522 = 2 ;
private :
USHORT SetTimerSyncEvent ( BYTE reg , USHORT timerLatch ) ;
USHORT GetTimer1Counter ( BYTE reg ) ;
USHORT GetTimer2Counter ( BYTE reg ) ;
bool IsTimer1Underflowed ( BYTE reg ) ;
bool IsTimer2Underflowed ( BYTE reg ) ;
bool CheckTimerUnderflow ( USHORT & counter , int & timerIrqDelay , const USHORT clocks ) ;
int OnTimer1Underflow ( USHORT & counter ) ;
UINT GetOpcodeCyclesForRead ( BYTE reg ) ;
UINT GetOpcodeCyclesForWrite ( BYTE reg ) ;
void StartTimer2 ( void ) ;
void StartTimer1_LoadStateV1 ( void ) ;
# pragma pack(push)
# pragma pack(1) // Ensure 'struct Regs' is packed so that GetRegs() can just do a memcpy()
struct IWORD
{
union
{
struct
{
BYTE l ;
BYTE h ;
} ;
USHORT w ;
} ;
} ;
struct Regs
{
BYTE ORB ; // $00 - Port B
BYTE ORA ; // $01 - Port A (with handshaking)
BYTE DDRB ; // $02 - Data Direction Register B
BYTE DDRA ; // $03 - Data Direction Register A
IWORD TIMER1_COUNTER ; // $04 - Read counter (L) / Write latch (L)
// $05 - Read / Write & initiate count (H)
IWORD TIMER1_LATCH ; // $06 - Read / Write & latch (L)
// $07 - Read / Write & latch (H)
IWORD TIMER2_COUNTER ; // $08 - Read counter (L) / Write latch (L)
// $09 - Read counter (H) / Write latch (H)
BYTE SERIAL_SHIFT ; // $0A
BYTE ACR ; // $0B - Auxiliary Control Register
BYTE PCR ; // $0C - Peripheral Control Register
BYTE IFR ; // $0D - Interrupt Flag Register
BYTE IER ; // $0E - Interrupt Enable Register
BYTE ORA_NO_HS ; // $0F - Port A (without handshaking)
//
IWORD TIMER2_LATCH ; // Doesn't exist in 6522
} ;
# pragma pack(pop)
Regs m_regs ;
int m_timer1IrqDelay ;
int m_timer2IrqDelay ;
bool m_timer1Active ;
bool m_timer2Active ;
class SyncEvent * m_syncEvent [ kNumTimersPer6522 ] ;
2023-01-28 18:15:28 +00:00
UINT m_slot ;
2023-04-12 17:19:18 +00:00
bool m_isMegaAudio ;
static const UINT kExtraMegaAudioTimerCycles = kExtraTimerCycles + 1 ;
2022-02-05 18:48:36 +00:00
} ;