Task

Implement a 2D sliding block puzzle game where blocks with numbers are combined to add their values.



Rules of the game

   The rules are that on each turn the player must choose a direction   (up, down, left or right).
   All tiles move as far as possible in that direction, some move more than others. 
   Two adjacent tiles (in that direction only) with matching numbers combine into one bearing the sum of those numbers. 
   A move is valid when at least one tile can be moved,   if only by combination. 
   A new tile with the value of   2   is spawned at the end of each turn at a randomly chosen empty square   (if there is one). 
   Adding a new tile on a blank space.   Most of the time,   a new   2   is to be added,   and occasionally   (10% of the time),   a   4.
   To win,   the player must create a tile with the number   2048. 
   The player loses if no valid moves are possible.


The name comes from the popular open-source implementation of this game mechanic, 2048.



Requirements

   "Non-greedy" movement.   
  The tiles that were created by combining other tiles should not be combined again during the same turn (move).   
  That is to say,   that moving the tile row of:
               [2][2][2][2] 

 to the right should result in: 
               ......[4][4] 

 and not:
               .........[8] 

   "Move direction priority".   
  If more than one variant of combining is possible,   move direction shall indicate which combination will take effect. 
  For example, moving the tile row of:
               ...[2][2][2] 

 to the right should result in:
               ......[2][4] 

 and not:
               ......[4][2] 



   Check for valid moves.   The player shouldn't be able to skip their turn by trying a move that doesn't change the board.
   Check for a  win condition.
   Check for a lose condition.


 
/* ARM assembly Raspberry PI  */
/*  program 2048.s   */ 
 
/* REMARK 1 : this program use routines in a include file 
   see task Include a file language arm assembly 
   for the routine affichageMess conversion10 
   see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"
.equ STDIN,      0    @ Linux input console
.equ READ,       3    @ Linux syscall
.equ SIZE,       4       
.equ TOTAL,      2048
.equ BUFFERSIZE, 80
 
.equ IOCTL,     0x36  @ Linux syscall
.equ SIGACTION, 0x43  @ Linux syscall
.equ SYSPOLL,   0xA8  @ Linux syscall
 
.equ TCGETS,    0x5401
.equ TCSETS,    0x5402
.equ ICANON,    2
.equ ECHO,     10
.equ POLLIN,    1
 
.equ SIGINT,   2      @ Issued if the user sends an interrupt signal (Ctrl + C)
.equ SIGQUIT,  3      @ Issued if the user sends a quit signal (Ctrl + D)
.equ SIGTERM, 15      @ Software termination signal (sent by kill by default)
.equ SIGTTOU, 22
 
/*******************************************/
/* Structures                               */
/********************************************/
/* structure termios see doc linux*/
    .struct  0
term_c_iflag:                    @ input modes
    .struct  term_c_iflag + 4 
term_c_oflag:                    @ output modes
    .struct  term_c_oflag + 4 
term_c_cflag:                    @ control modes
    .struct  term_c_cflag + 4 
term_c_lflag:                    @ local modes
    .struct  term_c_lflag + 4 
term_c_cc:                       @ special characters
    .struct  term_c_cc + 20      @ see length if necessary 
term_fin:
 
/* structure sigaction see doc linux */
    .struct  0
sa_handler:
    .struct  sa_handler + 4 
sa_mask:
    .struct  sa_mask + 4 
sa_flags:
    .struct  sa_flags + 4 
sa_sigaction:
    .struct  sa_sigaction + 4 
sa_fin:
 
/* structure poll see doc linux */
    .struct  0
poll_fd:                            @   File Descriptor
    .struct  poll_fd + 4 
poll_events:                        @  events mask
    .struct  poll_events + 4 
poll_revents:                       @ events returned
    .struct  poll_revents + 4 
poll_fin:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessOK:           .asciz "Bravo !! You win. \n"
szMessNotOK:        .asciz "You lost !! \n"
szMessNewGame:      .asciz "New game (y/n) ? \n"
szMessErreur:       .asciz "Error detected.\n"
szCarriageReturn:   .asciz "\n"
//szMessMovePos:             .asciz "\033[00;00H"
szMess0:            .asciz "      "
szMess2:            .asciz "   2  "
szMess4:            .asciz "   4  "
szMess8:            .asciz "   8  "
szMess16:           .asciz "  16  "
szMess32:           .asciz "  32  "
szMess64:           .asciz "  64  "
szMess128:          .asciz " 128  "
szMess256:          .asciz " 256  "
szMess512:          .asciz " 512  "
szMess1024:         .asciz " 1024 "
szMess2048:         .asciz " 2048 "
szClear1:           .byte 0x1B 
                    .byte 'c'           @ other console clear
                    .byte 0
 
szLineH:            .asciz "-----------------------------\n"
szLineV:            .asciz "|"
szLineVT:           .asciz "|      |      |      |      |\n"
.align 4
iGraine:            .int 123456
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:      .skip 24
sBuffer:        .skip BUFFERSIZE
iTbCase:        .skip 4 * SIZE * SIZE
iEnd:           .skip 4                        @ 0 loop  1 = end loop
iTouche:        .skip 4                        @ value key pressed
stOldtio:       .skip term_fin                 @ old terminal state
stCurtio:       .skip term_fin                 @ current terminal state
stSigAction:    .skip sa_fin                   @ area signal structure
stSigAction1:   .skip sa_fin
stPoll1:        .skip poll_fin                 @ area poll structure
stPoll2:        .skip poll_fin
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                 @ entry of program 
 
1:                                    @ begin game loop
    ldr r0,iAdrszClear1
    bl affichageMess
    bl razTable
2:
    bl addDigit   
    cmp r0,#-1
    beq 5f                            @ end game
    bl displayGame
3:
    bl readKey
    cmp r0,#-1
    beq 100f                          @ error or control-c
    bl keyMove
    cmp r0,#0
    beq 3b                            @ no change -> loop
    cmp r0,#2                         @ last addition = 2048 ?
    beq 4f
    cmp r0,#-1                        @ quit ?
    bne 2b                            @ loop
 
    b 10f
4:                                    @ last addition = 2048 
    ldr r0,iAdrszMessOK
    bl affichageMess
    b 10f
5:                                    @ display message no solution
    ldr r0,iAdrszMessNotOK
    bl affichageMess
 
10:                                   @ display new game ?
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    ldr r0,iAdrszMessNewGame
    bl affichageMess
    bl readKey
    ldr r0,iAdriTouche
    ldrb r0,[r0]
    cmp r0,#'y'
    beq 1b
    cmp r0,#'Y'
    beq 1b
 
100:                                  @ standard end of the program 
    mov r0, #0                        @ return code
    mov r7, #EXIT                     @ request to exit program
    svc #0                            @ perform the system call
 
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrszMessNotOK:          .int szMessNotOK
iAdrszMessOK:             .int szMessOK
iAdrszMessNewGame:        .int szMessNewGame
iAdrsZoneConv:            .int sZoneConv
iAdrszClear1:             .int szClear1
/******************************************************************/
/*     raz table cases                                                   */ 
/******************************************************************/
razTable:
    push {r0-r2,lr}                  @ save  registers
    ldr r1,iAdriTbCase
    mov r0,#0
    mov r2,#0
1:
    str r0,[r1,r2,lsl #2]
    add r2,r2,#1
    cmp r2,#SIZE * SIZE
    blt 1b
100:
    pop {r0-r2,lr}                   @ restaur registers 
    bx lr                            @return
/******************************************************************/
/*     key move                                                   */ 
/******************************************************************/
/* r0 contains key value               */
keyMove:
    push {r1,lr}                  @ save  registers
    cmp r0,#0x42                  @ down arrow 
    bne 1f
    bl moveDown
    b 100f
1:
    cmp r0,#0x41                  @ high arrow
    bne 2f
    bl moveUp
    b 100f
2:
    cmp r0,#0x43                  @ right arrow
    bne 3f
    bl moveRight
    b 100f
3:
    cmp r0,#0x44                  @ left arrow
    bne 4f
    bl moveLeft
    b 100f
4:
    ldr r0,iAdriTouche
    ldrb r0,[r0]
    cmp r0,#'q'                   @ quit game
    bne 5f
    mov r0,#-1
    b 100f
5:
    cmp r0,#'Q'                   @ quit game
    bne 100f
    mov r0,#-1
    b 100f
 
100:
    pop {r1,lr}                   @ restaur registers 
    bx lr                         @return
/******************************************************************/
/*           move left                                   */ 
/******************************************************************/
/* r0 return -1 if ok     */
moveLeft:
    push {r1-r10,lr}            @ save registers
    ldr r1,iAdriTbCase
    mov r0,#0                   @ top move Ok
    mov r2,#0                   @ line indice
1:
    mov r6,#0                   @ counter empty case
    mov r7,#0                   @ first digit
    mov r10,#0                  @ last digit to add
    mov r3,#0                   @ column indice
2:
    lsl r5,r2,#2                @ change this if size <> 4
    add r5,r5,r3                @ compute table indice
    ldr r4,[r1,r5,lsl #2]
    cmp r4,#0
    addeq r6,r6,#1              @ positions vides
    beq 5f
    cmp r6,#0
    beq 3f                      @ no empty left case
    mov r8,#0
    str r8,[r1,r5,lsl #2]       @ raz digit
    sub r5,r5,r6
    str r4,[r1,r5,lsl #2]       @ and store to left empty position
    mov r0,#1                   @ move Ok
    //sub r6,r6,#1
3:
    cmp r7,#0                   @ first digit
    beq 4f
    cmp r10,r4                  @ prec digit have to add 
    beq 4f
    sub r8,r5,#1                @ prec digit 
    ldr r9,[r1,r8,lsl #2]
    cmp r4,r9                   @ equal ?
    bne 4f
    mov r10,r4                  @ save digit 
    add r4,r4,r9                @ yes -> add
    str r4,[r1,r8,lsl #2]
    cmp r4,#TOTAL
    moveq r0,#2
    beq 100f
    mov r4,#0
    str r4,[r1,r5,lsl #2]
    add r6,r6,#1                @ empty case + 1
    mov r0,#1                   @ move Ok
4:
    add r7,r7,#1                @ no first digit
 
5:                              @ and loop
    add r3,r3,#1
    cmp r3,#SIZE
    blt 2b
    add r2,r2,#1
    cmp r2,#SIZE
    blt 1b
100:
    pop {r1-r12,lr}
    bx lr                       @ return 
/******************************************************************/
/*           move right                                   */ 
/******************************************************************/
/* r0 return -1 if ok     */
moveRight:
    push {r1-r5,lr}                @ save registers
    ldr r1,iAdriTbCase
    mov r0,#0
    mov r2,#0
1:
    mov r6,#0
    mov r7,#0
    mov r10,#0
    mov r3,#SIZE-1
2:
    lsl r5,r2,#2                  @ change this if size <> 4
    add r5,r5,r3
    ldr r4,[r1,r5,lsl #2]
    cmp r4,#0
    addeq r6,r6,#1                @ positions vides
    beq 5f
 
    cmp r6,#0
    beq 3f                      @ no empty right case
    mov r0,#0
    str r0,[r1,r5,lsl #2]       @ raz digit
    add r5,r5,r6
    str r4,[r1,r5,lsl #2]       @ and store to right empty position
    mov r0,#1
3:
    cmp r7,#0                   @ first digit
    beq 4f
    add r8,r5,#1                @ next digit 
    ldr r9,[r1,r8,lsl #2]
    cmp r4,r9                   @ equal ?
    bne 4f
    cmp r10,r4
    beq 4f
    mov r10,r4
    add r4,r4,r9                @ yes -> add
    str r4,[r1,r8,lsl #2]
    cmp r4,#TOTAL
    moveq r0,#2
    beq 100f
    mov r4,#0
    str r4,[r1,r5,lsl #2]
    add r6,r6,#1                @ empty case + 1
    mov r0,#1
4:
    add r7,r7,#1                @ no first digit
 
5:                              @ and loop
    sub r3,r3,#1
    cmp r3,#0
    bge 2b
    add r2,r2,#1
    cmp r2,#SIZE
    blt 1b
 
100:
    pop {r1-r5,lr}
    bx lr                          @ return 
/******************************************************************/
/*           move down                                   */ 
/******************************************************************/
/* r0 return -1 if ok     */
moveDown:
    push {r1-r5,lr}                @ save registers
    ldr r1,iAdriTbCase
    mov r0,#0
    mov r3,#0
1:
    mov r6,#0
    mov r7,#0
    mov r10,#0
    mov r2,#SIZE-1
2:
    lsl r5,r2,#2                  @ change this if size <> 4
    add r5,r5,r3
    ldr r4,[r1,r5,lsl #2]
    cmp r4,#0
    addeq r6,r6,#1                @ positions vides
    beq 5f
    cmp r6,#0
    beq 3f                      @ no empty right case
    mov r0,#0
    str r0,[r1,r5,lsl #2]       @ raz digit
    lsl r0,r6,#2
    add r5,r5,r0
    str r4,[r1,r5,lsl #2]       @ and store to right empty position
    mov r0,#1
3:
    cmp r7,#0                   @ first digit
    beq 4f
    add r8,r5,#SIZE                @ down digit 
    ldr r9,[r1,r8,lsl #2]
    cmp r4,r9                   @ equal ?
    bne 4f
    cmp r10,r4
    beq 4f
    mov r10,r4
    add r4,r4,r9                @ yes -> add
    str r4,[r1,r8,lsl #2]
    cmp r4,#TOTAL
    moveq r0,#2
    beq 100f
    mov r4,#0
    str r4,[r1,r5,lsl #2]
    add r6,r6,#1                @ empty case + 1
    mov r0,#1
4:
    add r7,r7,#1                   @ no first digit
 
5:                           @ and loop
    sub r2,r2,#1
    cmp r2,#0
    bge 2b
    add r3,r3,#1
    cmp r3,#SIZE
    blt 1b
 
100:
    pop {r1-r5,lr}
    bx lr                          @ return 
/******************************************************************/
/*           move up                                   */ 
/******************************************************************/
/* r0 return -1 if ok     */
moveUp:
    push {r1-r5,lr}                @ save registers
    ldr r1,iAdriTbCase
    mov r0,#0
    mov r3,#0
1:
    mov r6,#0
    mov r7,#0
    mov r10,#0
    mov r2,#0
2:
    lsl r5,r2,#2                  @ change this if size <> 4
    add r5,r5,r3
    ldr r4,[r1,r5,lsl #2]
    cmp r4,#0
    addeq r6,r6,#1                @ positions vides
    beq 5f
    cmp r6,#0
    beq 3f                      @ no empty right case
    mov r0,#0
    str r0,[r1,r5,lsl #2]       @ raz digit
    lsl r0,r6,#2
    sub r5,r5,r0
    str r4,[r1,r5,lsl #2]       @ and store to right empty position
    mov r0,#1
3:
    cmp r7,#0                   @ first digit
    beq 4f
    sub r8,r5,#SIZE             @ up digit 
    ldr r9,[r1,r8,lsl #2]
    cmp r4,r9                   @ equal ?
    bne 4f
    cmp r10,r4
    beq 4f
    mov r10,r4
    add r4,r4,r9                @ yes -> add
    str r4,[r1,r8,lsl #2]
    cmp r4,#TOTAL
    moveq r0,#2
    beq 100f
    mov r4,#0
    str r4,[r1,r5,lsl #2]
    add r6,r6,#1                @ empty case + 1
    mov r0,#1
4:
    add r7,r7,#1                @ no first digit
 
5:                              @ and loop
    add r2,r2,#1
    cmp r2,#SIZE
    blt 2b
    add r3,r3,#1
    cmp r3,#SIZE
    blt 1b
 
100:
    pop {r1-r5,lr}
    bx lr                          @ return 
/******************************************************************/
/*           add new digit on game                                   */ 
/******************************************************************/
/* r0 return -1 if ok     */
addDigit:
    push {r1-r5,lr}                @ save registers
    sub sp,#4 * SIZE*SIZE
    mov fp,sp
 
    mov r0,#100
    bl genereraleas
    cmp r0,#10
    movlt r5,#4
    movge r5,#2
    ldr r1,iAdriTbCase
    mov r3,#0
    mov r4,#0
1:  
    ldr r2,[r1,r3,lsl #2]
    cmp r2,#0
    bne 2f
    str r3,[fp,r4,lsl #2]
    add r4,r4,#1
2:
    add r3,r3,#1
    cmp r3,#SIZE*SIZE
    blt 1b
    cmp r4,#0              @ no empty case
    moveq r0,#-1
    beq 100f
    cmp r4,#1             
    bne 3f
    ldr r2,[fp]            @ one case
    str r5,[r1,r2,lsl #2]
    mov r0,#0
    b 100f
3:                         @ multiple case
    sub r0,r4,#1
    bl genereraleas
    ldr r2,[fp,r0,lsl #2]
    str r5,[r1,r2,lsl #2]
    mov r0,#0
 
100:
    add sp,#4*  (SIZE*SIZE)    @ stack alignement
    pop {r1-r5,lr}
    bx lr                      @ return 
iAdriTbCase:         .int iTbCase
/******************************************************************/
/*            display game                                      */ 
/******************************************************************/
displayGame:
    push {r1-r3,lr}            @ save registers
    ldr r0,iAdrszClear1
    bl affichageMess
    ldr r0,iAdrszLineH
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
    ldr r1,iAdriTbCase
    mov r2,#0
1:
    ldr r0,[r1,r2,lsl #2]
    bl digitString
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
    add r2,r2,#1
    cmp r2,#SIZE
    blt 1b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineH
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
2:
    ldr r0,[r1,r2,lsl #2]
    bl digitString
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
    add r2,r2,#1
    cmp r2,#SIZE*2
    blt 2b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineH
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
3:
    ldr r0,[r1,r2,lsl #2]
    bl digitString
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
    add r2,r2,#1
    cmp r2,#SIZE*3
    blt 3b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineH
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
4:
    ldr r0,[r1,r2,lsl #2]
    bl digitString
    bl affichageMess
    ldr r0,iAdrszLineV
    bl affichageMess
    add r2,r2,#1
    cmp r2,#SIZE*4
    blt 4b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    ldr r0,iAdrszLineVT
    bl affichageMess
    ldr r0,iAdrszLineH
    bl affichageMess
 
100:
    pop {r1-r3,lr}
    bx lr                       @ return 
iAdrszLineH:         .int szLineH
iAdrszLineV:         .int szLineV
iAdrszLineVT:        .int szLineVT
//iAdrszMessMovePos:   .int szMessMovePos
/******************************************************************/
/*            digits string                                       */ 
/******************************************************************/
/* r0 contains number */
/* r0 return address string */
digitString:
    push {r1,lr}        @ save registers
    cmp r0,#0
    bne 1f
    ldr r0,iAdrszMess0
    b 100f
1:
    cmp r0,#2
    bne 2f
    ldr r0,iAdrszMess2
    b 100f
2:
    cmp r0,#4
    bne 3f
    ldr r0,iAdrszMess4
    b 100f
3:
    cmp r0,#8
    bne 4f
    ldr r0,iAdrszMess8
    b 100f
4:
    cmp r0,#16
    bne 5f
    ldr r0,iAdrszMess16
    b 100f
5:
    cmp r0,#32
    bne 6f
    ldr r0,iAdrszMess32
    b 100f
6:
    cmp r0,#64
    bne 7f
    ldr r0,iAdrszMess64
    b 100f
7:
    cmp r0,#128
    bne 8f
    ldr r0,iAdrszMess128
    b 100f
8:
    cmp r0,#256
    bne 9f
    ldr r0,iAdrszMess256
    b 100f
9:
    cmp r0,#512
    bne 10f
    ldr r0,iAdrszMess512
    b 100f
10:
    cmp r0,#1024
    bne 11f
    ldr r0,iAdrszMess1024
    b 100f
11:
    cmp r0,#2048
    bne 12f
    ldr r0,iAdrszMess2048
    b 100f
12:
    ldr r1,iAdrszMessErreur                       @ error message
    bl   displayError
100:
    pop {r1,lr}
    bx lr                   @ return 
iAdrszMess0:          .int szMess0
iAdrszMess2:          .int szMess2
iAdrszMess4:          .int szMess4
iAdrszMess8:          .int szMess8
iAdrszMess16:         .int szMess16
iAdrszMess32:         .int szMess32
iAdrszMess64:         .int szMess64
iAdrszMess128:        .int szMess128
iAdrszMess256:        .int szMess256
iAdrszMess512:        .int szMess512
iAdrszMess1024:       .int szMess1024
iAdrszMess2048:        .int szMess2048
 
//iAdrsBuffer:         .int sBuffer
/***************************************************/
/*   Generation random number                  */
/***************************************************/
/* r0 contains limit  */
genereraleas:
    push {r1-r4,lr}         @ save registers 
    ldr r4,iAdriGraine
    ldr r2,[r4]
    ldr r3,iNbDep1
    mul r2,r3,r2
    ldr r3,iNbDep2
    add r2,r2,r3
    str r2,[r4]             @ maj de la graine pour l appel suivant 
    cmp r0,#0
    beq 100f
    add r1,r0,#1            @ divisor
    mov r0,r2               @ dividende
    bl division
    mov r0,r3               @ résult = remainder
 
100:                        @ end function
    pop {r1-r4,lr}          @ restaur registers
    bx lr                   @ return
/*****************************************************/
iAdriGraine: .int iGraine
iNbDep1:     .int 0x343FD
iNbDep2:     .int 0x269EC3 
/***************************************************/
/* read touch                                      */
/***************************************************/
readKey:
    push {r1-r7,lr}
    mov r5,#0
    ldr r1,iAdriTouche                            @ buffer address
    str r5,[r1]                                  @ raz 4 bytes iTouche
    /* read terminal state */
    mov r0,#STDIN                                @ input console
    mov r1,#TCGETS
    ldr r2,iAdrstOldtio
    mov r7, #IOCTL                               @ call system Linux
    svc #0 
    cmp r0,#0                                    @ error ?
    beq 1f
    ldr r1,iAdrszMessErreur                      @ error message
    bl   displayError
    mov r0,#-1
    b 100f
1:
    adr r0,sighandler                            @ adresse routine traitement signal
    ldr r1,iAdrstSigAction                       @ adresse structure sigaction
    str r0,[r1,#sa_handler]                      @ maj handler
    mov r0,#SIGINT                               @ signal type
    ldr r1,iAdrstSigAction
    mov r2,#0                                    @ NULL
    mov r7, #SIGACTION                           @ call system
    svc #0 
    cmp r0,#0                                    @ error ?
    bne 97f
    mov r0,#SIGQUIT
    ldr r1,iAdrstSigAction
    mov r2,#0                                    @ NULL
    mov r7, #SIGACTION                           @ call system 
    svc #0 
    cmp r0,#0                                    @ error ?
    bne 97f
    mov r0,#SIGTERM
    ldr r1,iAdrstSigAction
    mov r2,#0                                    @ NULL
    mov r7, #SIGACTION                           @ appel systeme 
    svc #0 
    cmp r0,#0
    bne 97f
    @
    adr r0,iSIG_IGN                              @ address signal ignore function
    ldr r1,iAdrstSigAction1
    str r0,[r1,#sa_handler]
    mov r0,#SIGTTOU                              @invalidate other process signal
    ldr r1,iAdrstSigAction1
    mov r2,#0                                    @ NULL
    mov r7,#SIGACTION                            @ call system 
    svc #0 
    cmp r0,#0
    bne 97f
    @
    /* read terminal current state  */
    mov r0,#STDIN
    mov r1,#TCGETS
    ldr r2,iAdrstCurtio                          @ address current termio
    mov r7,#IOCTL                                @ call systeme 
    svc #0 
    cmp r0,#0                                    @ error ?
    bne 97f
    mov r2,#ICANON | ECHO                        @ no key pressed echo on display
    mvn r2,r2                                    @ and one key 
    ldr r1,iAdrstCurtio
    ldr r3,[r1,#term_c_lflag]
    and r3,r2                                    @ add flags 
    str r3,[r1,#term_c_lflag]                    @ and store
    mov r0,#STDIN                                @ maj terminal current state 
    mov r1,#TCSETS
    ldr r2,iAdrstCurtio
    mov r7, #IOCTL                               @ call system
    svc #0 
    cmp r0,#0
    bne 97f
    @
2:                                               @ loop waiting key
    ldr r0,iAdriEnd                              @ if signal ctrl-c  -> end
    ldr r0,[r0]
    cmp r0,#0
    movne r5,#-1
    bne 98f
    ldr r0,iAdrstPoll1                            @ address structure poll
    mov r1,#STDIN
    str r1,[r0,#poll_fd]                          @ maj FD
    mov r1,#POLLIN                                @ action code
    str r1,[r0,#poll_events]
    mov r1,#1                                     @ items number structure poll
    mov r2,#0                                     @ timeout = 0 
    mov r7,#SYSPOLL                               @ call system POLL
    svc #0 
    cmp r0,#0                                     @ key pressed ?
    ble 2b                                        @ no key pressed -> loop
                                                  @ read key
    mov r0,#STDIN                                 @ File Descriptor
    ldr r1,iAdriTouche                            @ buffer address
    mov r2,#BUFFERSIZE                            @ buffer size
    mov r7,#READ                                  @ read key
    svc #0
    cmp r0,#0                                     @ error ?
    bgt 98f
 
97:                                               @ error detected
    ldr r1,iAdrszMessErreur                       @ error message
    bl   displayError
    mov r5,#-1
98:                                               @ end then restaur begin state terminal
    mov r0,#STDIN
    mov r1,#TCSETS
    ldr r2,iAdrstOldtio
    mov r7,#IOCTL                                 @ call system  
    svc #0
    cmp r0,#0
    beq 99f                                       @ restaur ok
    ldr r1,iAdrszMessErreur                       @ error message
    bl   displayError
    mov r0,#-1
    b 100f
99:
    cmp r5,#0                                     @ no error or control-c ?
    ldreq r2,iAdriTouche                          @ key address
    ldreqb r0,[r2,#2]                             @ return key byte
    movne r0,r5                                   @ or error
100:
    pop {r1-r7, lr}
    bx lr
iSIG_IGN:                 .int 1
iAdriEnd:                 .int iEnd
iAdrstPoll1:              .int stPoll1
iAdriTouche:              .int iTouche
iAdrstOldtio:             .int stOldtio
iAdrstCurtio:             .int stCurtio
iAdrstSigAction:          .int stSigAction
iAdrstSigAction1:         .int stSigAction1
iAdrszMessErreur :        .int szMessErreur 
/******************************************************************/
/*     traitement du signal                                       */ 
/******************************************************************/
sighandler:
    push {r0,r1}
    ldr r0,iAdriEnd
    mov r1,#1                 @ maj zone end
    str r1,[r0]
    pop {r0,r1}
    bx lr
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
 