>

Wack the Mole in i281 Assembly on FPGA


i281 Cpu Simulator

My digital logic class was offering extra credit, which included programming a game in the classe’s cpu, i281, assembly language. I would say making this game was the funnest part of the class yet (still have finals left).

The game is similiar to wack the mole. A “mole” pops out of one of the displays, and you need to smack it with the corresponding switch. The longer you fail to smack it, the bigger the mole gets. Once it’s to big, you have failed to smack it in time, so game over. If it’s not game over, than another mole should pop up, and so on. The game is hard programmed to last for no more than 4 official rounds, and for the moles to pop up in the same order. The sequence of which displays to pop out of are defined by “sequence” in the DMEM.

I would want the sequence to be random. One way I am thinking of how this could work is by having a start button before the game starts. There could be a timer running that stops once the user starts the game. This could give us a somewhat psuedo seed if we have our timer running fast. I would also want the current round to show up on far left display. Another way may be using xorshift . The issue with xorshift is implementing it alongside the game all in 64 instructions.

.data
    display BYTE 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ; MS - LS
    sequence BYTE 1 , 4 , 3 , 6
    gameRun BYTE 0
    shiftState BYTE ? , ? ; [shiftState + 1] is irrelevant
    switch BYTE ?
.code
    NOOP
    NOOP
    LOAD D , [ sequence ]; start popup display
Beg: INPUTD [ switch ] 
    LOAD B , [ switch ]
    LOADI C , 0 ; not for checking here
    LOADI A , 0 ; index for loop
LftShift: CMP A , D   ; shifts B left D times
; LftShift to UpdateDisplay formats B to 1 bit status
; of corresponding switch to "mole" display
    BRGE LftShiftEnd
    SHIFTL B
    ADDI A , 1
    JUMP LftShift
LftShiftEnd: SHIFTR B ; carry flag updates shifted out bit 
; would be nice if you could somehow get the carry flag bit instead of this
    SHIFTR B
    SHIFTR B
    SHIFTR B
    SHIFTR B
    SHIFTR B
    SHIFTR B
    STOREF [ shiftState + C ] , B ; if running from checking then last byte of this array ; shiftState + 0 states original and others arent so we can get out of a branch here
    JUMP Checking
UpdateDisplay: LOADF A , [ display + D ] ; get current display
    SHIFTL A ; expand
    ADDI A , 1 ; expand
    STOREF [ display + D ] , A ; expand
    SUBI A , 127 ; when display fully expanded
    BRE Exit
    LOADI C , 1 ; Checking starts here
    LOADI A , 0 ; reset index for loop
    INPUTD [ switch ]
    LOAD    B , [ switch ]
    JUMP LftShift
Checking: LOAD A , [shiftState + 0] ; original before start of mole
    CMP A , B ; no need to use shiftState + 1, thats to get out of a branch
    BRE UpdateDisplay
    LOAD A , [ gameRun ]
    ADDI A , 1
    LOADF D , [ sequence + A ]
    STORE [ gameRun ] , A
    JUMP Beg
Exit: NOOP
    JUMP Exit

Zane F. Salti

Find me here


2023-12-11