mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-24 15:12:23 +01:00
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.
245 lines
4.9 KiB
C++
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;
|