Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.nintendo.gameboy.mem;
- /**
- * Performs the virtual memory mangement of the Gameboy or Gameboy Color.
- *
- * @author Ryan Greene
- *
- */
- public final class MemoryManagementUnit {
- /**
- * The Gameboy's BIOS which isn't held in a ROM due to it being a constant.
- */
- private static final int[] BIOS = new int[] { 0x31, 0xFE, 0xFF, 0xAF, 0x21, 0xFF, 0x9F, 0x32, 0xCB, 0x7C, 0x20, 0xFB, 0x21, 0x26, 0xFF, 0x0E, 0x11, 0x3E, 0x80, 0x32, 0xE2, 0x0C, 0x3E, 0xF3,
- 0xE2, 0x32, 0x3E, 0x77, 0x77, 0x3E, 0xFC, 0xE0, 0x47, 0x11, 0x04, 0x01, 0x21, 0x10, 0x80, 0x1A, 0xCD, 0x95, 0x00, 0xCD, 0x96, 0x00, 0x13, 0x7B, 0xFE, 0x34, 0x20, 0xF3, 0x11, 0xD8,
- 0x00, 0x06, 0x08, 0x1A, 0x13, 0x22, 0x23, 0x05, 0x20, 0xF9, 0x3E, 0x19, 0xEA, 0x10, 0x99, 0x21, 0x2F, 0x99, 0x0E, 0x0C, 0x3D, 0x28, 0x08, 0x32, 0x0D, 0x20, 0xF9, 0x2E, 0x0F, 0x18,
- 0xF3, 0x67, 0x3E, 0x64, 0x57, 0xE0, 0x42, 0x3E, 0x91, 0xE0, 0x40, 0x04, 0x1E, 0x02, 0x0E, 0x0C, 0xF0, 0x44, 0xFE, 0x90, 0x20, 0xFA, 0x0D, 0x20, 0xF7, 0x1D, 0x20, 0xF2, 0x0E, 0x13,
- 0x24, 0x7C, 0x1E, 0x83, 0xFE, 0x62, 0x28, 0x06, 0x1E, 0xC1, 0xFE, 0x64, 0x20, 0x06, 0x7B, 0xE2, 0x0C, 0x3E, 0x87, 0xF2, 0xF0, 0x42, 0x90, 0xE0, 0x42, 0x15, 0x20, 0xD2, 0x05, 0x20,
- 0x4F, 0x16, 0x20, 0x18, 0xCB, 0x4F, 0x06, 0x04, 0xC5, 0xCB, 0x11, 0x17, 0xC1, 0xCB, 0x11, 0x17, 0x05, 0x20, 0xF5, 0x22, 0x23, 0x22, 0x23, 0xC9, 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D,
- 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, 0xBB, 0xBB, 0x67, 0x63,
- 0x6E, 0x0E, 0xEC, 0xCC, 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E, 0x3c, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x4C, 0x21, 0x04, 0x01, 0x11, 0xA8, 0x00, 0x1A, 0x13, 0xBE, 0x20,
- 0xFE, 0x23, 0x7D, 0xFE, 0x34, 0x20, 0xF5, 0x06, 0x19, 0x78, 0x86, 0x23, 0x05, 0x20, 0xFB, 0x86, 0x20, 0xFE, 0x3E, 0x01, 0xE0, 0x50 };
- /**
- * The ROM which is currently loaded in the memory.
- */
- private byte[] rom;
- /**
- * The external RAM.
- */
- private final byte[] externalRam;
- /**
- * The working RAM.
- */
- private final byte[] workRam;
- /**
- * The zeropage RAM.
- */
- private final byte[] zeropageRam;
- /**
- * Whether or not the memory is still in the BIOS sector.
- */
- private boolean inBios;
- /**
- * Constructs a new memory management unit, reseting the memory.
- */
- public MemoryManagementUnit() {
- workRam = new byte[8192]; // TODO: based off ROM?
- externalRam = new byte[8192];
- zeropageRam = new byte[128];
- reset();
- }
- /**
- * Loads a Gameboy or Gameboy Colored ROM into the memory.
- *
- * @param rom
- * The ROM being loaded into the memory.
- */
- public void loadReadOnlyMemory(final ReadOnlyMemory rom) {
- this.rom = rom.getMemory();
- reset();
- }
- /**
- * Reads a byte from the specified address.
- *
- * @param address
- * The address being read.
- * @return The read byte.
- */
- public int readByte(final int address) {
- switch (address & 0xF000) {
- case 0x0000: // ROM bank 0
- if (inBios) {
- if (address < 0x0100) {
- return BIOS[address];
- } else if (null == null) { // TODO: Z80._r.pc == 0x0100
- inBios = false;
- }
- } else {
- return rom[address];
- }
- case 0x1000:
- case 0x2000:
- case 0x3000:
- return rom[address];
- case 0x4000: // ROM bank 1
- case 0x5000:
- case 0x6000:
- case 0x7000:
- return rom[address];
- case 0x8000: // VRAM
- case 0x9000:
- return 0; // TODO: GPU._vram[addr&0x1FFF];
- case 0xA000: // External RAM
- case 0xB000:
- return externalRam[address & 0x1FFF];
- case 0xC000: // Work RAM and echo
- case 0xD000:
- case 0xE000:
- return workRam[address & 0x1FFF];
- case 0xF000: // Everything else
- switch (address & 0x0F00) {
- case 0x000: // Echo RAM
- case 0x100:
- case 0x200:
- case 0x300:
- case 0x400:
- case 0x500:
- case 0x600:
- case 0x700:
- case 0x800:
- case 0x900:
- case 0xA00:
- case 0xB00:
- case 0xC00:
- case 0xD00:
- return workRam[address & 0x1FFF];
- case 0xE000: // OAM
- return (address & 0xFF) < 0xA0 ? 0 : 0; // TODO: ((address & 0xFF) < 0xA0) ? GPU._oam[address & 0xFF] : 0;
- case 0xF00: // Zeropage RAM, I/O
- if (address > 0xFF7F) {
- return zeropageRam[address & 0x7F];
- } else {
- switch (address & 0xF0) {
- // TODO: ?
- }
- }
- }
- }
- throw new OutOfMemoryError("Invalid address given while reading byte");
- }
- /**
- * Reads a word from the specified address.
- *
- * @param address
- * The address being read.
- * @return The read word.
- */
- public int readWord(final int address) {
- return readByte(address) + (readByte(address + 1) << 8);
- }
- /**
- * Writes the specified byte to the specified address.
- *
- * @param address
- * The address the value is written to.
- * @param value
- * The value written at the address.
- */
- public void writeByte(final int address, final int value) { // TODO: integer to byte?
- switch (address & 0xF000) {
- case 0x0000: // ROM bank 0
- if (inBios && address < 0x0100) {
- return;
- } // fall through
- case 0x1000:
- case 0x2000:
- case 0x3000:
- break;
- case 0x4000: // ROM bank 1
- case 0x5000:
- case 0x6000:
- case 0x7000:
- break;
- case 0x8000: // VRAM
- case 0x9000:
- // TODO: GPU._vram[address & 0x1FFF] = value;
- // TODO: GPU.updatetile(address & 0x1FFF, value);
- break;
- case 0xA000: // External RAM
- case 0xB000:
- externalRam[address & 0x1FFF] = (byte) value;
- break;
- case 0xC000: // Work RAM and echo
- case 0xD000:
- case 0xE000:
- workRam[address & 0x1FFF] = (byte) value;
- break;
- case 0xF000:
- switch (address & 0x0F00) {
- case 0x000: // Echo RAM
- case 0x100:
- case 0x200:
- case 0x300:
- case 0x400:
- case 0x500:
- case 0x600:
- case 0x700:
- case 0x800:
- case 0x900:
- case 0xA00:
- case 0xB00:
- case 0xC00:
- case 0xD00:
- workRam[address & 0x1FFF] = (byte) value;
- break;
- case 0xE00: // OAM
- if ((address & 0xFF) < 0xA0) {
- // TODO: GPU._oam[address & 0xFF] = value;
- }
- case 0XF00: // Zeropage RAM, I/O
- if (address > 0xFF7F) {
- zeropageRam[address & 0x7F] = (byte) value;
- } else {
- switch (address & 0xF0) {
- // TODO: ?
- }
- }
- }
- }
- }
- /**
- * Writes the specified word to the specified address.
- *
- * @param address
- * The address the value is written to.
- * @param value
- * The value written at the address.
- */
- public void writeWord(final int address, final int value) { // TODO: integer to byte?
- writeByte(address, value & 255);
- writeByte(address + 1, value >> 8);
- }
- /**
- * Resets all of the memory returning it back to the BIOS sector.
- */
- public void reset() {
- for (int i = 0; i < 8192; i++) {
- workRam[i] = 0;
- externalRam[i] = 0;
- }
- for (int i = 0; i < 128; i++) {
- zeropageRam[i] = 0;
- }
- inBios = true;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement