bsnes/higan/sfc/cpu/cpu.hpp
Tim Allen a4629e1f64 Update to v102r21 release.
byuu says:

Changelog:

  - GBA: fixed WININ2 reads, BG3PB writes [Jonas Quinn]
  - R65816: added support for yielding/resuming from WAI/STP¹
  - SFC: removed status.dmaCounter functionality (also fixes possible
    TAS desync issue)
  - tomoko: added support for combinatorial inputs [hex\_usr\]²
  - nall: fixed missing return value from Arithmetic::operator--
    [Hendricks266]

Now would be the time to start looking for major regressions with the
new GBA PPU renderer, I suppose ...

¹: this doesn't matter for the master thread (SNES CPU), but is
important for slave threads (SNES SA1). If you try to save a state and
the SA1 is inside of a WAI instruction, it will get stuck there forever.
This was causing attempts to create a save state in Super Bomberman
- Panic Bomber W to deadlock the emulator and crash it. This is now
finally fixed.

Note that I still need to implement similar functionality into the Mega
Drive 68K and Z80 cores. They still have the possibility of deadlocking.
The SNES implementation was more a dry-run test for this new
functionality. This possible crashing bug in the Mega Drive core is the
major blocking bug for a new official release.

²: many, many thanks to hex\_usr for coming up with a really nice
design. I mostly implemented it the exact same way, but with a few tiny
differences that don't really matter (display " and ", " or " instead of
" & ", " | " in the input settings windows; append → bind;
assignmentName changed to displayName.)

The actual functionality is identical to the old higan v094 and earlier
builds. Emulated digital inputs let you combine multiple possible keys
to trigger the buttons. This is OR logic, so you can map to eg
keyboard.up OR gamepad.up for instance. Emulated analog inputs always
sum together. Emulated rumble outputs will cause all mapped devices to
rumble, which is probably not at all useful but whatever. Hotkeys use
AND logic, so you have to press every key mapped to trigger them. Useful
for eg Ctrl+F to trigger fullscreen.

Obviously, there are cases where OR logic would be nice for hotkeys,
too. Eg if you want both F11 and your gamepad's guide button to trigger
the fullscreen toggle. Unfortunately, this isn't supported, and likely
won't ever be in tomoko. Something I might consider is a throw switch in
the configuration file to swap between AND or OR logic for hotkeys, but
I'm not going to allow construction of mappings like "(Keyboard.Ctrl and
Keyboard.F) or Gamepad.Guide", as that's just too complicated to code,
and too complicated to make a nice GUI to set up the mappings for.
2017-06-06 23:44:40 +10:00

245 lines
4.9 KiB
C++

struct CPU : Processor::R65816, Thread, PPUcounter {
auto interruptPending() const -> bool override;
auto pio() const -> uint8;
auto joylatch() const -> bool;
auto synchronizing() const -> bool override;
CPU();
auto readPort(uint2 port) const -> uint8;
auto writePort(uint2 port, uint8 data) -> void;
static auto Enter() -> void;
auto main() -> void;
auto load(Markup::Node) -> bool;
auto power() -> void;
//dma.cpp
auto dmaStep(uint clocks) -> void;
auto dmaTransferValid(uint8 bbus, uint24 abus) -> bool;
auto dmaAddressValid(uint24 abus) -> bool;
auto dmaRead(uint24 abus) -> uint8;
auto dmaWrite(bool valid, uint addr = 0, uint8 data = 0) -> void;
auto dmaTransfer(bool direction, uint8 bbus, uint24 abus) -> void;
inline auto dmaAddressB(uint n, uint channel) -> uint8;
inline auto dmaAddress(uint n) -> uint24;
inline auto hdmaAddress(uint n) -> uint24;
inline auto hdmaIndirectAddress(uint n) -> uint24;
inline auto dmaEnabledChannels() -> uint;
inline auto hdmaActive(uint n) -> bool;
inline auto hdmaActiveAfter(uint s) -> bool;
inline auto hdmaEnabledChannels() -> uint;
inline auto hdmaActiveChannels() -> uint;
auto dmaRun() -> void;
auto hdmaUpdate(uint n) -> void;
auto hdmaRun() -> void;
auto hdmaInitReset() -> void;
auto hdmaInit() -> void;
//memory.cpp
auto idle() -> void override;
auto read(uint24 addr) -> uint8 override;
auto write(uint24 addr, uint8 data) -> void override;
alwaysinline auto speed(uint24 addr) const -> uint;
auto readDisassembler(uint24 addr) -> uint8 override;
//io.cpp
auto readAPU(uint24 addr, uint8 data) -> uint8;
auto readCPU(uint24 addr, uint8 data) -> uint8;
auto readDMA(uint24 addr, uint8 data) -> uint8;
auto writeAPU(uint24 addr, uint8 data) -> void;
auto writeCPU(uint24 addr, uint8 data) -> void;
auto writeDMA(uint24 addr, uint8 data) -> void;
//timing.cpp
inline auto dmaCounter() const -> uint;
inline auto joypadCounter() const -> uint;
auto step(uint clocks) -> void;
auto scanline() -> void;
alwaysinline auto aluEdge() -> void;
alwaysinline auto dmaEdge() -> void;
alwaysinline auto lastCycle() -> void;
//irq.cpp
alwaysinline auto pollInterrupts() -> void;
auto nmitimenUpdate(uint8 data) -> void;
auto rdnmi() -> bool;
auto timeup() -> bool;
alwaysinline auto nmiTest() -> bool;
alwaysinline auto irqTest() -> bool;
//joypad.cpp
auto joypadEdge() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
uint8 wram[128 * 1024];
vector<Thread*> coprocessors;
vector<Thread*> peripherals;
private:
uint version = 2; //allowed: 1, 2
uint clockCounter;
struct Status {
bool interruptPending;
uint clockCount;
uint lineClocks;
//timing
bool irqLock;
uint dramRefreshPosition;
bool dramRefreshed;
uint hdmaInitPosition;
bool hdmaInitTriggered;
uint hdmaPosition;
bool hdmaTriggered;
bool nmiValid;
bool nmiLine;
bool nmiTransition;
bool nmiPending;
bool nmiHold;
bool irqValid;
bool irqLine;
bool irqTransition;
bool irqPending;
bool irqHold;
bool powerPending;
bool resetPending;
//DMA
bool dmaActive;
uint dmaClocks;
bool dmaPending;
bool hdmaPending;
bool hdmaMode; //0 = init, 1 = run
//auto joypad polling
bool autoJoypadActive;
bool autoJoypadLatch;
uint autoJoypadCounter;
} status;
struct IO {
//$2140-217f
uint8 port[4];
//$2181-$2183
uint17 wramAddress;
//$4016-$4017
bool joypadStrobeLatch;
//$4200
bool nmiEnabled;
bool hirqEnabled;
bool virqEnabled;
bool autoJoypadPoll;
//$4201
uint8 pio;
//$4202-$4203
uint8 wrmpya;
uint8 wrmpyb;
//$4204-$4206
uint16 wrdiva;
uint8 wrdivb;
//$4207-$420a
uint9 hirqPos;
uint9 virqPos;
//$420d
uint romSpeed;
//$4214-$4217
uint16 rddiv;
uint16 rdmpy;
//$4218-$421f
uint16 joy1;
uint16 joy2;
uint16 joy3;
uint16 joy4;
} io;
struct ALU {
uint mpyctr;
uint divctr;
uint shift;
} alu;
struct Channel {
//$420b
bool dmaEnabled;
//$420c
bool hdmaEnabled;
//$43x0
bool direction;
bool indirect;
bool unused;
bool reverseTransfer;
bool fixedTransfer;
uint3 transferMode;
//$43x1
uint8 targetAddress;
//$43x2-$43x3
uint16 sourceAddress;
//$43x4
uint8 sourceBank;
//$43x5-$43x6
union {
uint16 transferSize;
uint16 indirectAddress;
};
//$43x7
uint8 indirectBank;
//$43x8-$43x9
uint16 hdmaAddress;
//$43xa
uint8 lineCounter;
//$43xb/$43xf
uint8 unknown;
//internal state
bool hdmaCompleted;
bool hdmaDoTransfer;
Channel() : transferSize(0) {}
} channel[8];
struct Pipe {
bool valid;
uint addr;
uint8 data;
} pipe;
};
extern CPU cpu;