cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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}