decompiled_code:
int __fastcall hardware_hwq(unsigned __int16 a1)
{
__int64 v1; // rdi
int result; // eax
int *v3; // rbx

v1 = 4LL * a1;
result = hardware[v1];
v3 = &hardware[v1];
if ( result == 1 )
{
write_register(0LL, **((unsigned __int16 **)v3 + 1));
write_register(1LL, HIWORD(**((_DWORD **)v3 + 1)));
write_register(2LL, *(unsigned __int16 *)(*((_QWORD *)v3 + 1) + 4LL));
write_register(3LL, *(unsigned __int16 *)(*((_QWORD *)v3 + 1) + 8LL));
result = write_register(4LL, *(unsigned __int16 *)(*((_QWORD *)v3 + 1) + 10LL));
}
else if ( result == 2 )
{
result = module_cmd_constprop_0(*((int **)v3 + 1), "hwq\n");
}
return result;
}

canonical_decompiled_code:
int __fastcall func8(unsigned __int16 a1)
{
__int64 v1; // rdi
int result; // eax
int *v3; // rbx

v1 = 4LL * a1;
result = hardware[v1];
v3 = &hardware[v1];
if ( result == 1 )
{
write_register(0LL, **((unsigned __int16 **)v3 + 1));
write_register(1LL, HIWORD(**((_DWORD **)v3 + 1)));
write_register(2LL, *(unsigned __int16 *)(*((_QWORD *)v3 + 1) + 4LL));
write_register(3LL, *(unsigned __int16 *)(*((_QWORD *)v3 + 1) + 8LL));
result = write_register(4LL, *(unsigned __int16 *)(*((_QWORD *)v3 + 1) + 10LL));
}
else if ( result == 2 )
{
result = func2(*((int **)v3 + 1), "hwq\n");
}
return result;
}

original_code:
void hardware_hwq(uint16_t where)
{
 switch (hardware[where].type) {
 case HARDWARE_NONE:
  break;
 case HARDWARE_BUILTIN:
  write_register(REG_A, hardware[where].hw.builtin->id & 0xFFFF);
  write_register(REG_B, hardware[where].hw.builtin->id >> 16);
  write_register(REG_C, hardware[where].hw.builtin->version);
  write_register(REG_X, hardware[where].hw.builtin->mfg & 0xFFFF);
  write_register(REG_Y, hardware[where].hw.builtin->mfg >> 16);
  break;
 case HARDWARE_MODULE:
  module_cmd(hardware[where].hw.module, "hwq\n", 4);
  break;
 default:
  break;
 }
}

canonical_original_code:
void hardware_hwq(unsigned short where)
{
 switch (hardware[where].type) {
 case HARDWARE_NONE:
  break;
 case HARDWARE_BUILTIN:
  write_register(REG_A, hardware[where].hw.builtin->id & 0xFFFF);
  write_register(REG_B, hardware[where].hw.builtin->id >> 16);
  write_register(REG_C, hardware[where].hw.builtin->version);
  write_register(REG_X, hardware[where].hw.builtin->mfg & 0xFFFF);
  write_register(REG_Y, hardware[where].hw.builtin->mfg >> 16);
  break;
 case HARDWARE_MODULE:
  module_cmd(hardware[where].hw.module, "hwq\n", 4);
  break;
 default:
  break;
 }
}


decompiled_code:
size_t hardware_step_all()
{
void *v0; // rbx
size_t result; // rax
unsigned __int16 v2; // di

v0 = 0LL;
do
{
while ( 1 )
{
result = (unsigned int)hardware[4 * (_QWORD)v0];
if ( (_DWORD)result )
break;
v0 = (char *)v0 + 1;
if ( v0 == &unk_10000 )
return result;
}
v2 = (unsigned __int16)v0;
v0 = (char *)v0 + 1;
result = hardware_step(v2);
}
while ( v0 != &unk_10000 );
return result;
}

canonical_decompiled_code:
size_t func9()
{
void *v0; // rbx
size_t result; // rax
unsigned __int16 v2; // di

v0 = 0LL;
do
{
while ( 1 )
{
result = (unsigned int)hardware[4 * (_QWORD)v0];
if ( (_DWORD)result )
break;
v0 = (char *)v0 + 1;
if ( v0 == &unk_10000 )
return result;
}
v2 = (unsigned __int16)v0;
v0 = (char *)v0 + 1;
result = func4(v2);
}
while ( v0 != &unk_10000 );
return result;
}

original_code:
void hardware_step_all(void)
{
 int i;
 for (i = 0; i < 0x10000; i++)
  if (hardware[i].type != HARDWARE_NONE)
   hardware_step(i);
}

canonical_original_code:
void hardware_step_all()
{
 int i;
 for (i = 0; i < 0x10000; i++)
  if (hardware[i].type != HARDWARE_NONE)
   hardware_step(i);
}

variable_types: i int

return_type: void


decompiled_code:
__int64 hardware_get_attached()
{
return (unsigned __int16)attached;
}

canonical_decompiled_code:
__int64 func10()
{
return (unsigned __int16)attached;
}

original_code:
uint16_t hardware_get_attached(void)
{
 return attached;
}

canonical_original_code:
unsigned short hardware_get_attached()
{
 return attached;
}

return_type: unsigned short


decompiled_code:
void __fastcall clock_tick(__int16 a1)
{
clock_time += a1;
}

canonical_decompiled_code:
void __fastcall func0(__int16 a1)
{
clock_time += a1;
}

original_code:
void clock_tick(uint16_t cycles)
{
 clock_time += cycles;
}

canonical_original_code:
void clock_tick(unsigned short cycles)
{
 clock_time += cycles;
}

variable_types:
cycles
unsigned short


decompiled_code:
__int16 *next_word_addr()
{
__int64 v0; // rax
__int16 v1; // dx
__int16 *result; // rax

clock_tick(1);
v0 = (unsigned __int16)registers[8];
v1 = v0 + 1;
result = &memory[v0];
registers[8] = v1;
return result;
}

canonical_decompiled_code:
__int16 *func1()
{
__int64 v0; // rax
__int16 v1; // dx
__int16 *result; // rax

func0(1);
v0 = (unsigned __int16)registers[8];
v1 = v0 + 1;
result = &memory[v0];
registers[8] = v1;
return result;
}

original_code:
uint16_t *next_word_addr(void)
{
 clock_tick(1);
 return &memory[registers.PC++];
}

canonical_original_code:
unsigned short *next_word_addr()
{
 clock_tick(1);
 return &memory[registers.PC++];
}

return_type: unsigned short *


decompiled_code:
__int64 next_word()
{
return (unsigned __int16)*next_word_addr();
}

canonical_decompiled_code:
__int64 func2()
{
return (unsigned __int16)*func1();
}

original_code:
uint16_t next_word(void)
{
 return *next_word_addr();
}

canonical_original_code:
unsigned short next_word()
{
 return *next_word_addr();
}


decompiled_code:
__int64 __fastcall decode_rvalue(int a1, __int64 a2, __int64 a3, __int64 a4)
{
__int64 result; // rax
__int64 v5; // rax
__int16 v6; // dx

if ( (_WORD)a1 == 24 )
{
v5 = (unsigned __int16)registers[9];
v6 = v5 + 1;
result = (unsigned __int16)memory[v5];
registers[9] = v6;
}
else
{
result = (unsigned int)(a1 - 33);
if ( (unsigned __int16)a1 <= 0x1Fu )
result = (unsigned __int16)*decode_lvalue((unsigned __int16)a1, a2, a3, a4);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(int a1, __int64 a2, __int64 a3, __int64 a4)
{
__int64 result; // rax
__int64 v5; // rax
__int16 v6; // dx

if ( (_WORD)a1 == 24 )
{
v5 = (unsigned __int16)registers[9];
v6 = v5 + 1;
result = (unsigned __int16)memory[v5];
registers[9] = v6;
}
else
{
result = (unsigned int)(a1 - 33);
if ( (unsigned __int16)a1 <= 0x1Fu )
result = (unsigned __int16)*decode_lvalue((unsigned __int16)a1, a2, a3, a4);
}
return result;
}

original_code:
uint16_t decode_rvalue(uint16_t val)
{
 if (val == 0x18)
  return memory[registers.SP++];
 else if (val < 0x20)
  return *decode_lvalue(val);
 else
  return val - 0x21;
}

canonical_original_code:
unsigned short decode_rvalue(unsigned short val)
{
 if (val == 0x18)
  return memory[registers.SP++];
 else if (val < 0x20)
  return *decode_lvalue(val);
 else
  return val - 0x21;
}

variable_types:
val
unsigned short


skip

decompiled_code:
__int64 skip()
{
__int64 v0; // rsi
__int64 v1; // rdx
__int64 v2; // rcx
unsigned int v3; // eax
unsigned __int64 v4; // rdi
int v5; // ecx
__int64 result; // rax

v0 = 3305046016LL;
do
{
clock_tick(1);
v3 = next_word(1LL, 3305046016LL, v1, v2);
v4 = v3;
v5 = v3 & 0x1F;
if ( (v3 & 0x8000u) == 0 )
{
LOWORD(v4) = (unsigned __int16)v3 >> 10;
if ( _bittest64(&v0, v4) )
++registers[8];
}
if ( _bittest64(&v0, ((unsigned __int16)v3 >> 5) & 0x1F) )
++registers[8];
result = (unsigned int)(v5 - 16);
}
while ( (unsigned __int16)(v5 - 16) <= 7u );
return result;
}

canonical_decompiled_code:
__int64 func4()
{
__int64 v0; // rsi
__int64 v1; // rdx
__int64 v2; // rcx
unsigned int v3; // eax
unsigned __int64 v4; // rdi
int v5; // ecx
__int64 result; // rax

v0 = 3305046016LL;
do
{
func0(1);
v3 = func2(1LL, 3305046016LL, v1, v2);
v4 = v3;
v5 = v3 & 0x1F;
if ( (v3 & 0x8000u) == 0 )
{
LOWORD(v4) = (unsigned __int16)v3 >> 10;
if ( _bittest64(&v0, v4) )
++registers[8];
}
if ( _bittest64(&v0, ((unsigned __int16)v3 >> 5) & 0x1F) )
++registers[8];
result = (unsigned int)(v5 - 16);
}
while ( (unsigned __int16)(v5 - 16) <= 7u );
return result;
}

canonical_original_code:
void skip()
{
 unsigned short inst; unsigned short op; unsigned short val_a; unsigned short val_b;
 do {
  clock_tick(1);
  inst = next_word();
  op = inst & 0x1F;
  val_b = (inst >> 5) & 0x1F;
  val_a = (inst >> 10) & 0x3F;
  if (((val_a >= 0x10) && (val_a <= 0x17)) ||
    (val_a == 0x1A) || (val_a == 0x1E) || (val_a == 0x1F))
   registers.PC++;
  if (((val_b >= 0x10) && (val_b <= 0x17)) ||
    (val_b == 0x1A) || (val_b == 0x1E) || (val_b == 0x1F))
   registers.PC++;
 } while ((op >= 0x10) && (op <= 0x17));
}

variable_types:
inst
unsigned short

variable_types:
op
unsigned short


decompiled_code:
void __fastcall ex_spc(unsigned __int16 a1)
{
__int64 v1; // rsi
__int16 v2; // ax
__int64 v3; // rdx
__int64 v4; // rcx
unsigned __int16 v5; // di
__int16 *v6; // rbx
unsigned __int16 v7; // ax
__int64 v8; // rdx
unsigned __int16 v9; // dx
__int16 v10; // cx

v1 = (a1 >> 5) & 0x1F;
clock_tick(spc_inst_clocks[(a1 >> 5) & 0x1F]);
if ( ((a1 >> 5) & 0x1F) != 0 )
{
v5 = (unsigned __int16)v2 >> 10;
if ( v2 < 0 )
{
v7 = decode_rvalue(v5, v1, v3, v4);
switch ( (__int16)v1 )
{
case 1:
LABEL_12:
v9 = registers[9] - 1;
v10 = registers[8];
registers[8] = v7;
registers[9] = v9;
memory[v9] = v10;
break;
case 8:
LABEL_11:
queue_interrupt(v7);
break;
case 10:
LABEL_10:
registers[11] = v7;
break;
case 11:
LABEL_9:
v8 = (unsigned __int16)registers[9];
interrupts_enabled = 1;
registers[0] = memory[v8];
registers[9] = v8 + 2;
registers[8] = memory[(unsigned __int16)(v8 + 1)];
break;
case 12:
LABEL_4:
interrupts_enabled = v7 == 0;
break;
case 17:
LABEL_8:
hardware_hwq(v7);
break;
case 18:
LABEL_7:
hardware_hwi(v7);
break;
default:
return;
}
}
else
{
v6 = decode_lvalue(v5 & 0x1F, v1, v3, v4);
v7 = *v6;
switch ( (__int16)v1 )
{
case 1:
goto LABEL_12;
case 8:
goto LABEL_11;
case 9:
*v6 = registers[11];
break;
case 10:
goto LABEL_10;
case 11:
goto LABEL_9;
case 12:
goto LABEL_4;
case 16:
*v6 = hardware_get_attached();
break;
case 17:
goto LABEL_8;
case 18:
goto LABEL_7;
default:
return;
}
}
}
}

canonical_decompiled_code:
void __fastcall func5(unsigned __int16 a1)
{
__int64 v1; // rsi
__int16 v2; // ax
__int64 v3; // rdx
__int64 v4; // rcx
unsigned __int16 v5; // di
__int16 *v6; // rbx
unsigned __int16 v7; // ax
__int64 v8; // rdx
unsigned __int16 v9; // dx
__int16 v10; // cx

v1 = (a1 >> 5) & 0x1F;
func0(spc_inst_clocks[(a1 >> 5) & 0x1F]);
if ( ((a1 >> 5) & 0x1F) != 0 )
{
v5 = (unsigned __int16)v2 >> 10;
if ( v2 < 0 )
{
v7 = func3(v5, v1, v3, v4);
switch ( (__int16)v1 )
{
case 1:
LABEL_12:
v9 = registers[9] - 1;
v10 = registers[8];
registers[8] = v7;
registers[9] = v9;
memory[v9] = v10;
break;
case 8:
LABEL_11:
queue_interrupt(v7);
break;
case 10:
LABEL_10:
registers[11] = v7;
break;
case 11:
LABEL_9:
v8 = (unsigned __int16)registers[9];
interrupts_enabled = 1;
registers[0] = memory[v8];
registers[9] = v8 + 2;
registers[8] = memory[(unsigned __int16)(v8 + 1)];
break;
case 12:
LABEL_4:
interrupts_enabled = v7 == 0;
break;
case 17:
LABEL_8:
hardware_hwq(v7);
break;
case 18:
LABEL_7:
hardware_hwi(v7);
break;
default:
return;
}
}
else
{
v6 = decode_lvalue(v5 & 0x1F, v1, v3, v4);
v7 = *v6;
switch ( (__int16)v1 )
{
case 1:
goto LABEL_12;
case 8:
goto LABEL_11;
case 9:
*v6 = registers[11];
break;
case 10:
goto LABEL_10;
case 11:
goto LABEL_9;
case 12:
goto LABEL_4;
case 16:
*v6 = hardware_get_attached();
break;
case 17:
goto LABEL_8;
case 18:
goto LABEL_7;
default:
return;
}
}
}
}

original_code:
void ex_spc(uint16_t inst)
{
 uint16_t op, rvalue, *lvalue;
 op = (inst >> 5) & 0x1F;
 clock_tick(spc_inst_clocks[op]);
 if (op == RES) {
  return;
 }
 if (((inst >> 10) & 0x3F) < 0x20) {
  lvalue = decode_lvalue((inst >> 10) & 0x1F);
  rvalue = *lvalue;
 } else {
  lvalue = ((void *)0);
  rvalue = decode_rvalue((inst >> 10) & 0x3F);
 }
 switch (op) {
 case JSR:
  memory[--registers.SP] = registers.PC;
  registers.PC = rvalue;
  break;
 case INT:
  queue_interrupt(rvalue);
  break;
 case IAG:
  if (lvalue != ((void *)0))
   *lvalue = registers.IA;
  break;
 case IAS:
  registers.IA = rvalue;
  break;
 case RFI:
  interrupts_enabled = 1;
  registers.A = memory[registers.SP++];
  registers.PC = memory[registers.SP++];
  break;
 case IAQ:
  if (rvalue == 0)
   interrupts_enabled = 1;
  else
   interrupts_enabled = 0;
  break;
 case HWN:
  if (lvalue != ((void *)0))
   *lvalue = hardware_get_attached();
  break;
 case HWQ:
  hardware_hwq(rvalue);
  break;
 case HWI:
  hardware_hwi(rvalue);
  break;
 default:
  break;
 }
}

canonical_original_code:
void ex_spc(unsigned short inst)
{
 unsigned short op; unsigned short rvalue; unsigned short *lvalue;
 op = (inst >> 5) & 0x1F;
 clock_tick(spc_inst_clocks[op]);
 if (op == RES) {
  return;
 }
 if (((inst >> 10) & 0x3F) < 0x20) {
  lvalue = decode_lvalue((inst >> 10) & 0x1F);
  rvalue = *lvalue;
 } else {
  lvalue = ((void *)0);
  rvalue = decode_rvalue((inst >> 10) & 0x3F);
 }
 switch (op) {
 case JSR:
  memory[--registers.SP] = registers.PC;
  registers.PC = rvalue;
  break;
 case INT:
  queue_interrupt(rvalue);
  break;
 case IAG:
  if (lvalue != ((void *)0))
   *lvalue = registers.IA;
  break;
 case IAS:
  registers.IA = rvalue;
  break;
 case RFI:
  interrupts_enabled = 1;
  registers.A = memory[registers.SP++];
  registers.PC = memory[registers.SP++];
  break;
 case IAQ:
  if (rvalue == 0)
   interrupts_enabled = 1;
  else
   interrupts_enabled = 0;
  break;
 case HWN:
  if (lvalue != ((void *)0))
   *lvalue = hardware_get_attached();
  break;
 case HWQ:
  hardware_hwq(rvalue);
  break;
 case HWI:
  hardware_hwi(rvalue);
  break;
 default:
  break;
 }
}

variable_types:
rvalue
unsigned short

variable_types:
lvalue
unsigned short *


ex

decompiled_code:
void __fastcall ex(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
unsigned int v4; // eax
__int64 v5; // rsi
unsigned __int16 v6; // di
__int64 v7; // rdx
__int64 v8; // rcx
__int64 v9; // rdi
__int64 v10; // rdx
__int64 v11; // rcx
__int16 *v12; // rax
int v13; // er9
__int16 *v14; // rsi
__int64 v15; // r8
int v16; // eax
int v17; // edx
int v18; // ecx
int v19; // edx

v4 = next_word(a1, a2, a3, a4);
v5 = v4;
if ( (v4 & 0x1F) != 0 )
{
clock_tick(inst_clocks[v4 & 0x1F] - 1);
v6 = v5;
LOWORD(v5) = (unsigned __int16)v5 >> 5;
decode_rvalue(v6 >> 10, v5, v7, v8);
v9 = v5 & 0x1F;
v12 = decode_lvalue(v9, v5, v10, v11);
v14 = v12;
switch ( v15 )
{
case 0LL:
case 24LL:
case 25LL:
case 28LL:
case 29LL:
return;
case 1LL:
goto LABEL_4;
case 2LL:
registers[10] = ((unsigned __int16)v13 + (unsigned int)(unsigned __int16)*v12) >> 16;
*v12 += v13;
return;
case 3LL:
registers[10] = ((unsigned __int16)*v12 - (unsigned int)(unsigned __int16)v13) >> 16;
*v12 -= v13;
return;
case 4LL:
case 5LL:
registers[10] = ((unsigned __int16)v13 * (unsigned int)(unsigned __int16)*v12) >> 16;
LOWORD(v13) = *v12 * v13;
LABEL_4:
*v12 = v13;
return;
case 6LL:
if ( !(_WORD)v13 )
goto LABEL_44;
registers[10] = ((unsigned __int16)*v12 << 16) / (unsigned int)(unsigned __int16)v13;
*v12 = (unsigned __int16)*v12 / (unsigned __int16)v13;
return;
case 7LL:
if ( (_WORD)v13 )
{
registers[10] = ((unsigned __int16)*v12 << 16) / (unsigned __int16)v13;
*v12 /= (__int16)v13;
}
else
{
LABEL_44:
registers[10] = 0;
*v12 = 0;
}
return;
case 8LL:
if ( !(_WORD)v13 )
goto LABEL_43;
*v12 = (unsigned __int16)*v12 % (unsigned __int16)v13;
return;
case 9LL:
if ( (_WORD)v13 )
*v12 %= (__int16)v13;
else
LABEL_43:
*v12 = 0;
return;
case 10LL:
*v12 &= v13;
return;
case 11LL:
*v12 |= v13;
return;
case 12LL:
*v12 ^= v13;
return;
case 13LL:
registers[10] = (unsigned int)((unsigned __int16)*v12 << 16) >> v13;
*v12 = (int)(unsigned __int16)*v12 >> v13;
return;
case 14LL:
registers[10] = (unsigned int)((unsigned __int16)*v12 << 16) >> v13;
*v12 >>= v13;
return;
case 15LL:
registers[10] = (unsigned int)((unsigned __int16)*v12 << v13) >> 16;
*v12 = (unsigned __int16)*v12 << v13;
return;
case 16LL:
if ( ((unsigned __int16)*v12 & (unsigned __int16)v13) == 0 )
goto LABEL_8;
return;
case 17LL:
if ( ((unsigned __int16)*v12 & (unsigned __int16)v13) != 0 )
goto LABEL_8;
return;
case 18LL:
if ( *v12 != (_WORD)v13 )
goto LABEL_8;
return;
case 19LL:
if ( *v12 == (_WORD)v13 )
goto LABEL_8;
return;
case 20LL:
if ( (unsigned __int16)*v12 <= (unsigned __int16)v13 )
goto LABEL_8;
return;
case 21LL:
if ( *v12 <= (__int16)v13 )
goto LABEL_8;
return;
case 22LL:
if ( (unsigned __int16)*v12 >= (unsigned __int16)v13 )
goto LABEL_8;
return;
case 23LL:
if ( *v12 >= (__int16)v13 )
LABEL_8:
skip(v9, v12);
break;
case 26LL:
v18 = (unsigned __int16)registers[10];
v19 = (unsigned __int16)*v12;
*v12 = v19 + v18 + v13;
registers[10] = (v19 + v18 + (unsigned int)(unsigned __int16)v13) >> 16;
break;
case 27LL:
v16 = (unsigned __int16)*v12;
v17 = (unsigned __int16)registers[10];
*v14 = v16 - v13 - v17;
registers[10] = (unsigned int)(v16 - (v13 + v17)) >> 16;
break;
case 30LL:
*v12 = v13;
++registers[6];
++registers[7];
break;
case 31LL:
*v12 = v13;
--registers[6];
--registers[7];
break;
}
}
else
{
ex_spc(v4);
}
}

canonical_decompiled_code:
void __fastcall func6(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
unsigned int v4; // eax
__int64 v5; // rsi
unsigned __int16 v6; // di
__int64 v7; // rdx
__int64 v8; // rcx
__int64 v9; // rdi
__int64 v10; // rdx
__int64 v11; // rcx
__int16 *v12; // rax
int v13; // er9
__int16 *v14; // rsi
__int64 v15; // r8
int v16; // eax
int v17; // edx
int v18; // ecx
int v19; // edx

v4 = func2(a1, a2, a3, a4);
v5 = v4;
if ( (v4 & 0x1F) != 0 )
{
func0(inst_clocks[v4 & 0x1F] - 1);
v6 = v5;
LOWORD(v5) = (unsigned __int16)v5 >> 5;
func3(v6 >> 10, v5, v7, v8);
v9 = v5 & 0x1F;
v12 = decode_lvalue(v9, v5, v10, v11);
v14 = v12;
switch ( v15 )
{
case 0LL:
case 24LL:
case 25LL:
case 28LL:
case 29LL:
return;
case 1LL:
goto LABEL_4;
case 2LL:
registers[10] = ((unsigned __int16)v13 + (unsigned int)(unsigned __int16)*v12) >> 16;
*v12 += v13;
return;
case 3LL:
registers[10] = ((unsigned __int16)*v12 - (unsigned int)(unsigned __int16)v13) >> 16;
*v12 -= v13;
return;
case 4LL:
case 5LL:
registers[10] = ((unsigned __int16)v13 * (unsigned int)(unsigned __int16)*v12) >> 16;
LOWORD(v13) = *v12 * v13;
LABEL_4:
*v12 = v13;
return;
case 6LL:
if ( !(_WORD)v13 )
goto LABEL_44;
registers[10] = ((unsigned __int16)*v12 << 16) / (unsigned int)(unsigned __int16)v13;
*v12 = (unsigned __int16)*v12 / (unsigned __int16)v13;
return;
case 7LL:
if ( (_WORD)v13 )
{
registers[10] = ((unsigned __int16)*v12 << 16) / (unsigned __int16)v13;
*v12 /= (__int16)v13;
}
else
{
LABEL_44:
registers[10] = 0;
*v12 = 0;
}
return;
case 8LL:
if ( !(_WORD)v13 )
goto LABEL_43;
*v12 = (unsigned __int16)*v12 % (unsigned __int16)v13;
return;
case 9LL:
if ( (_WORD)v13 )
*v12 %= (__int16)v13;
else
LABEL_43:
*v12 = 0;
return;
case 10LL:
*v12 &= v13;
return;
case 11LL:
*v12 |= v13;
return;
case 12LL:
*v12 ^= v13;
return;
case 13LL:
registers[10] = (unsigned int)((unsigned __int16)*v12 << 16) >> v13;
*v12 = (int)(unsigned __int16)*v12 >> v13;
return;
case 14LL:
registers[10] = (unsigned int)((unsigned __int16)*v12 << 16) >> v13;
*v12 >>= v13;
return;
case 15LL:
registers[10] = (unsigned int)((unsigned __int16)*v12 << v13) >> 16;
*v12 = (unsigned __int16)*v12 << v13;
return;
case 16LL:
if ( ((unsigned __int16)*v12 & (unsigned __int16)v13) == 0 )
goto LABEL_8;
return;
case 17LL:
if ( ((unsigned __int16)*v12 & (unsigned __int16)v13) != 0 )
goto LABEL_8;
return;
case 18LL:
if ( *v12 != (_WORD)v13 )
goto LABEL_8;
return;
case 19LL:
if ( *v12 == (_WORD)v13 )
goto LABEL_8;
return;
case 20LL:
if ( (unsigned __int16)*v12 <= (unsigned __int16)v13 )
goto LABEL_8;
return;
case 21LL:
if ( *v12 <= (__int16)v13 )
goto LABEL_8;
return;
case 22LL:
if ( (unsigned __int16)*v12 >= (unsigned __int16)v13 )
goto LABEL_8;
return;
case 23LL:
if ( *v12 >= (__int16)v13 )
LABEL_8:
func4(v9, v12);
break;
case 26LL:
v18 = (unsigned __int16)registers[10];
v19 = (unsigned __int16)*v12;
*v12 = v19 + v18 + v13;
registers[10] = (v19 + v18 + (unsigned int)(unsigned __int16)v13) >> 16;
break;
case 27LL:
v16 = (unsigned __int16)*v12;
v17 = (unsigned __int16)registers[10];
*v14 = v16 - v13 - v17;
registers[10] = (unsigned int)(v16 - (v13 + v17)) >> 16;
break;
case 30LL:
*v12 = v13;
++registers[6];
++registers[7];
break;
case 31LL:
*v12 = v13;
--registers[6];
--registers[7];
break;
}
}
else
{
func5(v4);
}
}

original_code:
void ex(void)
{
 uint16_t inst, op, *lvalue, rvalue, temp_EX;
 inst = next_word();
 op = inst & 0x1F;
 if (op == SPC) {
  ex_spc(inst);
  return;
 }
 clock_tick(inst_clocks[op] - 1);
 rvalue = decode_rvalue((inst >> 10) & 0x3F);
 lvalue = decode_lvalue((inst >> 5) & 0x1F);
 switch (op) {
 case SET:
  *lvalue = rvalue;
  break;
 case ADD:
  registers.EX = (((uint32_t)*lvalue + (uint32_t)rvalue) >> 16) & 0xFFFF;
  *lvalue += rvalue;
  break;
 case SUB:
  registers.EX = (((int32_t)*lvalue - (int32_t)rvalue) >> 16) & 0xFFFF;
  *lvalue -= rvalue;
  break;
 case MUL:
  registers.EX = (((uint32_t)*lvalue * (uint32_t)rvalue) >> 16) & 0xFFFF;
  *lvalue *= rvalue;
  break;
 case MLI:
  registers.EX = (((int32_t)*lvalue * (int32_t)rvalue) >> 16) & 0xFFFF;
  *(int16_t *)lvalue *= (int16_t)rvalue;
  break;
 case DIV:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((uint32_t)*lvalue << 16) / (uint32_t)rvalue) & 0xFFFF;
   *lvalue /= rvalue;
  }
  break;
 case DVI:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((int32_t)*lvalue << 16) / (int32_t)rvalue) & 0xFFFF;
   *(int16_t *)lvalue /= (int16_t)rvalue;
  }
  break;
 case MOD:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *lvalue %= rvalue;
  break;
 case MDI:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *(int16_t *)lvalue %= (int16_t)rvalue;
  break;
 case AND:
  *lvalue &= rvalue;
  break;
 case BOR:
  *lvalue |= rvalue;
  break;
 case XOR:
  *lvalue ^= rvalue;
  break;
 case SHR:
  registers.EX = (((uint32_t)*lvalue << 16) >> rvalue) & 0xFFFF;
  *lvalue >>= rvalue;
  break;
 case ASR:
  registers.EX = (((uint32_t)*lvalue << 16) >> rvalue) & 0xFFFF;
  *(int16_t *)lvalue >>= rvalue;
  break;
 case SHL:
  registers.EX = (((uint32_t)*lvalue << rvalue) >> 16) & 0xFFFF;
  *lvalue <<= rvalue;
  break;
 case IFB:
  if ((*lvalue & rvalue) == 0)
   skip();
  break;
 case IFC:
  if ((*lvalue & rvalue) != 0)
   skip();
  break;
 case IFE:
  if (*lvalue != rvalue)
   skip();
  break;
 case IFN:
  if (*lvalue == rvalue)
   skip();
  break;
 case IFG:
  if (*lvalue <= rvalue)
   skip();
  break;
 case IFA:
  if (*(int16_t *)lvalue <= (int16_t)rvalue)
   skip();
  break;
 case IFL:
  if (*lvalue >= rvalue)
   skip();
  break;
 case IFU:
  if (*(int16_t *)lvalue >= (int16_t)rvalue)
   skip();
  break;
 case ADX:
  temp_EX = (((uint32_t)*lvalue + (uint32_t)rvalue +
       (uint32_t)registers.EX) >> 16) & 0xFFFF;
  *lvalue += (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case SBX:
  temp_EX = (((int32_t)*lvalue - ((int32_t)rvalue +
       (int32_t)registers.EX)) >> 16) & 0xFFFF;
  *lvalue -= (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case STI:
  *lvalue = rvalue;
  registers.I += 1;
  registers.J += 1;
  break;
 case STD:
  *lvalue = rvalue;
  registers.I -= 1;
  registers.J -= 1;
  break;
 default:
  break;
 }
}

canonical_original_code:
void ex()
{
 unsigned short inst; unsigned short op; unsigned short *lvalue; unsigned short rvalue; unsigned short temp_EX;
 inst = next_word();
 op = inst & 0x1F;
 if (op == SPC) {
  ex_spc(inst);
  return;
 }
 clock_tick(inst_clocks[op] - 1);
 rvalue = decode_rvalue((inst >> 10) & 0x3F);
 lvalue = decode_lvalue((inst >> 5) & 0x1F);
 switch (op) {
 case SET:
  *lvalue = rvalue;
  break;
 case ADD:
  registers.EX = (((unsigned int)*lvalue + (unsigned int)rvalue) >> 16) & 0xFFFF;
  *lvalue += rvalue;
  break;
 case SUB:
  registers.EX = (((int)*lvalue - (int)rvalue) >> 16) & 0xFFFF;
  *lvalue -= rvalue;
  break;
 case MUL:
  registers.EX = (((unsigned int)*lvalue * (unsigned int)rvalue) >> 16) & 0xFFFF;
  *lvalue *= rvalue;
  break;
 case MLI:
  registers.EX = (((int)*lvalue * (int)rvalue) >> 16) & 0xFFFF;
  *(short *)lvalue *= (short)rvalue;
  break;
 case DIV:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((unsigned int)*lvalue << 16) / (unsigned int)rvalue) & 0xFFFF;
   *lvalue /= rvalue;
  }
  break;
 case DVI:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((int)*lvalue << 16) / (int)rvalue) & 0xFFFF;
   *(short *)lvalue /= (short)rvalue;
  }
  break;
 case MOD:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *lvalue %= rvalue;
  break;
 case MDI:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *(short *)lvalue %= (short)rvalue;
  break;
 case AND:
  *lvalue &= rvalue;
  break;
 case BOR:
  *lvalue |= rvalue;
  break;
 case XOR:
  *lvalue ^= rvalue;
  break;
 case SHR:
  registers.EX = (((unsigned int)*lvalue << 16) >> rvalue) & 0xFFFF;
  *lvalue >>= rvalue;
  break;
 case ASR:
  registers.EX = (((unsigned int)*lvalue << 16) >> rvalue) & 0xFFFF;
  *(short *)lvalue >>= rvalue;
  break;
 case SHL:
  registers.EX = (((unsigned int)*lvalue << rvalue) >> 16) & 0xFFFF;
  *lvalue <<= rvalue;
  break;
 case IFB:
  if ((*lvalue & rvalue) == 0)
   skip();
  break;
 case IFC:
  if ((*lvalue & rvalue) != 0)
   skip();
  break;
 case IFE:
  if (*lvalue != rvalue)
   skip();
  break;
 case IFN:
  if (*lvalue == rvalue)
   skip();
  break;
 case IFG:
  if (*lvalue <= rvalue)
   skip();
  break;
 case IFA:
  if (*(short *)lvalue <= (short)rvalue)
   skip();
  break;
 case IFL:
  if (*lvalue >= rvalue)
   skip();
  break;
 case IFU:
  if (*(short *)lvalue >= (short)rvalue)
   skip();
  break;
 case ADX:
  temp_EX = (((unsigned int)*lvalue + (unsigned int)rvalue +
       (unsigned int)registers.EX) >> 16) & 0xFFFF;
  *lvalue += (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case SBX:
  temp_EX = (((int)*lvalue - ((int)rvalue +
       (int)registers.EX)) >> 16) & 0xFFFF;
  *lvalue -= (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case STI:
  *lvalue = rvalue;
  registers.I += 1;
  registers.J += 1;
  break;
 case STD:
  *lvalue = rvalue;
  registers.I -= 1;
  registers.J -= 1;
  break;
 default:
  break;
 }
}


decompiled_code:
void sim_init()
{
;
}

canonical_decompiled_code:
void func7()
{
;
}

original_code:
void sim_init(void)
{
}

canonical_original_code:
void sim_init()
{
}


decompiled_code:
__int64 __fastcall sim_step(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
int v4; // ebx

v4 = (unsigned __int16)clock_time;
ex(a1, a2, a3, a4);
if ( interrupts_enabled )
trigger_next_queued_interrupt();
hardware_step_all();
return (unsigned int)(unsigned __int16)clock_time - v4;
}

canonical_decompiled_code:
__int64 __fastcall func8(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
int v4; // ebx

v4 = (unsigned __int16)clock_time;
func6(a1, a2, a3, a4);
if ( interrupts_enabled )
trigger_next_queued_interrupt();
hardware_step_all();
return (unsigned int)(unsigned __int16)clock_time - v4;
}

original_code:
uint16_t sim_step(void)
{
 int clock_before = clock_time;
 ex();
 if (interrupts_enabled)
  trigger_next_queued_interrupt();
 hardware_step_all();
 return clock_time - clock_before;
}

canonical_original_code:
unsigned short sim_step()
{
 int clock_before = clock_time;
 ex();
 if (interrupts_enabled)
  trigger_next_queued_interrupt();
 hardware_step_all();
 return clock_time - clock_before;
}


decompiled_code:
void __fastcall __noreturn run_dcpu16(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
while ( 1 )
sim_step(a1, a2, a3, a4);
}

canonical_decompiled_code:
void __fastcall __noreturn func9(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
while ( 1 )
func8(a1, a2, a3, a4);
}

original_code:
void run_dcpu16(void)
{
 while (1) {
  sim_step();
 }
}

canonical_original_code:
void run_dcpu16()
{
 while (1) {
  sim_step();
 }
}


decompiled_code:
void __noreturn CATCH_FIRE()
{
exit(1);
}

canonical_decompiled_code:
void __noreturn func10()
{
exit(1);
}

original_code:
void CATCH_FIRE(void)
{
 exit(1);
}

canonical_original_code:
void CATCH_FIRE()
{
 exit(1);
}


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
int v6; // [rsp+0h] [rbp-38h] BYREF
char v7; // [rsp+4h] [rbp-34h]

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = get_hw();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
if ( fgets((char *)&v6, 32, stdin) )
{
if ( v6 != 174684008 || v7 )
{
if ( !strcmp((const char *)&v6, "hwq\n") )
hwq(v4);
}
else
{
(*(void (**)(void))(v4 + 24))();
}
puts("done");
fflush(stdout);
}
}
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
int v6; // [rsp+0h] [rbp-38h] BYREF
char v7; // [rsp+4h] [rbp-34h]

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = func20();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
if ( fgets((char *)&v6, 32, stdin) )
{
if ( v6 != 174684008 || v7 )
{
if ( !strcmp((const char *)&v6, "hwq\n") )
func7(v4);
}
else
{
(*(void (**)(void))(v4 + 24))();
}
puts("done");
fflush(stdout);
}
}
return 0;
}

original_code:
int main(int argc, char *argv[])
{
 struct hw_builtin *hw;
 char input[32];
 char *status;
 fcntl(0, 4, fcntl(0, 3) | 04000);
 hw = get_hw();
 printf("%s\n", argv[0]);
 fflush(stdout);
 printf("ready\n");
 fflush(stdout);
 while (!feof(stdin)) {
  (*hw->step)();
  status = fgets(input, 32, stdin);
  if (((void *)0) != status) {
   if (strcmp(input, "hwi\n") == 0)
    (*hw->interrupt)();
   else if (strcmp(input, "hwq\n") == 0)
    hwq(hw);
   printf("done\n");
   fflush(stdout);
  }
 }
 return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); } *

variable_types:
input
char [32]

variable_types:
status
char *

return_type: int


hwq

decompiled_code:
__int64 __fastcall hwq(unsigned __int16 *a1)
{
write_register(0LL, *a1);
write_register(1LL, HIWORD(*(_DWORD *)a1));
write_register(2LL, a1[2]);
write_register(3LL, a1[4]);
return write_register(4LL, a1[5]);
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned __int16 *a1)
{
func13(0LL, *a1);
func13(1LL, HIWORD(*(_DWORD *)a1));
func13(2LL, a1[2]);
func13(3LL, a1[4]);
return func13(4LL, a1[5]);
}

original_code:
void hwq(struct hw_builtin *hw)
{
 write_register(REG_A, hw->id & 0xFFFF);
 write_register(REG_B, hw->id >> 16);
 write_register(REG_C, hw->version);
 write_register(REG_X, hw->mfg & 0xFFFF);
 write_register(REG_Y, hw->mfg >> 16);
}

user_defined_types: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); }


decompiled_code:
int set_input_blocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func8()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_blocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl & ~04000);
}

canonical_original_code:
void set_input_blocking()
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl & ~04000);
}

variable_types: fl int


decompiled_code:
int set_input_nonblocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func9()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_nonblocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl | 04000);
}

canonical_original_code:
void set_input_nonblocking()
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl | 04000);
}


decompiled_code:
__int64 get_uint16()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

set_input_blocking();
fgets(s, 32, stdin);
set_input_nonblocking();
__isoc99_sscanf();
return v1;
}

canonical_decompiled_code:
__int64 func10()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

func8();
fgets(s, 32, stdin);
func9();
__isoc99_sscanf();
return v1;
}

original_code:
uint16_t get_uint16(void)
{
 char buf[32];
 uint16_t ret;
 set_input_blocking();
 fgets(buf, 32, stdin);
 set_input_nonblocking();
 sscanf(buf, "%hu", &ret);
 return ret;
}

canonical_original_code:
unsigned short get_uint16()
{
 char buf[32];
 unsigned short ret;
 set_input_blocking();
 fgets(buf, 32, stdin);
 set_input_nonblocking();
 sscanf(buf, "%hu", &ret);
 return ret;
}

variable_types:
buf
char [32]

variable_types:
ret
unsigned short


decompiled_code:
void clk_init()
{
;
}

canonical_decompiled_code:
void func16()
{
;
}

original_code:
void clk_init(void)
{
}

canonical_original_code:
void clk_init()
{
}


decompiled_code:
void clk_step()
{
int v0; // ebx
unsigned __int64 v1; // rax
struct timespec v2; // [rsp+0h] [rbp-18h] BYREF

if ( clk_enabled )
{
v0 = ticks;
clock_gettime(0, &v2);
v1 = 60 * (v2.tv_nsec + 1000000000 * (v2.tv_sec - t0.tv_sec) - t0.tv_nsec) / 0x3B9ACA00uLL / clk_scale;
ticks = v1;
if ( int_enabled )
{
if ( v0 != (_DWORD)v1 )
raise_interrupt(int_msg);
}
}
}

canonical_decompiled_code:
void func17()
{
int v0; // ebx
unsigned __int64 v1; // rax
struct timespec v2; // [rsp+0h] [rbp-18h] BYREF

if ( clk_enabled )
{
v0 = ticks;
clock_gettime(0, &v2);
v1 = 60 * (v2.tv_nsec + 1000000000 * (v2.tv_sec - t0.tv_sec) - t0.tv_nsec) / 0x3B9ACA00uLL / clk_scale;
ticks = v1;
if ( int_enabled )
{
if ( v0 != (_DWORD)v1 )
func15(int_msg);
}
}
}

original_code:
void clk_step(void)
{
 struct timespec tp;
 uint64_t ns;
 int old_ticks = ticks;
 if (clk_enabled) {
  clock_gettime(0, &tp);
  ns = (tp.tv_sec - t0.tv_sec) * 1000000000;
  ns += (tp.tv_nsec - t0.tv_nsec);
  ticks = ns * 60 / 1000000000 / clk_scale;
  if (int_enabled && (old_ticks != ticks))
   raise_interrupt(int_msg);
 }
}

canonical_original_code:
void clk_step()
{
 struct timespec tp;
 unsigned long ns;
 int old_ticks = ticks;
 if (clk_enabled) {
  clock_gettime(0, &tp);
  ns = (tp.tv_sec - t0.tv_sec) * 1000000000;
  ns += (tp.tv_nsec - t0.tv_nsec);
  ticks = ns * 60 / 1000000000 / clk_scale;
  if (int_enabled && (old_ticks != ticks))
   raise_interrupt(int_msg);
 }
}

variable_types: struct timespec { long tv_sec; long tv_nsec; }

variable_types:
ns
unsigned long


decompiled_code:
__int64 clk_interrupt()
{
unsigned __int16 v0; // bx
__int16 v1; // ax
__int64 result; // rax

v0 = read_register(1u);
v1 = read_register(0);
if ( v1 == 1 )
{
write_register(2u, ticks);
result = 0LL;
}
else if ( v1 == 2 )
{
if ( v0 )
{
int_msg = v0;
result = 0LL;
int_enabled = 1;
}
else
{
int_enabled = 0;
result = 0LL;
}
}
else
{
if ( v1 )
return 0LL;
if ( v0 )
{
clk_enabled = 1;
clock_gettime(0, &t0);
clk_scale = v0;
return 0LL;
}
clk_enabled = 0;
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 func18()
{
unsigned __int16 v0; // bx
__int16 v1; // ax
__int64 result; // rax

v0 = func11(1u);
v1 = func11(0);
if ( v1 == 1 )
{
func13(2u, ticks);
result = 0LL;
}
else if ( v1 == 2 )
{
if ( v0 )
{
int_msg = v0;
result = 0LL;
int_enabled = 1;
}
else
{
int_enabled = 0;
result = 0LL;
}
}
else
{
if ( v1 )
return 0LL;
if ( v0 )
{
clk_enabled = 1;
clock_gettime(0, &t0);
clk_scale = v0;
return 0LL;
}
clk_enabled = 0;
result = 0LL;
}
return result;
}

original_code:
int clk_interrupt(void)
{
 uint16_t b = read_register(REG_B);
 switch(read_register(REG_A)) {
 case 0:
  if (b) {
   clk_enabled = 1;
   clock_gettime(0, &t0);
   clk_scale = b;
  } else {
   clk_enabled = 0;
  }
  break;
 case 1:
  write_register(REG_C, ticks);
  break;
 case 2:
  if (b) {
   int_enabled = 1;
   int_msg = b;
  } else {
   int_enabled = 0;
  }
  break;
 default:
  break;
 }
 return 0;
}

canonical_original_code:
int clk_interrupt()
{
 unsigned short b = read_register(REG_B);
 switch(read_register(REG_A)) {
 case 0:
  if (b) {
   clk_enabled = 1;
   clock_gettime(0, &t0);
   clk_scale = b;
  } else {
   clk_enabled = 0;
  }
  break;
 case 1:
  write_register(REG_C, ticks);
  break;
 case 2:
  if (b) {
   int_enabled = 1;
   int_msg = b;
  } else {
   int_enabled = 0;
  }
  break;
 default:
  break;
 }
 return 0;
}

variable_types:
b
unsigned short


decompiled_code:
__m128i *generic_clock()
{
__m128i *result; // rax
__m128i v1; // xmm1
__int64 (__fastcall *v2)(); // rdx

result = (__m128i *)malloc(0x28uLL);
v1 = _mm_load_si128((const __m128i *)&xmmword_4040B0);
v2 = off_4040C0;
*result = _mm_load_si128((const __m128i *)&clk_builtin);
result[2].m128i_i64[0] = (__int64)v2;
result[1] = v1;
return result;
}

canonical_decompiled_code:
__m128i *func19()
{
__m128i *result; // rax
__m128i v1; // xmm1
__int64 (__fastcall *v2)(); // rdx

result = (__m128i *)malloc(0x28uLL);
v1 = _mm_load_si128((const __m128i *)&xmmword_4040B0);
v2 = off_4040C0;
*result = _mm_load_si128((const __m128i *)&clk_builtin);
result[2].m128i_i64[0] = (__int64)v2;
result[1] = v1;
return result;
}

original_code:
struct hw_builtin *generic_clock(void)
{
 struct hw_builtin *clk;
 clk = (struct hw_builtin *)malloc(sizeof(struct hw_builtin));
 *clk = clk_builtin;
 return clk;
}

canonical_original_code:
struct hw_builtin *generic_clock()
{
 struct hw_builtin *clk;
 clk = (struct hw_builtin *)malloc(sizeof(struct hw_builtin));
 *clk = clk_builtin;
 return clk;
}

return_type: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); } *


decompiled_code:
__int64 __fastcall read_register(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return get_uint16();
}

canonical_decompiled_code:
__int64 __fastcall func11(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return func10();
}

original_code:
uint16_t read_register(uint16_t reg)
{
 printf("reg r %hu\n", reg);
 fflush(stdout);
 return get_uint16();
}

canonical_original_code:
unsigned short read_register(unsigned short reg)
{
 printf("reg r %hu\n", reg);
 fflush(stdout);
 return get_uint16();
}

variable_types:
reg
unsigned short


decompiled_code:
int __fastcall read_memory(unsigned __int16 a1, unsigned __int16 a2, __int64 a3)
{
int result; // eax
__int64 v5; // rbp

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3 + 2LL * ((unsigned int)a2 - 1) + 2;
do
{
result = get_uint16();
a3 += 2LL;
*(_WORD *)(a3 - 2) = result;
}
while ( a3 != v5 );
}
return result;
}

canonical_decompiled_code:
int __fastcall func12(unsigned __int16 a1, unsigned __int16 a2, __int64 a3)
{
int result; // eax
__int64 v5; // rbp

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3 + 2LL * ((unsigned int)a2 - 1) + 2;
do
{
result = func10();
a3 += 2LL;
*(_WORD *)(a3 - 2) = result;
}
while ( a3 != v5 );
}
return result;
}

original_code:
void read_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem r %hu %hu\n", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++)
  buf[i] = get_uint16();
}

canonical_original_code:
void read_memory(unsigned short addr, unsigned short len, unsigned short *buf)
{
 int i;
 printf("mem r %hu %hu\n", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++)
  buf[i] = get_uint16();
}

variable_types:
addr
unsigned short

variable_types:
len
unsigned short

variable_types:
buf
unsigned short *

variable_types: i int


decompiled_code:
int __fastcall write_register(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func13(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

original_code:
void write_register(uint16_t reg, uint16_t val)
{
 printf("reg w %hu %hu\n", reg, val);
 fflush(stdout);
}

canonical_original_code:
void write_register(unsigned short reg, unsigned short val)
{
 printf("reg w %hu %hu\n", reg, val);
 fflush(stdout);
}

variable_types:
val
unsigned short


decompiled_code:
int __fastcall write_memory(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
__int64 v4; // rbp
__int64 v5; // rsi

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = (__int64)&a3[a2];
do
{
v5 = *a3++;
printf(" %hu", v5);
fflush(stdout);
}
while ( a3 != (unsigned __int16 *)v4 );
}
putchar(10);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func14(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
__int64 v4; // rbp
__int64 v5; // rsi

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = (__int64)&a3[a2];
do
{
v5 = *a3++;
printf(" %hu", v5);
fflush(stdout);
}
while ( a3 != (unsigned __int16 *)v4 );
}
putchar(10);
return fflush(stdout);
}

original_code:
void write_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem w %hu %hu", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++) {
  printf(" %hu", buf[i]);
  fflush(stdout);
 }
 printf("\n");
 fflush(stdout);
}

canonical_original_code:
void write_memory(unsigned short addr, unsigned short len, unsigned short *buf)
{
 int i;
 printf("mem w %hu %hu", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++) {
  printf(" %hu", buf[i]);
  fflush(stdout);
 }
 printf("\n");
 fflush(stdout);
}


decompiled_code:
int __fastcall raise_interrupt(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func15(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

original_code:
void raise_interrupt(uint16_t msg)
{
 printf("int %hu\n", msg);
 fflush(stdout);
}

canonical_original_code:
void raise_interrupt(unsigned short msg)
{
 printf("int %hu\n", msg);
 fflush(stdout);
}

variable_types:
msg
unsigned short


decompiled_code:
// attributes: thunk
__m128i *get_hw(void)
{
return generic_clock();
}

canonical_decompiled_code:
__m128i *func20(void)
{
return func19();
}

original_code:
struct hw_builtin *get_hw(void)
{
 return generic_clock();
}

canonical_original_code:
struct hw_builtin *get_hw()
{
 return generic_clock();
}


decompiled_code:
__int64 __fastcall queue_interrupt(__int64 a1)
{
__int64 v1; // rsi
__int64 result; // rax

v1 = (unsigned int)(unsigned __int8)last_unused_interrupt + 1;
if ( (_DWORD)v1 == (unsigned __int8)next_interrupt )
return CATCH_FIRE(a1, v1, (unsigned __int8)last_unused_interrupt);
result = (unsigned __int8)last_unused_interrupt++;
interrupts[(int)result] = a1;
return result;
}

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

v1 = (unsigned int)(unsigned __int8)last_unused_interrupt + 1;
if ( (_DWORD)v1 == (unsigned __int8)next_interrupt )
return CATCH_FIRE(a1, v1, (unsigned __int8)last_unused_interrupt);
result = (unsigned __int8)last_unused_interrupt++;
interrupts[(int)result] = a1;
return result;
}

original_code:
void queue_interrupt(uint16_t msg)
{
 if ((last_unused_interrupt + 1) == next_interrupt)
  CATCH_FIRE();
 else
  interrupts[last_unused_interrupt++] = msg;
}

canonical_original_code:
void queue_interrupt(unsigned short msg)
{
 if ((last_unused_interrupt + 1) == next_interrupt)
  CATCH_FIRE();
 else
  interrupts[last_unused_interrupt++] = msg;
}


decompiled_code:
__int64 __fastcall trigger_interrupt(__int16 a1)
{
__int16 v1; // dx
__int16 v2; // ax
__int16 v3; // si
unsigned __int16 v4; // cx
__int64 result; // rax
__int16 v6; // cx

v1 = registers[11];
if ( v1 )
{
v2 = registers[9];
v3 = registers[8];
interrupts_enabled = 0;
registers[8] = v1;
v4 = v2 - 1;
LOWORD(result) = v2 - 2;
registers[9] = result;
result = (unsigned __int16)result;
*((_WORD *)&memory + v4) = v3;
v6 = registers[0];
registers[0] = a1;
*((_WORD *)&memory + (unsigned __int16)result) = v6;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int16 a1)
{
__int16 v1; // dx
__int16 v2; // ax
__int16 v3; // si
unsigned __int16 v4; // cx
__int64 result; // rax
__int16 v6; // cx

v1 = registers[11];
if ( v1 )
{
v2 = registers[9];
v3 = registers[8];
interrupts_enabled = 0;
registers[8] = v1;
v4 = v2 - 1;
LOWORD(result) = v2 - 2;
registers[9] = result;
result = (unsigned __int16)result;
*((_WORD *)&memory + v4) = v3;
v6 = registers[0];
registers[0] = a1;
*((_WORD *)&memory + (unsigned __int16)result) = v6;
}
return result;
}

original_code:
void trigger_interrupt(uint16_t msg)
{
 if (registers.IA != 0) {
  memory[--registers.SP] = registers.PC;
  memory[--registers.SP] = registers.A;
  registers.PC = registers.IA;
  registers.A = msg;
  interrupts_enabled = 0;
 }
}

canonical_original_code:
void trigger_interrupt(unsigned short msg)
{
 if (registers.IA != 0) {
  memory[--registers.SP] = registers.PC;
  memory[--registers.SP] = registers.A;
  registers.PC = registers.IA;
  registers.A = msg;
  interrupts_enabled = 0;
 }
}


decompiled_code:
__int64 trigger_next_queued_interrupt()
{
__int64 result; // rax
__int16 v1; // di

result = (unsigned __int8)next_interrupt;
if ( last_unused_interrupt != next_interrupt )
{
v1 = interrupts[(unsigned __int8)next_interrupt++];
result = trigger_interrupt(v1);
}
return result;
}

canonical_decompiled_code:
__int64 func2()
{
__int64 result; // rax
__int16 v1; // di

result = (unsigned __int8)next_interrupt;
if ( last_unused_interrupt != next_interrupt )
{
v1 = interrupts[(unsigned __int8)next_interrupt++];
result = func1(v1);
}
return result;
}

original_code:
void trigger_next_queued_interrupt(void)
{
 if (last_unused_interrupt != next_interrupt)
  trigger_interrupt(interrupts[next_interrupt++]);
}

canonical_original_code:
void trigger_next_queued_interrupt()
{
 if (last_unused_interrupt != next_interrupt)
  trigger_interrupt(interrupts[next_interrupt++]);
}


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
int v6; // [rsp+0h] [rbp-38h] BYREF
char v7; // [rsp+4h] [rbp-34h]

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = get_hw();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
if ( fgets((char *)&v6, 32, stdin) )
{
if ( v6 != 174684008 || v7 )
{
if ( !strcmp((const char *)&v6, "hwq\n") )
hwq(v4);
}
else
{
(*(void (**)(void))(v4 + 24))();
}
puts("done");
fflush(stdout);
}
}
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
int v6; // [rsp+0h] [rbp-38h] BYREF
char v7; // [rsp+4h] [rbp-34h]

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = func21();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
if ( fgets((char *)&v6, 32, stdin) )
{
if ( v6 != 174684008 || v7 )
{
if ( !strcmp((const char *)&v6, "hwq\n") )
func7(v4);
}
else
{
(*(void (**)(void))(v4 + 24))();
}
puts("done");
fflush(stdout);
}
}
return 0;
}

original_code:
int main(int argc, char *argv[])
{
 struct hw_builtin *hw;
 char input[32];
 char *status;
 fcntl(0, 4, fcntl(0, 3) | 04000);
 hw = get_hw();
 printf("%s\n", argv[0]);
 fflush(stdout);
 printf("ready\n");
 fflush(stdout);
 while (!feof(stdin)) {
  (*hw->step)();
  status = fgets(input, 32, stdin);
  if (((void *)0) != status) {
   if (strcmp(input, "hwi\n") == 0)
    (*hw->interrupt)();
   else if (strcmp(input, "hwq\n") == 0)
    hwq(hw);
   printf("done\n");
   fflush(stdout);
  }
 }
 return 0;
}

variable_types: argc int

variable_types:
argv
char *[]


hwq

decompiled_code:
__int64 __fastcall hwq(unsigned __int16 *a1)
{
write_register(0LL, *a1);
write_register(1LL, HIWORD(*(_DWORD *)a1));
write_register(2LL, a1[2]);
write_register(3LL, a1[4]);
return write_register(4LL, a1[5]);
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned __int16 *a1)
{
func13(0LL, *a1);
func13(1LL, HIWORD(*(_DWORD *)a1));
func13(2LL, a1[2]);
func13(3LL, a1[4]);
return func13(4LL, a1[5]);
}

original_code:
void hwq(struct hw_builtin *hw)
{
 write_register(REG_A, hw->id & 0xFFFF);
 write_register(REG_B, hw->id >> 16);
 write_register(REG_C, hw->version);
 write_register(REG_X, hw->mfg & 0xFFFF);
 write_register(REG_Y, hw->mfg >> 16);
}

variable_types: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); } *


decompiled_code:
int set_input_blocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func8()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_blocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl & ~04000);
}


decompiled_code:
int set_input_nonblocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func9()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_nonblocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl | 04000);
}


decompiled_code:
__int64 get_uint16()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

set_input_blocking();
fgets(s, 32, stdin);
set_input_nonblocking();
__isoc99_sscanf();
return v1;
}

canonical_decompiled_code:
__int64 func10()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

func8();
fgets(s, 32, stdin);
func9();
__isoc99_sscanf();
return v1;
}

original_code:
uint16_t get_uint16(void)
{
 char buf[32];
 uint16_t ret;
 set_input_blocking();
 fgets(buf, 32, stdin);
 set_input_nonblocking();
 sscanf(buf, "%hu", &ret);
 return ret;
}


decompiled_code:
void fd_init()
{
;
}

canonical_decompiled_code:
void func16()
{
;
}

original_code:
void fd_init(void)
{
}

canonical_original_code:
void fd_init()
{
}


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

if ( (unsigned __int16)(state - 1) > 1u )
return 0xFFFFFFFFLL;
ram_addr = a2;
disk_sector = a1;
state = 3;
result = 0LL;
read_in_progress = 1;
target_track = a1 / 0x12u;
return result;
}

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

if ( (unsigned __int16)(state - 1) > 1u )
return 0xFFFFFFFFLL;
ram_addr = a2;
disk_sector = a1;
state = 3;
result = 0LL;
read_in_progress = 1;
target_track = a1 / 0x12u;
return result;
}

original_code:
static int start_read(uint16_t read_sector, uint16_t addr)
{
 if ((state == STATE_READY) || (state == STATE_READY_WP)) {
  disk_sector = read_sector;
  target_track = read_sector / 18;
  ram_addr = addr;
  read_in_progress = 1;
  state = STATE_BUSY;
  return 0;
 } else {
  return -1;
 }
}

canonical_original_code:
static int start_read(unsigned short read_sector, unsigned short addr)
{
 if ((state == STATE_READY) || (state == STATE_READY_WP)) {
  disk_sector = read_sector;
  target_track = read_sector / 18;
  ram_addr = addr;
  read_in_progress = 1;
  state = STATE_BUSY;
  return 0;
 } else {
  return -1;
 }
}


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

if ( state != 1 )
return 0xFFFFFFFFLL;
ram_addr = a2;
disk_sector = a1;
state = 3;
result = 0LL;
write_in_progress = 1;
target_track = a1 / 0x12u;
return result;
}

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

if ( state != 1 )
return 0xFFFFFFFFLL;
ram_addr = a2;
disk_sector = a1;
state = 3;
result = 0LL;
write_in_progress = 1;
target_track = a1 / 0x12u;
return result;
}

original_code:
static int start_write(uint16_t write_sector, uint16_t addr)
{
 if (state == STATE_READY) {
  disk_sector = write_sector;
  target_track = write_sector / 18;
  ram_addr = addr;
  write_in_progress = 1;
  state = STATE_BUSY;
  return 0;
 } else {
  return -1;
 }
}

canonical_original_code:
static int start_write(unsigned short write_sector, unsigned short addr)
{
 if (state == STATE_READY) {
  disk_sector = write_sector;
  target_track = write_sector / 18;
  ram_addr = addr;
  write_in_progress = 1;
  state = STATE_BUSY;
  return 0;
 } else {
  return -1;
 }
}


decompiled_code:
void fd_step()
{
unsigned __int16 v0; // bx
unsigned __int16 v1; // bp
__int16 v2; // ax

v0 = track;
v1 = target_track;
if ( track == target_track )
{
if ( read_in_progress )
{
if ( reading )
{
if ( clock() - read_start > 16287 )
write_memory(ram_addr, 0x200u, (unsigned __int16 *)(disk + 2LL * (unsigned int)(disk_sector << 9)));
}
else
{
reading = 1;
read_start = clock();
}
}
else if ( write_in_progress )
{
if ( writing )
{
if ( clock() - write_start > 16287 )
read_memory(ram_addr, 0x200u, disk + 2LL * (unsigned int)(disk_sector << 9));
}
else
{
writing = 1;
write_start = clock();
}
}
}
else if ( seeking )
{
if ( clock() - seek_start > 2400 )
{
v2 = v0 - 1;
seeking = 0;
if ( v0 < v1 )
v2 = v0 + 1;
track = v2;
}
}
else
{
seeking = 1;
seek_start = clock();
}
}

canonical_decompiled_code:
void func19()
{
unsigned __int16 v0; // bx
unsigned __int16 v1; // bp
__int16 v2; // ax

v0 = track;
v1 = target_track;
if ( track == target_track )
{
if ( read_in_progress )
{
if ( reading )
{
if ( clock() - read_start > 16287 )
func14(ram_addr, 0x200u, (unsigned __int16 *)(disk + 2LL * (unsigned int)(disk_sector << 9)));
}
else
{
reading = 1;
read_start = clock();
}
}
else if ( write_in_progress )
{
if ( writing )
{
if ( clock() - write_start > 16287 )
func12(ram_addr, 0x200u, disk + 2LL * (unsigned int)(disk_sector << 9));
}
else
{
writing = 1;
write_start = clock();
}
}
}
else if ( seeking )
{
if ( clock() - seek_start > 2400 )
{
v2 = v0 - 1;
seeking = 0;
if ( v0 < v1 )
v2 = v0 + 1;
track = v2;
}
}
else
{
seeking = 1;
seek_start = clock();
}
}

original_code:
void fd_step(void)
{
 if (track != target_track) {
  if (!seeking) {
   seeking = 1;
   seek_start = clock();
  } else {
   if (((clock() - seek_start) * 1000000 / ((__clock_t) 1000000)) > 2400) {
    if (target_track > track)
     track++;
    else
     track--;
    seeking = 0;
   }
  }
 } else if (read_in_progress) {
  if (!reading) {
   reading = 1;
   read_start = clock();
  } else {
   if (((clock() - read_start) * 1000000 / ((__clock_t) 1000000)) > 16287)
    write_memory(ram_addr, 512, &disk[disk_sector * 512]);
  }
 } else if (write_in_progress) {
  if (!writing) {
   writing = 1;
   write_start = clock();
  } else {
   if (((clock() - write_start) * 1000000 / ((__clock_t) 1000000)) > 16287)
    read_memory(ram_addr, 512, &disk[disk_sector * 512]);
  }
 }
}

canonical_original_code:
void fd_step()
{
 if (track != target_track) {
  if (!seeking) {
   seeking = 1;
   seek_start = clock();
  } else {
   if (((clock() - seek_start) * 1000000 / ((long) 1000000)) > 2400) {
    if (target_track > track)
     track++;
    else
     track--;
    seeking = 0;
   }
  }
 } else if (read_in_progress) {
  if (!reading) {
   reading = 1;
   read_start = clock();
  } else {
   if (((clock() - read_start) * 1000000 / ((long) 1000000)) > 16287)
    write_memory(ram_addr, 512, &disk[disk_sector * 512]);
  }
 } else if (write_in_progress) {
  if (!writing) {
   writing = 1;
   write_start = clock();
  } else {
   if (((clock() - write_start) * 1000000 / ((long) 1000000)) > 16287)
    read_memory(ram_addr, 512, &disk[disk_sector * 512]);
  }
 }
}


decompiled_code:
__int64 fd_interrupt()
{
__int16 v0; // ax
__int16 v2; // bx
unsigned __int16 v3; // ax
__int16 v4; // bx
unsigned __int16 v5; // ax

read_register(3u);
v0 = read_register(0);
switch ( v0 )
{
case 2:
v2 = read_register(4u);
v3 = read_register(3u);
if ( (unsigned int)start_read(v3, v2) )
{
LABEL_9:
write_register(1u, 0);
return 0LL;
}
LABEL_7:
write_register(1u, 1u);
return 0LL;
case 3:
v4 = read_register(4u);
v5 = read_register(3u);
if ( (unsigned int)start_write(v5, v4) )
goto LABEL_9;
goto LABEL_7;
case 0:
write_register(1u, state);
write_register(2u, 0);
break;
}
return 0LL;
}

canonical_decompiled_code:
__int64 func20()
{
__int16 v0; // ax
__int16 v2; // bx
unsigned __int16 v3; // ax
__int16 v4; // bx
unsigned __int16 v5; // ax

func11(3u);
v0 = func11(0);
switch ( v0 )
{
case 2:
v2 = func11(4u);
v3 = func11(3u);
if ( (unsigned int)func17(v3, v2) )
{
LABEL_9:
func13(1u, 0);
return 0LL;
}
LABEL_7:
func13(1u, 1u);
return 0LL;
case 3:
v4 = func11(4u);
v5 = func11(3u);
if ( (unsigned int)func18(v5, v4) )
goto LABEL_9;
goto LABEL_7;
case 0:
func13(1u, state);
func13(2u, 0);
break;
}
return 0LL;
}

original_code:
int fd_interrupt(void)
{
 uint16_t x = read_register(REG_X);
 switch (read_register(REG_A)) {
 case 0:
  write_register(REG_B, state);
  write_register(REG_C, error);
  break;
 case 1:
  if (x) {
   int_enabled = 1;
   int_msg = x;
  } else {
   int_enabled = 0;
  }
  break;
 case 2:
  if (start_read(read_register(REG_X), read_register(REG_Y)) == 0)
   write_register(REG_B, 1);
  else
   write_register(REG_B, 0);
  break;
 case 3:
  if (start_write(read_register(REG_X), read_register(REG_Y)) == 0)
   write_register(REG_B, 1);
  else
   write_register(REG_B, 0);
  break;
 default:
  break;
 }
 return 0;
}

canonical_original_code:
int fd_interrupt()
{
 unsigned short x = read_register(REG_X);
 switch (read_register(REG_A)) {
 case 0:
  write_register(REG_B, state);
  write_register(REG_C, error);
  break;
 case 1:
  if (x) {
   int_enabled = 1;
   int_msg = x;
  } else {
   int_enabled = 0;
  }
  break;
 case 2:
  if (start_read(read_register(REG_X), read_register(REG_Y)) == 0)
   write_register(REG_B, 1);
  else
   write_register(REG_B, 0);
  break;
 case 3:
  if (start_write(read_register(REG_X), read_register(REG_Y)) == 0)
   write_register(REG_B, 1);
  else
   write_register(REG_B, 0);
  break;
 default:
  break;
 }
 return 0;
}

variable_types:
x
unsigned short


decompiled_code:
__int64 __fastcall read_register(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return get_uint16();
}

canonical_decompiled_code:
__int64 __fastcall func11(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return func10();
}

original_code:
uint16_t read_register(uint16_t reg)
{
 printf("reg r %hu\n", reg);
 fflush(stdout);
 return get_uint16();
}


decompiled_code:
int __fastcall read_memory(unsigned __int16 a1, unsigned __int16 a2, __int64 a3)
{
int result; // eax
__int64 v5; // rbp

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3 + 2LL * ((unsigned int)a2 - 1) + 2;
do
{
result = get_uint16();
a3 += 2LL;
*(_WORD *)(a3 - 2) = result;
}
while ( a3 != v5 );
}
return result;
}

canonical_decompiled_code:
int __fastcall func12(unsigned __int16 a1, unsigned __int16 a2, __int64 a3)
{
int result; // eax
__int64 v5; // rbp

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3 + 2LL * ((unsigned int)a2 - 1) + 2;
do
{
result = func10();
a3 += 2LL;
*(_WORD *)(a3 - 2) = result;
}
while ( a3 != v5 );
}
return result;
}

original_code:
void read_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem r %hu %hu\n", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++)
  buf[i] = get_uint16();
}


decompiled_code:
int __fastcall write_register(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func13(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

original_code:
void write_register(uint16_t reg, uint16_t val)
{
 printf("reg w %hu %hu\n", reg, val);
 fflush(stdout);
}


decompiled_code:
int __fastcall write_memory(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
__int64 v4; // rbp
__int64 v5; // rsi

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = (__int64)&a3[a2];
do
{
v5 = *a3++;
printf(" %hu", v5);
fflush(stdout);
}
while ( a3 != (unsigned __int16 *)v4 );
}
putchar(10);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func14(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
__int64 v4; // rbp
__int64 v5; // rsi

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = (__int64)&a3[a2];
do
{
v5 = *a3++;
printf(" %hu", v5);
fflush(stdout);
}
while ( a3 != (unsigned __int16 *)v4 );
}
putchar(10);
return fflush(stdout);
}

original_code:
void write_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem w %hu %hu", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++) {
  printf(" %hu", buf[i]);
  fflush(stdout);
 }
 printf("\n");
 fflush(stdout);
}


decompiled_code:
int __fastcall raise_interrupt(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func15(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

original_code:
void raise_interrupt(uint16_t msg)
{
 printf("int %hu\n", msg);
 fflush(stdout);
}


decompiled_code:
__m128i *get_hw()
{
return m35fd(0LL);
}

original_code:
struct hw_builtin *get_hw(void)
{
 return m35fd(((void *)0));
}

canonical_original_code:
struct hw_builtin *get_hw()
{
 return m35fd(((void *)0));
}


repo: jkarni/extendp

decompiled_code:
void __fastcall insert_substring(char *dest, char *src, int a3)
{
int v4; // ebp
char *v5; // r13
char *v6; // rbp
size_t v7; // rax
char *v8; // rax

v4 = strlen(dest);
v5 = substring((__int64)dest, 1, a3 - 1);
v6 = substring((__int64)dest, a3, v4 - a3 + 1);
strcpy(dest, v5);
free(v5);
v7 = strlen(dest);
v8 = stpcpy(&dest[v7], src);
strcpy(v8, v6);
free(v6);
}

canonical_decompiled_code:
void __fastcall func0(char *dest, char *src, int a3)
{
int v4; // ebp
char *v5; // r13
char *v6; // rbp
size_t v7; // rax
char *v8; // rax

v4 = strlen(dest);
v5 = substring((__int64)dest, 1, a3 - 1);
v6 = substring((__int64)dest, a3, v4 - a3 + 1);
strcpy(dest, v5);
free(v5);
v7 = strlen(dest);
v8 = stpcpy(&dest[v7], src);
strcpy(v8, v6);
free(v6);
}

original_code:
void insert_substring(char *a, char *b, int position)
{
   char *f, *e;
   int length;
   length = strlen(a);
   f = substring(a, 1, position - 1 );
   e = substring(a, position, length-position+1);
   strcpy(a, "");
   strcat(a, f);
   free(f);
   strcat(a, b);
   strcat(a, e);
   free(e);
}

canonical_original_code:
void insert_substring(char *a, char *b, int position)
{
   char *f; char *e;
   int length;
   length = strlen(a);
   f = substring(a, 1, position - 1 );
   e = substring(a, position, length-position+1);
   strcpy(a, "");
   strcat(a, f);
   free(f);
   strcat(a, b);
   strcat(a, e);
   free(e);
}

variable_types:
a
char *

variable_types:
b
char *

variable_types: position int

variable_types:
f
char *

variable_types:
e
char *

variable_types: length int


decompiled_code:
size_t __fastcall insert_substring_off(char *a1, char *a2, int a3)
{
size_t result; // rax

insert_substring(a1, a2, offset + a3);
result = strlen(a2);
offset += result;
return result;
}

canonical_decompiled_code:
size_t __fastcall func2(char *a1, char *a2, int a3)
{
size_t result; // rax

func0(a1, a2, offset + a3);
result = strlen(a2);
offset += result;
return result;
}

original_code:
void insert_substring_off(char *a, char *b, int position) {
   extern int offset;
   insert_substring(a, b, (position + offset));
   offset += strlen(b);
}

variable_types: offset int


xmalloc

decompiled_code:
void *__fastcall xmalloc(size_t a1)
{
void *result; // rax

result = malloc(a1);
if ( !result )
{
perror("Error: malloc");
exit(1);
}
return result;
}

canonical_decompiled_code:
void *__fastcall func1(size_t a1)
{
void *result; // rax

result = malloc(a1);
if ( !result )
{
perror("Error: malloc");
exit(1);
}
return result;
}

original_code:
void *xmalloc(size_t size)
{
    void *p = malloc(size);
    if (p) return p;
    perror("Error: malloc");
    exit(1);
}

canonical_original_code:
void *xmalloc(unsigned long size)
{
    void *p = malloc(size);
    if (p) return p;
    perror("Error: malloc");
    exit(1);
}

variable_types:
size
unsigned long

variable_types:
p
void *

return_type: void *


xrealloc

decompiled_code:
void *__fastcall xrealloc(void *a1, size_t a2)
{
void *result; // rax

result = realloc(a1, a2);
if ( !result )
{
perror("Error: realloc");
exit(1);
}
return result;
}

canonical_decompiled_code:
void *__fastcall func2(void *a1, size_t a2)
{
void *result; // rax

result = realloc(a1, a2);
if ( !result )
{
perror("Error: realloc");
exit(1);
}
return result;
}

original_code:
void *xrealloc(void *p, size_t size)
{
    p = realloc(p, size);
    if (p) return p;
    perror("Error: realloc");
    exit(1);
}

canonical_original_code:
void *xrealloc(void *p, unsigned long size)
{
    p = realloc(p, size);
    if (p) return p;
    perror("Error: realloc");
    exit(1);
}


repo: jkbenaim/cboy

decompiled_code:
__int64 __fastcall mbc_romSize2numBanks(unsigned __int8 a1)
{
__int64 result; // rax

if ( a1 > 7u )
{
result = 80LL;
if ( a1 != 83 )
{
if ( a1 == 84 )
{
result = 96LL;
}
else
{
result = 2LL;
if ( a1 == 82 )
result = 72LL;
}
}
}
else
{
result = 2LL;
if ( a1 )
{
switch ( a1 )
{
case 2u:
result = 8LL;
break;
case 3u:
result = 16LL;
break;
case 4u:
result = 32LL;
break;
case 5u:
result = 64LL;
break;
case 6u:
result = 128LL;
break;
case 7u:
result = 256LL;
break;
default:
result = 4LL;
break;
}
}
}
return result;
}

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

if ( a1 > 7u )
{
result = 80LL;
if ( a1 != 83 )
{
if ( a1 == 84 )
{
result = 96LL;
}
else
{
result = 2LL;
if ( a1 == 82 )
result = 72LL;
}
}
}
else
{
result = 2LL;
if ( a1 )
{
switch ( a1 )
{
case 2u:
result = 8LL;
break;
case 3u:
result = 16LL;
break;
case 4u:
result = 32LL;
break;
case 5u:
result = 64LL;
break;
case 6u:
result = 128LL;
break;
case 7u:
result = 256LL;
break;
default:
result = 4LL;
break;
}
}
}
return result;
}

original_code:
int mbc_romSize2numBanks(uint8_t romSize)
{
 switch (romSize) {
 case 0x00:
  return 2;
  break;
 case 0x01:
  return 4;
  break;
 case 0x02:
  return 8;
  break;
 case 0x03:
  return 16;
  break;
 case 0x04:
  return 32;
  break;
 case 0x05:
  return 64;
  break;
 case 0x06:
  return 128;
  break;
 case 0x07:
  return 256;
  break;
 case 0x52:
  return 72;
  break;
 case 0x53:
  return 80;
  break;
 case 0x54:
  return 96;
  break;
 default:
  return 2;
  break;
 }
}

canonical_original_code:
int mbc_romSize2numBanks(unsigned char romSize)
{
 switch (romSize) {
 case 0x00:
  return 2;
  break;
 case 0x01:
  return 4;
  break;
 case 0x02:
  return 8;
  break;
 case 0x03:
  return 16;
  break;
 case 0x04:
  return 32;
  break;
 case 0x05:
  return 64;
  break;
 case 0x06:
  return 128;
  break;
 case 0x07:
  return 256;
  break;
 case 0x52:
  return 72;
  break;
 case 0x53:
  return 80;
  break;
 case 0x54:
  return 96;
  break;
 default:
  return 2;
  break;
 }
}

variable_types:
romSize
unsigned char


decompiled_code:
__int64 __fastcall mbc_ramSize2numBytes(char a1)
{
unsigned __int8 v1; // di
__int64 result; // rax

v1 = a1 - 1;
result = 0LL;
if ( v1 <= 4u )
result = (unsigned int)CSWTCH_2[v1];
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(char a1)
{
unsigned __int8 v1; // di
__int64 result; // rax

v1 = a1 - 1;
result = 0LL;
if ( v1 <= 4u )
result = (unsigned int)CSWTCH_2[v1];
return result;
}

original_code:
int mbc_ramSize2numBytes(uint8_t ramSize)
{
 switch (ramSize) {
 case 0x00:
  return 0;
  break;
 case 0x01:
  return 2048;
  break;
 case 0x02:
  return 8192;
  break;
 case 0x03:
  return 32768;
  break;
 case 0x04:
  return 131072;
  break;
 case 0x05:
  return 65536;
  break;
 default:
  return 0;
  break;
 }
}

canonical_original_code:
int mbc_ramSize2numBytes(unsigned char ramSize)
{
 switch (ramSize) {
 case 0x00:
  return 0;
  break;
 case 0x01:
  return 2048;
  break;
 case 0x02:
  return 8192;
  break;
 case 0x03:
  return 32768;
  break;
 case 0x04:
  return 131072;
  break;
 case 0x05:
  return 65536;
  break;
 default:
  return 0;
  break;
 }
}

variable_types:
ramSize
unsigned char


decompiled_code:
__int64 mbc_none_read_ff()
{
return 0xFFFFFFFFLL;
}

canonical_decompiled_code:
__int64 func0()
{
return 0xFFFFFFFFLL;
}

original_code:
uint8_t mbc_none_read_ff(uint16_t address)
{
 return 0xff;
}

canonical_original_code:
unsigned char mbc_none_read_ff(unsigned short address)
{
 return 0xff;
}

variable_types:
address
unsigned short

return_type: unsigned char


decompiled_code:
void mbc_none_write_dummy()
{
;
}

canonical_decompiled_code:
void func1()
{
;
}

original_code:
void mbc_none_write_dummy(uint16_t address, uint8_t data)
{
}

canonical_original_code:
void mbc_none_write_dummy(unsigned short address, unsigned char data)
{
}

variable_types:
data
unsigned char


decompiled_code:
__int64 __fastcall mbc_none_read_bank_0(unsigned __int16 a1)
{
return *(unsigned __int8 *)(cart[6] + a1);
}

canonical_decompiled_code:
__int64 __fastcall func2(unsigned __int16 a1)
{
return *(unsigned __int8 *)(cart[6] + a1);
}

original_code:
uint8_t mbc_none_read_bank_0(uint16_t address)
{
 return cart.cartrom_bank_zero[address];
}

canonical_original_code:
unsigned char mbc_none_read_bank_0(unsigned short address)
{
 return cart.cartrom_bank_zero[address];
}


decompiled_code:
__int64 __fastcall mbc_none_read_bank_n(__int16 a1)
{
return *(unsigned __int8 *)(cart[7] + (a1 & 0x3FFF));
}

canonical_decompiled_code:
__int64 __fastcall func3(__int16 a1)
{
return *(unsigned __int8 *)(cart[7] + (a1 & 0x3FFF));
}

original_code:
uint8_t mbc_none_read_bank_n(uint16_t address)
{
 return cart.cartrom_bank_n[address & 0x3fff];
}

canonical_original_code:
unsigned char mbc_none_read_bank_n(unsigned short address)
{
 return cart.cartrom_bank_n[address & 0x3fff];
}


decompiled_code:
__int64 __fastcall mbc_none_read_extram(__int16 a1)
{
return *(unsigned __int8 *)(cart[14] + (a1 & 0x1FFF));
}

canonical_decompiled_code:
__int64 __fastcall func4(__int16 a1)
{
return *(unsigned __int8 *)(cart[14] + (a1 & 0x1FFF));
}

original_code:
uint8_t mbc_none_read_extram(uint16_t address)
{
 return cart.extram_bank[address & 0x1fff];
}

canonical_original_code:
unsigned char mbc_none_read_extram(unsigned short address)
{
 return cart.extram_bank[address & 0x1fff];
}


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

result = cart[14];
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
return result;
}

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

result = cart[14];
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
return result;
}

original_code:
void mbc_none_write_extram(uint16_t address, uint8_t data)
{
 cart.extram_bank[address & 0x1fff] = data;
}

canonical_original_code:
void mbc_none_write_extram(unsigned short address, unsigned char data)
{
 cart.extram_bank[address & 0x1fff] = data;
}


decompiled_code:
void mbc_none_cleanup()
{
;
}

canonical_decompiled_code:
void func6()
{
;
}

original_code:
void mbc_none_cleanup()
{
}

canonical_original_code:
void mbc_none_cleanup()
{
}


decompiled_code:
__int64 mbc_none_install()
{
char *v0; // rax
unsigned __int64 v1; // rax
char *v2; // rax
unsigned __int64 v3; // rdx
unsigned __int64 v4; // rdx
int v5; // ecx
int v6; // eax
__int64 v7; // rsi
__int64 v8; // rdx
__int64 v9; // rsi
__int64 v10; // rdx
__int64 v11; // rdx
__int64 v12; // rdx
__int64 v13; // rax
__int64 result; // rax

cart[20] = mbc_none_cleanup;
v0 = (char *)&readmem;
do
{
*(_QWORD *)v0 = mbc_none_read_bank_0;
v0 += 8;
}
while ( v0 != (char *)&readmem + 512 );
v1 = (unsigned int)((_DWORD)&readmem + 512);
do
{
*(_QWORD *)v1 = mbc_none_read_bank_n;
v1 += 8LL;
}
while ( (_UNKNOWN *)v1 != (_UNKNOWN *)((char *)&readmem + 1024) );
v2 = (char *)&writemem;
do
{
*(_QWORD *)v2 = mbc_none_write_dummy;
v2 += 8;
}
while ( v2 != (char *)&writemem + 1024 );
v3 = 0x2000LL;
if ( cart[18] <= 0x2000uLL )
v3 = cart[18];
v4 = v3 >> 8;
v5 = v4 + 160;
v6 = v4 + 160;
if ( !(_DWORD)v4 )
goto LABEL_15;
v7 = (unsigned int)(v4 - 1);
v8 = 160LL;
v9 = v7 + 161;
do
*((_QWORD *)&readmem + v8++) = mbc_none_read_extram;
while ( v8 != v9 );
if ( v5 != 192 )
{
LABEL_15:
v10 = v5;
do
*((_QWORD *)&readmem + v10++) = mbc_none_read_ff;
while ( (int)v10 <= 191 );
if ( v5 == 160 )
goto LABEL_23;
}
v11 = 160LL;
do
*((_QWORD *)&writemem + v11++) = mbc_none_write_extram;
while ( v5 > (int)v11 );
if ( v5 != 192 )
{
LABEL_23:
do
{
v12 = v6++;
*((_QWORD *)&writemem + v12) = mbc_none_write_dummy;
}
while ( v6 != 192 );
}
v13 = cart[4];
cart[6] = v13;
result = v13 + 0x4000;
cart[7] = result;
return result;
}

canonical_decompiled_code:
__int64 func7()
{
char *v0; // rax
unsigned __int64 v1; // rax
char *v2; // rax
unsigned __int64 v3; // rdx
unsigned __int64 v4; // rdx
int v5; // ecx
int v6; // eax
__int64 v7; // rsi
__int64 v8; // rdx
__int64 v9; // rsi
__int64 v10; // rdx
__int64 v11; // rdx
__int64 v12; // rdx
__int64 v13; // rax
__int64 result; // rax

cart[20] = mbc_none_cleanup;
v0 = (char *)&readmem;
do
{
*(_QWORD *)v0 = mbc_none_read_bank_0;
v0 += 8;
}
while ( v0 != (char *)&readmem + 512 );
v1 = (unsigned int)((_DWORD)&readmem + 512);
do
{
*(_QWORD *)v1 = mbc_none_read_bank_n;
v1 += 8LL;
}
while ( (_UNKNOWN *)v1 != (_UNKNOWN *)((char *)&readmem + 1024) );
v2 = (char *)&writemem;
do
{
*(_QWORD *)v2 = mbc_none_write_dummy;
v2 += 8;
}
while ( v2 != (char *)&writemem + 1024 );
v3 = 0x2000LL;
if ( cart[18] <= 0x2000uLL )
v3 = cart[18];
v4 = v3 >> 8;
v5 = v4 + 160;
v6 = v4 + 160;
if ( !(_DWORD)v4 )
goto LABEL_15;
v7 = (unsigned int)(v4 - 1);
v8 = 160LL;
v9 = v7 + 161;
do
*((_QWORD *)&readmem + v8++) = mbc_none_read_extram;
while ( v8 != v9 );
if ( v5 != 192 )
{
LABEL_15:
v10 = v5;
do
*((_QWORD *)&readmem + v10++) = mbc_none_read_ff;
while ( (int)v10 <= 191 );
if ( v5 == 160 )
goto LABEL_23;
}
v11 = 160LL;
do
*((_QWORD *)&writemem + v11++) = mbc_none_write_extram;
while ( v5 > (int)v11 );
if ( v5 != 192 )
{
LABEL_23:
do
{
v12 = v6++;
*((_QWORD *)&writemem + v12) = mbc_none_write_dummy;
}
while ( v6 != 192 );
}
v13 = cart[4];
cart[6] = v13;
result = v13 + 0x4000;
cart[7] = result;
return result;
}

original_code:
void mbc_none_install()
{
 cart.cleanup = &mbc_none_cleanup;
 int i;
 for (i = 0x00; i <= 0x3F; ++i) {
  readmem[i] = mbc_none_read_bank_0;
 }
 for (i = 0x40; i <= 0x7F; ++i) {
  readmem[i] = mbc_none_read_bank_n;
 }
 for (i = 0x00; i <= 0x7F; ++i) {
  writemem[i] = mbc_none_write_dummy;
 }
 int extram_end =
     0xA0 + (cart.extram_size > 8192 ? 8192 : cart.extram_size) / 256;
 for (i = 0xA0; i < extram_end; ++i) {
  readmem[i] = mbc_none_read_extram;
 }
 for (i = extram_end; i <= 0xBF; ++i) {
  readmem[i] = mbc_none_read_ff;
 }
 for (i = 0xA0; i < extram_end; ++i) {
  writemem[i] = mbc_none_write_extram;
 }
 for (i = extram_end; i <= 0xBF; ++i) {
  writemem[i] = mbc_none_write_dummy;
 }
 cart.cartrom_bank_zero = cart.cartrom;
 cart.cartrom_bank_n = cart.cartrom + 0x4000;
}

variable_types: i int


decompiled_code:
_BOOL8 pqueue_init()
{
return calloc(1uLL, 8uLL) == 0LL;
}

canonical_decompiled_code:
_BOOL8 func0()
{
return calloc(1uLL, 8uLL) == 0LL;
}

original_code:
int pqueue_init(pqueue_root * root)
{
 pqueue_root *newRoot = calloc(1, sizeof(pqueue_root));
 if (newRoot) {
  root = newRoot;
  return 0;
 } else {
  return 1;
 }
}

canonical_original_code:
int pqueue_init(struct pqueue_root_s *root)
{
 struct pqueue_root_s *newRoot = calloc(1, sizeof(pqueue_root));
 if (newRoot) {
  root = newRoot;
  return 0;
 } else {
  return 1;
 }
}

variable_types: struct pqueue_root_s { struct pqueue_node_s { struct pqueue_node_s *next; int priority; int message; } *first; } *

user_defined_types: struct pqueue_root_s { struct pqueue_node_s *first; }


decompiled_code:
_BOOL8 __fastcall pqueue_isEmpty(_QWORD *a1)
{
_BOOL8 result; // rax

result = 1LL;
if ( a1 )
result = *a1 == 0LL;
return result;
}

canonical_decompiled_code:
_BOOL8 __fastcall func1(_QWORD *a1)
{
_BOOL8 result; // rax

result = 1LL;
if ( a1 )
result = *a1 == 0LL;
return result;
}

original_code:
int pqueue_isEmpty(pqueue_root * root)
{
 return root == ((void *)0) || root->first == ((void *)0);
}

canonical_original_code:
int pqueue_isEmpty(struct pqueue_root_s *root)
{
 return root == ((void *)0) || root->first == ((void *)0);
}

user_defined_types: struct pqueue_node_s { struct pqueue_node_s *next; int priority; int message; }


decompiled_code:
__int64 __fastcall pqueue_peek(_QWORD *a1)
{
_BOOL4 v1; // er8
__int64 result; // rax

v1 = pqueue_isEmpty(a1);
result = 0LL;
if ( !v1 )
result = *(unsigned int *)(*a1 + 12LL);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func2(_QWORD *a1)
{
_BOOL4 v1; // er8
__int64 result; // rax

v1 = func1(a1);
result = 0LL;
if ( !v1 )
result = *(unsigned int *)(*a1 + 12LL);
return result;
}

original_code:
int pqueue_peek(pqueue_root * root)
{
 if (pqueue_isEmpty(root))
  return 0;
 else
  return root->first->message;
}

canonical_original_code:
int pqueue_peek(struct pqueue_root_s *root)
{
 if (pqueue_isEmpty(root))
  return 0;
 else
  return root->first->message;
}


decompiled_code:
__int64 __fastcall pqueue_pop(__int64 **a1)
{
unsigned int v1; // er8
int v3; // edx
__int64 v4; // rax

v1 = pqueue_peek(a1);
if ( !a1 || pqueue_isEmpty(a1) )
return v1;
v3 = *((_DWORD *)*a1 + 2);
v4 = **a1;
*a1 = (__int64 *)v4;
*(_DWORD *)(v4 + 8) += v3;
return v1;
}

original_code:
int pqueue_pop(pqueue_root * root)
{
 int returnValue = pqueue_peek(root);
 if (root == ((void *)0)) {
 } else {
  if (pqueue_isEmpty(root)) {
  } else {
   int priorityOfPoppedElement = root->first->priority;
   root->first = root->first->next;
   root->first->priority += priorityOfPoppedElement;
  }
 }
 return returnValue;
}

canonical_original_code:
int pqueue_pop(struct pqueue_root_s *root)
{
 int returnValue = pqueue_peek(root);
 if (root == ((void *)0)) {
 } else {
  if (pqueue_isEmpty(root)) {
  } else {
   int priorityOfPoppedElement = root->first->priority;
   root->first = root->first->next;
   root->first->priority += priorityOfPoppedElement;
  }
 }
 return returnValue;
}

variable_types: returnValue int

variable_types: priorityOfPoppedElement int


decompiled_code:
_BOOL8 __fastcall pqueue_hasNext(_QWORD *a1)
{
_BOOL4 v1; // er8
_BOOL8 result; // rax

v1 = pqueue_isEmpty(a1);
result = 1LL;
if ( !v1 )
result = *(_DWORD *)(*a1 + 8LL) > 0;
return result;
}

canonical_decompiled_code:
_BOOL8 __fastcall func4(_QWORD *a1)
{
_BOOL4 v1; // er8
_BOOL8 result; // rax

v1 = func1(a1);
result = 1LL;
if ( !v1 )
result = *(_DWORD *)(*a1 + 8LL) > 0;
return result;
}

original_code:
int pqueue_hasNext(pqueue_root * root)
{
 if (pqueue_isEmpty(root)) {
  return 1;
 } else {
  int priority = root->first->priority;
  if (priority <= 0) {
   return 0;
  } else {
   return 1;
  }
 }
}

canonical_original_code:
int pqueue_hasNext(struct pqueue_root_s *root)
{
 if (pqueue_isEmpty(root)) {
  return 1;
 } else {
  int priority = root->first->priority;
  if (priority <= 0) {
   return 0;
  } else {
   return 1;
  }
 }
}

variable_types: priority int


decompiled_code:
__int64 __fastcall pqueue_pass(_QWORD *a1, int a2)
{
__int64 result; // rax

result = pqueue_isEmpty(a1);
if ( !(_DWORD)result )
{
result = *a1;
*(_DWORD *)(*a1 + 8LL) -= a2;
}
return result;
}

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

result = func1(a1);
if ( !(_DWORD)result )
{
result = *a1;
*(_DWORD *)(*a1 + 8LL) -= a2;
}
return result;
}

original_code:
void pqueue_pass(pqueue_root * root, int time)
{
 if (pqueue_isEmpty(root)) {
 } else {
  root->first->priority -= time;
 }
}

canonical_original_code:
void pqueue_pass(struct pqueue_root_s *root, int time)
{
 if (pqueue_isEmpty(root)) {
 } else {
  root->first->priority -= time;
 }
}

variable_types: time int


original_code:
int pqueue_insert(pqueue_root * root, int priority, int message)
{
 if (root == ((void *)0))
  return 1;
 if (priority < 0)
  return 2;
 int didInsertionHappen = 1;
 if (pqueue_isEmpty(root)) {
  pqueue_node *newElement = calloc(1, sizeof(pqueue_node));
  if (newElement) {
   newElement->priority = priority;
   newElement->message = message;
   root->first = newElement;
   didInsertionHappen = 0;
  } else {
   return 3;
  }
 } else {
  pqueue_node *candidate = root->first;
  int prioritySoFar = 0;
  while (candidate != ((void *)0)) {
   if (candidate->priority >= priority) {
    int priorityOfInsertedElement =
        priority - prioritySoFar;
    int priorityOfCopiedMark =
        candidate->priority -
        priorityOfInsertedElement;
    pqueue_node *newElement =
        calloc(1, sizeof(pqueue_node));
    newElement->priority = priorityOfCopiedMark;
    newElement->message = candidate->message;
    newElement->next = candidate->next;
    candidate->next = newElement;
    candidate->priority = priorityOfInsertedElement;
    candidate->message = message;
    didInsertionHappen = 0;
    break;
   }
   if (candidate->next == ((void *)0)) {
    pqueue_node *newElement =
        calloc(1, sizeof(pqueue_node));
    newElement->priority = priority - prioritySoFar;
    newElement->message = message;
    candidate->next = newElement;
    didInsertionHappen = 0;
    break;
   }
   prioritySoFar += candidate->priority;
   candidate = candidate->next;
  }
 }
 if (didInsertionHappen == 0)
  return 0;
 else
  return 4;
}

canonical_original_code:
int pqueue_insert(struct pqueue_root_s *root, int priority, int message)
{
 if (root == ((void *)0))
  return 1;
 if (priority < 0)
  return 2;
 int didInsertionHappen = 1;
 if (pqueue_isEmpty(root)) {
  struct pqueue_node_s *newElement = calloc(1, sizeof(pqueue_node));
  if (newElement) {
   newElement->priority = priority;
   newElement->message = message;
   root->first = newElement;
   didInsertionHappen = 0;
  } else {
   return 3;
  }
 } else {
  struct pqueue_node_s *candidate = root->first;
  int prioritySoFar = 0;
  while (candidate != ((void *)0)) {
   if (candidate->priority >= priority) {
    int priorityOfInsertedElement = priority - prioritySoFar;
    int priorityOfCopiedMark = candidate->priority -
        priorityOfInsertedElement;
    struct pqueue_node_s *newElement = calloc(1, sizeof(pqueue_node));
    newElement->priority = priorityOfCopiedMark;
    newElement->message = candidate->message;
    newElement->next = candidate->next;
    candidate->next = newElement;
    candidate->priority = priorityOfInsertedElement;
    candidate->message = message;
    didInsertionHappen = 0;
    break;
   }
   if (candidate->next == ((void *)0)) {
    struct pqueue_node_s *newElement = calloc(1, sizeof(pqueue_node));
    newElement->priority = priority - prioritySoFar;
    newElement->message = message;
    candidate->next = newElement;
    didInsertionHappen = 0;
    break;
   }
   prioritySoFar += candidate->priority;
   candidate = candidate->next;
  }
 }
 if (didInsertionHappen == 0)
  return 0;
 else
  return 4;
}

variable_types: message int

variable_types: didInsertionHappen int

variable_types: struct pqueue_node_s { struct pqueue_node_s *next; int priority; int message; } *

variable_types: prioritySoFar int

variable_types: priorityOfInsertedElement int

variable_types: priorityOfCopiedMark int


decompiled_code:
__int64 mbc_mbc5_read_ff()
{
return 0xFFFFFFFFLL;
}

original_code:
uint8_t mbc_mbc5_read_ff(uint16_t address)
{
 return 0xff;
}

canonical_original_code:
unsigned char mbc_mbc5_read_ff(unsigned short address)
{
 return 0xff;
}


decompiled_code:
void mbc_mbc5_write_dummy()
{
;
}

original_code:
void mbc_mbc5_write_dummy(uint16_t address, uint8_t data)
{
}

canonical_original_code:
void mbc_mbc5_write_dummy(unsigned short address, unsigned char data)
{
}


decompiled_code:
__int64 __fastcall mbc_mbc5_read_bank_0(unsigned __int16 a1)
{
return *(unsigned __int8 *)(cart[6] + a1);
}

original_code:
uint8_t mbc_mbc5_read_bank_0(uint16_t address)
{
 return cart.cartrom_bank_zero[address];
}

canonical_original_code:
unsigned char mbc_mbc5_read_bank_0(unsigned short address)
{
 return cart.cartrom_bank_zero[address];
}


decompiled_code:
__int64 __fastcall mbc_mbc5_read_bank_n(__int16 a1)
{
return *(unsigned __int8 *)(cart[7] + (a1 & 0x3FFF));
}

original_code:
uint8_t mbc_mbc5_read_bank_n(uint16_t address)
{
 return cart.cartrom_bank_n[address & 0x3fff];
}

canonical_original_code:
unsigned char mbc_mbc5_read_bank_n(unsigned short address)
{
 return cart.cartrom_bank_n[address & 0x3fff];
}


decompiled_code:
void mbc_mbc5_write_ram_enable()
{
;
}

canonical_decompiled_code:
void func4()
{
;
}

original_code:
void mbc_mbc5_write_ram_enable(uint16_t address, uint8_t data)
{
}

canonical_original_code:
void mbc_mbc5_write_ram_enable(unsigned short address, unsigned char data)
{
}


decompiled_code:
__int64 __fastcall mbc_mbc5_write_rom_bank_select_low(__int64 a1, unsigned __int8 a2)
{
int v2; // eax
int v3; // edx
__int64 v4; // rax
__int64 result; // rax

v2 = HIDWORD(cart[1]);
LODWORD(cart[1]) = a2;
v3 = (a2 + (v2 << 8)) % SHIDWORD(cart[0]);
v4 = (__int64)v3 << 14;
if ( !v3 )
v4 = 0x4000LL;
result = cart[4] + v4;
cart[7] = result;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(__int64 a1, unsigned __int8 a2)
{
int v2; // eax
int v3; // edx
__int64 v4; // rax
__int64 result; // rax

v2 = HIDWORD(cart[1]);
LODWORD(cart[1]) = a2;
v3 = (a2 + (v2 << 8)) % SHIDWORD(cart[0]);
v4 = (__int64)v3 << 14;
if ( !v3 )
v4 = 0x4000LL;
result = cart[4] + v4;
cart[7] = result;
return result;
}

original_code:
void mbc_mbc5_write_rom_bank_select_low(uint16_t address, uint8_t data)
{
 cart.reg_rom_bank_low = data;
 int bank = cart.reg_rom_bank_low + (int)(cart.reg_rom_bank_high) * 256;
 bank = bank % cart.cartrom_num_banks;
 if (bank == 0)
  bank = 1;
 size_t offset = (size_t)bank * 16384;
 cart.cartrom_bank_n = cart.cartrom + offset;
}

canonical_original_code:
void mbc_mbc5_write_rom_bank_select_low(unsigned short address, unsigned char data)
{
 cart.reg_rom_bank_low = data;
 int bank = cart.reg_rom_bank_low + (int)(cart.reg_rom_bank_high) * 256;
 bank = bank % cart.cartrom_num_banks;
 if (bank == 0)
  bank = 1;
 unsigned long offset = (size_t)bank * 16384;
 cart.cartrom_bank_n = cart.cartrom + offset;
}

variable_types: bank int

variable_types:
offset
unsigned long


decompiled_code:
__int64 __fastcall mbc_mbc5_write_rom_bank_select_high(__int64 a1, char a2)
{
int v2; // eax
int v3; // edx
__int64 v4; // rax
__int64 result; // rax

v2 = a2 & 1;
HIDWORD(cart[1]) = v2;
v3 = (LODWORD(cart[1]) + (v2 << 8)) % SHIDWORD(cart[0]);
v4 = (__int64)v3 << 14;
if ( !v3 )
v4 = 0x4000LL;
result = cart[4] + v4;
cart[7] = result;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func6(__int64 a1, char a2)
{
int v2; // eax
int v3; // edx
__int64 v4; // rax
__int64 result; // rax

v2 = a2 & 1;
HIDWORD(cart[1]) = v2;
v3 = (LODWORD(cart[1]) + (v2 << 8)) % SHIDWORD(cart[0]);
v4 = (__int64)v3 << 14;
if ( !v3 )
v4 = 0x4000LL;
result = cart[4] + v4;
cart[7] = result;
return result;
}

original_code:
void mbc_mbc5_write_rom_bank_select_high(uint16_t address, uint8_t data)
{
 cart.reg_rom_bank_high = data & 0x01;
 int bank = cart.reg_rom_bank_low + (int)(cart.reg_rom_bank_high) * 256;
 bank = bank % cart.cartrom_num_banks;
 if (bank == 0)
  bank = 1;
 size_t offset = (size_t)bank * 16384;
 cart.cartrom_bank_n = cart.cartrom + offset;
}

canonical_original_code:
void mbc_mbc5_write_rom_bank_select_high(unsigned short address, unsigned char data)
{
 cart.reg_rom_bank_high = data & 0x01;
 int bank = cart.reg_rom_bank_low + (int)(cart.reg_rom_bank_high) * 256;
 bank = bank % cart.cartrom_num_banks;
 if (bank == 0)
  bank = 1;
 unsigned long offset = (size_t)bank * 16384;
 cart.cartrom_bank_n = cart.cartrom + offset;
}


decompiled_code:
__int64 __fastcall mbc_mbc5_read_extram(__int16 a1)
{
return *(unsigned __int8 *)(cart[14] + (a1 & 0x1FFF));
}

canonical_decompiled_code:
__int64 __fastcall func7(__int16 a1)
{
return *(unsigned __int8 *)(cart[14] + (a1 & 0x1FFF));
}

original_code:
uint8_t mbc_mbc5_read_extram(uint16_t address)
{
 return cart.extram_bank[address & 0x1fff];
}

canonical_original_code:
unsigned char mbc_mbc5_read_extram(unsigned short address)
{
 return cart.extram_bank[address & 0x1fff];
}


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

result = cart[14];
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
return result;
}

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

result = cart[14];
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
return result;
}

original_code:
void mbc_mbc5_write_extram(uint16_t address, uint8_t data)
{
 cart.extram_bank[address & 0x1fff] = data;
}

canonical_original_code:
void mbc_mbc5_write_extram(unsigned short address, unsigned char data)
{
 cart.extram_bank[address & 0x1fff] = data;
}


decompiled_code:
void mbc_mbc5_cleanup()
{
;
}

canonical_decompiled_code:
void func9()
{
;
}

original_code:
void mbc_mbc5_cleanup()
{
}

canonical_original_code:
void mbc_mbc5_cleanup()
{
}


decompiled_code:
int __fastcall mbc_mbc5_write_ram_bank_select(__int64 a1, __int16 a2)
{
int result; // eax

if ( cart[18] )
cart[14] = cart[11] + (unsigned __int16)(a2 << 13);
result = LODWORD(cart[0]) - 28;
if ( (unsigned int)(LODWORD(cart[0]) - 28) <= 2 && (a2 & 8) != 0 )
result = printf("rumble ON, power: %d\n", (unsigned __int8)a2 >> 4);
return result;
}

canonical_decompiled_code:
int __fastcall func10(__int64 a1, __int16 a2)
{
int result; // eax

if ( cart[18] )
cart[14] = cart[11] + (unsigned __int16)(a2 << 13);
result = LODWORD(cart[0]) - 28;
if ( (unsigned int)(LODWORD(cart[0]) - 28) <= 2 && (a2 & 8) != 0 )
result = printf("rumble ON, power: %d\n", (unsigned __int8)a2 >> 4);
return result;
}

original_code:
void mbc_mbc5_write_ram_bank_select(uint16_t address, uint8_t data)
{
 if (cart.extram_size > 0) {
  int bank = data & 0x07;
  cart.extram_bank = cart.extram + bank * 8192;
 }
 switch (cart.mbc_type) {
 case 0x1C:
 case 0x1D:
 case 0x1E:
  if (data & 0x08)
   printf("rumble ON, power: %d\n", data >> 4);
  break;
 default:
  break;
 }
}

canonical_original_code:
void mbc_mbc5_write_ram_bank_select(unsigned short address, unsigned char data)
{
 if (cart.extram_size > 0) {
  int bank = data & 0x07;
  cart.extram_bank = cart.extram + bank * 8192;
 }
 switch (cart.mbc_type) {
 case 0x1C:
 case 0x1D:
 case 0x1E:
  if (data & 0x08)
   printf("rumble ON, power: %d\n", data >> 4);
  break;
 default:
  break;
 }
}


decompiled_code:
__int64 mbc_mbc5_install()
{
char *v0; // rax
unsigned __int64 v1; // rax
char *v2; // rax
unsigned __int64 v3; // rax
unsigned __int64 v4; // rax
unsigned __int64 v5; // rax
void (**v6)(); // rax
unsigned __int64 v7; // rdx
unsigned __int64 v8; // rdx
int v9; // ecx
int v10; // eax
__int64 v11; // rsi
__int64 v12; // rdx
__int64 v13; // rsi
__int64 v14; // rdx
__int64 v15; // rdx
__int64 v16; // rdx
__int64 v17; // rax
__int64 result; // rax

cart[20] = mbc_mbc5_cleanup;
v0 = (char *)&readmem;
do
{
*(_QWORD *)v0 = mbc_mbc5_read_bank_0;
v0 += 8;
}
while ( v0 != (char *)&readmem + 512 );
v1 = (unsigned int)((_DWORD)&readmem + 512);
do
{
*(_QWORD *)v1 = mbc_mbc5_read_bank_n;
v1 += 8LL;
}
while ( (_UNKNOWN *)v1 != (_UNKNOWN *)((char *)&readmem + 1024) );
v2 = (char *)&writemem;
do
{
*(_QWORD *)v2 = mbc_mbc5_write_ram_enable;
v2 += 8;
}
while ( v2 != (char *)&writemem + 256 );
v3 = (unsigned int)((_DWORD)&writemem + 256);
do
{
*(_QWORD *)v3 = mbc_mbc5_write_rom_bank_select_low;
v3 += 8LL;
}
while ( (_UNKNOWN *)v3 != (_UNKNOWN *)((char *)&writemem + 384) );
v4 = (unsigned int)((_DWORD)&writemem + 384);
do
{
*(_QWORD *)v4 = mbc_mbc5_write_rom_bank_select_high;
v4 += 8LL;
}
while ( (_UNKNOWN *)v4 != (_UNKNOWN *)((char *)&writemem + 512) );
v5 = (unsigned int)((_DWORD)&writemem + 512);
do
{
*(_QWORD *)v5 = mbc_mbc5_write_ram_bank_select;
v5 += 8LL;
}
while ( (_UNKNOWN *)v5 != (_UNKNOWN *)((char *)&writemem + 768) );
v6 = (void (**)())(unsigned int)((_DWORD)&writemem + 768);
do
*v6++ = mbc_mbc5_write_dummy;
while ( (void (**)())(unsigned int)((_DWORD)&writemem + 1024) != v6 );
v7 = 0x2000LL;
if ( cart[18] <= 0x2000uLL )
v7 = cart[18];
v8 = v7 >> 8;
v9 = v8 + 160;
v10 = v8 + 160;
if ( !(_DWORD)v8 )
goto LABEL_23;
v11 = (unsigned int)(v8 - 1);
v12 = 160LL;
v13 = v11 + 161;
do
*((_QWORD *)&readmem + v12++) = mbc_mbc5_read_extram;
while ( v13 != v12 );
if ( v9 != 192 )
{
LABEL_23:
v14 = v9;
do
*((_QWORD *)&readmem + v14++) = mbc_mbc5_read_ff;
while ( (int)v14 <= 191 );
if ( v9 == 160 )
goto LABEL_31;
}
v15 = 160LL;
do
*((_QWORD *)&writemem + v15++) = mbc_mbc5_write_extram;
while ( v9 > (int)v15 );
if ( v9 != 192 )
{
LABEL_31:
do
{
v16 = v10++;
*((_QWORD *)&writemem + v16) = mbc_mbc5_write_dummy;
}
while ( v10 != 192 );
}
v17 = cart[4];
LOBYTE(cart[17]) = 0;
cart[1] = 1LL;
cart[6] = v17;
cart[7] = v17 + 0x4000;
result = cart[11];
cart[14] = result;
return result;
}

canonical_decompiled_code:
__int64 func11()
{
char *v0; // rax
unsigned __int64 v1; // rax
char *v2; // rax
unsigned __int64 v3; // rax
unsigned __int64 v4; // rax
unsigned __int64 v5; // rax
void (**v6)(); // rax
unsigned __int64 v7; // rdx
unsigned __int64 v8; // rdx
int v9; // ecx
int v10; // eax
__int64 v11; // rsi
__int64 v12; // rdx
__int64 v13; // rsi
__int64 v14; // rdx
__int64 v15; // rdx
__int64 v16; // rdx
__int64 v17; // rax
__int64 result; // rax

cart[20] = mbc_mbc5_cleanup;
v0 = (char *)&readmem;
do
{
*(_QWORD *)v0 = mbc_mbc5_read_bank_0;
v0 += 8;
}
while ( v0 != (char *)&readmem + 512 );
v1 = (unsigned int)((_DWORD)&readmem + 512);
do
{
*(_QWORD *)v1 = mbc_mbc5_read_bank_n;
v1 += 8LL;
}
while ( (_UNKNOWN *)v1 != (_UNKNOWN *)((char *)&readmem + 1024) );
v2 = (char *)&writemem;
do
{
*(_QWORD *)v2 = mbc_mbc5_write_ram_enable;
v2 += 8;
}
while ( v2 != (char *)&writemem + 256 );
v3 = (unsigned int)((_DWORD)&writemem + 256);
do
{
*(_QWORD *)v3 = mbc_mbc5_write_rom_bank_select_low;
v3 += 8LL;
}
while ( (_UNKNOWN *)v3 != (_UNKNOWN *)((char *)&writemem + 384) );
v4 = (unsigned int)((_DWORD)&writemem + 384);
do
{
*(_QWORD *)v4 = mbc_mbc5_write_rom_bank_select_high;
v4 += 8LL;
}
while ( (_UNKNOWN *)v4 != (_UNKNOWN *)((char *)&writemem + 512) );
v5 = (unsigned int)((_DWORD)&writemem + 512);
do
{
*(_QWORD *)v5 = mbc_mbc5_write_ram_bank_select;
v5 += 8LL;
}
while ( (_UNKNOWN *)v5 != (_UNKNOWN *)((char *)&writemem + 768) );
v6 = (void (**)())(unsigned int)((_DWORD)&writemem + 768);
do
*v6++ = mbc_mbc5_write_dummy;
while ( (void (**)())(unsigned int)((_DWORD)&writemem + 1024) != v6 );
v7 = 0x2000LL;
if ( cart[18] <= 0x2000uLL )
v7 = cart[18];
v8 = v7 >> 8;
v9 = v8 + 160;
v10 = v8 + 160;
if ( !(_DWORD)v8 )
goto LABEL_23;
v11 = (unsigned int)(v8 - 1);
v12 = 160LL;
v13 = v11 + 161;
do
*((_QWORD *)&readmem + v12++) = mbc_mbc5_read_extram;
while ( v13 != v12 );
if ( v9 != 192 )
{
LABEL_23:
v14 = v9;
do
*((_QWORD *)&readmem + v14++) = mbc_mbc5_read_ff;
while ( (int)v14 <= 191 );
if ( v9 == 160 )
goto LABEL_31;
}
v15 = 160LL;
do
*((_QWORD *)&writemem + v15++) = mbc_mbc5_write_extram;
while ( v9 > (int)v15 );
if ( v9 != 192 )
{
LABEL_31:
do
{
v16 = v10++;
*((_QWORD *)&writemem + v16) = mbc_mbc5_write_dummy;
}
while ( v10 != 192 );
}
v17 = cart[4];
LOBYTE(cart[17]) = 0;
cart[1] = 1LL;
cart[6] = v17;
cart[7] = v17 + 0x4000;
result = cart[11];
cart[14] = result;
return result;
}

original_code:
void mbc_mbc5_install()
{
 cart.cleanup = &mbc_mbc5_cleanup;
 int i;
 for (i = 0x00; i <= 0x3F; ++i) {
  readmem[i] = mbc_mbc5_read_bank_0;
 }
 for (i = 0x40; i <= 0x7F; ++i) {
  readmem[i] = mbc_mbc5_read_bank_n;
 }
 for (i = 0x00; i <= 0x1F; ++i) {
  writemem[i] = mbc_mbc5_write_ram_enable;
 }
 for (i = 0x20; i <= 0x2F; ++i) {
  writemem[i] = mbc_mbc5_write_rom_bank_select_low;
 }
 for (i = 0x30; i <= 0x3F; ++i) {
  writemem[i] = mbc_mbc5_write_rom_bank_select_high;
 }
 for (i = 0x40; i <= 0x5F; ++i) {
  writemem[i] = mbc_mbc5_write_ram_bank_select;
 }
 for (i = 0x60; i <= 0x7F; ++i) {
  writemem[i] = mbc_mbc5_write_dummy;
 }
 int extram_end =
     0xA0 + (cart.extram_size > 8192 ? 8192 : cart.extram_size) / 256;
 for (i = 0xA0; i < extram_end; ++i) {
  readmem[i] = mbc_mbc5_read_extram;
 }
 for (i = extram_end; i <= 0xBF; ++i) {
  readmem[i] = mbc_mbc5_read_ff;
 }
 for (i = 0xA0; i < extram_end; ++i) {
  writemem[i] = mbc_mbc5_write_extram;
 }
 for (i = extram_end; i <= 0xBF; ++i) {
  writemem[i] = mbc_mbc5_write_dummy;
 }
 cart.cartrom_bank_zero = cart.cartrom;
 cart.cartrom_bank_n = cart.cartrom + 0x4000;
 cart.reg_rom_bank_low = 1;
 cart.reg_rom_bank_high = 0;
 cart.extram_bank = cart.extram;
 cart.extram_bank_num = 0;
}


decompiled_code:
__int64 __fastcall mbc_huc1_read_bank_0(unsigned __int16 a1)
{
return *(unsigned __int8 *)(cart[6] + a1);
}

canonical_decompiled_code:
__int64 __fastcall func0(unsigned __int16 a1)
{
return *(unsigned __int8 *)(cart[6] + a1);
}

original_code:
uint8_t mbc_huc1_read_bank_0(uint16_t address)
{
 return cart.cartrom_bank_zero[address];
}

canonical_original_code:
unsigned char mbc_huc1_read_bank_0(unsigned short address)
{
 return cart.cartrom_bank_zero[address];
}


decompiled_code:
__int64 __fastcall mbc_huc1_read_bank_n(__int16 a1)
{
return *(unsigned __int8 *)(cart[7] + (a1 & 0x3FFF));
}

canonical_decompiled_code:
__int64 __fastcall func1(__int16 a1)
{
return *(unsigned __int8 *)(cart[7] + (a1 & 0x3FFF));
}

original_code:
uint8_t mbc_huc1_read_bank_n(uint16_t address)
{
 return cart.cartrom_bank_n[address & 0x3fff];
}

canonical_original_code:
unsigned char mbc_huc1_read_bank_n(unsigned short address)
{
 return cart.cartrom_bank_n[address & 0x3fff];
}


decompiled_code:
__int64 mbc_huc1_read_ff()
{
return 0xFFFFFFFFLL;
}

canonical_decompiled_code:
__int64 func3()
{
return 0xFFFFFFFFLL;
}

original_code:
uint8_t mbc_huc1_read_ff(uint16_t address)
{
 return 0xff;
}

canonical_original_code:
unsigned char mbc_huc1_read_ff(unsigned short address)
{
 return 0xff;
}


decompiled_code:
void mbc_huc1_write_dummy()
{
;
}

original_code:
void mbc_huc1_write_dummy(uint16_t address, uint8_t data)
{
}

canonical_original_code:
void mbc_huc1_write_dummy(unsigned short address, unsigned char data)
{
}


decompiled_code:
__int64 __fastcall mbc_huc1_read_extram(__int16 a1)
{
return *(unsigned __int8 *)(cart[14] + (a1 & 0x1FFF));
}

canonical_decompiled_code:
__int64 __fastcall func5(__int16 a1)
{
return *(unsigned __int8 *)(cart[14] + (a1 & 0x1FFF));
}

original_code:
uint8_t mbc_huc1_read_extram(uint16_t address)
{
 return cart.extram_bank[address & 0x1fff];
}

canonical_original_code:
unsigned char mbc_huc1_read_extram(unsigned short address)
{
 return cart.extram_bank[address & 0x1fff];
}


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

result = cart[14];
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
return result;
}

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

result = cart[14];
*(_BYTE *)(result + (a1 & 0x1FFF)) = a2;
return result;
}

original_code:
void mbc_huc1_write_extram(uint16_t address, uint8_t data)
{
 cart.extram_bank[address & 0x1fff] = data;
}

canonical_original_code:
void mbc_huc1_write_extram(unsigned short address, unsigned char data)
{
 cart.extram_bank[address & 0x1fff] = data;
}