emu.cpp (21949B)
1/* 2 * Gearboy - Nintendo Game Boy Emulator 3 * Copyright (C) 2012 Ignacio Sanchez 4 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * any later version. 9 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see http://www.gnu.org/licenses/ 17 * 18 */ 19 20#include "../../src/gearboy.h" 21#include "../audio-shared/Sound_Queue.h" 22 23#define EMU_IMPORT 24#include "emu.h" 25 26// red, green, blue 27static GB_Color original_palette[4] = {{0x87, 0x96, 0x03},{0x4D, 0x6B, 0x03},{0x2B, 0x55, 0x03},{0x14, 0x44, 0x03}}; 28static GB_Color sharp_palette[4] = {{0xF5, 0xFA, 0xEF},{0x86, 0xC2, 0x70},{0x2F, 0x69, 0x57},{0x0B, 0x19, 0x20}}; 29static GB_Color bw_palette[4] = {{0xFF, 0xFF, 0xFF},{0xAA, 0xAA, 0xAA},{0x55, 0x55, 0x55},{0x00, 0x00, 0x00}}; 30static GB_Color autumn_palette[4] = {{0xFF, 0xF6, 0xD3},{0xF9, 0xA8, 0x75},{0xEB, 0x6B, 0x6F},{0x7C, 0x3F, 0x58}}; 31static GB_Color soft_palette[4] = {{0xE0, 0xE0, 0xAA},{0xB0, 0xB8, 0x7C},{0x72, 0x82, 0x5B},{0x39, 0x34, 0x17}}; 32static GB_Color slime_palette[4] = {{0xD4, 0xEB, 0xA5},{0x62, 0xB8, 0x7C},{0x27, 0x76, 0x5D},{0x1D, 0x39, 0x39}}; 33 34static GearboyCore* gearboy; 35static Sound_Queue* sound_queue; 36static u16* frame_buffer_565; 37static u16* debug_background_buffer_565; 38static u16* debug_tile_buffers_565[2]; 39static u16* debug_oam_buffers_565[40]; 40static s16* audio_buffer; 41static bool audio_enabled; 42static bool debugging = false; 43static bool debug_step = false; 44static bool debug_next_frame = false; 45static bool color_correction = false; 46 47static void save_ram(void); 48static void load_ram(void); 49static void generate_24bit_buffer(GB_Color* dest, u16* src, int size); 50static const char* get_mbc(Cartridge::CartridgeTypes type); 51static void init_debug(void); 52static void update_debug(void); 53static void update_debug_background_buffer(void); 54static void update_debug_tile_buffers(void); 55static void update_debug_oam_buffers(void); 56 57void emu_init(void) 58{ 59 frame_buffer_565 = new u16[GAMEBOY_WIDTH * GAMEBOY_HEIGHT]; 60 emu_frame_buffer = new GB_Color[GAMEBOY_WIDTH * GAMEBOY_HEIGHT]; 61 62 init_debug(); 63 64 gearboy = new GearboyCore(); 65 gearboy->Init(); 66 67 sound_queue = new Sound_Queue(); 68 sound_queue->start(44100, 2); 69 70 audio_buffer = new s16[AUDIO_BUFFER_SIZE]; 71 72 for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) 73 audio_buffer[i] = 0; 74 75 audio_enabled = true; 76 emu_audio_sync = true; 77 emu_debug_disable_breakpoints_cpu = false; 78 emu_debug_disable_breakpoints_mem = false; 79 emu_debug_background_tile_address = -1; 80 emu_debug_background_map_address = -1; 81 emu_debug_tile_dmg_palette = 0; 82 emu_debug_tile_color_palette = 0; 83 emu_savefiles_dir_option = 0; 84 emu_savestates_dir_option = 0; 85 emu_savefiles_path[0] = 0; 86 emu_savestates_path[0] = 0; 87} 88 89void emu_destroy(void) 90{ 91 save_ram(); 92 SafeDeleteArray(audio_buffer); 93 SafeDelete(sound_queue); 94 SafeDelete(gearboy); 95 SafeDeleteArray(frame_buffer_565); 96 SafeDeleteArray(emu_frame_buffer); 97 SafeDeleteArray(debug_background_buffer_565); 98 SafeDeleteArray(emu_debug_background_buffer); 99 for (int b = 0; b < 2; b++) 100 { 101 SafeDeleteArray(debug_tile_buffers_565[b]); 102 SafeDeleteArray(emu_debug_tile_buffers[b]); 103 } 104 for (int s = 0; s < 40; s++) 105 { 106 SafeDeleteArray(debug_oam_buffers_565[s]); 107 SafeDeleteArray(emu_debug_oam_buffers[s]); 108 } 109} 110 111void emu_load_rom(const char* file_path, bool force_dmg, Cartridge::CartridgeTypes mbc, bool force_gba) 112{ 113 save_ram(); 114 gearboy->LoadROM(file_path, force_dmg, mbc, force_gba); 115 load_ram(); 116 emu_debug_continue(); 117} 118 119void emu_update(void) 120{ 121 if (!emu_is_empty()) 122 { 123 int sampleCount = 0; 124 125 if (!debugging || debug_step || debug_next_frame) 126 { 127 bool breakpoints = (!emu_debug_disable_breakpoints_cpu && !emu_debug_disable_breakpoints_mem) || IsValidPointer(gearboy->GetMemory()->GetRunToBreakpoint()); 128 129 if (gearboy->RunToVBlank(frame_buffer_565, audio_buffer, &sampleCount, false, debug_step, breakpoints)) 130 { 131 debugging = true; 132 } 133 134 debug_next_frame = false; 135 debug_step = false; 136 } 137 138 generate_24bit_buffer(emu_frame_buffer, frame_buffer_565, GAMEBOY_WIDTH * GAMEBOY_HEIGHT); 139 140 update_debug(); 141 142 if ((sampleCount > 0) && !gearboy->IsPaused()) 143 { 144 sound_queue->write(audio_buffer, sampleCount, emu_audio_sync); 145 } 146 } 147} 148 149void emu_key_pressed(Gameboy_Keys key) 150{ 151 gearboy->KeyPressed(key); 152} 153 154void emu_key_released(Gameboy_Keys key) 155{ 156 gearboy->KeyReleased(key); 157} 158 159void emu_pause(void) 160{ 161 gearboy->Pause(true); 162} 163 164void emu_resume(void) 165{ 166 gearboy->Pause(false); 167} 168 169bool emu_is_paused(void) 170{ 171 return gearboy->IsPaused(); 172} 173 174bool emu_is_empty(void) 175{ 176 return !gearboy->GetCartridge()->IsLoadedROM(); 177} 178 179void emu_reset(bool force_dmg, Cartridge::CartridgeTypes mbc, bool force_gba) 180{ 181 save_ram(); 182 gearboy->ResetROM(force_dmg, mbc, force_gba); 183 load_ram(); 184} 185 186void emu_memory_dump(void) 187{ 188 gearboy->SaveMemoryDump(); 189} 190 191void emu_dissasemble_rom(void) 192{ 193 gearboy->SaveDisassembledROM(); 194} 195 196void emu_audio_volume(float volume) 197{ 198 audio_enabled = (volume > 0.0f); 199 gearboy->SetSoundVolume(volume); 200} 201 202void emu_audio_reset(void) 203{ 204 sound_queue->stop(); 205 sound_queue->start(44100, 2); 206} 207 208bool emu_is_audio_enabled(void) 209{ 210 return audio_enabled; 211} 212 213void emu_dmg_palette(GB_Color& color1, GB_Color& color2, GB_Color& color3, GB_Color& color4) 214{ 215 gearboy->SetDMGPalette(color1, color2, color3, color4); 216} 217 218void emu_dmg_predefined_palette(int palette) 219{ 220 GB_Color* predefined; 221 222 switch (palette) 223 { 224 case 0: 225 predefined = original_palette; 226 break; 227 case 1: 228 predefined = sharp_palette; 229 break; 230 case 2: 231 predefined = bw_palette; 232 break; 233 case 3: 234 predefined = autumn_palette; 235 break; 236 case 4: 237 predefined = soft_palette; 238 break; 239 case 5: 240 predefined = slime_palette; 241 break; 242 default: 243 predefined = NULL; 244 } 245 246 if (predefined) 247 { 248 gearboy->SetDMGPalette(predefined[0], predefined[1], predefined[2], predefined[3]); 249 } 250} 251 252bool emu_is_cgb(void) 253{ 254 return gearboy->GetCartridge()->IsCGB(); 255} 256 257void emu_save_ram(const char* file_path) 258{ 259 if (!emu_is_empty()) 260 gearboy->SaveRam(file_path, true); 261} 262 263void emu_load_ram(const char* file_path, bool force_dmg, Cartridge::CartridgeTypes mbc, bool force_gba) 264{ 265 if (!emu_is_empty()) 266 { 267 save_ram(); 268 gearboy->ResetROM(force_dmg, mbc, force_gba); 269 gearboy->LoadRam(file_path, true); 270 } 271} 272 273void emu_save_state_slot(int index) 274{ 275 if (!emu_is_empty()) 276 { 277 if ((emu_savestates_dir_option == 0) && (strcmp(emu_savestates_path, ""))) 278 gearboy->SaveState(emu_savestates_path, index); 279 else 280 gearboy->SaveState(index); 281 } 282} 283 284void emu_load_state_slot(int index) 285{ 286 if (!emu_is_empty()) 287 { 288 if ((emu_savestates_dir_option == 0) && (strcmp(emu_savestates_path, ""))) 289 gearboy->LoadState(emu_savestates_path, index); 290 else 291 gearboy->LoadState(index); 292 } 293} 294 295void emu_save_state_file(const char* file_path) 296{ 297 if (!emu_is_empty()) 298 gearboy->SaveState(file_path, -1); 299} 300 301void emu_load_state_file(const char* file_path) 302{ 303 if (!emu_is_empty()) 304 gearboy->LoadState(file_path, -1); 305} 306 307void emu_add_cheat(const char* cheat) 308{ 309 gearboy->SetCheat(cheat); 310} 311 312void emu_clear_cheats(void) 313{ 314 gearboy->ClearCheats(); 315} 316 317void emu_get_info(char* info) 318{ 319 if (!emu_is_empty()) 320 { 321 Cartridge* cart = gearboy->GetCartridge(); 322 323 const char* filename = cart->GetFileName(); 324 const char* gbc = cart->IsCGB() ? "YES" : "NO"; 325 const char* sgb = cart->IsSGB() ? "YES" : "NO"; 326 const char* battery = cart->HasBattery() ? "YES" : "NO"; 327 const char* rtc = cart->IsRTCPresent() ? "YES" : "NO"; 328 const char* rumble = cart->IsRumblePresent() ? "YES" : "NO"; 329 const char* name = cart->GetName(); 330 const char* checksum = cart->IsValidROM() ? "VALID" : "FAILED"; 331 int version = cart->GetVersion(); 332 int rom_banks = cart->GetROMBankCount(); 333 int ram_banks = cart->GetRAMBankCount(); 334 335 const char* mbc = get_mbc(cart->GetType()); 336 337 sprintf(info, "File Name: %s\nMBC: %s\nGame Boy Color: %s\nSuper Game Boy: %s\nCartridge Name: %s\nCartridge Version: %d\nCartridge Checksum: %s\nROM Banks: %d\nRAM Banks: %d\nBattery: %s\nReal Time Clock: %s\nRumble: %s\n", filename, mbc, gbc, sgb, name, version, checksum, rom_banks, ram_banks, battery, rtc, rumble); 338 } 339 else 340 { 341 sprintf(info, "No data!"); 342 } 343} 344 345GearboyCore* emu_get_core(void) 346{ 347 return gearboy; 348} 349 350void emu_color_correction(bool correction) 351{ 352 color_correction = correction; 353} 354 355void emu_debug_step(void) 356{ 357 debugging = debug_step = true; 358 debug_next_frame = false; 359 gearboy->Pause(false); 360} 361 362void emu_debug_continue(void) 363{ 364 debugging = debug_step = debug_next_frame = false; 365 gearboy->Pause(false); 366} 367 368void emu_debug_next_frame(void) 369{ 370 debugging = debug_next_frame = true; 371 debug_step = false; 372 gearboy->Pause(false); 373} 374 375void emu_load_bootrom_dmg(const char* file_path) 376{ 377 gearboy->GetMemory()->LoadBootromDMG(file_path); 378} 379 380void emu_load_bootrom_gbc(const char* file_path) 381{ 382 gearboy->GetMemory()->LoadBootromGBC(file_path); 383} 384 385void emu_enable_bootrom_dmg(bool enable) 386{ 387 gearboy->GetMemory()->EnableBootromDMG(enable); 388} 389 390void emu_enable_bootrom_gbc(bool enable) 391{ 392 gearboy->GetMemory()->EnableBootromGBC(enable); 393} 394 395 396static void save_ram(void) 397{ 398#ifdef DEBUG_GEARBOY 399 emu_dissasemble_rom(); 400#endif 401 if ((emu_savefiles_dir_option == 0) && (strcmp(emu_savefiles_path, ""))) 402 gearboy->SaveRam(emu_savefiles_path); 403 else 404 gearboy->SaveRam(); 405} 406 407static void load_ram(void) 408{ 409 if ((emu_savefiles_dir_option == 0) && (strcmp(emu_savefiles_path, ""))) 410 gearboy->LoadRam(emu_savefiles_path); 411 else 412 gearboy->LoadRam(); 413} 414 415static void generate_24bit_buffer(GB_Color* dest, u16* src, int size) 416{ 417 for (int i=0; i < size; i++) 418 { 419 dest[i].red = (((src[i] >> 11) & 0x1F ) * 255 + 15) / 31; 420 dest[i].green = (((src[i] >> 5) & 0x3F ) * 255 + 31) / 63; 421 dest[i].blue = ((src[i] & 0x1F ) * 255 + 15) / 31; 422 423 if (gearboy->IsCGB() && color_correction) 424 { 425 u8 red = (u8)(((dest[i].red * 0.8125f) + (dest[i].green * 0.125f) + (dest[i].blue * 0.0625f)) * 0.95f); 426 u8 green = (u8)(((dest[i].green * 0.75f) + (dest[i].blue * 0.25f)) * 0.95f); 427 u8 blue = (u8)((((dest[i].red * 0.1875f) + (dest[i].green * 0.125f) + (dest[i].blue * 0.6875f))) * 0.95f); 428 429 dest[i].red = red; 430 dest[i].green = green; 431 dest[i].blue = blue; 432 } 433 } 434} 435 436static const char* get_mbc(Cartridge::CartridgeTypes type) 437{ 438 switch (type) 439 { 440 case Cartridge::CartridgeNoMBC: 441 return "ROM Only"; 442 break; 443 case Cartridge::CartridgeMBC1: 444 return "MBC 1"; 445 break; 446 case Cartridge::CartridgeMBC1Multi: 447 return "MBC 1 Multi 64"; 448 break; 449 case Cartridge::CartridgeMBC2: 450 return "MBC 2"; 451 break; 452 case Cartridge::CartridgeMBC3: 453 return "MBC 3"; 454 break; 455 case Cartridge::CartridgeMBC5: 456 return "MBC 5"; 457 break; 458 case Cartridge::CartridgeNotSupported: 459 return "Not Supported"; 460 break; 461 default: 462 return "Undefined"; 463 break; 464 } 465} 466 467static void init_debug(void) 468{ 469 debug_background_buffer_565 = new u16[256 * 256]; 470 emu_debug_background_buffer = new GB_Color[256 * 256]; 471 472 for (int b = 0; b < 2; b++) 473 { 474 debug_tile_buffers_565[b] = new u16[16 * 24 * 64]; 475 emu_debug_tile_buffers[b] = new GB_Color[16 * 24 * 64]; 476 477 for (int i=0; i < (16 * 24 * 64); i++) 478 { 479 emu_debug_tile_buffers[b][i].red = 0; 480 emu_debug_tile_buffers[b][i].green = 0; 481 emu_debug_tile_buffers[b][i].blue = 0; 482 debug_tile_buffers_565[b][i] = 0; 483 } 484 } 485 486 for (int s = 0; s < 40; s++) 487 { 488 debug_oam_buffers_565[s] = new u16[8 * 16]; 489 emu_debug_oam_buffers[s] = new GB_Color[8 * 16]; 490 491 for (int i=0; i < (8 * 16); i++) 492 { 493 emu_debug_oam_buffers[s][i].red = 0; 494 emu_debug_oam_buffers[s][i].green = 0; 495 emu_debug_oam_buffers[s][i].blue = 0; 496 debug_oam_buffers_565[s][i] = 0; 497 } 498 } 499 500 for (int i=0; i < (GAMEBOY_WIDTH * GAMEBOY_HEIGHT); i++) 501 { 502 emu_frame_buffer[i].red = 0; 503 emu_frame_buffer[i].green = 0; 504 emu_frame_buffer[i].blue = 0; 505 frame_buffer_565[i] = 0; 506 } 507 508 for (int i=0; i < (256 * 256); i++) 509 { 510 emu_debug_background_buffer[i].red = 0; 511 emu_debug_background_buffer[i].green = 0; 512 emu_debug_background_buffer[i].blue = 0; 513 debug_background_buffer_565[i] = 0; 514 } 515} 516 517static void update_debug(void) 518{ 519 update_debug_background_buffer(); 520 update_debug_tile_buffers(); 521 update_debug_oam_buffers(); 522 523 generate_24bit_buffer(emu_debug_background_buffer, debug_background_buffer_565, 256 * 256); 524 525 for (int b = 0; b < 2; b++) 526 { 527 generate_24bit_buffer(emu_debug_tile_buffers[b], debug_tile_buffers_565[b], 16 * 24 * 64); 528 } 529 530 for (int s = 0; s < 40; s++) 531 { 532 generate_24bit_buffer(emu_debug_oam_buffers[s], debug_oam_buffers_565[s], 8 * 16); 533 } 534 535} 536 537static void update_debug_background_buffer(void) 538{ 539 Video* video = gearboy->GetVideo(); 540 Memory* memory = gearboy->GetMemory(); 541 u16* dmg_palette = gearboy->GetDMGInternalPalette(); 542 u8 lcdc = memory->Retrieve(0xFF40); 543 544 for (int line = 0; line < 256; line++) 545 { 546 int line_width = (line * 256); 547 548 for (int pixel = 0; pixel < 256; pixel++) 549 { 550 int offset_x = pixel & 0x7; 551 int screen_tile = pixel >> 3; 552 int tile_start_addr = emu_debug_background_tile_address >= 0 ? emu_debug_background_tile_address : IsSetBit(lcdc, 4) ? 0x8000 : 0x8800; 553 int map_start_addr = emu_debug_background_map_address >= 0 ? emu_debug_background_map_address : IsSetBit(lcdc, 3) ? 0x9C00 : 0x9800; 554 int line_32 = (line >> 3) << 5; 555 int tile_pixel_y = line & 0x7; 556 int tile_pixel_y_2 = tile_pixel_y << 1; 557 int tile_pixel_y_flip_2 = (7 - tile_pixel_y) << 1; 558 u8 palette = memory->Retrieve(0xFF47); 559 560 int screen_pixel_x = (screen_tile << 3) + offset_x; 561 u8 map_pixel_x = screen_pixel_x; 562 int map_tile_x = map_pixel_x >> 3; 563 int map_tile_offset_x = map_pixel_x & 0x7; 564 u16 map_tile_addr = map_start_addr + line_32 + map_tile_x; 565 int map_tile = 0; 566 567 if (tile_start_addr == 0x8800) 568 { 569 map_tile = static_cast<s8> (memory->Retrieve(map_tile_addr)); 570 map_tile += 128; 571 } 572 else 573 { 574 map_tile = memory->Retrieve(map_tile_addr); 575 } 576 577 u8 cgb_tile_attr = gearboy->IsCGB() ? memory->ReadCGBLCDRAM(map_tile_addr, true) : 0; 578 u8 cgb_tile_pal = gearboy->IsCGB() ? (cgb_tile_attr & 0x07) : 0; 579 bool cgb_tile_bank = gearboy->IsCGB() ? IsSetBit(cgb_tile_attr, 3) : false; 580 bool cgb_tile_xflip = gearboy->IsCGB() ? IsSetBit(cgb_tile_attr, 5) : false; 581 bool cgb_tile_yflip = gearboy->IsCGB() ? IsSetBit(cgb_tile_attr, 6) : false; 582 int map_tile_16 = map_tile << 4; 583 u8 byte1 = 0; 584 u8 byte2 = 0; 585 int final_pixely_2 = cgb_tile_yflip ? tile_pixel_y_flip_2 : tile_pixel_y_2; 586 int tile_address = tile_start_addr + map_tile_16 + final_pixely_2; 587 588 if (cgb_tile_bank) 589 { 590 byte1 = memory->ReadCGBLCDRAM(tile_address, true); 591 byte2 = memory->ReadCGBLCDRAM(tile_address + 1, true); 592 } 593 else 594 { 595 byte1 = memory->Retrieve(tile_address); 596 byte2 = memory->Retrieve(tile_address + 1); 597 } 598 599 int pixel_x_in_tile = map_tile_offset_x; 600 601 if (cgb_tile_xflip) 602 { 603 pixel_x_in_tile = 7 - pixel_x_in_tile; 604 } 605 int pixel_x_in_tile_bit = 0x1 << (7 - pixel_x_in_tile); 606 int pixel_data = (byte1 & pixel_x_in_tile_bit) ? 1 : 0; 607 pixel_data |= (byte2 & pixel_x_in_tile_bit) ? 2 : 0; 608 609 int index = line_width + screen_pixel_x; 610 611 if (gearboy->IsCGB()) 612 { 613 PaletteMatrix bg_palettes = video->GetCGBBackgroundPalettes(); 614 debug_background_buffer_565[index] = (*bg_palettes)[cgb_tile_pal][pixel_data][1]; 615 } 616 else 617 { 618 u8 color = (palette >> (pixel_data << 1)) & 0x03; 619 debug_background_buffer_565[index] = dmg_palette[color]; 620 } 621 } 622 } 623} 624 625static void update_debug_tile_buffers(void) 626{ 627 Memory* memory = gearboy->GetMemory(); 628 Video* video = gearboy->GetVideo(); 629 u16* dmg_palette = gearboy->GetDMGInternalPalette(); 630 PaletteMatrix bg_palettes = video->GetCGBBackgroundPalettes(); 631 PaletteMatrix sprite_palettes = video->GetCGBSpritePalettes(); 632 633 for (int b = 0; b < 2; b++) 634 { 635 for (int pixel = 0; pixel < (16 * 24 * 64); pixel++) 636 { 637 int tilex = (pixel >> 3) & 0xF; 638 int tile_offset_x = pixel & 0x7; 639 int tiley = (pixel >> 10); 640 int tile_offset_y = (pixel >> 7) & 0x7; 641 int tile = (tiley << 4) + tilex; 642 int tile_address = 0x8000 + (tile << 4) + (tile_offset_y << 1); 643 u8 byte1 = 0; 644 u8 byte2 = 0; 645 646 if (b == 0) 647 { 648 byte1 = memory->Retrieve(tile_address); 649 byte2 = memory->Retrieve(tile_address + 1); 650 } 651 else 652 { 653 byte1 = memory->ReadCGBLCDRAM(tile_address, true); 654 byte2 = memory->ReadCGBLCDRAM(tile_address + 1, true); 655 } 656 657 int tile_bit = 0x1 << (7 - tile_offset_x); 658 int pixel_data = (byte1 & tile_bit) ? 1 : 0; 659 pixel_data |= (byte2 & tile_bit) ? 2 : 0; 660 661 if (gearboy->IsCGB()) 662 { 663 if (emu_debug_tile_color_palette > 7) 664 { 665 pixel_data = (*sprite_palettes)[emu_debug_tile_color_palette - 8][pixel_data][1]; 666 } 667 else 668 { 669 pixel_data = (*bg_palettes)[emu_debug_tile_color_palette][pixel_data][1]; 670 } 671 debug_tile_buffers_565[b][pixel] = pixel_data; 672 } 673 else 674 { 675 u8 palette = memory->Retrieve(0xFF47 + emu_debug_tile_dmg_palette); 676 pixel_data = (palette >> (pixel_data << 1)) & 0x03; 677 debug_tile_buffers_565[b][pixel] = dmg_palette[pixel_data]; 678 } 679 } 680 } 681} 682 683static void update_debug_oam_buffers(void) 684{ 685 Memory* memory = gearboy->GetMemory(); 686 Video* video = gearboy->GetVideo(); 687 u16 address = 0xFE00; 688 u16* dmg_palette = gearboy->GetDMGInternalPalette(); 689 PaletteMatrix sprite_palettes = video->GetCGBSpritePalettes(); 690 u8 lcdc = memory->Retrieve(0xFF40); 691 bool sprites_16 = IsSetBit(lcdc, 2); 692 693 for (int s = 0; s < 40; s++) 694 { 695 u8 tile = memory->Retrieve(address + 2); 696 u8 flags = memory->Retrieve(address + 3); 697 int palette = IsSetBit(flags, 4) ? 1 : 0; 698 bool xflip = IsSetBit(flags, 5); 699 bool yflip = IsSetBit(flags, 6); 700 bool cgb_bank = IsSetBit(flags, 3); 701 int cgb_pal = flags & 0x07; 702 703 for (int pixel = 0; pixel < (8 * 16); pixel++) 704 { 705 u16 tile_addr = 0x8000 + (tile * 16); 706 707 int pixel_x = pixel & 0x7; 708 int pixel_y = pixel / 8; 709 710 u16 line_addr = tile_addr + (2 * pixel_y); 711 712 if (xflip) 713 pixel_x = 7 - pixel_x; 714 if (yflip) 715 line_addr = (sprites_16 ? 15 : 7) - line_addr; 716 717 u8 byte1 = 0; 718 u8 byte2 = 0; 719 720 if (gearboy->IsCGB() && cgb_bank) 721 { 722 byte1 = memory->ReadCGBLCDRAM(line_addr, true); 723 byte2 = memory->ReadCGBLCDRAM(line_addr + 1, true); 724 } 725 else 726 { 727 byte1 = memory->Retrieve(line_addr); 728 byte2 = memory->Retrieve(line_addr + 1); 729 } 730 731 int tile_bit = 0x1 << (7 - pixel_x); 732 int pixel_data = (byte1 & tile_bit) ? 1 : 0; 733 pixel_data |= (byte2 & tile_bit) ? 2 : 0; 734 735 if (gearboy->IsCGB()) 736 { 737 pixel_data = (*sprite_palettes)[cgb_pal][pixel_data][1]; 738 debug_oam_buffers_565[s][pixel] = pixel_data; 739 } 740 else 741 { 742 u8 final_palette = memory->Retrieve(0xFF48 + palette); 743 pixel_data = (final_palette >> (pixel_data << 1)) & 0x03; 744 debug_oam_buffers_565[s][pixel] = dmg_palette[pixel_data]; 745 } 746 } 747 748 address += 4; 749 } 750}