Chiddix

ROM v0.03

Apr 6th, 2014
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.17 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 address where the first Nintendo logo checksum is located.
  31.      */
  32.     private static final int NINTENDO_LOGO_CHECKSUM_FIRST_ADDRESS = 0x104;
  33.  
  34.     /**
  35.      * The address where the first Nintendo logo checksum is located.
  36.      */
  37.     private static final int NINTENDO_LOGO_CHECKSUM_LAST_ADDRESS = 0x133;
  38.  
  39.     /**
  40.      * The address where the title is located.
  41.      */
  42.     private static final int TITLE_ADDRESS = 0x134;
  43.  
  44.     /**
  45.      * The address where the manufacturer code is located.
  46.      */
  47.     private static final int MANUFACTURER_CODE_ADDRESS = 0x13F;
  48.  
  49.     /**
  50.      * The address where the CGB flag is located.
  51.      */
  52.     private static final int CGB_ADDRESS = 0x143;
  53.  
  54.     /**
  55.      * The address where the new licensee code is located.
  56.      */
  57.     private static final int NEW_LICENSEE_CODE_ADDRESS = 0x144;
  58.  
  59.     /**
  60.      * The address where the SGB flag is located.
  61.      */
  62.     private static final int SGB_ADDRESS = 0x164;
  63.  
  64.     /**
  65.      * The address where the cartridge type is located.
  66.      */
  67.     private static final int CARTRIDGE_TYPE_ADDRESS = 0x147;
  68.  
  69.     /**
  70.      * The address where the ROM size is located.
  71.      */
  72.     private static final int ROM_SIZE_ADDRESS = 0x148;
  73.  
  74.     /**
  75.      * The address where the RAM size is located.
  76.      */
  77.     private static final int RAM_SIZE_ADDRESS = 0x149;
  78.  
  79.     /**
  80.      * The address where the shipping destination is located.
  81.      */
  82.     private static final int DESTINATION_CODE_ADDRESS = 0x14A;
  83.  
  84.     /**
  85.      * The address where the old licensee code is located.
  86.      */
  87.     private static final int OLD_LICENSEE_CODE_ADDRESS = 0x14B;
  88.  
  89.     /**
  90.      * The address where the mask ROM version number is located.
  91.      */
  92.     private static final int MASK_ROM_VERSION_NUMBER_ADDRESS = 0x14C;
  93.  
  94.     /**
  95.      * The address where the header checksum is located.
  96.      */
  97.     private static final int HEADER_CHECKSUM_ADDRESS = 0x14D;
  98.  
  99.     /**
  100.      * The file where the ROM is located.
  101.      */
  102.     private final File file;
  103.  
  104.     /**
  105.      * The input stream used to read the ROM.
  106.      */
  107.     private final InputStream input;
  108.  
  109.     /**
  110.      * The bytes which make up the ROM.
  111.      */
  112.     private final byte[] data;
  113.  
  114.     /**
  115.      * Whether or not the ROM paseed the Nintendo logo checksum.
  116.      */
  117.     private final boolean nintendoLogoChecksum;
  118.  
  119.     /**
  120.      * Title of the game in UPPER CASE ASCII. If it is less than 16 characters
  121.      * then the remaining bytes are filled with 00's. When inventing the CGB,
  122.      * Nintendo has reduced the length of this area to 15 characters, and some
  123.      * months later they had the fantastic idea to reduce it to 11 characters
  124.      * only.
  125.      */
  126.     private final String title;
  127.  
  128.     /**
  129.      * In older cartridges this area has been part of the Title, in newer
  130.      * cartridges this area contains an 4 character uppercase manufacturer code.
  131.      * Purpose and Deeper Meaning unknown.
  132.      */
  133.     private final String manufacturerCode;
  134.  
  135.     /**
  136.      * In older cartridges this byte has been part of the Title. In CGB
  137.      * cartridges the upper bit is used to enable CGB functions. This is
  138.      * required, otherwise the CGB switches itself into Non-CGB-Mode.
  139.      */
  140.     private final boolean cgb;
  141.  
  142.     /**
  143.      * Specifies a two character ASCII licensee code, indicating the company or
  144.      * publisher of the game. These two bytes are used in newer games only
  145.      * (games that have been released after the SGB has been invented). Older
  146.      * games are using the header entry at 014B instead.
  147.      */
  148.     private final String newLicenseeCode;
  149.  
  150.     /**
  151.      * Specifies whether the game supports SGB functions.
  152.      */
  153.     private final boolean sgb;
  154.  
  155.     /**
  156.      * Specifies which Memory Bank Controller (if any) is used in the cartridge,
  157.      * and if further external hardware exists in the cartridge.
  158.      */
  159.     private final int cartridgeType;
  160.  
  161.     /**
  162.      * Specifies the ROM Size of the cartridge.
  163.      */
  164.     private final int romSize;
  165.  
  166.     /**
  167.      * Specifies the size of the external RAM in the cartridge (if any). When
  168.      * using a MBC2 chip 00h must be specified in this entry, even though the
  169.      * MBC2 includes a built-in RAM of 512 x 4 bits.
  170.      */
  171.     private final int ramSize;
  172.  
  173.     /**
  174.      * Specifies if this version of the game is supposed to be sold in Japan, or
  175.      * anywhere else.
  176.      */
  177.     private final boolean destinationCode;
  178.  
  179.     /**
  180.      * Specifies the games company/publisher code in range 00-FFh. A value of
  181.      * 33h signalizes that the New License Code in header bytes 0144-0145 is
  182.      * used instead.
  183.      */
  184.     private final int oldLicenseeCode;
  185.  
  186.     /**
  187.      * Specifies the version number of the game. That is usually 00h.
  188.      */
  189.     private final int maskRomVersionNumber;
  190.  
  191.     /**
  192.      * Contains an 8 bit checksum across the cartridge header bytes 0134-014C.
  193.      * The lower 8 bits of the result must be the same than the value in this
  194.      * entry. The GAME WON'T WORK if this checksum is incorrect.
  195.      */
  196.     private final boolean headerChecksum;
  197.  
  198.     /**
  199.      * Constructs a new ROM from the specified directory.
  200.      *
  201.      * @param directory
  202.      *            The directory the ROM is located.
  203.      * @throws IOException
  204.      *             If an exception occurs while constructing the ROM.
  205.      */
  206.     public ROM(final String directory) throws IOException {
  207.         file = new File(directory);
  208.         input = new FileInputStream(file);
  209.         data = new byte[(int) file.length()];
  210.         input.read(data);
  211.  
  212.         nintendoLogoChecksum = (data[NINTENDO_LOGO_CHECKSUM_FIRST_ADDRESS] & 0xFF) == NINTENDO_LOGO[0] && (data[NINTENDO_LOGO_CHECKSUM_LAST_ADDRESS] & 0xFF) == NINTENDO_LOGO[47];
  213.         title = new String(data, TITLE_ADDRESS, 11, Charset.forName("US-ASCII"));
  214.         manufacturerCode = new String(data, MANUFACTURER_CODE_ADDRESS, 4);
  215.         cgb = data[CGB_ADDRESS] == 0xC0 ? true : false;
  216.         newLicenseeCode = new String(data, NEW_LICENSEE_CODE_ADDRESS, 2, Charset.forName("US-ASCII"));
  217.         sgb = data[SGB_ADDRESS] == 0x3 ? true : false;
  218.         cartridgeType = data[CARTRIDGE_TYPE_ADDRESS];
  219.  
  220.         final byte romType = data[ROM_SIZE_ADDRESS];
  221.         if (romType == 0x52) {
  222.             romSize = 0x120000;
  223.         } else if (romType == 0x53) {
  224.             romSize = 0x140000;
  225.         } else if (romType == 0x54) {
  226.             romSize = 0x180000;
  227.         } else {
  228.             romSize = 0x8000 << romType;
  229.         }
  230.  
  231.         final byte ramType = data[RAM_SIZE_ADDRESS];
  232.         if (ramType == 0x1) {
  233.             ramSize = 0x800;
  234.         } else if (ramType == 0x2) {
  235.             ramSize = 0x2000;
  236.         } else if (ramType == 0x3) {
  237.             ramSize = 0x8000;
  238.         } else {
  239.             ramSize = 0;
  240.         }
  241.  
  242.         destinationCode = data[DESTINATION_CODE_ADDRESS] == 0x0 ? true : false;
  243.         oldLicenseeCode = data[OLD_LICENSEE_CODE_ADDRESS];
  244.         maskRomVersionNumber = data[MASK_ROM_VERSION_NUMBER_ADDRESS];
  245.  
  246.         int checksum = 0;
  247.         for (int i = TITLE_ADDRESS; i < HEADER_CHECKSUM_ADDRESS; i++) {
  248.             checksum = checksum - data[i] - 1;
  249.         }
  250.  
  251.         headerChecksum = (checksum & 0xFF) == data[HEADER_CHECKSUM_ADDRESS] ? true : false;
  252.     }
  253.  
  254.     @Override
  255.     public String toString() {
  256.         return "[nintendoLogoChecksum=" + nintendoLogoChecksum + ", title=" + title + ", manufacturerCode=" + manufacturerCode + ", cgb=" + cgb + ", newLicenseeCode=" + newLicenseeCode
  257.                 + ", sgb=" + sgb + ", cartridgeType=" + cartridgeType + ", romSize=" + romSize + ", ramSize=" + ramSize + ", destinationCode=" + destinationCode + ", oldLicenseeCode="
  258.                 + oldLicenseeCode + ", maskRomVersionNumber=" + maskRomVersionNumber + ", headerChecksum=" + headerChecksum + "]";
  259.     }
  260. }
Add Comment
Please, Sign In to add comment