Advertisement
Chiddix

MemoryManagementUnit v0.02

Apr 7th, 2014
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.91 KB | None | 0 0
  1. package com.nintendo.gameboy.mem;
  2.  
  3. /**
  4.  * Performs the virtual memory mangement of the Gameboy or Gameboy Color.
  5.  *
  6.  * @author Ryan Greene
  7.  *
  8.  */
  9. public final class MemoryManagementUnit {
  10.  
  11.     /**
  12.      * The Gameboy's BIOS which isn't held in a ROM due to it being a constant.
  13.      */
  14.     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,
  15.             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,
  16.             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,
  17.             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,
  18.             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,
  19.             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,
  20.             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,
  21.             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,
  22.             0xFE, 0x23, 0x7D, 0xFE, 0x34, 0x20, 0xF5, 0x06, 0x19, 0x78, 0x86, 0x23, 0x05, 0x20, 0xFB, 0x86, 0x20, 0xFE, 0x3E, 0x01, 0xE0, 0x50 };
  23.  
  24.     /**
  25.      * The ROM which is currently loaded in the memory.
  26.      */
  27.     private byte[] rom;
  28.  
  29.     /**
  30.      * The external RAM.
  31.      */
  32.     private final byte[] externalRam;
  33.  
  34.     /**
  35.      * The working RAM.
  36.      */
  37.     private final byte[] workRam;
  38.  
  39.     /**
  40.      * The zeropage RAM.
  41.      */
  42.     private final byte[] zeropageRam;
  43.  
  44.     /**
  45.      * Whether or not the memory is still in the BIOS sector.
  46.      */
  47.     private boolean inBios;
  48.  
  49.     /**
  50.      * Constructs a new memory management unit, reseting the memory.
  51.      */
  52.     public MemoryManagementUnit() {
  53.         workRam = new byte[8192]; // TODO: based off ROM?
  54.         externalRam = new byte[8192];
  55.         zeropageRam = new byte[128];
  56.         reset();
  57.     }
  58.  
  59.     /**
  60.      * Loads a Gameboy or Gameboy Colored ROM into the memory.
  61.      *
  62.      * @param rom
  63.      *            The ROM being loaded into the memory.
  64.      */
  65.     public void loadReadOnlyMemory(final ReadOnlyMemory rom) {
  66.         this.rom = rom.getMemory();
  67.         reset();
  68.     }
  69.  
  70.     /**
  71.      * Reads a byte from the specified address.
  72.      *
  73.      * @param address
  74.      *            The address being read.
  75.      * @return The read byte.
  76.      */
  77.     public int readByte(final int address) {
  78.         switch (address & 0xF000) {
  79.         case 0x0000: // ROM bank 0
  80.             if (inBios) {
  81.                 if (address < 0x0100) {
  82.                     return BIOS[address];
  83.                 } else if (null == null) { // TODO: Z80._r.pc == 0x0100
  84.                     inBios = false;
  85.                 }
  86.             } else {
  87.                 return rom[address];
  88.             }
  89.         case 0x1000:
  90.         case 0x2000:
  91.         case 0x3000:
  92.             return rom[address];
  93.         case 0x4000: // ROM bank 1
  94.         case 0x5000:
  95.         case 0x6000:
  96.         case 0x7000:
  97.             return rom[address];
  98.         case 0x8000: // VRAM
  99.         case 0x9000:
  100.             return 0; // TODO: GPU._vram[addr&0x1FFF];
  101.         case 0xA000: // External RAM
  102.         case 0xB000:
  103.             return externalRam[address & 0x1FFF];
  104.         case 0xC000: // Work RAM and echo
  105.         case 0xD000:
  106.         case 0xE000:
  107.             return workRam[address & 0x1FFF];
  108.         case 0xF000: // Everything else
  109.             switch (address & 0x0F00) {
  110.             case 0x000: // Echo RAM
  111.             case 0x100:
  112.             case 0x200:
  113.             case 0x300:
  114.             case 0x400:
  115.             case 0x500:
  116.             case 0x600:
  117.             case 0x700:
  118.             case 0x800:
  119.             case 0x900:
  120.             case 0xA00:
  121.             case 0xB00:
  122.             case 0xC00:
  123.             case 0xD00:
  124.                 return workRam[address & 0x1FFF];
  125.             case 0xE000: // OAM
  126.                 return (address & 0xFF) < 0xA0 ? 0 : 0; // TODO: ((address & 0xFF) < 0xA0) ? GPU._oam[address & 0xFF] : 0;
  127.             case 0xF00: // Zeropage RAM, I/O
  128.                 if (address > 0xFF7F) {
  129.                     return zeropageRam[address & 0x7F];
  130.                 } else {
  131.                     switch (address & 0xF0) {
  132.                     // TODO: ?
  133.                     }
  134.                 }
  135.             }
  136.         }
  137.         throw new OutOfMemoryError("Invalid address given while reading byte");
  138.     }
  139.  
  140.     /**
  141.      * Reads a word from the specified address.
  142.      *
  143.      * @param address
  144.      *            The address being read.
  145.      * @return The read word.
  146.      */
  147.     public int readWord(final int address) {
  148.         return readByte(address) + (readByte(address + 1) << 8);
  149.     }
  150.  
  151.     /**
  152.      * Writes the specified byte to the specified address.
  153.      *
  154.      * @param address
  155.      *            The address the value is written to.
  156.      * @param value
  157.      *            The value written at the address.
  158.      */
  159.     public void writeByte(final int address, final int value) { // TODO: integer to byte?
  160.         switch (address & 0xF000) {
  161.         case 0x0000: // ROM bank 0
  162.             if (inBios && address < 0x0100) {
  163.                 return;
  164.             } // fall through
  165.         case 0x1000:
  166.         case 0x2000:
  167.         case 0x3000:
  168.             break;
  169.         case 0x4000: // ROM bank 1
  170.         case 0x5000:
  171.         case 0x6000:
  172.         case 0x7000:
  173.             break;
  174.         case 0x8000: // VRAM
  175.         case 0x9000:
  176.             // TODO: GPU._vram[address & 0x1FFF] = value;
  177.             // TODO: GPU.updatetile(address & 0x1FFF, value);
  178.             break;
  179.         case 0xA000: // External RAM
  180.         case 0xB000:
  181.             externalRam[address & 0x1FFF] = (byte) value;
  182.             break;
  183.         case 0xC000: // Work RAM and echo
  184.         case 0xD000:
  185.         case 0xE000:
  186.             workRam[address & 0x1FFF] = (byte) value;
  187.             break;
  188.         case 0xF000:
  189.             switch (address & 0x0F00) {
  190.             case 0x000: // Echo RAM
  191.             case 0x100:
  192.             case 0x200:
  193.             case 0x300:
  194.             case 0x400:
  195.             case 0x500:
  196.             case 0x600:
  197.             case 0x700:
  198.             case 0x800:
  199.             case 0x900:
  200.             case 0xA00:
  201.             case 0xB00:
  202.             case 0xC00:
  203.             case 0xD00:
  204.                 workRam[address & 0x1FFF] = (byte) value;
  205.                 break;
  206.             case 0xE00: // OAM
  207.                 if ((address & 0xFF) < 0xA0) {
  208.                     // TODO: GPU._oam[address & 0xFF] = value;
  209.                 }
  210.             case 0XF00: // Zeropage RAM, I/O
  211.                 if (address > 0xFF7F) {
  212.                     zeropageRam[address & 0x7F] = (byte) value;
  213.                 } else {
  214.                     switch (address & 0xF0) {
  215.                     // TODO: ?
  216.                     }
  217.                 }
  218.             }
  219.         }
  220.     }
  221.  
  222.     /**
  223.      * Writes the specified word to the specified address.
  224.      *
  225.      * @param address
  226.      *            The address the value is written to.
  227.      * @param value
  228.      *            The value written at the address.
  229.      */
  230.     public void writeWord(final int address, final int value) { // TODO: integer to byte?
  231.         writeByte(address, value & 255);
  232.         writeByte(address + 1, value >> 8);
  233.     }
  234.  
  235.     /**
  236.      * Resets all of the memory returning it back to the BIOS sector.
  237.      */
  238.     public void reset() {
  239.         for (int i = 0; i < 8192; i++) {
  240.             workRam[i] = 0;
  241.             externalRam[i] = 0;
  242.         }
  243.         for (int i = 0; i < 128; i++) {
  244.             zeropageRam[i] = 0;
  245.         }
  246.         inBios = true;
  247.     }
  248. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement