1 module nes.mapper3; 2 3 import std.conv; 4 import std.format; 5 6 import nes.cartridge; 7 import nes.mapper; 8 9 class Mapper3 : Mapper { 10 this(Cartridge cartridge) { 11 this.cart = cartridge; 12 this.chrBank = 0; 13 this.prgBank1 = 0; 14 15 auto prgBanks = cast(int)(cartridge.prg.length / 0x4000); 16 17 this.prgBank2 = prgBanks - 1; 18 } 19 20 void step() { 21 } 22 23 ubyte read(ushort address) { 24 if (address < 0x2000) { 25 auto index = this.chrBank * 0x2000 + cast(int)address; 26 return this.cart.chr[index]; 27 } 28 else if (address >= 0xC000) { 29 auto index = this.prgBank2 * 0x4000 + cast(int)(address - 0xC000); 30 return this.cart.prg[index]; 31 } 32 else if (address >= 0x8000) { 33 auto index = this.prgBank1 * 0x4000 + cast(int)(address - 0x8000); 34 return this.cart.prg[index]; 35 } 36 else if (address >= 0x6000) { 37 auto index = cast(int)address - 0x6000; 38 return this.cart.sram[index]; 39 } 40 else { 41 throw new MapperException(format("unhandled mapper3 read at address: 0x%04X", address)); 42 } 43 } 44 45 void write(ushort address, ubyte value) { 46 if (address < 0x2000) { 47 auto index = this.chrBank * 0x2000 + cast(int)address; 48 this.cart.chr[index] = value; 49 } 50 else if (address >= 0x8000) { 51 this.chrBank = cast(int)(value & 3); 52 } 53 else if (address >= 0x6000) { 54 auto index = cast(int)address - 0x6000; 55 this.cart.sram[index] = value; 56 } 57 else { 58 throw new MapperException(format("unhandled mapper3 write at address: 0x%04X", address)); 59 } 60 } 61 62 void save(string[string] state) { 63 state["mapper3.chrBank"] = to!string(this.chrBank); 64 state["mapper3.prgBank1"] = to!string(this.prgBank1); 65 state["mapper3.prgBank2"] = to!string(this.prgBank2); 66 } 67 68 void load(string[string] state) { 69 this.chrBank = to!int(state["mapper3.chrBank"]); 70 this.prgBank1 = to!int(state["mapper3.prgBank1"]); 71 this.prgBank2 = to!int(state["mapper3.prgBank2"]); 72 } 73 74 private: 75 Cartridge cart; 76 int chrBank; 77 int prgBank1; 78 int prgBank2; 79 }