decompiled_code:
__int64 print_flags()
{
unsigned __int64 v0; // rbx

v0 = *((_QWORD *)reg + 20);
debug_screen_newline(1LL);
debug_screen_printf(
" N: %d Z: %d C: %d V: %d CPSR: %08x SPSR: %08x mode: %s",
(v0 >> 31) & 1,
(v0 >> 30) & 1,
(v0 >> 29) & 1,
(v0 >> 28) & 1,
v0,
*((_QWORD *)&spsr + *((_QWORD *)reg + 29)),
cpu_mode_names[*((_QWORD *)reg + 29)]);
return debug_screen_newline(2LL);
}

canonical_decompiled_code:
__int64 func3()
{
unsigned __int64 v0; // rbx

v0 = *((_QWORD *)reg + 20);
debug_screen_newline(1LL);
debug_screen_printf(
" N: %d Z: %d C: %d V: %d CPSR: %08x SPSR: %08x mode: %s",
(v0 >> 31) & 1,
(v0 >> 30) & 1,
(v0 >> 29) & 1,
(v0 >> 28) & 1,
v0,
*((_QWORD *)&spsr + *((_QWORD *)reg + 29)),
cpu_mode_names[*((_QWORD *)reg + 29)]);
return debug_screen_newline(2LL);
}

original_code:
void print_flags()
{
  u32 cpsr = reg[REG_CPSR];
  debug_screen_newline(1);
  debug_screen_printf(
   " N: %d  Z: %d  C: %d  V: %d  CPSR: %08x  SPSR: %08x  mode: %s",
   (cpsr >> 31) & 0x01, (cpsr >> 30) & 0x01, (cpsr >> 29) & 0x01,
   (cpsr >> 28) & 0x01, cpsr, spsr[reg[CPU_MODE]],
   cpu_mode_names[reg[CPU_MODE]]);
  debug_screen_newline(2);
}

canonical_original_code:
void print_flags()
{
  unsigned long cpsr = reg[REG_CPSR];
  debug_screen_newline(1);
  debug_screen_printf(
   " N: %d  Z: %d  C: %d  V: %d  CPSR: %08x  SPSR: %08x  mode: %s",
   (cpsr >> 31) & 0x01, (cpsr >> 30) & 0x01, (cpsr >> 29) & 0x01,
   (cpsr >> 28) & 0x01, cpsr, spsr[reg[CPU_MODE]],
   cpu_mode_names[reg[CPU_MODE]]);
  debug_screen_newline(2);
}

variable_types:
cpsr
unsigned long


decompiled_code:
__int64 print_stack()
{
__int64 v0; // r12
__int64 v1; // rbx
__int64 v2; // rbp
__int64 v3; // rdi
__int64 v4; // rax
__int64 v5; // r12
__int64 v6; // rdi
__int64 v7; // rax

debug_screen_printf("Stack:");
debug_screen_newline(1LL);
v0 = *((_QWORD *)reg + 13);
v1 = v0 + 20;
v2 = v0;
do
{
v3 = v2;
v2 += 4LL;
v4 = read_memory32(v3);
debug_screen_printf(" %08x", v4);
}
while ( v1 != v2 );
v5 = v0 + 40;
debug_screen_newline(1LL);
do
{
v6 = v1;
v1 += 4LL;
v7 = read_memory32(v6);
debug_screen_printf(" %08x", v7);
}
while ( v1 != v5 );
debug_screen_newline(1LL);
return debug_screen_newline(1LL);
}

canonical_decompiled_code:
__int64 func4()
{
__int64 v0; // r12
__int64 v1; // rbx
__int64 v2; // rbp
__int64 v3; // rdi
__int64 v4; // rax
__int64 v5; // r12
__int64 v6; // rdi
__int64 v7; // rax

debug_screen_printf("Stack:");
debug_screen_newline(1LL);
v0 = *((_QWORD *)reg + 13);
v1 = v0 + 20;
v2 = v0;
do
{
v3 = v2;
v2 += 4LL;
v4 = read_memory32(v3);
debug_screen_printf(" %08x", v4);
}
while ( v1 != v2 );
v5 = v0 + 40;
debug_screen_newline(1LL);
do
{
v6 = v1;
v1 += 4LL;
v7 = read_memory32(v6);
debug_screen_printf(" %08x", v7);
}
while ( v1 != v5 );
debug_screen_newline(1LL);
return debug_screen_newline(1LL);
}

original_code:
void print_stack()
{
  u32 i, i2, i3;
  debug_screen_printf("Stack:");
  debug_screen_newline(1);
  for(i = 0, i3 = reg[REG_SP]; i < stack_print_lines; i++)
  {
    for(i2 = 0; i2 < 5; i2++, i3 += 4)
    {
      debug_screen_printf(" %08x", read_memory32(i3));
    }
    if(i != stack_print_lines)
      debug_screen_newline(1);
  }
  debug_screen_newline(1);
}

canonical_original_code:
void print_stack()
{
  unsigned long i; unsigned long i2; unsigned long i3;
  debug_screen_printf("Stack:");
  debug_screen_newline(1);
  for(i = 0, i3 = reg[REG_SP]; i < stack_print_lines; i++)
  {
    for(i2 = 0; i2 < 5; i2++, i3 += 4)
    {
      debug_screen_printf(" %08x", read_memory32(i3));
    }
    if(i != stack_print_lines)
      debug_screen_newline(1);
  }
  debug_screen_newline(1);
}

variable_types:
i
unsigned long

return_type: void


decompiled_code:
__int64 debug_on()
{
current_debug_state = 0;
return debug_screen_start();
}

canonical_decompiled_code:
__int64 func5()
{
current_debug_state = 0;
return debug_screen_start();
}

original_code:
u32 debug_on()
{
  current_debug_state = STEP;
  debug_screen_start();
}

canonical_original_code:
unsigned long debug_on()
{
  current_debug_state = STEP;
  debug_screen_start();
}

return_type: unsigned long


decompiled_code:
__int64 __fastcall debug_off(int a1)
{
current_debug_state = a1;
return debug_screen_end();
}

canonical_decompiled_code:
__int64 __fastcall func6(int a1)
{
current_debug_state = a1;
return debug_screen_end();
}

original_code:
u32 debug_off(debug_state new_debug_state)
{
  current_debug_state = new_debug_state;
  debug_screen_end();
}

canonical_original_code:
unsigned long debug_off(enum debug_state new_debug_state)
{
  current_debug_state = new_debug_state;
  debug_screen_end();
}

variable_types: enum debug_state { STEP=0, PC_BREAKPOINT=1, VCOUNT_BREAKPOINT=2, Z_BREAKPOINT=3, COUNTDOWN_BREAKPOINT=4, COUNTDOWN_BREAKPOINT_B=5, COUNTDOWN_BREAKPOINT_C=6, STEP_RUN=7, RUN=8 }


decompiled_code:
__int64 __fastcall step_debug(__int64 a1, __int64 a2)
{
__int64 v3; // rbx
__int64 *v4; // rax
unsigned int v5; // ecx
__int64 v6; // rbp
__int64 v7; // rdx
int v8; // ebp
__int64 *v9; // rsi
__int64 v10; // rdi
__int64 v11; // rax
__int64 v12; // rdi
__int64 v13; // rbx
__int64 result; // rax
__int64 v15; // rdx
void *v16; // r12
_BYTE v17[536]; // [rsp+0h] [rbp-218h] BYREF

v3 = a1;
v4 = (__int64 *)reg;
v5 = current_debug_state;
v6 = *((_QWORD *)reg + 20);
v7 = instruction_count + 1;
*((_QWORD *)reg + 15) = a1;
instruction_count = v7;
v8 = v6 & 0x20;
v9 = v4;
switch ( v5 )
{
case 1u:
if ( breakpoint_value == a1 )
goto LABEL_3;
goto LABEL_12;
case 2u:
if ( io_registers[3] == breakpoint_value )
goto LABEL_3;
goto LABEL_12;
case 3u:
if ( v4[17] == 1 )
goto LABEL_3;
goto LABEL_12;
case 4u:
if ( !breakpoint_value )
goto LABEL_3;
--breakpoint_value;
goto LABEL_12;
case 5u:
if ( v7 != breakpoint_value )
goto LABEL_12;
LABEL_3:
debug_on(v5, v4);
v5 = current_debug_state;
goto LABEL_4;
case 6u:
v15 = in_interrupt;
if ( a1 == 24 )
v15 = ++in_interrupt;
if ( breakpoint_value )
{
if ( !v15 )
{
--breakpoint_value;
LABEL_36:
v9 = v4;
v11 = v4[15];
goto LABEL_13;
}
goto LABEL_22;
}
if ( v15 )
{
LABEL_22:
if ( a1 != 316 )
{
LABEL_12:
v11 = a1;
goto LABEL_13;
}
goto LABEL_39;
}
debug_on(breakpoint_value, v4);
v15 = in_interrupt;
v5 = current_debug_state;
if ( in_interrupt && a1 == 316 )
LABEL_39:
in_interrupt = v15 - 1;
LABEL_4:
if ( v5 && v5 != 7 )
{
v4 = (__int64 *)reg;
goto LABEL_36;
}
SDL_mutexP(sound_mutex, v9);
SDL_PauseAudio(1LL);
if ( (unsigned __int64)output_field > 1 )
{
output_field = 0LL;
debug_screen_clear();
v10 = a2;
if ( v8 )
goto LABEL_8;
LABEL_28:
print_arm_instruction(v10);
goto LABEL_9;
}
v10 = a2;
if ( !v8 )
goto LABEL_28;
LABEL_8:
print_thumb_instruction(v10);
LABEL_9:
print_arm_registers();
print_flags();
print_stack();
printf("%x instructions in, VCOUNT %d, cycles remaining: %d \n", instruction_count, io_registers[3], a2);
debug_screen_update();
++output_field;
if ( current_debug_state != 7 )
{
switch ( getchar() )
{
case 'a':
v16 = (void *)copy_screen();
get_savestate_filename_noshot(savestate_slot, v17);
save_state(v17, v16);
free(v16);
break;
case 'b':
debug_off(1);
break;
case 'c':
printf("break after N instructions (hex): ");
scanf("%08x", &breakpoint_value);
--breakpoint_value;
debug_off(4);
break;
case 'd':
dump_translation_cache();
break;
case 'f':
printf("break after N instructions, skip in IRQ (hex): ");
scanf("%08x", &breakpoint_value);
--breakpoint_value;
debug_off(6);
break;
case 'g':
printf("break after N instructions (since start): ");
scanf("%d", &breakpoint_value);
debug_off(5);
break;
case 'q':
quit();
break;
case 'r':
goto LABEL_32;
case 's':
current_debug_state = 7;
break;
case 't':
global_cycles_per_instruction = 0LL;
LABEL_32:
debug_off(8);
break;
case 'v':
printf("break at VCOUNT: ");
scanf("%d", &breakpoint_value);
debug_off(2);
break;
case 'x':
printf("break at PC (hex): ");
scanf("%08x", &breakpoint_value);
debug_off(1);
break;
case 'z':
debug_off(3);
break;
default:
break;
}
}
SDL_PauseAudio(0LL);
SDL_mutexV(sound_mutex);
v9 = (__int64 *)reg;
v11 = *((_QWORD *)reg + 15);
LABEL_13:
v12 = v3 + 2;
v13 = v3 + 4;
last_instruction = v11;
if ( v8 )
v13 = v12;
result = 0LL;
v9[15] = v13;
return result;
default:
goto LABEL_4;
}
}

canonical_decompiled_code:
__int64 __fastcall func7(__int64 a1, __int64 a2)
{
__int64 v3; // rbx
__int64 *v4; // rax
unsigned int v5; // ecx
__int64 v6; // rbp
__int64 v7; // rdx
int v8; // ebp
__int64 *v9; // rsi
__int64 v10; // rdi
__int64 v11; // rax
__int64 v12; // rdi
__int64 v13; // rbx
__int64 result; // rax
__int64 v15; // rdx
void *v16; // r12
_BYTE v17[536]; // [rsp+0h] [rbp-218h] BYREF

v3 = a1;
v4 = (__int64 *)reg;
v5 = current_debug_state;
v6 = *((_QWORD *)reg + 20);
v7 = instruction_count + 1;
*((_QWORD *)reg + 15) = a1;
instruction_count = v7;
v8 = v6 & 0x20;
v9 = v4;
switch ( v5 )
{
case 1u:
if ( breakpoint_value == a1 )
goto LABEL_3;
goto LABEL_12;
case 2u:
if ( io_registers[3] == breakpoint_value )
goto LABEL_3;
goto LABEL_12;
case 3u:
if ( v4[17] == 1 )
goto LABEL_3;
goto LABEL_12;
case 4u:
if ( !breakpoint_value )
goto LABEL_3;
--breakpoint_value;
goto LABEL_12;
case 5u:
if ( v7 != breakpoint_value )
goto LABEL_12;
LABEL_3:
func5(v5, v4);
v5 = current_debug_state;
goto LABEL_4;
case 6u:
v15 = in_interrupt;
if ( a1 == 24 )
v15 = ++in_interrupt;
if ( breakpoint_value )
{
if ( !v15 )
{
--breakpoint_value;
LABEL_36:
v9 = v4;
v11 = v4[15];
goto LABEL_13;
}
goto LABEL_22;
}
if ( v15 )
{
LABEL_22:
if ( a1 != 316 )
{
LABEL_12:
v11 = a1;
goto LABEL_13;
}
goto LABEL_39;
}
func5(breakpoint_value, v4);
v15 = in_interrupt;
v5 = current_debug_state;
if ( in_interrupt && a1 == 316 )
LABEL_39:
in_interrupt = v15 - 1;
LABEL_4:
if ( v5 && v5 != 7 )
{
v4 = (__int64 *)reg;
goto LABEL_36;
}
SDL_mutexP(sound_mutex, v9);
SDL_PauseAudio(1LL);
if ( (unsigned __int64)output_field > 1 )
{
output_field = 0LL;
debug_screen_clear();
v10 = a2;
if ( v8 )
goto LABEL_8;
LABEL_28:
func2(v10);
goto LABEL_9;
}
v10 = a2;
if ( !v8 )
goto LABEL_28;
LABEL_8:
func1(v10);
LABEL_9:
func0();
func3();
func4();
printf("%x instructions in, VCOUNT %d, cycles remaining: %d \n", instruction_count, io_registers[3], a2);
debug_screen_update();
++output_field;
if ( current_debug_state != 7 )
{
switch ( getchar() )
{
case 'a':
v16 = (void *)copy_screen();
get_savestate_filename_noshot(savestate_slot, v17);
save_state(v17, v16);
free(v16);
break;
case 'b':
func6(1);
break;
case 'c':
printf("break after N instructions (hex): ");
scanf("%08x", &breakpoint_value);
--breakpoint_value;
func6(4);
break;
case 'd':
dump_translation_cache();
break;
case 'f':
printf("break after N instructions, skip in IRQ (hex): ");
scanf("%08x", &breakpoint_value);
--breakpoint_value;
func6(6);
break;
case 'g':
printf("break after N instructions (since start): ");
scanf("%d", &breakpoint_value);
func6(5);
break;
case 'q':
quit();
break;
case 'r':
goto LABEL_32;
case 's':
current_debug_state = 7;
break;
case 't':
global_cycles_per_instruction = 0LL;
LABEL_32:
func6(8);
break;
case 'v':
printf("break at VCOUNT: ");
scanf("%d", &breakpoint_value);
func6(2);
break;
case 'x':
printf("break at PC (hex): ");
scanf("%08x", &breakpoint_value);
func6(1);
break;
case 'z':
func6(3);
break;
default:
break;
}
}
SDL_PauseAudio(0LL);
SDL_mutexV(sound_mutex);
v9 = (__int64 *)reg;
v11 = *((_QWORD *)reg + 15);
LABEL_13:
v12 = v3 + 2;
v13 = v3 + 4;
last_instruction = v11;
if ( v8 )
v13 = v12;
result = 0LL;
v9[15] = v13;
return result;
default:
goto LABEL_4;
}
}

original_code:
u32 __attribute__((regparm(2))) step_debug(u32 pc, u32 cycles)
{
  u32 thumb = 0;
  reg[REG_PC] = pc;
  if(reg[REG_CPSR] & 0x20)
    thumb = 1;
  instruction_count++;
  switch(current_debug_state)
  {
    case PC_BREAKPOINT:
      if(reg[REG_PC] == breakpoint_value)
        debug_on();
      break;
    case Z_BREAKPOINT:
      if(reg[REG_Z_FLAG] == 1)
        debug_on();
      break;
    case VCOUNT_BREAKPOINT:
      if(io_registers[REG_VCOUNT] == breakpoint_value)
        debug_on();
      break;
    case COUNTDOWN_BREAKPOINT:
      if(breakpoint_value == 0)
        debug_on();
      else
        breakpoint_value--;
      break;
    case COUNTDOWN_BREAKPOINT_B:
      if(breakpoint_value == instruction_count)
        debug_on();
      break;
    case COUNTDOWN_BREAKPOINT_C:
    {
      if(pc == 0x18)
        in_interrupt++;
      if((breakpoint_value == 0) && (in_interrupt == 0))
      {
        debug_on();
      }
      else
      if(in_interrupt == 0)
        breakpoint_value--;
      if(in_interrupt && (pc == 0x13c))
        in_interrupt--;
      break;
    }
  }
  if((current_debug_state == STEP) ||
   (current_debug_state == STEP_RUN))
  {
    u32 key = 0;
    SDL_mutexP(sound_mutex);
    SDL_PauseAudio(1);
    if(output_field >= num_output_fields)
    {
      output_field = 0;
      debug_screen_clear();
    }
    if(thumb)
      print_thumb_instruction(cycles);
    else
      print_arm_instruction(cycles);
    print_arm_registers();
    print_flags();
    print_stack();
    printf("%x instructions in, VCOUNT %d, cycles remaining: %d \n",
     instruction_count, io_registers[REG_VCOUNT], cycles);
    debug_screen_update();
    output_field++;
    if(current_debug_state != STEP_RUN)
    {
      key = getchar();
    }
    switch(key)
    {
      case 'd':
        dump_translation_cache();
        break;
      case 'z':
        debug_off(Z_BREAKPOINT);
        break;
      case 'x':
        printf("break at PC (hex): ");
        scanf("%08x", &breakpoint_value);
        debug_off(PC_BREAKPOINT);
        break;
      case 'c':
        printf("break after N instructions (hex): ");
        scanf("%08x", &breakpoint_value);
        breakpoint_value -= 1;
        debug_off(COUNTDOWN_BREAKPOINT);
        break;
      case 'f':
        printf("break after N instructions, skip in IRQ (hex): ");
        scanf("%08x", &breakpoint_value);
        breakpoint_value -= 1;
        debug_off(COUNTDOWN_BREAKPOINT_C);
        break;
      case 'g':
        printf("break after N instructions (since start): ");
        scanf("%d", &breakpoint_value);
        debug_off(COUNTDOWN_BREAKPOINT_B);
        break;
      case 'v':
        printf("break at VCOUNT: ");
        scanf("%d", &breakpoint_value);
        debug_off(VCOUNT_BREAKPOINT);
        break;
      case 's':
        current_debug_state = STEP_RUN;
        break;
      case 'r':
        debug_off(RUN);
        break;
      case 'b':
        debug_off(PC_BREAKPOINT);
        break;
      case 't':
        global_cycles_per_instruction = 0;
        debug_off(RUN);
        break;
      case 'a':
      {
        u8 current_savestate_filename[512];
        u16 *current_screen = copy_screen();
        get_savestate_filename_noshot(savestate_slot,
         current_savestate_filename);
        save_state(current_savestate_filename, current_screen);
        free(current_screen);
        break;
      }
      case 'q':
        quit();
    }
    SDL_PauseAudio(0);
    SDL_mutexV(sound_mutex);
  }
  last_instruction = reg[REG_PC];
  if(thumb)
    reg[REG_PC] = pc + 2;
  else
    reg[REG_PC] = pc + 4;
  return 0;
}

canonical_original_code:
unsigned long step_debug(unsigned long pc, unsigned long cycles)
{
  unsigned long thumb = 0;
  reg[REG_PC] = pc;
  if(reg[REG_CPSR] & 0x20)
    thumb = 1;
  instruction_count++;
  switch(current_debug_state)
  {
    case PC_BREAKPOINT:
      if(reg[REG_PC] == breakpoint_value)
        debug_on();
      break;
    case Z_BREAKPOINT:
      if(reg[REG_Z_FLAG] == 1)
        debug_on();
      break;
    case VCOUNT_BREAKPOINT:
      if(io_registers[REG_VCOUNT] == breakpoint_value)
        debug_on();
      break;
    case COUNTDOWN_BREAKPOINT:
      if(breakpoint_value == 0)
        debug_on();
      else
        breakpoint_value--;
      break;
    case COUNTDOWN_BREAKPOINT_B:
      if(breakpoint_value == instruction_count)
        debug_on();
      break;
    case COUNTDOWN_BREAKPOINT_C:
    {
      if(pc == 0x18)
        in_interrupt++;
      if((breakpoint_value == 0) && (in_interrupt == 0))
      {
        debug_on();
      }
      else
      if(in_interrupt == 0)
        breakpoint_value--;
      if(in_interrupt && (pc == 0x13c))
        in_interrupt--;
      break;
    }
  }
  if((current_debug_state == STEP) ||
   (current_debug_state == STEP_RUN))
  {
    unsigned long key = 0;
    SDL_mutexP(sound_mutex);
    SDL_PauseAudio(1);
    if(output_field >= num_output_fields)
    {
      output_field = 0;
      debug_screen_clear();
    }
    if(thumb)
      print_thumb_instruction(cycles);
    else
      print_arm_instruction(cycles);
    print_arm_registers();
    print_flags();
    print_stack();
    printf("%x instructions in, VCOUNT %d, cycles remaining: %d \n",
     instruction_count, io_registers[REG_VCOUNT], cycles);
    debug_screen_update();
    output_field++;
    if(current_debug_state != STEP_RUN)
    {
      key = getchar();
    }
    switch(key)
    {
      case 'd':
        dump_translation_cache();
        break;
      case 'z':
        debug_off(Z_BREAKPOINT);
        break;
      case 'x':
        printf("break at PC (hex): ");
        scanf("%08x", &breakpoint_value);
        debug_off(PC_BREAKPOINT);
        break;
      case 'c':
        printf("break after N instructions (hex): ");
        scanf("%08x", &breakpoint_value);
        breakpoint_value -= 1;
        debug_off(COUNTDOWN_BREAKPOINT);
        break;
      case 'f':
        printf("break after N instructions, skip in IRQ (hex): ");
        scanf("%08x", &breakpoint_value);
        breakpoint_value -= 1;
        debug_off(COUNTDOWN_BREAKPOINT_C);
        break;
      case 'g':
        printf("break after N instructions (since start): ");
        scanf("%d", &breakpoint_value);
        debug_off(COUNTDOWN_BREAKPOINT_B);
        break;
      case 'v':
        printf("break at VCOUNT: ");
        scanf("%d", &breakpoint_value);
        debug_off(VCOUNT_BREAKPOINT);
        break;
      case 's':
        current_debug_state = STEP_RUN;
        break;
      case 'r':
        debug_off(RUN);
        break;
      case 'b':
        debug_off(PC_BREAKPOINT);
        break;
      case 't':
        global_cycles_per_instruction = 0;
        debug_off(RUN);
        break;
      case 'a':
      {
        unsigned char current_savestate_filename[512];
        unsigned short *current_screen = copy_screen();
        get_savestate_filename_noshot(savestate_slot,
         current_savestate_filename);
        save_state(current_savestate_filename, current_screen);
        free(current_screen);
        break;
      }
      case 'q':
        quit();
    }
    SDL_PauseAudio(0);
    SDL_mutexV(sound_mutex);
  }
  last_instruction = reg[REG_PC];
  if(thumb)
    reg[REG_PC] = pc + 2;
  else
    reg[REG_PC] = pc + 4;
  return 0;
}

variable_types:
pc
unsigned long

variable_types:
cycles
unsigned long

variable_types:
thumb
unsigned long

variable_types:
key
unsigned long


original_code:
void init_cpu()
{
  u32 i;
  for(i = 0; i < 16; i++)
  {
    reg[i] = 0;
  }
  reg[REG_SP] = 0x03007F00;
  reg[REG_PC] = 0x08000000;
  reg[REG_CPSR] = 0x0000001F;
  reg[CPU_HALT_STATE] = CPU_ACTIVE;
  reg[CPU_MODE] = MODE_USER;
  reg[CHANGED_PC_STATUS] = 0;
  reg_mode[MODE_USER][5] = 0x03007F00;
  reg_mode[MODE_IRQ][5] = 0x03007FA0;
  reg_mode[MODE_FIQ][5] = 0x03007FA0;
  reg_mode[MODE_SUPERVISOR][5] = 0x03007FE0;
}

canonical_original_code:
void init_cpu()
{
  unsigned long i;
  for(i = 0; i < 16; i++)
  {
    reg[i] = 0;
  }
  reg[REG_SP] = 0x03007F00;
  reg[REG_PC] = 0x08000000;
  reg[REG_CPSR] = 0x0000001F;
  reg[CPU_HALT_STATE] = CPU_ACTIVE;
  reg[CPU_MODE] = MODE_USER;
  reg[CHANGED_PC_STATUS] = 0;
  reg_mode[MODE_USER][5] = 0x03007F00;
  reg_mode[MODE_IRQ][5] = 0x03007FA0;
  reg_mode[MODE_FIQ][5] = 0x03007FA0;
  reg_mode[MODE_SUPERVISOR][5] = 0x03007FE0;
}


decompiled_code:
void __fastcall process_cheat_gs1(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
unsigned __int64 v5; // r13
__int64 *i; // rbp
__int64 v7; // r12
__int64 v8; // r15
__int64 *v9; // rbx
__int64 v10; // r8
__int64 v11; // r8
__int64 *v12; // rbp
__int64 v13; // rdi
__int64 v14; // r12
unsigned __int64 v15; // [rsp+0h] [rbp-40h]
__int64 v16; // [rsp+0h] [rbp-40h]

if ( *(_QWORD *)(a1 + 2080) )
{
v5 = 0LL;
for ( i = (__int64 *)(a1 + 32); ; i = v9 )
{
v7 = *i;
v8 = i[1];
v9 = i + 2;
v10 = *i & 0xFFFFFFF;
switch ( (unsigned __int64)*i >> 28 )
{
case 0uLL:
write_memory8(*i & 0xFFFFFFF, (unsigned __int8)v8);
goto LABEL_5;
case 1uLL:
write_memory16(*i & 0xFFFFFFF, (unsigned __int16)v8);
goto LABEL_5;
case 2uLL:
write_memory32(*i & 0xFFFFFFF, i[1], a3, a4, v10);
goto LABEL_5;
case 3uLL:
v16 = (unsigned __int16)v7;
if ( !(_WORD)v7 )
goto LABEL_5;
v12 = &i[2 * (unsigned __int16)v7 + 2];
break;
case 0xDuLL:
if ( read_memory16(*i & 0xFFFFFFF) != (unsigned __int16)v8 )
{
++v5;
v9 = i + 4;
}
goto LABEL_5;
case 0xEuLL:
v15 = *i & 0xFFFFFFF;
if ( read_memory16(i[1] & 0xFFFFFFF) == (unsigned __int16)v7 )
goto LABEL_5;
v11 = (v15 >> 16) & 3;
v5 += v11 + 1;
v9 += 2 * v11;
if ( *(_QWORD *)(a1 + 2080) <= v5 )
return;
continue;
default:
goto LABEL_5;
}
do
{
while ( 1 )
{
v13 = *v9;
v14 = v9[1];
v9 += 2;
write_memory32(v13, v8, a3, a4, v10);
if ( v14 )
break;
if ( v12 == v9 )
goto LABEL_17;
}
write_memory32(v14, v8, a3, a4, v10);
}
while ( v12 != v9 );
LABEL_17:
v5 += v16;
LABEL_5:
if ( *(_QWORD *)(a1 + 2080) <= ++v5 )
break;
}
}
}

canonical_decompiled_code:
void __fastcall func2(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
unsigned __int64 v5; // r13
__int64 *i; // rbp
__int64 v7; // r12
__int64 v8; // r15
__int64 *v9; // rbx
__int64 v10; // r8
__int64 v11; // r8
__int64 *v12; // rbp
__int64 v13; // rdi
__int64 v14; // r12
unsigned __int64 v15; // [rsp+0h] [rbp-40h]
__int64 v16; // [rsp+0h] [rbp-40h]

if ( *(_QWORD *)(a1 + 2080) )
{
v5 = 0LL;
for ( i = (__int64 *)(a1 + 32); ; i = v9 )
{
v7 = *i;
v8 = i[1];
v9 = i + 2;
v10 = *i & 0xFFFFFFF;
switch ( (unsigned __int64)*i >> 28 )
{
case 0uLL:
write_memory8(*i & 0xFFFFFFF, (unsigned __int8)v8);
goto LABEL_5;
case 1uLL:
write_memory16(*i & 0xFFFFFFF, (unsigned __int16)v8);
goto LABEL_5;
case 2uLL:
write_memory32(*i & 0xFFFFFFF, i[1], a3, a4, v10);
goto LABEL_5;
case 3uLL:
v16 = (unsigned __int16)v7;
if ( !(_WORD)v7 )
goto LABEL_5;
v12 = &i[2 * (unsigned __int16)v7 + 2];
break;
case 0xDuLL:
if ( read_memory16(*i & 0xFFFFFFF) != (unsigned __int16)v8 )
{
++v5;
v9 = i + 4;
}
goto LABEL_5;
case 0xEuLL:
v15 = *i & 0xFFFFFFF;
if ( read_memory16(i[1] & 0xFFFFFFF) == (unsigned __int16)v7 )
goto LABEL_5;
v11 = (v15 >> 16) & 3;
v5 += v11 + 1;
v9 += 2 * v11;
if ( *(_QWORD *)(a1 + 2080) <= v5 )
return;
continue;
default:
goto LABEL_5;
}
do
{
while ( 1 )
{
v13 = *v9;
v14 = v9[1];
v9 += 2;
write_memory32(v13, v8, a3, a4, v10);
if ( v14 )
break;
if ( v12 == v9 )
goto LABEL_17;
}
write_memory32(v14, v8, a3, a4, v10);
}
while ( v12 != v9 );
LABEL_17:
v5 += v16;
LABEL_5:
if ( *(_QWORD *)(a1 + 2080) <= ++v5 )
break;
}
}
}

original_code:
void process_cheat_gs1(cheat_type *cheat)
{
  u32 cheat_opcode;
  u32 *code_ptr = cheat->cheat_codes;
  u32 address, value;
  u32 i;
  for(i = 0; i < cheat->num_cheat_lines; i++)
  {
    address = code_ptr[0];
    value = code_ptr[1];
    code_ptr += 2;
    cheat_opcode = address >> 28;
    address &= 0xFFFFFFF;
    switch(cheat_opcode)
    {
      case 0x0:
        write_memory8(address, value);
        break;
      case 0x1:
        write_memory16(address, value);
        break;
      case 0x2:
        write_memory32(address, value);
        break;
      case 0x3:
      {
        u32 num_addresses = address & 0xFFFF;
        u32 address1, address2;
        u32 i2;
        for(i2 = 0; i2 < num_addresses; i2++)
        {
          address1 = code_ptr[0];
          address2 = code_ptr[1];
          code_ptr += 2;
          i++;
          write_memory32(address1, value);
          if(address2 != 0)
            write_memory32(address2, value);
        }
        break;
      }
      case 0x6:
        break;
      case 0x8:
        break;
      case 0xD:
        if(read_memory16(address) != (value & 0xFFFF))
        {
          code_ptr += 2;
          i++;
        }
        break;
      case 0xE:
        if(read_memory16(value & 0xFFFFFFF) != (address & 0xFFFF))
        {
          u32 skip = ((address >> 16) & 0x03);
          code_ptr += skip * 2;
          i += skip;
        }
        break;
      case 0x0F:
        break;
    }
  }
}

canonical_original_code:
void process_cheat_gs1(struct cheat_type *cheat)
{
  unsigned long cheat_opcode;
  unsigned long *code_ptr = cheat->cheat_codes;
  unsigned long address; unsigned long value;
  unsigned long i;
  for(i = 0; i < cheat->num_cheat_lines; i++)
  {
    address = code_ptr[0];
    value = code_ptr[1];
    code_ptr += 2;
    cheat_opcode = address >> 28;
    address &= 0xFFFFFFF;
    switch(cheat_opcode)
    {
      case 0x0:
        write_memory8(address, value);
        break;
      case 0x1:
        write_memory16(address, value);
        break;
      case 0x2:
        write_memory32(address, value);
        break;
      case 0x3:
      {
        unsigned long num_addresses = address & 0xFFFF;
        unsigned long address1; unsigned long address2;
        unsigned long i2;
        for(i2 = 0; i2 < num_addresses; i2++)
        {
          address1 = code_ptr[0];
          address2 = code_ptr[1];
          code_ptr += 2;
          i++;
          write_memory32(address1, value);
          if(address2 != 0)
            write_memory32(address2, value);
        }
        break;
      }
      case 0x6:
        break;
      case 0x8:
        break;
      case 0xD:
        if(read_memory16(address) != (value & 0xFFFF))
        {
          code_ptr += 2;
          i++;
        }
        break;
      case 0xE:
        if(read_memory16(value & 0xFFFFFFF) != (address & 0xFFFF))
        {
          unsigned long skip = ((address >> 16) & 0x03);
          code_ptr += skip * 2;
          i += skip;
        }
        break;
      case 0x0F:
        break;
    }
  }
}

variable_types: struct cheat_type { unsigned char cheat_name[17]; unsigned long cheat_active; unsigned long cheat_codes[256]; unsigned long num_cheat_lines; enum cheat_variant_enum { CHEAT_TYPE_GAMESHARK_V1=0, CHEAT_TYPE_GAMESHARK_V3=1, CHEAT_TYPE_INVALID=2 } cheat_variant; } *

variable_types:
address
unsigned long

variable_types:
value
unsigned long

variable_types:
skip
unsigned long

user_defined_types: struct cheat_type { unsigned char cheat_name[17]; unsigned long cheat_active; unsigned long cheat_codes[256]; unsigned long num_cheat_lines; enum cheat_variant_enum cheat_variant; }


original_code:
void process_cheat_gs3(cheat_type *cheat)
{
  u32 cheat_opcode;
  u32 *code_ptr = cheat->cheat_codes;
  u32 address, value;
  u32 i;
  for(i = 0; i < cheat->num_cheat_lines; i++)
  {
    address = code_ptr[0];
    value = code_ptr[1];
    code_ptr += 2;
    cheat_opcode = address >> 28;
    address &= 0xFFFFFFF;
    switch(cheat_opcode)
    {
      case 0x0:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
        switch(cheat_opcode)
        {
          case 0x0:
          {
            u32 iterations = value >> 24;
            u32 i2;
            value &= 0xFF;
            for(i2 = 0; i2 <= iterations; i2++, address++)
            {
              write_memory8(address, value);
            }
            break;
          }
          case 0x2:
          {
            u32 iterations = value >> 16;
            u32 i2;
            value &= 0xFFFF;
            for(i2 = 0; i2 <= iterations; i2++, address += 2)
            {
              write_memory16(address, value);
            }
            break;
          }
          case 0x4:
            write_memory32(address, value);
            break;
        }
        break;
      case 0x4:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
        switch(cheat_opcode)
        {
          case 0x0:
            address = read_memory32(address) + (value >> 24);
            write_memory8(address, value & 0xFF);
            break;
          case 0x2:
            address = read_memory32(address) + ((value >> 16) * 2);
            write_memory16(address, value & 0xFFFF);
            break;
          case 0x4:
            address = read_memory32(address);
            write_memory32(address, value);
            break;
        }
        break;
      case 0x8:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
        switch(cheat_opcode)
        {
          case 0x0:
            value = (value & 0xFF) + read_memory8(address);
            write_memory8(address, value);
            break;
          case 0x2:
            value = (value & 0xFFFF) + read_memory16(address);
            write_memory16(address, value);
            break;
          case 0x4:
            value = value + read_memory32(address);
            write_memory32(address, value);
            break;
        }
        break;
      case 0xC:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFFF) + 0x4000000;
        switch(cheat_opcode)
        {
          case 0x6:
            write_memory16(address, value);
            break;
          case 0x7:
            write_memory32(address, value);
            break;
        }
        break;
    }
  }
}

canonical_original_code:
void process_cheat_gs3(struct cheat_type *cheat)
{
  unsigned long cheat_opcode;
  unsigned long *code_ptr = cheat->cheat_codes;
  unsigned long address; unsigned long value;
  unsigned long i;
  for(i = 0; i < cheat->num_cheat_lines; i++)
  {
    address = code_ptr[0];
    value = code_ptr[1];
    code_ptr += 2;
    cheat_opcode = address >> 28;
    address &= 0xFFFFFFF;
    switch(cheat_opcode)
    {
      case 0x0:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
        switch(cheat_opcode)
        {
          case 0x0:
          {
            unsigned long iterations = value >> 24;
            unsigned long i2;
            value &= 0xFF;
            for(i2 = 0; i2 <= iterations; i2++, address++)
            {
              write_memory8(address, value);
            }
            break;
          }
          case 0x2:
          {
            unsigned long iterations = value >> 16;
            unsigned long i2;
            value &= 0xFFFF;
            for(i2 = 0; i2 <= iterations; i2++, address += 2)
            {
              write_memory16(address, value);
            }
            break;
          }
          case 0x4:
            write_memory32(address, value);
            break;
        }
        break;
      case 0x4:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
        switch(cheat_opcode)
        {
          case 0x0:
            address = read_memory32(address) + (value >> 24);
            write_memory8(address, value & 0xFF);
            break;
          case 0x2:
            address = read_memory32(address) + ((value >> 16) * 2);
            write_memory16(address, value & 0xFFFF);
            break;
          case 0x4:
            address = read_memory32(address);
            write_memory32(address, value);
            break;
        }
        break;
      case 0x8:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
        switch(cheat_opcode)
        {
          case 0x0:
            value = (value & 0xFF) + read_memory8(address);
            write_memory8(address, value);
            break;
          case 0x2:
            value = (value & 0xFFFF) + read_memory16(address);
            write_memory16(address, value);
            break;
          case 0x4:
            value = value + read_memory32(address);
            write_memory32(address, value);
            break;
        }
        break;
      case 0xC:
        cheat_opcode = address >> 24;
        address = (address & 0xFFFFFF) + 0x4000000;
        switch(cheat_opcode)
        {
          case 0x6:
            write_memory16(address, value);
            break;
          case 0x7:
            write_memory32(address, value);
            break;
        }
        break;
    }
  }
}

variable_types:
iterations
unsigned long

user_defined_types: enum cheat_variant_enum { CHEAT_TYPE_GAMESHARK_V1=0, CHEAT_TYPE_GAMESHARK_V3=1, CHEAT_TYPE_INVALID=2 }


decompiled_code:
void __fastcall process_cheats(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5)
{
unsigned __int64 v5; // rbp
__int64 *v6; // rbx
int v7; // eax

if ( num_cheats )
{
v5 = 0LL;
v6 = cheats;
do
{
if ( v6[3] )
{
v7 = *((_DWORD *)v6 + 522);
if ( v7 )
{
if ( v7 == 1 )
process_cheat_gs3((__int64)v6, a2, a3, a4, a5);
}
else
{
process_cheat_gs1((__int64)v6, a2, a3, a4);
}
}
++v5;
v6 += 262;
}
while ( num_cheats > v5 );
}
}

original_code:
void process_cheats()
{
  u32 i;
  for(i = 0; i < num_cheats; i++)
  {
    if(cheats[i].cheat_active)
    {
      switch(cheats[i].cheat_variant)
      {
        case CHEAT_TYPE_GAMESHARK_V1:
          process_cheat_gs1(cheats + i);
          break;
        case CHEAT_TYPE_GAMESHARK_V3:
          process_cheat_gs3(cheats + i);
          break;
      }
    }
  }
}

canonical_original_code:
void process_cheats()
{
  unsigned long i;
  for(i = 0; i < num_cheats; i++)
  {
    if(cheats[i].cheat_active)
    {
      switch(cheats[i].cheat_variant)
      {
        case CHEAT_TYPE_GAMESHARK_V1:
          process_cheat_gs1(cheats + i);
          break;
        case CHEAT_TYPE_GAMESHARK_V3:
          process_cheat_gs3(cheats + i);
          break;
      }
    }
  }
}


decompiled_code:
__int64 __fastcall trigger_key(unsigned __int16 a1, __int64 a2)
{
__int64 result; // rax
__int64 v3; // rdi
unsigned __int64 v4; // rdx

result = io_registers[153];
if ( (result & 0x4000) != 0 )
{
v3 = (unsigned __int16)result & a1 & 0x3FF;
v4 = (unsigned __int64)(unsigned __int16)result >> 15;
if ( v4 )
{
result &= 0x3FFu;
if ( result != v3 )
return result;
return raise_interrupt(4096LL, a2, v4);
}
if ( v3 )
return raise_interrupt(4096LL, a2, v4);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(unsigned __int16 a1, __int64 a2)
{
__int64 result; // rax
__int64 v3; // rdi
unsigned __int64 v4; // rdx

result = io_registers[153];
if ( (result & 0x4000) != 0 )
{
v3 = (unsigned __int16)result & a1 & 0x3FF;
v4 = (unsigned __int64)(unsigned __int16)result >> 15;
if ( v4 )
{
result &= 0x3FFu;
if ( result != v3 )
return result;
return raise_interrupt(4096LL, a2, v4);
}
if ( v3 )
return raise_interrupt(4096LL, a2, v4);
}
return result;
}

original_code:
void trigger_key(u32 key)
{
  u32 p1_cnt = io_registers[REG_P1CNT];
  u32 p1;
  if((p1_cnt >> 14) & 0x01)
  {
    u32 key_intersection = (p1_cnt & key) & 0x3FF;
    if(p1_cnt >> 15)
    {
      if(key_intersection == (p1_cnt & 0x3FF))
        raise_interrupt(IRQ_KEYPAD);
    }
    else
    {
      if(key_intersection)
        raise_interrupt(IRQ_KEYPAD);
    }
  }
}

canonical_original_code:
void trigger_key(unsigned long key)
{
  unsigned long p1_cnt = io_registers[REG_P1CNT];
  unsigned long p1;
  if((p1_cnt >> 14) & 0x01)
  {
    unsigned long key_intersection = (p1_cnt & key) & 0x3FF;
    if(p1_cnt >> 15)
    {
      if(key_intersection == (p1_cnt & 0x3FF))
        raise_interrupt(IRQ_KEYPAD);
    }
    else
    {
      if(key_intersection)
        raise_interrupt(IRQ_KEYPAD);
    }
  }
}


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

if ( a1 > 0x134 )
return 0LL;
if ( a1 <= 0x110 )
{
result = 8LL;
if ( a1 != 13 )
{
result = 0LL;
if ( a1 == 120 )
result = 256LL;
}
}
else
{
switch ( a1 )
{
case 0x111u:
result = 64LL;
break;
case 0x112u:
result = 128LL;
break;
case 0x113u:
result = 16LL;
break;
case 0x114u:
result = 32LL;
break;
case 0x12Fu:
result = 4LL;
break;
case 0x130u:
result = 512LL;
break;
case 0x132u:
result = 2LL;
break;
case 0x134u:
result = 1LL;
break;
default:
return 0LL;
}
}
return result;
}

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

if ( a1 > 0x134 )
return 0LL;
if ( a1 <= 0x110 )
{
result = 8LL;
if ( a1 != 13 )
{
result = 0LL;
if ( a1 == 120 )
result = 256LL;
}
}
else
{
switch ( a1 )
{
case 0x111u:
result = 64LL;
break;
case 0x112u:
result = 128LL;
break;
case 0x113u:
result = 16LL;
break;
case 0x114u:
result = 32LL;
break;
case 0x12Fu:
result = 4LL;
break;
case 0x130u:
result = 512LL;
break;
case 0x132u:
result = 2LL;
break;
case 0x134u:
result = 1LL;
break;
default:
return 0LL;
}
}
return result;
}

original_code:
u32 key_map(SDLKey key_sym)
{
  switch(key_sym)
  {
    case SDLK_LSHIFT:
      return BUTTON_L;
    case SDLK_x:
      return BUTTON_R;
    case SDLK_DOWN:
      return BUTTON_DOWN;
    case SDLK_UP:
      return BUTTON_UP;
    case SDLK_LEFT:
      return BUTTON_LEFT;
    case SDLK_RIGHT:
      return BUTTON_RIGHT;
    case SDLK_RETURN:
      return BUTTON_START;
    case SDLK_RSHIFT:
      return BUTTON_SELECT;
    case SDLK_LCTRL:
      return BUTTON_B;
    case SDLK_LALT:
      return BUTTON_A;
    default:
      return BUTTON_NONE;
  }
}

canonical_original_code:
unsigned long key_map(enum SDLKey key_sym)
{
  switch(key_sym)
  {
    case SDLK_LSHIFT:
      return BUTTON_L;
    case SDLK_x:
      return BUTTON_R;
    case SDLK_DOWN:
      return BUTTON_DOWN;
    case SDLK_UP:
      return BUTTON_UP;
    case SDLK_LEFT:
      return BUTTON_LEFT;
    case SDLK_RIGHT:
      return BUTTON_RIGHT;
    case SDLK_RETURN:
      return BUTTON_START;
    case SDLK_RSHIFT:
      return BUTTON_SELECT;
    case SDLK_LCTRL:
      return BUTTON_B;
    case SDLK_LALT:
      return BUTTON_A;
    default:
      return BUTTON_NONE;
  }
}

variable_types: enum SDLKey { SDLK_UNKNOWN=0, SDLK_FIRST=0, SDLK_BACKSPACE=8, SDLK_TAB=9, SDLK_CLEAR=12, SDLK_RETURN=13, SDLK_PAUSE=19, SDLK_ESCAPE=27, SDLK_SPACE=32, SDLK_EXCLAIM=33, SDLK_QUOTEDBL=34, SDLK_HASH=35, SDLK_DOLLAR=36, SDLK_AMPERSAND=38, SDLK_QUOTE=39, SDLK_LEFTPAREN=40, SDLK_RIGHTPAREN=41, SDLK_ASTERISK=42, SDLK_PLUS=43, SDLK_COMMA=44, SDLK_MINUS=45, SDLK_PERIOD=46, SDLK_SLASH=47, SDLK_0=48, SDLK_1=49, SDLK_2=50, SDLK_3=51, SDLK_4=52, SDLK_5=53, SDLK_6=54, SDLK_7=55, SDLK_8=56, SDLK_9=57, SDLK_COLON=58, SDLK_SEMICOLON=59, SDLK_LESS=60, SDLK_EQUALS=61, SDLK_GREATER=62, SDLK_QUESTION=63, SDLK_AT=64, SDLK_LEFTBRACKET=91, SDLK_BACKSLASH=92, SDLK_RIGHTBRACKET=93, SDLK_CARET=94, SDLK_UNDERSCORE=95, SDLK_BACKQUOTE=96, SDLK_a=97, SDLK_b=98, SDLK_c=99, SDLK_d=100, SDLK_e=101, SDLK_f=102, SDLK_g=103, SDLK_h=104, SDLK_i=105, SDLK_j=106, SDLK_k=107, SDLK_l=108, SDLK_m=109, SDLK_n=110, SDLK_o=111, SDLK_p=112, SDLK_q=113, SDLK_r=114, SDLK_s=115, SDLK_t=116, SDLK_u=117, SDLK_v=118, SDLK_w=119, SDLK_x=120, SDLK_y=121, SDLK_z=122, SDLK_DELETE=127, SDLK_WORLD_0=160, SDLK_WORLD_1=161, SDLK_WORLD_2=162, SDLK_WORLD_3=163, SDLK_WORLD_4=164, SDLK_WORLD_5=165, SDLK_WORLD_6=166, SDLK_WORLD_7=167, SDLK_WORLD_8=168, SDLK_WORLD_9=169, SDLK_WORLD_10=170, SDLK_WORLD_11=171, SDLK_WORLD_12=172, SDLK_WORLD_13=173, SDLK_WORLD_14=174, SDLK_WORLD_15=175, SDLK_WORLD_16=176, SDLK_WORLD_17=177, SDLK_WORLD_18=178, SDLK_WORLD_19=179, SDLK_WORLD_20=180, SDLK_WORLD_21=181, SDLK_WORLD_22=182, SDLK_WORLD_23=183, SDLK_WORLD_24=184, SDLK_WORLD_25=185, SDLK_WORLD_26=186, SDLK_WORLD_27=187, SDLK_WORLD_28=188, SDLK_WORLD_29=189, SDLK_WORLD_30=190, SDLK_WORLD_31=191, SDLK_WORLD_32=192, SDLK_WORLD_33=193, SDLK_WORLD_34=194, SDLK_WORLD_35=195, SDLK_WORLD_36=196, SDLK_WORLD_37=197, SDLK_WORLD_38=198, SDLK_WORLD_39=199, SDLK_WORLD_40=200, SDLK_WORLD_41=201, SDLK_WORLD_42=202, SDLK_WORLD_43=203, SDLK_WORLD_44=204, SDLK_WORLD_45=205, SDLK_WORLD_46=206, SDLK_WORLD_47=207, SDLK_WORLD_48=208, SDLK_WORLD_49=209, SDLK_WORLD_50=210, SDLK_WORLD_51=211, SDLK_WORLD_52=212, SDLK_WORLD_53=213, SDLK_WORLD_54=214, SDLK_WORLD_55=215, SDLK_WORLD_56=216, SDLK_WORLD_57=217, SDLK_WORLD_58=218, SDLK_WORLD_59=219, SDLK_WORLD_60=220, SDLK_WORLD_61=221, SDLK_WORLD_62=222, SDLK_WORLD_63=223, SDLK_WORLD_64=224, SDLK_WORLD_65=225, SDLK_WORLD_66=226, SDLK_WORLD_67=227, SDLK_WORLD_68=228, SDLK_WORLD_69=229, SDLK_WORLD_70=230, SDLK_WORLD_71=231, SDLK_WORLD_72=232, SDLK_WORLD_73=233, SDLK_WORLD_74=234, SDLK_WORLD_75=235, SDLK_WORLD_76=236, SDLK_WORLD_77=237, SDLK_WORLD_78=238, SDLK_WORLD_79=239, SDLK_WORLD_80=240, SDLK_WORLD_81=241, SDLK_WORLD_82=242, SDLK_WORLD_83=243, SDLK_WORLD_84=244, SDLK_WORLD_85=245, SDLK_WORLD_86=246, SDLK_WORLD_87=247, SDLK_WORLD_88=248, SDLK_WORLD_89=249, SDLK_WORLD_90=250, SDLK_WORLD_91=251, SDLK_WORLD_92=252, SDLK_WORLD_93=253, SDLK_WORLD_94=254, SDLK_WORLD_95=255, SDLK_KP0=256, SDLK_KP1=257, SDLK_KP2=258, SDLK_KP3=259, SDLK_KP4=260, SDLK_KP5=261, SDLK_KP6=262, SDLK_KP7=263, SDLK_KP8=264, SDLK_KP9=265, SDLK_KP_PERIOD=266, SDLK_KP_DIVIDE=267, SDLK_KP_MULTIPLY=268, SDLK_KP_MINUS=269, SDLK_KP_PLUS=270, SDLK_KP_ENTER=271, SDLK_KP_EQUALS=272, SDLK_UP=273, SDLK_DOWN=274, SDLK_RIGHT=275, SDLK_LEFT=276, SDLK_INSERT=277, SDLK_HOME=278, SDLK_END=279, SDLK_PAGEUP=280, SDLK_PAGEDOWN=281, SDLK_F1=282, SDLK_F2=283, SDLK_F3=284, SDLK_F4=285, SDLK_F5=286, SDLK_F6=287, SDLK_F7=288, SDLK_F8=289, SDLK_F9=290, SDLK_F10=291, SDLK_F11=292, SDLK_F12=293, SDLK_F13=294, SDLK_F14=295, SDLK_F15=296, SDLK_NUMLOCK=300, SDLK_CAPSLOCK=301, SDLK_SCROLLOCK=302, SDLK_RSHIFT=303, SDLK_LSHIFT=304, SDLK_RCTRL=305, SDLK_LCTRL=306, SDLK_RALT=307, SDLK_LALT=308, SDLK_RMETA=309, SDLK_LMETA=310, SDLK_LSUPER=311, SDLK_RSUPER=312, SDLK_MODE=313, SDLK_COMPOSE=314, SDLK_HELP=315, SDLK_PRINT=316, SDLK_SYSREQ=317, SDLK_BREAK=318, SDLK_MENU=319, SDLK_POWER=320, SDLK_EURO=321, SDLK_UNDO=322, SDLK_LAST=323 }


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

result = 0LL;
if ( a1 <= 9 )
result = CSWTCH_15[a1];
return result;
}

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

result = 0LL;
if ( a1 <= 9 )
result = CSWTCH_15[a1];
return result;
}

original_code:
u32 joy_map(u32 button)
{
  switch(button)
  {
    case 4:
      return BUTTON_L;
    case 5:
      return BUTTON_R;
    case 9:
      return BUTTON_START;
    case 8:
      return BUTTON_SELECT;
    case 0:
      return BUTTON_B;
    case 1:
      return BUTTON_A;
    default:
      return BUTTON_NONE;
  }
}

canonical_original_code:
unsigned long joy_map(unsigned long button)
{
  switch(button)
  {
    case 4:
      return BUTTON_L;
    case 5:
      return BUTTON_R;
    case 9:
      return BUTTON_START;
    case 8:
      return BUTTON_SELECT;
    case 0:
      return BUTTON_B;
    case 1:
      return BUTTON_A;
    default:
      return BUTTON_NONE;
  }
}

variable_types:
button
unsigned long


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

result = SDL_NumJoysticks();
if ( (_DWORD)result )
{
SDL_JoystickOpen(0LL);
result = SDL_JoystickEventState(1LL);
}
return result;
}

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

result = SDL_NumJoysticks();
if ( (_DWORD)result )
{
SDL_JoystickOpen(0LL);
result = SDL_JoystickEventState(1LL);
}
return result;
}

original_code:
void init_input()
{
  u32 joystick_count = SDL_NumJoysticks();
  if(joystick_count > 0)
  {
    SDL_JoystickOpen(0);
    SDL_JoystickEventState(1);
  }
}

canonical_original_code:
void init_input()
{
  unsigned long joystick_count = SDL_NumJoysticks();
  if(joystick_count > 0)
  {
    SDL_JoystickOpen(0);
    SDL_JoystickEventState(1);
  }
}


main

canonical_name: main

decompiled_code:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
__pid_t v3; // eax
char *v4; // rax
char *v5; // rdi
__int64 i; // rcx
char *file; // [rsp+0h] [rbp-68h] BYREF
int pipedes[2]; // [rsp+8h] [rbp-60h] BYREF
__int128 buf; // [rsp+10h] [rbp-58h] BYREF
char v10[56]; // [rsp+20h] [rbp-48h] BYREF
unsigned __int64 v11; // [rsp+58h] [rbp-10h]

v11 = __readfsqword(0x28u);
if ( pipe(pipedes) != -1 )
{
v3 = fork();
if ( v3 != -1 )
{
if ( v3 )
{
close(pipedes[1]);
wait((__WAIT_STATUS)&file);
if ( !(BYTE1(file) | (unsigned __int8)file & 0x7F) )
{
v5 = v10;
for ( i = 12LL; i; --i )
{
*(_DWORD *)v5 = 0;
v5 += 4;
}
buf = 0LL;
if ( read(pipedes[0], &buf, 0x40uLL) > 0 )
{
v10[47] = 0;
close(pipedes[0]);
execlp((const char *)&buf, (const char *)&buf, 0LL, 0.0);
}
}
}
else
{
close(pipedes[0]);
if ( dup2(pipedes[1], 1) != -1 )
{
v4 = getenv("USER");
asprintf(&file, "%s%s%s%s", "/home/", v4, "/.cabal/bin/", "yeganesh");
execlp(file, "yeganesh", "-x", 0LL);
close(pipedes[1]);
exit(1);
}
}
}
}
exit(1);
}

original_code:
int main()
{
 int pipefd[2];
 if (pipe(pipefd) == -1)
  exit(1);
 switch (fork()) {
 case -1:
  exit(1);
 case 0:
  close(pipefd[0]);
  if (dup2(pipefd[1], 1) == -1)
   exit(1);
  execlp(({ char *yg_path; asprintf(&yg_path, "%s%s%s%s", "/home/", getenv("USER"), "/.cabal/bin/", "yeganesh"); yg_path; }), "yeganesh", "-x", ((void *)0));
  close(pipefd[1]);
  exit(1);
 default:
  close(pipefd[1]);
  int status;
  wait(&status);
  if (!((((status) & 0x7f) == 0) && ((((status) & 0xff00) >> 8) == 0)))
   exit(1);
  char buf[64] = "";
  if (read(pipefd[0], buf, 64) < 1)
   exit(1);
  buf[64 -1] = '\0';
  close(pipefd[0]);
  execlp(buf, buf, ((void *)0));
  exit(1);
 }
}

variable_types:
pipefd
int [2]

variable_types: status int

variable_types:
buf
char [64]

return_type: int


setlevel

repo: nissafors/lwrace

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

result = _isoc99_sscanf(a1, &unk_5AC, &level);
if ( (_DWORD)result != 1 || level > 9u )
level = -1;
return result;
}

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

result = _isoc99_sscanf(a1, &unk_5AC, &level);
if ( (_DWORD)result != 1 || level > 9u )
level = -1;
return result;
}

original_code:
static void setlevel(char *optarg) {
    extern int level;
    int scanfargc;
    scanfargc = sscanf(optarg, "%d", &level);
    if (scanfargc != 1 || level < 0 || level > 9) {
        level = -1;
    }
}

variable_types:
optarg
char *

variable_types: level int

variable_types: scanfargc int


showhelp

decompiled_code:
int __fastcall showhelp(const char *a1)
{
if ( !a1 )
return puts(
"Usage: lwrace [-l <0-9>] [-f <file>] [-k <file>]\n"
" lwrace [-h[=keyword] | -p | -s [-f <file>] [-l <level>] | -v ]\n"
"Run terminal mode game Lawyer Race, an enhanced clone of an old QBasic game.\n"
"Default game control: use arrow keys to move, space to stop, p to pause and\n"
"escape to abort game.\n"
"\n"
" -f <file>, or Read and store high scores to and from <file>.\n"
" --scorefile <file> Type \"lwrace --help=scorefile\" for details.\n"
" -h, --help Display this help and exit.\n"
" -k <file>, or Use keys defined in <file> for game control.\n"
" --keyfile <file> Type \"lwrace --help=keyfile\" for details.\n"
" -l <0-9>, or Set difficulty of the game. 0-2 = easy, 3 = default,\n"
" --level <0-9> 4-9 = medium to hard. High scores are level dependent.\n"
" -p, --plot Display the original game plot and exit.\n"
" -s, --scores Display high scores and exit.\n"
" -v, --version Output version information and exit.\n"
"\n"
"Report bugs to aa@mensa.se\n"
"Github project page: <https://github.com/nissafors/lwrace>");
if ( !strcmp(a1, "keyfile") )
return puts(
"There are seven possible actions in a lawyer race game: Move up, move down,\n"
"move left, move right, stop, pause and give up. By default these actions are\n"
"mapped to arrow keys, space, p and esc respectively. To remap keys, you can\n"
"use a keyfile. This is a textfile containing key map commands with syntax:\n"
"\n"
" action (whitespace) key\n"
"\n"
"\"Action\" is one of the following: up, down, left, right, stop, pause or exit\n"
"\"Whitespace\" is tabs or spaces.\n"
"\"Key\" is either a typable character surrounded by single quotes, a raw\n"
"number that curses getch() can handle or any of <return>, <tab>, <esc>,\n"
"<space>, <enter>, <down>, <up>, <left>, <right>, <home>, <backspace>, <del>,\n"
" <ins>, <pgdn>, <pgup> or <end>. Note that you can't use ' '; Use <space>.\n"
"Here's a sample keyfile to make things clearer:\n"
"\n"
" # Lines that begin with \"#\" are comments\n"
" pause 27\n"
" up 'w'\n"
" down 's'\n"
" left 'a'\n"
" right 'd'\n"
" exit <end>\n"
"\n"
"\"lwrace --keyfile /path/to/keyfile\" tells the program to use your keyfile.\n"
"You can also rename you file \"keys\" and put it in ~/.lwrace/, where lwrace\n"
"will look by default.");
if ( strcmp(a1, "scorefile") )
return puts(
"Usage: lwrace [-l <0-9>] [-f <file>] [-k <file>]\n"
" lwrace [-h[=keyword] | -p | -s [-f <file>] [-l <level>] | -v ]\n"
"Run terminal mode game Lawyer Race, an enhanced clone of an old QBasic game.\n"
"Default game control: use arrow keys to move, space to stop, p to pause and\n"
"escape to abort game.\n"
"\n"
" -f <file>, or Read and store high scores to and from <file>.\n"
" --scorefile <file> Type \"lwrace --help=scorefile\" for details.\n"
" -h, --help Display this help and exit.\n"
" -k <file>, or Use keys defined in <file> for game control.\n"
" --keyfile <file> Type \"lwrace --help=keyfile\" for details.\n"
" -l <0-9>, or Set difficulty of the game. 0-2 = easy, 3 = default,\n"
" --level <0-9> 4-9 = medium to hard. High scores are level dependent.\n"
" -p, --plot Display the original game plot and exit.\n"
" -s, --scores Display high scores and exit.\n"
" -v, --version Output version information and exit.\n"
"\n"
"Report bugs to aa@mensa.se\n"
"Github project page: <https://github.com/nissafors/lwrace>");
return puts(
"By default lawyer race writes high scores to files in ~/.lwrace/ directory.\n"
"Filenames are prepended with .<number>, where <number> is the level chosen\n"
"with the --level option. A player who has played on default level plus level\n"
"two and level six will have these files in his/her ~/.lwrace/ directory:\n"
"\n"
" highscores.2 highscores.3 highscores.6\n"
"\n"
"You can tell the program to store scores in a high score file of your choice\n"
"by issuing \"lwrace --scorefile /path/to/scorefile\".\n"
"Note that the level extension will always be added to the filename, thus the\n"
"command \"lwrace -l 5 -f myfile \" will produce the file \"myfile.5\"");
}

canonical_decompiled_code:
int __fastcall func1(const char *a1)
{
if ( !a1 )
return puts(
"Usage: lwrace [-l <0-9>] [-f <file>] [-k <file>]\n"
" lwrace [-h[=keyword] | -p | -s [-f <file>] [-l <level>] | -v ]\n"
"Run terminal mode game Lawyer Race, an enhanced clone of an old QBasic game.\n"
"Default game control: use arrow keys to move, space to stop, p to pause and\n"
"escape to abort game.\n"
"\n"
" -f <file>, or Read and store high scores to and from <file>.\n"
" --scorefile <file> Type \"lwrace --help=scorefile\" for details.\n"
" -h, --help Display this help and exit.\n"
" -k <file>, or Use keys defined in <file> for game control.\n"
" --keyfile <file> Type \"lwrace --help=keyfile\" for details.\n"
" -l <0-9>, or Set difficulty of the game. 0-2 = easy, 3 = default,\n"
" --level <0-9> 4-9 = medium to hard. High scores are level dependent.\n"
" -p, --plot Display the original game plot and exit.\n"
" -s, --scores Display high scores and exit.\n"
" -v, --version Output version information and exit.\n"
"\n"
"Report bugs to aa@mensa.se\n"
"Github project page: <https://github.com/nissafors/lwrace>");
if ( !strcmp(a1, "keyfile") )
return puts(
"There are seven possible actions in a lawyer race game: Move up, move down,\n"
"move left, move right, stop, pause and give up. By default these actions are\n"
"mapped to arrow keys, space, p and esc respectively. To remap keys, you can\n"
"use a keyfile. This is a textfile containing key map commands with syntax:\n"
"\n"
" action (whitespace) key\n"
"\n"
"\"Action\" is one of the following: up, down, left, right, stop, pause or exit\n"
"\"Whitespace\" is tabs or spaces.\n"
"\"Key\" is either a typable character surrounded by single quotes, a raw\n"
"number that curses getch() can handle or any of <return>, <tab>, <esc>,\n"
"<space>, <enter>, <down>, <up>, <left>, <right>, <home>, <backspace>, <del>,\n"
" <ins>, <pgdn>, <pgup> or <end>. Note that you can't use ' '; Use <space>.\n"
"Here's a sample keyfile to make things clearer:\n"
"\n"
" # Lines that begin with \"#\" are comments\n"
" pause 27\n"
" up 'w'\n"
" down 's'\n"
" left 'a'\n"
" right 'd'\n"
" exit <end>\n"
"\n"
"\"lwrace --keyfile /path/to/keyfile\" tells the program to use your keyfile.\n"
"You can also rename you file \"keys\" and put it in ~/.lwrace/, where lwrace\n"
"will look by default.");
if ( strcmp(a1, "scorefile") )
return puts(
"Usage: lwrace [-l <0-9>] [-f <file>] [-k <file>]\n"
" lwrace [-h[=keyword] | -p | -s [-f <file>] [-l <level>] | -v ]\n"
"Run terminal mode game Lawyer Race, an enhanced clone of an old QBasic game.\n"
"Default game control: use arrow keys to move, space to stop, p to pause and\n"
"escape to abort game.\n"
"\n"
" -f <file>, or Read and store high scores to and from <file>.\n"
" --scorefile <file> Type \"lwrace --help=scorefile\" for details.\n"
" -h, --help Display this help and exit.\n"
" -k <file>, or Use keys defined in <file> for game control.\n"
" --keyfile <file> Type \"lwrace --help=keyfile\" for details.\n"
" -l <0-9>, or Set difficulty of the game. 0-2 = easy, 3 = default,\n"
" --level <0-9> 4-9 = medium to hard. High scores are level dependent.\n"
" -p, --plot Display the original game plot and exit.\n"
" -s, --scores Display high scores and exit.\n"
" -v, --version Output version information and exit.\n"
"\n"
"Report bugs to aa@mensa.se\n"
"Github project page: <https://github.com/nissafors/lwrace>");
return puts(
"By default lawyer race writes high scores to files in ~/.lwrace/ directory.\n"
"Filenames are prepended with .<number>, where <number> is the level chosen\n"
"with the --level option. A player who has played on default level plus level\n"
"two and level six will have these files in his/her ~/.lwrace/ directory:\n"
"\n"
" highscores.2 highscores.3 highscores.6\n"
"\n"
"You can tell the program to store scores in a high score file of your choice\n"
"by issuing \"lwrace --scorefile /path/to/scorefile\".\n"
"Note that the level extension will always be added to the filename, thus the\n"
"command \"lwrace -l 5 -f myfile \" will produce the file \"myfile.5\"");
}

original_code:
static void showhelp(char *optarg) {
    if (optarg) {
        if (strcmp(optarg, "keyfile") == 0) {
            puts(keyfilehelp);
            return;
        } else if (strcmp(optarg, "scorefile") == 0) {
            puts(scorefilehelp);
            return;
        }
    }
    puts(usage);
}


incompatibleopts

decompiled_code:
__int64 __fastcall incompatibleopts(char *s)
{
_BOOL4 v1; // er12
size_t v2; // rax

if ( strchr(s, 112) || (v1 = 0, strchr(s, 118)) )
v1 = strlen(s) > 1;
if ( !strchr(s, 115) )
return v1;
v2 = strlen(s);
if ( v2 > 3 )
return 1LL;
if ( v2 == 3 )
{
if ( strchr(s, 102) )
goto LABEL_7;
return 1LL;
}
if ( v2 != 2 )
return v1;
if ( !strchr(s, 102) )
{
LABEL_7:
if ( !strchr(s, 108) )
v1 = 1;
return v1;
}
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func2(char *s)
{
_BOOL4 v1; // er12
size_t v2; // rax

if ( strchr(s, 112) || (v1 = 0, strchr(s, 118)) )
v1 = strlen(s) > 1;
if ( !strchr(s, 115) )
return v1;
v2 = strlen(s);
if ( v2 > 3 )
return 1LL;
if ( v2 == 3 )
{
if ( strchr(s, 102) )
goto LABEL_7;
return 1LL;
}
if ( v2 != 2 )
return v1;
if ( !strchr(s, 102) )
{
LABEL_7:
if ( !strchr(s, 108) )
v1 = 1;
return v1;
}
return v1;
}

original_code:
int incompatibleopts(char *argstring) {
    int errbool = 0;
    if ( (strchr(argstring, 'p') || strchr(argstring, 'v')) &&
          strlen(argstring) > 1 )
    {
        errbool = 1;
    }
    if (strchr(argstring, 's')) {
        if (strlen(argstring) > 3)
            errbool = 1;
        if (strlen(argstring) == 3)
            if ( !(strchr(argstring, 'f') && strchr(argstring, 'l')) )
                errbool = 1;
        if (strlen(argstring) == 2)
            if ( !(strchr(argstring, 'f') || strchr(argstring, 'l')) )
                errbool = 1;
    }
    return errbool;
}

variable_types:
argstring
char *

variable_types: errbool int


parseargs

decompiled_code:
__int64 __fastcall parseargs(int argc, char **argv)
{
unsigned int v2; // er14
char *v3; // rbx
int v4; // eax
int v5; // er12
void *v6; // r15
void *v7; // r15
unsigned int v8; // er12
char s[8]; // [rsp+8h] [rbp-140h] BYREF
struct option longopts; // [rsp+10h] [rbp-138h] BYREF
const char *v12; // [rsp+30h] [rbp-118h]
int v13; // [rsp+38h] [rbp-110h]
__int64 v14; // [rsp+40h] [rbp-108h]
int v15; // [rsp+48h] [rbp-100h]
const char *v16; // [rsp+50h] [rbp-F8h]
int v17; // [rsp+58h] [rbp-F0h]
__int64 v18; // [rsp+60h] [rbp-E8h]
int v19; // [rsp+68h] [rbp-E0h]
const char *v20; // [rsp+70h] [rbp-D8h]
int v21; // [rsp+78h] [rbp-D0h]
__int64 v22; // [rsp+80h] [rbp-C8h]
int v23; // [rsp+88h] [rbp-C0h]
const char *v24; // [rsp+90h] [rbp-B8h]
int v25; // [rsp+98h] [rbp-B0h]
__int64 v26; // [rsp+A0h] [rbp-A8h]
int v27; // [rsp+A8h] [rbp-A0h]
const char *v28; // [rsp+B0h] [rbp-98h]
int v29; // [rsp+B8h] [rbp-90h]
__int64 v30; // [rsp+C0h] [rbp-88h]
int v31; // [rsp+C8h] [rbp-80h]
const char *v32; // [rsp+D0h] [rbp-78h]
int v33; // [rsp+D8h] [rbp-70h]
__int64 v34; // [rsp+E0h] [rbp-68h]
int v35; // [rsp+E8h] [rbp-60h]
__int64 v36; // [rsp+F0h] [rbp-58h]
int v37; // [rsp+F8h] [rbp-50h]
__int64 v38; // [rsp+100h] [rbp-48h]
int v39; // [rsp+108h] [rbp-40h]

v2 = 0;
s[0] = 0;
v3 = s;
longopts.name = "level";
longopts.has_arg = 1;
longopts.flag = 0LL;
longopts.val = 108;
v12 = "scorefile";
v13 = 1;
v14 = 0LL;
v15 = 102;
v16 = "help";
v17 = 2;
v18 = 0LL;
v19 = 104;
v20 = "keyfile";
v21 = 1;
v22 = 0LL;
v23 = 107;
v24 = "plot";
v25 = 0;
v26 = 0LL;
v27 = 112;
v28 = "scores";
v29 = 0;
v30 = 0LL;
v31 = 115;
v32 = "version";
v33 = 0;
v34 = 0LL;
v35 = 118;
v36 = 0LL;
v37 = 0;
v38 = 0LL;
v39 = 0;
while ( 1 )
{
v4 = getopt_long(argc, argv, "l:f:h::k:psv", &longopts, 0LL);
v5 = v4;
if ( v4 == -1 )
break;
if ( v4 == 63 || v4 == 58 )
goto LABEL_37;
if ( strchr(s, v4) )
{
fprintf(stderr, "%s: option may be given only once -- %c\n", *argv, (unsigned int)v5);
goto LABEL_37;
}
if ( optarg && *optarg == 61 )
++optarg;
if ( v5 == 107 )
{
v6 = (void *)expandpath(optarg, 1LL);
if ( v6 )
{
v2 |= 4u;
free(key_file_path);
key_file_path = v6;
}
}
else if ( v5 > 107 )
{
if ( v5 == 108 )
{
v2 |= 1u;
setlevel((__int64)optarg);
}
}
else if ( v5 == 102 )
{
v7 = (void *)expandpath(optarg, 1LL);
if ( v7 )
{
v2 |= 2u;
free(hiscore_file_path);
hiscore_file_path = v7;
}
}
else if ( v5 == 104 )
{
showhelp(optarg);
exit(0);
}
*v3++ = v5;
*v3 = 0;
}
if ( (unsigned int)incompatibleopts(s) )
{
error(1, 0, "illegal combination of arguments -- %s", s);
goto LABEL_39;
}
v8 = level;
if ( level == -1 )
{
fprintf(stderr, "%s: level out of range\n", *argv);
goto LABEL_37;
}
if ( strchr(s, 102) && !hiscore_file_path || strchr(s, 107) && !key_file_path )
{
LABEL_39:
fprintf(stderr, "%s: could not expand path\n", *argv);
LABEL_37:
exit(1);
}
if ( strchr(s, 115) )
{
if ( !strchr(s, 108) )
{
level = -1;
v8 = -1;
}
printscores(hiscore_file_path, v8);
exit(0);
}
if ( s[0] == 112 )
{
puts(
"L A W Y E R R A C E - The original QB game plot:\n"
"\"Once mr O needed a lawyer for some reason, and so he hired one. When the\n"
"case was lost and all mr O:s money was gone with the wind, the lawyer\n"
"office still wanted its fee, and they set after mr O, who had fled to the\n"
"mountains, looking for dollars. Rocks are falling all around him while mr O\n"
"is struggling to escape wild lawyers and to collect money enough to set him\n"
"free. Play the game to find out if mr O will make it!\"");
exit(0);
}
if ( s[0] == 118 )
{
printf("Lawyer race version %s\n", "1.0 RC1");
exit(0);
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func3(int argc, char **argv)
{
unsigned int v2; // er14
char *v3; // rbx
int v4; // eax
int v5; // er12
void *v6; // r15
void *v7; // r15
unsigned int v8; // er12
char s[8]; // [rsp+8h] [rbp-140h] BYREF
struct option longopts; // [rsp+10h] [rbp-138h] BYREF
const char *v12; // [rsp+30h] [rbp-118h]
int v13; // [rsp+38h] [rbp-110h]
__int64 v14; // [rsp+40h] [rbp-108h]
int v15; // [rsp+48h] [rbp-100h]
const char *v16; // [rsp+50h] [rbp-F8h]
int v17; // [rsp+58h] [rbp-F0h]
__int64 v18; // [rsp+60h] [rbp-E8h]
int v19; // [rsp+68h] [rbp-E0h]
const char *v20; // [rsp+70h] [rbp-D8h]
int v21; // [rsp+78h] [rbp-D0h]
__int64 v22; // [rsp+80h] [rbp-C8h]
int v23; // [rsp+88h] [rbp-C0h]
const char *v24; // [rsp+90h] [rbp-B8h]
int v25; // [rsp+98h] [rbp-B0h]
__int64 v26; // [rsp+A0h] [rbp-A8h]
int v27; // [rsp+A8h] [rbp-A0h]
const char *v28; // [rsp+B0h] [rbp-98h]
int v29; // [rsp+B8h] [rbp-90h]
__int64 v30; // [rsp+C0h] [rbp-88h]
int v31; // [rsp+C8h] [rbp-80h]
const char *v32; // [rsp+D0h] [rbp-78h]
int v33; // [rsp+D8h] [rbp-70h]
__int64 v34; // [rsp+E0h] [rbp-68h]
int v35; // [rsp+E8h] [rbp-60h]
__int64 v36; // [rsp+F0h] [rbp-58h]
int v37; // [rsp+F8h] [rbp-50h]
__int64 v38; // [rsp+100h] [rbp-48h]
int v39; // [rsp+108h] [rbp-40h]

v2 = 0;
s[0] = 0;
v3 = s;
longopts.name = "level";
longopts.has_arg = 1;
longopts.flag = 0LL;
longopts.val = 108;
v12 = "scorefile";
v13 = 1;
v14 = 0LL;
v15 = 102;
v16 = "help";
v17 = 2;
v18 = 0LL;
v19 = 104;
v20 = "keyfile";
v21 = 1;
v22 = 0LL;
v23 = 107;
v24 = "plot";
v25 = 0;
v26 = 0LL;
v27 = 112;
v28 = "scores";
v29 = 0;
v30 = 0LL;
v31 = 115;
v32 = "version";
v33 = 0;
v34 = 0LL;
v35 = 118;
v36 = 0LL;
v37 = 0;
v38 = 0LL;
v39 = 0;
while ( 1 )
{
v4 = getopt_long(argc, argv, "l:f:h::k:psv", &longopts, 0LL);
v5 = v4;
if ( v4 == -1 )
break;
if ( v4 == 63 || v4 == 58 )
goto LABEL_37;
if ( strchr(s, v4) )
{
fprintf(stderr, "%s: option may be given only once -- %c\n", *argv, (unsigned int)v5);
goto LABEL_37;
}
if ( optarg && *optarg == 61 )
++optarg;
if ( v5 == 107 )
{
v6 = (void *)expandpath(optarg, 1LL);
if ( v6 )
{
v2 |= 4u;
free(key_file_path);
key_file_path = v6;
}
}
else if ( v5 > 107 )
{
if ( v5 == 108 )
{
v2 |= 1u;
func0((__int64)optarg);
}
}
else if ( v5 == 102 )
{
v7 = (void *)expandpath(optarg, 1LL);
if ( v7 )
{
v2 |= 2u;
free(hiscore_file_path);
hiscore_file_path = v7;
}
}
else if ( v5 == 104 )
{
func1(optarg);
exit(0);
}
*v3++ = v5;
*v3 = 0;
}
if ( (unsigned int)func2(s) )
{
error(1, 0, "illegal combination of arguments -- %s", s);
goto LABEL_39;
}
v8 = level;
if ( level == -1 )
{
fprintf(stderr, "%s: level out of range\n", *argv);
goto LABEL_37;
}
if ( strchr(s, 102) && !hiscore_file_path || strchr(s, 107) && !key_file_path )
{
LABEL_39:
fprintf(stderr, "%s: could not expand path\n", *argv);
LABEL_37:
exit(1);
}
if ( strchr(s, 115) )
{
if ( !strchr(s, 108) )
{
level = -1;
v8 = -1;
}
printscores(hiscore_file_path, v8);
exit(0);
}
if ( s[0] == 112 )
{
puts(
"L A W Y E R R A C E - The original QB game plot:\n"
"\"Once mr O needed a lawyer for some reason, and so he hired one. When the\n"
"case was lost and all mr O:s money was gone with the wind, the lawyer\n"
"office still wanted its fee, and they set after mr O, who had fled to the\n"
"mountains, looking for dollars. Rocks are falling all around him while mr O\n"
"is struggling to escape wild lawyers and to collect money enough to set him\n"
"free. Play the game to find out if mr O will make it!\"");
exit(0);
}
if ( s[0] == 118 )
{
printf("Lawyer race version %s\n", "1.0 RC1");
exit(0);
}
return v2;
}

original_code:
int parseargs(int argc, char *argv[])
{
    extern int level;
    extern char *key_file_path;
    extern char *hiscore_file_path;
    int return_bits = 0;
    char *heap_area_for_scorefile_path;
    char *heap_area_for_keyfile_path;
    int c, i;
    char argstring[7 + 1];
    argstring[0] = '\0';
    char *optstring = "l:f:h::k:psv";
    struct option longopts[] = {
        {"level", 1, ((void *)0), 'l'},
        {"scorefile", 1, ((void *)0), 'f'},
        {"help", 2, ((void *)0), 'h'},
        {"keyfile", 1, ((void *)0), 'k'},
        {"plot", 0, ((void *)0), 'p'},
        {"scores", 0, ((void *)0), 's'},
        {"version", 0, ((void *)0), 'v'},
        {0, 0, 0, 0}
    };
    i = 0;
    while ((c = getopt_long(argc, argv, optstring, longopts, ((void *)0))) != -1) {
        if (c == '?' || c == ':')
            exit(1);
        if ( (strchr(argstring, c)) ) {
            fprintf(stderr, "%s: option may be given only once -- %c\n",
                    argv[0], c);
            exit(1);
        }
        if(optarg && *optarg == '=')
            optarg++;
        switch (c) {
            case 'l':
                setlevel(optarg);
                return_bits = return_bits | 1;
                break;
            case 'f':
                if( (heap_area_for_scorefile_path = expandpath(optarg, 1)) )
                {
                    free(hiscore_file_path);
                    hiscore_file_path = heap_area_for_scorefile_path;
                    return_bits = return_bits | 2;
                }
                break;
            case 'h':
                showhelp(optarg);
                exit(0);
            case 'k':
                if( (heap_area_for_keyfile_path = expandpath(optarg, 1)) )
                {
                    free(key_file_path);
                    key_file_path = heap_area_for_keyfile_path;
                    return_bits = return_bits | 4;
                }
                break;
        }
        argstring[i++] = (char)c;
        argstring[i] = '\0';
    }
    if (incompatibleopts(argstring))
        error(1, 0, "illegal combination of arguments -- %s", argstring);
    if (level == -1) {
        fprintf(stderr, "%s: level out of range\n", argv[0]);
        exit(1);
    }
    if ( (strchr(argstring, 'f') && !hiscore_file_path) ||
         (strchr(argstring, 'k') && !key_file_path) )
    {
        fprintf(stderr, "%s: could not expand path\n", argv[0]);
        exit(1);
    }
    if (strchr(argstring, 's')) {
        if (!strchr(argstring, 'l')) {
            level = -1;
        }
        printscores(hiscore_file_path, level);
        exit(0);
    }
    if (*argstring == 'p') {
        puts(plot);
        exit(0);
    }
    if (*argstring == 'v') {
        printf(version, "1.0 RC1");
        exit(0);
    }
    return return_bits;
}

canonical_original_code:
int parseargs(int argc, char *argv[])
{
    extern int level;
    extern char *key_file_path;
    extern char *hiscore_file_path;
    int return_bits = 0;
    char *heap_area_for_scorefile_path;
    char *heap_area_for_keyfile_path;
    int c; int i;
    char argstring[-1];
    argstring[0] = '\0';
    char *optstring = "l:f:h::k:psv";
    struct option longopts[] = {
        {"level", 1, ((void *)0), 'l'},
        {"scorefile", 1, ((void *)0), 'f'},
        {"help", 2, ((void *)0), 'h'},
        {"keyfile", 1, ((void *)0), 'k'},
        {"plot", 0, ((void *)0), 'p'},
        {"scores", 0, ((void *)0), 's'},
        {"version", 0, ((void *)0), 'v'},
        {0, 0, 0, 0}
    };
    i = 0;
    while ((c = getopt_long(argc, argv, optstring, longopts, ((void *)0))) != -1) {
        if (c == '?' || c == ':')
            exit(1);
        if ( (strchr(argstring, c)) ) {
            fprintf(stderr, "%s: option may be given only once -- %c\n",
                    argv[0], c);
            exit(1);
        }
        if(optarg && *optarg == '=')
            optarg++;
        switch (c) {
            case 'l':
                setlevel(optarg);
                return_bits = return_bits | 1;
                break;
            case 'f':
                if( (heap_area_for_scorefile_path = expandpath(optarg, 1)) )
                {
                    free(hiscore_file_path);
                    hiscore_file_path = heap_area_for_scorefile_path;
                    return_bits = return_bits | 2;
                }
                break;
            case 'h':
                showhelp(optarg);
                exit(0);
            case 'k':
                if( (heap_area_for_keyfile_path = expandpath(optarg, 1)) )
                {
                    free(key_file_path);
                    key_file_path = heap_area_for_keyfile_path;
                    return_bits = return_bits | 4;
                }
                break;
        }
        argstring[i++] = (char)c;
        argstring[i] = '\0';
    }
    if (incompatibleopts(argstring))
        error(1, 0, "illegal combination of arguments -- %s", argstring);
    if (level == -1) {
        fprintf(stderr, "%s: level out of range\n", argv[0]);
        exit(1);
    }
    if ( (strchr(argstring, 'f') && !hiscore_file_path) ||
         (strchr(argstring, 'k') && !key_file_path) )
    {
        fprintf(stderr, "%s: could not expand path\n", argv[0]);
        exit(1);
    }
    if (strchr(argstring, 's')) {
        if (!strchr(argstring, 'l')) {
            level = -1;
        }
        printscores(hiscore_file_path, level);
        exit(0);
    }
    if (*argstring == 'p') {
        puts(plot);
        exit(0);
    }
    if (*argstring == 'v') {
        printf(version, "1.0 RC1");
        exit(0);
    }
    return return_bits;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types: c int

variable_types: i int

variable_types:
argstring
char [-1]

variable_types:
optstring
char *

variable_types: struct option { char *name; int has_arg; int *flag; int val; } []


initglobals

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

level = 3;
enemy_nokill_time = LC0;
fobj_init_delay_min = 24;
row_to_col_delay_ratio = LC1;
fobj_init_delay_max = 48;
fobj_fall_delay_start = LC2;
fobj_hang_delay_min = 0;
fobj_fall_delay_end = LC3;
fobj_hang_delay_max = 24;
fobj_base = LC4;
key_esc = 27;
fobj_acc = LC5;
key_pause = 112;
key_stop = 32;
key_enter = 10;
key_up = 259;
key_down = 258;
key_left = 260;
key_right = 261;
key_file_path = expandpath("~/.lwrace/keys", 1LL);
result = expandpath("~/.lwrace/highscores", 1LL);
hiscore_file_path = result;
return result;
}

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

level = 3;
enemy_nokill_time = LC0;
fobj_init_delay_min = 24;
row_to_col_delay_ratio = LC1;
fobj_init_delay_max = 48;
fobj_fall_delay_start = LC2;
fobj_hang_delay_min = 0;
fobj_fall_delay_end = LC3;
fobj_hang_delay_max = 24;
fobj_base = LC4;
key_esc = 27;
fobj_acc = LC5;
key_pause = 112;
key_stop = 32;
key_enter = 10;
key_up = 259;
key_down = 258;
key_left = 260;
key_right = 261;
key_file_path = expandpath("~/.lwrace/keys", 1LL);
result = expandpath("~/.lwrace/highscores", 1LL);
hiscore_file_path = result;
return result;
}

original_code:
static void initglobals() {
    level = 3;
    enemy_nokill_time = 3;
    row_to_col_delay_ratio = 23.0 / 80.0;
    fobj_init_delay_min = 24;
    fobj_init_delay_max = 48;
    fobj_hang_delay_min = 0;
    fobj_hang_delay_max = 24;
    fobj_fall_delay_start = 4.8;
    fobj_fall_delay_end = 0.72;
    fobj_base = 2;
    fobj_acc = 16;
    key_esc = 27;
    key_pause = 'p';
    key_stop = ' ';
    key_enter = '\n';
    key_up = 0403;
    key_down = 0402;
    key_left = 0404;
    key_right = 0405;
    key_file_path = expandpath("~/.lwrace/keys", 1);
    hiscore_file_path = expandpath("~/.lwrace/highscores", 1);
}


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // ebx
char v4; // r12
void *v5; // rdi
int v6; // er14
int v7; // esi
int v8; // eax
unsigned int v9; // er13
unsigned int v10; // eax
__int64 v11; // rsi
unsigned int v12; // er12
__int64 v13; // rdi
unsigned __int64 v14; // r15
int v15; // edx
int v16; // eax
unsigned __int64 v17; // rbp
unsigned int v18; // eax
__int64 v20; // rbp

initglobals(argc, argv, envp);
v4 = parseargs((unsigned int)argc, argv);
setspeed();
if ( (unsigned int)setkeys(key_file_path) == 2 )
return 1;
v5 = (void *)expandpath("~/.lwrace", 0LL);
v6 = mk_default_dir(v5);
free(v5);
if ( v6 && (v4 & 2) != 0 )
v6 = 0;
seedgenrand();
initscr();
cbreak();
keypad(stdscr, 1);
noecho();
curs_set(0);
nodelay(stdscr, 1);
if ( stdscr )
{
v7 = stdscr->_maxy + 1;
v8 = stdscr->_maxx + 1;
}
else
{
v7 = -1;
v8 = -1;
}
cols = v8;
v9 = 0;
rows = v7 - 1;
v10 = genrand(0LL);
v11 = (unsigned int)cols;
v12 = v10;
v13 = 0xFFFFFFFFLL;
v14 = (unsigned int)genrand(0LL);
while ( 1 )
{
v18 = getdir(v13, v11);
if ( v18 == -2 )
break;
if ( v18 == 9 )
idle("Game paused");
else
v3 = v18;
if ( stdscr )
{
v15 = stdscr->_maxy;
v16 = stdscr->_maxx + 1;
}
else
{
v15 = -2;
v16 = -1;
}
rows = v15;
cols = v16;
v17 = drawplayer(v3, (v14 << 32) | v12);
v12 = v17;
v14 = HIDWORD(v17);
v9 += treasures(v17);
printstatus(v9);
if ( (unsigned int)drawenemies(v17, v9) || (v11 = v9, (unsigned int)fobjects(v17, v9)) )
{
if ( wmove(stdscr, v17, SHIDWORD(v17)) != -1 )
waddch(stdscr, 0x58uLL);
wrefresh(stdscr);
idle("GAME OVER!");
if ( !v6 && (unsigned int)is_high_score(v9, (unsigned int)level, hiscore_file_path) )
{
v20 = getname();
endwin();
if ( !(unsigned int)writescores(hiscore_file_path, v20, v9, (unsigned int)level) )
{
printscores(hiscore_file_path, (unsigned int)level);
exit(0);
}
error(1, 0, "Can't open high score file -- %s", (const char *)hiscore_file_path);
JUMPOUT(0x62CLL);
}
break;
}
v13 = v3;
}
endwin();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // ebx
char v4; // r12
void *v5; // rdi
int v6; // er14
int v7; // esi
int v8; // eax
unsigned int v9; // er13
unsigned int v10; // eax
__int64 v11; // rsi
unsigned int v12; // er12
__int64 v13; // rdi
unsigned __int64 v14; // r15
int v15; // edx
int v16; // eax
unsigned __int64 v17; // rbp
unsigned int v18; // eax
__int64 v20; // rbp

func0(argc, argv, envp);
v4 = parseargs((unsigned int)argc, argv);
setspeed();
if ( (unsigned int)setkeys(key_file_path) == 2 )
return 1;
v5 = (void *)expandpath("~/.lwrace", 0LL);
v6 = mk_default_dir(v5);
free(v5);
if ( v6 && (v4 & 2) != 0 )
v6 = 0;
seedgenrand();
initscr();
cbreak();
keypad(stdscr, 1);
noecho();
curs_set(0);
nodelay(stdscr, 1);
if ( stdscr )
{
v7 = stdscr->_maxy + 1;
v8 = stdscr->_maxx + 1;
}
else
{
v7 = -1;
v8 = -1;
}
cols = v8;
v9 = 0;
rows = v7 - 1;
v10 = genrand(0LL);
v11 = (unsigned int)cols;
v12 = v10;
v13 = 0xFFFFFFFFLL;
v14 = (unsigned int)genrand(0LL);
while ( 1 )
{
v18 = getdir(v13, v11);
if ( v18 == -2 )
break;
if ( v18 == 9 )
func1("Game paused");
else
v3 = v18;
if ( stdscr )
{
v15 = stdscr->_maxy;
v16 = stdscr->_maxx + 1;
}
else
{
v15 = -2;
v16 = -1;
}
rows = v15;
cols = v16;
v17 = drawplayer(v3, (v14 << 32) | v12);
v12 = v17;
v14 = HIDWORD(v17);
v9 += treasures(v17);
printstatus(v9);
if ( (unsigned int)drawenemies(v17, v9) || (v11 = v9, (unsigned int)fobjects(v17, v9)) )
{
if ( wmove(stdscr, v17, SHIDWORD(v17)) != -1 )
waddch(stdscr, 0x58uLL);
wrefresh(stdscr);
func1("GAME OVER!");
if ( !v6 && (unsigned int)is_high_score(v9, (unsigned int)level, hiscore_file_path) )
{
v20 = getname();
endwin();
if ( !(unsigned int)writescores(hiscore_file_path, v20, v9, (unsigned int)level) )
{
printscores(hiscore_file_path, (unsigned int)level);
exit(0);
}
error(1, 0, "Can't open high score file -- %s", (const char *)hiscore_file_path);
JUMPOUT(0x62CLL);
}
break;
}
v13 = v3;
}
endwin();
return 0;
}

original_code:
int main(int argc, char *argv[])
{
    struct pos plpos;
    dir_t pldir;
    dir_t lastdir;
    int score;
    char *name;
    char *default_dir;
    int parseargs_bitmask;
    bool_t scores_off;
    initglobals();
    parseargs_bitmask = parseargs(argc, argv);
    setspeed();
    if (setkeys(key_file_path) == 2) {
        return 1;
    }
    default_dir = expandpath("~/.lwrace", 0);
    scores_off = mk_default_dir(default_dir);
    free(default_dir);
    if (scores_off && (parseargs_bitmask & 2)) {
        scores_off = 0;
    }
    seedgenrand();
    initscr();
    cbreak();
    keypad(stdscr, 1);
    noecho();
    curs_set(0);
    nodelay(stdscr, 1);
    pldir = -1;
    ((rows) = ((0 != (const void *)((stdscr))) ? ((stdscr)->_maxy + 1) : (-1)), (cols) = ((0 != (const void *)((stdscr))) ? ((stdscr)->_maxx + 1) : (-1))), rows--;
    plpos.row = genrand(0, rows);
    plpos.col = genrand(0, cols);
    score = 0;
    while ((pldir = getdir(pldir)) != -2) {
        if (pldir == 9) {
            idle("Game paused");
            pldir = lastdir;
        }
        lastdir = pldir;
        ((rows) = ((0 != (const void *)((stdscr))) ? ((stdscr)->_maxy + 1) : (-1)), (cols) = ((0 != (const void *)((stdscr))) ? ((stdscr)->_maxx + 1) : (-1))), rows--;
        plpos = drawplayer(pldir, plpos);
        score += treasures(plpos);
        printstatus(score);
        if(drawenemies(plpos, score) || fobjects(plpos, score)) {
            (wmove((stdscr),((plpos.row)),((plpos.col))) == (-1) ? (-1) : waddch((stdscr),(('X'))));
            wrefresh(stdscr);
            idle("GAME OVER!");
            if (!scores_off) {
                if (is_high_score(score, level, hiscore_file_path)) {
                    name = getname();
                    endwin();
                    scores_off = writescores(hiscore_file_path, name, score, level);
                    if (scores_off) {
                        error(1, 0, "Can't open high score file -- %s", hiscore_file_path);
                    }
                    printscores(hiscore_file_path, level);
                    exit(0);
                }
            }
            break;
        }
    }
    endwin();
    return 0;
}

canonical_original_code:
int main(int argc, char *argv[])
{
    struct pos plpos;
    int pldir;
    int lastdir;
    int score;
    char *name;
    char *default_dir;
    int parseargs_bitmask;
    int scores_off;
    initglobals();
    parseargs_bitmask = parseargs(argc, argv);
    setspeed();
    if (setkeys(key_file_path) == 2) {
        return 1;
    }
    default_dir = expandpath("~/.lwrace", 0);
    scores_off = mk_default_dir(default_dir);
    free(default_dir);
    if (scores_off && (parseargs_bitmask & 2)) {
        scores_off = 0;
    }
    seedgenrand();
    initscr();
    cbreak();
    keypad(stdscr, 1);
    noecho();
    curs_set(0);
    nodelay(stdscr, 1);
    pldir = -1;
    ((rows) = ((0 != (void *)((stdscr))) ? ((stdscr)->_maxy + 1) : (-1)), (cols) = ((0 != (void *)((stdscr))) ? ((stdscr)->_maxx + 1) : (-1))), rows--;
    plpos.row = genrand(0, rows);
    plpos.col = genrand(0, cols);
    score = 0;
    while ((pldir = getdir(pldir)) != -2) {
        if (pldir == 9) {
            idle("Game paused");
            pldir = lastdir;
        }
        lastdir = pldir;
        ((rows) = ((0 != (void *)((stdscr))) ? ((stdscr)->_maxy + 1) : (-1)), (cols) = ((0 != (void *)((stdscr))) ? ((stdscr)->_maxx + 1) : (-1))), rows--;
        plpos = drawplayer(pldir, plpos);
        score += treasures(plpos);
        printstatus(score);
        if(drawenemies(plpos, score) || fobjects(plpos, score)) {
            (wmove((stdscr),((plpos.row)),((plpos.col))) == (-1) ? (-1) : waddch((stdscr),(('X'))));
            wrefresh(stdscr);
            idle("GAME OVER!");
            if (!scores_off) {
                if (is_high_score(score, level, hiscore_file_path)) {
                    name = getname();
                    endwin();
                    scores_off = writescores(hiscore_file_path, name, score, level);
                    if (scores_off) {
                        error(1, 0, "Can't open high score file -- %s", hiscore_file_path);
                    }
                    printscores(hiscore_file_path, level);
                    exit(0);
                }
            }
            break;
        }
    }
    endwin();
    return 0;
}

variable_types:
plpos
struct pos { int row; int col; }

variable_types: pldir int

variable_types: lastdir int

variable_types: score int

variable_types:
name
char *


genrand

decompiled_code:
__int64 __fastcall genrand(int a1, int a2)
{
return (unsigned int)(rand() % (a2 - a1) + a1);
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1, int a2)
{
return (unsigned int)(rand() % (a2 - a1) + a1);
}

original_code:
int genrand(int min, int max) {
    return rand() % (max-min) + min;
}

variable_types: min int

variable_types: max int


seedgenrand

decompiled_code:
void seedgenrand()
{
struct timeval v0; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v0, 0LL);
srand(LODWORD(v0.tv_usec) * LODWORD(v0.tv_sec));
}

canonical_decompiled_code:
void func1()
{
struct timeval v0; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v0, 0LL);
srand(LODWORD(v0.tv_usec) * LODWORD(v0.tv_sec));
}

original_code:
void seedgenrand() {
    long seed;
    struct timeval now;
    gettimeofday(&now, ((void *)0));
    seed = now.tv_sec * now.tv_usec;
    srand(seed);
}

variable_types: seed long

variable_types: struct timeval { long tv_sec; long tv_usec; }


getnow

decompiled_code:
double getnow()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)SLODWORD(v1.tv_usec) / 1000000.0 + (double)SLODWORD(v1.tv_sec);
}

canonical_decompiled_code:
double func2()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)SLODWORD(v1.tv_usec) / 1000000.0 + (double)SLODWORD(v1.tv_sec);
}

original_code:
double getnow() {
    struct timeval now;
    gettimeofday(&now, ((void *)0));
    return now.tv_sec+(now.tv_usec/1000000.0);
}

return_type: double

user_defined_types: struct timeval { long tv_sec; long tv_usec; }


decompiled_code:
__int64 __fastcall mk_default_dir(char *path)
{
char v1; // al
struct stat v3; // [rsp+0h] [rbp-98h] BYREF

if ( stat(path, &v3) == -1 )
{
if ( mkdir(path, 0x1FDu) )
{
error(0, 0, "Error creating %s", path);
goto LABEL_5;
}
return 0LL;
}
if ( (v3.st_mode & 0xF000) == 0x4000 )
return 0LL;
error(0, 0, "%s exists but is not a directory.\n", path);
do
{
LABEL_5:
puts("Can't write high scores to default target\nfile or read default keyfile.\nPlay anyway? [y/n]");
v1 = getchar();
if ( v1 == 110 )
exit(0);
}
while ( v1 != 121 );
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func3(char *path)
{
char v1; // al
struct stat v3; // [rsp+0h] [rbp-98h] BYREF

if ( stat(path, &v3) == -1 )
{
if ( mkdir(path, 0x1FDu) )
{
error(0, 0, "Error creating %s", path);
goto LABEL_5;
}
return 0LL;
}
if ( (v3.st_mode & 0xF000) == 0x4000 )
return 0LL;
error(0, 0, "%s exists but is not a directory.\n", path);
do
{
LABEL_5:
puts("Can't write high scores to default target\nfile or read default keyfile.\nPlay anyway? [y/n]");
v1 = getchar();
if ( v1 == 110 )
exit(0);
}
while ( v1 != 121 );
return 1LL;
}

original_code:
int mk_default_dir(char *path) {
    char *notdirerr = "%s exists but is not a directory.\n";
    char *othererr = "Error creating %s";
    char *play_anyway =
"Can't write high scores to default target\nfile or read default keyfile.\n"
"Play anyway? [y/n]";
    char reply;
    struct stat buf;
    int statret;
    int mkdirret;
    statret = stat(path, &buf);
    if (statret == -1) {
        mkdirret = mkdir(path, (0400|0200|0100) | ((0400|0200|0100) >> 3) | ((0400 >> 3) >> 3) | ((0100 >> 3) >> 3));
        if (mkdirret == 0) {
            return 0;
        }
        error(0, 0, othererr, path);
    } else if (((((buf.st_mode)) & 0170000) == (0040000))) {
        return 0;
    } else {
        error(0, 0, notdirerr, path);
    }
    while (1) {
        puts(play_anyway);
        reply = getchar();
        if (reply == 'n')
            exit(0);
        if (reply == 'y')
            break;
    }
    return 1;
}

variable_types:
path
char *

variable_types:
notdirerr
char *

variable_types:
othererr
char *

variable_types: reply char

variable_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec { long tv_sec; long tv_nsec; } st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }

variable_types: statret int

variable_types: mkdirret int

user_defined_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }


decompiled_code:
char *__fastcall extend_str_space(void *src, int a2)
{
size_t v2; // rax
int v3; // ebp
size_t v4; // rbx
char *v5; // rax
char *v6; // r12

v2 = strlen((const char *)src);
v3 = a2 + v2 + 1;
v4 = v2;
v5 = (char *)malloc(v3);
v6 = v5;
if ( v5 )
{
memcpy(v5, src, v4 + 1);
if ( (int)v4 < v3 - 1 )
memset(&v6[(int)v4], 32, (unsigned int)(v3 - v4 - 2) + 1LL);
v6[v3 - 1] = 0;
}
return v6;
}

canonical_decompiled_code:
char *__fastcall func1(void *src, int a2)
{
size_t v2; // rax
int v3; // ebp
size_t v4; // rbx
char *v5; // rax
char *v6; // r12

v2 = strlen((const char *)src);
v3 = a2 + v2 + 1;
v4 = v2;
v5 = (char *)malloc(v3);
v6 = v5;
if ( v5 )
{
memcpy(v5, src, v4 + 1);
if ( (int)v4 < v3 - 1 )
memset(&v6[(int)v4], 32, (unsigned int)(v3 - v4 - 2) + 1LL);
v6[v3 - 1] = 0;
}
return v6;
}

original_code:
char *extend_str_space(char *string, int extend_by) {
    char *ext;
    int len, i;
    len = strlen(string) + 1;
    ext = malloc((len + extend_by) * sizeof(char));
    if(!ext)
        return ((void *)0);
    ext = strcpy(ext, string);
    for (i = len - 1; i < len + extend_by - 1; i++) {
        ext[i] = ' ';
    }
    ext[len + extend_by - 1] = '\0';
    return ext;
}

canonical_original_code:
char *extend_str_space(char *string, int extend_by) {
    char *ext;
    int len; int i;
    len = strlen(string) + 1;
    ext = malloc((len + extend_by) * sizeof(char));
    if(!ext)
        return ((void *)0);
    ext = strcpy(ext, string);
    for (i = len - 1; i < len + extend_by - 1; i++) {
        ext[i] = ' ';
    }
    ext[len + extend_by - 1] = '\0';
    return ext;
}

variable_types:
string
char *

variable_types:
ext
char *

variable_types: len int

variable_types: i int

return_type: char *


decompiled_code:
const char *__fastcall append_dotnr_to_path(const char *a1, char a2)
{
int v2; // eax

v2 = strlen(a1);
a1[v2 - 2] = 46;
a1[v2 - 1] = a2 + 48;
a1[v2] = 0;
return a1;
}

canonical_decompiled_code:
const char *__fastcall func2(const char *a1, char a2)
{
int v2; // eax

v2 = strlen(a1);
a1[v2 - 2] = 46;
a1[v2 - 1] = a2 + 48;
a1[v2] = 0;
return a1;
}

original_code:
char *append_dotnr_to_path(char *path, int number) {
    int len;
    len = strlen(path);
    path[len - 2] = '.';
    path[len - 1] = '0' + number;
    path[len] = '\0';
    return path;
}

variable_types: number int


decompiled_code:
_BOOL8 __fastcall is_high_score(int a1, char a2, void *a3)
{
char *v3; // rax
const char *v4; // rax
__int64 v5; // rax
__int64 v6; // rdx
int v7; // ecx

v3 = extend_str_space(a3, 2);
v4 = append_dotnr_to_path(v3, a2);
v5 = readscores(v4);
if ( v5 )
{
v6 = v5 + 160;
while ( *(_QWORD *)v5 )
{
v7 = *(_DWORD *)(v5 + 8);
v5 += 16LL;
if ( v5 == v6 )
return a1 > v7;
}
}
return 1LL;
}

canonical_decompiled_code:
_BOOL8 __fastcall func4(int a1, char a2, void *a3)
{
char *v3; // rax
const char *v4; // rax
__int64 v5; // rax
__int64 v6; // rdx
int v7; // ecx

v3 = func1(a3, 2);
v4 = func2(v3, a2);
v5 = func0(v4);
if ( v5 )
{
v6 = v5 + 160;
while ( *(_QWORD *)v5 )
{
v7 = *(_DWORD *)(v5 + 8);
v5 += 16LL;
if ( v5 == v6 )
return a1 > v7;
}
}
return 1LL;
}

original_code:
int is_high_score(int score, int level, char *path) {
    struct hiscore *scores;
    char *extpath;
    int i, lastscore = -1;
    extpath = extend_str_space(path, 2);
    extpath = append_dotnr_to_path(extpath, level);
    scores = readscores(extpath);
    if (!scores) {
        return 1;
    }
    for (i = 0; i < 10; i++) {
        if (!(scores+i)->name) {
            return 1;
        }
        lastscore = (scores+i)->score;
    }
    if (score > lastscore)
        return 1;
    return 0;
}

canonical_original_code:
int is_high_score(int score, int level, char *path) {
    struct hiscore *scores;
    char *extpath;
    int i; int lastscore = -1;
    extpath = extend_str_space(path, 2);
    extpath = append_dotnr_to_path(extpath, level);
    scores = readscores(extpath);
    if (!scores) {
        return 1;
    }
    for (i = 0; i < 10; i++) {
        if (!(scores+i)->name) {
            return 1;
        }
        lastscore = (scores+i)->score;
    }
    if (score > lastscore)
        return 1;
    return 0;
}

variable_types: score int

variable_types: level int

variable_types: struct hiscore { char *name; int score; } *

variable_types:
extpath
char *

variable_types: lastscore int


printscores

decompiled_code:
int __fastcall printscores(void *a1, unsigned int a2)
{
char v2; // r14
unsigned int v3; // er13
int v4; // ebp
const char *v5; // r12
__int64 v6; // rax
__int64 v7; // rbx
unsigned int v8; // er15
const char *v9; // rcx
__int64 v10; // rdx

v2 = 9;
LOBYTE(v3) = 0;
if ( a2 <= 9 )
LOBYTE(v3) = a2;
if ( a2 <= 9 )
v2 = a2;
v4 = 0;
v5 = extend_str_space(a1, 2);
v3 = (char)v3;
do
{
v5 = append_dotnr_to_path(v5, v3);
v6 = readscores(v5);
v7 = v6;
if ( v6 )
{
v8 = 0;
dashes(27);
printf(" High Scores - level %d\n", v3);
LODWORD(v6) = dashes(27);
while ( 1 )
{
v9 = *(const char **)v7;
if ( !*(_QWORD *)v7 )
break;
v10 = *(unsigned int *)(v7 + 8);
++v8;
++v4;
v7 += 16LL;
LODWORD(v6) = printf("%3d: %5d :: %s\n", v8, v10, v9);
if ( v8 == 10 )
goto LABEL_10;
}
if ( !v8 )
{
error(1, 0, "file empty -- %s", v5);
goto LABEL_15;
}
}
LABEL_10:
++v3;
}
while ( v2 >= (char)v3 );
if ( !v4 )
{
LABEL_15:
error(1, 0, "error reading high score file");
JUMPOUT(0x66ELL);
}
return v6;
}

canonical_decompiled_code:
int __fastcall func7(void *a1, unsigned int a2)
{
char v2; // r14
unsigned int v3; // er13
int v4; // ebp
const char *v5; // r12
__int64 v6; // rax
__int64 v7; // rbx
unsigned int v8; // er15
const char *v9; // rcx
__int64 v10; // rdx

v2 = 9;
LOBYTE(v3) = 0;
if ( a2 <= 9 )
LOBYTE(v3) = a2;
if ( a2 <= 9 )
v2 = a2;
v4 = 0;
v5 = func1(a1, 2);
v3 = (char)v3;
do
{
v5 = func2(v5, v3);
v6 = func0(v5);
v7 = v6;
if ( v6 )
{
v8 = 0;
func6(27);
printf(" High Scores - level %d\n", v3);
LODWORD(v6) = func6(27);
while ( 1 )
{
v9 = *(const char **)v7;
if ( !*(_QWORD *)v7 )
break;
v10 = *(unsigned int *)(v7 + 8);
++v8;
++v4;
v7 += 16LL;
LODWORD(v6) = printf("%3d: %5d :: %s\n", v8, v10, v9);
if ( v8 == 10 )
goto LABEL_10;
}
if ( !v8 )
{
error(1, 0, "file empty -- %s", v5);
goto LABEL_15;
}
}
LABEL_10:
++v3;
}
while ( v2 >= (char)v3 );
if ( !v4 )
{
LABEL_15:
error(1, 0, "error reading high score file");
JUMPOUT(0x66ELL);
}
return v6;
}

original_code:
void printscores(char *path, int level) {
    struct hiscore *scores;
    char *extpath = ((void *)0);
    int printed_count = 0;
    char *heading = "  High Scores - level %d\n";
    char *fstr = "%3d: %5d :: %s\n";
    char fromlevel, tolevel;
    int i;
    if (level >= 0 && level <= 9) {
        fromlevel = tolevel = level;
    } else {
        fromlevel = 0;
        tolevel = 9;
    }
    extpath = extend_str_space(path, 2);
    for ( ; fromlevel <= tolevel; fromlevel++) {
        extpath = append_dotnr_to_path(extpath, fromlevel);
        if ( (scores = readscores(extpath)) ) {
            dashes(strlen(heading) + 2);
            printf(heading, fromlevel);
            dashes(strlen(heading) + 2);
        }
        if (!scores)
            continue;
        for (i = 0; i < 10; i++) {
            if ((scores + i)->name) {
                printf(fstr, i + 1, (scores + i)->score,
                        (scores + i)->name);
                printed_count++;
            }
            else {
                if(i == 0)
                    error(1, 0, "file empty -- %s", extpath);
                else
                    break;
            }
        }
    }
    if (printed_count == 0)
        error(1, 0, "error reading high score file");
}

canonical_original_code:
void printscores(char *path, int level) {
    struct hiscore *scores;
    char *extpath = ((void *)0);
    int printed_count = 0;
    char *heading = "  High Scores - level %d\n";
    char *fstr = "%3d: %5d :: %s\n";
    char fromlevel; char tolevel;
    int i;
    if (level >= 0 && level <= 9) {
        fromlevel = tolevel = level;
    } else {
        fromlevel = 0;
        tolevel = 9;
    }
    extpath = extend_str_space(path, 2);
    for ( ; fromlevel <= tolevel; fromlevel++) {
        extpath = append_dotnr_to_path(extpath, fromlevel);
        if ( (scores = readscores(extpath)) ) {
            dashes(strlen(heading) + 2);
            printf(heading, fromlevel);
            dashes(strlen(heading) + 2);
        }
        if (!scores)
            continue;
        for (i = 0; i < 10; i++) {
            if ((scores + i)->name) {
                printf(fstr, i + 1, (scores + i)->score,
                        (scores + i)->name);
                printed_count++;
            }
            else {
                if(i == 0)
                    error(1, 0, "file empty -- %s", extpath);
                else
                    break;
            }
        }
    }
    if (printed_count == 0)
        error(1, 0, "error reading high score file");
}

variable_types:
path
char *

variable_types:
heading
char *

variable_types:
fstr
char *

variable_types: fromlevel char

variable_types: tolevel char

user_defined_types: struct hiscore { char *name; int score; }


getdir

decompiled_code:
__int64 __fastcall getdir(unsigned int a1)
{
int v1; // eax
unsigned int v2; // er8

v1 = wgetch(stdscr);
v2 = 1;
if ( key_up != v1 )
{
if ( key_down == v1 )
{
v2 = 2;
}
else if ( key_left == v1 )
{
v2 = 3;
}
else if ( key_right == v1 )
{
v2 = 4;
}
else
{
v2 = 0;
if ( key_stop != v1 )
{
if ( key_pause == v1 )
{
v2 = 9;
}
else
{
v2 = -2;
if ( key_esc != v1 )
v2 = a1;
}
}
}
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func0(unsigned int a1)
{
int v1; // eax
unsigned int v2; // er8

v1 = wgetch(stdscr);
v2 = 1;
if ( key_up != v1 )
{
if ( key_down == v1 )
{
v2 = 2;
}
else if ( key_left == v1 )
{
v2 = 3;
}
else if ( key_right == v1 )
{
v2 = 4;
}
else
{
v2 = 0;
if ( key_stop != v1 )
{
if ( key_pause == v1 )
{
v2 = 9;
}
else
{
v2 = -2;
if ( key_esc != v1 )
v2 = a1;
}
}
}
}
return v2;
}

original_code:
dir_t getdir(dir_t curdir) {
    extern int key_up, key_down, key_left, key_right;
    extern int key_stop, key_pause, key_esc;
    int key = wgetch(stdscr);
    if (key == key_up)
        return 1;
    if (key == key_down)
        return 2;
    if (key == key_left)
        return 3;
    if (key == key_right)
        return 4;
    if (key == key_stop)
        return 0;
    if (key == key_pause)
        return 9;
    if (key == key_esc)
        return -2;
    return curdir;
}

canonical_original_code:
int getdir(int curdir) {
    extern int key_up; extern int key_down; extern int key_left; extern int key_right;
    extern int key_stop; extern int key_pause; extern int key_esc;
    int key = wgetch(stdscr);
    if (key == key_up)
        return 1;
    if (key == key_down)
        return 2;
    if (key == key_left)
        return 3;
    if (key == key_right)
        return 4;
    if (key == key_stop)
        return 0;
    if (key == key_pause)
        return 9;
    if (key == key_esc)
        return -2;
    return curdir;
}

variable_types: curdir int

variable_types: key int


drawplayer

decompiled_code:
__int64 __fastcall drawplayer(__int64 a1, __int64 a2)
{
int v2; // eax
__int64 result; // rax
__int64 v4; // [rsp+0h] [rbp-30h] BYREF
double v5; // [rsp+8h] [rbp-28h] BYREF
double v6[4]; // [rsp+10h] [rbp-20h] BYREF

v4 = a2;
v5 = player_row_delay / (double)rows;
v6[0] = player_col_delay / (double)cols;
v2 = setpos(a1, &v4, &v5, v6, &lasttime_3);
if ( (_DWORD)a1 != -1 && !v2 )
return v4;
result = drawfigure(v4, 79LL, a2, 32LL, (unsigned int)lastrows_1, (unsigned int)lastcols_2);
lastrows_1 = rows;
lastcols_2 = cols;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, __int64 a2)
{
int v2; // eax
__int64 result; // rax
__int64 v4; // [rsp+0h] [rbp-30h] BYREF
double v5; // [rsp+8h] [rbp-28h] BYREF
double v6[4]; // [rsp+10h] [rbp-20h] BYREF

v4 = a2;
v5 = player_row_delay / (double)rows;
v6[0] = player_col_delay / (double)cols;
v2 = setpos(a1, &v4, &v5, v6, &lasttime_3);
if ( (_DWORD)a1 != -1 && !v2 )
return v4;
result = drawfigure(v4, 79LL, a2, 32LL, (unsigned int)lastrows_1, (unsigned int)lastcols_2);
lastrows_1 = rows;
lastcols_2 = cols;
return result;
}

original_code:
struct pos drawplayer(dir_t dir, struct pos curpos) {
    extern int rows, cols;
    extern double player_row_delay;
    extern double player_col_delay;
    static double lasttime;
    static int lastrows, lastcols;
    struct pos oldpos;
    double rdelay = player_row_delay / rows;
    double cdelay = player_col_delay / cols;
    oldpos = curpos;
    if (setpos(dir, &curpos, &rdelay, &cdelay, &lasttime) || dir == -1) {
        curpos = drawfigure(curpos, 'O', oldpos, ' ',
                            lastrows, lastcols);
        lastrows = rows, lastcols = cols;
    }
    return curpos;
}

canonical_original_code:
struct pos drawplayer(int dir, struct pos curpos) {
    extern int rows; extern int cols;
    extern double player_row_delay;
    extern double player_col_delay;
    static double lasttime;
    static int lastrows; static int lastcols;
    struct pos oldpos;
    double rdelay = player_row_delay / rows;
    double cdelay = player_col_delay / cols;
    oldpos = curpos;
    if (setpos(dir, &curpos, &rdelay, &cdelay, &lasttime) || dir == -1) {
        curpos = drawfigure(curpos, 'O', oldpos, ' ',
                            lastrows, lastcols);
        lastrows = rows, lastcols = cols;
    }
    return curpos;
}

variable_types: dir int

variable_types:
curpos
struct pos

variable_types: rows int

variable_types: cols int

variable_types: lasttime double

variable_types: lastrows int

variable_types: lastcols int

variable_types:
oldpos
struct pos { int row; int col; }

variable_types: rdelay double

variable_types: cdelay double

return_type: struct pos { int row; int col; }