cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

Processor_inline.h (15045B)


      1#ifndef PROCESSOR_INLINE_H
      2#define	PROCESSOR_INLINE_H
      3
      4#include "definitions.h"
      5#include "Memory.h"
      6
      7inline bool Processor::InterruptIsAboutToRaise()
      8{
      9    u8 ie_reg = m_pMemory->Retrieve(0xFFFF);
     10    u8 if_reg = m_pMemory->Retrieve(0xFF0F);
     11
     12    return (if_reg & ie_reg & 0x1F) != 0;
     13}
     14
     15inline Processor::Interrupts Processor::InterruptPending()
     16{
     17    u8 ie_reg = m_pMemory->Retrieve(0xFFFF);
     18    u8 if_reg = m_pMemory->Retrieve(0xFF0F);
     19    u8 ie_if = if_reg & ie_reg;
     20    
     21    if ((ie_if & 0x1F) == 0)
     22    {
     23        return None_Interrupt;
     24    }
     25    else if ((ie_if & 0x01) && (m_iInterruptDelayCycles <= 0))
     26    {
     27        return VBlank_Interrupt;
     28    }
     29    else if (ie_if & 0x02)
     30    {
     31        return LCDSTAT_Interrupt;
     32    }
     33    else if (ie_if & 0x04)
     34    {
     35        return Timer_Interrupt;
     36    }
     37    else if (ie_if & 0x08)
     38    {
     39        return Serial_Interrupt;
     40    }
     41    else if (ie_if & 0x10)
     42    {
     43        return Joypad_Interrupt;
     44    }
     45    
     46    return None_Interrupt;
     47}
     48
     49inline void Processor::RequestInterrupt(Interrupts interrupt)
     50{
     51    m_pMemory->Load(0xFF0F, m_pMemory->Retrieve(0xFF0F) | interrupt);
     52
     53    if ((interrupt == VBlank_Interrupt) && !m_bCGBSpeed)
     54    {
     55        m_iInterruptDelayCycles = 4;
     56    }
     57}
     58
     59inline void Processor::ResetTIMACycles()
     60{
     61    m_iTIMACycles = 0;
     62    m_pMemory->Load(0xFF05, m_pMemory->Retrieve(0xFF06));
     63}
     64
     65inline void Processor::ResetDIVCycles()
     66{
     67    m_iDIVCycles = 0;
     68    m_pMemory->Load(0xFF04, 0x00);
     69}
     70
     71inline bool Processor::Halted() const
     72{
     73    return m_bHalt;
     74}
     75
     76inline bool Processor::DuringOpCode() const
     77{
     78    return m_iAccurateOPCodeState != 0;
     79}
     80
     81inline bool Processor::CGBSpeed() const
     82{
     83    return m_bCGBSpeed;
     84}
     85
     86inline void Processor::AddCycles(unsigned int cycles)
     87{
     88    m_iCurrentClockCycles += cycles;
     89}
     90
     91inline void Processor::ClearAllFlags()
     92{
     93    SetFlag(FLAG_NONE);
     94}
     95
     96inline void Processor::ToggleZeroFlagFromResult(u8 result)
     97{
     98    if (result == 0)
     99        ToggleFlag(FLAG_ZERO);
    100}
    101
    102inline void Processor::SetFlag(u8 flag)
    103{
    104    AF.SetLow(flag);
    105}
    106
    107inline void Processor::FlipFlag(u8 flag)
    108{
    109    AF.SetLow(AF.GetLow() ^ flag);
    110}
    111
    112inline void Processor::ToggleFlag(u8 flag)
    113{
    114    AF.SetLow(AF.GetLow() | flag);
    115}
    116
    117inline void Processor::UntoggleFlag(u8 flag)
    118{
    119    AF.SetLow(AF.GetLow() & (~flag));
    120}
    121
    122inline bool Processor::IsSetFlag(u8 flag)
    123{
    124    return (AF.GetLow() & flag) != 0;
    125}
    126
    127inline void Processor::StackPush(SixteenBitRegister* reg)
    128{
    129    SP.Decrement();
    130    m_pMemory->Write(SP.GetValue(), reg->GetHigh());
    131    SP.Decrement();
    132    m_pMemory->Write(SP.GetValue(), reg->GetLow());
    133}
    134
    135inline void Processor::StackPop(SixteenBitRegister* reg)
    136{
    137    reg->SetLow(m_pMemory->Read(SP.GetValue()));
    138    SP.Increment();
    139    reg->SetHigh(m_pMemory->Read(SP.GetValue()));
    140    SP.Increment();
    141}
    142
    143inline int Processor::AdjustedCycles(int cycles)
    144{
    145    if (!cycles) return cycles;
    146    return cycles >> m_iSpeedMultiplier;
    147}
    148
    149inline void Processor::InvalidOPCode()
    150{
    151    Log("--> ** INVALID OP Code");
    152}
    153
    154inline void Processor::OPCodes_LD(u8* reg1, u8 reg2)
    155{
    156    *reg1 = reg2;
    157}
    158
    159inline void Processor::OPCodes_LD(u8* reg, u16 address)
    160{
    161    *reg = m_pMemory->Read(address);
    162}
    163
    164inline void Processor::OPCodes_LD(u16 address, u8 reg)
    165{
    166    m_pMemory->Write(address, reg);
    167}
    168
    169inline void Processor::OPCodes_OR(u8 number)
    170{
    171    u8 result = AF.GetHigh() | number;
    172    AF.SetHigh(result);
    173    ClearAllFlags();
    174    ToggleZeroFlagFromResult(result);
    175}
    176
    177inline void Processor::OPCodes_XOR(u8 number)
    178{
    179    u8 result = AF.GetHigh() ^ number;
    180    AF.SetHigh(result);
    181    ClearAllFlags();
    182    ToggleZeroFlagFromResult(result);
    183}
    184
    185inline void Processor::OPCodes_AND(u8 number)
    186{
    187    u8 result = AF.GetHigh() & number;
    188    AF.SetHigh(result);
    189    SetFlag(FLAG_HALF);
    190    ToggleZeroFlagFromResult(result);
    191}
    192
    193inline void Processor::OPCodes_CP(u8 number)
    194{
    195    SetFlag(FLAG_SUB);
    196    if (AF.GetHigh() < number)
    197    {
    198        ToggleFlag(FLAG_CARRY);
    199    }
    200    if (AF.GetHigh() == number)
    201    {
    202        ToggleFlag(FLAG_ZERO);
    203    }
    204    if (((AF.GetHigh() - number) & 0xF) > (AF.GetHigh() & 0xF))
    205    {
    206        ToggleFlag(FLAG_HALF);
    207    }
    208}
    209
    210inline void Processor::OPCodes_INC(u8* reg)
    211{
    212    u8 result = *reg + 1;
    213    *reg = result;
    214    IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    215    ToggleZeroFlagFromResult(result);
    216    if ((result & 0x0F) == 0x00)
    217    {
    218        ToggleFlag(FLAG_HALF);
    219    }
    220}
    221
    222inline void Processor::OPCodes_INC_HL()
    223{
    224    if (m_iAccurateOPCodeState == 1)
    225    {
    226        m_iReadCache = m_pMemory->Read(HL.GetValue()) + 1;
    227        return;
    228    }
    229    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    230    IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    231    ToggleZeroFlagFromResult(m_iReadCache);
    232    if ((m_iReadCache & 0x0F) == 0x00)
    233    {
    234        ToggleFlag(FLAG_HALF);
    235    }
    236}
    237
    238inline void Processor::OPCodes_DEC(u8* reg)
    239{
    240    u8 result = *reg - 1;
    241    *reg = result;
    242    IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    243    ToggleFlag(FLAG_SUB);
    244    ToggleZeroFlagFromResult(result);
    245    if ((result & 0x0F) == 0x0F)
    246    {
    247        ToggleFlag(FLAG_HALF);
    248    }
    249}
    250
    251inline void Processor::OPCodes_DEC_HL()
    252{
    253    if (m_iAccurateOPCodeState == 1)
    254    {
    255        m_iReadCache = m_pMemory->Read(HL.GetValue()) - 1;
    256        return;
    257    }
    258    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    259    IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    260    ToggleFlag(FLAG_SUB);
    261    ToggleZeroFlagFromResult(m_iReadCache);
    262    if ((m_iReadCache & 0x0F) == 0x0F)
    263    {
    264        ToggleFlag(FLAG_HALF);
    265    }
    266}
    267
    268inline void Processor::OPCodes_ADD(u8 number)
    269{
    270    int result = AF.GetHigh() + number;
    271    int carrybits = AF.GetHigh() ^ number ^ result;
    272    AF.SetHigh(static_cast<u8> (result));
    273    ClearAllFlags();
    274    ToggleZeroFlagFromResult(static_cast<u8> (result));
    275    if ((carrybits & 0x100) != 0)
    276    {
    277        ToggleFlag(FLAG_CARRY);
    278    }
    279    if ((carrybits & 0x10) != 0)
    280    {
    281        ToggleFlag(FLAG_HALF);
    282    }
    283}
    284
    285inline void Processor::OPCodes_ADC(u8 number)
    286{
    287    int carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;
    288    int result = AF.GetHigh() + number + carry;
    289    ClearAllFlags();
    290    ToggleZeroFlagFromResult(static_cast<u8> (result));
    291    if (result > 0xFF)
    292    {
    293        ToggleFlag(FLAG_CARRY);
    294    }
    295    if (((AF.GetHigh()& 0x0F) + (number & 0x0F) + carry) > 0x0F)
    296    {
    297        ToggleFlag(FLAG_HALF);
    298    }
    299    AF.SetHigh(static_cast<u8> (result));
    300}
    301
    302inline void Processor::OPCodes_SUB(u8 number)
    303{
    304    int result = AF.GetHigh() - number;
    305    int carrybits = AF.GetHigh() ^ number ^ result;
    306    AF.SetHigh(static_cast<u8> (result));
    307    SetFlag(FLAG_SUB);
    308    ToggleZeroFlagFromResult(static_cast<u8> (result));
    309    if ((carrybits & 0x100) != 0)
    310    {
    311        ToggleFlag(FLAG_CARRY);
    312    }
    313    if ((carrybits & 0x10) != 0)
    314    {
    315        ToggleFlag(FLAG_HALF);
    316    }
    317}
    318
    319inline void Processor::OPCodes_SBC(u8 number)
    320{
    321    int carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;
    322    int result = AF.GetHigh() - number - carry;
    323    SetFlag(FLAG_SUB);
    324    ToggleZeroFlagFromResult(static_cast<u8> (result));
    325    if (result < 0)
    326    {
    327        ToggleFlag(FLAG_CARRY);
    328    }
    329    if (((AF.GetHigh() & 0x0F) - (number & 0x0F) - carry) < 0)
    330    {
    331        ToggleFlag(FLAG_HALF);
    332    }
    333    AF.SetHigh(static_cast<u8> (result));
    334}
    335
    336inline void Processor::OPCodes_ADD_HL(u16 number)
    337{
    338    int result = HL.GetValue() + number;
    339    IsSetFlag(FLAG_ZERO) ? SetFlag(FLAG_ZERO) : ClearAllFlags();
    340    if (result & 0x10000)
    341    {
    342        ToggleFlag(FLAG_CARRY);
    343    }
    344    if ((HL.GetValue() ^ number ^ (result & 0xFFFF)) & 0x1000)
    345    {
    346        ToggleFlag(FLAG_HALF);
    347    }
    348    HL.SetValue(static_cast<u16> (result));
    349}
    350
    351inline void Processor::OPCodes_ADD_SP(s8 number)
    352{
    353    int result = SP.GetValue() + number;
    354    ClearAllFlags();
    355    if (((SP.GetValue() ^ number ^ (result & 0xFFFF)) & 0x100) == 0x100)
    356    {
    357        ToggleFlag(FLAG_CARRY);
    358    }
    359    if (((SP.GetValue() ^ number ^ (result & 0xFFFF)) & 0x10) == 0x10)
    360    {
    361        ToggleFlag(FLAG_HALF);
    362    }
    363    SP.SetValue(static_cast<u16> (result));
    364}
    365
    366inline void Processor::OPCodes_SWAP_Register(u8* reg)
    367{
    368    u8 low_half = *reg & 0x0F;
    369    u8 high_half = (*reg >> 4) & 0x0F;
    370    *reg = (low_half << 4) + high_half;
    371    ClearAllFlags();
    372    ToggleZeroFlagFromResult(*reg);
    373}
    374
    375inline void Processor::OPCodes_SWAP_HL()
    376{
    377    if (m_iAccurateOPCodeState == 1)
    378    {
    379        m_iReadCache = m_pMemory->Read(HL.GetValue());
    380        return;
    381    }
    382    u8 low_half = m_iReadCache & 0x0F;
    383    u8 high_half = (m_iReadCache >> 4) & 0x0F;
    384    m_iReadCache = (low_half << 4) + high_half;
    385    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    386    ClearAllFlags();
    387    ToggleZeroFlagFromResult(m_iReadCache);
    388}
    389
    390inline void Processor::OPCodes_SLA(u8* reg)
    391{
    392    (*reg & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    393    u8 result = *reg << 1;
    394    *reg = result;
    395    ToggleZeroFlagFromResult(result);
    396}
    397
    398inline void Processor::OPCodes_SLA_HL()
    399{
    400    if (m_iAccurateOPCodeState == 1)
    401    {
    402        m_iReadCache = m_pMemory->Read(HL.GetValue());
    403        return;
    404    }
    405    (m_iReadCache & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    406    m_iReadCache <<= 1;
    407    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    408    ToggleZeroFlagFromResult(m_iReadCache);
    409}
    410
    411inline void Processor::OPCodes_SRA(u8* reg)
    412{
    413    u8 result = *reg;
    414    (result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    415    if ((result & 0x80) != 0)
    416    {
    417        result >>= 1;
    418        result |= 0x80;
    419    }
    420    else
    421    {
    422        result >>= 1;
    423    }
    424    *reg = result;
    425    ToggleZeroFlagFromResult(result);
    426}
    427
    428inline void Processor::OPCodes_SRA_HL()
    429{
    430    if (m_iAccurateOPCodeState == 1)
    431    {
    432        m_iReadCache = m_pMemory->Read(HL.GetValue());
    433        return;
    434    }
    435    (m_iReadCache & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    436    if ((m_iReadCache & 0x80) != 0)
    437    {
    438        m_iReadCache >>= 1;
    439        m_iReadCache |= 0x80;
    440    }
    441    else
    442    {
    443        m_iReadCache >>= 1;
    444    }
    445    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    446    ToggleZeroFlagFromResult(m_iReadCache);
    447}
    448
    449inline void Processor::OPCodes_SRL(u8* reg)
    450{
    451    u8 result = *reg;
    452    (result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    453    result >>= 1;
    454    *reg = result;
    455    ToggleZeroFlagFromResult(result);
    456}
    457
    458inline void Processor::OPCodes_SRL_HL()
    459{
    460    if (m_iAccurateOPCodeState == 1)
    461    {
    462        m_iReadCache = m_pMemory->Read(HL.GetValue());
    463        return;
    464    }
    465    (m_iReadCache & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    466    m_iReadCache >>= 1;
    467    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    468    ToggleZeroFlagFromResult(m_iReadCache);
    469}
    470
    471inline void Processor::OPCodes_RLC(u8* reg, bool isRegisterA)
    472{
    473    u8 result = *reg;
    474    if ((result & 0x80) != 0)
    475    {
    476        SetFlag(FLAG_CARRY);
    477        result <<= 1;
    478        result |= 0x1;
    479    }
    480    else
    481    {
    482        ClearAllFlags();
    483        result <<= 1;
    484    }
    485    *reg = result;
    486    if (!isRegisterA)
    487    {
    488        ToggleZeroFlagFromResult(result);
    489    }
    490}
    491
    492inline void Processor::OPCodes_RLC_HL()
    493{
    494    if (m_iAccurateOPCodeState == 1)
    495    {
    496        m_iReadCache = m_pMemory->Read(HL.GetValue());
    497        return;
    498    }
    499    if ((m_iReadCache & 0x80) != 0)
    500    {
    501        SetFlag(FLAG_CARRY);
    502        m_iReadCache <<= 1;
    503        m_iReadCache |= 0x1;
    504    }
    505    else
    506    {
    507        ClearAllFlags();
    508        m_iReadCache <<= 1;
    509    }
    510    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    511    ToggleZeroFlagFromResult(m_iReadCache);
    512}
    513
    514inline void Processor::OPCodes_RL(u8* reg, bool isRegisterA)
    515{
    516    u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;
    517    u8 result = *reg;
    518    ((result & 0x80) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    519    result <<= 1;
    520    result |= carry;
    521    *reg = result;
    522    if (!isRegisterA)
    523    {
    524        ToggleZeroFlagFromResult(result);
    525    }
    526}
    527
    528inline void Processor::OPCodes_RL_HL()
    529{
    530    if (m_iAccurateOPCodeState == 1)
    531    {
    532        m_iReadCache = m_pMemory->Read(HL.GetValue());
    533        return;
    534    }
    535    u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;
    536    ((m_iReadCache & 0x80) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    537    m_iReadCache <<= 1;
    538    m_iReadCache |= carry;
    539    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    540    ToggleZeroFlagFromResult(m_iReadCache);
    541}
    542
    543inline void Processor::OPCodes_RRC(u8* reg, bool isRegisterA)
    544{
    545    u8 result = *reg;
    546    if ((result & 0x01) != 0)
    547    {
    548        SetFlag(FLAG_CARRY);
    549        result >>= 1;
    550        result |= 0x80;
    551    }
    552    else
    553    {
    554        ClearAllFlags();
    555        result >>= 1;
    556    }
    557    *reg = result;
    558    if (!isRegisterA)
    559    {
    560        ToggleZeroFlagFromResult(result);
    561    }
    562}
    563
    564inline void Processor::OPCodes_RRC_HL()
    565{
    566    if (m_iAccurateOPCodeState == 1)
    567    {
    568        m_iReadCache = m_pMemory->Read(HL.GetValue());
    569        return;
    570    }
    571    if ((m_iReadCache & 0x01) != 0)
    572    {
    573        SetFlag(FLAG_CARRY);
    574        m_iReadCache >>= 1;
    575        m_iReadCache |= 0x80;
    576    }
    577    else
    578    {
    579        ClearAllFlags();
    580        m_iReadCache >>= 1;
    581    }
    582    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    583    ToggleZeroFlagFromResult(m_iReadCache);
    584}
    585
    586inline void Processor::OPCodes_RR(u8* reg, bool isRegisterA)
    587{
    588    u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00;
    589    u8 result = *reg;
    590    ((result & 0x01) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    591    result >>= 1;
    592    result |= carry;
    593    *reg = result;
    594    if (!isRegisterA)
    595    {
    596        ToggleZeroFlagFromResult(result);
    597    }
    598}
    599
    600inline void Processor::OPCodes_RR_HL()
    601{
    602    if (m_iAccurateOPCodeState == 1)
    603    {
    604        m_iReadCache = m_pMemory->Read(HL.GetValue());
    605        return;
    606    }
    607    u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00;
    608    ((m_iReadCache & 0x01) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
    609    m_iReadCache >>= 1;
    610    m_iReadCache |= carry;
    611    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    612    ToggleZeroFlagFromResult(m_iReadCache);
    613}
    614
    615inline void Processor::OPCodes_BIT(u8* reg, int bit)
    616{
    617    if (((*reg >> bit) & 0x01) == 0)
    618    {
    619        ToggleFlag(FLAG_ZERO);
    620    }
    621    else
    622    {
    623        UntoggleFlag(FLAG_ZERO);
    624    }
    625    ToggleFlag(FLAG_HALF);
    626    UntoggleFlag(FLAG_SUB);
    627}
    628
    629inline void Processor::OPCodes_BIT_HL(int bit)
    630{
    631    if (((m_pMemory->Read(HL.GetValue()) >> bit) & 0x01) == 0)
    632    {
    633        ToggleFlag(FLAG_ZERO);
    634    }
    635    else
    636    {
    637        UntoggleFlag(FLAG_ZERO);
    638    }
    639    ToggleFlag(FLAG_HALF);
    640    UntoggleFlag(FLAG_SUB);
    641}
    642
    643inline void Processor::OPCodes_SET(u8* reg, int bit)
    644{
    645    *reg = (*reg | (0x1 << bit));
    646}
    647
    648inline void Processor::OPCodes_SET_HL(int bit)
    649{
    650    if (m_iAccurateOPCodeState == 1)
    651    {
    652        m_iReadCache = m_pMemory->Read(HL.GetValue());
    653        return;
    654    }
    655    m_iReadCache |= (0x1 << bit);
    656    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    657}
    658
    659inline void Processor::OPCodes_RES(u8* reg, int bit)
    660{
    661    *reg = (*reg & (~(0x1 << bit)));
    662}
    663
    664inline void Processor::OPCodes_RES_HL(int bit)
    665{
    666    if (m_iAccurateOPCodeState == 1)
    667    {
    668        m_iReadCache = m_pMemory->Read(HL.GetValue());
    669        return;
    670    }
    671    m_iReadCache &= ~(0x1 << bit);
    672    m_pMemory->Write(HL.GetValue(), m_iReadCache);
    673}
    674
    675#endif	/* PROCESSOR_INLINE_H */
    676