struct Memory { virtual unsigned size() const { return 0; } virtual uint8 read(unsigned addr) = 0; virtual void write(unsigned addr, uint8 data) = 0; }; struct MMIO { virtual uint8 mmio_read(unsigned addr) = 0; virtual void mmio_write(unsigned addr, uint8 data) = 0; }; struct UnmappedMemory : Memory { uint8 read(unsigned); void write(unsigned, uint8); }; struct UnmappedMMIO : MMIO { uint8 mmio_read(unsigned); void mmio_write(unsigned, uint8); }; struct StaticRAM : Memory { uint8* data() { return data_; } unsigned size() const { return size_; } inline uint8 read(unsigned addr) { return data_[addr]; } inline void write(unsigned addr, uint8 n) { data_[addr] = n; } inline uint8& operator[](unsigned addr) { return data_[addr]; } inline const uint8& operator[](unsigned addr) const { return data_[addr]; } StaticRAM(unsigned n) : size_(n) { data_ = new uint8[size_]; } ~StaticRAM() { delete[] data_; } private: uint8 *data_; unsigned size_; }; struct MappedRAM : Memory { void reset() { if(data_) { delete[] data_; data_ = 0; } size_ = -1U; write_protect_ = false; } void map(uint8 *source, unsigned length) { reset(); data_ = source; size_ = data_ && length > 0 ? length : -1U; } void write_protect(bool status) { write_protect_ = status; } uint8* data() { return data_; } unsigned size() const { return size_; } inline uint8 read(unsigned addr) { return data_[addr]; } inline void write(unsigned addr, uint8 n) { if(!write_protect_) data_[addr] = n; } inline const uint8 operator[](unsigned addr) const { return data_[addr]; } MappedRAM() : data_(0), size_(-1U), write_protect_(false) {} private: uint8 *data_; unsigned size_; bool write_protect_; }; struct MMIOAccess : Memory { void map(unsigned addr, MMIO &access); uint8 read(unsigned addr); void write(unsigned addr, uint8 data); MMIO *mmio[0x4000]; }; struct Bus { unsigned mirror(unsigned addr, unsigned size); void map(unsigned addr, Memory &access, unsigned offset); enum MapMode { MapDirect, MapLinear, MapShadow }; void map(MapMode mode, uint8 bank_lo, uint8 bank_hi, uint16 addr_lo, uint16 addr_hi, Memory &access, unsigned offset = 0, unsigned size = 0); alwaysinline uint8 read(unsigned addr) { #if defined(CHEAT_SYSTEM) if(cheat.active() && cheat.exists(addr)) { uint8 r; if(cheat.read(addr, r)) return r; } #endif Page &p = page[addr >> 8]; return p.access->read(p.offset + addr); } alwaysinline void write(unsigned addr, uint8 data) { Page &p = page[addr >> 8]; return p.access->write(p.offset + addr, data); } virtual bool load_cart() { return false; } virtual void unload_cart() {} virtual void power() {} virtual void reset() {} Bus() {} virtual ~Bus() {} struct Page { Memory *access; unsigned offset; } page[65536]; }; namespace memory { extern MMIOAccess mmio; //S-CPU, S-PPU extern StaticRAM wram; //S-CPU extern StaticRAM apuram; //S-SMP, S-DSP extern StaticRAM vram; //S-PPU extern StaticRAM oam; //S-PPU extern StaticRAM cgram; //S-PPU extern UnmappedMemory memory_unmapped; extern UnmappedMMIO mmio_unmapped; };