repo: vicnils/tetrominic

decompiled_code:
__int64 __fastcall update_next_tetmino(_DWORD *a1)
{
__int64 result; // rax
int v2; // edx
int v3; // ecx

result = 0LL;
if ( a1[27] )
{
v2 = a1[38];
if ( v2 > 21 )
{
v3 = a1[40] - 1;
a1[40] = v3;
result = 0LL;
if ( v3 <= 0 )
{
a1[38] = v2 - 1;
a1[40] = a1[26];
result = 1LL;
}
}
}
return result;
}

original_code:
static int update_next_tetmino(struct game *game)
{
 struct tetfield *tf = &game->tetfield;
 if (tf->state == TETFIELD_SPAWN) {
  return 0;
 }
 if (game->next_tetmino.row > (24 - 4) + 1) {
  game->next_tetmino.falling--;
  if (game->next_tetmino.falling > 0) {
   return 0;
  }
  game->next_tetmino.row--;
  game->next_tetmino.falling = tf->gravity;
  return 1;
 }
 return 0;
}

variable_types: struct game { struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } tetgrid; struct tetfield { struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } mino; struct tetgrid *grid; int gravity; enum { TETFIELD_SPAWN=0, TETFIELD_MOVE=1, TETFIELD_PLACED=2, TETFIELD_TOP_OUT=3 } state; enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } last_action; unsigned char timeout[-1]; unsigned long score; unsigned int pieces; } tetfield; struct tetmino next_tetmino; struct tetmino_piece { struct piece { struct copyrect { int width; int di; } r; unsigned char piece[-1]; struct piece *prev; } piece; struct tetmino *tetmino; int mask; struct tetmino_piece *succ; } piece; struct blocks { struct bitmap { unsigned char *bitmap; int width; int height; } bitmap; struct tg_tiles { char chars[16]; unsigned short attrs[16]; } tiles; int x; int rendered; } blocks; unsigned char bitmap[-1]; } *

variable_types: struct tetfield { struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } mino; struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } *grid; int gravity; enum { TETFIELD_SPAWN=0, TETFIELD_MOVE=1, TETFIELD_PLACED=2, TETFIELD_TOP_OUT=3 } state; enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } last_action; unsigned char timeout[-1]; unsigned long score; unsigned int pieces; } *

user_defined_types: struct game { struct tetgrid tetgrid; struct tetfield tetfield; struct tetmino next_tetmino; struct tetmino_piece piece; struct blocks blocks; unsigned char bitmap[-1]; }

user_defined_types: struct tetfield { struct tetmino mino; struct tetgrid *grid; int gravity; enum { TETFIELD_SPAWN=0, TETFIELD_MOVE=1, TETFIELD_PLACED=2, TETFIELD_TOP_OUT=3 } state; enum action last_action; unsigned char timeout[-1]; unsigned long score; unsigned int pieces; }

user_defined_types: struct tetmino_piece { struct piece piece; struct tetmino *tetmino; int mask; struct tetmino_piece *succ; }

user_defined_types: struct blocks { struct bitmap bitmap; struct tg_tiles tiles; int x; int rendered; }

user_defined_types: struct piece { struct copyrect r; unsigned char piece[-1]; struct piece *prev; }


decompiled_code:
__int64 __fastcall spawn_piece(_DWORD *a1)
{
unsigned int v1; // er12
unsigned int v2; // ebp
unsigned int v3; // eax

enter_tetfield(a1 + 16, (unsigned int)a1[37], 6LL);
v1 = a1[26];
v2 = a1[18] + 4;
v3 = rand7();
return init_tetmino(a1 + 36, v3, v2, 6LL, v1);
}

canonical_decompiled_code:
__int64 __fastcall func1(_DWORD *a1)
{
unsigned int v1; // er12
unsigned int v2; // ebp
unsigned int v3; // eax

enter_tetfield(a1 + 16, (unsigned int)a1[37], 6LL);
v1 = a1[26];
v2 = a1[18] + 4;
v3 = rand7();
return init_tetmino(a1 + 36, v3, v2, 6LL, v1);
}

original_code:
static struct tetmino *spawn_piece(struct game *game)
{
 enter_tetfield(&game->tetfield, game->next_tetmino.piece, (3 + 3));
 return init_tetmino(&game->next_tetmino,
  rand7(),
  game->tetfield.mino.row + 4,
  (3 + 3),
  game->tetfield.gravity);
}

variable_types: struct game { struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } tetgrid; struct tetfield { struct tetmino mino; struct tetgrid *grid; int gravity; enum { TETFIELD_SPAWN=0, TETFIELD_MOVE=1, TETFIELD_PLACED=2, TETFIELD_TOP_OUT=3 } state; enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } last_action; unsigned char timeout[-1]; unsigned long score; unsigned int pieces; } tetfield; struct tetmino next_tetmino; struct tetmino_piece { struct piece { struct copyrect { int width; int di; } r; unsigned char piece[-1]; struct piece *prev; } piece; struct tetmino *tetmino; int mask; struct tetmino_piece *succ; } piece; struct blocks { struct bitmap { unsigned char *bitmap; int width; int height; } bitmap; struct tg_tiles { char chars[16]; unsigned short attrs[16]; } tiles; int x; int rendered; } blocks; unsigned char bitmap[-1]; } *

return_type: struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } *


variable_types: w int

variable_types: struct blocks { struct bitmap { unsigned char *bitmap; int width; int height; } bitmap; struct tg_tiles { char chars[16]; unsigned short attrs[16]; } tiles; int x; int rendered; }

return_type: void

user_defined_types: struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; }

user_defined_types: struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; }

user_defined_types: enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 }


decompiled_code:
__int64 __fastcall get_action(const char *a1)
{
unsigned int v1; // edx

v1 = 4;
if ( strcmp(a1, "j") )
{
if ( strcmp(a1, "left") )
{
v1 = 1;
if ( strcmp(a1, "k") )
{
if ( strcmp(a1, "up") )
{
v1 = 2;
if ( strcmp(a1, "i") )
{
v1 = 3;
if ( strcmp(a1, "l") )
{
if ( strcmp(a1, "right") )
{
v1 = 6;
if ( strcmp(a1, "m") )
{
if ( strcmp(a1, "down") )
v1 = strcmp(a1, "space") == 0 ? 5 : 0;
}
}
}
}
}
}
}
}
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func3(const char *a1)
{
unsigned int v1; // edx

v1 = 4;
if ( strcmp(a1, "j") )
{
if ( strcmp(a1, "left") )
{
v1 = 1;
if ( strcmp(a1, "k") )
{
if ( strcmp(a1, "up") )
{
v1 = 2;
if ( strcmp(a1, "i") )
{
v1 = 3;
if ( strcmp(a1, "l") )
{
if ( strcmp(a1, "right") )
{
v1 = 6;
if ( strcmp(a1, "m") )
{
if ( strcmp(a1, "down") )
v1 = strcmp(a1, "space") == 0 ? 5 : 0;
}
}
}
}
}
}
}
}
return v1;
}

original_code:
static enum action get_action(const char *input)
{
 if (!strcmp(input, "j") || !strcmp(input, "left")) {
  return MOVE_LEFT;
 }
 if (!strcmp(input, "k") || !strcmp(input, "up")) {
  return ROTATE_CW;
 }
 if (!strcmp(input, "i")) {
  return ROTATE_CCW;
 }
 if (!strcmp(input, "l") || !strcmp(input, "right")) {
  return MOVE_RIGHT;
 }
 if (!strcmp(input, "m") || !strcmp(input, "down")) {
  return SOFTDROP;
 }
 if (!strcmp(input, "space")) {
  return HARDDROP;
 }
 return NO_ACTION;
}

canonical_original_code:
static enum action get_action(char *input)
{
 if (!strcmp(input, "j") || !strcmp(input, "left")) {
  return MOVE_LEFT;
 }
 if (!strcmp(input, "k") || !strcmp(input, "up")) {
  return ROTATE_CW;
 }
 if (!strcmp(input, "i")) {
  return ROTATE_CCW;
 }
 if (!strcmp(input, "l") || !strcmp(input, "right")) {
  return MOVE_RIGHT;
 }
 if (!strcmp(input, "m") || !strcmp(input, "down")) {
  return SOFTDROP;
 }
 if (!strcmp(input, "space")) {
  return HARDDROP;
 }
 return NO_ACTION;
}

variable_types:
input
char *

return_type: enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 }


decompiled_code:
int __fastcall render_score(__int64 a1)
{
int result; // eax

moveto(terminal[8], terminal[9]);
set_text_attr(0LL);
printf("Score: %lu\n", *(_QWORD *)(a1 + 64));
result = printf("Gravity: %d\n", *(unsigned int *)(a1 + 40));
terminal[7] += 2;
return result;
}

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

moveto(terminal[8], terminal[9]);
set_text_attr(0LL);
printf("Score: %lu\n", *(_QWORD *)(a1 + 64));
result = printf("Gravity: %d\n", *(unsigned int *)(a1 + 40));
terminal[7] += 2;
return result;
}

original_code:
static void render_score(const struct tetfield *tf)
{
 moveto(terminal.x0, terminal.y0);
 set_text_attr(0);
 printf("Score: %lu\n", tf->score);
 printf("Gravity: %d\n", tf->gravity);
 terminal.cursor_y++;
 terminal.cursor_y++;
}

canonical_original_code:
static void render_score(struct tetfield *tf)
{
 moveto(terminal.x0, terminal.y0);
 set_text_attr(0);
 printf("Score: %lu\n", tf->score);
 printf("Gravity: %d\n", tf->gravity);
 terminal.cursor_y++;
 terminal.cursor_y++;
}


original_code:
void init_game(struct game *game, int gravity)
{
 struct tetfield tetfield = { { 0 } };
 tetfield.grid = &game->tetgrid;
 tetfield.gravity = gravity;
 init_tetgrid(&game->tetgrid, 10);
 game->tetfield = tetfield;
 game->next_tetmino.piece = rand7();
 init_tetmino_piece(&game->next_piece, spawn_piece(game), 0x7f,
  init_tetmino_piece(&game->piece, &game->tetfield.mino, 0x77, ((void *)0)));
 init_game_blocks(game);
}

variable_types: gravity int

variable_types: struct tetfield { struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } mino; struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } *grid; int gravity; enum { TETFIELD_SPAWN=0, TETFIELD_MOVE=1, TETFIELD_PLACED=2, TETFIELD_TOP_OUT=3 } state; enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } last_action; unsigned char timeout[-1]; unsigned long score; unsigned int pieces; }

user_defined_types: struct bitmap { unsigned char *bitmap; int width; int height; }

user_defined_types: struct tg_tiles { char chars[16]; unsigned short attrs[16]; }


decompiled_code:
__int64 __fastcall update_game(_DWORD *a1, const char *a2)
{
__int64 v2; // r15
_DWORD *v3; // r12
int v4; // er13
int v5; // edx
unsigned int i; // ebx
unsigned __int16 v7; // ax
bool v8; // zf
__int64 result; // rax
unsigned int v10; // eax
int v11; // eax
int v12[16]; // [rsp+8h] [rbp-40h] BYREF

v2 = (__int64)(a1 + 16);
v3 = a1 + 76;
v4 = update_line_clears();
v5 = LOWORD(terminal[0]) >> 1;
a1[92] = v5 - 10;
a1[93] = 1;
if ( terminal[1] == 1 )
{
a1[94] = 0;
draw_acs("x22", 1LL, (unsigned int)(v5 - 11), 1LL, 264LL);
draw_acs("x22", 1LL, (unsigned int)(a1[92] + 20), (unsigned int)a1[93], 264LL);
draw_acs("lq19k", 22LL, (unsigned int)(a1[92] - 1), 0LL, 264LL);
draw_acs("mq19j", 22LL, (unsigned int)(a1[92] - 1), (unsigned int)(a1[93] + 23), 264LL);
render_score(v2);
render_tetmino_blocks(v3, a1 + 60);
}
if ( v4 > 0 )
{
for ( i = v4; (int)i > 0; i = next_cleared_row(a1, i) )
{
v7 = shift_cleared_blocks(a1, i);
render_cleared_blocks(v3, i, v7);
}
render_score(v2);
}
v8 = strcmp(a2, "q") == 0;
result = !v8;
if ( !v8 )
{
v10 = get_action(a2);
result = run_tetfield(v2, v10, v12);
if ( (_DWORD)result )
{
v11 = update_next_tetmino(a1);
if ( v4 > 0 || v11 | v12[1] | v12[0] )
render_tetmino_blocks(v3, a1 + 60);
}
else
{
if ( a1[27] == 3 )
return result;
render_tetmino_piece(v3, a1 + 44, v2, 127LL);
lock_tetfield(v2);
spawn_piece(a1);
render_tetmino_blocks(v3, a1 + 44);
}
flush_output();
result = 1LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func6(_DWORD *a1, const char *a2)
{
__int64 v2; // r15
_DWORD *v3; // r12
int v4; // er13
int v5; // edx
unsigned int i; // ebx
unsigned __int16 v7; // ax
bool v8; // zf
__int64 result; // rax
unsigned int v10; // eax
int v11; // eax
int v12[16]; // [rsp+8h] [rbp-40h] BYREF

v2 = (__int64)(a1 + 16);
v3 = a1 + 76;
v4 = update_line_clears();
v5 = LOWORD(terminal[0]) >> 1;
a1[92] = v5 - 10;
a1[93] = 1;
if ( terminal[1] == 1 )
{
a1[94] = 0;
draw_acs("x22", 1LL, (unsigned int)(v5 - 11), 1LL, 264LL);
draw_acs("x22", 1LL, (unsigned int)(a1[92] + 20), (unsigned int)a1[93], 264LL);
draw_acs("lq19k", 22LL, (unsigned int)(a1[92] - 1), 0LL, 264LL);
draw_acs("mq19j", 22LL, (unsigned int)(a1[92] - 1), (unsigned int)(a1[93] + 23), 264LL);
func4(v2);
render_tetmino_blocks(v3, a1 + 60);
}
if ( v4 > 0 )
{
for ( i = v4; (int)i > 0; i = next_cleared_row(a1, i) )
{
v7 = shift_cleared_blocks(a1, i);
render_cleared_blocks(v3, i, v7);
}
func4(v2);
}
v8 = strcmp(a2, "q") == 0;
result = !v8;
if ( !v8 )
{
v10 = func3(a2);
result = run_tetfield(v2, v10, v12);
if ( (_DWORD)result )
{
v11 = func0(a1);
if ( v4 > 0 || v11 | v12[1] | v12[0] )
render_tetmino_blocks(v3, a1 + 60);
}
else
{
if ( a1[27] == 3 )
return result;
render_tetmino_piece(v3, a1 + 44, v2, 127LL);
lock_tetfield(v2);
func1(a1);
render_tetmino_blocks(v3, a1 + 44);
}
flush_output();
result = 1LL;
}
return result;
}

original_code:
int update_game(struct game *game, const char *input)
{
 struct tetgrid *grid = &game->tetgrid;
 struct tetfield *tf = &game->tetfield;
 struct blocks *b = &game->blocks;
 struct changed changed;
 int cleared = update_line_clears(grid);
 b->x = terminal.width / 2 - 10;
 b->y = 1;
 if (terminal.lines == 1) {
  int attr = ((0) | 8) | 0x100;
  b->rendered = 0;
  draw_acs("x22", 1, b->x - 1, b->y, attr);
  draw_acs("x22", 1, b->x + 10 * 2, b->y, attr);
  draw_acs("lq19k", 22, b->x - 1, 0, attr);
  draw_acs("mq19j", 22, b->x - 1, b->y + (24 - 1), attr);
  render_score(tf);
  render_tetmino_blocks(b, &game->next_piece);
 }
 if (cleared > 0) {
  int row = cleared;
  while (row > 0) {
   blocks_row mask = shift_cleared_blocks(grid, row);
   render_cleared_blocks(&b->bitmap, row, mask);
   row = next_cleared_row(grid, row);
  }
  render_score(tf);
 }
 if (!strcmp(input, "q")) {
  return 0;
 }
 if (!run_tetfield(tf, get_action(input), &changed)) {
  if (tf->state == TETFIELD_TOP_OUT) {
   return 0;
  }
  render_tetmino_piece(&b->bitmap, &game->piece.piece, &tf->mino, 0x7f);
  lock_tetfield(tf);
  spawn_piece(game);
  render_tetmino_blocks(b, &game->piece);
 } else if (update_next_tetmino(game) || cleared > 0 || (changed.moved | changed.dropped)) {
  render_tetmino_blocks(b, &game->next_piece);
 }
 flush_output();
 return 1;
}

canonical_original_code:
int update_game(struct game *game, char *input)
{
 struct tetgrid *grid = &game->tetgrid;
 struct tetfield *tf = &game->tetfield;
 struct blocks *b = &game->blocks;
 struct changed changed;
 int cleared = update_line_clears(grid);
 b->x = terminal.width / 2 - 10;
 b->y = 1;
 if (terminal.lines == 1) {
  int attr = ((0) | 8) | 0x100;
  b->rendered = 0;
  draw_acs("x22", 1, b->x - 1, b->y, attr);
  draw_acs("x22", 1, b->x + 10 * 2, b->y, attr);
  draw_acs("lq19k", 22, b->x - 1, 0, attr);
  draw_acs("mq19j", 22, b->x - 1, b->y + (24 - 1), attr);
  render_score(tf);
  render_tetmino_blocks(b, &game->next_piece);
 }
 if (cleared > 0) {
  int row = cleared;
  while (row > 0) {
   unsigned short mask = shift_cleared_blocks(grid, row);
   render_cleared_blocks(&b->bitmap, row, mask);
   row = next_cleared_row(grid, row);
  }
  render_score(tf);
 }
 if (!strcmp(input, "q")) {
  return 0;
 }
 if (!run_tetfield(tf, get_action(input), &changed)) {
  if (tf->state == TETFIELD_TOP_OUT) {
   return 0;
  }
  render_tetmino_piece(&b->bitmap, &game->piece.piece, &tf->mino, 0x7f);
  lock_tetfield(tf);
  spawn_piece(game);
  render_tetmino_blocks(b, &game->piece);
 } else if (update_next_tetmino(game) || cleared > 0 || (changed.moved | changed.dropped)) {
  render_tetmino_blocks(b, &game->next_piece);
 }
 flush_output();
 return 1;
}

variable_types: struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } *

variable_types: struct blocks { struct bitmap { unsigned char *bitmap; int width; int height; } bitmap; struct tg_tiles { char chars[16]; unsigned short attrs[16]; } tiles; int x; int rendered; } *

variable_types: struct changed { enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } moved; int dropped; }

variable_types: cleared int

variable_types: attr int

variable_types: row int

variable_types:
mask
unsigned short

return_type: int

user_defined_types: struct changed { enum action moved; int dropped; }


original_code:
void flush_tg(struct tg_buffer *line)
{
 int len = line->len;
 int attr = line->attr;
 if (len > 0 && line_is_visible(line)) {
  line->buf[len] = '\0';
  moveto(line->x, line->y);
  if (attr & 0x1000) {
   set_text_attr(attr | 0x2000);
   terminal.putacs(line->buf);
  } else {
   set_text_attr(attr | 0x1000);
   terminal.puttext(line->buf);
  }
  line->x = (terminal.cursor_x += len);
 }
 line->len = 0;
}

variable_types: struct tg_buffer { int x; int len; int attr; char buf[32]; } *

variable_types: len int


drawchar

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

if ( a3[3] != a2 || (unsigned int)a3[2] > 0x1E )
{
flush_tg(a3);
a3[3] = a2;
}
LODWORD(result) = a3[2];
a3[2] = result + 1;
result = (int)result;
*((_BYTE *)a3 + (int)result + 16) = a1;
return result;
}

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

if ( a3[3] != a2 || (unsigned int)a3[2] > 0x1E )
{
func2(a3);
a3[3] = a2;
}
LODWORD(result) = a3[2];
a3[2] = result + 1;
result = (int)result;
*((_BYTE *)a3 + (int)result + 16) = a1;
return result;
}

original_code:
void drawchar(int c, int attr, struct tg_buffer *line)
{
 if (attr != line->attr || line->len >= sizeof(line->buf)-1) {
  flush_tg(line);
  line->attr = attr;
 }
 line->buf[line->len++] = c;
}

variable_types: c int

user_defined_types: struct tg_buffer { int x; int len; int attr; char buf[32]; }


original_code:
static void draw_tile(int nibbles, Tiles tiles, struct tg_buffer *line)
{
 int n1 = (nibbles & 0xF0) >> 4,
     n2 = (nibbles & 0x0F);
 drawchar(tiles->chars[n1], tiles->attrs[n1], line);
 drawchar(tiles->chars[n2], tiles->attrs[n2], line);
}

canonical_original_code:
static void draw_tile(int nibbles, struct tg_tiles *tiles, struct tg_buffer *line)
{
 int n1 = (nibbles & 0xF0) >> 4; int n2 = (nibbles & 0x0F);
 drawchar(tiles->chars[n1], tiles->attrs[n1], line);
 drawchar(tiles->chars[n2], tiles->attrs[n2], line);
}

variable_types: nibbles int

variable_types: struct tg_tiles { char chars[16]; unsigned short attrs[16]; } *


drawacs

original_code:
void drawacs(const char *s, int w, struct tg_buffer *line, int x0)
{
 while (*s && *s != ')' && w > 0) {
  int c = *s++;
  int repeat = 0;
  if (*s > '0' && *s <= '9') {
   do {
    repeat = *s - '0' + 10*repeat;
    s++;
   } while (*s >= '0' && *s <= '9');
  }
  if (c == '(') {
   for (; repeat >= 0; repeat--)
    drawacs(s, w, line, x0);
   s = match_paren(s);
  }
  for (; repeat >= 0; repeat--) {
   if (line->x + line->len >= x0 + w) {
    flush_tg(line);
    line->y++;
    line->x = x0;
   }
   drawchar(c, 0x1000 | line->attr, line);
  }
 }
}

canonical_original_code:
void drawacs(char *s, int w, struct tg_buffer *line, int x0)
{
 while (*s && *s != ')' && w > 0) {
  int c = *s++;
  int repeat = 0;
  if (*s > '0' && *s <= '9') {
   do {
    repeat = *s - '0' + 10*repeat;
    s++;
   } while (*s >= '0' && *s <= '9');
  }
  if (c == '(') {
   for (; repeat >= 0; repeat--)
    drawacs(s, w, line, x0);
   s = match_paren(s);
  }
  for (; repeat >= 0; repeat--) {
   if (line->x + line->len >= x0 + w) {
    flush_tg(line);
    line->y++;
    line->x = x0;
   }
   drawchar(c, 0x1000 | line->attr, line);
  }
 }
}

variable_types:
s
char *

variable_types: w int

variable_types: repeat int


decompiled_code:
void __fastcall draw_acs(char *a1, int a2, unsigned int a3, int a4, int a5)
{
int v5[14]; // [rsp+0h] [rbp-38h] BYREF

v5[0] = a3;
v5[1] = a4;
v5[2] = 0;
v5[3] = a5;
drawacs(a1, a2, v5, a3);
flush_tg(v5);
}

canonical_decompiled_code:
void __fastcall func6(char *a1, int a2, unsigned int a3, int a4, int a5)
{
int v5[14]; // [rsp+0h] [rbp-38h] BYREF

v5[0] = a3;
v5[1] = a4;
v5[2] = 0;
v5[3] = a5;
func5(a1, a2, v5, a3);
func2(v5);
}

original_code:
void draw_acs(const char *s, int w, int x, int y, int attr)
{
 struct tg_buffer line;
 line.x = x;
 line.y = y;
 line.len = 0;
 line.attr = attr;
 drawacs(s, w, &line, x);
 flush_tg(&line);
}

canonical_original_code:
void draw_acs(char *s, int w, int x, int y, int attr)
{
 struct tg_buffer line;
 line.x = x;
 line.y = y;
 line.len = 0;
 line.attr = attr;
 drawacs(s, w, &line, x);
 flush_tg(&line);
}

variable_types: x int

variable_types: y int

variable_types: struct tg_buffer { int x; int len; int attr; char buf[32]; }


drawtiles

original_code:
void drawtiles(unsigned char *front, const unsigned char *back,
        int w, int h, int x, int y, Tiles tiles)
{
 struct tg_buffer line;
 line.y = y;
 line.len = 0;
 line.attr = 0;
 for (; h > 0; h--) {
  const unsigned char *nextRow = back + w;
  line.x = x;
  while (back < nextRow) {
   if (front) {
    if (*front == *back) {
     flush_tg(&line);
     do {
      line.x += 2;
      front++; back++;
     } while (back < nextRow &&
       *front == *back);
     continue;
    }
    *front = *back;
    front++;
   }
   draw_tile(*back, tiles, &line);
   back++;
  }
  flush_tg(&line);
  line.y++;
 }
}

canonical_original_code:
void drawtiles(unsigned char *front, unsigned char *back, int w, int h, int x, int y, struct tg_tiles *tiles)
{
 struct tg_buffer line;
 line.y = y;
 line.len = 0;
 line.attr = 0;
 for (; h > 0; h--) {
  unsigned char *nextRow = back + w;
  line.x = x;
  while (back < nextRow) {
   if (front) {
    if (*front == *back) {
     flush_tg(&line);
     do {
      line.x += 2;
      front++; back++;
     } while (back < nextRow &&
       *front == *back);
     continue;
    }
    *front = *back;
    front++;
   }
   draw_tile(*back, tiles, &line);
   back++;
  }
  flush_tg(&line);
  line.y++;
 }
}

variable_types:
front
unsigned char *

variable_types:
back
unsigned char *

variable_types: h int

variable_types:
nextRow
unsigned char *


cleartoeol

decompiled_code:
size_t cleartoeol()
{
return fwrite(&unk_494, 1uLL, 3uLL, stdout);
}

canonical_decompiled_code:
size_t func0()
{
return fwrite(&unk_494, 1uLL, 3uLL, stdout);
}

original_code:
void cleartoeol()
{
 fputs("\033" "[" "K", stdout);
}


variable_types: attr int

variable_types:
sgr
char [20]

variable_types:
p
char *

variable_types: toggle int


nlto

decompiled_code:
__int64 __fastcall nlto(unsigned int a1)
{
int v1; // ebx
__int64 result; // rax

v1 = a1 - terminal[7];
if ( v1 > 0 )
{
set_text_attr(0);
do
{
putchar(10);
--v1;
}
while ( v1 );
result = terminal[8];
terminal[6] = result;
terminal[7] = a1;
}
return result;
}

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

v1 = a1 - terminal[7];
if ( v1 > 0 )
{
func1(0);
do
{
putchar(10);
--v1;
}
while ( v1 );
result = terminal[8];
terminal[6] = result;
terminal[7] = a1;
}
return result;
}

original_code:
static void nlto(int y)
{
 int dy = y - terminal.cursor_y;
 if (dy > 0) {
  set_text_attr(0);
  for (; dy > 0; dy--)
   putchar('\n');
  terminal.cursor_x = terminal.x0;
  terminal.cursor_y = y;
 }
}

variable_types: dy int


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

result = a1 - terminal[9];
if ( (int)terminal[1] <= (int)result )
{
terminal[1] = result + 1;
result = nlto(a1);
}
return result;
}

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

result = a1 - terminal[9];
if ( (int)terminal[1] <= (int)result )
{
terminal[1] = result + 1;
result = func2(a1);
}
return result;
}

original_code:
static void grow_lines(int y)
{
 int y0 = terminal.y0;
 int top = y - y0;
 if (top >= terminal.lines) {
  terminal.lines = top+1;
  nlto(y);
 }
}

variable_types: top int


moveto

decompiled_code:
int __fastcall moveto(unsigned int a1, signed int a2)
{
unsigned int v2; // ebx
signed int v3; // eax
signed int v4; // edx
signed int v5; // eax
unsigned int v6; // er13
int v7; // er12
unsigned int v8; // esi
int result; // eax

v2 = a2;
v3 = terminal[1];
v4 = HIWORD(terminal[0]);
if ( v3 > v4 )
{
terminal[9] += v3 - v4;
terminal[1] = v4;
}
v5 = terminal[7];
if ( (int)terminal[9] > v5 )
terminal[9] = v5;
if ( v5 < a2 )
grow_lines(a2);
if ( (int)terminal[9] >= a2 )
v2 = terminal[9];
v6 = terminal[6];
v7 = a1 - v6;
v8 = terminal[7];
terminal[6] = a1;
terminal[7] = v2;
result = v2 - v8;
if ( v2 != v8 )
{
if ( result < 0 )
result = printf("\x1B[%dA", v8 - v2);
else
result = printf("\x1B[%dB", (unsigned int)result);
}
if ( v7 )
{
if ( v7 <= 0 )
result = printf("\x1B[%dD", v6 - a1);
else
result = printf("\x1B[%dC", (unsigned int)v7);
}
return result;
}

canonical_decompiled_code:
int __fastcall func4(unsigned int a1, signed int a2)
{
unsigned int v2; // ebx
signed int v3; // eax
signed int v4; // edx
signed int v5; // eax
unsigned int v6; // er13
int v7; // er12
unsigned int v8; // esi
int result; // eax

v2 = a2;
v3 = terminal[1];
v4 = HIWORD(terminal[0]);
if ( v3 > v4 )
{
terminal[9] += v3 - v4;
terminal[1] = v4;
}
v5 = terminal[7];
if ( (int)terminal[9] > v5 )
terminal[9] = v5;
if ( v5 < a2 )
func3(a2);
if ( (int)terminal[9] >= a2 )
v2 = terminal[9];
v6 = terminal[6];
v7 = a1 - v6;
v8 = terminal[7];
terminal[6] = a1;
terminal[7] = v2;
result = v2 - v8;
if ( v2 != v8 )
{
if ( result < 0 )
result = printf("\x1B[%dA", v8 - v2);
else
result = printf("\x1B[%dB", (unsigned int)result);
}
if ( v7 )
{
if ( v7 <= 0 )
result = printf("\x1B[%dD", v6 - a1);
else
result = printf("\x1B[%dC", (unsigned int)v7);
}
return result;
}

original_code:
void moveto(int x, int y)
{
 int dx, dy;
 if (terminal.lines > terminal.height) {
  terminal.y0 += terminal.lines - terminal.height;
  terminal.lines = terminal.height;
 }
 if (terminal.y0 > terminal.cursor_y) {
  terminal.y0 = terminal.cursor_y;
 }
 if (y > terminal.cursor_y) {
  grow_lines(y);
 }
 if (y < terminal.y0) y = terminal.y0;
 dx = x - terminal.cursor_x;
 dy = y - terminal.cursor_y;
 terminal.cursor_x = x;
 terminal.cursor_y = y;
 if (dy) {
  if (dy < 0)
   printf("\033" "[" "%dA", -dy);
  else
   printf("\033" "[" "%dB", dy);
 }
 if (dx) {
  if (dx > 0)
   printf("\033" "[" "%dC", dx);
  else
   printf("\033" "[" "%dD", -dx);
 }
}

canonical_original_code:
void moveto(int x, int y)
{
 int dx; int dy;
 if (terminal.lines > terminal.height) {
  terminal.y0 += terminal.lines - terminal.height;
  terminal.lines = terminal.height;
 }
 if (terminal.y0 > terminal.cursor_y) {
  terminal.y0 = terminal.cursor_y;
 }
 if (y > terminal.cursor_y) {
  grow_lines(y);
 }
 if (y < terminal.y0) y = terminal.y0;
 dx = x - terminal.cursor_x;
 dy = y - terminal.cursor_y;
 terminal.cursor_x = x;
 terminal.cursor_y = y;
 if (dy) {
  if (dy < 0)
   printf("\033" "[" "%dA", -dy);
  else
   printf("\033" "[" "%dB", dy);
 }
 if (dx) {
  if (dx > 0)
   printf("\033" "[" "%dC", dx);
  else
   printf("\033" "[" "%dD", -dx);
 }
}

variable_types: dx int


clearscreen

decompiled_code:
__int64 clearscreen()
{
int v0; // edx
unsigned int v1; // eax
__int64 result; // rax

v0 = terminal[9];
if ( v0 > 0 )
{
v1 = saved_lines_0;
if ( (int)terminal[1] >= saved_lines_0 )
v1 = terminal[1];
terminal[1] = v0 + v1;
terminal[9] = 0;
}
moveto(terminal[8], terminal[9]);
fwrite("\x1B[J", 1uLL, 3uLL, stdout);
result = terminal[1];
saved_lines_0 = terminal[1];
terminal[1] = 1;
return result;
}

canonical_decompiled_code:
__int64 func5()
{
int v0; // edx
unsigned int v1; // eax
__int64 result; // rax

v0 = terminal[9];
if ( v0 > 0 )
{
v1 = saved_lines_0;
if ( (int)terminal[1] >= saved_lines_0 )
v1 = terminal[1];
terminal[1] = v0 + v1;
terminal[9] = 0;
}
func4(terminal[8], terminal[9]);
fwrite("\x1B[J", 1uLL, 3uLL, stdout);
result = terminal[1];
saved_lines_0 = terminal[1];
terminal[1] = 1;
return result;
}

original_code:
void clearscreen()
{
 static int saved_lines;
 if (terminal.y0 > 0) {
  terminal.lines = terminal.y0 + (
   saved_lines > terminal.lines ? saved_lines : terminal.lines
  );
  terminal.y0 = 0;
 }
 moveto(terminal.x0, terminal.y0);
 fputs("\033" "[" "J", stdout);
 saved_lines = terminal.lines;
 terminal.lines = 1;
}


decompiled_code:
int flush_output()
{
if ( (int)terminal[6] > (int)terminal[8] )
{
if ( (int)(terminal[7] + 1) >= (int)(terminal[9] + terminal[1]) )
{
fwrite("\x1B[A", 1uLL, 3uLL, stdout);
--terminal[7];
}
nlto(terminal[7] + 1);
}
return fflush(stdout);
}

canonical_decompiled_code:
int func6()
{
if ( (int)terminal[6] > (int)terminal[8] )
{
if ( (int)(terminal[7] + 1) >= (int)(terminal[9] + terminal[1]) )
{
fwrite("\x1B[A", 1uLL, 3uLL, stdout);
--terminal[7];
}
func2(terminal[7] + 1);
}
return fflush(stdout);
}

original_code:
void flush_output()
{
 if (terminal.cursor_x > terminal.x0) {
  if (terminal.cursor_y + 1 >= terminal.y0 + terminal.lines) {
   fputs("\033" "[" "A", stdout);
   terminal.cursor_y--;
  }
  nlto(terminal.cursor_y + 1);
 }
 fflush(stdout);
}


decompiled_code:
size_t hide_cursor()
{
return fwrite("\x1B[?25l", 1uLL, 6uLL, stdout);
}

canonical_decompiled_code:
size_t func7()
{
return fwrite("\x1B[?25l", 1uLL, 6uLL, stdout);
}

original_code:
void hide_cursor()
{
 fputs("\033" "[" "?25l", stdout);
}


decompiled_code:
size_t show_cursor()
{
return fwrite("\x1B[?25h", 1uLL, 6uLL, stdout);
}

canonical_decompiled_code:
size_t func8()
{
return fwrite("\x1B[?25h", 1uLL, 6uLL, stdout);
}

original_code:
void show_cursor()
{
 fputs("\033" "[" "?25h", stdout);
}


decompiled_code:
int __fastcall puttext_ibm(char *s)
{
if ( (ansi_attr & 0x1000) == 0 )
{
fwrite("\x1B[11m", 1uLL, 5uLL, stdout);
ansi_attr |= 0x1000u;
}
return fputs(s, stdout);
}

canonical_decompiled_code:
int __fastcall func9(char *s)
{
if ( (ansi_attr & 0x1000) == 0 )
{
fwrite("\x1B[11m", 1uLL, 5uLL, stdout);
ansi_attr |= 0x1000u;
}
return fputs(s, stdout);
}

original_code:
void puttext_ibm(const char *s)
{
 if (!(ansi_attr & 0x1000)) {
  fputs("\033" "[" "11m", stdout);
  ansi_attr |= 0x1000;
 }
 fputs(s, stdout);
}

canonical_original_code:
void puttext_ibm(char *s)
{
 if (!(ansi_attr & 0x1000)) {
  fputs("\033" "[" "11m", stdout);
  ansi_attr |= 0x1000;
 }
 fputs(s, stdout);
}

variable_types:
s
char *


decompiled_code:
int __fastcall putacs_vt100(char *s)
{
int v1; // edx

v1 = ansi_attr;
BYTE1(v1) = BYTE1(ansi_attr) | 0x30;
if ( ansi_attr != v1 )
{
puttext_ibm("\x1B(0");
ansi_attr |= 0x3000u;
}
return fputs(s, stdout);
}

canonical_decompiled_code:
int __fastcall func10(char *s)
{
int v1; // edx

v1 = ansi_attr;
BYTE1(v1) = BYTE1(ansi_attr) | 0x30;
if ( ansi_attr != v1 )
{
func9("\x1B(0");
ansi_attr |= 0x3000u;
}
return fputs(s, stdout);
}

original_code:
void putacs_vt100(const char *s)
{
 if ((ansi_attr | 0x1000 | 0x2000) != ansi_attr) {
  puttext_ibm("\033" "(0");
  ansi_attr |= 0x1000 | 0x2000;
 }
 fputs(s, stdout);
}

canonical_original_code:
void putacs_vt100(char *s)
{
 if ((ansi_attr | 0x1000 | 0x2000) != ansi_attr) {
  puttext_ibm("\033" "(0");
  ansi_attr |= 0x1000 | 0x2000;
 }
 fputs(s, stdout);
}


decompiled_code:
_BOOL8 set_input_mode()
{
_BOOL4 v0; // edx
struct termios v2; // [rsp+0h] [rbp-48h] BYREF

*(__m128i *)&v2.c_iflag = _mm_load_si128((const __m128i *)&saved_term_attr);
*(__m128i *)&v2.c_line = _mm_load_si128((const __m128i *)&saved_term_attr.c_line);
*(__m128i *)&v2.c_cc[15] = _mm_load_si128((const __m128i *)&saved_term_attr.c_cc[15]);
*(_QWORD *)&v2.c_cc[31] = *(_QWORD *)&saved_term_attr.c_cc[31];
v2.c_ospeed = saved_term_attr.c_ospeed;
v0 = 0;
if ( v2.c_lflag )
{
v2.c_lflag &= 0xFFFFFFF5;
*(_WORD *)&v2.c_cc[5] = 2;
v0 = tcsetattr(0, 0, &v2) == 0;
}
return v0;
}

canonical_decompiled_code:
_BOOL8 func0()
{
_BOOL4 v0; // edx
struct termios v2; // [rsp+0h] [rbp-48h] BYREF

*(__m128i *)&v2.c_iflag = _mm_load_si128((const __m128i *)&saved_term_attr);
*(__m128i *)&v2.c_line = _mm_load_si128((const __m128i *)&saved_term_attr.c_line);
*(__m128i *)&v2.c_cc[15] = _mm_load_si128((const __m128i *)&saved_term_attr.c_cc[15]);
*(_QWORD *)&v2.c_cc[31] = *(_QWORD *)&saved_term_attr.c_cc[31];
v2.c_ospeed = saved_term_attr.c_ospeed;
v0 = 0;
if ( v2.c_lflag )
{
v2.c_lflag &= 0xFFFFFFF5;
*(_WORD *)&v2.c_cc[5] = 2;
v0 = tcsetattr(0, 0, &v2) == 0;
}
return v0;
}

original_code:
static int set_input_mode()
{
 struct termios attr = saved_term_attr;
 if (attr.c_lflag == 0) {
  return 0;
 }
 attr.c_lflag &= ~(0000002|0000010);
 attr.c_cc[6] = 0;
 attr.c_cc[5] = 2;
 return tcsetattr(0, 0, &attr) == 0;
}

variable_types: struct termios { unsigned int c_iflag; unsigned int c_oflag; unsigned int c_cflag; unsigned int c_lflag; unsigned char c_line; unsigned char c_cc[32]; unsigned int c_ispeed; unsigned int c_ospeed; }


decompiled_code:
_BOOL8 restore_input_mode()
{
_BOOL8 result; // rax

result = 0LL;
if ( saved_term_attr.c_lflag )
result = tcsetattr(0, 0, &saved_term_attr) == 0;
return result;
}

canonical_decompiled_code:
_BOOL8 func1()
{
_BOOL8 result; // rax

result = 0LL;
if ( saved_term_attr.c_lflag )
result = tcsetattr(0, 0, &saved_term_attr) == 0;
return result;
}

original_code:
static int restore_input_mode()
{
 if (saved_term_attr.c_lflag == 0) {
  return 0;
 }
 return tcsetattr(0, 0, &saved_term_attr) == 0;
}


decompiled_code:
int __fastcall get_terminal_size(int a1)
{
int result; // eax
__int16 v2[8]; // [rsp+8h] [rbp-10h] BYREF

result = ioctl(a1, 0x5413uLL, v2);
if ( !result )
{
terminal[0] = v2[1];
result = (unsigned __int16)v2[0];
terminal[1] = v2[0];
}
return result;
}

canonical_decompiled_code:
int __fastcall func2(int a1)
{
int result; // eax
__int16 v2[8]; // [rsp+8h] [rbp-10h] BYREF

result = ioctl(a1, 0x5413uLL, v2);
if ( !result )
{
terminal[0] = v2[1];
result = (unsigned __int16)v2[0];
terminal[1] = v2[0];
}
return result;
}

original_code:
static void get_terminal_size(int fd)
{
 struct winsize win;
 if (!ioctl(fd, 0x5413, &win)) {
  terminal.width = win.ws_col;
  terminal.height = win.ws_row;
 }
}

variable_types: fd int

variable_types: struct winsize { unsigned short ws_row; unsigned short ws_col; unsigned short ws_xpixel; unsigned short ws_ypixel; }


decompiled_code:
__int64 setup_terminal()
{
int v0; // edi

v0 = 1;
if ( set_input_mode() )
{
hide_cursor(1LL);
v0 = 0;
}
get_terminal_size(v0);
set_text_attr(0LL);
return clearscreen();
}

canonical_decompiled_code:
__int64 func3()
{
int v0; // edi

v0 = 1;
if ( func0() )
{
hide_cursor(1LL);
v0 = 0;
}
func2(v0);
set_text_attr(0LL);
return clearscreen();
}

original_code:
void setup_terminal()
{
 int fd = 1;
 if (set_input_mode()) {
  hide_cursor();
  fd = 0;
 }
 get_terminal_size(fd);
 set_text_attr(0);
 clearscreen();
}


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

result = isatty(1);
if ( result )
{
tcgetattr(0, &saved_term_attr);
setup_terminal();
result = 1;
}
return result;
}

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

result = isatty(1);
if ( result )
{
tcgetattr(0, &saved_term_attr);
func3();
result = 1;
}
return result;
}

original_code:
int init_terminal()
{
 if (!isatty(1)) {
  return 0;
 }
 tcgetattr(0, &saved_term_attr);
 setup_terminal();
 return 1;
}


decompiled_code:
__int64 restore_terminal()
{
int v0; // esi

set_text_attr(0LL);
v0 = *(_DWORD *)&terminal[2];
if ( v0 != 1 || *(_DWORD *)&terminal[16] != *(_DWORD *)&terminal[12] )
moveto(*(unsigned int *)&terminal[16], (unsigned int)(*(_DWORD *)&terminal[18] + v0));
*(_DWORD *)&terminal[14] = 0;
*(_DWORD *)&terminal[18] = 0;
clearscreen();
if ( restore_input_mode() )
show_cursor();
return flush_output();
}

canonical_decompiled_code:
__int64 func5()
{
int v0; // esi

set_text_attr(0LL);
v0 = *(_DWORD *)&terminal[2];
if ( v0 != 1 || *(_DWORD *)&terminal[16] != *(_DWORD *)&terminal[12] )
moveto(*(unsigned int *)&terminal[16], (unsigned int)(*(_DWORD *)&terminal[18] + v0));
*(_DWORD *)&terminal[14] = 0;
*(_DWORD *)&terminal[18] = 0;
clearscreen();
if ( func1() )
show_cursor();
return flush_output();
}

original_code:
void restore_terminal()
{
 set_text_attr(0);
 if (terminal.lines != 1 || terminal.x0 != terminal.cursor_x) {
  moveto(terminal.x0, terminal.y0 + terminal.lines);
 }
 terminal.cursor_y = 0;
 terminal.y0 = 0;
 clearscreen();
 if (restore_input_mode()) {
  show_cursor();
 }
 flush_output();
}


decompiled_code:
void __fastcall print_error(char *s)
{
int *v1; // rbx
int v2; // er12

v1 = _errno_location();
v2 = *v1;
set_text_attr(0LL);
clearscreen();
flush_output();
*v1 = v2;
perror(s);
}

canonical_decompiled_code:
void __fastcall func6(char *s)
{
int *v1; // rbx
int v2; // er12

v1 = _errno_location();
v2 = *v1;
set_text_attr(0LL);
clearscreen();
flush_output();
*v1 = v2;
perror(s);
}

original_code:
void print_error(const char *s)
{
 int saved_errno = (*__errno_location ());
 set_text_attr(0);
 clearscreen();
 flush_output();
 (*__errno_location ()) = saved_errno;
 perror(s);
}

canonical_original_code:
void print_error(char *s)
{
 int saved_errno = (*__errno_location ());
 set_text_attr(0);
 clearscreen();
 flush_output();
 (*__errno_location ()) = saved_errno;
 perror(s);
}


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

result = *(unsigned int *)(a1 + 48);
if ( (_DWORD)result == 5 )
{
*(_DWORD *)(a1 + 48) = 0;
*(_BYTE *)(a1 + 52) = 0;
*(_BYTE *)(a1 + 57) += 22;
}
else if ( (_DWORD)result )
{
*(_DWORD *)(a1 + 48) = 0;
*(_BYTE *)(a1 + 52) += 22;
}
return result;
}

original_code:
static void stop_retrying_action(struct tetfield *tf)
{
 if (tf->last_action == HARDDROP) {
  tf->last_action = NO_ACTION;
  tf->timeout[NO_ACTION] = 0;
  tf->timeout[HARDDROP] += 25 - 3;
 }
 if (tf->last_action != NO_ACTION) {
  tf->last_action = NO_ACTION;
  tf->timeout[NO_ACTION] += 25 - 3;
 }
}

variable_types: struct tetfield { struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } mino; struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } *grid; int gravity; enum { TETFIELD_SPAWN=0, TETFIELD_MOVE=1, TETFIELD_PLACED=2, TETFIELD_TOP_OUT=3 } state; enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } last_action; unsigned char timeout[-1]; unsigned long score; unsigned int pieces; } *


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

if ( !*(_BYTE *)(a1 + 52) )
{
if ( a2 <= 2 )
{
if ( a2 )
*(_DWORD *)(a1 + 48) = a2;
}
else
{
result = a2 - 3;
if ( (unsigned int)result <= 3 )
{
result = a2;
if ( !*(_BYTE *)(a1 + a2 + 52) )
{
*(_DWORD *)(a1 + 16) = 1;
*(_BYTE *)(a1 + a2 + 52) = 1;
}
}
}
}
return result;
}

original_code:
static void update_prespawn(struct tetfield *tf, enum action a)
{
 if (!tf->timeout[NO_ACTION]) {
  switch (a) {
  case ROTATE_CW:
  case ROTATE_CCW:
   tf->last_action = a;
   break;
  case MOVE_RIGHT:
  case MOVE_LEFT:
  case HARDDROP:
  case SOFTDROP:
   if (!tf->timeout[a]) {
    tf->mino.falling = 1;
    tf->timeout[a] = 1;
   }
   break;
  default:
   break;
  }
 }
}

variable_types: enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 }


decompiled_code:
__int64 __fastcall is_movable(_DWORD *a1)
{
__int64 result; // rax

result = 1LL;
if ( !a1[4] )
{
result = (unsigned int)a1[5];
if ( (_DWORD)result )
result = a1[6] != 0;
}
return result;
}

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

result = 1LL;
if ( !a1[4] )
{
result = (unsigned int)a1[5];
if ( (_DWORD)result )
result = a1[6] != 0;
}
return result;
}

original_code:
static int is_movable(const struct tetmino *t)
{
 return t->falling || (t->lock_delay_move && t->lock_delay_step);
}

canonical_original_code:
static int is_movable(struct tetmino *t)
{
 return t->falling || (t->lock_delay_move && t->lock_delay_step);
}

variable_types: struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } *


levelup

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

result = *(unsigned int *)(a1 + 40);
if ( (int)result > 1 )
{
result = (unsigned int)(int)((double)(int)result * 0.9);
*(_DWORD *)(a1 + 40) = result;
*(_DWORD *)(a1 + 72) = 0;
}
return result;
}

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

result = *(unsigned int *)(a1 + 40);
if ( (int)result > 1 )
{
result = (unsigned int)(int)((double)(int)result * 0.9);
*(_DWORD *)(a1 + 40) = result;
*(_DWORD *)(a1 + 72) = 0;
}
return result;
}

original_code:
static void levelup(struct tetfield *tf)
{
 if (tf->gravity > 1) {
  tf->gravity *= 0.9;
  tf->pieces = 0;
 }
}


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

result = 0LL;
if ( !*(_BYTE *)(a1 + a2 + 52) )
{
v3 = control_tetmino(a1, *(_QWORD *)(a1 + 32) + 12LL, a2);
result = 0LL;
if ( v3 )
{
v4 = *(_DWORD *)(a1 + 48);
if ( !v4 || !*(_BYTE *)(a1 + v4 + 52) )
*(_DWORD *)(a1 + 48) = a2;
*(_BYTE *)(a1 + 52) = 3;
*(_BYTE *)(a1 + a2 + 52) = 3;
result = a2;
}
}
return result;
}

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

result = 0LL;
if ( !*(_BYTE *)(a1 + a2 + 52) )
{
v3 = control_tetmino(a1, *(_QWORD *)(a1 + 32) + 12LL, a2);
result = 0LL;
if ( v3 )
{
v4 = *(_DWORD *)(a1 + 48);
if ( !v4 || !*(_BYTE *)(a1 + v4 + 52) )
*(_DWORD *)(a1 + 48) = a2;
*(_BYTE *)(a1 + 52) = 3;
*(_BYTE *)(a1 + a2 + 52) = 3;
result = a2;
}
}
return result;
}

original_code:
static enum action make_move(struct tetfield *tf, enum action a)
{
 if (tf->timeout[a] == 0 && control_tetmino(&tf->mino, tf->grid->blocks, a)) {
  if (tf->last_action == NO_ACTION || tf->timeout[tf->last_action] == 0) {
   tf->last_action = a;
  }
  tf->timeout[NO_ACTION] = 3;
  tf->timeout[a] = 3;
  return a;
 }
 return NO_ACTION;
}


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

if ( *(_BYTE *)(a1 + a2 + 52) )
{
result = 0LL;
if ( *(_BYTE *)(a1 + 52) )
result = make_move(a1, *(_DWORD *)(a1 + 48));
if ( a2 )
{
*(_DWORD *)(a1 + 48) = a2;
*(_BYTE *)(a1 + 52) = 3;
}
}
else
{
result = make_move(a1, a2);
if ( a2 && !(_DWORD)result )
{
*(_DWORD *)(a1 + 48) = a2;
*(_BYTE *)(a1 + 52) = 4;
}
}
return result;
}

original_code:
static enum action update_move(struct tetfield *tf, enum action a)
{
 enum action moved = NO_ACTION;
 if (tf->timeout[a]) {
  if (tf->timeout[NO_ACTION]) {
   moved = make_move(tf, tf->last_action);
  }
  if (a != NO_ACTION) {
   tf->last_action = a;
   tf->timeout[NO_ACTION] = 3;
  }
 } else if ((moved = make_move(tf, a)) == NO_ACTION) {
  if (a != NO_ACTION) {
   tf->last_action = a;
   tf->timeout[NO_ACTION] = 4;
  }
 }
 return moved;
}


decompiled_code:
__int64 __fastcall is_lockable(unsigned int *a1)
{
__int64 v1; // r12
__int64 i; // rbx

v1 = *((_QWORD *)a1 + 4) + 2LL * (int)a1[2];
for ( i = 0LL; i != 4; ++i )
{
if ( (*(_BYTE *)(v1 + 2 * i + 12) & 1) == 0 && (unsigned int)tetmino_has_row(*a1, (unsigned int)i) )
return 0LL;
}
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func6(unsigned int *a1)
{
__int64 v1; // r12
__int64 i; // rbx

v1 = *((_QWORD *)a1 + 4) + 2LL * (int)a1[2];
for ( i = 0LL; i != 4; ++i )
{
if ( (*(_BYTE *)(v1 + 2 * i + 12) & 1) == 0 && (unsigned int)tetmino_has_row(*a1, (unsigned int)i) )
return 0LL;
}
return 1LL;
}

original_code:
static int is_lockable(const struct tetfield *tf)
{
 const blocks_row *blocks = tf->grid->blocks + tf->mino.row;
 int i;
 for (i=0; i < 4; i++) {
  if (!(blocks[i] & 1) && tetmino_has_row(tf->mino.shape, i))
   return 0;
 }
 return 1;
}

canonical_original_code:
static int is_lockable(struct tetfield *tf)
{
 unsigned short *blocks = tf->grid->blocks + tf->mino.row;
 int i;
 for (i=0; i < 4; i++) {
  if (!(blocks[i] & 1) && tetmino_has_row(tf->mino.shape, i))
   return 0;
 }
 return 1;
}

variable_types:
blocks
unsigned short *

variable_types: i int


decompiled_code:
__int64 __fastcall enter_tetfield(__int64 a1, __int64 a2, unsigned int a3)
{
init_tetmino(a1, a2, 21LL, a3, 26LL);
*(_DWORD *)(a1 + 44) = 0;
return stop_retrying_action(a1);
}

canonical_decompiled_code:
__int64 __fastcall func7(__int64 a1, __int64 a2, unsigned int a3)
{
init_tetmino(a1, a2, 21LL, a3, 26LL);
*(_DWORD *)(a1 + 44) = 0;
return func0(a1);
}

original_code:
void enter_tetfield(struct tetfield *tf, int piece, int col)
{
 init_tetmino(&tf->mino, piece, (24 - 4) + 1, col, 25 + 1);
 tf->state = TETFIELD_SPAWN;
 stop_retrying_action(tf);
}

variable_types: piece int

variable_types: col int


decompiled_code:
__int64 __fastcall run_tetfield(__int64 a1, unsigned int a2, _DWORD *a3)
{
__int64 v4; // r13
unsigned int v5; // eax
int v6; // eax
unsigned int v7; // edx
int v9; // eax

v4 = *(_QWORD *)(a1 + 32);
dec_timeout(a1);
*a3 = 0;
a3[1] = 0;
v5 = *(_DWORD *)(a1 + 44);
if ( v5 == 2 )
{
a3[1] = control_tetmino(a1, v4 + 12, 5LL);
goto LABEL_5;
}
if ( v5 > 2 )
{
v7 = 0;
if ( v5 == 3 )
return v7;
goto LABEL_5;
}
if ( v5 )
{
*a3 = update_move(a1, a2);
a3[1] = update_tetmino(a1, v4 + 12, *(unsigned int *)(a1 + 40));
LABEL_5:
if ( *(_BYTE *)(a1 + 52) == 1 )
stop_retrying_action(a1);
update_removable_rows(v4, a1);
v6 = is_movable((_DWORD *)a1);
v7 = 1;
if ( !v6 )
{
*(_DWORD *)(a1 + 44) = 2;
v7 = is_lockable((unsigned int *)a1) == 0;
}
return v7;
}
update_prespawn(a1, a2);
v9 = *(_DWORD *)(a1 + 16);
if ( v9 <= 1 )
{
v7 = update_tetmino(a1, v4 + 12, *(unsigned int *)(a1 + 40));
a3[1] = v7;
if ( !v7 )
{
*(_DWORD *)(a1 + 44) = 3;
return v7;
}
*(_BYTE *)(a1 + 52) = 1;
*(_DWORD *)(a1 + 44) = 1;
*a3 = update_move(a1, a2);
goto LABEL_5;
}
v7 = 1;
if ( !*(_DWORD *)(v4 + 4) )
*(_DWORD *)(a1 + 16) = v9 - 1;
return v7;
}

original_code:
int run_tetfield(struct tetfield *tf, enum action a, struct changed *out)
{
 struct tetgrid *grid = tf->grid;
 dec_timeout(tf);
 out->moved = NO_ACTION;
 out->dropped = 0;
 switch (tf->state) {
 case TETFIELD_SPAWN:
  update_prespawn(tf, a);
  if (tf->mino.falling > 1) {
   if (grid->clearing) return 1;
   tf->mino.falling--;
   return 1;
  }
  out->dropped = update_tetmino(&tf->mino, grid->blocks, tf->gravity);
  if (!out->dropped) {
   tf->state = TETFIELD_TOP_OUT;
   return 0;
  }
  tf->timeout[NO_ACTION] = 1;
  tf->state = TETFIELD_MOVE;
  out->moved = update_move(tf, a);
  break;
 case TETFIELD_MOVE:
  out->moved = update_move(tf, a);
  out->dropped = update_tetmino(&tf->mino, grid->blocks, tf->gravity);
  break;
 case TETFIELD_PLACED:
  out->dropped = control_tetmino(&tf->mino, grid->blocks, HARDDROP);
  break;
 case TETFIELD_TOP_OUT:
  return 0;
 }
 if (tf->timeout[NO_ACTION] == 1) {
  stop_retrying_action(tf);
 }
 update_removable_rows(grid, &tf->mino);
 return is_movable(&tf->mino) || (tf->state = TETFIELD_PLACED, !is_lockable(tf));
}

variable_types: struct changed { enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } moved; int dropped; } *

variable_types: struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } *


original_code:
int lock_tetfield(struct tetfield *tf)
{
 struct tetgrid *grid = tf->grid;
 blocks_row *blocks = grid->blocks;
 int num_lines_cleared = 0;
 int i;
 xor_tetmino(&tf->mino, blocks);
 blocks += tf->mino.row;
 for (i=0; i < 4; i++) {
  blocks_row b = blocks[i] + 1;
  if (!b) {
   num_lines_cleared++;
   blocks[i] ^= 1;
   grid->clearing++;
   grid->delay += 5;
  }
 }
 tf->score += (num_lines_cleared << num_lines_cleared) *
  (grid->cols * grid->cols + tf->pieces) / tf->gravity;
 tf->pieces++;
 if (tf->pieces >= 25 && num_lines_cleared) {
  levelup(tf);
 }
 return num_lines_cleared;
}

canonical_original_code:
int lock_tetfield(struct tetfield *tf)
{
 struct tetgrid *grid = tf->grid;
 unsigned short *blocks = grid->blocks;
 int num_lines_cleared = 0;
 int i;
 xor_tetmino(&tf->mino, blocks);
 blocks += tf->mino.row;
 for (i=0; i < 4; i++) {
  unsigned short b = blocks[i] + 1;
  if (!b) {
   num_lines_cleared++;
   blocks[i] ^= 1;
   grid->clearing++;
   grid->delay += 5;
  }
 }
 tf->score += (num_lines_cleared << num_lines_cleared) *
  (grid->cols * grid->cols + tf->pieces) / tf->gravity;
 tf->pieces++;
 if (tf->pieces >= 25 && num_lines_cleared) {
  levelup(tf);
 }
 return num_lines_cleared;
}

variable_types:
b
unsigned short


original_code:
static size_t get_seq_len(const char *s, size_t buflen)
{
 size_t i = 0;
 if (buflen == 0) {
  return 0;
 }
 if (s[0]) {
  i = 1;
 }
 if (s[0] == '\033') {
  int final_byte_start = 0x30;
  if (s[1] == '[') {
   final_byte_start = 0x40;
   i = 2;
   while (s[i] >= 0x30 && s[i] < 0x40) {
    i++;
   }
  }
  if (s[1] == 'O') {
   i = 2;
  } else {
   while (s[i] >= 0x20 && s[i] < 0x30) {
    i++;
   }
  }
  if (s[i] >= final_byte_start && s[i] < 0x7f) {
   i++;
   return i;
  }
  if (i == buflen) {
   return 0;
  }
 }
 if (!s[i]) {
  return i + 1;
 }
 return i;
}

canonical_original_code:
static unsigned long get_seq_len(char *s, unsigned long buflen)
{
 unsigned long i = 0;
 if (buflen == 0) {
  return 0;
 }
 if (s[0]) {
  i = 1;
 }
 if (s[0] == '\033') {
  int final_byte_start = 0x30;
  if (s[1] == '[') {
   final_byte_start = 0x40;
   i = 2;
   while (s[i] >= 0x30 && s[i] < 0x40) {
    i++;
   }
  }
  if (s[1] == 'O') {
   i = 2;
  } else {
   while (s[i] >= 0x20 && s[i] < 0x30) {
    i++;
   }
  }
  if (s[i] >= final_byte_start && s[i] < 0x7f) {
   i++;
   return i;
  }
  if (i == buflen) {
   return 0;
  }
 }
 if (!s[i]) {
  return i + 1;
 }
 return i;
}

variable_types:
buflen
unsigned long

variable_types:
i
unsigned long

return_type: unsigned long


decompiled_code:
int check_stdin_ready()
{
struct timeval v1; // [rsp+0h] [rbp-98h] BYREF
fd_set readfds; // [rsp+10h] [rbp-88h] BYREF

memset(&readfds, 0, sizeof(readfds));
readfds.fds_bits[0] |= 1uLL;
v1.tv_sec = 0LL;
v1.tv_usec = 0LL;
return select(1, &readfds, 0LL, 0LL, &v1);
}

canonical_decompiled_code:
int func2()
{
struct timeval v1; // [rsp+0h] [rbp-98h] BYREF
fd_set readfds; // [rsp+10h] [rbp-88h] BYREF

memset(&readfds, 0, sizeof(readfds));
readfds.fds_bits[0] |= 1uLL;
v1.tv_sec = 0LL;
v1.tv_usec = 0LL;
return select(1, &readfds, 0LL, 0LL, &v1);
}

original_code:
static int check_stdin_ready()
{
 fd_set fds;
 struct timeval timeout;
 do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&fds)->__fds_bits)[0]) : "memory"); } while (0);
 ((void) (((&fds)->__fds_bits)[((0) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((0) % (8 * (int) sizeof (__fd_mask)))))));
 timeout.tv_sec = 0;
 timeout.tv_usec = 0;
 return select(0 + 1, &fds, ((void *)0), ((void *)0), &timeout);
}

canonical_original_code:
static int check_stdin_ready()
{
 struct fd_set fds;
 struct timeval timeout;
 do { int __d0; int __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&fds)->__fds_bits)[0]) : "memory"); } while (0);
 ((void) (((&fds)->__fds_bits)[((0) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((0) % (8 * (int) sizeof (__fd_mask)))))));
 timeout.tv_sec = 0;
 timeout.tv_usec = 0;
 return select(0 + 1, &fds, ((void *)0), ((void *)0), &timeout);
}

variable_types:
fds
struct fd_set { long __fds_bits[-1]; }

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


decompiled_code:
__int64 __fastcall read_into_buffer(__int64 a1, __int64 a2)
{
_BYTE *v2; // rbp
int v3; // ebx
__int64 result; // rax
int v5; // eax

v2 = (_BYTE *)(a2 + a1 + 16);
v3 = check_stdin_ready();
memset(v2, 0, 16 - a2);
if ( v3 > 0 )
{
v3 = read(0, v2, 15 - a2);
if ( !v3 )
{
*v2 = 4;
return 1LL;
}
}
else if ( !v3 )
{
if ( a2 )
{
v3 = read(0, v2, 15 - a2);
if ( !v3 )
return 1LL;
}
}
result = v3;
if ( v3 < 0 )
{
v5 = *_errno_location();
if ( v5 != 4 && v5 != 11 )
{
print_error("Error reading from stdin");
restore_terminal();
exit(1);
}
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1, __int64 a2)
{
_BYTE *v2; // rbp
int v3; // ebx
__int64 result; // rax
int v5; // eax

v2 = (_BYTE *)(a2 + a1 + 16);
v3 = func2();
memset(v2, 0, 16 - a2);
if ( v3 > 0 )
{
v3 = read(0, v2, 15 - a2);
if ( !v3 )
{
*v2 = 4;
return 1LL;
}
}
else if ( !v3 )
{
if ( a2 )
{
v3 = read(0, v2, 15 - a2);
if ( !v3 )
return 1LL;
}
}
result = v3;
if ( v3 < 0 )
{
v5 = *_errno_location();
if ( v5 != 4 && v5 != 11 )
{
print_error("Error reading from stdin");
restore_terminal();
exit(1);
}
result = 0LL;
}
return result;
}

original_code:
static size_t read_into_buffer(struct terminal_input *inp, size_t len)
{
 char *buf = inp->next.s + len;
 size_t nbytes = sizeof(inp->next.s) - len;
 int ret = check_stdin_ready();
 memset(buf, '\0', nbytes);
 if (ret > 0) {
  ret = read(0, buf, nbytes - 1);
  if (ret == 0) {
   buf[0] = '\004';
   return 1;
  }
 } else if (ret == 0 && len > 0) {
  ret = read(0, buf, nbytes - 1);
  if (ret == 0) {
   return 1;
  }
 }
 if (ret >= 0) {
  return ret;
 }
 if ((*__errno_location ()) != 4 && (*__errno_location ()) != 11 && (*__errno_location ()) != 11) {
  print_error("Error reading from stdin");
  restore_terminal();
  exit(1);
 }
 return 0;
}

canonical_original_code:
static unsigned long read_into_buffer(struct terminal_input *inp, unsigned long len)
{
 char *buf = inp->next.s + len;
 unsigned long nbytes = sizeof(inp->next.s) - len;
 int ret = check_stdin_ready();
 memset(buf, '\0', nbytes);
 if (ret > 0) {
  ret = read(0, buf, nbytes - 1);
  if (ret == 0) {
   buf[0] = '\004';
   return 1;
  }
 } else if (ret == 0 && len > 0) {
  ret = read(0, buf, nbytes - 1);
  if (ret == 0) {
   return 1;
  }
 }
 if (ret >= 0) {
  return ret;
 }
 if ((*__errno_location ()) != 4 && (*__errno_location ()) != 11 && (*__errno_location ()) != 11) {
  print_error("Error reading from stdin");
  restore_terminal();
  exit(1);
 }
 return 0;
}

variable_types: struct terminal_input { struct terminal_seq_buffer { char s[16]; } current; unsigned long next_length; } *

variable_types:
len
unsigned long

variable_types:
buf
char *

variable_types:
nbytes
unsigned long

variable_types: ret int

user_defined_types: struct terminal_input { struct terminal_seq_buffer current; unsigned long next_length; }


original_code:
size_t read_terminal_seq(struct terminal_input *inp)
{
 char *buf = inp->next.s;
 size_t len = get_seq_len(buf, inp->next_length);
 if (len == 0) {
  inp->next_length = truncate_seq(buf, inp->next_length, 8);
  len = read_into_buffer(inp, inp->next_length);
  if (len > 0) {
   inp->next_length += len;
   len = get_seq_len(buf, inp->next_length);
  }
 }
 if (len > 0) {
  inp->current = inp->next;
  if (len < inp->next_length) {
   inp->next_length -= len;
  } else {
   inp->next_length = 0;
  }
  memcpy(buf, inp->current.s + len, inp->next_length + 1);
 }
 inp->current.s[len] = '\0';
 return len;
}

canonical_original_code:
unsigned long read_terminal_seq(struct terminal_input *inp)
{
 char *buf = inp->next.s;
 unsigned long len = get_seq_len(buf, inp->next_length);
 if (len == 0) {
  inp->next_length = truncate_seq(buf, inp->next_length, 8);
  len = read_into_buffer(inp, inp->next_length);
  if (len > 0) {
   inp->next_length += len;
   len = get_seq_len(buf, inp->next_length);
  }
 }
 if (len > 0) {
  inp->current = inp->next;
  if (len < inp->next_length) {
   inp->next_length -= len;
  } else {
   inp->next_length = 0;
  }
  memcpy(buf, inp->current.s + len, inp->next_length + 1);
 }
 inp->current.s[len] = '\0';
 return len;
}

user_defined_types: struct terminal_seq_buffer { char s[16]; }


original_code:
const char *read_terminal_keypress(struct terminal_input *inp)
{
 size_t len = read_terminal_seq(inp);
 const char *s = inp->current.s;
 if (!strcmp(s, " ")) {
  return "space";
 }
 if (len == 3 && s[0] == '\033' && s[1] == '[') {
  switch (s[2]) {
  case 'A': return "up";
  case 'B': return "down";
  case 'C': return "right";
  case 'D': return "left";
  }
 }
 return s;
}

canonical_original_code:
char *read_terminal_keypress(struct terminal_input *inp)
{
 unsigned long len = read_terminal_seq(inp);
 char *s = inp->current.s;
 if (!strcmp(s, " ")) {
  return "space";
 }
 if (len == 3 && s[0] == '\033' && s[1] == '[') {
  switch (s[2]) {
  case 'A': return "up";
  case 'B': return "down";
  case 'C': return "right";
  case 'D': return "left";
  }
 }
 return s;
}

variable_types:
s
char *

return_type: char *


original_code:
static int is_empty_row(const struct tetgrid *grid, int row)
{
 return (grid->blocks[row] & grid->blocks[0]) == 0;
}

canonical_original_code:
static int is_empty_row(struct tetgrid *grid, int row)
{
 return (grid->blocks[row] & grid->blocks[0]) == 0;
}

variable_types: row int


decompiled_code:
__int64 __fastcall invert_blocks(__int64 a1, int a2)
{
return ~(*(unsigned __int16 *)(a1 + 2LL * a2 + 12) | 1u);
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, int a2)
{
return ~(*(unsigned __int16 *)(a1 + 2LL * a2 + 12) | 1u);
}

original_code:
static blocks_row invert_blocks(const struct tetgrid *grid, int row)
{
 blocks_row b = -1;
 return b ^ (grid->blocks[row] | 1);
}

canonical_original_code:
static unsigned short invert_blocks(struct tetgrid *grid, int row)
{
 unsigned short b = -1;
 return b ^ (grid->blocks[row] | 1);
}

return_type: unsigned short


original_code:
static blocks_row grow_cleared_blocks(struct tetgrid *grid, int row)
{
 blocks_row b = invert_blocks(grid, row);
 if (b)
  grid->blocks[row] &= ~((b << 1) | (b >> 1));
 else {
  b = (grid->cols & 1) ? 1 : 3;
  grid->blocks[row] ^= b << (grid->cols/2 + 3 - 1);
 }
 return (b ^ invert_blocks(grid, row)) >> 3;
}

canonical_original_code:
static unsigned short grow_cleared_blocks(struct tetgrid *grid, int row)
{
 unsigned short b = invert_blocks(grid, row);
 if (b)
  grid->blocks[row] &= ~((b << 1) | (b >> 1));
 else {
  b = (grid->cols & 1) ? 1 : 3;
  grid->blocks[row] ^= b << (grid->cols/2 + 3 - 1);
 }
 return (b ^ invert_blocks(grid, row)) >> 3;
}


original_code:
int update_line_clears(struct tetgrid *grid)
{
 int cleared = 0;
 int clearing = grid->clearing;
 int i;
 if (grid->delay > 0) {
  grid->delay--;
  return 0;
 }
 for (i=1; clearing > 0 && i < 24; i++) {
  if (!(grid->blocks[i] & 1)) {
   cleared = i;
   clearing--;
   grid->delay = 5;
  }
 }
 for (i = cleared + 1; i + 1 < 24; i++) {
  if (is_empty_row(grid, i) && !is_empty_row(grid, i + 1)) {
   grid->blocks[i] ^= 1;
   grid->clearing++;
  }
 }
 return cleared;
}

variable_types: cleared int

variable_types: clearing int

variable_types: i int


decompiled_code:
__int16 __fastcall shift_cleared_blocks(_DWORD *a1, int a2)
{
char *v2; // rax

if ( !is_empty_row((__int64)a1, a2) )
return grow_cleared_blocks(a1, a2);
if ( a2 <= 22 )
{
v2 = (char *)a1 + 2 * a2;
do
{
*((_WORD *)v2 + 6) = *((_WORD *)v2 + 7);
v2 += 2;
}
while ( v2 != (char *)a1 + 2 * a2 + 2 * (unsigned __int64)(unsigned int)(22 - a2) + 2 );
}
--a1[1];
return 0;
}

original_code:
blocks_row shift_cleared_blocks(struct tetgrid *grid, int row)
{
 if (is_empty_row(grid, row)) {
  for (; row + 1 < 24; row++) {
   grid->blocks[row] = grid->blocks[row + 1];
  }
  grid->clearing--;
  return 0;
 }
 return grow_cleared_blocks(grid, row);
}

canonical_original_code:
unsigned short shift_cleared_blocks(struct tetgrid *grid, int row)
{
 if (is_empty_row(grid, row)) {
  for (; row + 1 < 24; row++) {
   grid->blocks[row] = grid->blocks[row + 1];
  }
  grid->clearing--;
  return 0;
 }
 return grow_cleared_blocks(grid, row);
}


decompiled_code:
__int64 __fastcall next_cleared_row(__int64 a1, int a2)
{
__int64 v2; // rsi
unsigned int v3; // edx
__int16 v4; // ax

v2 = a2 - 1;
do
{
v3 = v2;
v4 = *(_WORD *)(a1 + 2 * v2-- + 12);
}
while ( (v4 & 1) != 0 );
return v3;
}

original_code:
int next_cleared_row(const struct tetgrid *grid, int row)
{
 do row--;
 while (grid->blocks[row] & 1);
 return row;
}

canonical_original_code:
int next_cleared_row(struct tetgrid *grid, int row)
{
 do row--;
 while (grid->blocks[row] & 1);
 return row;
}


decompiled_code:
__int64 __fastcall update_removable_rows(const __m128i *a1, __int64 a2)
{
__int64 result; // rax
int v3; // ebx
__int128 v4[3]; // [rsp+0h] [rbp-58h] BYREF
__int64 v5; // [rsp+30h] [rbp-28h]
int v6; // [rsp+38h] [rbp-20h]

v4[0] = (__int128)_mm_loadu_si128(a1);
v4[1] = (__int128)_mm_loadu_si128(a1 + 1);
v4[2] = (__int128)_mm_loadu_si128(a1 + 2);
v5 = a1[3].m128i_i64[0];
v6 = a1[3].m128i_i32[2];
result = update_line_clears((__int64)v4);
v3 = result;
if ( (int)result > 0 )
{
while ( 1 )
{
if ( !shift_cleared_blocks(v4, v3) )
{
result = can_move_tetmino(a2, (char *)v4 + 12, 0LL);
if ( !(_DWORD)result )
break;
}
result = next_cleared_row((__int64)a1, v3);
v3 = result;
if ( (int)result <= 0 )
return result;
}
if ( v3 > 0 )
{
do
{
if ( is_empty_row((__int64)a1, v3) )
{
a1->m128i_i16[v3 + 6] |= 1u;
--a1->m128i_i32[1];
}
result = next_cleared_row((__int64)a1, v3);
v3 = result;
}
while ( (int)result > 0 );
}
}
return result;
}

original_code:
void update_removable_rows(struct tetgrid *grid, const struct tetmino *t)
{
 struct tetgrid grid2 = *grid;
 int row = update_line_clears(&grid2);
 while (row > 0 && (shift_cleared_blocks(&grid2, row) || can_move_tetmino(t, grid2.blocks, 0))) {
  row = next_cleared_row(grid, row);
 }
 while (row > 0) {
  if (is_empty_row(grid, row)) {
   grid->blocks[row] |= 1;
   grid->clearing--;
  }
  row = next_cleared_row(grid, row);
 }
}

canonical_original_code:
void update_removable_rows(struct tetgrid *grid, struct tetmino *t)
{
 struct tetgrid grid2 = *grid;
 int row = update_line_clears(&grid2);
 while (row > 0 && (shift_cleared_blocks(&grid2, row) || can_move_tetmino(t, grid2.blocks, 0))) {
  row = next_cleared_row(grid, row);
 }
 while (row > 0) {
  if (is_empty_row(grid, row)) {
   grid->blocks[row] |= 1;
   grid->clearing--;
  }
  row = next_cleared_row(grid, row);
 }
}

variable_types: struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } *

variable_types: struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; }


original_code:
static void render_piece(struct bitmap *bitmap, struct piece *p, int mask)
{
 unsigned char *bmp = bitmap->bitmap;
 struct copyrect r = p->r;
 for (; r.height > 0; r.height--) {
  int i;
  for (i=0; i < r.width; i++) {
   int block = p->piece[r.si + i];
   p->piece[r.si + i] = bmp[r.di + i];
   if (block)
    bmp[r.di + i] = block & mask;
  }
  r.di += bitmap->width;
  r.si += 4;
 }
}

variable_types: struct bitmap { unsigned char *bitmap; int width; int height; } *

variable_types: struct piece { struct copyrect { int width; int di; } r; unsigned char piece[-1]; struct piece *prev; } *

variable_types: mask int

variable_types:
bmp
unsigned char *

variable_types:
r
struct copyrect { int width; int di; }

variable_types: block int


original_code:
void render_tetmino_piece(struct bitmap *bitmap, struct piece *p, const struct tetmino *t, int mask)
{
 int w = bitmap->width;
 int h = bitmap->height;
 p->r = cliprect(
  w, h, 4, 4,
  t->col - 3, h - (4 - 1) - t->row
 );
 make_piece(p->piece, t->shape);
 mask &= 0x88 | (0x11 * (t->piece + 1));
 render_piece(bitmap, p, mask);
}

canonical_original_code:
void render_tetmino_piece(struct bitmap *bitmap, struct piece *p, struct tetmino *t, int mask)
{
 int w = bitmap->width;
 int h = bitmap->height;
 p->r = cliprect(
  w, h, 4, 4,
  t->col - 3, h - (4 - 1) - t->row
 );
 make_piece(p->piece, t->shape);
 mask &= 0x88 | (0x11 * (t->piece + 1));
 render_piece(bitmap, p, mask);
}

variable_types: w int

variable_types: h int


original_code:
static struct piece *render_tetmino_pieces(struct bitmap *bitmap, struct tetmino_piece *tp)
{
 struct piece *piece = ((void *)0);
 while (tp) {
  render_tetmino_piece(bitmap, &tp->piece, tp->tetmino, tp->mask);
  tp->piece.prev = piece;
  piece = &tp->piece;
  tp = tp->succ;
 }
 return piece;
}

variable_types: struct tetmino_piece { struct piece piece; struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } *tetmino; int mask; struct tetmino_piece *succ; } *

return_type: struct piece { struct copyrect { int width; int di; } r; unsigned char piece[-1]; struct piece *prev; } *


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

result = a1;
*(_QWORD *)(a1 + 40) = a2;
*(_DWORD *)(a1 + 48) = a3;
*(_QWORD *)(a1 + 56) = a4;
return result;
}

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

result = a1;
*(_QWORD *)(a1 + 40) = a2;
*(_DWORD *)(a1 + 48) = a3;
*(_QWORD *)(a1 + 56) = a4;
return result;
}

original_code:
struct tetmino_piece *init_tetmino_piece(struct tetmino_piece *tp,
 const struct tetmino *t, int mask, struct tetmino_piece *succ)
{
 tp->tetmino = t;
 tp->mask = mask;
 tp->succ = succ;
 return tp;
}

canonical_original_code:
struct tetmino_piece *init_tetmino_piece(struct tetmino_piece *tp, struct tetmino *t, int mask, struct tetmino_piece *succ)
{
 tp->tetmino = t;
 tp->mask = mask;
 tp->succ = succ;
 return tp;
}

variable_types:
tp
struct tetmino_piece *

variable_types:
t
struct tetmino *

variable_types:
succ
struct tetmino_piece *

return_type: struct tetmino_piece { struct piece { struct copyrect { int width; int di; } r; unsigned char piece[-1]; struct piece *prev; } piece; struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } *tetmino; int mask; struct tetmino_piece *succ; } *


original_code:
void render_cleared_blocks(struct bitmap *bitmap, int row, blocks_row mask)
{
 unsigned char *bmp = bitmap->bitmap;
 int w = bitmap->width;
 int h = bitmap->height;
 int i = 0;
 if (mask) {
  for (; mask; mask >>= 1, i++) {
   if (mask & 1)
    bmp[w * (h - row) + i] = 0x80;
  }
 } else {
  memmove(bmp + w, bmp, w * (h - row));
  memset(bmp, 0, w);
  while (memchr(bmp + w, 0, w)) {
   bmp += w;
  }
  for (; i < w; i++) {
   if (!bmp[i]) {
    bmp[i] = 0x80;
   }
  }
 }
}

canonical_original_code:
void render_cleared_blocks(struct bitmap *bitmap, int row, unsigned short mask)
{
 unsigned char *bmp = bitmap->bitmap;
 int w = bitmap->width;
 int h = bitmap->height;
 int i = 0;
 if (mask) {
  for (; mask; mask >>= 1, i++) {
   if (mask & 1)
    bmp[w * (h - row) + i] = 0x80;
  }
 } else {
  memmove(bmp + w, bmp, w * (h - row));
  memset(bmp, 0, w);
  while (memchr(bmp + w, 0, w)) {
   bmp += w;
  }
  for (; i < w; i++) {
   if (!bmp[i]) {
    bmp[i] = 0x80;
   }
  }
 }
}

variable_types: row int

variable_types:
mask
unsigned short


decompiled_code:
__int64 __fastcall get_blocks_box(unsigned __int16 *a1, char a2)
{
unsigned __int16 *v3; // rsi
unsigned __int16 *v4; // rdi
unsigned int v5; // edx

v3 = a1;
v4 = a1 + 4;
v5 = 0;
do
v5 = ((int)*v3++ >> a2) & 0xF | (16 * v5);
while ( v3 != v4 );
return v5;
}

canonical_decompiled_code:
__int64 __fastcall func0(unsigned __int16 *a1, char a2)
{
unsigned __int16 *v3; // rsi
unsigned __int16 *v4; // rdi
unsigned int v5; // edx

v3 = a1;
v4 = a1 + 4;
v5 = 0;
do
v5 = ((int)*v3++ >> a2) & 0xF | (16 * v5);
while ( v3 != v4 );
return v5;
}

original_code:
static unsigned get_blocks_box(const blocks_row *blocks, int col)
{
 unsigned box = 0, row_mask = (1 << 4) - 1;
 int i;
 for (i=0; i < 4; i++)
  box = (box << 4) | ((blocks[i] >> col) & row_mask);
 return box;
}

canonical_original_code:
static unsigned int get_blocks_box(unsigned short *blocks, int col)
{
 unsigned int box = 0; unsigned int row_mask = (1 << 4) - 1;
 int i;
 for (i=0; i < 4; i++)
  box = (box << 4) | ((blocks[i] >> col) & row_mask);
 return box;
}

variable_types:
blocks
unsigned short *

variable_types: col int

variable_types:
box
unsigned int

variable_types: i int

return_type: unsigned int


decompiled_code:
__int64 __fastcall floor_kick(_DWORD *a1, unsigned int a2, int a3)
{
__int64 result; // rax

result = 0LL;
if ( (a3 & a2) >> 12 && (a2 & (16 * a3)) == 0 && !a1[7] )
{
a1[7] = 1;
++a1[2];
result = 1LL;
if ( a1[4] )
a1[4] = 1;
}
return result;
}

original_code:
static int floor_kick(struct tetmino *t, unsigned rotated, unsigned box)
{
 if ((rotated & box) >> (4 -1) * 4 &&
     !(rotated & (box << 4)) && !t->climbed) {
  t->climbed = 1;
  t->row++;
  if (t->falling) {
   t->falling = 1;
  }
  return 1;
 }
 return 0;
}

canonical_original_code:
static int floor_kick(struct tetmino *t, unsigned int rotated, unsigned int box)
{
 if ((rotated & box) >> (4 -1) * 4 &&
     !(rotated & (box << 4)) && !t->climbed) {
  t->climbed = 1;
  t->row++;
  if (t->falling) {
   t->falling = 1;
  }
  return 1;
 }
 return 0;
}

variable_types: struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } *

variable_types:
rotated
unsigned int


decompiled_code:
__int64 __fastcall wall_kick(_DWORD *a1, int a2, int a3, unsigned __int16 *a4)
{
int v4; // edx
unsigned int v5; // er12
unsigned int v6; // er13

if ( a2 == 3840 )
{
v5 = 2 * (*a1 != 8738) - 1;
}
else
{
v4 = a2 & a3;
if ( (v4 & 0xFFFFBBBB) != 0 )
{
v5 = 0;
if ( (v4 & 0xFFFFEEEE) != 0 )
return v5;
v5 = 1;
}
else
{
v5 = -1;
}
}
v6 = a1[3] + v5;
if ( (a2 & (unsigned int)get_blocks_box(a4, *((_BYTE *)a1 + 12) + (unsigned __int8)v5)) != 0 )
return 0;
a1[3] = v6;
return v5;
}

canonical_decompiled_code:
__int64 __fastcall func2(_DWORD *a1, int a2, int a3, unsigned __int16 *a4)
{
int v4; // edx
unsigned int v5; // er12
unsigned int v6; // er13

if ( a2 == 3840 )
{
v5 = 2 * (*a1 != 8738) - 1;
}
else
{
v4 = a2 & a3;
if ( (v4 & 0xFFFFBBBB) != 0 )
{
v5 = 0;
if ( (v4 & 0xFFFFEEEE) != 0 )
return v5;
v5 = 1;
}
else
{
v5 = -1;
}
}
v6 = a1[3] + v5;
if ( (a2 & (unsigned int)func0(a4, *((_BYTE *)a1 + 12) + (unsigned __int8)v5)) != 0 )
return 0;
a1[3] = v6;
return v5;
}

original_code:
static int wall_kick(struct tetmino *t, unsigned rotated, unsigned box,
       const blocks_row *blocks)
{
 unsigned overlap = rotated & box,
   mask1 = 0x2222 >> 1,
   mask3 = 0x2222 << 1;
 int n = 0;
 if (rotated == 0x0F00)
  n = (t->shape == 0x2222) ? -1 : 1;
 else {
  if (overlap == (overlap & mask1))
   n = 1;
  if (overlap == (overlap & mask3))
   n = -1;
 }
 if (n && !(rotated & get_blocks_box(blocks, t->col + n))) {
  t->col += n;
  return n;
 }
 return 0;
}

canonical_original_code:
static int wall_kick(struct tetmino *t, unsigned int rotated, unsigned int box, unsigned short *blocks)
{
 unsigned int overlap = rotated & box; unsigned int mask1 = 0x2222 >> 1; unsigned int mask3 = 0x2222 << 1;
 int n = 0;
 if (rotated == 0x0F00)
  n = (t->shape == 0x2222) ? -1 : 1;
 else {
  if (overlap == (overlap & mask1))
   n = 1;
  if (overlap == (overlap & mask3))
   n = -1;
 }
 if (n && !(rotated & get_blocks_box(blocks, t->col + n))) {
  t->col += n;
  return n;
 }
 return 0;
}

variable_types:
overlap
unsigned int

variable_types: n int


rotate

decompiled_code:
__int64 __fastcall rotate(unsigned int *a1, unsigned __int16 *a2, int a3)
{
__int16 *v5; // rbp
int v6; // er14
unsigned int v7; // ecx
__int64 v8; // rax
int v9; // esi
__int64 result; // rax
unsigned __int16 v11; // r12
unsigned int v12; // ebp

v5 = &tetmino_shapes[4 * a1[1]];
v6 = get_blocks_box(a2, a1[3]);
v7 = *a1;
v8 = 0LL;
if ( (unsigned __int16)*v5 != *a1 )
{
while ( 1 )
{
v9 = v8;
if ( v7 == (unsigned __int16)v5[v8] )
break;
if ( ++v8 == 4 )
return 0LL;
}
v11 = v5[((_BYTE)a3 + (_BYTE)v8) & 3];
v12 = v11;
if ( (v11 & (unsigned __int16)v6) == 0 )
goto LABEL_12;
LABEL_10:
if ( v9 == 2 && (unsigned int)floor_kick(a1, v12, v6) || (result = wall_kick(a1, v12, v6, a2), (_DWORD)result) )
{
LABEL_12:
*a1 = v12;
return v11 ^ 0x6600u;
}
return result;
}
result = 1LL;
if ( v7 == (unsigned __int16)v5[2] )
{
result = 1LL;
if ( ((unsigned __int16)v6 & (unsigned __int16)v5[a3]) != 0 )
{
LOBYTE(a3) = a3 + 2;
result = 0LL;
}
}
v11 = v5[a3 & 3];
v12 = v11;
if ( (v11 & (unsigned __int16)v6) == 0 )
goto LABEL_12;
if ( (_DWORD)result )
{
v9 = 0;
goto LABEL_10;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(unsigned int *a1, unsigned __int16 *a2, int a3)
{
__int16 *v5; // rbp
int v6; // er14
unsigned int v7; // ecx
__int64 v8; // rax
int v9; // esi
__int64 result; // rax
unsigned __int16 v11; // r12
unsigned int v12; // ebp

v5 = &tetmino_shapes[4 * a1[1]];
v6 = func0(a2, a1[3]);
v7 = *a1;
v8 = 0LL;
if ( (unsigned __int16)*v5 != *a1 )
{
while ( 1 )
{
v9 = v8;
if ( v7 == (unsigned __int16)v5[v8] )
break;
if ( ++v8 == 4 )
return 0LL;
}
v11 = v5[((_BYTE)a3 + (_BYTE)v8) & 3];
v12 = v11;
if ( (v11 & (unsigned __int16)v6) == 0 )
goto LABEL_12;
LABEL_10:
if ( v9 == 2 && (unsigned int)func1(a1, v12, v6) || (result = func2(a1, v12, v6, a2), (_DWORD)result) )
{
LABEL_12:
*a1 = v12;
return v11 ^ 0x6600u;
}
return result;
}
result = 1LL;
if ( v7 == (unsigned __int16)v5[2] )
{
result = 1LL;
if ( ((unsigned __int16)v6 & (unsigned __int16)v5[a3]) != 0 )
{
LOBYTE(a3) = a3 + 2;
result = 0LL;
}
}
v11 = v5[a3 & 3];
v12 = v11;
if ( (v11 & (unsigned __int16)v6) == 0 )
goto LABEL_12;
if ( (_DWORD)result )
{
v9 = 0;
goto LABEL_10;
}
return result;
}

original_code:
static int rotate(struct tetmino *t, const blocks_row *blocks, int n)
{
 const unsigned short *rot_states = tetmino_shapes[t->piece];
 unsigned box = get_blocks_box(blocks, t->col);
 int kick = 1;
 int i;
 if (rot_states[0] == t->shape &&
     rot_states[2] == t->shape && (rot_states[n] & box)) {
  n += 2;
  kick = 0;
 }
 for (i=0; i<4; i++) {
  if (rot_states[i] == t->shape) {
   unsigned rotated = rot_states[(i+n) & 3];
   if (rotated & box) {
    if (!kick)
     return 0;
    if (i == 2 && floor_kick(t, rotated, box))
     ;
    else if (!wall_kick(t, rotated, box, blocks))
     return 0;
   }
   t->shape = rotated;
   return rotated ^ 0x6600;
  }
 }
 return 0;
}

canonical_original_code:
static int rotate(struct tetmino *t, unsigned short *blocks, int n)
{
 unsigned short *rot_states = tetmino_shapes[t->piece];
 unsigned int box = get_blocks_box(blocks, t->col);
 int kick = 1;
 int i;
 if (rot_states[0] == t->shape &&
     rot_states[2] == t->shape && (rot_states[n] & box)) {
  n += 2;
  kick = 0;
 }
 for (i=0; i<4; i++) {
  if (rot_states[i] == t->shape) {
   unsigned int rotated = rot_states[(i+n) & 3];
   if (rotated & box) {
    if (!kick)
     return 0;
    if (i == 2 && floor_kick(t, rotated, box))
     ;
    else if (!wall_kick(t, rotated, box, blocks))
     return 0;
   }
   t->shape = rotated;
   return rotated ^ 0x6600;
  }
 }
 return 0;
}

variable_types: kick int


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

result = (unsigned int)(20 - a2);
*(_DWORD *)(a1 + 24) = 30;
if ( *(_DWORD *)(a1 + 20) < (int)result )
*(_DWORD *)(a1 + 20) = result;
return result;
}

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

result = (unsigned int)(20 - a2);
*(_DWORD *)(a1 + 24) = 30;
if ( *(_DWORD *)(a1 + 20) < (int)result )
*(_DWORD *)(a1 + 20) = result;
return result;
}

original_code:
static void init_lock_delay(struct tetmino *t, int gravity)
{
 int lock_delay = 20 - gravity;
 t->lock_delay_step = 30;
 if (lock_delay > t->lock_delay_move)
  t->lock_delay_move = lock_delay;
}

variable_types: gravity int


decompiled_code:
__int64 __fastcall tetmino_has_row(unsigned int a1, char a2)
{
return (a1 >> (4 * (3 - a2))) & 0xF;
}

canonical_decompiled_code:
__int64 __fastcall func5(unsigned int a1, char a2)
{
return (a1 >> (4 * (3 - a2))) & 0xF;
}

original_code:
int tetmino_has_row(unsigned shape, int i)
{
 int shift = (4 - 1 - i) * 4;
 return (shape >> shift) % (1 << 4);
}

canonical_original_code:
int tetmino_has_row(unsigned int shape, int i)
{
 int shift = (4 - 1 - i) * 4;
 return (shape >> shift) % (1 << 4);
}

variable_types:
shape
unsigned int

variable_types: shift int


decompiled_code:
_BOOL8 __fastcall can_move_tetmino(__int64 a1, __int64 a2, char a3)
{
return (*(_DWORD *)a1 & (unsigned int)get_blocks_box(
(unsigned __int16 *)(a2 + 2LL * *(int *)(a1 + 8)),
*(_BYTE *)(a1 + 12) + a3)) == 0;
}

canonical_decompiled_code:
_BOOL8 __fastcall func6(__int64 a1, __int64 a2, char a3)
{
return (*(_DWORD *)a1 & (unsigned int)func0(
(unsigned __int16 *)(a2 + 2LL * *(int *)(a1 + 8)),
*(_BYTE *)(a1 + 12) + a3)) == 0;
}

original_code:
int can_move_tetmino(const struct tetmino *t, const blocks_row *blocks, int d)
{
 return !(t->shape & get_blocks_box(blocks + t->row, t->col + d));
}

canonical_original_code:
int can_move_tetmino(struct tetmino *t, unsigned short *blocks, int d)
{
 return !(t->shape & get_blocks_box(blocks + t->row, t->col + d));
}

variable_types: d int


original_code:
int drop_height(const struct tetmino *t, const blocks_row *blocks, int max)
{
 int h = 0;
 if (max > t->row)
  max = t->row;
 if (max > 0) {
  unsigned box = get_blocks_box(blocks += t->row - 1, t->col);
  while (!(t->shape & box)) {
   h++;
   if (h == max)
    break;
   box = (box >> 4) |
         (blocks[-h] >> t->col
          << (4 -1) * 4);
   box &= (1U << 4 * 4) - 1;
  }
 }
 return h;
}

canonical_original_code:
int drop_height(struct tetmino *t, unsigned short *blocks, int max)
{
 int h = 0;
 if (max > t->row)
  max = t->row;
 if (max > 0) {
  unsigned int box = get_blocks_box(blocks += t->row - 1, t->col);
  while (!(t->shape & box)) {
   h++;
   if (h == max)
    break;
   box = (box >> 4) |
         (blocks[-h] >> t->col
          << (4 -1) * 4);
   box &= (1U << 4 * 4) - 1;
  }
 }
 return h;
}

variable_types: max int

variable_types: h int


drop

decompiled_code:
__int64 __fastcall drop(int *a1, __int64 a2, int a3)
{
__int64 result; // rax
int v4; // edx

result = drop_height(a1, a2, a3);
a1[2] -= result;
v4 = a1[7] - result;
if ( v4 < 0 )
v4 = 0;
a1[7] = v4;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(int *a1, __int64 a2, int a3)
{
__int64 result; // rax
int v4; // edx

result = func7(a1, a2, a3);
a1[2] -= result;
v4 = a1[7] - result;
if ( v4 < 0 )
v4 = 0;
a1[7] = v4;
return result;
}

original_code:
static int drop(struct tetmino *t, const blocks_row *blocks, int n)
{
 int h = drop_height(t, blocks, n);
 t->row -= h;
 t->climbed -= h;
 if (t->climbed < 0)
  t->climbed = 0;
 return h;
}

canonical_original_code:
static int drop(struct tetmino *t, unsigned short *blocks, int n)
{
 int h = drop_height(t, blocks, n);
 t->row -= h;
 t->climbed -= h;
 if (t->climbed < 0)
  t->climbed = 0;
 return h;
}


decompiled_code:
__int64 __fastcall control_tetmino(unsigned int *a1, __int64 a2, int a3)
{
unsigned int v3; // eax
int v4; // edx
__int64 result; // rax

switch ( a3 )
{
case 1:
v3 = rotate(a1, (unsigned __int16 *)(a2 + 2LL * (int)a1[2]), 1);
goto LABEL_3;
case 2:
v3 = rotate(a1, (unsigned __int16 *)(a2 + 2LL * (int)a1[2]), 3);
goto LABEL_3;
case 3:
v3 = can_move_tetmino((__int64)a1, a2, 1);
a1[3] += v3;
goto LABEL_3;
case 4:
v3 = can_move_tetmino((__int64)a1, a2, -1);
a1[3] -= v3;
goto LABEL_3;
case 5:
drop((int *)a1, a2, a1[2]);
goto LABEL_10;
case 6:
v4 = drop((int *)a1, a2, 1);
if ( v4 )
{
v3 = 0;
LABEL_5:
result = v4 | v3;
}
else
{
LABEL_10:
a1[4] = 0;
a1[5] = 0;
a1[6] = 0;
result = 1LL;
}
return result;
default:
v3 = 0;
LABEL_3:
v4 = v3;
if ( v3 )
{
a1[5] = 21;
v4 = 0;
}
goto LABEL_5;
}
}

canonical_decompiled_code:
__int64 __fastcall func9(unsigned int *a1, __int64 a2, int a3)
{
unsigned int v3; // eax
int v4; // edx
__int64 result; // rax

switch ( a3 )
{
case 1:
v3 = func3(a1, (unsigned __int16 *)(a2 + 2LL * (int)a1[2]), 1);
goto LABEL_3;
case 2:
v3 = func3(a1, (unsigned __int16 *)(a2 + 2LL * (int)a1[2]), 3);
goto LABEL_3;
case 3:
v3 = func6((__int64)a1, a2, 1);
a1[3] += v3;
goto LABEL_3;
case 4:
v3 = func6((__int64)a1, a2, -1);
a1[3] -= v3;
goto LABEL_3;
case 5:
func8((int *)a1, a2, a1[2]);
goto LABEL_10;
case 6:
v4 = func8((int *)a1, a2, 1);
if ( v4 )
{
v3 = 0;
LABEL_5:
result = v4 | v3;
}
else
{
LABEL_10:
a1[4] = 0;
a1[5] = 0;
a1[6] = 0;
result = 1LL;
}
return result;
default:
v3 = 0;
LABEL_3:
v4 = v3;
if ( v3 )
{
a1[5] = 21;
v4 = 0;
}
goto LABEL_5;
}
}

original_code:
int control_tetmino(struct tetmino *t, const blocks_row *blocks, enum action a)
{
 int moved = 0, dropped = 0, lock = 0;
 switch (a) {
 case ROTATE_CW:
  moved = rotate(t, blocks + t->row, 1);
  break;
 case ROTATE_CCW:
  moved = rotate(t, blocks + t->row, 3);
  break;
 case MOVE_RIGHT:
  t->col += (moved = can_move_tetmino(t, blocks, 1));
  break;
 case MOVE_LEFT:
  t->col -= (moved = can_move_tetmino(t, blocks, -1));
  break;
 case HARDDROP:
  dropped = drop(t, blocks, t->row);
  lock = 1;
  break;
 case SOFTDROP:
  dropped = drop(t, blocks, 1);
  lock = !dropped;
 default:
  break;
 }
 if (lock) {
  t->falling = 0;
  t->lock_delay_move = 0;
  t->lock_delay_step = 0;
  return lock;
 }
 if (moved) {
  t->lock_delay_move = 20 + 1;
 }
 return moved | dropped;
}

canonical_original_code:
int control_tetmino(struct tetmino *t, unsigned short *blocks, enum action a)
{
 int moved = 0; int dropped = 0; int lock = 0;
 switch (a) {
 case ROTATE_CW:
  moved = rotate(t, blocks + t->row, 1);
  break;
 case ROTATE_CCW:
  moved = rotate(t, blocks + t->row, 3);
  break;
 case MOVE_RIGHT:
  t->col += (moved = can_move_tetmino(t, blocks, 1));
  break;
 case MOVE_LEFT:
  t->col -= (moved = can_move_tetmino(t, blocks, -1));
  break;
 case HARDDROP:
  dropped = drop(t, blocks, t->row);
  lock = 1;
  break;
 case SOFTDROP:
  dropped = drop(t, blocks, 1);
  lock = !dropped;
 default:
  break;
 }
 if (lock) {
  t->falling = 0;
  t->lock_delay_move = 0;
  t->lock_delay_step = 0;
  return lock;
 }
 if (moved) {
  t->lock_delay_move = 20 + 1;
 }
 return moved | dropped;
}

variable_types: enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 }

variable_types: moved int

variable_types: dropped int

variable_types: lock int


decompiled_code:
void __fastcall unfloat_tetmino(int *a1, __int64 a2)
{
if ( !a1[4] )
{
drop(a1, a2, a1[7]);
a1[4] = drop_height(a1, a2, 1);
}
}

original_code:
void unfloat_tetmino(struct tetmino *t, const blocks_row *blocks)
{
 if (!t->falling) {
  drop(t, blocks, t->climbed);
  t->falling = drop_height(t, blocks, 1);
 }
}

canonical_original_code:
void unfloat_tetmino(struct tetmino *t, unsigned short *blocks)
{
 if (!t->falling) {
  drop(t, blocks, t->climbed);
  t->falling = drop_height(t, blocks, 1);
 }
}

variable_types:
blocks
unsigned short *


original_code:
int update_tetmino(struct tetmino *t, const blocks_row *blocks, int gravity)
{
 unfloat_tetmino(t, blocks);
 if (!t->falling) {
  if (t->lock_delay_move > 0)
   t->lock_delay_move--;
  if (t->lock_delay_step > 0)
   t->lock_delay_step--;
  return 0;
 }
 if (t->falling > gravity)
  t->falling = gravity;
 t->falling--;
 if (t->falling > 0)
  return 0;
 if (drop(t, blocks, 1)) {
  t->falling = gravity;
  return 1;
 } else {
  t->falling = 0;
  init_lock_delay(t, gravity);
  return 0;
 }
}

canonical_original_code:
int update_tetmino(struct tetmino *t, unsigned short *blocks, int gravity)
{
 unfloat_tetmino(t, blocks);
 if (!t->falling) {
  if (t->lock_delay_move > 0)
   t->lock_delay_move--;
  if (t->lock_delay_step > 0)
   t->lock_delay_step--;
  return 0;
 }
 if (t->falling > gravity)
  t->falling = gravity;
 t->falling--;
 if (t->falling > 0)
  return 0;
 if (drop(t, blocks, 1)) {
  t->falling = gravity;
  return 1;
 } else {
  t->falling = 0;
  init_lock_delay(t, gravity);
  return 0;
 }
}


decompiled_code:
__int64 __fastcall to_wide(unsigned __int8 a1)
{
unsigned int v1; // edx

v1 = a1;
if ( (a1 & 0x80u) != 0 )
{
v1 = -1;
if ( (unsigned int)a1 - 176 <= 0x2F )
{
v1 = (unsigned __int8)extended_b0_0[a1 - 176];
BYTE1(v1) = 37;
}
}
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func0(unsigned __int8 a1)
{
unsigned int v1; // edx

v1 = a1;
if ( (a1 & 0x80u) != 0 )
{
v1 = -1;
if ( (unsigned int)a1 - 176 <= 0x2F )
{
v1 = (unsigned __int8)extended_b0_0[a1 - 176];
BYTE1(v1) = 37;
}
}
return v1;
}

canonical_original_code:
static unsigned int to_wide(int c)
{
 static unsigned char extended_b0[48] = {
  0x91, 0x92, 0x93, 0x02, 0x24, 0x61, 0x62, 0x56,
  0x55, 0x63, 0x51, 0x57, 0x5d, 0x5c, 0x5b, 0x10,
  0x14, 0x34, 0x2c, 0x1c, 0x00, 0x3c, 0x5e, 0x5f,
  0x5a, 0x54, 0x69, 0x66, 0x60, 0x50, 0x6c, 0x67,
  0x68, 0x64, 0x65, 0x59, 0x58, 0x52, 0x53, 0x6b,
  0x6a, 0x18, 0x0c, 0x88, 0x84, 0x8c, 0x90, 0x80
 };
 int codepoint = (unsigned char) c;
 if (codepoint < 128)
  return codepoint;
 if (codepoint >= 0xb0 && codepoint < 0xe0)
  return extended_b0[codepoint - 0xb0] | 0x2500;
 return (0xffffffffu);
}

variable_types: c int

variable_types: codepoint int


decompiled_code:
void __fastcall puttext_unicode(unsigned __int8 *a1)
{
unsigned __int8 *v1; // rbx
char v2[40]; // [rsp+0h] [rbp-28h] BYREF

v1 = a1;
while ( *v1 )
{
v1 += (int)convert_text(v1, v2, 0x14uLL);
fputs(v2, stdout);
}
}

canonical_decompiled_code:
void __fastcall func2(unsigned __int8 *a1)
{
unsigned __int8 *v1; // rbx
char v2[40]; // [rsp+0h] [rbp-28h] BYREF

v1 = a1;
while ( *v1 )
{
v1 += (int)func1(v1, v2, 0x14uLL);
fputs(v2, stdout);
}
}

original_code:
void puttext_unicode(const char *s)
{
 char buf[20];
 while (*s) {
  s += convert_text(s, buf, sizeof(buf));
  fputs(buf, stdout);
 }
}

canonical_original_code:
void puttext_unicode(char *s)
{
 char buf[20];
 while (*s) {
  s += convert_text(s, buf, sizeof(buf));
  fputs(buf, stdout);
 }
}

variable_types:
s
char *

variable_types:
buf
char [20]


decompiled_code:
void __fastcall catch_signal(int a1)
{
signal_caught = a1;
}

canonical_decompiled_code:
void __fastcall func0(int a1)
{
signal_caught = a1;
}

original_code:
static void catch_signal(int sig)
{
 signal_caught = sig;
}

variable_types: sig int


decompiled_code:
_BOOL8 is_linux_console()
{
char *v0; // rsi
_BOOL8 result; // rax

v0 = getenv("TERM");
result = 0LL;
if ( v0 )
result = strcmp(v0, "linux") == 0;
return result;
}

canonical_decompiled_code:
_BOOL8 func1()
{
char *v0; // rsi
_BOOL8 result; // rax

v0 = getenv("TERM");
result = 0LL;
if ( v0 )
result = strcmp(v0, "linux") == 0;
return result;
}

original_code:
static int is_linux_console()
{
 char *s = getenv("TERM");
 return s && !strcmp(s, "linux");
}


decompiled_code:
bool detect_charset()
{
bool v0; // zf
_BOOL4 v1; // eax

v0 = strcmp(nl_langinfo(14), "UTF-8") == 0;
LOBYTE(v1) = !v0;
if ( v0 )
{
terminal[2] = &puttext_unicode;
terminal[1] = &putacs_text;
}
else
{
v1 = is_linux_console();
if ( v1 )
terminal[1] = &putacs_text;
}
return v1;
}

canonical_decompiled_code:
bool func2()
{
bool v0; // zf
_BOOL4 v1; // eax

v0 = strcmp(nl_langinfo(14), "UTF-8") == 0;
LOBYTE(v1) = !v0;
if ( v0 )
{
terminal[2] = &puttext_unicode;
terminal[1] = &putacs_text;
}
else
{
v1 = func1();
if ( v1 )
terminal[1] = &putacs_text;
}
return v1;
}

original_code:
static void detect_charset()
{
 if (!strcmp(nl_langinfo(CODESET), "UTF-8")) {
  terminal.puttext = puttext_unicode;
  terminal.putacs = putacs_text;
 } else if (is_linux_console()) {
  terminal.putacs = putacs_text;
 }
}


decompiled_code:
int wait_one_frame()
{
int *v0; // rax
fd_set v2; // [rsp+0h] [rbp-98h] BYREF
struct timeval timeout; // [rsp+80h] [rbp-18h] BYREF

timeout.tv_sec = 0LL;
memset(&v2, 0, sizeof(v2));
v2.fds_bits[0] |= 1uLL;
timeout.tv_usec = 16666LL;
LODWORD(v0) = select(1, &v2, 0LL, 0LL, &timeout);
if ( (int)v0 < 0 )
{
v0 = _errno_location();
if ( *v0 != 4 )
{
print_error("select");
restore_terminal();
exit(1);
}
}
return (int)v0;
}

canonical_decompiled_code:
int func3()
{
int *v0; // rax
fd_set v2; // [rsp+0h] [rbp-98h] BYREF
struct timeval timeout; // [rsp+80h] [rbp-18h] BYREF

timeout.tv_sec = 0LL;
memset(&v2, 0, sizeof(v2));
v2.fds_bits[0] |= 1uLL;
timeout.tv_usec = 16666LL;
LODWORD(v0) = select(1, &v2, 0LL, 0LL, &timeout);
if ( (int)v0 < 0 )
{
v0 = _errno_location();
if ( *v0 != 4 )
{
print_error("select");
restore_terminal();
exit(1);
}
}
return (int)v0;
}

original_code:
static void wait_one_frame()
{
 struct timeval timeout = {0};
 fd_set fds;
 do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&fds)->__fds_bits)[0]) : "memory"); } while (0);
 ((void) (((&fds)->__fds_bits)[((0) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((0) % (8 * (int) sizeof (__fd_mask)))))));
 timeout.tv_usec = (1000000L / 60);
 if (select(0 + 1, &fds, ((void *)0), ((void *)0), &timeout) < 0) {
  if ((*__errno_location ()) != 4) {
   print_error("select");
   restore_terminal();
   exit(1);
  }
 }
}

canonical_original_code:
static void wait_one_frame()
{
 struct timeval timeout = {0};
 struct fd_set fds;
 do { int __d0; int __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&fds)->__fds_bits)[0]) : "memory"); } while (0);
 ((void) (((&fds)->__fds_bits)[((0) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((0) % (8 * (int) sizeof (__fd_mask)))))));
 timeout.tv_usec = (1000000L / 60);
 if (select(0 + 1, &fds, ((void *)0), ((void *)0), &timeout) < 0) {
  if ((*__errno_location ()) != 4) {
   print_error("select");
   restore_terminal();
   exit(1);
  }
 }
}

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

variable_types:
fds
struct fd_set { long __fds_bits[-1]; }


decompiled_code:
__int64 run_game_loop()
{
__int64 *v0; // rbx
__int64 result; // rax
_BYTE v2[848]; // [rsp+0h] [rbp-388h] BYREF
__int64 v3[7]; // [rsp+350h] [rbp-38h] BYREF

v3[0] = 0LL;
v3[1] = 0LL;
v3[2] = 0LL;
v3[3] = 0LL;
v3[4] = 0LL;
init_game(v2, 20LL);
signal(2, catch_signal);
signal(15, catch_signal);
signal(18, catch_signal);
signal(20, catch_signal);
signal(28, catch_signal);
v0 = v3;
while ( 1 )
{
result = update_game(v2, v0);
if ( !(_DWORD)result )
break;
wait_one_frame();
process_signal();
v0 = (__int64 *)read_terminal_keypress(v3);
process_signal();
}
return result;
}

canonical_decompiled_code:
__int64 func5()
{
__int64 *v0; // rbx
__int64 result; // rax
_BYTE v2[848]; // [rsp+0h] [rbp-388h] BYREF
__int64 v3[7]; // [rsp+350h] [rbp-38h] BYREF

v3[0] = 0LL;
v3[1] = 0LL;
v3[2] = 0LL;
v3[3] = 0LL;
v3[4] = 0LL;
init_game(v2, 20LL);
signal(2, catch_signal);
signal(15, catch_signal);
signal(18, catch_signal);
signal(20, catch_signal);
signal(28, catch_signal);
v0 = v3;
while ( 1 )
{
result = update_game(v2, v0);
if ( !(_DWORD)result )
break;
func3();
func4();
v0 = (__int64 *)read_terminal_keypress(v3);
func4();
}
return result;
}

original_code:
static void run_game_loop()
{
 struct terminal_input input = {{""}};
 const char *keypress = input.current.s;
 struct game game;
 init_game(&game, 20);
 signal(2, catch_signal);
 signal(15, catch_signal);
 signal(18, catch_signal);
 signal(20, catch_signal);
 signal(28, catch_signal);
 while (update_game(&game, keypress)) {
  wait_one_frame();
  process_signal();
  keypress = read_terminal_keypress(&input);
  process_signal();
 }
}

canonical_original_code:
static void run_game_loop()
{
 struct terminal_input input = {{""}};
 char *keypress = input.current.s;
 struct game game;
 init_game(&game, 20);
 signal(2, catch_signal);
 signal(15, catch_signal);
 signal(18, catch_signal);
 signal(20, catch_signal);
 signal(28, catch_signal);
 while (update_game(&game, keypress)) {
  wait_one_frame();
  process_signal();
  keypress = read_terminal_keypress(&input);
  process_signal();
 }
}

variable_types: struct terminal_input { struct terminal_seq_buffer { char s[16]; } current; unsigned long next_length; }

variable_types:
keypress
char *

variable_types: struct game { struct tetgrid { int cols; int clearing; int delay; unsigned short blocks[24]; } tetgrid; struct tetfield { struct tetmino { unsigned int shape; int piece; int row; int falling; int lock_delay_move; int lock_delay_step; int climbed; } mino; struct tetgrid *grid; int gravity; enum { TETFIELD_SPAWN=0, TETFIELD_MOVE=1, TETFIELD_PLACED=2, TETFIELD_TOP_OUT=3 } state; enum action { NO_ACTION=0, ROTATE_CW=1, ROTATE_CCW=2, MOVE_RIGHT=3, MOVE_LEFT=4, HARDDROP=5, SOFTDROP=6, END_ACTION=7 } last_action; unsigned char timeout[-1]; unsigned long score; unsigned int pieces; } tetfield; struct tetmino next_tetmino; struct tetmino_piece { struct piece { struct copyrect { int width; int di; } r; unsigned char piece[-1]; struct piece *prev; } piece; struct tetmino *tetmino; int mask; struct tetmino_piece *succ; } piece; struct blocks { struct bitmap { unsigned char *bitmap; int width; int height; } bitmap; struct tg_tiles { char chars[16]; unsigned short attrs[16]; } tiles; int x; int rendered; } blocks; unsigned char bitmap[-1]; }


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // edx
int result; // eax
unsigned int v5; // edi

setlocale(0, &locale);
v3 = init_terminal();
result = 1;
if ( v3 )
{
detect_charset();
v5 = time(0LL);
srandom(v5);
run_game_loop();
restore_terminal();
result = 0;
}
return result;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // edx
int result; // eax
unsigned int v5; // edi

setlocale(0, &locale);
v3 = init_terminal();
result = 1;
if ( v3 )
{
func2();
v5 = time(0LL);
srandom(v5);
func5();
restore_terminal();
result = 0;
}
return result;
}

original_code:
int main(int argc, char **argv)
{
 setlocale(0, "");
 if (!init_terminal()) {
  return 1;
 }
 detect_charset();
 srandom(time(((void *)0)));
 run_game_loop();
 restore_terminal();
 return 0;
}

variable_types: argc int

variable_types:
argv
char **


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

switch ( a1 )
{
case 'a':
result = 4294967217LL;
break;
case 'h':
result = 4294967216LL;
break;
case 'j':
result = 4294967257LL;
break;
case 'k':
result = 4294967231LL;
break;
case 'l':
result = 4294967258LL;
break;
case 'm':
result = 4294967232LL;
break;
case 'n':
result = 4294967237LL;
break;
case 'q':
result = 4294967236LL;
break;
case 't':
result = 4294967235LL;
break;
case 'u':
result = 4294967220LL;
break;
case 'v':
result = 4294967233LL;
break;
case 'w':
result = 4294967234LL;
break;
case 'x':
result = 4294967219LL;
break;
default:
result = a1;
break;
}
return result;
}

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

switch ( a1 )
{
case 'a':
result = 4294967217LL;
break;
case 'h':
result = 4294967216LL;
break;
case 'j':
result = 4294967257LL;
break;
case 'k':
result = 4294967231LL;
break;
case 'l':
result = 4294967258LL;
break;
case 'm':
result = 4294967232LL;
break;
case 'n':
result = 4294967237LL;
break;
case 'q':
result = 4294967236LL;
break;
case 't':
result = 4294967235LL;
break;
case 'u':
result = 4294967220LL;
break;
case 'v':
result = 4294967233LL;
break;
case 'w':
result = 4294967234LL;
break;
case 'x':
result = 4294967219LL;
break;
default:
result = a1;
break;
}
return result;
}

original_code:
static int acs_to_text(int c)
{
 switch (c) {
 case 'a': return TEXT_MEDIUM_SHADE;
 case 'h': return TEXT_LIGHT_SHADE;
 case 'j': return TEXT_LOWER_RIGHT_CORNER;
 case 'k': return TEXT_UPPER_RIGHT_CORNER;
 case 'l': return TEXT_UPPER_LEFT_CORNER;
 case 'm': return TEXT_LOWER_LEFT_CORNER;
 case 'n': return TEXT_CROSS;
 case 'q': return TEXT_HORIZONTAL_LINE;
 case 't': return TEXT_LEFT_T;
 case 'u': return TEXT_RIGHT_T;
 case 'v': return TEXT_BOTTOM_T;
 case 'w': return TEXT_TOP_T;
 case 'x': return TEXT_VERTICAL_LINE;
 }
 return c;
}


decompiled_code:
void __fastcall putacs_text(char *a1)
{
char *v1; // rbx
_BYTE v2[40]; // [rsp+0h] [rbp-28h] BYREF

v1 = a1;
while ( *v1 )
{
v1 += (int)convert_chars(v1, (__int64)v2, 20LL);
terminal[2](v2);
}
}

canonical_decompiled_code:
void __fastcall func2(char *a1)
{
char *v1; // rbx
_BYTE v2[40]; // [rsp+0h] [rbp-28h] BYREF

v1 = a1;
while ( *v1 )
{
v1 += (int)func1(v1, (__int64)v2, 20LL);
terminal[2](v2);
}
}

original_code:
void putacs_text(const char *s)
{
 char buf[20];
 while (*s) {
  s += convert_chars(s, buf, sizeof(buf));
  terminal.puttext(buf);
 }
}

canonical_original_code:
void putacs_text(char *s)
{
 char buf[20];
 while (*s) {
  s += convert_chars(s, buf, sizeof(buf));
  terminal.puttext(buf);
 }
}


decompiled_code:
__int64 rand7()
{
__int64 v0; // rdx
__int64 result; // rax

do
{
v0 = random() / 306783378;
result = (unsigned int)v0;
}
while ( (int)v0 > 6 );
return result;
}

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

do
{
v0 = random() / 306783378;
result = (unsigned int)v0;
}
while ( (int)v0 > 6 );
return result;
}

variable_types: x int


original_code:
int centre_text(const char *s, int w, int x, int y)
{
 char buf[80] = " ";
 int len = strcspn(strncat(buf, s, 72), "\n\t");
 buf[len++] = ' ';
 buf[len] = '\0';
 if (w - len > 0)
  x += (w - len)/2;
 moveto(x, y);
 terminal.puttext(buf);
 terminal.cursor_x += len;
 return len - 2;
}

canonical_original_code:
int centre_text(char *s, int w, int x, int y)
{
 char buf[80] = " ";
 int len = strcspn(strncat(buf, s, 72), "\n\t");
 buf[len++] = ' ';
 buf[len] = '\0';
 if (w - len > 0)
  x += (w - len)/2;
 moveto(x, y);
 terminal.puttext(buf);
 terminal.cursor_x += len;
 return len - 2;
}

variable_types: w int

variable_types: y int

variable_types:
buf
char [80]

variable_types: len int