idle

decompiled_code:
__int64 idle()
{
glutGet(700LL);
if ( save_state_called )
{
save_state_callback();
save_state_called = 0;
}
else if ( load_state_called )
{
load_state_callback();
load_state_called = 0;
}
return glutPostRedisplay();
}

canonical_decompiled_code:
__int64 func4()
{
glutGet(700LL);
if ( save_state_called )
{
func2();
save_state_called = 0;
}
else if ( load_state_called )
{
func3();
load_state_called = 0;
}
return glutPostRedisplay();
}

original_code:
void idle(void)
{
    int current_time = glutGet(0x02BC);
    int elapsed = current_time - last_frame;
    if(elapsed < target_elapsed) {
    }
    last_frame = current_time;
    if(save_state_called == 1) {
        save_state_callback();
        save_state_called = 0;
    } else if(load_state_called == 1) {
        load_state_callback();
        load_state_called = 0;
    }
    glutPostRedisplay();
}

canonical_original_code:
void idle()
{
    int current_time = glutGet(0x02BC);
    int elapsed = current_time - last_frame;
    if(elapsed < target_elapsed) {
    }
    last_frame = current_time;
    if(save_state_called == 1) {
        save_state_callback();
        save_state_called = 0;
    } else if(load_state_called == 1) {
        load_state_callback();
        load_state_called = 0;
    }
    glutPostRedisplay();
}

variable_types: elapsed int


processKeyboard

repo: tylerschloesser/cgbemu-core

decompiled_code:
__int64 __fastcall processKeyboard(int a1, unsigned __int8 a2)
{
__int64 result; // rax

if ( a1 == 113 )
exit(0);
if ( a1 <= 113 )
{
if ( a1 == 13 )
{
result = cgbemu_set_button_pressed(7LL, a2);
}
else if ( a1 == 32 )
{
result = cgbemu_set_button_pressed(6LL, a2);
}
}
else if ( a1 == 120 )
{
result = cgbemu_set_button_pressed(4LL, a2);
}
else if ( a1 == 122 )
{
result = cgbemu_set_button_pressed(5LL, a2);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(int a1, unsigned __int8 a2)
{
__int64 result; // rax

if ( a1 == 113 )
exit(0);
if ( a1 <= 113 )
{
if ( a1 == 13 )
{
result = cgbemu_set_button_pressed(7LL, a2);
}
else if ( a1 == 32 )
{
result = cgbemu_set_button_pressed(6LL, a2);
}
}
else if ( a1 == 120 )
{
result = cgbemu_set_button_pressed(4LL, a2);
}
else if ( a1 == 122 )
{
result = cgbemu_set_button_pressed(5LL, a2);
}
return result;
}

original_code:
void processKeyboard(int key, _Bool down)
{
    switch (key) {
        case 'z':
            cgbemu_set_button_pressed(B, down);
            break;
        case 'x':
            cgbemu_set_button_pressed(A, down);
            break;
        case 13:
            cgbemu_set_button_pressed(START, down);
            break;
        case ' ':
            cgbemu_set_button_pressed(SELECT, down);
            break;
        case 'q':
            exit(0);
        default:
            return;
    }
}

variable_types: key int

return_type: void


keyboard

decompiled_code:
__int64 __fastcall keyboard(unsigned __int8 a1)
{
return processKeyboard(a1, 1u);
}

canonical_decompiled_code:
__int64 __fastcall func6(unsigned __int8 a1)
{
return func5(a1, 1u);
}

original_code:
void keyboard(unsigned char key, int x, int y)
{
    processKeyboard(key, 1);
}

variable_types:
key
unsigned char

variable_types: x int

variable_types: y int


keyboardUp

decompiled_code:
__int64 __fastcall keyboardUp(unsigned __int8 a1)
{
return processKeyboard(a1, 0);
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned __int8 a1)
{
return func5(a1, 0);
}

original_code:
void keyboardUp(unsigned char key, int x, int y)
{
    processKeyboard(key, 0);
}


processSpecial

decompiled_code:
__int64 __fastcall processSpecial(int a1, unsigned __int8 a2)
{
__int64 result; // rax

if ( a1 == 101 )
return cgbemu_set_button_pressed(0LL, a2);
if ( a1 > 101 )
{
if ( a1 == 102 )
{
result = cgbemu_set_button_pressed(2LL, a2);
}
else if ( a1 == 103 )
{
result = cgbemu_set_button_pressed(1LL, a2);
}
}
else if ( a1 == 2 )
{
if ( !a2 )
load_state_called = 1;
}
else if ( a1 == 100 )
{
result = cgbemu_set_button_pressed(3LL, a2);
}
else if ( a1 == 1 && !a2 )
{
save_state_called = 1;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(int a1, unsigned __int8 a2)
{
__int64 result; // rax

if ( a1 == 101 )
return cgbemu_set_button_pressed(0LL, a2);
if ( a1 > 101 )
{
if ( a1 == 102 )
{
result = cgbemu_set_button_pressed(2LL, a2);
}
else if ( a1 == 103 )
{
result = cgbemu_set_button_pressed(1LL, a2);
}
}
else if ( a1 == 2 )
{
if ( !a2 )
load_state_called = 1;
}
else if ( a1 == 100 )
{
result = cgbemu_set_button_pressed(3LL, a2);
}
else if ( a1 == 1 && !a2 )
{
save_state_called = 1;
}
return result;
}

original_code:
void processSpecial(int key, _Bool down)
{
    switch(key) {
        case 0x0065:
            cgbemu_set_button_pressed(UP, down);
            break;
        case 0x0066:
            cgbemu_set_button_pressed(RIGHT, down);
            break;
        case 0x0067:
            cgbemu_set_button_pressed(DOWN, down);
            break;
        case 0x0064:
            cgbemu_set_button_pressed(LEFT, down);
            break;
        case 0x0001:
            if(!down)
                save_state_called = 1;
            break;
        case 0x0002:
            if(!down)
                load_state_called = 1;
            break;
        default:
            return;
    }
}


special

decompiled_code:
__int64 __fastcall special(int a1)
{
return processSpecial(a1, 1u);
}

canonical_decompiled_code:
__int64 __fastcall func9(int a1)
{
return func8(a1, 1u);
}

original_code:
void special(int key, int x, int y)
{
    processSpecial(key, 1);
}


specialUp

decompiled_code:
__int64 __fastcall specialUp(int a1)
{
return processSpecial(a1, 0);
}

canonical_decompiled_code:
__int64 __fastcall func10(int a1)
{
return func8(a1, 0);
}

original_code:
void specialUp(int key, int x, int y)
{
    processSpecial(key, 0);
}


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // er12
int v5[5]; // [rsp+Ch] [rbp-14h] BYREF

v5[0] = argc;
if ( argc == 2 )
{
v3 = initialize_cgbemu(argv[1], 0LL, envp);
if ( v3 )
{
v3 = 1;
}
else
{
screen_buffer = cgbemu_get_screen_buffer();
if ( screen_buffer )
{
glutInit(v5, argv);
glutInitDisplayMode(0LL);
glutInitWindowSize((unsigned int)window_width, (unsigned int)window_height);
glutInitWindowPosition(100LL, 100LL);
glutCreateWindow(*argv);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardUp);
glutSpecialFunc(special);
glutSpecialUpFunc(specialUp);
glutMainLoop();
}
else
{
v3 = 1;
fwrite("Failed to get screen buffer\n", 1uLL, 0x1CuLL, stderr);
}
}
}
else
{
v3 = 1;
puts("Invalid arguments");
}
return v3;
}

original_code:
int main(int argc, char** argv)
{
    if(argc != 2) {
        printf("Invalid arguments\n");
        return 1;
    }
    if(initialize_cgbemu(argv[1], ((void *)0)) != 0) {
        return 1;
    }
    screen_buffer = cgbemu_get_screen_buffer();
    if(screen_buffer == ((void *)0)) {
        fprintf(stderr, "Failed to get screen buffer\n");
        return 1;
    }
    glutInit(&argc, argv);
    glutInitDisplayMode (0x0000 | 0x0000);
    glutInitWindowSize (window_width, window_height);
    glutInitWindowPosition (100, 100);
    glutCreateWindow (argv[0]);
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutSpecialFunc(special);
    glutSpecialUpFunc(specialUp);
    glutMainLoop();
    return 0;
}

canonical_original_code:
int main(int argc, char **argv)
{
    if(argc != 2) {
        printf("Invalid arguments\n");
        return 1;
    }
    if(initialize_cgbemu(argv[1], ((void *)0)) != 0) {
        return 1;
    }
    screen_buffer = cgbemu_get_screen_buffer();
    if(screen_buffer == ((void *)0)) {
        fprintf(stderr, "Failed to get screen buffer\n");
        return 1;
    }
    glutInit(&argc, argv);
    glutInitDisplayMode (0x0000 | 0x0000);
    glutInitWindowSize (window_width, window_height);
    glutInitWindowPosition (100, 100);
    glutCreateWindow (argv[0]);
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutSpecialFunc(special);
    glutSpecialUpFunc(specialUp);
    glutMainLoop();
    return 0;
}

variable_types: argc int

variable_types:
argv
char **

return_type: int


decompiled_code:
size_t open_log()
{
if ( output_log )
_assert_fail("output_log == NULL", "debug.c", 0xEu, "open_log");
output_log = fopen("log.txt", "w");
if ( !output_log )
_assert_fail("output_log != NULL", "debug.c", 0x10u, "open_log");
return fwrite("log opened\n", 1uLL, 0xBuLL, stderr);
}

canonical_decompiled_code:
size_t func0()
{
if ( output_log )
_assert_fail("output_log == NULL", "debug.c", 0xEu, "open_log");
output_log = fopen("log.txt", "w");
if ( !output_log )
_assert_fail("output_log != NULL", "debug.c", 0x10u, "open_log");
return fwrite("log opened\n", 1uLL, 0xBuLL, stderr);
}

original_code:
void open_log()
{
    ((output_log == ((void *)0)) ? (void) (0) : __assert_fail ("output_log == NULL", "debug.c", 14, __extension__ __PRETTY_FUNCTION__));
    output_log = fopen("log.txt", "w");
    ((output_log != ((void *)0)) ? (void) (0) : __assert_fail ("output_log != NULL", "debug.c", 16, __extension__ __PRETTY_FUNCTION__));
    fprintf(stderr,"log opened\n");
}


decompiled_code:
int close_log()
{
int result; // eax

if ( output_log )
result = fclose(output_log);
return result;
}

canonical_decompiled_code:
int func1()
{
int result; // eax

if ( output_log )
result = fclose(output_log);
return result;
}

original_code:
void close_log()
{
    if(output_log) {
        fclose(output_log);
    }
}


decompiled_code:
int write_log(char *format, ...)
{
gcc_va_list arg; // [rsp+8h] [rbp-C8h] BYREF

va_start(arg, format);
return vfprintf(output_log, format, arg);
}

canonical_decompiled_code:
int func2(char *format, ...)
{
gcc_va_list arg; // [rsp+8h] [rbp-C8h] BYREF

va_start(arg, format);
return vfprintf(output_log, format, arg);
}

original_code:
void write_log( const char* format, ... )
{
    va_list args;
    __builtin_va_start(args,format);
    vfprintf(output_log, format, args);
    __builtin_va_end(args);
}

canonical_original_code:
void write_log(char *format, ...)
{
    __builtin_va_list args;
    __builtin_va_start(args,format);
    vfprintf(output_log, format, args);
    __builtin_va_end(args);
}

variable_types:
format
char *


decompiled_code:
__int64 __fastcall update_cartridge_banking(__int64 a1)
{
__int64 result; // rax

if ( !a1 )
_assert_fail("cartridge != NULL", "memory.c", 0x21u, "update_cartridge_banking");
if ( *(_BYTE *)(a1 + 105) )
{
*(_WORD *)(a1 + 80) &= 0x1Fu;
cartridge_update_selected_rom();
result = cartridge_update_selected_ram();
}
else
{
*(_WORD *)(a1 + 80) |= 32 * *(_WORD *)(a1 + 82);
result = cartridge_update_selected_rom();
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(__int64 a1)
{
__int64 result; // rax

if ( !a1 )
_assert_fail("cartridge != NULL", "memory.c", 0x21u, "update_cartridge_banking");
if ( *(_BYTE *)(a1 + 105) )
{
*(_WORD *)(a1 + 80) &= 0x1Fu;
cartridge_update_selected_rom();
result = cartridge_update_selected_ram();
}
else
{
*(_WORD *)(a1 + 80) |= 32 * *(_WORD *)(a1 + 82);
result = cartridge_update_selected_rom();
}
return result;
}

original_code:
void update_cartridge_banking(Cartridge* cartridge) {
    ((cartridge != ((void *)0)) ? (void) (0) : __assert_fail ("cartridge != NULL", "memory.c", 33, __extension__ __PRETTY_FUNCTION__));
    if(cartridge->banking_mode == 0x00) {
        cartridge->selected_rom_bank |=
            (cartridge->selected_ram_bank << 5);
        cartridge_update_selected_rom();
    } else {
        cartridge->selected_rom_bank &= 0x1F;
        cartridge_update_selected_rom();
        cartridge_update_selected_ram();
    }
}

canonical_original_code:
void update_cartridge_banking(struct Cartridge *cartridge) {
    ((cartridge != ((void *)0)) ? (void) (0) : __assert_fail ("cartridge != NULL", "memory.c", 33, __extension__ __PRETTY_FUNCTION__));
    if(cartridge->banking_mode == 0x00) {
        cartridge->selected_rom_bank |=
            (cartridge->selected_ram_bank << 5);
        cartridge_update_selected_rom();
    } else {
        cartridge->selected_rom_bank &= 0x1F;
        cartridge_update_selected_rom();
        cartridge_update_selected_ram();
    }
}

variable_types: struct Cartridge { enum CartridgeId { ID_ROM_ONLY=0, ID_MBC1=1, ID_MBC1_RAM=2, ID_MBC1_RAM_BATTERY=3, ID_MBC2=4, ID_MBC2_BATTERY=5, ID_ROM_RAM=6, ID_ROM_RAM_BATTERY=7, ID_MMM01=8, ID_MMM01_RAM=9, ID_MMM01_RAM_BATTERY=10, ID_MBC3_TIMER_BATTERY=11, ID_MBC3_TIMER_RAM_BATTERY=12, ID_MBC3=13, ID_MBC3_RAM=14, ID_MBC3_RAM_BATTERY=15, ID_MBC4=16, ID_MBC4_RAM=17, ID_MBC4_RAM_BATTERY=18, ID_MBC5=19, ID_MBC5_RAM=20, ID_MBC5_RAM_BATTERY=21, ID_MBC5_RUMBLE=22, ID_MBC5_RUMBLE_RAM=23, ID_MBC5_RUMBLE_RAM_BATTERY=24, ID_POCKET_CAMERA=25, ID_BANDAI_TAMA5=26, ID_HUC3=27, ID_HUC1_RAM_BATTERY=28 } id; char name[32]; enum MemoryBankController { NONE=0, MBC1=1, MBC2=2, MBC3=3, MBC4=4, MBC5=5, UNSUPPORTED=6 } mbc; unsigned char *rom; unsigned char *ram; unsigned int ram_size; unsigned int rom_size; unsigned char *selected_rom; unsigned char *selected_ram; unsigned short selected_rom_bank; unsigned short selected_ram_bank; unsigned char (*read)(unsigned short); void (*write)(unsigned short, unsigned char); _Bool ram_enabled; unsigned char banking_mode; _Bool has_battery; unsigned char rtc_register; } *

user_defined_types: struct Cartridge { enum CartridgeId id; char name[32]; enum MemoryBankController mbc; unsigned char *rom; unsigned char *ram; unsigned int ram_size; unsigned int rom_size; unsigned char *selected_rom; unsigned char *selected_ram; unsigned short selected_rom_bank; unsigned short selected_ram_bank; unsigned char (*read)(unsigned short); void (*write)(unsigned short, unsigned char); _Bool ram_enabled; unsigned char banking_mode; _Bool has_battery; unsigned char rtc_register; }


decompiled_code:
void __noreturn mbc0_write()
{
_assert_fail("false", "memory.c", 0x37u, "mbc0_write");
}

canonical_decompiled_code:
void __noreturn func1()
{
_assert_fail("false", "memory.c", 0x37u, "mbc0_write");
}

original_code:
void mbc0_write(uint16_t location, uint8_t data) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 55, __extension__ __PRETTY_FUNCTION__));
}

canonical_original_code:
void mbc0_write(unsigned short location, unsigned char data) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 55, __extension__ __PRETTY_FUNCTION__));
}

variable_types:
location
unsigned short

variable_types:
data
unsigned char


decompiled_code:
void __noreturn mbc0_read()
{
_assert_fail("false", "memory.c", 0x3Bu, "mbc0_read");
}

canonical_decompiled_code:
void __noreturn func2()
{
_assert_fail("false", "memory.c", 0x3Bu, "mbc0_read");
}

original_code:
uint8_t mbc0_read(uint16_t location) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 59, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

canonical_original_code:
unsigned char mbc0_read(unsigned short location) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 59, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

return_type: unsigned char


decompiled_code:
__int64 __fastcall mbc1_write(unsigned __int16 a1, char a2)
{
__int64 result; // rax
int v3; // esi
__int64 v4; // rdi
__int64 v5; // rdi
__int64 v6; // rdi

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
case 3:
v3 = a2 & 0x1F;
v4 = cartridge;
if ( !v3 )
LOBYTE(v3) = 1;
*(_WORD *)(cartridge + 80LL) = (unsigned __int8)v3;
result = update_cartridge_banking(v4);
break;
case 4:
case 5:
v5 = cartridge;
*(_WORD *)(cartridge + 82LL) = a2 & 3;
result = update_cartridge_banking(v5);
break;
case 6:
case 7:
v6 = cartridge;
*(_BYTE *)(cartridge + 105LL) = a2 & 1;
result = update_cartridge_banking(v6);
break;
case 8:
case 9:
result = *(_QWORD *)(gb + 51616LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 10:
case 11:
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0x5Fu, "mbc1_write");
result = *(_QWORD *)(cartridge + 72LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 12:
result = gb;
*(_BYTE *)(gb + (a1 & 0xFFF)) = a2;
break;
case 13:
result = *(_QWORD *)(gb + 51624LL);
*(_BYTE *)(result + (a1 & 0xFFF)) = a2;
break;
default:
return result;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(unsigned __int16 a1, char a2)
{
__int64 result; // rax
int v3; // esi
__int64 v4; // rdi
__int64 v5; // rdi
__int64 v6; // rdi

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
case 3:
v3 = a2 & 0x1F;
v4 = cartridge;
if ( !v3 )
LOBYTE(v3) = 1;
*(_WORD *)(cartridge + 80LL) = (unsigned __int8)v3;
result = func0(v4);
break;
case 4:
case 5:
v5 = cartridge;
*(_WORD *)(cartridge + 82LL) = a2 & 3;
result = func0(v5);
break;
case 6:
case 7:
v6 = cartridge;
*(_BYTE *)(cartridge + 105LL) = a2 & 1;
result = func0(v6);
break;
case 8:
case 9:
result = *(_QWORD *)(gb + 51616LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 10:
case 11:
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0x5Fu, "mbc1_write");
result = *(_QWORD *)(cartridge + 72LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 12:
result = gb;
*(_BYTE *)(gb + (a1 & 0xFFF)) = a2;
break;
case 13:
result = *(_QWORD *)(gb + 51624LL);
*(_BYTE *)(result + (a1 & 0xFFF)) = a2;
break;
default:
return result;
}
return result;
}

original_code:
void mbc1_write(uint16_t location, uint8_t data) {
    uint8_t location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
            cartridge->ram_enabled = ((data & 0x0A) == 0x0A);
            break;
        case 0x2:
        case 0x3:
            data &= 0x1F;
            if(data == 0x00) data = 0x01;
            cartridge->selected_rom_bank = data;
            update_cartridge_banking(cartridge);
            break;
        case 0x4:
        case 0x5:
            cartridge->selected_ram_bank = (data & 0x03);
            update_cartridge_banking(cartridge);
            break;
        case 0x6:
        case 0x7:
            cartridge->banking_mode = (data & 0x01);
            update_cartridge_banking(cartridge);
            break;
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            gb->selected_vram[location] = data;
            break;
        case 0xA:
        case 0xB:
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 95, __extension__ __PRETTY_FUNCTION__));
            location &= 0x1FFF;
            cartridge->selected_ram[location] = data;
            break;
        case 0xC:
            location &= 0x0FFF;
            gb->ram[location] = data;
            break;
        case 0xD:
            location &= 0x0FFF;
            gb->selected_ram[location] = data;
            break;
    }
}

canonical_original_code:
void mbc1_write(unsigned short location, unsigned char data) {
    unsigned char location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
            cartridge->ram_enabled = ((data & 0x0A) == 0x0A);
            break;
        case 0x2:
        case 0x3:
            data &= 0x1F;
            if(data == 0x00) data = 0x01;
            cartridge->selected_rom_bank = data;
            update_cartridge_banking(cartridge);
            break;
        case 0x4:
        case 0x5:
            cartridge->selected_ram_bank = (data & 0x03);
            update_cartridge_banking(cartridge);
            break;
        case 0x6:
        case 0x7:
            cartridge->banking_mode = (data & 0x01);
            update_cartridge_banking(cartridge);
            break;
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            gb->selected_vram[location] = data;
            break;
        case 0xA:
        case 0xB:
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 95, __extension__ __PRETTY_FUNCTION__));
            location &= 0x1FFF;
            cartridge->selected_ram[location] = data;
            break;
        case 0xC:
            location &= 0x0FFF;
            gb->ram[location] = data;
            break;
        case 0xD:
            location &= 0x0FFF;
            gb->selected_ram[location] = data;
            break;
    }
}


decompiled_code:
__int64 __fastcall mbc1_read(unsigned __int16 a1)
{
__int64 result; // rax

switch ( a1 >> 12 )
{
case 0:
case 1:
case 2:
case 3:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 40LL) + (a1 & 0x3FFF));
break;
case 4:
case 5:
case 6:
case 7:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 64LL) + (a1 & 0x3FFF));
break;
case 8:
case 9:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51616LL) + (a1 & 0x1FFF));
break;
case 0xA:
case 0xB:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 72LL) + (a1 & 0x1FFF));
break;
case 0xC:
result = *(unsigned __int8 *)(gb + (a1 & 0xFFF));
break;
case 0xD:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51624LL) + (a1 & 0xFFF));
break;
default:
_assert_fail("false", "memory.c", 0x91u, "mbc1_read");
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(unsigned __int16 a1)
{
__int64 result; // rax

switch ( a1 >> 12 )
{
case 0:
case 1:
case 2:
case 3:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 40LL) + (a1 & 0x3FFF));
break;
case 4:
case 5:
case 6:
case 7:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 64LL) + (a1 & 0x3FFF));
break;
case 8:
case 9:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51616LL) + (a1 & 0x1FFF));
break;
case 0xA:
case 0xB:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 72LL) + (a1 & 0x1FFF));
break;
case 0xC:
result = *(unsigned __int8 *)(gb + (a1 & 0xFFF));
break;
case 0xD:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51624LL) + (a1 & 0xFFF));
break;
default:
_assert_fail("false", "memory.c", 0x91u, "mbc1_read");
}
return result;
}

original_code:
uint8_t mbc1_read(uint16_t location) {
    uint8_t location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
        case 0x2:
        case 0x3:
        {
            location &= 0x3FFF;
            return cartridge->rom[location];
        }
        case 0x4:
        case 0x5:
        case 0x6:
        case 0x7:
            location &= 0x3FFF;
            return cartridge->selected_rom[location];
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            return gb->selected_vram[location];
        case 0xA:
        case 0xB:
            location &= 0x1FFF;
            return cartridge->selected_ram[location];
        case 0xC:
            location &= 0x0FFF;
            return gb->ram[location];
        case 0xD:
            location &= 0x0FFF;
            return gb->selected_ram[location];
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 145, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

canonical_original_code:
unsigned char mbc1_read(unsigned short location) {
    unsigned char location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
        case 0x2:
        case 0x3:
        {
            location &= 0x3FFF;
            return cartridge->rom[location];
        }
        case 0x4:
        case 0x5:
        case 0x6:
        case 0x7:
            location &= 0x3FFF;
            return cartridge->selected_rom[location];
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            return gb->selected_vram[location];
        case 0xA:
        case 0xB:
            location &= 0x1FFF;
            return cartridge->selected_ram[location];
        case 0xC:
            location &= 0x0FFF;
            return gb->ram[location];
        case 0xD:
            location &= 0x0FFF;
            return gb->selected_ram[location];
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 145, __extension__ __PRETTY_FUNCTION__));
    return 0;
}


decompiled_code:
void __noreturn mbc2_write()
{
_assert_fail("false", "memory.c", 0x98u, "mbc2_write");
}

canonical_decompiled_code:
void __noreturn func5()
{
_assert_fail("false", "memory.c", 0x98u, "mbc2_write");
}

original_code:
void mbc2_write(uint16_t location, uint8_t data) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 152, __extension__ __PRETTY_FUNCTION__));
}

canonical_original_code:
void mbc2_write(unsigned short location, unsigned char data) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 152, __extension__ __PRETTY_FUNCTION__));
}


decompiled_code:
void __noreturn mbc2_read()
{
_assert_fail("false", "memory.c", 0x9Du, "mbc2_read");
}

canonical_decompiled_code:
void __noreturn func6()
{
_assert_fail("false", "memory.c", 0x9Du, "mbc2_read");
}

original_code:
uint8_t mbc2_read(uint16_t location) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 157, __extension__ __PRETTY_FUNCTION__));
}

canonical_original_code:
unsigned char mbc2_read(unsigned short location) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 157, __extension__ __PRETTY_FUNCTION__));
}


decompiled_code:
__int64 __fastcall mbc3_write(unsigned __int16 a1, unsigned __int8 a2)
{
__int64 result; // rax
int v3; // esi

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
case 3:
v3 = a2 & 0x7F;
if ( !v3 )
LOBYTE(v3) = 1;
*(_WORD *)(cartridge + 80LL) = (unsigned __int8)v3;
result = cartridge_update_selected_rom();
break;
case 4:
case 5:
result = cartridge;
if ( a2 <= 3u )
{
*(_BYTE *)(cartridge + 107LL) = 0;
*(_WORD *)(result + 82) = a2;
result = cartridge_update_selected_ram();
}
else
{
*(_BYTE *)(cartridge + 107LL) = a2;
}
break;
case 8:
case 9:
result = *(_QWORD *)(gb + 51616LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 10:
case 11:
result = cartridge;
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0xC7u, "mbc3_write");
if ( !*(_BYTE *)(cartridge + 107LL) )
{
result = *(_QWORD *)(cartridge + 72LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
}
break;
case 12:
result = gb;
*(_BYTE *)(gb + (a1 & 0xFFF)) = a2;
break;
case 13:
result = *(_QWORD *)(gb + 51624LL);
*(_BYTE *)(result + (a1 & 0xFFF)) = a2;
break;
default:
return result;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned __int16 a1, unsigned __int8 a2)
{
__int64 result; // rax
int v3; // esi

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
case 3:
v3 = a2 & 0x7F;
if ( !v3 )
LOBYTE(v3) = 1;
*(_WORD *)(cartridge + 80LL) = (unsigned __int8)v3;
result = cartridge_update_selected_rom();
break;
case 4:
case 5:
result = cartridge;
if ( a2 <= 3u )
{
*(_BYTE *)(cartridge + 107LL) = 0;
*(_WORD *)(result + 82) = a2;
result = cartridge_update_selected_ram();
}
else
{
*(_BYTE *)(cartridge + 107LL) = a2;
}
break;
case 8:
case 9:
result = *(_QWORD *)(gb + 51616LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 10:
case 11:
result = cartridge;
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0xC7u, "mbc3_write");
if ( !*(_BYTE *)(cartridge + 107LL) )
{
result = *(_QWORD *)(cartridge + 72LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
}
break;
case 12:
result = gb;
*(_BYTE *)(gb + (a1 & 0xFFF)) = a2;
break;
case 13:
result = *(_QWORD *)(gb + 51624LL);
*(_BYTE *)(result + (a1 & 0xFFF)) = a2;
break;
default:
return result;
}
return result;
}

original_code:
void mbc3_write(uint16_t location, uint8_t data) {
    uint8_t location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
            cartridge->ram_enabled = ((data & 0x0A) == 0x0A);
            break;
        case 0x2:
        case 0x3:
            data &= 0x7F;
            if(data == 0x00) data = 0x01;
            cartridge->selected_rom_bank = data;
            cartridge_update_selected_rom();
            break;
        case 0x4:
        case 0x5:
            if(data > 0x03) {
                cartridge->rtc_register = data;
                break;
            }
            cartridge->rtc_register = 0x00;
            cartridge->selected_ram_bank = (data & 0x03);
            cartridge_update_selected_ram();
            break;
        case 0x6:
        case 0x7:
            break;
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            gb->selected_vram[location] = data;
            break;
        case 0xA:
        case 0xB:
        {
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 199, __extension__ __PRETTY_FUNCTION__));
            if(cartridge->rtc_register) {
                break;
            }
            location &= 0x1FFF;
            cartridge->selected_ram[location] = data;
            break;
        }
        case 0xC:
            location &= 0x0FFF;
            gb->ram[location] = data;
            break;
        case 0xD:
            location &= 0x0FFF;
            gb->selected_ram[location] = data;
            break;
    }
}

canonical_original_code:
void mbc3_write(unsigned short location, unsigned char data) {
    unsigned char location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
            cartridge->ram_enabled = ((data & 0x0A) == 0x0A);
            break;
        case 0x2:
        case 0x3:
            data &= 0x7F;
            if(data == 0x00) data = 0x01;
            cartridge->selected_rom_bank = data;
            cartridge_update_selected_rom();
            break;
        case 0x4:
        case 0x5:
            if(data > 0x03) {
                cartridge->rtc_register = data;
                break;
            }
            cartridge->rtc_register = 0x00;
            cartridge->selected_ram_bank = (data & 0x03);
            cartridge_update_selected_ram();
            break;
        case 0x6:
        case 0x7:
            break;
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            gb->selected_vram[location] = data;
            break;
        case 0xA:
        case 0xB:
        {
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 199, __extension__ __PRETTY_FUNCTION__));
            if(cartridge->rtc_register) {
                break;
            }
            location &= 0x1FFF;
            cartridge->selected_ram[location] = data;
            break;
        }
        case 0xC:
            location &= 0x0FFF;
            gb->ram[location] = data;
            break;
        case 0xD:
            location &= 0x0FFF;
            gb->selected_ram[location] = data;
            break;
    }
}


decompiled_code:
__int64 __fastcall mbc3_read(unsigned __int16 a1)
{
__int64 result; // rax

switch ( a1 >> 12 )
{
case 0:
case 1:
case 2:
case 3:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 40LL) + (a1 & 0x3FFF));
break;
case 4:
case 5:
case 6:
case 7:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 64LL) + (a1 & 0x3FFF));
break;
case 8:
case 9:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51616LL) + (a1 & 0x1FFF));
break;
case 0xA:
case 0xB:
result = 0LL;
if ( !*(_BYTE *)(cartridge + 107LL) )
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 72LL) + (a1 & 0x1FFF));
break;
case 0xC:
result = *(unsigned __int8 *)(gb + (a1 & 0xFFF));
break;
case 0xD:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51624LL) + (a1 & 0xFFF));
break;
default:
_assert_fail("false", "memory.c", 0x102u, "mbc3_read");
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(unsigned __int16 a1)
{
__int64 result; // rax

switch ( a1 >> 12 )
{
case 0:
case 1:
case 2:
case 3:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 40LL) + (a1 & 0x3FFF));
break;
case 4:
case 5:
case 6:
case 7:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 64LL) + (a1 & 0x3FFF));
break;
case 8:
case 9:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51616LL) + (a1 & 0x1FFF));
break;
case 0xA:
case 0xB:
result = 0LL;
if ( !*(_BYTE *)(cartridge + 107LL) )
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 72LL) + (a1 & 0x1FFF));
break;
case 0xC:
result = *(unsigned __int8 *)(gb + (a1 & 0xFFF));
break;
case 0xD:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51624LL) + (a1 & 0xFFF));
break;
default:
_assert_fail("false", "memory.c", 0x102u, "mbc3_read");
}
return result;
}

original_code:
uint8_t mbc3_read(uint16_t location) {
    uint8_t location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
        case 0x2:
        case 0x3:
        {
            location &= 0x3FFF;
            return cartridge->rom[location];
        }
        case 0x4:
        case 0x5:
        case 0x6:
        case 0x7:
            location &= 0x3FFF;
            return cartridge->selected_rom[location];
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            return gb->selected_vram[location];
        case 0xA:
        case 0xB:
            if(cartridge->rtc_register) {
                return 0x00;
            }
            location &= 0x1FFF;
            return cartridge->selected_ram[location];
        case 0xC:
            location &= 0x0FFF;
            return gb->ram[location];
        case 0xD:
            location &= 0x0FFF;
            return gb->selected_ram[location];
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 258, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

canonical_original_code:
unsigned char mbc3_read(unsigned short location) {
    unsigned char location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
        case 0x2:
        case 0x3:
        {
            location &= 0x3FFF;
            return cartridge->rom[location];
        }
        case 0x4:
        case 0x5:
        case 0x6:
        case 0x7:
            location &= 0x3FFF;
            return cartridge->selected_rom[location];
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            return gb->selected_vram[location];
        case 0xA:
        case 0xB:
            if(cartridge->rtc_register) {
                return 0x00;
            }
            location &= 0x1FFF;
            return cartridge->selected_ram[location];
        case 0xC:
            location &= 0x0FFF;
            return gb->ram[location];
        case 0xD:
            location &= 0x0FFF;
            return gb->selected_ram[location];
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 258, __extension__ __PRETTY_FUNCTION__));
    return 0;
}


decompiled_code:
void __noreturn mbc4_write()
{
_assert_fail("false", "memory.c", 0x108u, "mbc4_write");
}

canonical_decompiled_code:
void __noreturn func9()
{
_assert_fail("false", "memory.c", 0x108u, "mbc4_write");
}

original_code:
void mbc4_write(uint16_t location, uint8_t data) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 264, __extension__ __PRETTY_FUNCTION__));
}

canonical_original_code:
void mbc4_write(unsigned short location, unsigned char data) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 264, __extension__ __PRETTY_FUNCTION__));
}


decompiled_code:
void __noreturn mbc4_read()
{
_assert_fail("false", "memory.c", 0x10Du, "mbc4_read");
}

canonical_decompiled_code:
void __noreturn func10()
{
_assert_fail("false", "memory.c", 0x10Du, "mbc4_read");
}

original_code:
uint8_t mbc4_read(uint16_t location) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 269, __extension__ __PRETTY_FUNCTION__));
}

canonical_original_code:
unsigned char mbc4_read(unsigned short location) {
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 269, __extension__ __PRETTY_FUNCTION__));
}


decompiled_code:
__int64 __fastcall mbc5_write(unsigned __int16 a1, char a2)
{
__int64 result; // rax

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
*(_BYTE *)(cartridge + 80LL) = a2;
result = cartridge_update_selected_rom();
break;
case 3:
*(_BYTE *)(cartridge + 81LL) = a2 & 1;
result = cartridge_update_selected_rom();
break;
case 4:
case 5:
*(_WORD *)(cartridge + 82LL) = a2 & 0xF;
result = cartridge_update_selected_ram();
break;
case 8:
case 9:
result = *(_QWORD *)(gb + 51616LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 10:
case 11:
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0x132u, "mbc5_write");
result = *(_QWORD *)(cartridge + 72LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 12:
result = gb;
*(_BYTE *)(gb + (a1 & 0xFFF)) = a2;
break;
case 13:
result = *(_QWORD *)(gb + 51624LL);
*(_BYTE *)(result + (a1 & 0xFFF)) = a2;
break;
default:
return result;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func11(unsigned __int16 a1, char a2)
{
__int64 result; // rax

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
*(_BYTE *)(cartridge + 80LL) = a2;
result = cartridge_update_selected_rom();
break;
case 3:
*(_BYTE *)(cartridge + 81LL) = a2 & 1;
result = cartridge_update_selected_rom();
break;
case 4:
case 5:
*(_WORD *)(cartridge + 82LL) = a2 & 0xF;
result = cartridge_update_selected_ram();
break;
case 8:
case 9:
result = *(_QWORD *)(gb + 51616LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 10:
case 11:
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0x132u, "mbc5_write");
result = *(_QWORD *)(cartridge + 72LL);
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
break;
case 12:
result = gb;
*(_BYTE *)(gb + (a1 & 0xFFF)) = a2;
break;
case 13:
result = *(_QWORD *)(gb + 51624LL);
*(_BYTE *)(result + (a1 & 0xFFF)) = a2;
break;
default:
return result;
}
return result;
}

original_code:
void mbc5_write(uint16_t location, uint8_t data) {
    uint8_t location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
            cartridge->ram_enabled = ((data & 0x0A) == 0x0A);
            break;
        case 0x2:
            cartridge->selected_rom_bank &= 0xFF00;
            cartridge->selected_rom_bank |= data;
            cartridge_update_selected_rom();
            break;
        case 0x3:
            cartridge->selected_rom_bank &= 0x00FF;
            cartridge->selected_rom_bank |= ((data & 0x1) << 8);
            cartridge_update_selected_rom();
            break;
        case 0x4:
        case 0x5:
            cartridge->selected_ram_bank = (data & 0x0F);
            cartridge_update_selected_ram();
            break;
        case 0x6:
        case 0x7:
            break;
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            gb->selected_vram[location] = data;
            break;
        case 0xA:
        case 0xB:
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 306, __extension__ __PRETTY_FUNCTION__));
            location &= 0x1FFF;
            cartridge->selected_ram[location] = data;
            break;
        case 0xC:
            location &= 0x0FFF;
            gb->ram[location] = data;
            break;
        case 0xD:
            location &= 0x0FFF;
            gb->selected_ram[location] = data;
            break;
    }
}

canonical_original_code:
void mbc5_write(unsigned short location, unsigned char data) {
    unsigned char location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
            cartridge->ram_enabled = ((data & 0x0A) == 0x0A);
            break;
        case 0x2:
            cartridge->selected_rom_bank &= 0xFF00;
            cartridge->selected_rom_bank |= data;
            cartridge_update_selected_rom();
            break;
        case 0x3:
            cartridge->selected_rom_bank &= 0x00FF;
            cartridge->selected_rom_bank |= ((data & 0x1) << 8);
            cartridge_update_selected_rom();
            break;
        case 0x4:
        case 0x5:
            cartridge->selected_ram_bank = (data & 0x0F);
            cartridge_update_selected_ram();
            break;
        case 0x6:
        case 0x7:
            break;
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            gb->selected_vram[location] = data;
            break;
        case 0xA:
        case 0xB:
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 306, __extension__ __PRETTY_FUNCTION__));
            location &= 0x1FFF;
            cartridge->selected_ram[location] = data;
            break;
        case 0xC:
            location &= 0x0FFF;
            gb->ram[location] = data;
            break;
        case 0xD:
            location &= 0x0FFF;
            gb->selected_ram[location] = data;
            break;
    }
}


decompiled_code:
__int64 __fastcall mbc5_read(unsigned __int16 a1)
{
__int64 result; // rax

switch ( a1 >> 12 )
{
case 0:
case 1:
case 2:
case 3:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 40LL) + (a1 & 0x3FFF));
break;
case 4:
case 5:
case 6:
case 7:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 64LL) + (a1 & 0x3FFF));
break;
case 8:
case 9:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51616LL) + (a1 & 0x1FFF));
break;
case 0xA:
case 0xB:
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0x15Au, "mbc5_read");
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 72LL) + (a1 & 0x1FFF));
break;
case 0xC:
result = *(unsigned __int8 *)(gb + (a1 & 0xFFF));
break;
case 0xD:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51624LL) + (a1 & 0xFFF));
break;
default:
_assert_fail("false", "memory.c", 0x166u, "mbc5_read");
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func12(unsigned __int16 a1)
{
__int64 result; // rax

switch ( a1 >> 12 )
{
case 0:
case 1:
case 2:
case 3:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 40LL) + (a1 & 0x3FFF));
break;
case 4:
case 5:
case 6:
case 7:
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 64LL) + (a1 & 0x3FFF));
break;
case 8:
case 9:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51616LL) + (a1 & 0x1FFF));
break;
case 0xA:
case 0xB:
if ( !*(_BYTE *)(cartridge + 104LL) )
_assert_fail("cartridge->ram_enabled == true", "memory.c", 0x15Au, "mbc5_read");
result = *(unsigned __int8 *)(*(_QWORD *)(cartridge + 72LL) + (a1 & 0x1FFF));
break;
case 0xC:
result = *(unsigned __int8 *)(gb + (a1 & 0xFFF));
break;
case 0xD:
result = *(unsigned __int8 *)(*(_QWORD *)(gb + 51624LL) + (a1 & 0xFFF));
break;
default:
_assert_fail("false", "memory.c", 0x166u, "mbc5_read");
}
return result;
}

original_code:
uint8_t mbc5_read(uint16_t location) {
    uint8_t location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
        case 0x2:
        case 0x3:
        {
            location &= 0x3FFF;
            return cartridge->rom[location];
        }
        case 0x4:
        case 0x5:
        case 0x6:
        case 0x7:
            location &= 0x3FFF;
            return cartridge->selected_rom[location];
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            return gb->selected_vram[location];
        case 0xA:
        case 0xB:
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 346, __extension__ __PRETTY_FUNCTION__));
            location &= 0x1FFF;
            return cartridge->selected_ram[location];
        case 0xC:
            location &= 0x0FFF;
            return gb->ram[location];
        case 0xD:
            location &= 0x0FFF;
            return gb->selected_ram[location];
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 358, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

canonical_original_code:
unsigned char mbc5_read(unsigned short location) {
    unsigned char location_hi = ((location & 0xF000) >> 12);
    switch(location_hi) {
        case 0x0:
        case 0x1:
        case 0x2:
        case 0x3:
        {
            location &= 0x3FFF;
            return cartridge->rom[location];
        }
        case 0x4:
        case 0x5:
        case 0x6:
        case 0x7:
            location &= 0x3FFF;
            return cartridge->selected_rom[location];
        case 0x8:
        case 0x9:
            location &= 0x1FFF;
            return gb->selected_vram[location];
        case 0xA:
        case 0xB:
            ((cartridge->ram_enabled == 1) ? (void) (0) : __assert_fail ("cartridge->ram_enabled == true", "memory.c", 346, __extension__ __PRETTY_FUNCTION__));
            location &= 0x1FFF;
            return cartridge->selected_ram[location];
        case 0xC:
            location &= 0x0FFF;
            return gb->ram[location];
        case 0xD:
            location &= 0x0FFF;
            return gb->selected_ram[location];
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 358, __extension__ __PRETTY_FUNCTION__));
    return 0;
}


decompiled_code:
__int64 __fastcall memory_read(unsigned __int16 a1)
{
__int64 result; // rax

while ( 1 )
{
if ( a1 <= 0xDFFFu )
return (*(__int64 (__fastcall **)(_QWORD))(cartridge + 88LL))(a1);
if ( a1 > 0xFDFFu )
break;
a1 -= 0x2000;
}
if ( a1 <= 0xFE9Fu )
return *(unsigned __int8 *)(gb + a1 - 65024 + 49152LL);
if ( a1 <= 0xFEFFu )
return 0LL;
if ( a1 > 0xFF7Fu )
{
if ( a1 == 0xFFFF )
result = *(unsigned __int8 *)(gb + 52015LL);
else
result = *(unsigned __int8 *)(gb + a1 - 65408 + 51760LL);
}
else if ( a1 == 0xFF00 )
{
result = get_joypad_state();
}
else
{
result = *(unsigned __int8 *)(gb + a1 - 65280 + 51887LL);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func13(unsigned __int16 a1)
{
__int64 result; // rax

while ( 1 )
{
if ( a1 <= 0xDFFFu )
return (*(__int64 (__fastcall **)(_QWORD))(cartridge + 88LL))(a1);
if ( a1 > 0xFDFFu )
break;
a1 -= 0x2000;
}
if ( a1 <= 0xFE9Fu )
return *(unsigned __int8 *)(gb + a1 - 65024 + 49152LL);
if ( a1 <= 0xFEFFu )
return 0LL;
if ( a1 > 0xFF7Fu )
{
if ( a1 == 0xFFFF )
result = *(unsigned __int8 *)(gb + 52015LL);
else
result = *(unsigned __int8 *)(gb + a1 - 65408 + 51760LL);
}
else if ( a1 == 0xFF00 )
{
result = get_joypad_state();
}
else
{
result = *(unsigned __int8 *)(gb + a1 - 65280 + 51887LL);
}
return result;
}

original_code:
uint8_t memory_read(uint16_t location) {
    if(location < 0xE000) {
        return cartridge->read(location);
    }
    else if (location < 0x10000)
    {
        if(location < 0xFE00)
        {
            return memory_read( location - 0x2000 );
        }
        else if(location < 0xFEA0)
        {
            int offset = 0xFE00;
            return gb->oam[location - offset];
        }
        else if(location < 0xFF00)
        {
            return 0;
        }
        else if(location < 0xFF80)
        {
            int offset = 0xFF00;
            switch(location - offset)
            {
                case P1:
                {
                    u8 joypad_state = get_joypad_state();
                    return joypad_state;
                }
            }
            return gb->hw_registers[location - offset];
        }
        else if(location < 0xFFFF) {
            return gb->hram[location - 0xFF80];
        } else if (location == 0xFFFF) {
            return gb->ie_register;
        } else {
            ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 637, __extension__ __PRETTY_FUNCTION__));
        }
    }
    else
    {
        return 0;
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 644, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

canonical_original_code:
unsigned char memory_read(unsigned short location) {
    if(location < 0xE000) {
        return cartridge->read(location);
    }
    else if (location < 0x10000)
    {
        if(location < 0xFE00)
        {
            return memory_read( location - 0x2000 );
        }
        else if(location < 0xFEA0)
        {
            int offset = 0xFE00;
            return gb->oam[location - offset];
        }
        else if(location < 0xFF00)
        {
            return 0;
        }
        else if(location < 0xFF80)
        {
            int offset = 0xFF00;
            switch(location - offset)
            {
                case P1:
                {
                    unsigned char joypad_state = get_joypad_state();
                    return joypad_state;
                }
            }
            return gb->hw_registers[location - offset];
        }
        else if(location < 0xFFFF) {
            return gb->hram[location - 0xFF80];
        } else if (location == 0xFFFF) {
            return gb->ie_register;
        } else {
            ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 637, __extension__ __PRETTY_FUNCTION__));
        }
    }
    else
    {
        return 0;
    }
    ((0) ? (void) (0) : __assert_fail ("false", "memory.c", 644, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

variable_types: offset int


original_code:
void memory_write(uint16_t location, uint8_t data)
{
    if(location < 0xE000) {
        cartridge->write(location, data);
        return;
    }
    else if(location < 0x10000)
    {
        if(location < 0xFE00)
        {
            return;
        }
        else if(location < 0xFEA0)
        {
            int offset = 0xFE00;
            gb->oam[location - offset] = data;
        }
        else if (location < 0xFF00)
        {
            return;
        }
        else if(location < 0xFF80)
        {
            int offset = 0xFF00;
            switch(location - offset) {
                case LCDC:
                    update_lcd_control_register(data);
                    break;
                case P1:
                {
                    data &= 0x30;
                    if((data & 0x30) == 0) {
                        gb->hw_registers[P1] |= (data & 0x0F);
                    } else if((data & 0x10) == 0) {
                        joypad_select_direction_keys();
                    } else if((data & 0x20) == 0) {
                        joypad_select_button_keys();
                    }
                    break;
                }
                case HDMA5:
                {
                    if(cpu->hdma_active == 1) {
                        if((data & 0x80) == 0x00) {
                            cpu->hdma_active = 0;
                            gb->hw_registers[HDMA5] = 0xFF;
                        } else {
                            gb->hw_registers[HDMA5] = (data & 0x7F);
                        }
                        return;
                    }
                    u8 *dma_registers = &gb->hw_registers[HDMA1];
                    cpu->hdma_source = (*dma_registers) << 8;
                    cpu->hdma_source |= (*(++dma_registers));
                    cpu->hdma_destination = (*(++dma_registers)) << 8;
                    cpu->hdma_destination |= (*(++dma_registers));
                    cpu->hdma_destination &= ~0x000F;
                    cpu->hdma_source &= 0xFFF0;
                    cpu->hdma_destination &= ~0xE000;
                    cpu->hdma_destination |= 0x8000;
                    cpu->hdma_transfer_length = ((data & 0x7F) + 1) * 0x10;
                    if((data & 0x80) == 0x00) {
                        for(int i = 0; i < cpu->hdma_transfer_length; ++i) {
                            memory_write(cpu->hdma_destination++,
                                    memory_read(cpu->hdma_source++));
                        }
                        gb->hw_registers[HDMA1] = 0xFF;
                        gb->hw_registers[HDMA2] = 0xFF;
                        gb->hw_registers[HDMA3] = 0xFF;
                        gb->hw_registers[HDMA4] = 0xFF;
                        gb->hw_registers[HDMA5] = 0xFF;
                    } else {
                        gb->hw_registers[HDMA5] = (data & 0x7F);
                        cpu->hdma_active = 1;
                        u8 lcd_status = gb->hw_registers[STAT];
                        if((lcd_status & 0x03) == 0x00) {
                            hdma_transfer();
                        }
                    }
                    return;
                }
                case DMA:
                {
                    int dma_source = data << 8;
                    for(int i = 0; i < 0xA0; ++i) {
                            memory_write(0xFE00 + i, memory_read(dma_source + i));
                    }
                    gb->hw_registers[DMA] = data;
                    return;
                }
                case DIV:
                case LY:
                    data = 0;
                    break;
                case TAC:
                {
                    if((gb->hw_registers[TAC] & 0x3) != (data & 0x3)) {
                        u32 timer_counter = 0;
                        switch(data & 0x3) { case 0x0:
                                timer_counter = 1024;
                                break;
                            case 0x1:
                                timer_counter = 16;
                                break;
                            case 0x2:
                                timer_counter = 64;
                                break;
                            case 0x3:
                                timer_counter = 256;
                                break;
                        }
                        if( timer_counter != 0 ) {
                            cpu->timer_counter = timer_counter;
                        }
                    }
                    break;
                }
                case SVBK:
                {
                    if(data == 0) {
                        data = 1;
                    }
                    gb->hw_registers[SVBK] = data;
                    gameboy_update_selected_ram();
                    return;
                }
                case VBK:
                {
                    gb->hw_registers[VBK] = (data & 0x01);
                    gameboy_update_selected_vram();
                    return;
                }
                case BCPD:
                {
                    int pallete_index = gb->hw_registers[BCPS] & 0x3F;
                    gb->bg_pallete[pallete_index] = data;
                    if(gb->hw_registers[BCPS] & 0x80) {
                        ++gb->hw_registers[BCPS];
                    }
                    gb->hw_registers[BCPS] &= 0xBF;
                    return;
                }
                case OCPD:
                {
                    int pallete_index = gb->hw_registers[OCPS] & 0x3F;
                    gb->ob_pallete[pallete_index] = data;
                    if(gb->hw_registers[OCPS] & 0x80) {
                        ++gb->hw_registers[OCPS];
                    }
                    gb->hw_registers[OCPS] &= 0xBF;
                    return;
                }
                case BLCK:
                {
                    if(data == 0x11) {
                        if(gb->use_bios) {
                            gameboy_disable_bios();
                        }
                    }
                }
            }
            gb->hw_registers[location - offset] = data;
        }
        else if(location < 0xFFFF)
        {
            int offset = 0xFF80;
            gb->hram[location - offset] = data;
        }
        else if(location == 0xFFFF)
        {
            gb->ie_register = data;
        }
        else
        {
        }
    }
    else
    {
        return;
    }
}

canonical_original_code:
void memory_write(unsigned short location, unsigned char data)
{
    if(location < 0xE000) {
        cartridge->write(location, data);
        return;
    }
    else if(location < 0x10000)
    {
        if(location < 0xFE00)
        {
            return;
        }
        else if(location < 0xFEA0)
        {
            int offset = 0xFE00;
            gb->oam[location - offset] = data;
        }
        else if (location < 0xFF00)
        {
            return;
        }
        else if(location < 0xFF80)
        {
            int offset = 0xFF00;
            switch(location - offset) {
                case LCDC:
                    update_lcd_control_register(data);
                    break;
                case P1:
                {
                    data &= 0x30;
                    if((data & 0x30) == 0) {
                        gb->hw_registers[P1] |= (data & 0x0F);
                    } else if((data & 0x10) == 0) {
                        joypad_select_direction_keys();
                    } else if((data & 0x20) == 0) {
                        joypad_select_button_keys();
                    }
                    break;
                }
                case HDMA5:
                {
                    if(cpu->hdma_active == 1) {
                        if((data & 0x80) == 0x00) {
                            cpu->hdma_active = 0;
                            gb->hw_registers[HDMA5] = 0xFF;
                        } else {
                            gb->hw_registers[HDMA5] = (data & 0x7F);
                        }
                        return;
                    }
                    unsigned char *dma_registers = &gb->hw_registers[HDMA1];
                    cpu->hdma_source = (*dma_registers) << 8;
                    cpu->hdma_source |= (*(++dma_registers));
                    cpu->hdma_destination = (*(++dma_registers)) << 8;
                    cpu->hdma_destination |= (*(++dma_registers));
                    cpu->hdma_destination &= ~0x000F;
                    cpu->hdma_source &= 0xFFF0;
                    cpu->hdma_destination &= ~0xE000;
                    cpu->hdma_destination |= 0x8000;
                    cpu->hdma_transfer_length = ((data & 0x7F) + 1) * 0x10;
                    if((data & 0x80) == 0x00) {
                        for(int i = 0; i < cpu->hdma_transfer_length; ++i) {
                            memory_write(cpu->hdma_destination++,
                                    memory_read(cpu->hdma_source++));
                        }
                        gb->hw_registers[HDMA1] = 0xFF;
                        gb->hw_registers[HDMA2] = 0xFF;
                        gb->hw_registers[HDMA3] = 0xFF;
                        gb->hw_registers[HDMA4] = 0xFF;
                        gb->hw_registers[HDMA5] = 0xFF;
                    } else {
                        gb->hw_registers[HDMA5] = (data & 0x7F);
                        cpu->hdma_active = 1;
                        unsigned char lcd_status = gb->hw_registers[STAT];
                        if((lcd_status & 0x03) == 0x00) {
                            hdma_transfer();
                        }
                    }
                    return;
                }
                case DMA:
                {
                    int dma_source = data << 8;
                    for(int i = 0; i < 0xA0; ++i) {
                            memory_write(0xFE00 + i, memory_read(dma_source + i));
                    }
                    gb->hw_registers[DMA] = data;
                    return;
                }
                case DIV:
                case LY:
                    data = 0;
                    break;
                case TAC:
                {
                    if((gb->hw_registers[TAC] & 0x3) != (data & 0x3)) {
                        unsigned int timer_counter = 0;
                        switch(data & 0x3) { case 0x0:
                                timer_counter = 1024;
                                break;
                            case 0x1:
                                timer_counter = 16;
                                break;
                            case 0x2:
                                timer_counter = 64;
                                break;
                            case 0x3:
                                timer_counter = 256;
                                break;
                        }
                        if( timer_counter != 0 ) {
                            cpu->timer_counter = timer_counter;
                        }
                    }
                    break;
                }
                case SVBK:
                {
                    if(data == 0) {
                        data = 1;
                    }
                    gb->hw_registers[SVBK] = data;
                    gameboy_update_selected_ram();
                    return;
                }
                case VBK:
                {
                    gb->hw_registers[VBK] = (data & 0x01);
                    gameboy_update_selected_vram();
                    return;
                }
                case BCPD:
                {
                    int pallete_index = gb->hw_registers[BCPS] & 0x3F;
                    gb->bg_pallete[pallete_index] = data;
                    if(gb->hw_registers[BCPS] & 0x80) {
                        ++gb->hw_registers[BCPS];
                    }
                    gb->hw_registers[BCPS] &= 0xBF;
                    return;
                }
                case OCPD:
                {
                    int pallete_index = gb->hw_registers[OCPS] & 0x3F;
                    gb->ob_pallete[pallete_index] = data;
                    if(gb->hw_registers[OCPS] & 0x80) {
                        ++gb->hw_registers[OCPS];
                    }
                    gb->hw_registers[OCPS] &= 0xBF;
                    return;
                }
                case BLCK:
                {
                    if(data == 0x11) {
                        if(gb->use_bios) {
                            gameboy_disable_bios();
                        }
                    }
                }
            }
            gb->hw_registers[location - offset] = data;
        }
        else if(location < 0xFFFF)
        {
            int offset = 0xFF80;
            gb->hram[location - offset] = data;
        }
        else if(location == 0xFFFF)
        {
            gb->ie_register = data;
        }
        else
        {
        }
    }
    else
    {
        return;
    }
}

variable_types: i int


decompiled_code:
__int64 hdma_transfer()
{
int v0; // ebx
unsigned __int16 v1; // di
unsigned __int8 v2; // al
unsigned __int16 v3; // di
__int64 v4; // rcx
__int64 v5; // rdx
__int64 result; // rax

if ( !cartridge )
_assert_fail("cartridge", "memory.c", 0xFu, "hdma_transfer");
v0 = 16;
do
{
v1 = *(_WORD *)(cpu + 2LL);
*(_WORD *)(cpu + 2LL) = v1 + 1;
v2 = memory_read(v1);
v3 = *(_WORD *)(cpu + 4LL);
*(_WORD *)(cpu + 4LL) = v3 + 1;
memory_write(v3, v2);
--v0;
}
while ( v0 );
v4 = gb;
v5 = cpu;
*(_WORD *)(cpu + 6LL) -= 16;
result = (unsigned int)(unsigned __int8)(*(_BYTE *)(v4 + 51972))-- - 1;
if ( (_BYTE)result == 0xFF )
*(_BYTE *)(v5 + 8) = 0;
return result;
}

canonical_decompiled_code:
__int64 func15()
{
int v0; // ebx
unsigned __int16 v1; // di
unsigned __int8 v2; // al
unsigned __int16 v3; // di
__int64 v4; // rcx
__int64 v5; // rdx
__int64 result; // rax

if ( !cartridge )
_assert_fail("cartridge", "memory.c", 0xFu, "hdma_transfer");
v0 = 16;
do
{
v1 = *(_WORD *)(cpu + 2LL);
*(_WORD *)(cpu + 2LL) = v1 + 1;
v2 = func13(v1);
v3 = *(_WORD *)(cpu + 4LL);
*(_WORD *)(cpu + 4LL) = v3 + 1;
func14(v3, v2);
--v0;
}
while ( v0 );
v4 = gb;
v5 = cpu;
*(_WORD *)(cpu + 6LL) -= 16;
result = (unsigned int)(unsigned __int8)(*(_BYTE *)(v4 + 51972))-- - 1;
if ( (_BYTE)result == 0xFF )
*(_BYTE *)(v5 + 8) = 0;
return result;
}

original_code:
void hdma_transfer(void)
{
    ((cartridge) ? (void) (0) : __assert_fail ("cartridge", "memory.c", 15, __extension__ __PRETTY_FUNCTION__));
    for(int i = 0; i < 0x10; ++i) {
        memory_write(cpu->hdma_destination++, memory_read(cpu->hdma_source++));
    }
    cpu->hdma_transfer_length -= 0x10;
    if(--gb->hw_registers[HDMA5] == 0xFF) {
        cpu->hdma_active = 0;
    }
}

canonical_original_code:
void hdma_transfer()
{
    ((cartridge) ? (void) (0) : __assert_fail ("cartridge", "memory.c", 15, __extension__ __PRETTY_FUNCTION__));
    for(int i = 0; i < 0x10; ++i) {
        memory_write(cpu->hdma_destination++, memory_read(cpu->hdma_source++));
    }
    cpu->hdma_transfer_length -= 0x10;
    if(--gb->hw_registers[HDMA5] == 0xFF) {
        cpu->hdma_active = 0;
    }
}


decompiled_code:
__int64 __fastcall update_screen_buffer(int a1, int a2, int a3)
{
__int64 result; // rax

result = ((unsigned __int16)a3 >> 10) & 0x1F | (unsigned int)(a3 << 11);
screen_buffer[160 * a1 + a2] = ((unsigned __int16)a3 >> 10) & 0x1F | ((_WORD)a3 << 11) | ((((unsigned __int16)a3 >> 5) & 0x1F) << 6);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1, int a2, int a3)
{
__int64 result; // rax

result = ((unsigned __int16)a3 >> 10) & 0x1F | (unsigned int)(a3 << 11);
screen_buffer[160 * a1 + a2] = ((unsigned __int16)a3 >> 10) & 0x1F | ((_WORD)a3 << 11) | ((((unsigned __int16)a3 >> 5) & 0x1F) << 6);
return result;
}

original_code:
void update_screen_buffer( int y_pixel, int x_pixel, u16 pallete_entry )
{
    u8 r, g, b;
    r = (pallete_entry >> 0 ) & 0x1F;
    g = (pallete_entry >> 5 ) & 0x1F;
    b = (pallete_entry >> 10) & 0x1F;
    uint16_t rgb_565 = b | (g << 6) | (r << 11);
    screen_buffer[y_pixel][x_pixel] = rgb_565;
}

canonical_original_code:
void update_screen_buffer(int y_pixel, int x_pixel, unsigned short pallete_entry)
{
    unsigned char r; unsigned char g; unsigned char b;
    r = (pallete_entry >> 0 ) & 0x1F;
    g = (pallete_entry >> 5 ) & 0x1F;
    b = (pallete_entry >> 10) & 0x1F;
    unsigned short rgb_565 = b | (g << 6) | (r << 11);
    screen_buffer[y_pixel][x_pixel] = rgb_565;
}

variable_types:
r
unsigned char

variable_types:
g
unsigned char

variable_types:
b
unsigned char


original_code:
void render_background(void)
{
    uint16_t tile_map_offset;
    uint16_t tile_row;
    uint8_t scanline = gb->hw_registers[LY];
    uint8_t scroll_y = gb->hw_registers[SCY];
    uint8_t scroll_x = gb->hw_registers[SCX];
    uint8_t window_y = gb->hw_registers[WY];
    uint8_t window_x = gb->hw_registers[WX];
    uint8_t y_position;
    uint8_t x_position;
    _Bool render_window = 0;
    if(window_enabled && (window_y <= scanline)) {
        render_window = 1;
    }
    if(render_window) {
        x_position = window_x - 7;
        y_position = scanline - window_y;
        tile_map_offset = window_tile_map;
    } else {
        x_position = scroll_x;
        y_position = scanline + scroll_y;
        tile_map_offset = bg_tile_map;
    }
    tile_row = y_position / 8;
    for(uint8_t x_pixel = 0; x_pixel < 160; ++x_pixel, ++x_position ) {
        uint16_t tile_column = x_position / 8;
        uint16_t tile_address = tile_map_offset + (tile_row * 32) + tile_column;
        uint8_t tile_number = gb->vram[tile_address];
        uint16_t tile_attributes = gb->vram[tile_address + 0x2000];
        int vram_offset = ((tile_attributes & 0x08) << 10);
        vram_offset += tile_data_offset;
        uint8_t pallete_number = tile_attributes & BACKGROUND_PALETTE_NUMBER;
        uint8_t pallete_index = pallete_number * 8;
        uint8_t tile_x_pixel = flip_table[((tile_attributes & 0x20) >> 2) | (x_position % 8)];
        uint8_t tile_y_pixel = flip_table[((tile_attributes & 0x40) >> 3) | (y_position % 8)];
        int tile_pixel = (tile_y_pixel * 8) + tile_x_pixel;
        int vram_index = (((tile_number + (128 * signed_tiles)) & 0xFF) * 16);
        vram_index += vram_offset + (tile_pixel / 8) * 2;
        uint8_t low = gb->vram[vram_index++];
        uint8_t high = gb->vram[vram_index];
        uint8_t shift = tile_x_pixel;
        uint8_t bit = 0x80 >> shift;
        uint8_t pallete_index_offset;
        uint16_t pallete_entry;
        shift = 7 - shift;
        pallete_index_offset = ((low & bit) >> shift) << 1;
        pallete_index_offset |= ((high & bit) >> shift) << 2;
        pallete_index += pallete_index_offset;
        pallete_entry = gb->bg_pallete[pallete_index++];
        pallete_entry |= (gb->bg_pallete[pallete_index] << 8);
        scanline_bg_priority[x_pixel] = pallete_index_offset;
        update_screen_buffer(scanline, x_pixel, pallete_entry);
    }
}

canonical_original_code:
void render_background()
{
    unsigned short tile_map_offset;
    unsigned short tile_row;
    unsigned char scanline = gb->hw_registers[LY];
    unsigned char scroll_y = gb->hw_registers[SCY];
    unsigned char scroll_x = gb->hw_registers[SCX];
    unsigned char window_y = gb->hw_registers[WY];
    unsigned char window_x = gb->hw_registers[WX];
    unsigned char y_position;
    unsigned char x_position;
    _Bool render_window = 0;
    if(window_enabled && (window_y <= scanline)) {
        render_window = 1;
    }
    if(render_window) {
        x_position = window_x - 7;
        y_position = scanline - window_y;
        tile_map_offset = window_tile_map;
    } else {
        x_position = scroll_x;
        y_position = scanline + scroll_y;
        tile_map_offset = bg_tile_map;
    }
    tile_row = y_position / 8;
    for(unsigned char x_pixel = 0; x_pixel < 160; ++x_pixel, ++x_position ) {
        unsigned short tile_column = x_position / 8;
        unsigned short tile_address = tile_map_offset + (tile_row * 32) + tile_column;
        unsigned char tile_number = gb->vram[tile_address];
        unsigned short tile_attributes = gb->vram[tile_address + 0x2000];
        int vram_offset = ((tile_attributes & 0x08) << 10);
        vram_offset += tile_data_offset;
        unsigned char pallete_number = tile_attributes & BACKGROUND_PALETTE_NUMBER;
        unsigned char pallete_index = pallete_number * 8;
        unsigned char tile_x_pixel = flip_table[((tile_attributes & 0x20) >> 2) | (x_position % 8)];
        unsigned char tile_y_pixel = flip_table[((tile_attributes & 0x40) >> 3) | (y_position % 8)];
        int tile_pixel = (tile_y_pixel * 8) + tile_x_pixel;
        int vram_index = (((tile_number + (128 * signed_tiles)) & 0xFF) * 16);
        vram_index += vram_offset + (tile_pixel / 8) * 2;
        unsigned char low = gb->vram[vram_index++];
        unsigned char high = gb->vram[vram_index];
        unsigned char shift = tile_x_pixel;
        unsigned char bit = 0x80 >> shift;
        unsigned char pallete_index_offset;
        unsigned short pallete_entry;
        shift = 7 - shift;
        pallete_index_offset = ((low & bit) >> shift) << 1;
        pallete_index_offset |= ((high & bit) >> shift) << 2;
        pallete_index += pallete_index_offset;
        pallete_entry = gb->bg_pallete[pallete_index++];
        pallete_entry |= (gb->bg_pallete[pallete_index] << 8);
        scanline_bg_priority[x_pixel] = pallete_index_offset;
        update_screen_buffer(scanline, x_pixel, pallete_entry);
    }
}

variable_types:
scanline
unsigned char

variable_types:
low
unsigned char

variable_types:
high
unsigned char

variable_types:
shift
unsigned char

variable_types:
bit
unsigned char


decompiled_code:
__int64 render_sprites()
{
unsigned int v0; // ebx
unsigned __int8 v1; // al
__int16 v2; // r15
unsigned __int8 v3; // r13
__int16 v4; // r12
__int16 v5; // r14
__int64 result; // rax
__int16 v7; // cx
int v8; // edi
char v9; // si
char v10; // r13
char v11; // si
unsigned int v12; // er15
__int64 v13; // r12
int v14; // er13
__int16 v15; // si
int v16; // er14
unsigned __int16 v17; // si
char v18; // r9
char v19; // r8
int v20; // edx
char v21; // dl
char v22; // [rsp+8h] [rbp-38h]
char v23; // [rsp+9h] [rbp-37h]
char v24; // [rsp+Ah] [rbp-36h]
unsigned __int8 v25; // [rsp+Bh] [rbp-35h]

v0 = 65024;
memset(scanline_obj_priority, 0, sizeof(scanline_obj_priority));
do
{
v1 = memory_read(v0);
v2 = v1 - 16;
v3 = v1;
v4 = (unsigned __int8)memory_read(v0 + 1);
v5 = (unsigned __int8)memory_read(v0 + 2);
result = memory_read(v0 + 3);
if ( v2 != -16 && v2 <= 143 )
{
v7 = v4 - 8;
if ( v4 )
{
if ( v7 <= 159 )
{
LOWORD(v8) = *(unsigned __int8 *)(gb + 51955LL);
v9 = *(_BYTE *)(gb + 51955LL);
if ( v2 <= (__int16)v8 )
{
v8 = (unsigned __int8)v8;
if ( (unsigned __int8)v8 < (unsigned __int8)sprite_height + v2 )
{
v10 = v3 - 16;
if ( (((int)(unsigned __int8)result >> 2) & 0x10) != 0 )
v11 = sprite_height - 1 - v9 + v10;
else
v11 = v9 - v10;
v12 = v7;
v13 = v7;
v14 = 0;
v15 = v11 + 8 * v5;
v16 = ((int)(unsigned __int8)result >> 2) & 8;
v17 = (((unsigned __int8)result << 10) & 0x2000) + 2 * v15;
v18 = *(_BYTE *)(gb + v17 + 0x8000LL);
v19 = *(_BYTE *)(gb + (unsigned __int16)(v17 + 1) + 0x8000LL);
v22 = 8 * (result & 7);
do
{
if ( v12 <= 0x9F
&& !scanline_obj_priority[v13]
&& ((result & 0x80u) == 0LL || !scanline_bg_priority[v13]) )
{
scanline_obj_priority[v13] = 1;
v20 = 128 >> flip_table[v14 | v16];
v21 = (4 * ((int)(unsigned __int8)(v20 & v19) >> (7 - flip_table[v14 | v16]))) | (2
* ((int)(unsigned __int8)(v18 & v20) >> (7 - flip_table[v14 | v16])));
if ( v21 )
{
v25 = result;
v23 = v19;
v24 = v18;
update_screen_buffer(
v8,
v12,
(unsigned __int16)(*(unsigned __int8 *)(gb + (unsigned __int8)(v22 + v21 + 1) + 51696LL) << 8) | (unsigned __int16)*(unsigned __int8 *)(gb + (unsigned __int8)(v22 + v21) + 51696LL));
v19 = v23;
v18 = v24;
result = v25;
}
}
++v14;
++v12;
++v13;
}
while ( v14 != 8 );
}
}
}
}
}
v0 += 4;
}
while ( v0 != 65184 );
return result;
}

canonical_decompiled_code:
__int64 func2()
{
unsigned int v0; // ebx
unsigned __int8 v1; // al
__int16 v2; // r15
unsigned __int8 v3; // r13
__int16 v4; // r12
__int16 v5; // r14
__int64 result; // rax
__int16 v7; // cx
int v8; // edi
char v9; // si
char v10; // r13
char v11; // si
unsigned int v12; // er15
__int64 v13; // r12
int v14; // er13
__int16 v15; // si
int v16; // er14
unsigned __int16 v17; // si
char v18; // r9
char v19; // r8
int v20; // edx
char v21; // dl
char v22; // [rsp+8h] [rbp-38h]
char v23; // [rsp+9h] [rbp-37h]
char v24; // [rsp+Ah] [rbp-36h]
unsigned __int8 v25; // [rsp+Bh] [rbp-35h]

v0 = 65024;
memset(scanline_obj_priority, 0, sizeof(scanline_obj_priority));
do
{
v1 = memory_read(v0);
v2 = v1 - 16;
v3 = v1;
v4 = (unsigned __int8)memory_read(v0 + 1);
v5 = (unsigned __int8)memory_read(v0 + 2);
result = memory_read(v0 + 3);
if ( v2 != -16 && v2 <= 143 )
{
v7 = v4 - 8;
if ( v4 )
{
if ( v7 <= 159 )
{
LOWORD(v8) = *(unsigned __int8 *)(gb + 51955LL);
v9 = *(_BYTE *)(gb + 51955LL);
if ( v2 <= (__int16)v8 )
{
v8 = (unsigned __int8)v8;
if ( (unsigned __int8)v8 < (unsigned __int8)sprite_height + v2 )
{
v10 = v3 - 16;
if ( (((int)(unsigned __int8)result >> 2) & 0x10) != 0 )
v11 = sprite_height - 1 - v9 + v10;
else
v11 = v9 - v10;
v12 = v7;
v13 = v7;
v14 = 0;
v15 = v11 + 8 * v5;
v16 = ((int)(unsigned __int8)result >> 2) & 8;
v17 = (((unsigned __int8)result << 10) & 0x2000) + 2 * v15;
v18 = *(_BYTE *)(gb + v17 + 0x8000LL);
v19 = *(_BYTE *)(gb + (unsigned __int16)(v17 + 1) + 0x8000LL);
v22 = 8 * (result & 7);
do
{
if ( v12 <= 0x9F
&& !scanline_obj_priority[v13]
&& ((result & 0x80u) == 0LL || !scanline_bg_priority[v13]) )
{
scanline_obj_priority[v13] = 1;
v20 = 128 >> flip_table[v14 | v16];
v21 = (4 * ((int)(unsigned __int8)(v20 & v19) >> (7 - flip_table[v14 | v16]))) | (2
* ((int)(unsigned __int8)(v18 & v20) >> (7 - flip_table[v14 | v16])));
if ( v21 )
{
v25 = result;
v23 = v19;
v24 = v18;
func0(
v8,
v12,
(unsigned __int16)(*(unsigned __int8 *)(gb + (unsigned __int8)(v22 + v21 + 1) + 51696LL) << 8) | (unsigned __int16)*(unsigned __int8 *)(gb + (unsigned __int8)(v22 + v21) + 51696LL));
v19 = v23;
v18 = v24;
result = v25;
}
}
++v14;
++v12;
++v13;
}
while ( v14 != 8 );
}
}
}
}
}
v0 += 4;
}
while ( v0 != 65184 );
return result;
}

original_code:
void render_sprites(void) {
    memset(scanline_obj_priority, 0, 160);
    uint16_t sprite_attribute_index = 0xFE00;
    int sprite_count = 40;
    for(int sprite = 0; sprite < sprite_count; ++sprite) {
        s16 y_position = ((s16)memory_read(sprite_attribute_index++)) - 16;
        s16 x_position = ((s16)memory_read(sprite_attribute_index++)) - 8;
        uint8_t tile_number = memory_read(sprite_attribute_index++);
        uint8_t tile_attributes = memory_read(sprite_attribute_index++);
        if(y_position == -16 || y_position >= 144)
            continue;
        if(x_position == -8 || x_position >= 160)
            continue;
        s16 scanline = gb->hw_registers[LY];
        if((scanline >= y_position) && (scanline < (y_position + sprite_height))) {
            uint8_t pallete_number = tile_attributes & 0x07;
            uint16_t vram_offset = (tile_attributes & 0x08) << 10;
            uint8_t x_flip = (tile_attributes & 0x20) >> 2;
            uint8_t y_flip = (tile_attributes & 0x40) >> 2;
            uint8_t bg_priority = tile_attributes & 0x80;
            s8 sprite_line = scanline - y_position;
            if(y_flip) {
                sprite_line -= ( sprite_height - 1 );
                sprite_line *= -1;
            }
            uint16_t sprite_address = vram_offset + (tile_number * 16) + (sprite_line * 2);
            uint8_t low = gb->vram[sprite_address++];
            uint8_t high = gb->vram[sprite_address];
            for(int sprite_pixel = 0; sprite_pixel < 8; ++sprite_pixel){
                int x_pixel = x_position + sprite_pixel;
                if(x_pixel < 0 || x_pixel > 159 || scanline_obj_priority[x_pixel]) {
                    continue;
                }
                if(bg_priority && scanline_bg_priority[x_pixel]) {
                    continue;
                }
                scanline_obj_priority[x_pixel] = 0x01;
                uint8_t shift = flip_table[x_flip | sprite_pixel];
                uint8_t bit = 0x80 >> shift;
                shift = 7 - shift;
                uint8_t pallete_index_offset;
                pallete_index_offset = ((low & bit) >> shift) << 1;
                pallete_index_offset |= ((high & bit) >> shift) << 2;
                if(pallete_index_offset == 0) {
                    continue;
                }
                uint8_t pallete_index = pallete_index_offset + pallete_number * 8;
                uint16_t pallete_entry;
                pallete_entry = gb->ob_pallete[pallete_index++];
                pallete_entry |= (gb->ob_pallete[pallete_index] << 8);
                update_screen_buffer(scanline, x_pixel, pallete_entry);
            }
        }
    }
}

canonical_original_code:
void render_sprites() {
    memset(scanline_obj_priority, 0, 160);
    unsigned short sprite_attribute_index = 0xFE00;
    int sprite_count = 40;
    for(int sprite = 0; sprite < sprite_count; ++sprite) {
        short y_position = ((s16)memory_read(sprite_attribute_index++)) - 16;
        short x_position = ((s16)memory_read(sprite_attribute_index++)) - 8;
        unsigned char tile_number = memory_read(sprite_attribute_index++);
        unsigned char tile_attributes = memory_read(sprite_attribute_index++);
        if(y_position == -16 || y_position >= 144)
            continue;
        if(x_position == -8 || x_position >= 160)
            continue;
        short scanline = gb->hw_registers[LY];
        if((scanline >= y_position) && (scanline < (y_position + sprite_height))) {
            unsigned char pallete_number = tile_attributes & 0x07;
            unsigned short vram_offset = (tile_attributes & 0x08) << 10;
            unsigned char x_flip = (tile_attributes & 0x20) >> 2;
            unsigned char y_flip = (tile_attributes & 0x40) >> 2;
            unsigned char bg_priority = tile_attributes & 0x80;
            char sprite_line = scanline - y_position;
            if(y_flip) {
                sprite_line -= ( sprite_height - 1 );
                sprite_line *= -1;
            }
            unsigned short sprite_address = vram_offset + (tile_number * 16) + (sprite_line * 2);
            unsigned char low = gb->vram[sprite_address++];
            unsigned char high = gb->vram[sprite_address];
            for(int sprite_pixel = 0; sprite_pixel < 8; ++sprite_pixel){
                int x_pixel = x_position + sprite_pixel;
                if(x_pixel < 0 || x_pixel > 159 || scanline_obj_priority[x_pixel]) {
                    continue;
                }
                if(bg_priority && scanline_bg_priority[x_pixel]) {
                    continue;
                }
                scanline_obj_priority[x_pixel] = 0x01;
                unsigned char shift = flip_table[x_flip | sprite_pixel];
                unsigned char bit = 0x80 >> shift;
                shift = 7 - shift;
                unsigned char pallete_index_offset;
                pallete_index_offset = ((low & bit) >> shift) << 1;
                pallete_index_offset |= ((high & bit) >> shift) << 2;
                if(pallete_index_offset == 0) {
                    continue;
                }
                unsigned char pallete_index = pallete_index_offset + pallete_number * 8;
                unsigned short pallete_entry;
                pallete_entry = gb->ob_pallete[pallete_index++];
                pallete_entry |= (gb->ob_pallete[pallete_index] << 8);
                update_screen_buffer(scanline, x_pixel, pallete_entry);
            }
        }
    }
}

variable_types: sprite int

variable_types: scanline short


decompiled_code:
void *initialize_screen()
{
void *result; // rax

if ( screen_initialized )
_assert_fail("screen_initialized == false", "screen.c", 0x26u, "initialize_screen");
result = memset(screen_buffer, 0, sizeof(screen_buffer));
screen_initialized = 1;
return result;
}

canonical_decompiled_code:
void *func3()
{
void *result; // rax

if ( screen_initialized )
_assert_fail("screen_initialized == false", "screen.c", 0x26u, "initialize_screen");
result = memset(screen_buffer, 0, sizeof(screen_buffer));
screen_initialized = 1;
return result;
}

original_code:
void initialize_screen() {
    ((screen_initialized == 0) ? (void) (0) : __assert_fail ("screen_initialized == false", "screen.c", 38, __extension__ __PRETTY_FUNCTION__));
    memset(screen_buffer, 0, (144 * 160) * sizeof(uint16_t));
    screen_initialized = 1;
}

canonical_original_code:
void initialize_screen() {
    ((screen_initialized == 0) ? (void) (0) : __assert_fail ("screen_initialized == false", "screen.c", 38, __extension__ __PRETTY_FUNCTION__));
    memset(screen_buffer, 0, (144 * 160) * sizeof(unsigned short));
    screen_initialized = 1;
}


decompiled_code:
__int16 __fastcall update_lcd_control_register(char a1)
{
__int16 v1; // ax
__int16 result; // ax

bg_enabled = a1 & 1;
obj_enabled = a1 & 2;
sprite_height = (a1 & 4) == 0 ? 8 : 16;
bg_tile_map = (a1 & 8) == 0 ? 6144 : 7168;
if ( (a1 & 0x10) != 0 )
{
signed_tiles = 0;
v1 = 0;
tile_data = 0;
}
else
{
signed_tiles = 1;
tile_data = 2048;
v1 = 2048;
}
tile_data_offset = v1;
window_enabled = a1 & 0x20;
lcd_enabled = a1 & 0x80;
result = (a1 & 0x40) == 0 ? 6144 : 7168;
window_tile_map = result;
return result;
}

canonical_decompiled_code:
__int16 __fastcall func4(char a1)
{
__int16 v1; // ax
__int16 result; // ax

bg_enabled = a1 & 1;
obj_enabled = a1 & 2;
sprite_height = (a1 & 4) == 0 ? 8 : 16;
bg_tile_map = (a1 & 8) == 0 ? 6144 : 7168;
if ( (a1 & 0x10) != 0 )
{
signed_tiles = 0;
v1 = 0;
tile_data = 0;
}
else
{
signed_tiles = 1;
tile_data = 2048;
v1 = 2048;
}
tile_data_offset = v1;
window_enabled = a1 & 0x20;
lcd_enabled = a1 & 0x80;
result = (a1 & 0x40) == 0 ? 6144 : 7168;
window_tile_map = result;
return result;
}

original_code:
void update_lcd_control_register(uint8_t lcd_control)
{
    bg_enabled = (lcd_control & 0x01);
    obj_enabled = (lcd_control & 0x02);
    if(lcd_control & 0x04) {
        sprite_height = 16;
    } else {
        sprite_height = 8;
    }
    if(lcd_control & 0x08){
        bg_tile_map = 0x1C00;
    } else {
        bg_tile_map = 0x1800;
    }
    if(lcd_control & 0x10) {
        tile_data = 0x0000;
        signed_tiles = 0x00;
    } else {
        tile_data = 0x0800;
        signed_tiles = 0x01;
    }
    tile_data_offset = tile_data;
    window_enabled = (lcd_control & 0x20);
    if(lcd_control & 0x40) {
        window_tile_map = 0x1C00;
    } else {
        window_tile_map = 0x1800;
    }
    lcd_enabled = (lcd_control & 0x80);
}

canonical_original_code:
void update_lcd_control_register(unsigned char lcd_control)
{
    bg_enabled = (lcd_control & 0x01);
    obj_enabled = (lcd_control & 0x02);
    if(lcd_control & 0x04) {
        sprite_height = 16;
    } else {
        sprite_height = 8;
    }
    if(lcd_control & 0x08){
        bg_tile_map = 0x1C00;
    } else {
        bg_tile_map = 0x1800;
    }
    if(lcd_control & 0x10) {
        tile_data = 0x0000;
        signed_tiles = 0x00;
    } else {
        tile_data = 0x0800;
        signed_tiles = 0x01;
    }
    tile_data_offset = tile_data;
    window_enabled = (lcd_control & 0x20);
    if(lcd_control & 0x40) {
        window_tile_map = 0x1C00;
    } else {
        window_tile_map = 0x1800;
    }
    lcd_enabled = (lcd_control & 0x80);
}


decompiled_code:
__int64 render_scanline()
{
__int64 result; // rax

if ( !bg_enabled )
{
if ( !obj_enabled )
return result;
return render_sprites();
}
result = render_background();
if ( obj_enabled )
return render_sprites();
return result;
}

canonical_decompiled_code:
__int64 func5()
{
__int64 result; // rax

if ( !bg_enabled )
{
if ( !obj_enabled )
return result;
return func2();
}
result = func1();
if ( obj_enabled )
return func2();
return result;
}

original_code:
void render_scanline(void)
{
    if(bg_enabled) {
        render_background();
    }
    if(obj_enabled) {
        render_sprites();
    }
}

canonical_original_code:
void render_scanline()
{
    if(bg_enabled) {
        render_background();
    }
    if(obj_enabled) {
        render_sprites();
    }
}


decompiled_code:
__int64 initialize_joypad()
{
__int64 result; // rax

if ( initialized )
_assert_fail("initialized == false", "joypad.c", 0x14u, "initialize_joypad");
result = gb;
joypad_state = -1;
initialized = 1;
*(_BYTE *)(gb + 51887LL) |= 0xFu;
return result;
}

canonical_decompiled_code:
__int64 func0()
{
__int64 result; // rax

if ( initialized )
_assert_fail("initialized == false", "joypad.c", 0x14u, "initialize_joypad");
result = gb;
joypad_state = -1;
initialized = 1;
*(_BYTE *)(gb + 51887LL) |= 0xFu;
return result;
}

original_code:
void initialize_joypad()
{
    ((initialized == 0) ? (void) (0) : __assert_fail ("initialized == false", "joypad.c", 20, __extension__ __PRETTY_FUNCTION__));
    joypad_state = 0xFF;
    gb->hw_registers[P1] |= 0xF;
    initialized = 1;
}


decompiled_code:
__int64 reinitialize_joypad()
{
if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x1Eu, "reinitialize_joypad");
initialized = 0;
return initialize_joypad();
}

canonical_decompiled_code:
__int64 func1()
{
if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x1Eu, "reinitialize_joypad");
initialized = 0;
return func0();
}

original_code:
void reinitialize_joypad()
{
    ((initialized == 1) ? (void) (0) : __assert_fail ("initialized == true", "joypad.c", 30, __extension__ __PRETTY_FUNCTION__));
    initialized = 0;
    initialize_joypad();
}


decompiled_code:
__int64 get_joypad_state()
{
__int64 result; // rax
int v1; // ecx

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x26u, "get_joypad_state");
result = 15LL;
v1 = *(_BYTE *)(gb + 51887LL) & 0x30;
if ( (*(_BYTE *)(gb + 51887LL) & 0x30) != 0 )
{
if ( (*(_BYTE *)(gb + 51887LL) & 0x10) != 0 )
{
result = 0xFFFFFFFFLL;
if ( (*(_BYTE *)(gb + 51887LL) & 0x20) == 0 )
result = v1 | (unsigned int)((unsigned __int8)joypad_state >> 4);
}
else
{
result = v1 | joypad_state & 0xFu;
}
}
return result;
}

canonical_decompiled_code:
__int64 func2()
{
__int64 result; // rax
int v1; // ecx

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x26u, "get_joypad_state");
result = 15LL;
v1 = *(_BYTE *)(gb + 51887LL) & 0x30;
if ( (*(_BYTE *)(gb + 51887LL) & 0x30) != 0 )
{
if ( (*(_BYTE *)(gb + 51887LL) & 0x10) != 0 )
{
result = 0xFFFFFFFFLL;
if ( (*(_BYTE *)(gb + 51887LL) & 0x20) == 0 )
result = v1 | (unsigned int)((unsigned __int8)joypad_state >> 4);
}
else
{
result = v1 | joypad_state & 0xFu;
}
}
return result;
}

original_code:
u8 get_joypad_state() {
    ((initialized == 1) ? (void) (0) : __assert_fail ("initialized == true", "joypad.c", 38, __extension__ __PRETTY_FUNCTION__));
    u8 joypad_select = gb->hw_registers[P1] & 0x30;
    if((joypad_select & 0x30) == 0) {
        return (joypad_select | 0x0F);
    } else if((joypad_select & 0x10) == 0) {
        return (joypad_select | ((joypad_state >> 0) & 0x0F));
    } else if((joypad_select & 0x20) == 0) {
        return (joypad_select | ((joypad_state >> 4) & 0x0F));
    }
    return 0xFF;
}

canonical_original_code:
unsigned char get_joypad_state() {
    ((initialized == 1) ? (void) (0) : __assert_fail ("initialized == true", "joypad.c", 38, __extension__ __PRETTY_FUNCTION__));
    unsigned char joypad_select = gb->hw_registers[P1] & 0x30;
    if((joypad_select & 0x30) == 0) {
        return (joypad_select | 0x0F);
    } else if((joypad_select & 0x10) == 0) {
        return (joypad_select | ((joypad_state >> 0) & 0x0F));
    } else if((joypad_select & 0x20) == 0) {
        return (joypad_select | ((joypad_state >> 4) & 0x0F));
    }
    return 0xFF;
}


decompiled_code:
__int64 __fastcall joypad_down(int a1)
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized", "joypad.c", 0x3Au, "joypad_down");
if ( a1 > 7 )
_assert_fail("gb_key < 8", "joypad.c", 0x3Bu, "joypad_down");
joypad_state &= __ROL4__(-2, a1);
result = get_joypad_state() & 0xF;
*(_BYTE *)(gb + 51887LL) |= result;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(int a1)
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized", "joypad.c", 0x3Au, "joypad_down");
if ( a1 > 7 )
_assert_fail("gb_key < 8", "joypad.c", 0x3Bu, "joypad_down");
joypad_state &= __ROL4__(-2, a1);
result = func2() & 0xF;
*(_BYTE *)(gb + 51887LL) |= result;
return result;
}

original_code:
void joypad_down(int gb_key) {
    ((initialized) ? (void) (0) : __assert_fail ("initialized", "joypad.c", 58, __extension__ __PRETTY_FUNCTION__));
    ((gb_key < 8) ? (void) (0) : __assert_fail ("gb_key < 8", "joypad.c", 59, __extension__ __PRETTY_FUNCTION__));
    joypad_state &= ~(1 << gb_key);
    gb->hw_registers[P1] |= (get_joypad_state() & 0x0F);
}


decompiled_code:
__int64 __fastcall joypad_up(int a1)
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x46u, "joypad_up");
if ( a1 > 7 )
_assert_fail("gb_key < 8", "joypad.c", 0x47u, "joypad_up");
joypad_state |= 1 << a1;
result = get_joypad_state() & 0xF;
*(_BYTE *)(gb + 51887LL) |= result;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(int a1)
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x46u, "joypad_up");
if ( a1 > 7 )
_assert_fail("gb_key < 8", "joypad.c", 0x47u, "joypad_up");
joypad_state |= 1 << a1;
result = func2() & 0xF;
*(_BYTE *)(gb + 51887LL) |= result;
return result;
}

original_code:
void joypad_up(int gb_key) {
    ((initialized == 1) ? (void) (0) : __assert_fail ("initialized == true", "joypad.c", 70, __extension__ __PRETTY_FUNCTION__));
    ((gb_key < 8) ? (void) (0) : __assert_fail ("gb_key < 8", "joypad.c", 71, __extension__ __PRETTY_FUNCTION__));
    joypad_state |= (1 << gb_key);
    gb->hw_registers[P1] |= (get_joypad_state() & 0x0F);
}


decompiled_code:
__int64 joypad_select_button_keys()
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x53u, "joypad_select_button_keys");
result = gb;
*(_BYTE *)(gb + 51887LL) = -33;
return result;
}

canonical_decompiled_code:
__int64 func5()
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x53u, "joypad_select_button_keys");
result = gb;
*(_BYTE *)(gb + 51887LL) = -33;
return result;
}

original_code:
void joypad_select_button_keys() {
    ((initialized == 1) ? (void) (0) : __assert_fail ("initialized == true", "joypad.c", 83, __extension__ __PRETTY_FUNCTION__));
    gb->hw_registers[P1] = ~0x20;
    gb->hw_registers[P1] |= ((joypad_state >> 4) & 0x0F);
}


decompiled_code:
__int64 joypad_select_direction_keys()
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x62u, "joypad_select_direction_keys");
result = gb;
*(_BYTE *)(gb + 51887LL) = -17;
return result;
}

canonical_decompiled_code:
__int64 func6()
{
__int64 result; // rax

if ( !initialized )
_assert_fail("initialized == true", "joypad.c", 0x62u, "joypad_select_direction_keys");
result = gb;
*(_BYTE *)(gb + 51887LL) = -17;
return result;
}

original_code:
void joypad_select_direction_keys() {
    ((initialized == 1) ? (void) (0) : __assert_fail ("initialized == true", "joypad.c", 98, __extension__ __PRETTY_FUNCTION__));
    gb->hw_registers[P1] = ~0x10;
    gb->hw_registers[P1] |= ((joypad_state >> 0) & 0x0F);
}


decompiled_code:
__int64 cgbemu_run_to_vblank()
{
return emulate_cpu();
}

canonical_decompiled_code:
__int64 func0()
{
return emulate_cpu();
}

original_code:
void cgbemu_run_to_vblank()
{
    emulate_cpu();
}


decompiled_code:
__int64 __fastcall initialize_cgbemu(__int64 a1, __int64 a2)
{
if ( !a1 )
_assert_fail("cartridge_filepath", "cgbemu.c", 0xFu, "initialize_cgbemu");
initialize_gameboy(a2 != 0);
if ( (unsigned int)initialize_cartridge(a1) )
return 1LL;
initialize_cpu(a2 != 0);
initialize_joypad();
initialize_screen();
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, __int64 a2)
{
if ( !a1 )
_assert_fail("cartridge_filepath", "cgbemu.c", 0xFu, "initialize_cgbemu");
initialize_gameboy(a2 != 0);
if ( (unsigned int)initialize_cartridge(a1) )
return 1LL;
initialize_cpu(a2 != 0);
initialize_joypad();
initialize_screen();
return 0LL;
}

original_code:
int initialize_cgbemu(const char* cartridge_filepath, const char* bios_filepath) {
    ((cartridge_filepath) ? (void) (0) : __assert_fail ("cartridge_filepath", "cgbemu.c", 15, __extension__ __PRETTY_FUNCTION__));
    if(cartridge_filepath == ((void *)0)) {
        fprintf(stderr, "No cartridge filepath provided\n");
        return 1;
    }
    _Bool use_bios = bios_filepath == ((void *)0) ? 0 : 1;
    initialize_gameboy(use_bios, bios_filepath);
    if(initialize_cartridge(cartridge_filepath) != 0) {
        return 1;
    }
    initialize_cpu(use_bios);
    initialize_joypad();
    initialize_screen();
    return 0;
}

canonical_original_code:
int initialize_cgbemu(char *cartridge_filepath, char *bios_filepath) {
    ((cartridge_filepath) ? (void) (0) : __assert_fail ("cartridge_filepath", "cgbemu.c", 15, __extension__ __PRETTY_FUNCTION__));
    if(cartridge_filepath == ((void *)0)) {
        fprintf(stderr, "No cartridge filepath provided\n");
        return 1;
    }
    _Bool use_bios = bios_filepath == ((void *)0) ? 0 : 1;
    initialize_gameboy(use_bios, bios_filepath);
    if(initialize_cartridge(cartridge_filepath) != 0) {
        return 1;
    }
    initialize_cpu(use_bios);
    initialize_joypad();
    initialize_screen();
    return 0;
}


decompiled_code:
__int64 __fastcall cgbemu_set_button_pressed(unsigned int a1, char a2)
{
__int64 v2; // rdi
__int64 result; // rax

if ( a1 <= 7 )
{
v2 = (unsigned int)CSWTCH_4[a1];
if ( a2 )
result = joypad_down(v2);
else
result = joypad_up(v2);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func2(unsigned int a1, char a2)
{
__int64 v2; // rdi
__int64 result; // rax

if ( a1 <= 7 )
{
v2 = (unsigned int)CSWTCH_4[a1];
if ( a2 )
result = joypad_down(v2);
else
result = joypad_up(v2);
}
return result;
}

original_code:
void cgbemu_set_button_pressed(Button button, _Bool pressed)
{
    int gb_key;
    switch(button) {
        case UP:
            gb_key = JOYPAD_UP;
            break;
        case DOWN:
            gb_key = JOYPAD_DOWN;
            break;
        case RIGHT:
            gb_key = JOYPAD_RIGHT;
            break;
        case LEFT:
            gb_key = JOYPAD_LEFT;
            break;
        case A:
            gb_key = JOYPAD_A;
            break;
        case B:
            gb_key = JOYPAD_B;
            break;
        case SELECT:
            gb_key = JOYPAD_SELECT;
            break;
        case START:
            gb_key = JOYPAD_START;
            break;
        default:
            return;
    }
    if(pressed) {
        joypad_down(gb_key);
    } else {
        joypad_up(gb_key);
    }
}

canonical_original_code:
void cgbemu_set_button_pressed(enum Button button, _Bool pressed)
{
    int gb_key;
    switch(button) {
        case UP:
            gb_key = JOYPAD_UP;
            break;
        case DOWN:
            gb_key = JOYPAD_DOWN;
            break;
        case RIGHT:
            gb_key = JOYPAD_RIGHT;
            break;
        case LEFT:
            gb_key = JOYPAD_LEFT;
            break;
        case A:
            gb_key = JOYPAD_A;
            break;
        case B:
            gb_key = JOYPAD_B;
            break;
        case SELECT:
            gb_key = JOYPAD_SELECT;
            break;
        case START:
            gb_key = JOYPAD_START;
            break;
        default:
            return;
    }
    if(pressed) {
        joypad_down(gb_key);
    } else {
        joypad_up(gb_key);
    }
}

variable_types: enum Button { UP=0, DOWN=1, RIGHT=2, LEFT=3, A=4, B=5, SELECT=6, START=7 }


decompiled_code:
void *cgbemu_get_screen_buffer()
{
return &screen_buffer;
}

canonical_decompiled_code:
void *func3()
{
return &screen_buffer;
}

original_code:
uint16_t* cgbemu_get_screen_buffer()
{
    return (uint16_t*)screen_buffer;
}

canonical_original_code:
unsigned short *cgbemu_get_screen_buffer()
{
    return (unsigned short *)screen_buffer;
}

return_type: unsigned short *


decompiled_code:
__int64 cgbemu_save_state()
{
return gameboy_save_state();
}

canonical_decompiled_code:
__int64 func4()
{
return gameboy_save_state();
}

original_code:
void cgbemu_save_state(const char* filepath) {
    gameboy_save_state(filepath);
}

canonical_original_code:
void cgbemu_save_state(char *filepath) {
    gameboy_save_state(filepath);
}

variable_types:
filepath
char *


decompiled_code:
__int64 cgbemu_load_state()
{
return gameboy_load_state();
}

canonical_decompiled_code:
__int64 func5()
{
return gameboy_load_state();
}

original_code:
void cgbemu_load_state(const char* filepath) {
    gameboy_load_state(filepath);
}

canonical_original_code:
void cgbemu_load_state(char *filepath) {
    gameboy_load_state(filepath);
}


decompiled_code:
__int64 __fastcall get_cartridge_ram_size(int a1)
{
__int64 result; // rax

result = 0xFFFFFFFFLL;
if ( a1 <= 3 )
result = (unsigned int)CSWTCH_56[a1];
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1)
{
__int64 result; // rax

result = 0xFFFFFFFFLL;
if ( a1 <= 3 )
result = (unsigned int)CSWTCH_56[a1];
return result;
}

original_code:
static int get_cartridge_ram_size(int header_value) {
    switch(header_value) {
        case 0:
            return 0;
        case 1:
            return 0x800;
        case 2:
            return 0x2000;
        case 3:
            return 0x8000;
    }
    return -1;
}