Game Duenix for Amiga computers/RecordAndReplay.s

From Wikiversity
Jump to navigation Jump to search
;------------------------------------------------------------------------------
; Record and replay assembly procedures for Duenix for the Amiga
;------------------------------------------------------------------------------
; Player decisions (one of three options 0, 1, and 2, requiring two bits)
; are being stored/saved, to be loaded later.
; The single round/frame requires 6 * 2 bits of storage,
; two bits per player; they are stored in a single 16-bit word.
; One would think this would have been fast enough in
; in AMOS using peeks, pokes and similar.
; The comments have been expanded in 2024 to be excessively detailed,
; which is fine for educational purposes.
; This is Motorola 68000 assembly.
;------------------------------------------------------------------------------

MaxSize = 8000 

   ;-------------------------
   ; Interface variables
   ;-------------------------

PMove   dc.l 0      ;The beginning of an array of player moves/decisions for the current round.
                    ;Each move is stored in an AMOS integer, so the array takes 4 * 6 bytes.
Record  dc.l 0      ;The address of record space, containing recorded decisions of players for all rounds.
                    ;In this space, the decision for all players for a given round takes 16 bits
                    ;(12 bits, plus 4 bits free).
TopPtr  dc.l 0      ;The pointer in the record space

   ;-------------------------
   ; Procedure entry points
   ;-------------------------

    Bra SavePos
    Bra LoadPos

   ;----------------------
   ; Procedure SavePos
   ;----------------------

SavePos
    Moveq  #0,d1             ;d1 := 0
    Moveq  #5,d0             ;PlayerNumber := 5
    Move.l PMove(pc),a0      ;a0 := PMove address
    Lea    TopPtr(pc),a2     ;a2 := TopPtr address
SavePos_Loop
    Move.l d0,d2
    Asl.l  #2,d2             ;d2 := PlayerNumber * 4
    Move.l (a0,d2),d3        ;d3 := PMove[PlayerNumber], which is one of 0, 1, and 2
    Asl.w  d0,d3
    Asl.w  d0,d3             ;d3 := d3 << (2 * PlayerNumber)
    Or.w   d3,d1             ;d1 := d1 bitor d3
    DBra   d0,SavePos_Loop   ;Go to next PlayerNumber

    Move.l Record(pc),a1
    Move.l (a2),d2
    Move.w d1,(a1,d2)        ;Record[TopPtr] := word containing the decisions of all players

    Cmp.w  #MaxSize,a2
    Beq SavePos_Skip
    Addq.l #2,(a2)           ;TopPtr += 2
SavePos_Skip
    Rts

   ;----------------------
   ; Procedure LoadPos
   ;----------------------

LoadPos
    Move.l PMove(pc),a0      ;a0 := PMove address
    Lea    TopPtr(pc),a2     ;a2 := TopPtr address
    Move.l Record(pc),a1
    Move.l (a2),d2
    Move.w (a1,d2),d1        ;d1 := Record[TopPtr]

    Cmp.w  #MaxSize,d2
    Beq    LoadPos_Skip
           
    Addq.l #2,(a2)           ;TopPtr += 2
LoadPos_Skip
    Moveq  #5,d0             ;PlayerNumber := 5
LoadPos_Loop 
    Move.w d1,d2             ;d2 := Record[TopPtr]
    Asr.w  d0,d2
    Asr.w  d0,d2
    And.w  #3,d2             ;d2 := (Record[TopPtr] >> (2 * PlayerNumber)) bitand 0b11
    Ext.l  d2
    Move.l d0,d3
    Asl.l  #2,d3
    Move.l d2,(a0,d3)        ;PMove[PlayerNumber] := (Record[TopPtr] >> (2 * PlayerNumber)) bitand 0b11
    DBra   d0,LoadPos_Loop   ;Go to next PlayerNumber
    Rts