diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index b55b3596f..4f48669d5 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -544,6 +544,21 @@ template void Proces break; } continue; + case CycleAddXToAddressLowReadSTA: + next_address_.full = address_.full + x_; + address_.halves.low = next_address_.halves.low; + + // Cf. https://groups.google.com/g/comp.sys.apple2/c/RuTGaRxu5Iw/m/uyFLEsF8ceIJ + // + // STA abs,X has been fixed for the PX (page-crossing) case by adding a dummy read of the + // program counter, so the change was rW -> W. In the non-PX case it still reads the destination + // address, so there is no change: RW -> RW. + if(!is_65c02(personality) || next_address_.full == address_.full) { + throwaway_read(address_.full); + } else { + throwaway_read(pc_.full - 1); + } + break; case CycleAddXToAddressLowRead: next_address_.full = address_.full + x_; address_.halves.low = next_address_.halves.low; diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 1bb88d5c9..c9fa2a59b 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -18,6 +18,7 @@ using namespace CPU::MOS6502; #define AbsoluteXr CycleLoadAddressAbsolute, CycleAddXToAddressLow, OperationCorrectAddressHigh #define AbsoluteYr CycleLoadAddressAbsolute, CycleAddYToAddressLow, OperationCorrectAddressHigh #define AbsoluteXw CycleLoadAddressAbsolute, CycleAddXToAddressLowRead, OperationCorrectAddressHigh +#define AbsoluteXwSTA CycleLoadAddressAbsolute, CycleAddXToAddressLowReadSTA, OperationCorrectAddressHigh #define AbsoluteYw CycleLoadAddressAbsolute, CycleAddYToAddressLowRead, OperationCorrectAddressHigh #define Zero OperationLoadAddressZeroPage #define ZeroX CycleLoadAddessZeroX @@ -43,6 +44,7 @@ using namespace CPU::MOS6502; #define AbsoluteWrite(op) Program(Absolute, Write(op)) #define AbsoluteXWrite(op) Program(AbsoluteXw, Write(op)) +#define AbsoluteXWriteSTA(op) Program(AbsoluteXwSTA, Write(op)) #define AbsoluteYWrite(op) Program(AbsoluteYw, Write(op)) #define ZeroWrite(op) Program(Zero, Write(op)) #define ZeroXWrite(op) Program(ZeroX, Write(op)) @@ -162,7 +164,7 @@ ProcessorStorage::ProcessorStorage(Personality personality) { /* 0x96 STX zpg, y */ ZeroYWrite(OperationSTX), /* 0x97 SAX zpg, y */ ZeroYWrite(OperationSAX), /* 0x98 TYA */ Program(OperationTYA), /* 0x99 STA abs, y */ AbsoluteYWrite(OperationSTA), /* 0x9a TXS */ Program(OperationTXS), /* 0x9b SHS abs, y */ AbsoluteYWrite(OperationSHS), - /* 0x9c SHY abs, x */ AbsoluteXWrite(OperationSHY), /* 0x9d STA abs, x */ AbsoluteXWrite(OperationSTA), + /* 0x9c SHY abs, x */ AbsoluteXWrite(OperationSHY), /* 0x9d STA abs, x */ AbsoluteXWriteSTA(OperationSTA), /* 0x9e SHX abs, y */ AbsoluteYWrite(OperationSHX), /* 0x9f SHA abs, y */ AbsoluteYWrite(OperationSHA), /* 0xa0 LDY # */ Immediate(OperationLDY), /* 0xa1 LDA x, ind */ IndexedIndirectRead(OperationLDA), /* 0xa2 LDX # */ Immediate(OperationLDX), /* 0xa3 LAX x, ind */ IndexedIndirectRead(OperationLAX), diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index 5984e4c27..850f51bea 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -77,6 +77,11 @@ class ProcessorStorage { CycleAddYToAddressLowRead, // calculates address_ + y and stores it to next_address; copies next_address.l back to address_.l; 6502: schedules a throwaway read from address_; 65C02: schedules a throaway read from PC-1 OperationCorrectAddressHigh, // copies next_address_ to address_ + // Implements 65c02-compatible version of CycleAddXToAddressLowRead specialised for STA; on that processor + // a non-page-crossing `STA abs, x` acts exactly like a 6502, doing a read of the target address before + // the write, but a page-crossing store instead performs throaway read from PC-1. + CycleAddXToAddressLowReadSTA, + OperationIncrementPC, // increments the PC CycleFetchOperandFromAddress, // fetches operand_ from address_ CycleWriteOperandToAddress, // writes operand_ to address_