gameboy wormboy manboy gameworm gameman wormgame mangame manworm

Dependencies:   mbed SDFileSystem2

Committer:
dicarloj
Date:
Sun Jan 13 19:00:10 2019 +0000
Revision:
17:c9afe1a7b423
a

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dicarloj 17:c9afe1a7b423 1 #define NDEBUG
dicarloj 17:c9afe1a7b423 2 #include <assert.h>
dicarloj 17:c9afe1a7b423 3 #include <stdlib.h>
dicarloj 17:c9afe1a7b423 4 #include <mbed.h>
dicarloj 17:c9afe1a7b423 5
dicarloj 17:c9afe1a7b423 6 #include "mem.h"
dicarloj 17:c9afe1a7b423 7 #include "platform.h"
dicarloj 17:c9afe1a7b423 8
dicarloj 17:c9afe1a7b423 9 #define DANGER_MODE
dicarloj 17:c9afe1a7b423 10
dicarloj 17:c9afe1a7b423 11 MemState globalMemState;
dicarloj 17:c9afe1a7b423 12
dicarloj 17:c9afe1a7b423 13 void CartInfo::print() {
dicarloj 17:c9afe1a7b423 14 printf("Gameboy Cartridge\n"
dicarloj 17:c9afe1a7b423 15 "\ttitle: %s\n"
dicarloj 17:c9afe1a7b423 16 "\tisColor: 0x%x\n"
dicarloj 17:c9afe1a7b423 17 "\tSGB: 0x%x\n"
dicarloj 17:c9afe1a7b423 18 "\tcartType: 0x%x\n"
dicarloj 17:c9afe1a7b423 19 "\tromSize: 0x%x\n"
dicarloj 17:c9afe1a7b423 20 "\tramSize: 0x%x\n"
dicarloj 17:c9afe1a7b423 21 "\tnotJapan: 0x%x\n",
dicarloj 17:c9afe1a7b423 22 title, isColor, SGB, (u8)cartType, (u8)romSize, (u8)ramSize, notJapan);
dicarloj 17:c9afe1a7b423 23 }
dicarloj 17:c9afe1a7b423 24
dicarloj 17:c9afe1a7b423 25 // number of banks for given cartridge types
dicarloj 17:c9afe1a7b423 26 static const u8 romSizeIDToNBanks[7] = {2,4,8,16,32,64,128};
dicarloj 17:c9afe1a7b423 27 static const u8 ramSizeIDToNBanks[5] = {0,1,1,4,4};
dicarloj 17:c9afe1a7b423 28 static u8* fileData = nullptr;
dicarloj 17:c9afe1a7b423 29
dicarloj 17:c9afe1a7b423 30 void saveGame() {
dicarloj 17:c9afe1a7b423 31 FileLoadData fld;
dicarloj 17:c9afe1a7b423 32 fld.size = 0x2000 * globalMemState.nRamBanks;
dicarloj 17:c9afe1a7b423 33 fld.data = globalMemState.mappedRamAllocation;
dicarloj 17:c9afe1a7b423 34 saveFile("savegame.gam", fld);
dicarloj 17:c9afe1a7b423 35 }
dicarloj 17:c9afe1a7b423 36
dicarloj 17:c9afe1a7b423 37 void loadGame() {
dicarloj 17:c9afe1a7b423 38 FileLoadData fld = loadFile("savegame.gam");
dicarloj 17:c9afe1a7b423 39 memcpy(globalMemState.mappedRamAllocation, fld.data, 0x2000 * globalMemState.nRamBanks);
dicarloj 17:c9afe1a7b423 40 }
dicarloj 17:c9afe1a7b423 41
dicarloj 17:c9afe1a7b423 42
dicarloj 17:c9afe1a7b423 43
dicarloj 17:c9afe1a7b423 44
dicarloj 17:c9afe1a7b423 45 void initMem(FileLoadData file) {
dicarloj 17:c9afe1a7b423 46 CartInfo* cartInfo = (CartInfo*)(file.data + CART_INFO_ADDR);
dicarloj 17:c9afe1a7b423 47 cartInfo->print();
dicarloj 17:c9afe1a7b423 48 fileData = file.data;
dicarloj 17:c9afe1a7b423 49 printf("ROM size: 0x%x bytes\n", file.size);
dicarloj 17:c9afe1a7b423 50
dicarloj 17:c9afe1a7b423 51
dicarloj 17:c9afe1a7b423 52 globalMemState.inBios = true; // start in BIOS mode
dicarloj 17:c9afe1a7b423 53 globalMemState.rom0 = file.data; // ROM-bank 0 is the bottom of the cartridge
dicarloj 17:c9afe1a7b423 54
dicarloj 17:c9afe1a7b423 55 // initialize everything to zero
dicarloj 17:c9afe1a7b423 56 globalMemState.mappedRom = nullptr;
dicarloj 17:c9afe1a7b423 57 globalMemState.nRamBanks = 0;
dicarloj 17:c9afe1a7b423 58 globalMemState.nRomBanks = 0;
dicarloj 17:c9afe1a7b423 59 globalMemState.vram = nullptr;
dicarloj 17:c9afe1a7b423 60 globalMemState.mappedRam = nullptr;
dicarloj 17:c9afe1a7b423 61 globalMemState.disabledMappedRam = nullptr;
dicarloj 17:c9afe1a7b423 62 globalMemState.mappedRamAllocation = nullptr;
dicarloj 17:c9afe1a7b423 63 globalMemState.internalRam = nullptr;
dicarloj 17:c9afe1a7b423 64 globalMemState.upperRam = nullptr;
dicarloj 17:c9afe1a7b423 65
dicarloj 17:c9afe1a7b423 66 switch(cartInfo->cartType) {
dicarloj 17:c9afe1a7b423 67 case ROM_ONLY:
dicarloj 17:c9afe1a7b423 68 globalMemState.mappedRom = file.data + 0x4000; // maps in upper ROM by default
dicarloj 17:c9afe1a7b423 69 break;
dicarloj 17:c9afe1a7b423 70
dicarloj 17:c9afe1a7b423 71 case ROM_MBC1:
dicarloj 17:c9afe1a7b423 72 globalMemState.mappedRom = file.data + 0x4000; // maps in upper ROM by default
dicarloj 17:c9afe1a7b423 73 globalMemState.mbcType = 1;
dicarloj 17:c9afe1a7b423 74 if((u8)cartInfo->romSize < 7) {
dicarloj 17:c9afe1a7b423 75 globalMemState.nRomBanks = romSizeIDToNBanks[(u8)cartInfo->romSize]; // has ROM banks
dicarloj 17:c9afe1a7b423 76 } else {
dicarloj 17:c9afe1a7b423 77 printf("unknown number of rom banks\n");
dicarloj 17:c9afe1a7b423 78 assert(false);
dicarloj 17:c9afe1a7b423 79 }
dicarloj 17:c9afe1a7b423 80 break;
dicarloj 17:c9afe1a7b423 81
dicarloj 17:c9afe1a7b423 82 case ROM_MBC1_RAM:
dicarloj 17:c9afe1a7b423 83 globalMemState.mappedRom = file.data + 0x4000; // maps in upper ROM by default
dicarloj 17:c9afe1a7b423 84 globalMemState.mbcType = 1;
dicarloj 17:c9afe1a7b423 85 if((u8)cartInfo->romSize < 7) {
dicarloj 17:c9afe1a7b423 86 globalMemState.nRomBanks = romSizeIDToNBanks[(u8)cartInfo->romSize]; // has ROM banks
dicarloj 17:c9afe1a7b423 87 } else {
dicarloj 17:c9afe1a7b423 88 printf("unknown number of rom banks\n");
dicarloj 17:c9afe1a7b423 89 assert(false);
dicarloj 17:c9afe1a7b423 90 }
dicarloj 17:c9afe1a7b423 91
dicarloj 17:c9afe1a7b423 92 if((u8)cartInfo->ramSize < 5) {
dicarloj 17:c9afe1a7b423 93 globalMemState.nRamBanks = ramSizeIDToNBanks[(u8)cartInfo->ramSize]; // has RAM banks
dicarloj 17:c9afe1a7b423 94 } else {
dicarloj 17:c9afe1a7b423 95 printf("unknown number of ram banks\n");
dicarloj 17:c9afe1a7b423 96 assert(false);
dicarloj 17:c9afe1a7b423 97 }
dicarloj 17:c9afe1a7b423 98 break;
dicarloj 17:c9afe1a7b423 99
dicarloj 17:c9afe1a7b423 100 case ROM_MBC3_RAM_BATT:
dicarloj 17:c9afe1a7b423 101 case ROM_MBC3_TIMER_RAM_BATT:
dicarloj 17:c9afe1a7b423 102 globalMemState.mappedRom = file.data + 0x4000; // maps in upper ROM by default
dicarloj 17:c9afe1a7b423 103 globalMemState.mbcType = 3;
dicarloj 17:c9afe1a7b423 104 if((u8)cartInfo->romSize < 7) {
dicarloj 17:c9afe1a7b423 105 globalMemState.nRomBanks = romSizeIDToNBanks[(u8)cartInfo->romSize]; // has ROM banks
dicarloj 17:c9afe1a7b423 106 } else {
dicarloj 17:c9afe1a7b423 107 printf("unknown number of rom banks\n");
dicarloj 17:c9afe1a7b423 108 assert(false);
dicarloj 17:c9afe1a7b423 109 }
dicarloj 17:c9afe1a7b423 110
dicarloj 17:c9afe1a7b423 111 if((u8)cartInfo->ramSize < 5) {
dicarloj 17:c9afe1a7b423 112 globalMemState.nRamBanks = ramSizeIDToNBanks[(u8)cartInfo->ramSize]; // has RAM banks
dicarloj 17:c9afe1a7b423 113 } else {
dicarloj 17:c9afe1a7b423 114 printf("unknown number of ram banks\n");
dicarloj 17:c9afe1a7b423 115 }
dicarloj 17:c9afe1a7b423 116 break;
dicarloj 17:c9afe1a7b423 117 default:
dicarloj 17:c9afe1a7b423 118 printf("unknown cart type 0x%x\n", (u8)cartInfo->cartType);
dicarloj 17:c9afe1a7b423 119 assert(false);
dicarloj 17:c9afe1a7b423 120 break;
dicarloj 17:c9afe1a7b423 121 }
dicarloj 17:c9afe1a7b423 122
dicarloj 17:c9afe1a7b423 123 printf("mbc%d\n", globalMemState.mbcType);
dicarloj 17:c9afe1a7b423 124 printf("rom-banks: %d\n", globalMemState.nRomBanks);
dicarloj 17:c9afe1a7b423 125 printf("ram-banks: %d\n", globalMemState.nRamBanks);
dicarloj 17:c9afe1a7b423 126
dicarloj 17:c9afe1a7b423 127 // allocate cartridge RAM (8 KB * # of banks)
dicarloj 17:c9afe1a7b423 128 if(globalMemState.nRamBanks) {
dicarloj 17:c9afe1a7b423 129 globalMemState.mappedRamAllocation = (u8*)malloc(0x2000 * globalMemState.nRamBanks);
dicarloj 17:c9afe1a7b423 130 memset((void*)globalMemState.mappedRamAllocation, 0, 0x2000 * globalMemState.nRamBanks);
dicarloj 17:c9afe1a7b423 131 globalMemState.disabledMappedRam = globalMemState.mappedRamAllocation;
dicarloj 17:c9afe1a7b423 132 } else {
dicarloj 17:c9afe1a7b423 133
dicarloj 17:c9afe1a7b423 134 }
dicarloj 17:c9afe1a7b423 135
dicarloj 17:c9afe1a7b423 136 // allocate memories:
dicarloj 17:c9afe1a7b423 137 // internal RAM
dicarloj 17:c9afe1a7b423 138 globalMemState.internalRam = (u8*)badalloc_check(0x2000, "internal_ram");
dicarloj 17:c9afe1a7b423 139 globalMemState.vram = (u8*)badalloc_check(0x2000, "vram");
dicarloj 17:c9afe1a7b423 140 globalMemState.upperRam = (u8*)badalloc_check(0x80, "upper-regs");
dicarloj 17:c9afe1a7b423 141 globalMemState.ioRegs = (u8*)badalloc_check(0x80, "io-regs");
dicarloj 17:c9afe1a7b423 142
dicarloj 17:c9afe1a7b423 143 printf("[initRam] ioRegs: 0x%x\n", globalMemState.ioRegs);
dicarloj 17:c9afe1a7b423 144
dicarloj 17:c9afe1a7b423 145 // clear RAMs
dicarloj 17:c9afe1a7b423 146 memset(globalMemState.internalRam, 0, 0x2000);
dicarloj 17:c9afe1a7b423 147 memset(globalMemState.vram, 0, 0x2000);
dicarloj 17:c9afe1a7b423 148 memset(globalMemState.upperRam, 0, 0x80);
dicarloj 17:c9afe1a7b423 149 memset(globalMemState.ioRegs, 0, 0x80);
dicarloj 17:c9afe1a7b423 150
dicarloj 17:c9afe1a7b423 151 // setup i/o regs and friends
dicarloj 17:c9afe1a7b423 152 u8* io = globalMemState.ioRegs;
dicarloj 17:c9afe1a7b423 153 io[IO_TIMA] = 0; // reset TIMER COUNT to 0
dicarloj 17:c9afe1a7b423 154 io[IO_TMA] = 0; // TIMER RELOAD
dicarloj 17:c9afe1a7b423 155 io[IO_TAC] = 0; // TIMER STOP
dicarloj 17:c9afe1a7b423 156 io[IO_NR10] = 0x80;
dicarloj 17:c9afe1a7b423 157 io[IO_NR11] = 0xbf;
dicarloj 17:c9afe1a7b423 158 io[IO_NR12] = 0xf3;
dicarloj 17:c9afe1a7b423 159 io[IO_NR14] = 0xbf;
dicarloj 17:c9afe1a7b423 160 io[IO_NR21] = 0x3f;
dicarloj 17:c9afe1a7b423 161 io[IO_NR22] = 0x00;
dicarloj 17:c9afe1a7b423 162 io[IO_NR24] = 0xbf;
dicarloj 17:c9afe1a7b423 163 io[IO_NR30] = 0x7f;
dicarloj 17:c9afe1a7b423 164 io[IO_NR31] = 0xff;
dicarloj 17:c9afe1a7b423 165 io[IO_NR32] = 0x9f;
dicarloj 17:c9afe1a7b423 166 io[IO_NR34] = 0xbf;
dicarloj 17:c9afe1a7b423 167 io[IO_NR41] = 0xff;
dicarloj 17:c9afe1a7b423 168 io[IO_NR42] = 0x00;
dicarloj 17:c9afe1a7b423 169 io[IO_NR43] = 0x00;
dicarloj 17:c9afe1a7b423 170 io[IO_NR44] = 0xbf;
dicarloj 17:c9afe1a7b423 171 io[IO_NR50] = 0x77;
dicarloj 17:c9afe1a7b423 172 io[IO_NR51] = 0xf3;
dicarloj 17:c9afe1a7b423 173 io[IO_NR52] = 0xf1;
dicarloj 17:c9afe1a7b423 174 io[IO_LCDC] = 0x91;
dicarloj 17:c9afe1a7b423 175 io[IO_SCROLLY] = 0x00;
dicarloj 17:c9afe1a7b423 176 io[IO_SCROLLX] = 0x00;
dicarloj 17:c9afe1a7b423 177 io[IO_LYC] = 0x00;
dicarloj 17:c9afe1a7b423 178 io[IO_BGP] = 0xfc;
dicarloj 17:c9afe1a7b423 179 io[IO_OBP0] = 0xff;
dicarloj 17:c9afe1a7b423 180 io[IO_OBP1] = 0xff;
dicarloj 17:c9afe1a7b423 181 io[IO_WINY] = 0x00;
dicarloj 17:c9afe1a7b423 182 io[IO_WINX] = 0x00;
dicarloj 17:c9afe1a7b423 183
dicarloj 17:c9afe1a7b423 184 // turn off interrupts
dicarloj 17:c9afe1a7b423 185 globalMemState.upperRam[0x7f] = 0;
dicarloj 17:c9afe1a7b423 186 }
dicarloj 17:c9afe1a7b423 187
dicarloj 17:c9afe1a7b423 188
dicarloj 17:c9afe1a7b423 189 // boot ROM
dicarloj 17:c9afe1a7b423 190 static const u8 bios[256] = {0x31, 0xFE, 0xFF, // LD, SP, $fffe 0
dicarloj 17:c9afe1a7b423 191 0xAF, // XOR A 3
dicarloj 17:c9afe1a7b423 192 0x21, 0xFF, 0x9F, // LD HL, $9fff 4
dicarloj 17:c9afe1a7b423 193 0x32, // LD (HL--), A 7
dicarloj 17:c9afe1a7b423 194 0xCB, 0x7C, // BIT 7, H 8
dicarloj 17:c9afe1a7b423 195 0x20, 0xFB, // JR NZ 7 a
dicarloj 17:c9afe1a7b423 196 0x21, 0x26, 0xFF, // LD HL, $ff26 c
dicarloj 17:c9afe1a7b423 197 0x0E, 0x11, // LD c,$11 f
dicarloj 17:c9afe1a7b423 198 0x3E, 0x80, // LD a,$80 11
dicarloj 17:c9afe1a7b423 199 0x32, // LD (HL--), A 13
dicarloj 17:c9afe1a7b423 200 0xE2, // LD($FF00+C),A 14
dicarloj 17:c9afe1a7b423 201 0x0C, // INC C 15
dicarloj 17:c9afe1a7b423 202 0x3E, 0xF3, // LD A, $f3 16
dicarloj 17:c9afe1a7b423 203 0xE2, // LD (HL--), A 18
dicarloj 17:c9afe1a7b423 204 0x32, // LD($FF00+C),A 19
dicarloj 17:c9afe1a7b423 205 0x3E, 0x77, // LD A,$77 1a
dicarloj 17:c9afe1a7b423 206 0x77, 0x3E, 0xFC, 0xE0,
dicarloj 17:c9afe1a7b423 207 0x47, 0x11, 0x04, 0x01, 0x21, 0x10, 0x80, 0x1A, 0xCD, 0x95, 0x00, 0xCD, 0x96, 0x00, 0x13, 0x7B,
dicarloj 17:c9afe1a7b423 208 0xFE, 0x34, 0x20, 0xF3, 0x11, 0xD8, 0x00, 0x06, 0x08, 0x1A, 0x13, 0x22, 0x23, 0x05, 0x20, 0xF9,
dicarloj 17:c9afe1a7b423 209 0x3E, 0x19, 0xEA, 0x10, 0x99, 0x21, 0x2F, 0x99, 0x0E, 0x0C, 0x3D, 0x28, 0x08, 0x32, 0x0D, 0x20,
dicarloj 17:c9afe1a7b423 210 0xF9, 0x2E, 0x0F, 0x18, 0xF3, 0x67, 0x3E, 0x64, 0x57, 0xE0, 0x42, 0x3E, 0x91, 0xE0, 0x40, 0x04,
dicarloj 17:c9afe1a7b423 211 0x1E, 0x02, 0x0E, 0x0C, 0xF0, 0x44, 0xFE, 0x90, 0x20, 0xFA, 0x0D, 0x20, 0xF7, 0x1D, 0x20, 0xF2,
dicarloj 17:c9afe1a7b423 212 0x0E, 0x13, 0x24, 0x7C, 0x1E, 0x83, 0xFE, 0x62, 0x28, 0x06, 0x1E, 0xC1, 0xFE, 0x64, 0x20, 0x06,
dicarloj 17:c9afe1a7b423 213 0x7B, 0xE2, 0x0C, 0x3E, 0x87, 0xF2, 0xF0, 0x42, 0x90, 0xE0, 0x42, 0x15, 0x20, 0xD2, 0x05, 0x20,
dicarloj 17:c9afe1a7b423 214 0x4F, 0x16, 0x20, 0x18, 0xCB, 0x4F, 0x06, 0x04, 0xC5, 0xCB, 0x11, 0x17, 0xC1, 0xCB, 0x11, 0x17,
dicarloj 17:c9afe1a7b423 215 0x05, 0x20, 0xF5, 0x22, 0x23, 0x22, 0x23, 0xC9, 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,
dicarloj 17:c9afe1a7b423 216 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E,
dicarloj 17:c9afe1a7b423 217 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC,
dicarloj 17:c9afe1a7b423 218 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E, 0x3c, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x4C,
dicarloj 17:c9afe1a7b423 219 0x21, 0x04, 0x01, 0x11, 0xA8, 0x00, 0x1A, 0x13, 0xBE, 0x20, 0xFE, 0x23, 0x7D, 0xFE, 0x34, 0x20,
dicarloj 17:c9afe1a7b423 220 0xF5, 0x06, 0x19, 0x78, 0x86, 0x23, 0x05, 0x20, 0xFB, 0x86, 0x20, 0xFE, 0x3E, 0x01, 0xE0, 0x50};
dicarloj 17:c9afe1a7b423 221
dicarloj 17:c9afe1a7b423 222 // handler for MBC0 switch
dicarloj 17:c9afe1a7b423 223 void mbc0Handler(u16 addr, u8 value) {
dicarloj 17:c9afe1a7b423 224
dicarloj 17:c9afe1a7b423 225 // it looks like tetris tries to select ROM 1 for banked ROM, so we need to allow this:
dicarloj 17:c9afe1a7b423 226 if(addr >= 0x2000 && addr < 0x3fff) {
dicarloj 17:c9afe1a7b423 227 if(value == 0 || value == 1) {
dicarloj 17:c9afe1a7b423 228 // nothing to do!
dicarloj 17:c9afe1a7b423 229 } else {
dicarloj 17:c9afe1a7b423 230 assert(false);
dicarloj 17:c9afe1a7b423 231 }
dicarloj 17:c9afe1a7b423 232 } else {
dicarloj 17:c9afe1a7b423 233 assert(false);
dicarloj 17:c9afe1a7b423 234 }
dicarloj 17:c9afe1a7b423 235
dicarloj 17:c9afe1a7b423 236 }
dicarloj 17:c9afe1a7b423 237
dicarloj 17:c9afe1a7b423 238 // handler for MBC1 switch (doesn't handle everything yet...)
dicarloj 17:c9afe1a7b423 239 void mbc1Handler(u16 addr, u8 value) {
dicarloj 17:c9afe1a7b423 240 if(addr >= 0x2000 && addr < 0x3fff) {
dicarloj 17:c9afe1a7b423 241 // ROM bank switch
dicarloj 17:c9afe1a7b423 242 if(value >= globalMemState.nRomBanks) {
dicarloj 17:c9afe1a7b423 243 printf("\trequested rom bank %d when there are only %d banks!\n", value, globalMemState.nRomBanks);
dicarloj 17:c9afe1a7b423 244 assert(false);
dicarloj 17:c9afe1a7b423 245 }
dicarloj 17:c9afe1a7b423 246
dicarloj 17:c9afe1a7b423 247 if(value == 0) value = 1;
dicarloj 17:c9afe1a7b423 248 if(value == 0x21) value = 0x20;
dicarloj 17:c9afe1a7b423 249 if(value == 0x41) value = 0x40;
dicarloj 17:c9afe1a7b423 250 globalMemState.mappedRom = fileData + 0x4000 * value;
dicarloj 17:c9afe1a7b423 251 } else if(addr >= 0 && addr < 0x1fff) {
dicarloj 17:c9afe1a7b423 252 // enable RAM
dicarloj 17:c9afe1a7b423 253 if(value == 0) {
dicarloj 17:c9afe1a7b423 254 globalMemState.disabledMappedRam = globalMemState.mappedRam;
dicarloj 17:c9afe1a7b423 255 globalMemState.mappedRam = nullptr;
dicarloj 17:c9afe1a7b423 256 } else if(value == 0xa) {
dicarloj 17:c9afe1a7b423 257 globalMemState.mappedRam = globalMemState.disabledMappedRam;
dicarloj 17:c9afe1a7b423 258 } else {
dicarloj 17:c9afe1a7b423 259 assert(false);
dicarloj 17:c9afe1a7b423 260 }
dicarloj 17:c9afe1a7b423 261 } else {
dicarloj 17:c9afe1a7b423 262 assert(false);
dicarloj 17:c9afe1a7b423 263 }
dicarloj 17:c9afe1a7b423 264
dicarloj 17:c9afe1a7b423 265 }
dicarloj 17:c9afe1a7b423 266
dicarloj 17:c9afe1a7b423 267 // handler for MBC2 switch (doesn't handle anything yet...)
dicarloj 17:c9afe1a7b423 268 void mbc2Handler(u16 addr, u8 value) {
dicarloj 17:c9afe1a7b423 269 assert(false);
dicarloj 17:c9afe1a7b423 270 }
dicarloj 17:c9afe1a7b423 271
dicarloj 17:c9afe1a7b423 272 // handler for MBC3 switch (doesn't handle anything yet...)
dicarloj 17:c9afe1a7b423 273 void mbc3Handler(u16 addr, u8 value) {
dicarloj 17:c9afe1a7b423 274
dicarloj 17:c9afe1a7b423 275 if(addr >= 0x2000 && addr < 0x3fff) {
dicarloj 17:c9afe1a7b423 276 // ROM bank switch
dicarloj 17:c9afe1a7b423 277 if(value >= globalMemState.nRomBanks) {
dicarloj 17:c9afe1a7b423 278 printf("\trequested rom bank %d when there are only %d banks!\n", value, globalMemState.nRomBanks);
dicarloj 17:c9afe1a7b423 279 assert(false);
dicarloj 17:c9afe1a7b423 280 }
dicarloj 17:c9afe1a7b423 281
dicarloj 17:c9afe1a7b423 282 if(value == 0) value = 1;
dicarloj 17:c9afe1a7b423 283 globalMemState.mappedRom = fileData + 0x4000 * value;
dicarloj 17:c9afe1a7b423 284 } else if(addr >= 0 && addr < 0x1fff) {
dicarloj 17:c9afe1a7b423 285 // RAM enable/disable
dicarloj 17:c9afe1a7b423 286 if(value == 0) {
dicarloj 17:c9afe1a7b423 287 globalMemState.disabledMappedRam = globalMemState.mappedRam;
dicarloj 17:c9afe1a7b423 288 globalMemState.mappedRam = nullptr;
dicarloj 17:c9afe1a7b423 289 } else if(value == 0xa) {
dicarloj 17:c9afe1a7b423 290 globalMemState.mappedRam = globalMemState.disabledMappedRam;
dicarloj 17:c9afe1a7b423 291 } else {
dicarloj 17:c9afe1a7b423 292 //assert(false);
dicarloj 17:c9afe1a7b423 293 }
dicarloj 17:c9afe1a7b423 294 } else if(addr >= 0x4000 && addr < 0x5fff) {
dicarloj 17:c9afe1a7b423 295 // RAM bank switch
dicarloj 17:c9afe1a7b423 296 if(value < globalMemState.nRamBanks) {
dicarloj 17:c9afe1a7b423 297 globalMemState.mappedRam = globalMemState.mappedRamAllocation + 0x2000 * value;
dicarloj 17:c9afe1a7b423 298 } else {
dicarloj 17:c9afe1a7b423 299 //assert(false);
dicarloj 17:c9afe1a7b423 300 }
dicarloj 17:c9afe1a7b423 301 } else if(addr == 0x6000) {
dicarloj 17:c9afe1a7b423 302 // ?? RTC latch nonsense
dicarloj 17:c9afe1a7b423 303 } else {
dicarloj 17:c9afe1a7b423 304 assert(false);
dicarloj 17:c9afe1a7b423 305 }
dicarloj 17:c9afe1a7b423 306 }
dicarloj 17:c9afe1a7b423 307
dicarloj 17:c9afe1a7b423 308 // handler for all MBC switches
dicarloj 17:c9afe1a7b423 309 void mbcHandler(u16 addr, u8 value) {
dicarloj 17:c9afe1a7b423 310 switch(globalMemState.mbcType) {
dicarloj 17:c9afe1a7b423 311 case 0:
dicarloj 17:c9afe1a7b423 312 mbc0Handler(addr, value);
dicarloj 17:c9afe1a7b423 313 break;
dicarloj 17:c9afe1a7b423 314 case 1:
dicarloj 17:c9afe1a7b423 315 mbc1Handler(addr, value);
dicarloj 17:c9afe1a7b423 316 break;
dicarloj 17:c9afe1a7b423 317 case 2:
dicarloj 17:c9afe1a7b423 318 mbc2Handler(addr, value);
dicarloj 17:c9afe1a7b423 319 break;
dicarloj 17:c9afe1a7b423 320 case 3:
dicarloj 17:c9afe1a7b423 321 mbc3Handler(addr, value);
dicarloj 17:c9afe1a7b423 322 break;
dicarloj 17:c9afe1a7b423 323 default:
dicarloj 17:c9afe1a7b423 324 assert(false);
dicarloj 17:c9afe1a7b423 325 break;
dicarloj 17:c9afe1a7b423 326 }
dicarloj 17:c9afe1a7b423 327 }
dicarloj 17:c9afe1a7b423 328
dicarloj 17:c9afe1a7b423 329 // read a u16 from game memory
dicarloj 17:c9afe1a7b423 330 u16 readU16(u16 addr) {
dicarloj 17:c9afe1a7b423 331 return (u16)readByte(addr) + ((u16)(readByte(addr+(u16)1)) << 8);
dicarloj 17:c9afe1a7b423 332 }
dicarloj 17:c9afe1a7b423 333
dicarloj 17:c9afe1a7b423 334 // write a u16 to game memory
dicarloj 17:c9afe1a7b423 335 void writeU16(u16 mem, u16 addr) {
dicarloj 17:c9afe1a7b423 336 writeByte((u8)(mem & 0xff), addr);
dicarloj 17:c9afe1a7b423 337 writeByte((u8)(mem >> 8), addr + (u16)1);
dicarloj 17:c9afe1a7b423 338 }
dicarloj 17:c9afe1a7b423 339
dicarloj 17:c9afe1a7b423 340 // read byte from memory
dicarloj 17:c9afe1a7b423 341 u8 readByte(u16 addr) {
dicarloj 17:c9afe1a7b423 342 switch(addr & 0xf000) {
dicarloj 17:c9afe1a7b423 343 case 0x0000: // either BIOS or ROM 0:
dicarloj 17:c9afe1a7b423 344 if(globalMemState.inBios) {
dicarloj 17:c9afe1a7b423 345 if(addr < 0x100) {
dicarloj 17:c9afe1a7b423 346 return bios[addr];
dicarloj 17:c9afe1a7b423 347 } else if(addr == 0x100) {
dicarloj 17:c9afe1a7b423 348 printf("EXIT BIOS ERROR\n");
dicarloj 17:c9afe1a7b423 349 assert(false);
dicarloj 17:c9afe1a7b423 350 } else {
dicarloj 17:c9afe1a7b423 351 return globalMemState.rom0[addr]; // todo <- change this for stm32
dicarloj 17:c9afe1a7b423 352 }
dicarloj 17:c9afe1a7b423 353 } else {
dicarloj 17:c9afe1a7b423 354 return globalMemState.rom0[addr]; // todo <- change this for stm32
dicarloj 17:c9afe1a7b423 355 }
dicarloj 17:c9afe1a7b423 356
dicarloj 17:c9afe1a7b423 357 case 0x1000: // ROM 0
dicarloj 17:c9afe1a7b423 358 case 0x2000: // ROM 0
dicarloj 17:c9afe1a7b423 359 case 0x3000: // ROM 0
dicarloj 17:c9afe1a7b423 360 return globalMemState.rom0[addr]; // todo <- change this for stm32
dicarloj 17:c9afe1a7b423 361
dicarloj 17:c9afe1a7b423 362 case 0x4000: // banked ROM
dicarloj 17:c9afe1a7b423 363 case 0x5000:
dicarloj 17:c9afe1a7b423 364 case 0x6000:
dicarloj 17:c9afe1a7b423 365 case 0x7000:
dicarloj 17:c9afe1a7b423 366 return globalMemState.mappedRom[addr & 0x3fff]; // todo <- change this for stm32
dicarloj 17:c9afe1a7b423 367
dicarloj 17:c9afe1a7b423 368 case 0x8000: // VRAM
dicarloj 17:c9afe1a7b423 369 case 0x9000:
dicarloj 17:c9afe1a7b423 370 return globalMemState.vram[addr & 0x1fff];
dicarloj 17:c9afe1a7b423 371
dicarloj 17:c9afe1a7b423 372 case 0xa000: // mapped RAM
dicarloj 17:c9afe1a7b423 373 case 0xb000:
dicarloj 17:c9afe1a7b423 374 if(!globalMemState.mappedRam) {
dicarloj 17:c9afe1a7b423 375 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 376 assert(false);
dicarloj 17:c9afe1a7b423 377 #endif
dicarloj 17:c9afe1a7b423 378 return 0xff;
dicarloj 17:c9afe1a7b423 379 }
dicarloj 17:c9afe1a7b423 380 return globalMemState.mappedRam[addr & 0x1fff];
dicarloj 17:c9afe1a7b423 381
dicarloj 17:c9afe1a7b423 382 case 0xc000: // internal RAM
dicarloj 17:c9afe1a7b423 383 case 0xd000:
dicarloj 17:c9afe1a7b423 384 return globalMemState.internalRam[addr & 0x1fff];
dicarloj 17:c9afe1a7b423 385
dicarloj 17:c9afe1a7b423 386 case 0xe000: // interal RAM copy
dicarloj 17:c9afe1a7b423 387 return globalMemState.internalRam[addr & 0x1fff];
dicarloj 17:c9afe1a7b423 388
dicarloj 17:c9afe1a7b423 389 case 0xf000: // either internal RAM copy or I/O or top-ram
dicarloj 17:c9afe1a7b423 390 switch(addr & 0x0f00) {
dicarloj 17:c9afe1a7b423 391 case 0x000:
dicarloj 17:c9afe1a7b423 392 case 0x100:
dicarloj 17:c9afe1a7b423 393 case 0x200:
dicarloj 17:c9afe1a7b423 394 case 0x300:
dicarloj 17:c9afe1a7b423 395 case 0x400:
dicarloj 17:c9afe1a7b423 396 case 0x500:
dicarloj 17:c9afe1a7b423 397 case 0x600:
dicarloj 17:c9afe1a7b423 398 case 0x700:
dicarloj 17:c9afe1a7b423 399 case 0x800:
dicarloj 17:c9afe1a7b423 400 case 0x900:
dicarloj 17:c9afe1a7b423 401 case 0xa00:
dicarloj 17:c9afe1a7b423 402 case 0xb00:
dicarloj 17:c9afe1a7b423 403 case 0xc00:
dicarloj 17:c9afe1a7b423 404 case 0xd00:
dicarloj 17:c9afe1a7b423 405 case 0xe00:
dicarloj 17:c9afe1a7b423 406 return globalMemState.internalRam[addr & 0x1fff];
dicarloj 17:c9afe1a7b423 407
dicarloj 17:c9afe1a7b423 408
dicarloj 17:c9afe1a7b423 409 case 0xf00:
dicarloj 17:c9afe1a7b423 410 if(addr >= 0xff80) {
dicarloj 17:c9afe1a7b423 411 return globalMemState.upperRam[addr & 0x7f];
dicarloj 17:c9afe1a7b423 412 } else {
dicarloj 17:c9afe1a7b423 413 u8 lowAddr = (u8)(addr & 0xff);
dicarloj 17:c9afe1a7b423 414 switch(lowAddr) {
dicarloj 17:c9afe1a7b423 415 case IO_LY:
dicarloj 17:c9afe1a7b423 416 case IO_SCROLLX:
dicarloj 17:c9afe1a7b423 417 case IO_SCROLLY:
dicarloj 17:c9afe1a7b423 418 case IO_NR10: // nyi
dicarloj 17:c9afe1a7b423 419 case IO_NR11: // nyi
dicarloj 17:c9afe1a7b423 420 case IO_NR12: // nyi
dicarloj 17:c9afe1a7b423 421 case IO_NR13: // nyi
dicarloj 17:c9afe1a7b423 422 case IO_NR14: // nyi
dicarloj 17:c9afe1a7b423 423 case IO_NR21: // nyi
dicarloj 17:c9afe1a7b423 424 case IO_NR22: // nyi
dicarloj 17:c9afe1a7b423 425 case IO_NR23: // nyi
dicarloj 17:c9afe1a7b423 426 case IO_NR24: // nyi
dicarloj 17:c9afe1a7b423 427 case IO_NR30: // nyi
dicarloj 17:c9afe1a7b423 428 case IO_NR31: // nyi
dicarloj 17:c9afe1a7b423 429 case IO_NR32: // nyi
dicarloj 17:c9afe1a7b423 430 case IO_NR33: // nyi
dicarloj 17:c9afe1a7b423 431 case IO_NR34: // nyi
dicarloj 17:c9afe1a7b423 432 case IO_NR41: // nyi
dicarloj 17:c9afe1a7b423 433 case IO_NR42: // nyi
dicarloj 17:c9afe1a7b423 434 case IO_NR43: // nyi
dicarloj 17:c9afe1a7b423 435 case IO_NR44: // nyi
dicarloj 17:c9afe1a7b423 436 case IO_NR50: // nyi
dicarloj 17:c9afe1a7b423 437 case IO_NR51: // nyi
dicarloj 17:c9afe1a7b423 438 case IO_NR52: // nyi
dicarloj 17:c9afe1a7b423 439 case IO_STAT: // nyi
dicarloj 17:c9afe1a7b423 440 case IO_WAVE_PATTERN: // nyi
dicarloj 17:c9afe1a7b423 441 case IO_LCDC: // nyi
dicarloj 17:c9afe1a7b423 442 case IO_BGP:
dicarloj 17:c9afe1a7b423 443 case IO_OBP0:
dicarloj 17:c9afe1a7b423 444 case IO_OBP1:
dicarloj 17:c9afe1a7b423 445 case IO_SERIAL_SB:
dicarloj 17:c9afe1a7b423 446 case IO_SERIAL_SC:
dicarloj 17:c9afe1a7b423 447 case IO_DIV:
dicarloj 17:c9afe1a7b423 448 case IO_TIMA:
dicarloj 17:c9afe1a7b423 449 case IO_TMA:
dicarloj 17:c9afe1a7b423 450 case IO_TAC:
dicarloj 17:c9afe1a7b423 451 case IO_WINY:
dicarloj 17:c9afe1a7b423 452 case IO_WINX:
dicarloj 17:c9afe1a7b423 453 return globalMemState.ioRegs[lowAddr];
dicarloj 17:c9afe1a7b423 454 break;
dicarloj 17:c9afe1a7b423 455
dicarloj 17:c9afe1a7b423 456 case IO_IF:
dicarloj 17:c9afe1a7b423 457 printf("read if: 0x%x\n", globalMemState.ioRegs[lowAddr]);
dicarloj 17:c9afe1a7b423 458 printf("timer value: 0x%x\n", globalMemState.ioRegs[IO_TIMA]);
dicarloj 17:c9afe1a7b423 459 return globalMemState.ioRegs[lowAddr];
dicarloj 17:c9afe1a7b423 460 break;
dicarloj 17:c9afe1a7b423 461
dicarloj 17:c9afe1a7b423 462
dicarloj 17:c9afe1a7b423 463 case IO_P1:
dicarloj 17:c9afe1a7b423 464 {
dicarloj 17:c9afe1a7b423 465 u8 regP1 = globalMemState.ioRegs[IO_P1];
dicarloj 17:c9afe1a7b423 466 //printf("ireg: 0x%x\n", regP1);
dicarloj 17:c9afe1a7b423 467 u8 joypad_data = 0;
dicarloj 17:c9afe1a7b423 468 if(regP1 & 0x10) {
dicarloj 17:c9afe1a7b423 469 if(keyboard.a) joypad_data += 0x1;
dicarloj 17:c9afe1a7b423 470 if(keyboard.b) joypad_data += 0x2;
dicarloj 17:c9afe1a7b423 471 if(keyboard.select) joypad_data += 0x4;
dicarloj 17:c9afe1a7b423 472 if(keyboard.start) joypad_data += 0x8;
dicarloj 17:c9afe1a7b423 473 }
dicarloj 17:c9afe1a7b423 474 if(regP1 & 0x20) {
dicarloj 17:c9afe1a7b423 475 if(keyboard.r) joypad_data += 0x1;
dicarloj 17:c9afe1a7b423 476 if(keyboard.l) joypad_data += 0x2;
dicarloj 17:c9afe1a7b423 477 if(keyboard.u) joypad_data += 0x4;
dicarloj 17:c9afe1a7b423 478 if(keyboard.d) joypad_data += 0x8;
dicarloj 17:c9afe1a7b423 479 }
dicarloj 17:c9afe1a7b423 480
dicarloj 17:c9afe1a7b423 481 regP1 = (regP1 & 0xf0);
dicarloj 17:c9afe1a7b423 482 joypad_data = ~joypad_data;
dicarloj 17:c9afe1a7b423 483 joypad_data = regP1 + (joypad_data & 0xf);
dicarloj 17:c9afe1a7b423 484 //globalMemState.ioRegs[IO_P1] = joypad_data;
dicarloj 17:c9afe1a7b423 485 //printf("jpd: 0x%x\n", joypad_data);
dicarloj 17:c9afe1a7b423 486 return joypad_data;
dicarloj 17:c9afe1a7b423 487 }
dicarloj 17:c9afe1a7b423 488
dicarloj 17:c9afe1a7b423 489 break;
dicarloj 17:c9afe1a7b423 490
dicarloj 17:c9afe1a7b423 491 case IO_GBCSPEED:
dicarloj 17:c9afe1a7b423 492 return 0xff;
dicarloj 17:c9afe1a7b423 493
dicarloj 17:c9afe1a7b423 494 case IO_LYC:
dicarloj 17:c9afe1a7b423 495 case IO_DMA:
dicarloj 17:c9afe1a7b423 496
dicarloj 17:c9afe1a7b423 497 printf("unhandled I/O read @ 0x%x\n", addr);
dicarloj 17:c9afe1a7b423 498 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 499 assert(false);
dicarloj 17:c9afe1a7b423 500 #endif
dicarloj 17:c9afe1a7b423 501 break;
dicarloj 17:c9afe1a7b423 502 default:
dicarloj 17:c9afe1a7b423 503 printf("unknown I/O read @ 0x%x\n", addr);
dicarloj 17:c9afe1a7b423 504 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 505 assert(false);
dicarloj 17:c9afe1a7b423 506 #endif
dicarloj 17:c9afe1a7b423 507 break;
dicarloj 17:c9afe1a7b423 508 }
dicarloj 17:c9afe1a7b423 509
dicarloj 17:c9afe1a7b423 510 }
dicarloj 17:c9afe1a7b423 511 default:
dicarloj 17:c9afe1a7b423 512 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 513 assert(false);
dicarloj 17:c9afe1a7b423 514 #endif
dicarloj 17:c9afe1a7b423 515 break;
dicarloj 17:c9afe1a7b423 516
dicarloj 17:c9afe1a7b423 517 }
dicarloj 17:c9afe1a7b423 518 break;
dicarloj 17:c9afe1a7b423 519
dicarloj 17:c9afe1a7b423 520 default:
dicarloj 17:c9afe1a7b423 521 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 522 assert(false);
dicarloj 17:c9afe1a7b423 523 #endif
dicarloj 17:c9afe1a7b423 524 break;
dicarloj 17:c9afe1a7b423 525 }
dicarloj 17:c9afe1a7b423 526 assert(false);
dicarloj 17:c9afe1a7b423 527 return 0xff;
dicarloj 17:c9afe1a7b423 528 }
dicarloj 17:c9afe1a7b423 529
dicarloj 17:c9afe1a7b423 530
dicarloj 17:c9afe1a7b423 531 void writeByte(u8 byte, u16 addr) {
dicarloj 17:c9afe1a7b423 532 switch(addr & 0xf000) {
dicarloj 17:c9afe1a7b423 533 case 0x0000: // ROM 0, but possibly the BIOS area
dicarloj 17:c9afe1a7b423 534 if(globalMemState.inBios) {
dicarloj 17:c9afe1a7b423 535 printf("ERROR: tried to write into ROM0 or BIOS (@ 0x%04x) during BIOS!\n", addr);
dicarloj 17:c9afe1a7b423 536 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 537 assert(false);
dicarloj 17:c9afe1a7b423 538 #endif
dicarloj 17:c9afe1a7b423 539 } else {
dicarloj 17:c9afe1a7b423 540 mbcHandler(addr, byte);
dicarloj 17:c9afe1a7b423 541 }
dicarloj 17:c9afe1a7b423 542 break;
dicarloj 17:c9afe1a7b423 543
dicarloj 17:c9afe1a7b423 544
dicarloj 17:c9afe1a7b423 545 case 0x1000: // ROM 0
dicarloj 17:c9afe1a7b423 546 case 0x2000: // ROM 0
dicarloj 17:c9afe1a7b423 547 case 0x3000: // ROM 0
dicarloj 17:c9afe1a7b423 548 case 0x4000: // ROM 1
dicarloj 17:c9afe1a7b423 549 case 0x5000: // ROM 1
dicarloj 17:c9afe1a7b423 550 case 0x6000: // ROM 1
dicarloj 17:c9afe1a7b423 551 case 0x7000: // ROM 1
dicarloj 17:c9afe1a7b423 552 mbcHandler(addr, byte);
dicarloj 17:c9afe1a7b423 553 break;
dicarloj 17:c9afe1a7b423 554
dicarloj 17:c9afe1a7b423 555 case 0x8000: // VRAM
dicarloj 17:c9afe1a7b423 556 case 0x9000:
dicarloj 17:c9afe1a7b423 557 globalMemState.vram[addr & 0x1fff] = byte;
dicarloj 17:c9afe1a7b423 558 break;
dicarloj 17:c9afe1a7b423 559
dicarloj 17:c9afe1a7b423 560 case 0xa000: // mapped RAM
dicarloj 17:c9afe1a7b423 561 case 0xb000:
dicarloj 17:c9afe1a7b423 562 if(!globalMemState.mappedRam) {
dicarloj 17:c9afe1a7b423 563 //printf("write to unmapped ram @ 0x%x value 0x%x\n", addr, byte);
dicarloj 17:c9afe1a7b423 564 //#ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 565 // assert(false);
dicarloj 17:c9afe1a7b423 566 //#endif
dicarloj 17:c9afe1a7b423 567 break;
dicarloj 17:c9afe1a7b423 568 }
dicarloj 17:c9afe1a7b423 569 globalMemState.mappedRam[addr & 0x1fff] = byte;
dicarloj 17:c9afe1a7b423 570 break;
dicarloj 17:c9afe1a7b423 571
dicarloj 17:c9afe1a7b423 572 case 0xc000: // internal RAM
dicarloj 17:c9afe1a7b423 573 case 0xd000:
dicarloj 17:c9afe1a7b423 574 globalMemState.internalRam[addr & 0x1fff] = byte;
dicarloj 17:c9afe1a7b423 575 break;
dicarloj 17:c9afe1a7b423 576
dicarloj 17:c9afe1a7b423 577 case 0xe000: // interal RAM copy
dicarloj 17:c9afe1a7b423 578 globalMemState.internalRam[addr & 0x1fff] = byte;
dicarloj 17:c9afe1a7b423 579 break;
dicarloj 17:c9afe1a7b423 580
dicarloj 17:c9afe1a7b423 581 case 0xf000: // either internal RAM copy or I/O or top-ram
dicarloj 17:c9afe1a7b423 582 switch(addr & 0x0f00) {
dicarloj 17:c9afe1a7b423 583 case 0x000:
dicarloj 17:c9afe1a7b423 584 case 0x100:
dicarloj 17:c9afe1a7b423 585 case 0x200:
dicarloj 17:c9afe1a7b423 586 case 0x300:
dicarloj 17:c9afe1a7b423 587 case 0x400:
dicarloj 17:c9afe1a7b423 588 case 0x500:
dicarloj 17:c9afe1a7b423 589 case 0x600:
dicarloj 17:c9afe1a7b423 590 case 0x700:
dicarloj 17:c9afe1a7b423 591 case 0x800:
dicarloj 17:c9afe1a7b423 592 case 0x900:
dicarloj 17:c9afe1a7b423 593 case 0xa00:
dicarloj 17:c9afe1a7b423 594 case 0xb00:
dicarloj 17:c9afe1a7b423 595 case 0xc00:
dicarloj 17:c9afe1a7b423 596 case 0xd00:
dicarloj 17:c9afe1a7b423 597 case 0xe00:
dicarloj 17:c9afe1a7b423 598 globalMemState.internalRam[addr & 0x1fff] = byte;
dicarloj 17:c9afe1a7b423 599 break;
dicarloj 17:c9afe1a7b423 600
dicarloj 17:c9afe1a7b423 601
dicarloj 17:c9afe1a7b423 602 case 0xf00:
dicarloj 17:c9afe1a7b423 603 if(addr >= 0xff80) {
dicarloj 17:c9afe1a7b423 604 globalMemState.upperRam[addr & 0x7f] = byte;
dicarloj 17:c9afe1a7b423 605 break;
dicarloj 17:c9afe1a7b423 606 } else {
dicarloj 17:c9afe1a7b423 607 u16 maskedAddress = addr & 0x7f;
dicarloj 17:c9afe1a7b423 608 globalMemState.ioRegs[maskedAddress] = byte;
dicarloj 17:c9afe1a7b423 609 u8 lowAddr = (u8)(addr & 0xff);
dicarloj 17:c9afe1a7b423 610 switch(lowAddr) {
dicarloj 17:c9afe1a7b423 611
dicarloj 17:c9afe1a7b423 612 case IO_NR10:
dicarloj 17:c9afe1a7b423 613 case IO_NR11:
dicarloj 17:c9afe1a7b423 614 case IO_NR12:
dicarloj 17:c9afe1a7b423 615 case IO_NR13:
dicarloj 17:c9afe1a7b423 616 case IO_NR14:
dicarloj 17:c9afe1a7b423 617 case IO_NR21:
dicarloj 17:c9afe1a7b423 618 case IO_NR22:
dicarloj 17:c9afe1a7b423 619 case IO_NR23:
dicarloj 17:c9afe1a7b423 620 case IO_NR24:
dicarloj 17:c9afe1a7b423 621 case IO_NR30:
dicarloj 17:c9afe1a7b423 622 case IO_NR31:
dicarloj 17:c9afe1a7b423 623 case IO_NR32:
dicarloj 17:c9afe1a7b423 624 case IO_NR33:
dicarloj 17:c9afe1a7b423 625 case IO_NR34:
dicarloj 17:c9afe1a7b423 626 case IO_NR41:
dicarloj 17:c9afe1a7b423 627 case IO_NR42:
dicarloj 17:c9afe1a7b423 628 case IO_NR43:
dicarloj 17:c9afe1a7b423 629 case IO_NR44:
dicarloj 17:c9afe1a7b423 630 case IO_NR50:
dicarloj 17:c9afe1a7b423 631 case IO_NR51:
dicarloj 17:c9afe1a7b423 632 case IO_NR52:
dicarloj 17:c9afe1a7b423 633 case IO_WAVE_PATTERN:
dicarloj 17:c9afe1a7b423 634 case 0x31:
dicarloj 17:c9afe1a7b423 635 case 0x32:
dicarloj 17:c9afe1a7b423 636 case 0x33:
dicarloj 17:c9afe1a7b423 637 case 0x34:
dicarloj 17:c9afe1a7b423 638 case 0x35:
dicarloj 17:c9afe1a7b423 639 case 0x36:
dicarloj 17:c9afe1a7b423 640 case 0x37:
dicarloj 17:c9afe1a7b423 641 case 0x38:
dicarloj 17:c9afe1a7b423 642 case 0x39:
dicarloj 17:c9afe1a7b423 643 case 0x3a:
dicarloj 17:c9afe1a7b423 644 case 0x3b:
dicarloj 17:c9afe1a7b423 645 case 0x3c:
dicarloj 17:c9afe1a7b423 646 case 0x3d:
dicarloj 17:c9afe1a7b423 647 case 0x3e:
dicarloj 17:c9afe1a7b423 648 case 0x3f:
dicarloj 17:c9afe1a7b423 649 case IO_BGP:
dicarloj 17:c9afe1a7b423 650 case IO_SCROLLX:
dicarloj 17:c9afe1a7b423 651 case IO_SCROLLY:
dicarloj 17:c9afe1a7b423 652 case IO_LCDC:
dicarloj 17:c9afe1a7b423 653 case IO_STAT:
dicarloj 17:c9afe1a7b423 654 case IO_OBP0:
dicarloj 17:c9afe1a7b423 655 case IO_OBP1:
dicarloj 17:c9afe1a7b423 656 case IO_P1:
dicarloj 17:c9afe1a7b423 657 case IO_IF:
dicarloj 17:c9afe1a7b423 658 case IO_TAC:
dicarloj 17:c9afe1a7b423 659 case IO_TIMA:
dicarloj 17:c9afe1a7b423 660 case IO_TMA:
dicarloj 17:c9afe1a7b423 661 case IO_SERIAL_SB:
dicarloj 17:c9afe1a7b423 662 case IO_SERIAL_SC:
dicarloj 17:c9afe1a7b423 663 case IO_WINY:
dicarloj 17:c9afe1a7b423 664 case IO_WINX:
dicarloj 17:c9afe1a7b423 665 case IO_LYC:
dicarloj 17:c9afe1a7b423 666 break;
dicarloj 17:c9afe1a7b423 667
dicarloj 17:c9afe1a7b423 668 case IO_EXIT_BIOS:
dicarloj 17:c9afe1a7b423 669 if(globalMemState.inBios) {
dicarloj 17:c9afe1a7b423 670 printf("EXIT BIOS by write 0x%x to 0x%x", byte, addr);
dicarloj 17:c9afe1a7b423 671 globalMemState.inBios = false;
dicarloj 17:c9afe1a7b423 672 break;
dicarloj 17:c9afe1a7b423 673 } else {
dicarloj 17:c9afe1a7b423 674 printf("tried to write to 0xff50 when not in bios?\n");
dicarloj 17:c9afe1a7b423 675 break;
dicarloj 17:c9afe1a7b423 676 }
dicarloj 17:c9afe1a7b423 677 break;
dicarloj 17:c9afe1a7b423 678
dicarloj 17:c9afe1a7b423 679 case IO_DMA:
dicarloj 17:c9afe1a7b423 680 {
dicarloj 17:c9afe1a7b423 681 u16 dmaAddr = ((u16)byte) << 8;
dicarloj 17:c9afe1a7b423 682 for(u16 i = 0; i < 160; i++) {
dicarloj 17:c9afe1a7b423 683 writeByte(readByte(dmaAddr + i), (u16)0xfe00 + i);
dicarloj 17:c9afe1a7b423 684 }
dicarloj 17:c9afe1a7b423 685 break;
dicarloj 17:c9afe1a7b423 686 }
dicarloj 17:c9afe1a7b423 687
dicarloj 17:c9afe1a7b423 688 case 0x7f:
dicarloj 17:c9afe1a7b423 689 printf("OOPS\n");
dicarloj 17:c9afe1a7b423 690 break;
dicarloj 17:c9afe1a7b423 691
dicarloj 17:c9afe1a7b423 692
dicarloj 17:c9afe1a7b423 693 case IO_LY:
dicarloj 17:c9afe1a7b423 694 printf("unhandled I/O write @ 0x%x\n", addr);
dicarloj 17:c9afe1a7b423 695 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 696 assert(false);
dicarloj 17:c9afe1a7b423 697 #endif
dicarloj 17:c9afe1a7b423 698 break;
dicarloj 17:c9afe1a7b423 699 default:
dicarloj 17:c9afe1a7b423 700 printf("unknown I/O write @ 0x%x\n", addr);
dicarloj 17:c9afe1a7b423 701 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 702 assert(false);
dicarloj 17:c9afe1a7b423 703 #endif
dicarloj 17:c9afe1a7b423 704 break;
dicarloj 17:c9afe1a7b423 705 }
dicarloj 17:c9afe1a7b423 706 break;
dicarloj 17:c9afe1a7b423 707 }
dicarloj 17:c9afe1a7b423 708 default:
dicarloj 17:c9afe1a7b423 709 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 710 assert(false);
dicarloj 17:c9afe1a7b423 711 #endif
dicarloj 17:c9afe1a7b423 712 break;
dicarloj 17:c9afe1a7b423 713 }
dicarloj 17:c9afe1a7b423 714 break;
dicarloj 17:c9afe1a7b423 715 default:
dicarloj 17:c9afe1a7b423 716 #ifndef DANGER_MODE
dicarloj 17:c9afe1a7b423 717 assert(false);
dicarloj 17:c9afe1a7b423 718 #endif
dicarloj 17:c9afe1a7b423 719 break;
dicarloj 17:c9afe1a7b423 720 }
dicarloj 17:c9afe1a7b423 721 }