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 AARCH64 Raspberry PI 3B */
/*  program 2048_64.s   */ 
 
/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
.equ SIZE,       4       
.equ TOTAL,      2048
.equ BUFFERSIZE, 80
 
.equ KEYSIZE,    8
.equ IOCTL,     0x1D  // Linux syscall
.equ SIGACTION, 0x86  // Linux syscall
.equ SYSPOLL,   0x16  // Linux syscall
.equ CREATPOLL, 0x14  // Linux syscall
.equ CTLPOLL,   0x15  // Linux syscall
 
.equ TCGETS,    0x5401
.equ TCSETS,    0x5402
.equ ICANON,    2
.equ ECHO,     10
.equ POLLIN,    1
.equ EPOLL_CTL_ADD,    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 + 40      // see length if necessary 
term_fin:
 
/* structure sigaction see doc linux */
    .struct  0
sa_handler:
    .struct  sa_handler + 8 
sa_mask:
    .struct  sa_mask + 8 
sa_flags:
    .struct  sa_flags + 8
sa_sigaction:
    .struct  sa_sigaction + 8
sa_fin:
 
/* structure poll see doc linux */
    .struct  0
poll_event:                        //  events mask
    .struct  poll_event + 8
poll_fd:                           // events returned
    .struct  poll_fd  + 8
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"
szMessErrInitTerm:  .asciz "Error terminal init.\n"
szMessErrInitPoll:  .asciz "Error poll init.\n"
szMessErreurKey:    .asciz "Error read key.\n"
szMessErr:          .asciz    "Error code hexa : @ décimal : @ \n"
szCarriageReturn:   .asciz "\n"
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 "
szCleax1:           .byte 0x1B 
                    .byte 'c'           // other console clear
                    .byte 0
 
szLineH:            .asciz "-----------------------------\n"
szLineV:            .asciz "|"
szLineVT:           .asciz "|      |      |      |      |\n"
.align 4
qGraine:            .quad 123456
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:      .skip 24
sBuffer:        .skip BUFFERSIZE
qTbCase:        .skip 8 * SIZE * SIZE
qEnd:           .skip 8                        // 0 loop  1 = end loop
qTouche:        .skip KEYSIZE                  // 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
stSigAction2:   .skip sa_fin
stSigAction3:   .skip sa_fin
stPoll1:        .skip poll_fin                 // area poll structure
stPoll2:        .skip poll_fin
stevents:       .skip 16
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                // entry of program 
    mov x0,#0
    bl initTerm                      // terminal init
    cmp x0,0                         // error ?
    blt 100f
    bl initPoll                      // epoll instance init
    cmp x0,0
    blt 99f
    mov x22,x0                        // save epfd
1:                                    // begin game loop
    ldr x0,qAdrszCleax1
    bl affichageMess
    bl razTable
2:
    bl addDigit   
    cmp x0,#-1
    beq 5f                            // end game
    bl displayGame
3:
    mov x0,x22
    bl waitKey
    cmp x0,0
    beq 3b
    bl readKey
    cmp x0,#-1
    beq 99f                          // error
    bl keyMove
    cmp x0,#0
    beq 3b                            // no change -> loop
    cmp x0,#2                         // last addition = 2048 ?
    beq 4f
    cmp x0,#-1                        // quit ?
    bne 2b                            // loop
 
    b 10f
4:                                    // last addition = 2048 
    ldr x0,qAdrszMessOK
    bl affichageMess
    b 10f
5:                                    // display message no solution
    ldr x0,qAdrszMessNotOK
    bl affichageMess
 
10:                                   // display new game ?
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszMessNewGame
    bl affichageMess
11:
    mov x0,x22
    bl waitKey
    cmp x0,0
    beq 11b
    bl readKey
    ldr x0,qAdrqTouche
    ldrb w0,[x0]
    cmp w0,#'y'
    beq 1b
    cmp w0,#'Y'
    beq 1b
99:
    bl restauTerm                     // terminal restaur
100:                                  // standard end of the program 
    mov x0, #0                        // return code
    mov x8, #EXIT                     // request to exit program
    svc #0                            // perform the system call
 
qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrszMessNotOK:          .quad szMessNotOK
qAdrszMessOK:             .quad szMessOK
qAdrszMessNewGame:        .quad szMessNewGame
qAdrsZoneConv:            .quad sZoneConv
qAdrszCleax1:             .quad szCleax1
qAdrszMessErrInitTerm:    .quad szMessErrInitTerm
qAdrszMessErrInitPoll:    .quad szMessErrInitPoll
qAdrszMessErreurKey:      .quad szMessErreurKey
qAdrstOldtio:             .quad stOldtio
qAdrstCurtio:             .quad stCurtio
qAdrstSigAction:          .quad stSigAction
qAdrstSigAction1:         .quad stSigAction1
qAdrSIG_IGN:              .quad 1
qAdrqEnd:                 .quad qEnd
qAdrqTouche:              .quad qTouche
qAdrstevents:             .quad stevents
/******************************************************************/
/*     raz table cases                                                   */ 
/******************************************************************/
razTable:
    stp x0,lr,[sp,-16]!     // save  registres
    stp x1,x2,[sp,-16]!     // save  registres
    ldr x1,qAdrqTbCase
    mov x2,#0
1:
    str xzr,[x1,x2,lsl #3]
    add x2,x2,#1
    cmp x2,#SIZE * SIZE
    blt 1b
100:
    ldp x1,x2,[sp],16       // restaur des  2 registres
    ldp x0,lr,[sp],16       // restaur des  2 registres
    ret
/******************************************************************/
/*     key move                                                   */ 
/******************************************************************/
/* x0 contains key value               */
keyMove:
    stp x1,lr,[sp,-16]!     // save  registres
    lsr x0,x0,#16
    cmp x0,#0x42                  // down arrow 
    bne 1f
    bl moveDown
    b 100f
1:
    cmp x0,#0x41                  // high arrow
    bne 2f
    bl moveUp
    b 100f
2:
    cmp x0,#0x43                  // right arrow
    bne 3f
    bl moveRight
    b 100f
3:
    cmp x0,#0x44                  // left arrow
    bne 4f
    bl moveLeft
    b 100f
4:
    ldr x0,qAdrqTouche
    ldrb w0,[x0]
    cmp w0,#'q'                   // quit game
    bne 5f
    mov x0,#-1
    b 100f
5:
    cmp w0,#'Q'                   // quit game
    bne 100f
    mov x0,#-1
    b 100f
 
100:
    ldp x1,lr,[sp],16       // restaur des  2 registres
    ret
/******************************************************************/
/*           move left                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveLeft:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0                   // top move Ok
    mov x2,#0                   // line indice
1:
    mov x6,#0                   // counter empty case
    mov x7,#0                   // first digit
    mov x10,#0                  // last digit to add
    mov x3,#0                   // column indice
2:
    lsl x5,x2,#2                // change this if size <> 4
    add x5,x5,x3                // compute table indice
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
    cmp x6,#0
    beq 3f                      // no empty left case
    mov x8,#0
    str x8,[x1,x5,lsl #3]       // raz digit
    sub x5,x5,x6
    str x4,[x1,x5,lsl #3]       // and store to left empty position
    mov x0,#1                   // move Ok
3:
    cmp x7,#0                   // first digit
    beq 4f
    cmp x10,x4                  // prec digit have to add 
    beq 4f
    sub x8,x5,#1                // prec digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    mov x10,x4                  // save digit 
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1                   // move Ok
4:
    add x7,x7,#1                // no first digit
 
5:                              // and loop
    add x3,x3,#1
    cmp x3,#SIZE
    blt 2b
    add x2,x2,#1
    cmp x2,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2                   // total = 2048
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           move right                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveRight:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0
    mov x2,#0
1:
    mov x6,#0
    mov x7,#0
    mov x10,#0
    mov x3,#SIZE-1
2:
    lsl x5,x2,#2                  // change this if size <> 4
    add x5,x5,x3
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
 
    cmp x6,#0
    beq 3f                      // no empty right case
    mov x0,#0
    str x0,[x1,x5,lsl #3]       // raz digit
    add x5,x5,x6
    str x4,[x1,x5,lsl #3]       // and store to right empty position
    mov x0,#1
3:
    cmp x7,#0                   // first digit
    beq 4f
    add x8,x5,#1                // next digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    cmp x10,x4
    beq 4f
    mov x10,x4
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1
4:
    add x7,x7,#1                // no first digit
 
5:                              // and loop
    sub x3,x3,#1
    cmp x3,#0
    bge 2b
    add x2,x2,#1
    cmp x2,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           move down                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveDown:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0
    mov x3,#0
1:
    mov x6,#0
    mov x7,#0
    mov x10,#0
    mov x2,#SIZE-1
2:
    lsl x5,x2,#2                  // change this if size <> 4
    add x5,x5,x3
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
    cmp x6,#0
    beq 3f                      // no empty right case
    mov x0,#0
    str x0,[x1,x5,lsl #3]       // raz digit
    lsl x0,x6,#2
    add x5,x5,x0
    str x4,[x1,x5,lsl #3]       // and store to right empty position
    mov x0,#1
3:
    cmp x7,#0                   // first digit
    beq 4f
    add x8,x5,#SIZE                // down digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    cmp x10,x4
    beq 4f
    mov x10,x4
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1
4:
    add x7,x7,#1                   // no first digit
 
5:                           // and loop
    sub x2,x2,#1
    cmp x2,#0
    bge 2b
    add x3,x3,#1
    cmp x3,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           move up                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveUp:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0
    mov x3,#0
1:
    mov x6,#0
    mov x7,#0
    mov x10,#0
    mov x2,#0
2:
    lsl x5,x2,#2                  // change this if size <> 4
    add x5,x5,x3
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
    cmp x6,#0
    beq 3f                      // no empty right case
    mov x0,#0
    str x0,[x1,x5,lsl #3]       // raz digit
    lsl x0,x6,#2
    sub x5,x5,x0
    str x4,[x1,x5,lsl #3]       // and store to right empty position
    mov x0,#1
3:
    cmp x7,#0                   // first digit
    beq 4f
    sub x8,x5,#SIZE             // up digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    cmp x10,x4
    beq 4f
    mov x10,x4
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1
4:
    add x7,x7,#1                // no first digit
 
5:                              // and loop
    add x2,x2,#1
    cmp x2,#SIZE
    blt 2b
    add x3,x3,#1
    cmp x3,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           add new digit on game                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
addDigit:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    sub sp,sp,#8 * SIZE*SIZE
    mov fp,sp
 
    mov x0,#100
    bl genereraleas
    cmp x0,#10
    mov x1,#4
    mov x5,#2
    csel x5,x5,x1,ge
   // movlt x5,#4
    //movge x5,#2
    ldr x1,qAdrqTbCase
    mov x3,#0
    mov x4,#0
1:  
    ldr x2,[x1,x3,lsl 3]
    cmp x2,#0
    bne 2f
    str x3,[fp,x4,lsl 3]
    add x4,x4,#1
2:
    add x3,x3,#1
    cmp x3,#SIZE*SIZE
    blt 1b
    cmp x4,#0                 // no empty case
    beq 4f
    cmp x4,#1
    bne 3f
    ldr x2,[fp]               // one case
    str x5,[x1,x2,lsl 3]
    mov x0,#0
    b 100f
3:                            // multiple case
    sub x0,x4,#1
    bl genereraleas
    ldr x2,[fp,x0,lsl 3]
    str x5,[x1,x2,lsl 3]
    mov x0,#0
    b 100f
4:
    mov x0,#-1
100:
    add sp,sp,#8*  (SIZE*SIZE)  // stack alignement
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrqTbCase:         .quad qTbCase
/******************************************************************/
/*            display game                                      */ 
/******************************************************************/
displayGame:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    ldr x0,qAdrszCleax1
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    ldr x1,qAdrqTbCase
    mov x2,#0
1:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE
    blt 1b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
2:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE*2
    blt 2b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
3:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE*3
    blt 3b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
4:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE*4
    blt 4b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
 
100:
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrszLineH:         .quad szLineH
qAdrszLineV:         .quad szLineV
qAdrszLineVT:        .quad szLineVT
/******************************************************************/
/*            digits string                                       */ 
/******************************************************************/
/* x0 contains number */
/* x0 return address string */
digitString:
    stp x1,lr,[sp,-16]!          // save  registres
    cmp x0,#0
    bne 1f
    ldr x0,qAdrszMess0
    b 100f
1:
    cmp x0,#2
    bne 2f
    ldr x0,qAdrszMess2
    b 100f
2:
    cmp x0,#4
    bne 3f
    ldr x0,qAdrszMess4
    b 100f
3:
    cmp x0,#8
    bne 4f
    ldr x0,qAdrszMess8
    b 100f
4:
    cmp x0,#16
    bne 5f
    ldr x0,qAdrszMess16
    b 100f
5:
    cmp x0,#32
    bne 6f
    ldr x0,qAdrszMess32
    b 100f
6:
    cmp x0,#64
    bne 7f
    ldr x0,qAdrszMess64
    b 100f
7:
    cmp x0,#128
    bne 8f
    ldr x0,qAdrszMess128
    b 100f
8:
    cmp x0,#256
    bne 9f
    ldr x0,qAdrszMess256
    b 100f
9:
    cmp x0,#512
    bne 10f
    ldr x0,qAdrszMess512
    b 100f
10:
    cmp x0,#1024
    bne 11f
    ldr x0,qAdrszMess1024
    b 100f
11:
    cmp x0,#2048
    bne 12f
    ldr x0,qAdrszMess2048
    b 100f
12:
    ldr x1,qAdrszMessErreur                       // error message
    bl   displayError
100:
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrszMess0:          .quad szMess0
qAdrszMess2:          .quad szMess2
qAdrszMess4:          .quad szMess4
qAdrszMess8:          .quad szMess8
qAdrszMess16:         .quad szMess16
qAdrszMess32:         .quad szMess32
qAdrszMess64:         .quad szMess64
qAdrszMess128:        .quad szMess128
qAdrszMess256:        .quad szMess256
qAdrszMess512:        .quad szMess512
qAdrszMess1024:       .quad szMess1024
qAdrszMess2048:        .quad szMess2048
 
//qAdrsBuffer:         .quad sBuffer
qAdrszMessErreur :        .quad szMessErreur 
 
/***************************************************/
/*   Generation random number                  */
/***************************************************/
/* x0 contains limit  */
genereraleas:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    ldr x1,qAdrqGraine
    ldr x2,[x1]
    ldr x3,qNbDep1
    mul x2,x3,x2
    ldr x3,qNbDep2
    add x2,x2,x3
    str x2,[x1]                    // maj de la graine pour l appel suivant 
    cmp x0,#0
    beq 100f
    udiv x3,x2,x0
    msub x0,x3,x0,x2               // résult = remainder
 
100:                               // end function
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*****************************************************/
qAdrqGraine: .quad qGraine
qNbDep1:     .quad 0x0019660d
qNbDep2:     .quad 0x3c6ef35f
 
/******************************************************************/
/*     traitement du signal                                       */ 
/******************************************************************/
sighandler:
    stp x0,lr,[sp,-16]!            // save  registers
    str x1,[sp,-16]! 
    ldr x0,qAdrqEnd
    mov x1,#1                      // maj zone end
    str x1,[x0]
    ldr x1,[sp],16
    ldp x0,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/***************************************************/
/*   display error message                         */
/***************************************************/
/* x0 contains error code  x1 : message address */
displayError:
    stp x2,lr,[sp,-16]!            // save  registers
    mov x2,x0                      // save error code
    mov x0,x1
    bl affichageMess
    mov x0,x2                      // error code
    ldr x1,qAdrsZoneConv
    bl conversion16                // conversion hexa
    ldr x0,qAdrszMessErr           // display error message
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc               // insert result at @ character
    mov x3,x0
    mov x0,x2                      // error code
    ldr x1,qAdrsZoneConv               // result address
    bl conversion10S                // conversion decimale
    mov x0,x3
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc               // insert result at @ character
    bl affichageMess
100:
    ldp x2,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
qAdrszMessErr:                 .quad szMessErr
/*********************************/
/* init terminal state            */
/*********************************/
initTerm:
    stp x1,lr,[sp,-16]!            // save  registers
    /* read terminal state */
    mov x0,STDIN                   // input console
    mov x1,TCGETS
    ldr x2,qAdrstOldtio
    mov x8,IOCTL                   // call system Linux
    svc 0 
    cbnz x0,98f                    // error ?
 
    adr x0,sighandler              // adresse routine traitement signal
    ldr x1,qAdrstSigAction         // adresse structure sigaction
    str x0,[x1,sa_handler]         // maj handler
    mov x0,SIGINT                  // signal type
    ldr x1,qAdrstSigAction
    mov x2,0
    mov x3,8
    mov x8,SIGACTION               // call system
    svc 0 
 
    cmp x0,0                       // error ?
    bne 98f
    mov x0,SIGQUIT
    ldr x1,qAdrstSigAction
    mov x2,0                       // NULL
    mov x8,SIGACTION               // call system 
    svc 0 
    cmp x0,0                       // error ?
    bne 98f
    mov x0,SIGTERM
    ldr x1,qAdrstSigAction
    mov x2,0                       // NULL
    mov x8,SIGACTION               // appel systeme 
    svc 0 
    cmp x0,0
    bne 98f
    //
    adr x0,qAdrSIG_IGN             // address signal igonre function
    ldr x1,qAdrstSigAction1
    str x0,[x1,sa_handler]
    mov x0,SIGTTOU                 //invalidate other process signal
    ldr x1,qAdrstSigAction1
    mov x2,0                       // NULL
    mov x8,SIGACTION               // call system 
    svc 0 
    cmp x0,0
    bne 98f
    //
    /* read terminal current state  */
    mov x0,STDIN
    mov x1,TCGETS
    ldr x2,qAdrstCurtio            // address current termio
    mov x8,IOCTL                   // call systeme 
    svc 0 
    cmp x0,0                       // error ?
    bne 98f
    mov x2,ICANON | ECHO           // no key pressed echo on display
    mvn x2,x2                      // and one key 
    ldr x1,qAdrstCurtio
    ldr x3,[x1,#term_c_lflag]
    and x3,x2,x2                   // add flags 
    str x3,[x1,#term_c_lflag]      // and store
    mov x0,STDIN                   // maj terminal current state 
    mov x1,TCSETS
    ldr x2,qAdrstCurtio
    mov x8,IOCTL                   // call system
    svc 0 
    cbz x0,100f
98:                                // error display
    ldr x1,qAdrszMessErrInitTerm
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
qAdrstSigAction2:    .quad stSigAction2
qAdrstSigAction3:    .quad stSigAction3
/*********************************/
/* init instance epool            */
/*********************************/
initPoll:
    stp x1,lr,[sp,-16]!            // save  registers
    ldr x0,qAdrstevents
    mov x1,STDIN                   // maj structure events
    str x1,[x0,#poll_fd]           // maj FD
    mov x1,POLLIN                  // action code
    str x1,[x0,#poll_event]
    mov x0,0
    mov x8,CREATPOLL               // create epoll instance
    svc 0
    cmp x0,0                       // error ?
    ble 98f
    mov x10,x0                     // return FD epoll instance
    mov x1,EPOLL_CTL_ADD
    mov x2,STDIN                   // Fd to we want add
    ldr x3,qAdrstevents            // structure events address
    mov x8,CTLPOLL                 // call system control epoll
    svc 0
    cmp x0,0                       // error ?
    blt 98f                       // no
    mov x0,x10                     // return FD epoll instance
    b 100f
98:                                // error display
    ldr x1,qAdrszMessErrInitPoll   // error message
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*********************************/
/* wait key                      */
/*********************************/
/* x0 contains FD poll    */
waitKey:
    stp x1,lr,[sp,-16]!            // save  registers
    ldr x11,qAdrqTouche            // key address
    str xzr,[x11]                  // raz key
1:
    ldr x1,qAdrqEnd                // if signal ctrl-c  -> end
    ldr x1,[x1]
    cbnz x1,100f
 
    ldr x1,qAdrstevents
    mov x2,12                      // size events
    mov x3,1                       // timeout = 1  TODO: ??
    mov x4,0
    mov x8,SYSPOLL                 // call system wait POLL
    svc 0 
    cmp x0,0                       // key pressed ?
    bge 100f
98:                                // error display
    ldr x1,qAdrszMessErreurKey        // error message
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*********************************/
/* read key                      */
/*********************************/
/* x0 returns key value */
readKey:
    stp x1,lr,[sp,-16]!            // save  registers
    mov x0,STDIN                   // File Descriptor
    ldr x1,qAdrqTouche             // buffer address
    mov x2,KEYSIZE                 // key size
    mov x8,READ                    // read key
    svc #0
    cmp x0,0                       // error ?
    ble 98f
    ldr x2,qAdrqTouche             // key address
    ldr x0,[x2]
    b 100f
98:                                // error display
    ldr x1,qAdrszMessErreur        // error message
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*********************************/
/* restaur terminal state        */
/*********************************/
restauTerm:
    stp x1,lr,[sp,-16]!            // save  registers
    mov x0,STDIN                   // end then restaur begin state terminal
    mov x1,TCSETS
    ldr x2,qAdrstOldtio
    mov x8,IOCTL                   // call system  
    svc 0
    cbz x0,100f
    ldr x1,qAdrszMessErreur        // error message
    bl   displayError
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
 