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* handle() { return data; } unsigned size() const { return datasize; } 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) : datasize(n) { data = new uint8[datasize]; } ~StaticRAM() { delete[] data; } private: uint8 *data; unsigned datasize; }; struct MappedRAM : Memory { void map(uint8 *source, unsigned length) { data = source; datasize = length > 0 ? length : -1U; } void write_protect(bool status) { write_protection = status; } uint8* handle() { return data; } unsigned size() const { return datasize; } inline uint8 read(unsigned addr) { return data[addr]; } inline void write(unsigned addr, uint8 n) { if(!write_protection) data[addr] = n; } inline const uint8& operator[](unsigned addr) const { return data[addr]; } MappedRAM() : data(0), datasize(0), write_protection(false) {} private: uint8 *data; unsigned datasize; bool write_protection; }; struct MMIOAccess : Memory { void map(unsigned addr, MMIO &access); MMIO* get(unsigned addr); uint8 read(unsigned addr); void write(unsigned addr, uint8 data); private: MMIO *mmio[0x4000]; }; class Bus { public: 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); } void set_speed(bool fast) { fastSpeed = fast ? 6 : 8; } alwaysinline unsigned speed(unsigned addr) const { if(addr & 0x408000) { if(addr & 0x800000) return fastSpeed; return 8; } if((addr + 0x6000) & 0x4000) return 8; if((addr - 0x4000) & 0x7e00) return 6; return 12; } virtual bool load_cart() = 0; virtual void unload_cart() = 0; virtual void power() = 0; virtual void reset() = 0; Bus() {} virtual ~Bus() {} protected: struct Page { Memory *access; unsigned offset; } page[65536]; unsigned fastSpeed; }; 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; };