bsnes/higan/sfc/cpu/cpu.hpp
Tim Allen 1929ad47d2 Update to v098r03 release.
byuu says:

It took several hours, but I've rebuilt much of the SNES' bus memory
mapping architecture.

The new design unifies the cartridge string-based mapping
("00-3f,80-bf:8000-ffff") and internal bus.map calls. The map() function
now has an accompanying unmap() function, and instead of a fixed 256
callbacks, it'll scan to find the first available slot. unmap() will
free slots up when zero addresses reference a given slot.

The controllers and expansion port are now both entirely dynamic.
Instead of load/unload/power/reset, they only have the constructor
(power/reset/load) and destructor (unload). What this means is you can
now dynamically change even expansion port devices after the system is
loaded.

Note that this is incredibly dangerous and stupid, but ... oh well. The
whole point of this was for 21fx. There's no way to change the expansion
port device prior to loading a game, but if the 21fx isn't active, then
the reset vector hijack won't work. Now you can load a 21fx game, change
the expansion port device, and simply reset the system to active the
device.

The unification of design between controller port devices and expansion
port devices is nice, and overall this results in a reduction of code
(all of the Mapping stuff in Cartridge is gone, replaced with direct bus
mapping.) And there's always the potential to expand this system more in
the future now.

The big missing feature right now is the ability to push/pop mappings.
So if you look at how the 21fx does the reset vector, you might vomit
a little bit. But ... it works.

Also changed exit(0) to _exit(0) in the POSIX version of nall::execute.

[The _exit(0) thing is an attempt to make higan not crash when it tries
to launch icarus and it's not on $PATH. The theory is that higan forks,
then the child tries to exec icarus and fails, so it exits, all the
unique_ptrs clean up their resources and tell the X server to free
things the parent process is still using. Calling _exit() prevents
destructors from running, and seems to prevent the problem. -Ed.]
2016-04-09 20:21:18 +10:00

256 lines
5.2 KiB
C++

struct CPU : Processor::R65816, Thread, PPUcounter {
auto interruptPending() const -> bool override;
auto pio() const -> uint8;
auto joylatch() const -> bool;
CPU();
alwaysinline auto step(uint clocks) -> void;
alwaysinline auto synchronizeSMP() -> void;
auto synchronizePPU() -> void;
auto synchronizeCoprocessors() -> void;
auto synchronizePeripherals() -> void;
auto portRead(uint2 port) const -> uint8;
auto portWrite(uint2 port, uint8 data) -> void;
static auto Enter() -> void;
auto main() -> void;
auto power() -> void;
auto reset() -> void;
//dma.cpp
auto dmaAddClocks(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;
auto dmaAddressB(uint n, uint channel) -> uint8;
auto dmaAddress(uint n) -> uint24;
auto hdmaAddress(uint n) -> uint24;
auto hdmaIndirectAddress(uint n) -> uint24;
auto dmaEnabledChannels() -> uint;
auto hdmaActive(uint n) -> bool;
auto hdmaActiveAfter(uint s) -> bool;
auto hdmaEnabledChannels() -> uint;
auto hdmaActiveChannels() -> uint;
auto dmaRun() -> void;
auto hdmaUpdate(uint n) -> void;
auto hdmaRun() -> void;
auto hdmaInitReset() -> void;
auto hdmaInit() -> void;
//memory.cpp
auto io() -> void override;
auto read(uint24 addr) -> uint8 override;
auto write(uint24 addr, uint8 data) -> void override;
alwaysinline auto speed(uint24 addr) const -> uint;
auto disassemblerRead(uint24 addr) -> uint8 override;
//mmio.cpp
auto apuPortRead(uint24 addr, uint8 data) -> uint8;
auto cpuPortRead(uint24 addr, uint8 data) -> uint8;
auto dmaPortRead(uint24 addr, uint8 data) -> uint8;
auto apuPortWrite(uint24 addr, uint8 data) -> void;
auto cpuPortWrite(uint24 addr, uint8 data) -> void;
auto dmaPortWrite(uint24 addr, uint8 data) -> void;
//timing.cpp
auto dmaCounter() const -> uint;
auto addClocks(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 stepAutoJoypadPoll() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
uint8 wram[128 * 1024];
vector<Thread*> coprocessors;
vector<Thread*> peripherals;
privileged:
uint cpu_version = 2; //allowed: 1, 2
struct Status {
bool interrupt_pending;
uint clock_count;
uint line_clocks;
//timing
bool irq_lock;
uint dram_refresh_position;
bool dram_refreshed;
uint hdma_init_position;
bool hdma_init_triggered;
uint hdma_position;
bool hdma_triggered;
bool nmi_valid;
bool nmi_line;
bool nmi_transition;
bool nmi_pending;
bool nmi_hold;
bool irq_valid;
bool irq_line;
bool irq_transition;
bool irq_pending;
bool irq_hold;
bool power_pending;
bool reset_pending;
//DMA
bool dma_active;
uint dma_counter;
uint dma_clocks;
bool dma_pending;
bool hdma_pending;
bool hdma_mode; //0 = init, 1 = run
//auto joypad polling
bool auto_joypad_active;
bool auto_joypad_latch;
uint auto_joypad_counter;
uint auto_joypad_clock;
//MMIO
//$2140-217f
uint8 port[4];
//$2181-$2183
uint17 wram_addr;
//$4016-$4017
bool joypad_strobe_latch;
uint32 joypad1_bits;
uint32 joypad2_bits;
//$4200
bool nmi_enabled;
bool hirq_enabled, virq_enabled;
bool auto_joypad_poll;
//$4201
uint8 pio;
//$4202-$4203
uint8 wrmpya;
uint8 wrmpyb;
//$4204-$4206
uint16 wrdiva;
uint8 wrdivb;
//$4207-$420a
uint9 hirq_pos;
uint9 virq_pos;
//$420d
uint rom_speed;
//$4214-$4217
uint16 rddiv;
uint16 rdmpy;
//$4218-$421f
uint16 joy1;
uint16 joy2;
uint16 joy3;
uint16 joy4;
} status;
struct ALU {
uint mpyctr;
uint divctr;
uint shift;
} alu;
struct Channel {
//$420b
bool dma_enabled;
//$420c
bool hdma_enabled;
//$43x0
bool direction;
bool indirect;
bool unused;
bool reverse_transfer;
bool fixed_transfer;
uint3 transfer_mode;
//$43x1
uint8 dest_addr;
//$43x2-$43x3
uint16 source_addr;
//$43x4
uint8 source_bank;
//$43x5-$43x6
union {
uint16_t transfer_size;
uint16_t indirect_addr;
};
//$43x7
uint8 indirect_bank;
//$43x8-$43x9
uint16 hdma_addr;
//$43xa
uint8 line_counter;
//$43xb/$43xf
uint8 unknown;
//internal state
bool hdma_completed;
bool hdma_do_transfer;
} channel[8];
struct Pipe {
bool valid;
uint addr;
uint8 data;
} pipe;
struct Debugger {
hook<auto (uint24) -> void> op_exec;
hook<auto (uint24, uint8) -> void> op_read;
hook<auto (uint24, uint8) -> void> op_write;
hook<auto () -> void> op_nmi;
hook<auto () -> void> op_irq;
} debugger;
};
extern CPU cpu;