Advertisement
Chiddix

ROM v0.02

Apr 6th, 2014
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.19 KB | None | 0 0
  1. package com.nintendo.gameboy;
  2.  
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.nio.charset.Charset;
  8.  
  9. /**
  10.  * Represents a single Gameboy or Gameboy Color ROM.
  11.  *
  12.  * @author Ryan Greene
  13.  *
  14.  */
  15. public final class ROM {
  16.  
  17.     /**
  18.      * These bytes define the bitmap of the Nintendo logo that is displayed when
  19.      * the Gameboy gets turned on. The Gameboy's boot procedure verifies the
  20.      * content of this bitmap (after it has displayed it), and LOCKS ITSELF UP
  21.      * if these bytes are incorrect. A CGB verifies only the first 18h bytes of
  22.      * the bitmap, but others (for example a Pocket Gameboy) verify all 30h
  23.      * bytes. We currently only verify the first and last bytes of the bitmap
  24.      * because I'm lazy.
  25.      */
  26.     private static final int[] NINTENDO_LOGO = new int[] { 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89,
  27.             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 };
  28.  
  29.     /**
  30.      * The file where the ROM is located.
  31.      */
  32.     private final File file;
  33.  
  34.     /**
  35.      * The input stream used to read the ROM.
  36.      */
  37.     private final InputStream input;
  38.  
  39.     /**
  40.      * The bytes which make up the ROM.
  41.      */
  42.     private final byte[] data;
  43.  
  44.     /**
  45.      * Whether or not the ROM paseed the Nintendo logo checksum.
  46.      */
  47.     private final boolean nintendoLogoChecksum;
  48.  
  49.     /**
  50.      * Title of the game in UPPER CASE ASCII. If it is less than 16 characters
  51.      * then the remaining bytes are filled with 00's. When inventing the CGB,
  52.      * Nintendo has reduced the length of this area to 15 characters, and some
  53.      * months later they had the fantastic idea to reduce it to 11 characters
  54.      * only.
  55.      */
  56.     private final String title;
  57.  
  58.     /**
  59.      * In older cartridges this area has been part of the Title, in newer
  60.      * cartridges this area contains an 4 character uppercase manufacturer code.
  61.      * Purpose and Deeper Meaning unknown.
  62.      */
  63.     private final String manufacturerCode;
  64.  
  65.     /**
  66.      * In older cartridges this byte has been part of the Title. In CGB
  67.      * cartridges the upper bit is used to enable CGB functions. This is
  68.      * required, otherwise the CGB switches itself into Non-CGB-Mode.
  69.      */
  70.     private final boolean cgb;
  71.  
  72.     /**
  73.      * Specifies a two character ASCII licensee code, indicating the company or
  74.      * publisher of the game. These two bytes are used in newer games only
  75.      * (games that have been released after the SGB has been invented). Older
  76.      * games are using the header entry at 014B instead.
  77.      */
  78.     private final String newLicenseeCode;
  79.  
  80.     /**
  81.      * Specifies whether the game supports SGB functions.
  82.      */
  83.     private final boolean sgb;
  84.  
  85.     /**
  86.      * Specifies which Memory Bank Controller (if any) is used in the cartridge,
  87.      * and if further external hardware exists in the cartridge.
  88.      */
  89.     private final byte cartridgeType; // TODO: handle
  90.  
  91.     /**
  92.      * Specifies the ROM Size of the cartridge.
  93.      */
  94.     private final int romSize;
  95.  
  96.     /**
  97.      * Specifies the size of the external RAM in the cartridge (if any). When
  98.      * using a MBC2 chip 00h must be specified in this entry, even though the
  99.      * MBC2 includes a built-in RAM of 512 x 4 bits.
  100.      */
  101.     private final int ramSize;
  102.  
  103.     /**
  104.      * Specifies if this version of the game is supposed to be sold in Japan, or
  105.      * anywhere else.
  106.      */
  107.     private final boolean destinationCode;
  108.  
  109.     /**
  110.      * Specifies the games company/publisher code in range 00-FFh. A value of
  111.      * 33h signalizes that the New License Code in header bytes 0144-0145 is
  112.      * used instead.
  113.      */
  114.     private final int oldLicenseeCode;
  115.  
  116.     /**
  117.      * Specifies the version number of the game. That is usually 00h.
  118.      */
  119.     private final int maskRomVersionNumber;
  120.  
  121.     /**
  122.      * Contains an 8 bit checksum across the cartridge header bytes 0134-014C.
  123.      * The lower 8 bits of the result must be the same than the value in this
  124.      * entry. The GAME WON'T WORK if this checksum is incorrect.
  125.      */
  126.     private final boolean headerChecksum;
  127.  
  128.     /**
  129.      * Constructs a new ROM from the specified directory.
  130.      *
  131.      * @param directory
  132.      *            The directory the ROM is located.
  133.      * @throws IOException
  134.      *             If an exception occurs while constructing the ROM.
  135.      */
  136.     public ROM(final String directory) throws IOException {
  137.         file = new File(directory);
  138.         input = new FileInputStream(file);
  139.         data = new byte[(int) file.length()];
  140.         input.read(data);
  141.  
  142.         nintendoLogoChecksum = (data[0x104] & 0xFF) == NINTENDO_LOGO[0] && (data[0x133] & 0xFF) == NINTENDO_LOGO[47];
  143.         title = new String(data, 0x134, 11, Charset.forName("US-ASCII"));
  144.         manufacturerCode = new String(data, 0x13F, 4);
  145.         cgb = data[0x143] == 0xC0 ? true : false;
  146.         newLicenseeCode = new String(data, 0x144, 2, Charset.forName("US-ASCII"));
  147.         sgb = data[0x164] == 0x3 ? true : false;
  148.         cartridgeType = data[0x147];
  149.  
  150.         final byte romType = data[0x148];
  151.         if (romType == 0x52) {
  152.             romSize = 0x120000;
  153.         } else if (romType == 0x53) {
  154.             romSize = 0x140000;
  155.         } else if (romType == 0x54) {
  156.             romSize = 0x180000;
  157.         } else {
  158.             romSize = 32 * 1024 << romType;
  159.         }
  160.  
  161.         final byte ramType = data[0x149];
  162.         if (ramType == 0x1) {
  163.             ramSize = 0x800;
  164.         } else if (ramType == 0x2) {
  165.             ramSize = 0x2000;
  166.         } else if (ramType == 0x3) {
  167.             ramSize = 0x8000;
  168.         } else {
  169.             ramSize = -1; // XXX: or 0?
  170.         }
  171.  
  172.         destinationCode = data[0x14A] == 0x0 ? true : false;
  173.         oldLicenseeCode = data[0x14B];
  174.         maskRomVersionNumber = data[0x14C];
  175.  
  176.         int x = 0;
  177.         for (int i = 0x134; i < 0x14D; i++) {
  178.             x = x - data[i] - 1;
  179.         }
  180.  
  181.         headerChecksum = (x & 0xFF) == data[0x14D] ? true : false;
  182.  
  183.         // TODO: global checksum
  184.     }
  185.  
  186.     @Override
  187.     public String toString() {
  188.         return "[nintendoLogoChecksum=" + nintendoLogoChecksum + ", title=" + title + ", manufacturerCode=" + manufacturerCode + ", cgb=" + cgb + ", newLicenseeCode=" + newLicenseeCode
  189.                 + ", sgb=" + sgb + ", cartridgeType=" + cartridgeType + ", romSize=" + romSize + ", ramSize=" + ramSize + ", destinationCode=" + destinationCode + ", oldLicenseeCode="
  190.                 + oldLicenseeCode + ", maskRomVersionNumber=" + maskRomVersionNumber + ", headerChecksum=" + headerChecksum + "]";
  191.     }
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement