Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.nintendo.gameboy;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.nio.charset.Charset;
- /**
- * Represents a single Gameboy or Gameboy Color ROM.
- *
- * @author Ryan Greene
- *
- */
- public final class ROM {
- /**
- * These bytes define the bitmap of the Nintendo logo that is displayed when
- * the Gameboy gets turned on. The Gameboy's boot procedure verifies the
- * content of this bitmap (after it has displayed it), and LOCKS ITSELF UP
- * if these bytes are incorrect. A CGB verifies only the first 18h bytes of
- * the bitmap, but others (for example a Pocket Gameboy) verify all 30h
- * bytes. We currently only verify the first and last bytes of the bitmap
- * because I'm lazy.
- */
- 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,
- 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 };
- /**
- * The address where the first Nintendo logo checksum is located.
- */
- private static final int NINTENDO_LOGO_CHECKSUM_FIRST_ADDRESS = 0x104;
- /**
- * The address where the first Nintendo logo checksum is located.
- */
- private static final int NINTENDO_LOGO_CHECKSUM_LAST_ADDRESS = 0x133;
- /**
- * The address where the title is located.
- */
- private static final int TITLE_ADDRESS = 0x134;
- /**
- * The address where the manufacturer code is located.
- */
- private static final int MANUFACTURER_CODE_ADDRESS = 0x13F;
- /**
- * The address where the CGB flag is located.
- */
- private static final int CGB_ADDRESS = 0x143;
- /**
- * The address where the new licensee code is located.
- */
- private static final int NEW_LICENSEE_CODE_ADDRESS = 0x144;
- /**
- * The address where the SGB flag is located.
- */
- private static final int SGB_ADDRESS = 0x164;
- /**
- * The address where the cartridge type is located.
- */
- private static final int CARTRIDGE_TYPE_ADDRESS = 0x147;
- /**
- * The address where the ROM size is located.
- */
- private static final int ROM_SIZE_ADDRESS = 0x148;
- /**
- * The address where the RAM size is located.
- */
- private static final int RAM_SIZE_ADDRESS = 0x149;
- /**
- * The address where the shipping destination is located.
- */
- private static final int DESTINATION_CODE_ADDRESS = 0x14A;
- /**
- * The address where the old licensee code is located.
- */
- private static final int OLD_LICENSEE_CODE_ADDRESS = 0x14B;
- /**
- * The address where the mask ROM version number is located.
- */
- private static final int MASK_ROM_VERSION_NUMBER_ADDRESS = 0x14C;
- /**
- * The address where the header checksum is located.
- */
- private static final int HEADER_CHECKSUM_ADDRESS = 0x14D;
- /**
- * The file where the ROM is located.
- */
- private final File file;
- /**
- * The input stream used to read the ROM.
- */
- private final InputStream input;
- /**
- * The bytes which make up the ROM.
- */
- private final byte[] data;
- /**
- * Whether or not the ROM paseed the Nintendo logo checksum.
- */
- private final boolean nintendoLogoChecksum;
- /**
- * Title of the game in UPPER CASE ASCII. If it is less than 16 characters
- * then the remaining bytes are filled with 00's. When inventing the CGB,
- * Nintendo has reduced the length of this area to 15 characters, and some
- * months later they had the fantastic idea to reduce it to 11 characters
- * only.
- */
- private final String title;
- /**
- * In older cartridges this area has been part of the Title, in newer
- * cartridges this area contains an 4 character uppercase manufacturer code.
- * Purpose and Deeper Meaning unknown.
- */
- private final String manufacturerCode;
- /**
- * In older cartridges this byte has been part of the Title. In CGB
- * cartridges the upper bit is used to enable CGB functions. This is
- * required, otherwise the CGB switches itself into Non-CGB-Mode.
- */
- private final boolean cgb;
- /**
- * Specifies a two character ASCII licensee code, indicating the company or
- * publisher of the game. These two bytes are used in newer games only
- * (games that have been released after the SGB has been invented). Older
- * games are using the header entry at 014B instead.
- */
- private final String newLicenseeCode;
- /**
- * Specifies whether the game supports SGB functions.
- */
- private final boolean sgb;
- /**
- * Specifies which Memory Bank Controller (if any) is used in the cartridge,
- * and if further external hardware exists in the cartridge.
- */
- private final int cartridgeType;
- /**
- * Specifies the ROM Size of the cartridge.
- */
- private final int romSize;
- /**
- * Specifies the size of the external RAM in the cartridge (if any). When
- * using a MBC2 chip 00h must be specified in this entry, even though the
- * MBC2 includes a built-in RAM of 512 x 4 bits.
- */
- private final int ramSize;
- /**
- * Specifies if this version of the game is supposed to be sold in Japan, or
- * anywhere else.
- */
- private final boolean destinationCode;
- /**
- * Specifies the games company/publisher code in range 00-FFh. A value of
- * 33h signalizes that the New License Code in header bytes 0144-0145 is
- * used instead.
- */
- private final int oldLicenseeCode;
- /**
- * Specifies the version number of the game. That is usually 00h.
- */
- private final int maskRomVersionNumber;
- /**
- * Contains an 8 bit checksum across the cartridge header bytes 0134-014C.
- * The lower 8 bits of the result must be the same than the value in this
- * entry. The GAME WON'T WORK if this checksum is incorrect.
- */
- private final boolean headerChecksum;
- /**
- * Constructs a new ROM from the specified directory.
- *
- * @param directory
- * The directory the ROM is located.
- * @throws IOException
- * If an exception occurs while constructing the ROM.
- */
- public ROM(final String directory) throws IOException {
- file = new File(directory);
- input = new FileInputStream(file);
- data = new byte[(int) file.length()];
- input.read(data);
- nintendoLogoChecksum = (data[NINTENDO_LOGO_CHECKSUM_FIRST_ADDRESS] & 0xFF) == NINTENDO_LOGO[0] && (data[NINTENDO_LOGO_CHECKSUM_LAST_ADDRESS] & 0xFF) == NINTENDO_LOGO[47];
- title = new String(data, TITLE_ADDRESS, 11, Charset.forName("US-ASCII"));
- manufacturerCode = new String(data, MANUFACTURER_CODE_ADDRESS, 4);
- cgb = data[CGB_ADDRESS] == 0xC0 ? true : false;
- newLicenseeCode = new String(data, NEW_LICENSEE_CODE_ADDRESS, 2, Charset.forName("US-ASCII"));
- sgb = data[SGB_ADDRESS] == 0x3 ? true : false;
- cartridgeType = data[CARTRIDGE_TYPE_ADDRESS];
- final byte romType = data[ROM_SIZE_ADDRESS];
- if (romType == 0x52) {
- romSize = 0x120000;
- } else if (romType == 0x53) {
- romSize = 0x140000;
- } else if (romType == 0x54) {
- romSize = 0x180000;
- } else {
- romSize = 0x8000 << romType;
- }
- final byte ramType = data[RAM_SIZE_ADDRESS];
- if (ramType == 0x1) {
- ramSize = 0x800;
- } else if (ramType == 0x2) {
- ramSize = 0x2000;
- } else if (ramType == 0x3) {
- ramSize = 0x8000;
- } else {
- ramSize = 0;
- }
- destinationCode = data[DESTINATION_CODE_ADDRESS] == 0x0 ? true : false;
- oldLicenseeCode = data[OLD_LICENSEE_CODE_ADDRESS];
- maskRomVersionNumber = data[MASK_ROM_VERSION_NUMBER_ADDRESS];
- int checksum = 0;
- for (int i = TITLE_ADDRESS; i < HEADER_CHECKSUM_ADDRESS; i++) {
- checksum = checksum - data[i] - 1;
- }
- headerChecksum = (checksum & 0xFF) == data[HEADER_CHECKSUM_ADDRESS] ? true : false;
- }
- @Override
- public String toString() {
- return "[nintendoLogoChecksum=" + nintendoLogoChecksum + ", title=" + title + ", manufacturerCode=" + manufacturerCode + ", cgb=" + cgb + ", newLicenseeCode=" + newLicenseeCode
- + ", sgb=" + sgb + ", cartridgeType=" + cartridgeType + ", romSize=" + romSize + ", ramSize=" + ramSize + ", destinationCode=" + destinationCode + ", oldLicenseeCode="
- + oldLicenseeCode + ", maskRomVersionNumber=" + maskRomVersionNumber + ", headerChecksum=" + headerChecksum + "]";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement