decompiled_code:
char *__fastcall strutil_reverse(char *src)
{
size_t v1; // rbp
char *v2; // rbx
char *v3; // rdx
size_t v4; // rax
char v5; // cl

v1 = strlen(src);
v2 = (char *)calloc(v1 + 1, 1uLL);
strncpy(v2, src, v1);
if ( v1 > 1 )
{
v3 = &v2[v1 - 1];
v4 = 0LL;
do
{
v5 = v2[v4];
v2[v4] = *v3;
*v3 = v5;
++v4;
--v3;
}
while ( v4 < v1 >> 1 );
}
return v2;
}

canonical_decompiled_code:
char *__fastcall func13(char *src)
{
size_t v1; // rbp
char *v2; // rbx
char *v3; // rdx
size_t v4; // rax
char v5; // cl

v1 = strlen(src);
v2 = (char *)calloc(v1 + 1, 1uLL);
strncpy(v2, src, v1);
if ( v1 > 1 )
{
v3 = &v2[v1 - 1];
v4 = 0LL;
do
{
v5 = v2[v4];
v2[v4] = *v3;
*v3 = v5;
++v4;
--v3;
}
while ( v4 < v1 >> 1 );
}
return v2;
}

original_code:
char * strutil_reverse(char *string) {
    char temp = 0;
    size_t length = strlen(string);
    char *reversed = calloc(length + 1, sizeof(char));
    strncpy(reversed, string, length);
    for (size_t i = 0; i < (length / 2); i++) {
        temp = reversed[i];
        reversed[i] = reversed[length-1-i];
        reversed[length-1-i] = temp;
    }
    return reversed;
}

canonical_original_code:
char *strutil_reverse(char *string) {
    char temp = 0;
    unsigned long length = strlen(string);
    char *reversed = calloc(length + 1, sizeof(char));
    strncpy(reversed, string, length);
    for (unsigned long i = 0; i < (length / 2); i++) {
        temp = reversed[i];
        reversed[i] = reversed[length-1-i];
        reversed[length-1-i] = temp;
    }
    return reversed;
}

variable_types:
string
char *

variable_types: temp char

variable_types:
length
unsigned long

variable_types:
reversed
char *


repo: tyler-cromwell/Strutil

decompiled_code:
__int64 __fastcall strutil_ends_with(char *s, char *s2)
{
size_t v2; // r13
size_t v3; // rdx
__int64 result; // rax
void *v5; // r12
size_t v6; // rax

mcount(s, s2);
v2 = strlen(s2);
v3 = strlen(s);
result = 0LL;
if ( v2 <= v3 )
{
v5 = (void *)strutil_substring(s, v3 - v2);
v6 = strlen(s2);
if ( !strncmp((const char *)v5, s2, v6) )
{
free(v5);
result = 1LL;
}
else
{
free(v5);
result = 0LL;
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(char *s, char *s2)
{
size_t v2; // r13
size_t v3; // rdx
__int64 result; // rax
void *v5; // r12
size_t v6; // rax

func1(s, s2);
v2 = strlen(s2);
v3 = strlen(s);
result = 0LL;
if ( v2 <= v3 )
{
v5 = (void *)func9(s, v3 - v2);
v6 = strlen(s2);
if ( !strncmp((const char *)v5, s2, v6) )
{
free(v5);
result = 1LL;
}
else
{
free(v5);
result = 0LL;
}
}
return result;
}

original_code:
int strutil_ends_with(char *string, char *endtok) {
    if (strlen(endtok) > strlen(string)) {
        return 0;
    }
    char *substr = strutil_substring(string, strlen(string)-strlen(endtok), strlen(string));
    if (!strncmp(substr, endtok, strlen(endtok))) {
        free(substr);
        return 1;
    } else {
        free(substr);
        return 0;
    }
}

variable_types:
endtok
char *

variable_types:
substr
char *

return_type: int


decompiled_code:
char *__fastcall strutil_substring(__int64 a1, __int64 a2)
{
__int64 v2; // rdx
size_t v3; // r13
char *v4; // rax

mcount(a1, a2);
v3 = v2 - a2;
v4 = (char *)calloc(v2 - a2 + 1, 1uLL);
return strncpy(v4, (const char *)(a1 + a2), v3);
}

canonical_decompiled_code:
char *__fastcall func9(__int64 a1, __int64 a2)
{
__int64 v2; // rdx
size_t v3; // r13
char *v4; // rax

func1(a1, a2);
v3 = v2 - a2;
v4 = (char *)calloc(v2 - a2 + 1, 1uLL);
return strncpy(v4, (const char *)(a1 + a2), v3);
}

original_code:
char * strutil_substring(char *original, size_t start, size_t end) {
    char *substring = calloc((end-start)+1, sizeof(char));
    strncpy(substring, original+start, end-start);
    return substring;
}

canonical_original_code:
char *strutil_substring(char *original, unsigned long start, unsigned long end) {
    char *substring = calloc((end-start)+1, sizeof(char));
    strncpy(substring, original+start, end-start);
    return substring;
}

variable_types:
original
char *

variable_types:
start
unsigned long

variable_types:
end
unsigned long

variable_types:
substring
char *

return_type: char *


decompiled_code:
__int64 __fastcall strutil_contains(char *s1, char *s2)
{
char *v2; // rbx
size_t v3; // r14
size_t v4; // rax
unsigned int v5; // edx
char *v6; // r12

mcount(s1, s2);
v2 = s1;
v3 = strlen(s2);
v4 = strlen(s1);
v5 = 0;
if ( v3 <= v4 )
{
if ( v4 )
{
v6 = &s1[v4];
while ( strncmp(v2, s2, v3) )
{
if ( v6 == ++v2 )
return 0;
}
v5 = 1;
}
else
{
v5 = 0;
}
}
return v5;
}

canonical_decompiled_code:
__int64 __fastcall func8(char *s1, char *s2)
{
char *v2; // rbx
size_t v3; // r14
size_t v4; // rax
unsigned int v5; // edx
char *v6; // r12

func1(s1, s2);
v2 = s1;
v3 = strlen(s2);
v4 = strlen(s1);
v5 = 0;
if ( v3 <= v4 )
{
if ( v4 )
{
v6 = &s1[v4];
while ( strncmp(v2, s2, v3) )
{
if ( v6 == ++v2 )
return 0;
}
v5 = 1;
}
else
{
v5 = 0;
}
}
return v5;
}

original_code:
int strutil_contains(char *string, char *sequence) {
    char *s = string;
    if (strlen(sequence) > strlen(string)) {
        return 0;
    }
    for (size_t i = 0; i < strlen(string); i++) {
        if (!strncmp(s, sequence, strlen(sequence))) {
            return 1;
        } else {
            s++;
        }
    }
    return 0;
}

canonical_original_code:
int strutil_contains(char *string, char *sequence) {
    char *s = string;
    if (strlen(sequence) > strlen(string)) {
        return 0;
    }
    for (unsigned long i = 0; i < strlen(string); i++) {
        if (!strncmp(s, sequence, strlen(sequence))) {
            return 1;
        } else {
            s++;
        }
    }
    return 0;
}

variable_types:
sequence
char *

variable_types:
s
char *

variable_types:
i
unsigned long


decompiled_code:
char *__fastcall strutil_trim(char *src)
{
size_t v1; // rax
char *v2; // r13
__int64 v3; // r12
size_t v4; // rax
size_t v5; // rdx
size_t v6; // rbx
char *v7; // r12

mcount(src);
if ( !src )
return 0LL;
if ( *src == 32 )
{
v1 = strlen(src);
v2 = src;
v3 = 0LL;
do
{
if ( v1 == v3 )
break;
++v3;
++v2;
}
while ( *v2 == 32 );
}
else
{
v2 = src;
v3 = 0LL;
}
v4 = strlen(src);
v5 = v4 - 1;
if ( src[v4 - 1] == 32 && v4 != 1 )
{
do
--v5;
while ( src[v5] == 32 && v5 );
}
v6 = v5 - v3;
v7 = (char *)calloc(v5 - v3 + 2, 1uLL);
strncpy(v7, v2, v6 + 1);
return v7;
}

canonical_decompiled_code:
char *__fastcall func8(char *src)
{
size_t v1; // rax
char *v2; // r13
__int64 v3; // r12
size_t v4; // rax
size_t v5; // rdx
size_t v6; // rbx
char *v7; // r12

func1(src);
if ( !src )
return 0LL;
if ( *src == 32 )
{
v1 = strlen(src);
v2 = src;
v3 = 0LL;
do
{
if ( v1 == v3 )
break;
++v3;
++v2;
}
while ( *v2 == 32 );
}
else
{
v2 = src;
v3 = 0LL;
}
v4 = strlen(src);
v5 = v4 - 1;
if ( src[v4 - 1] == 32 && v4 != 1 )
{
do
--v5;
while ( src[v5] == 32 && v5 );
}
v6 = v5 - v3;
v7 = (char *)calloc(v5 - v3 + 2, 1uLL);
strncpy(v7, v2, v6 + 1);
return v7;
}

original_code:
char *strutil_trim(char *original) {
    if (original != ((void *)0)) {
        size_t i = 0;
        while (original[i] == ' ' && i < strlen(original)) i++;
        size_t start = i;
        for (i = strlen(original)-1; original[i] == ' ' && i > 0; i--);
        size_t end = i;
        char *new = calloc(end-start+2, sizeof(char));
        strncpy(new, original+start, end-start+1);
        return new;
    }
    else {
        return ((void *)0);
    }
}

canonical_original_code:
char *strutil_trim(char *original) {
    if (original != ((void *)0)) {
        unsigned long i = 0;
        while (original[i] == ' ' && i < strlen(original)) i++;
        unsigned long start = i;
        for (i = strlen(original)-1; original[i] == ' ' && i > 0; i--);
        unsigned long end = i;
        char *new = calloc(end-start+2, sizeof(char));
        strncpy(new, original+start, end-start+1);
        return new;
    }
    else {
        return ((void *)0);
    }
}

variable_types:
new
char *


decompiled_code:
char *__fastcall strutil_replace_all(char *src, char a2)
{
char v2; // dl
char v3; // r12
size_t v4; // r15
_QWORD *v5; // r13
char *v6; // rbx
_QWORD *v7; // rax
_QWORD *v8; // rcx
__int64 v10[7]; // [rsp+8h] [rbp-38h] BYREF

mcount(src);
v3 = v2;
v10[0] = 0LL;
v4 = strlen(src);
v5 = (_QWORD *)strutil_indices_of(src, (unsigned int)a2, v10);
v6 = (char *)calloc(v4 + 1, 1uLL);
strncpy(v6, src, v4);
if ( v10[0] )
{
v7 = v5;
v8 = &v5[v10[0]];
do
v6[*v7++] = v3;
while ( v7 != v8 );
}
free(v5);
return v6;
}

canonical_decompiled_code:
char *__fastcall func8(char *src, char a2)
{
char v2; // dl
char v3; // r12
size_t v4; // r15
_QWORD *v5; // r13
char *v6; // rbx
_QWORD *v7; // rax
_QWORD *v8; // rcx
__int64 v10[7]; // [rsp+8h] [rbp-38h] BYREF

func1(src);
v3 = v2;
v10[0] = 0LL;
v4 = strlen(src);
v5 = (_QWORD *)strutil_indices_of(src, (unsigned int)a2, v10);
v6 = (char *)calloc(v4 + 1, 1uLL);
strncpy(v6, src, v4);
if ( v10[0] )
{
v7 = v5;
v8 = &v5[v10[0]];
do
v6[*v7++] = v3;
while ( v7 != v8 );
}
free(v5);
return v6;
}

original_code:
char * strutil_replace_all(char *string, char old, char new) {
    size_t amount = 0;
    size_t length = strlen(string);
    size_t *indices = strutil_indices_of(string, old, &amount);
    char *replaced = calloc(length + 1, sizeof(char));
    strncpy(replaced, string, length);
    for (size_t i = 0; i < amount; i++) {
        replaced[indices[i]] = new;
    }
    free(indices);
    return replaced;
}

canonical_original_code:
char *strutil_replace_all(char *string, char old, char new) {
    unsigned long amount = 0;
    unsigned long length = strlen(string);
    unsigned long *indices = strutil_indices_of(string, old, &amount);
    char *replaced = calloc(length + 1, sizeof(char));
    strncpy(replaced, string, length);
    for (unsigned long i = 0; i < amount; i++) {
        replaced[indices[i]] = new;
    }
    free(indices);
    return replaced;
}

variable_types: old char

variable_types: new char

variable_types:
amount
unsigned long

variable_types:
indices
unsigned long *

variable_types:
replaced
char *


decompiled_code:
char *__fastcall strutil_remove(char *src, size_t n)
{
__int64 v2; // rdx
__int64 v3; // r14
size_t v4; // r12
char *v5; // r13

mcount(src, n);
v3 = v2;
v4 = strlen(src);
v5 = (char *)calloc(n - v3 + v4 + 1, 1uLL);
strncpy(v5, src, n);
return strncat(v5, &src[v3], v4 - v3);
}

canonical_decompiled_code:
char *__fastcall func8(char *src, size_t n)
{
__int64 v2; // rdx
__int64 v3; // r14
size_t v4; // r12
char *v5; // r13

func1(src, n);
v3 = v2;
v4 = strlen(src);
v5 = (char *)calloc(n - v3 + v4 + 1, 1uLL);
strncpy(v5, src, n);
return strncat(v5, &src[v3], v4 - v3);
}

original_code:
char * strutil_remove(char *original, size_t start, size_t end) {
    size_t len = end - start;
    size_t length = strlen(original);
    char *condensed = calloc(length-len+1, sizeof(char));
    strncpy(condensed, original, start);
    strncat(condensed, original + end, length - end);
    return condensed;
}

canonical_original_code:
char *strutil_remove(char *original, unsigned long start, unsigned long end) {
    unsigned long len = end - start;
    unsigned long length = strlen(original);
    char *condensed = calloc(length-len+1, sizeof(char));
    strncpy(condensed, original, start);
    strncat(condensed, original + end, length - end);
    return condensed;
}

variable_types:
len
unsigned long

variable_types:
length
unsigned long

variable_types:
condensed
char *


decompiled_code:
__int64 __fastcall strutil_index_of(_BYTE *a1, char a2)
{
__int64 result; // rax
char v3; // dl

mcount();
if ( !*a1 || *a1 == a2 )
return 0LL;
result = 0LL;
do
v3 = a1[++result];
while ( v3 && v3 != a2 );
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(_BYTE *a1, char a2)
{
__int64 result; // rax
char v3; // dl

func1();
if ( !*a1 || *a1 == a2 )
return 0LL;
result = 0LL;
do
v3 = a1[++result];
while ( v3 && v3 != a2 );
return result;
}

original_code:
inline size_t strutil_index_of(char *string, char character) {
    size_t i = 0;
    while (string[i] != character && string[i] != '\0') i++;
    return i;
}

canonical_original_code:
inline unsigned long strutil_index_of(char *string, char character) {
    unsigned long i = 0;
    while (string[i] != character && string[i] != '\0') i++;
    return i;
}

variable_types:
string
char *

variable_types: character char

return_type: unsigned long


decompiled_code:
char *__fastcall strutil_insert(char *src, char *a2)
{
size_t v2; // rdx
size_t v3; // r14
size_t v4; // rbx
char *v5; // r12
char *v6; // rax
size_t n; // [rsp+8h] [rbp-38h]

mcount(src, a2);
v3 = v2;
v4 = strlen(src);
v5 = 0LL;
if ( v4 > v3 )
{
n = strlen(a2);
v6 = (char *)calloc(v4 + n, 1uLL);
v5 = v6;
if ( v3 )
{
strncpy(v6, src, v3);
strncat(v5, a2, n);
strncat(v5, &src[v3], v4 - v3);
}
else
{
strncpy(v6, a2, n);
strncat(v5, src, v4);
}
}
return v5;
}

canonical_decompiled_code:
char *__fastcall func8(char *src, char *a2)
{
size_t v2; // rdx
size_t v3; // r14
size_t v4; // rbx
char *v5; // r12
char *v6; // rax
size_t n; // [rsp+8h] [rbp-38h]

func1(src, a2);
v3 = v2;
v4 = strlen(src);
v5 = 0LL;
if ( v4 > v3 )
{
n = strlen(a2);
v6 = (char *)calloc(v4 + n, 1uLL);
v5 = v6;
if ( v3 )
{
strncpy(v6, src, v3);
strncat(v5, a2, n);
strncat(v5, &src[v3], v4 - v3);
}
else
{
strncpy(v6, a2, n);
strncat(v5, src, v4);
}
}
return v5;
}

original_code:
char * strutil_insert(char *original, char *additional, size_t index) {
    size_t lo = strlen(original);
    size_t la = strlen(additional);
    if (index >= lo) {
        return ((void *)0);
    }
    char *expanded = calloc(lo + la, sizeof(char));
    if (index == 0) {
        strncpy(expanded, additional, la);
        strncat(expanded, original, lo);
    } else {
        strncpy(expanded, original, index);
        strncat(expanded, additional, la);
        strncat(expanded, original + index, lo - index);
    }
    return expanded;
}

canonical_original_code:
char *strutil_insert(char *original, char *additional, unsigned long index) {
    unsigned long lo = strlen(original);
    unsigned long la = strlen(additional);
    if (index >= lo) {
        return ((void *)0);
    }
    char *expanded = calloc(lo + la, sizeof(char));
    if (index == 0) {
        strncpy(expanded, additional, la);
        strncat(expanded, original, lo);
    } else {
        strncpy(expanded, original, index);
        strncat(expanded, additional, la);
        strncat(expanded, original + index, lo - index);
    }
    return expanded;
}

variable_types:
original
char *

variable_types:
additional
char *

variable_types:
index
unsigned long

variable_types:
lo
unsigned long

variable_types:
la
unsigned long

variable_types:
expanded
char *


display

repo: tylerschloesser/cgbemu-core

decompiled_code:
__int64 display()
{
glClear(0x4000LL);
glColor3f(1.0, 1.0);
cgbemu_run_to_vblank();
glLoadIdentity();
glTranslatef(0.0, 0.0);
glTexImage2D(3553LL, 0LL, 6407LL, 160LL, 144LL, 0LL, 6407LL, 33635LL, screen_buffer);
glTexParameteri(3553LL, 10240LL, 9728LL);
glBegin(7LL);
glTexCoord2f(0.0, 1.0);
glVertex2f(-1.0);
glTexCoord2f(COERCE_DOUBLE((unsigned __int64)LC0), 1.0);
glVertex2f(1.0);
glTexCoord2f(COERCE_DOUBLE((unsigned __int64)LC0), 0.0);
glVertex2f(1.0);
glTexCoord2f(0.0, 0.0);
glVertex2f(-1.0);
glEnd(-1.0, 1.0);
return glFlush();
}

canonical_decompiled_code:
__int64 func0()
{
glClear(0x4000LL);
glColor3f(1.0, 1.0);
cgbemu_run_to_vblank();
glLoadIdentity();
glTranslatef(0.0, 0.0);
glTexImage2D(3553LL, 0LL, 6407LL, 160LL, 144LL, 0LL, 6407LL, 33635LL, screen_buffer);
glTexParameteri(3553LL, 10240LL, 9728LL);
glBegin(7LL);
glTexCoord2f(0.0, 1.0);
glVertex2f(-1.0);
glTexCoord2f(COERCE_DOUBLE((unsigned __int64)LC0), 1.0);
glVertex2f(1.0);
glTexCoord2f(COERCE_DOUBLE((unsigned __int64)LC0), 0.0);
glVertex2f(1.0);
glTexCoord2f(0.0, 0.0);
glVertex2f(-1.0);
glEnd(-1.0, 1.0);
return glFlush();
}

original_code:
void display(void)
{
    glClear (0x00004000);
    glColor3f (1.0, 1.0, 1.0);
    cgbemu_run_to_vblank();
    glLoadIdentity();
    glTranslatef( 0, 0, 0.f );
    glTexImage2D(0x0DE1,
        0,
        0x1907,
        160,
        144,
        0,
        0x1907,
        0x8363,
        screen_buffer);
    glTexParameteri(0x0DE1, 0x2800, 0x2600);
    glBegin (0x0007);
    glTexCoord2f (0.0, 1.0); glVertex2f (-1.0, -1.0);
    glTexCoord2f (1.0, 1.0); glVertex2f (1.0, -1.0);
    glTexCoord2f (1.0, 0.0); glVertex2f (1.0, 1.0);
    glTexCoord2f (0.0, 0.0); glVertex2f (-1.0, 1.0);
    glEnd ();
    glFlush ();
}

canonical_original_code:
void display()
{
    glClear (0x00004000);
    glColor3f (1.0, 1.0, 1.0);
    cgbemu_run_to_vblank();
    glLoadIdentity();
    glTranslatef( 0, 0, 0.f );
    glTexImage2D(0x0DE1,
        0,
        0x1907,
        160,
        144,
        0,
        0x1907,
        0x8363,
        screen_buffer);
    glTexParameteri(0x0DE1, 0x2800, 0x2600);
    glBegin (0x0007);
    glTexCoord2f (0.0, 1.0); glVertex2f (-1.0, -1.0);
    glTexCoord2f (1.0, 1.0); glVertex2f (1.0, -1.0);
    glTexCoord2f (1.0, 0.0); glVertex2f (1.0, 1.0);
    glTexCoord2f (0.0, 0.0); glVertex2f (-1.0, 1.0);
    glEnd ();
    glFlush ();
}

return_type: void


reshape

decompiled_code:
__int64 __fastcall reshape(unsigned int a1, unsigned int a2)
{
window_height = a2;
window_width = a1;
glViewport(0LL, 0LL, a1, a2);
glDeleteTextures(1LL, &texture);
glEnable(3553LL);
glGenTextures(1LL, &texture);
glBindTexture(3553LL, (unsigned int)texture);
glTexParameterf(3553LL, 10241LL, 9729.0);
return glTexParameterf(3553LL, 10240LL, 9729.0);
}

canonical_decompiled_code:
__int64 __fastcall func1(unsigned int a1, unsigned int a2)
{
window_height = a2;
window_width = a1;
glViewport(0LL, 0LL, a1, a2);
glDeleteTextures(1LL, &texture);
glEnable(3553LL);
glGenTextures(1LL, &texture);
glBindTexture(3553LL, (unsigned int)texture);
glTexParameterf(3553LL, 10241LL, 9729.0);
return glTexParameterf(3553LL, 10240LL, 9729.0);
}

original_code:
void reshape (int w, int h)
{
    window_height = h;
    window_width = w;
    glViewport (0, 0, (GLsizei) w, (GLsizei) h);
    glDeleteTextures(1, &texture);
    glEnable(0x0DE1);
    glGenTextures(1, &texture);
    glBindTexture(0x0DE1, texture);
    glTexParameterf(0x0DE1, 0x2801, 0x2601);
    glTexParameterf(0x0DE1, 0x2800, 0x2601);
}

canonical_original_code:
void reshape(int w, int h)
{
    window_height = h;
    window_width = w;
    glViewport (0, 0, (int) w, (int) h);
    glDeleteTextures(1, &texture);
    glEnable(0x0DE1);
    glGenTextures(1, &texture);
    glBindTexture(0x0DE1, texture);
    glTexParameterf(0x0DE1, 0x2801, 0x2601);
    glTexParameterf(0x0DE1, 0x2800, 0x2601);
}

variable_types: w int

variable_types: h int


decompiled_code:
__int64 save_state_callback()
{
return cgbemu_save_state("save_state.bin");
}

canonical_decompiled_code:
__int64 func2()
{
return cgbemu_save_state("save_state.bin");
}

original_code:
void save_state_callback() {
    cgbemu_save_state("save_state.bin");
}


decompiled_code:
__int64 load_state_callback()
{
return cgbemu_load_state("save_state.bin");
}

canonical_decompiled_code:
__int64 func3()
{
return cgbemu_load_state("save_state.bin");
}

original_code:
void load_state_callback() {
    cgbemu_load_state("save_state.bin");
}


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

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


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; // ebx
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
{
fwrite("Failed to get screen buffer\n", 1uLL, 0x1CuLL, stderr);
v3 = 1;
}
}
}
else
{
puts("Invalid arguments");
v3 = 1;
}
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 **


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
__int64 v3; // rdi
int v4; // esi
__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 = cartridge;
v4 = a2 & 0x1F;
if ( !v4 )
LOBYTE(v4) = 1;
*(_WORD *)(cartridge + 80LL) = (unsigned __int8)v4;
result = update_cartridge_banking(v3);
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
__int64 v3; // rdi
int v4; // esi
__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 = cartridge;
v4 = a2 & 0x1F;
if ( !v4 )
LOBYTE(v4) = 1;
*(_WORD *)(cartridge + 80LL) = (unsigned __int8)v4;
result = func0(v3);
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 & 3;
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 & 3;
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, unsigned __int8 a2)
{
__int64 result; // rax
__int16 v3; // ax

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
v3 = *(_WORD *)(cartridge + 80LL);
LOBYTE(v3) = 0;
*(_WORD *)(cartridge + 80LL) = v3 | 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, unsigned __int8 a2)
{
__int64 result; // rax
__int16 v3; // ax

result = a1 >> 12;
switch ( (char)result )
{
case 0:
case 1:
result = cartridge;
*(_BYTE *)(cartridge + 104LL) = (a2 & 0xA) == 10;
break;
case 2:
v3 = *(_WORD *)(cartridge + 80LL);
LOBYTE(v3) = 0;
*(_WORD *)(cartridge + 80LL) = v3 | 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

if ( a1 <= 0xDFFFu )
return (*(__int64 (__fastcall **)(_QWORD))(cartridge + 88LL))(a1);
if ( a1 <= 0xFDFFu )
return memory_read((unsigned __int16)(a1 - 0x2000));
if ( a1 <= 0xFE9Fu )
return *(unsigned __int8 *)(gb + a1 - 65024 + 49152LL);
result = 0LL;
if ( a1 > 0xFEFFu )
{
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

if ( a1 <= 0xDFFFu )
return (*(__int64 (__fastcall **)(_QWORD))(cartridge + 88LL))(a1);
if ( a1 <= 0xFDFFu )
return func13((unsigned __int16)(a1 - 0x2000));
if ( a1 <= 0xFE9Fu )
return *(unsigned __int8 *)(gb + a1 - 65024 + 49152LL);
result = 0LL;
if ( a1 > 0xFEFFu )
{
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


decompiled_code:
void __fastcall memory_write(unsigned __int16 a1, unsigned __int8 a2)
{
char v2; // r12
char v3; // r13
int v4; // ebx
int v5; // eax
unsigned __int8 *v6; // rdx
__int64 v7; // rdx
int v8; // ebx
unsigned __int16 v9; // ax
unsigned __int8 v10; // si
unsigned __int16 v11; // ax
_BYTE *v12; // rax
__int64 v13; // rax
int i; // ebx
unsigned __int8 v15; // al
__int64 v16; // rax
char v17; // dl
__int64 v18; // rax
char v19; // dl

v2 = a2;
v3 = a2;
if ( a1 <= 0xDFFFu )
{
(*(void (__fastcall **)(_QWORD, _QWORD))(cartridge + 96LL))(a1, a2);
return;
}
if ( a1 > 0xFDFFu )
{
if ( a1 <= 0xFE9Fu )
{
*(_BYTE *)(gb + a1 - 65024 + 49152LL) = a2;
return;
}
if ( a1 > 0xFEFFu )
{
if ( a1 > 0xFF7Fu )
{
if ( a1 == 0xFFFF )
*(_BYTE *)(gb + 52015LL) = a2;
else
*(_BYTE *)(gb + a1 - 65408 + 51760LL) = a2;
return;
}
v4 = a1 - 65280;
if ( v4 <= 112 )
{
if ( v4 > 63 )
{
switch ( a1 )
{
case 0xFF40u:
update_lcd_control_register(a2);
goto LABEL_59;
case 0xFF44u:
v3 = 0;
goto LABEL_59;
case 0xFF46u:
for ( i = 0; i != 160; ++i )
{
v15 = memory_read((a2 << 8) + i);
memory_write((unsigned int)(i + 65024), v15);
}
*(_BYTE *)(gb + 51957LL) = a2;
break;
case 0xFF4Fu:
*(_BYTE *)(gb + 51966LL) = a2 & 1;
gameboy_update_selected_vram();
break;
case 0xFF50u:
if ( a2 == 17 && *(_BYTE *)(gb + 52018LL) )
gameboy_disable_bios();
goto LABEL_59;
case 0xFF55u:
if ( *(_BYTE *)(cpu + 8LL) )
{
if ( (a2 & 0x80u) != 0 )
{
*(_BYTE *)(gb + 51972LL) = a2 & 0x7F;
}
else
{
*(_BYTE *)(cpu + 8LL) = 0;
*(_BYTE *)(gb + 51972LL) = -1;
}
}
else
{
v6 = (unsigned __int8 *)gb;
*(_WORD *)(cpu + 2LL) = *(unsigned __int8 *)(gb + 51968LL) << 8;
*(_WORD *)(cpu + 2LL) |= v6[51969];
*(_WORD *)(cpu + 4LL) = v6[51970] << 8;
*(_WORD *)(cpu + 4LL) |= v6[51971];
*(_WORD *)(cpu + 4LL) &= 0xFFF0u;
*(_WORD *)(cpu + 2LL) &= 0xFFF0u;
*(_WORD *)(cpu + 4LL) &= 0x1FFFu;
*(_WORD *)(cpu + 4LL) |= 0x8000u;
*(_WORD *)(cpu + 6LL) = 16 * (unsigned __int8)((a2 & 0x7F) + 1);
if ( (a2 & 0x80u) != 0 )
{
v13 = gb;
*(_BYTE *)(gb + 51972LL) = a2 & 0x7F;
*(_BYTE *)(cpu + 8LL) = 1;
if ( (*(_BYTE *)(v13 + 51952) & 3) == 0 )
hdma_transfer();
}
else
{
v7 = cpu;
if ( *(_WORD *)(cpu + 6LL) )
{
v8 = 0;
do
{
v9 = *(_WORD *)(v7 + 2);
*(_WORD *)(v7 + 2) = v9 + 1;
v10 = memory_read(v9);
v11 = *(_WORD *)(cpu + 4LL);
*(_WORD *)(cpu + 4LL) = v11 + 1;
memory_write(v11, v10);
++v8;
v7 = cpu;
}
while ( *(unsigned __int16 *)(cpu + 6LL) > v8 );
}
v12 = (_BYTE *)gb;
*(_BYTE *)(gb + 51968LL) = -1;
v12[51969] = -1;
v12[51970] = -1;
v12[51971] = -1;
v12[51972] = -1;
}
}
break;
case 0xFF69u:
v16 = gb;
v17 = *(_BYTE *)(gb + 51991LL);
*(_BYTE *)(gb + (v17 & 0x3F) + 51632LL) = a2;
if ( v17 < 0 )
*(_BYTE *)(v16 + 51991) = v17 + 1;
*(_BYTE *)(v16 + 51991) &= 0xBFu;
break;
case 0xFF6Bu:
v18 = gb;
v19 = *(_BYTE *)(gb + 51993LL);
*(_BYTE *)(gb + (v19 & 0x3F) + 51696LL) = a2;
if ( v19 < 0 )
*(_BYTE *)(v18 + 51993) = v19 + 1;
*(_BYTE *)(v18 + 51993) &= 0xBFu;
break;
case 0xFF70u:
if ( !a2 )
v2 = 1;
*(_BYTE *)(gb + 51999LL) = v2;
gameboy_update_selected_ram();
break;
default:
goto LABEL_59;
}
return;
}
switch ( a1 )
{
case 0xFF04u:
v3 = 0;
break;
case 0xFF07u:
if ( ((*(_BYTE *)(gb + 51894LL) ^ a2) & 3) != 0 )
{
if ( (a2 & 3) == 2 )
{
v5 = 64;
}
else if ( (a2 & 3) == 3 )
{
v5 = 256;
}
else if ( (a2 & 3) != 0 )
{
v5 = 16;
}
else
{
v5 = 1024;
}
*(_DWORD *)(cpu + 12LL) = v5;
}
break;
case 0xFF00u:
v3 = a2 & 0x30;
if ( (a2 & 0x30) != 0 )
{
if ( (a2 & 0x10) != 0 )
{
if ( (a2 & 0x20) == 0 )
joypad_select_button_keys();
}
else
{
joypad_select_direction_keys();
}
}
break;
}
}
LABEL_59:
*(_BYTE *)(gb + v4 + 51887LL) = v3;
return;
}
}
}

canonical_decompiled_code:
void __fastcall func14(unsigned __int16 a1, unsigned __int8 a2)
{
char v2; // r12
char v3; // r13
int v4; // ebx
int v5; // eax
unsigned __int8 *v6; // rdx
__int64 v7; // rdx
int v8; // ebx
unsigned __int16 v9; // ax
unsigned __int8 v10; // si
unsigned __int16 v11; // ax
_BYTE *v12; // rax
__int64 v13; // rax
int i; // ebx
unsigned __int8 v15; // al
__int64 v16; // rax
char v17; // dl
__int64 v18; // rax
char v19; // dl

v2 = a2;
v3 = a2;
if ( a1 <= 0xDFFFu )
{
(*(void (__fastcall **)(_QWORD, _QWORD))(cartridge + 96LL))(a1, a2);
return;
}
if ( a1 > 0xFDFFu )
{
if ( a1 <= 0xFE9Fu )
{
*(_BYTE *)(gb + a1 - 65024 + 49152LL) = a2;
return;
}
if ( a1 > 0xFEFFu )
{
if ( a1 > 0xFF7Fu )
{
if ( a1 == 0xFFFF )
*(_BYTE *)(gb + 52015LL) = a2;
else
*(_BYTE *)(gb + a1 - 65408 + 51760LL) = a2;
return;
}
v4 = a1 - 65280;
if ( v4 <= 112 )
{
if ( v4 > 63 )
{
switch ( a1 )
{
case 0xFF40u:
update_lcd_control_register(a2);
goto LABEL_59;
case 0xFF44u:
v3 = 0;
goto LABEL_59;
case 0xFF46u:
for ( i = 0; i != 160; ++i )
{
v15 = func13((a2 << 8) + i);
func14((unsigned int)(i + 65024), v15);
}
*(_BYTE *)(gb + 51957LL) = a2;
break;
case 0xFF4Fu:
*(_BYTE *)(gb + 51966LL) = a2 & 1;
gameboy_update_selected_vram();
break;
case 0xFF50u:
if ( a2 == 17 && *(_BYTE *)(gb + 52018LL) )
gameboy_disable_bios();
goto LABEL_59;
case 0xFF55u:
if ( *(_BYTE *)(cpu + 8LL) )
{
if ( (a2 & 0x80u) != 0 )
{
*(_BYTE *)(gb + 51972LL) = a2 & 0x7F;
}
else
{
*(_BYTE *)(cpu + 8LL) = 0;
*(_BYTE *)(gb + 51972LL) = -1;
}
}
else
{
v6 = (unsigned __int8 *)gb;
*(_WORD *)(cpu + 2LL) = *(unsigned __int8 *)(gb + 51968LL) << 8;
*(_WORD *)(cpu + 2LL) |= v6[51969];
*(_WORD *)(cpu + 4LL) = v6[51970] << 8;
*(_WORD *)(cpu + 4LL) |= v6[51971];
*(_WORD *)(cpu + 4LL) &= 0xFFF0u;
*(_WORD *)(cpu + 2LL) &= 0xFFF0u;
*(_WORD *)(cpu + 4LL) &= 0x1FFFu;
*(_WORD *)(cpu + 4LL) |= 0x8000u;
*(_WORD *)(cpu + 6LL) = 16 * (unsigned __int8)((a2 & 0x7F) + 1);
if ( (a2 & 0x80u) != 0 )
{
v13 = gb;
*(_BYTE *)(gb + 51972LL) = a2 & 0x7F;
*(_BYTE *)(cpu + 8LL) = 1;
if ( (*(_BYTE *)(v13 + 51952) & 3) == 0 )
func15();
}
else
{
v7 = cpu;
if ( *(_WORD *)(cpu + 6LL) )
{
v8 = 0;
do
{
v9 = *(_WORD *)(v7 + 2);
*(_WORD *)(v7 + 2) = v9 + 1;
v10 = func13(v9);
v11 = *(_WORD *)(cpu + 4LL);
*(_WORD *)(cpu + 4LL) = v11 + 1;
func14(v11, v10);
++v8;
v7 = cpu;
}
while ( *(unsigned __int16 *)(cpu + 6LL) > v8 );
}
v12 = (_BYTE *)gb;
*(_BYTE *)(gb + 51968LL) = -1;
v12[51969] = -1;
v12[51970] = -1;
v12[51971] = -1;
v12[51972] = -1;
}
}
break;
case 0xFF69u:
v16 = gb;
v17 = *(_BYTE *)(gb + 51991LL);
*(_BYTE *)(gb + (v17 & 0x3F) + 51632LL) = a2;
if ( v17 < 0 )
*(_BYTE *)(v16 + 51991) = v17 + 1;
*(_BYTE *)(v16 + 51991) &= 0xBFu;
break;
case 0xFF6Bu:
v18 = gb;
v19 = *(_BYTE *)(gb + 51993LL);
*(_BYTE *)(gb + (v19 & 0x3F) + 51696LL) = a2;
if ( v19 < 0 )
*(_BYTE *)(v18 + 51993) = v19 + 1;
*(_BYTE *)(v18 + 51993) &= 0xBFu;
break;
case 0xFF70u:
if ( !a2 )
v2 = 1;
*(_BYTE *)(gb + 51999LL) = v2;
gameboy_update_selected_ram();
break;
default:
goto LABEL_59;
}
return;
}
switch ( a1 )
{
case 0xFF04u:
v3 = 0;
break;
case 0xFF07u:
if ( ((*(_BYTE *)(gb + 51894LL) ^ a2) & 3) != 0 )
{
if ( (a2 & 3) == 2 )
{
v5 = 64;
}
else if ( (a2 & 3) == 3 )
{
v5 = 256;
}
else if ( (a2 & 3) != 0 )
{
v5 = 16;
}
else
{
v5 = 1024;
}
*(_DWORD *)(cpu + 12LL) = v5;
}
break;
case 0xFF00u:
v3 = a2 & 0x30;
if ( (a2 & 0x30) != 0 )
{
if ( (a2 & 0x10) != 0 )
{
if ( (a2 & 0x20) == 0 )
joypad_select_button_keys();
}
else
{
joypad_select_direction_keys();
}
}
break;
}
}
LABEL_59:
*(_BYTE *)(gb + v4 + 51887LL) = v3;
return;
}
}
}

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 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 );
*(_WORD *)(cpu + 6LL) -= 16;
result = (unsigned int)(unsigned __int8)(*(_BYTE *)(gb + 51972LL))-- - 1;
if ( (_BYTE)result == 0xFF )
{
result = cpu;
*(_BYTE *)(cpu + 8LL) = 0;
}
return result;
}

canonical_decompiled_code:
__int64 func15()
{
int v0; // ebx
unsigned __int16 v1; // di
unsigned __int8 v2; // al
unsigned __int16 v3; // di
__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 );
*(_WORD *)(cpu + 6LL) -= 16;
result = (unsigned int)(unsigned __int8)(*(_BYTE *)(gb + 51972LL))-- - 1;
if ( (_BYTE)result == 0xFF )
{
result = cpu;
*(_BYTE *)(cpu + 8LL) = 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