Simon Says

A simple Simon Says style game for use on a Moterolla HC11 processor.

***********************************************************************************
* Lab 9 - ECE 171 - Fall 2005                                                     *
* Simon Says                                                                      *
*                                                                                 *
* Programmer: Sean P. O. MacCath-Moran                                            *
* Date: 07 Apr 2005                                                               *
*                                                                                 *
*                                                                                 *
***********************************************************************************
******************** DATA *******************
DIPSWITCHES   EQU  $1003
*1 & 2 reserved for PC0 and PC1
DIPSWITCH1    EQU  $01
DIPSWITCH2    EQU  $02
*3 & 4 set nothing
DIPSWITCH3    EQU  $04
DIPSWITCH4    EQU  $08
*5, 6 & 7 set nothing
DIPSWITCH5    EQU  $10
DIPSWITCH6    EQU  $20
DIPSWITCH7    EQU  $40
*Termination switch
DIPSWITCH8    EQU  $80
********************* CODE *******************
ORG  $AFFF
RANDVAL       RMB  1                     ;randomizing value for next light
SEQLENGTH     RMB  1                     ;current lengh of memorized sequence
SEQUENCE      RMB  40
***************** MAIN PROGRAM ***************
START         ORG  $8800                 ;start out in timbucktoo
LDS  #$DFFF                ;initialize stack pointer.
JSR  KEYSCANINIT           ;initialize keypad usage
JSR  MIMICINIT             ;initialize MIMIC usage
LDY  #MIMICFLAGS           ;retrieve address of mimic flags
WAITAGAIN     JSR  INITnWAIT             ;wait for user to press key
CLR  SEQLENGTH             ;init sequence length to 0
GETNEXTSEQ    JSR  INCSEQ                ;get new value onto SEQUENCE stack
JSR  DISPLAY               ;show the current sequence to the user
JSR  MIMIC                 ;accept sequence of button presses
BRCLR 0,Y MIMICFLAGERR GETNEXTSEQ
;if no errorflag, then get next value
JSR  ERRORDISPLAY          ;display error message to user
ENDISNIGH     LDAA #DIPSWITCH8           ;check for end switch
BITA DIPSWITCHES
BEQ  ENDISWAYNEIGH
JMP  WAITAGAIN             ;keep up with loop until switch set
ENDISWAYNEIGH SWI                        ;ok - love ya - bye bye now
* Main END ************************************************************************
***********************************************************************************
* Initialize and Wait                                                             *
*                                                                                 *
* PURPOSE:  Setup for next game start and wait for user interaction               *
*                                                                                 *
* USE:      Call the function                                                     *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
INITPORTB     EQU  $1004
INITPAUSETIME EQU  2
****************** CODE START ****************
INITnWAIT     PSHB                       ;save the B reg state
PSHA                       ;save the A reg state
PSHY                       ;save the X reg state
CLR  INITPORTB             ;blank out the LEDs
LDY  #KEYPADFLAGS          ;load X with address of flags
INITnWAIT1    LDAA #INITPAUSETIME        ;setup to pause for about 1/4 second
JSR  DELAY10X              ;pause for x/10th second
INC  RANDVAL               ;set random value to next digit
JSR  KEYSCAN               ;check status of keypad
BRCLR 0,Y KEYPADFLAGPRE INITnWAIT1
;wait until a key is pressed
LDAB KEYPADKEYCHK          ;retrieve the key being pressed
JSR  DISPLAYKEY            ;display this key to user while it's being pressed
INITnWAIT2    JSR  KEYSCAN               ;check status of keypad
BRSET 0,Y KEYPADFLAGPRE INITnWAIT2
;wait until key is released
CLR  INITPORTB             ;blank out the LEDs
PULY                       ;restore the X reg state
PULA                       ;restore the A reg state
PULB                       ;restore the B reg state
RTS                        ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Increment Sequence                                                              *
*                                                                                 *
* PURPOSE:  generate the next value in the sequence                               *
*                                                                                 *
* USE:      Call the function                                                     *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
INCSEQVALMASK EQU  %00000011             ;mask to retrieve bits used in random value
****************** CODE START ****************
INCSEQ        PSHX                       ;save the X reg state
PSHB                       ;save the B reg state
PSHA                       ;save the A reg state
LDX  #SEQUENCE             ;retrieve memory position of SEQUENCE
LDAB SEQLENGTH             ;retrieve lench of SEQUENCE
ABX                        ;move X to end of sequence
LDAA RANDVAL               ;retrieve the current random value
ANDA #INCSEQVALMASK        ;keep only those values in mask
INCA                       ;add 1 to value for use as index
STAA 0,X                   ;store new value at end of SEQUENCE
INC  SEQLENGTH             ;increase length of sequence by 1
PULA                       ;restore the A reg state
PULB                       ;restore the B reg state
PULX                       ;restore the X reg state
RTS                        ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Accept Sequence                                                                 *
*                                                                                 *
* PURPOSE:  Accpept button presses from user and check them against the SEQUENCE. *
*           If a wrong key is pressed or if more than three seconds elapses in    *
*           waiting for a button, then MIMIC will abort with an error. If all     *
*           keys are pressed correctly, then MIMIC returns with no ERROR.         *
*                                                                                 *
* USE:      Call the function                                                     *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
MIMICFLAGERR  EQU  %00000001             ;flag for user error detected
MIMICFLAGB    EQU  %00000010             ;flag for ?
MIMICFLAGC    EQU  %00000100             ;flag for ?
MIMICFLAGD    EQU  %00001000             ;flag for ?
MIMICFLAGE    EQU  %00010000             ;flag for ?
MIMICFLAGF    EQU  %00100000             ;flag for ?
MIMICFLAGG    EQU  %01000000             ;flag for ?
MIMICFLAGH    EQU  %10000000             ;flag for ?
MIMICPAUSETIM EQU  2
MIMICBCNTRVAL EQU  15
MIMICPORTB    EQU  $1004
****************** CODE **********************
MIMICFLAGS    RMB  1                     ;status flags for MIMIC
;0 = Error,
;1 = ?, 2 = ?, 3 = ?, 4 = ?, 5 = ?, 6 = ?, 7 = ?
MIMICBCNTR    RMB  1                     ;BCounter value
MIMICSCNTR    RMB  1                     ;SEQLENGTH value
****************** CODE INITIALIZATION *******
MIMICINIT
CLR  MIMICFLAGS            ;clear all flags
RTS                        ;return to sender *weg*
****************** CODE START ****************
MIMIC         PSHB                       ;save the B reg state
PSHA                       ;save the A reg state
PSHY                       ;save the X reg state
PSHX                       ;save the X reg state
LDY  #MIMICFLAGS           ;retrieve location of flags
BSET 0,Y MIMICFLAGERR      ;set the error flag
LDY  #KEYPADFLAGS          ;load Y with address of flags
LDX  #SEQUENCE             ;retrieve memory position of SEQUENCE
LDAA SEQLENGTH             ;retrieve the SEQLENGTH
STAA MIMICSCNTR            ;init the total sequence length count
MIMICNEXTBUT  LDAA #MIMICBCNTRVAL        ;retrive BCOUNTER value
STAA MIMICBCNTR            ;initialize BCOUNTER value
MIMICWAITBUT  INC  RANDVAL               ;set random value to next digit
LDAA #MIMICPAUSETIM        ;setup pause count
JSR  DELAY10X              ;pause for x/10th second
DEC  MIMICBCNTR            ;count down pause timer
BEQ  MIMICEND              ;if out of time, then end
JSR  KEYSCAN               ;check status of keypad
BRCLR 0,Y KEYPADFLAGPRE MIMICWAITBUT
;wait for button pressed status
LDAA 0,X                   ;retrieve value pointed to by stack
CMPA KEYPADKEYCHK          ;check for match with value from KEYSCAN
BNE  MIMICEND              ;wrong button pressed
LDAB KEYPADKEYCHK          ;retrieve the key being pressed
JSR  DISPLAYKEY            ;display this key to user while it's being pressed
MIMICWAITREL  JSR  KEYSCAN               ;check status of keypad
BRSET 0,Y KEYPADFLAGPRE MIMICWAITREL
;wait for button released status
CLR  MIMICPORTB            ;blank out the LEDs
INX                        ;point at next value
DEC  MIMICSCNTR            ;count off another success
BNE  MIMICNEXTBUT          ;go wait for next button press if not done
LDY  #MIMICFLAGS           ;retrieve location of flags
BCLR 0,Y MIMICFLAGERR      ;clear the error flag
MIMICEND
PULX                       ;restore the X reg state
PULY                       ;restore the X reg state
PULA                       ;restore the A reg state
PULB                       ;restore the B reg state
RTS                        ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Display Sequence                                                                *
*                                                                                 *
* PURPOSE:  Display the required sequence to the user                             *
*                                                                                 *
* USE:      Call the function                                                     *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
DISPLAYPORTB  EQU  $1004
DISPLAYPAUSE  EQU  3
****************** CODE **********************
DISPLAYINDEX  RMB  1
****************** CODE START ****************
DISPLAY       PSHB                       ;save the B reg state
PSHA                       ;save the A reg state
PSHX                       ;save the X reg state
LDAA SEQLENGTH             ;retrieve current length
STAA DISPLAYINDEX          ;init index to length
LDAA #DISPLAYPAUSE         ;init time to pause for each cycle
LDX  #SEQUENCE             ;point at the next value to display
DISPLAYNEXT   CLR  DISPLAYPORTB          ;clear the LEDs
JSR  DELAY10X              ;pause for DISPLAYPAUSE/10th sec
LDAB 0,X                   ;retrieve the next value in SEQUENCE
JSR  DISPLAYKEY            ;display the next value in SEQUENCE
JSR  DELAY10X              ;pause for DISPLAYPAUSE/10th sec
INX                        ;point at the next value to display
DEC  DISPLAYINDEX          ;completed another loop
BNE  DISPLAYNEXT           ;show next value if not done
CLR  DISPLAYPORTB          ;clear the LEDs
PULX                       ;restore the X reg state
PULA                       ;restore the A reg state
PULB                       ;restore the B reg state
RTS                        ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Check Next Key                                                                  *
*                                                                                 *
* PURPOSE:  Retrieve the next key being pressed, returning indicators via flags   *
*           to determine if a key has been pressed, is being pressed, or was just *
*           pressed.                                                              *
*                                                                                 *
* USE:      Call function and examine flags to determine keypad status.           *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
KEYPADLAST    EQU  3333                  ;Holds the last key value pressed
KEYPADPRTG    EQU  $6200                 ;keypad memory address
KEYPADPRTGMSK EQU  $6202                 ;keypad mask memory address
KEYPADPRTGINI EQU  %00001111             ;mask for DDRG
KEYPADCNTROWS EQU  4                     ;number of rows of buttons to initialize to
KEYPADCNTCOLS EQU  4                     ;number of columns of buttons to initialize to
KEYPADCNTBUTS EQU  16                    ;total number of buttons to initialize too
KEYPADSCANPAT EQU  %11110111             ;starting scan pattern for keypad
KEYPADFLAGDET EQU  %00000001             ;flag for no current activity detected
KEYPADFLAGPRE EQU  %00000010             ;flag for key is currenty being pressed by user
KEYPADFLAGPRO EQU  %00000100             ;flag for key has been released and is ready to be processed
KEYPADFLAGD   EQU  %00001000             ;flag for ?
KEYPADFLAGE   EQU  %00010000             ;flag for ?
KEYPADFLAGF   EQU  %00100000             ;flag for ?
KEYPADFLAGG   EQU  %01000000             ;flag for ?
KEYPADFLAGH   EQU  %10000000             ;flag for ?
********************* CODE *******************
KEYPADFLAGS  RMB  1                      ;set of byte flags for use by Get Next Key function (0 = false, 1 = true)
;bit 0: No current activity detected
;bit 1: Key is currently being pressed
;bit 2: Key is ready to be processed
;bit 3:
;bit 4:
;bit 5:
;bit 6:
;bit 7:
KEYPADSMASK   RMB  1                     ;scan pattern for keypad
KEYPADCURRENT RMB  1                     ;
KEYPADKEYCHK  RMB  1                     ;
KEYPADROWNUM  RMB  1                     ;
KEYPADCOLNUM  RMB  1                     ;
****************** CODE INITIALIZATION *******
KEYSCANINIT   PSHA                       ;save the A reg state
LDAA #KEYPADPRTGINI        ;retrieve the DDRG mask and ...
STAA KEYPADPRTGMSK         ;... initialize the DDRG mask
CLR  KEYPADFLAGS           ;clear the flags register
PULA                       ;restore the A reg state
RTS                        ;return to sender *weg*
****************** CODE START ****************
KEYSCAN       PSHX                       ;save the X reg state
PSHB                       ;save the B reg state
PSHA                       ;save the A reg state
LDAA #KEYPADCNTROWS        ;retrieve the row count and ...
STAA KEYPADROWNUM          ;... initialize the number of rows
LDAA #KEYPADCNTBUTS        ;retrive the button count and ...
STAA KEYPADCURRENT         ;... initialize the current button position
LDAA #KEYPADSCANPAT        ;retrieve the starting scan pattern ...
STAA KEYPADSMASK           ;... initialize the current mask
;why isn't this working????
;BCLR KEYPADFLAGS,KEYPADFLAGPRE  ;clear the "key is being pressed" flag
LDAB #KEYPADFLAGPRE        ;retrieve the "key is being pressed" flag
COMB                       ;reverse the flag to create a mask
ANDB KEYPADFLAGS           ;clear the "key is being pressed" flag if it was set
STAB KEYPADFLAGS           ;store the resulting flag set
KEYPADOUTTER  LDAA KEYPADSMASK           ;Retrieve the current mask and ...
STAA KEYPADPRTG            ;... set the keypad mask to this value
LDAA KEYPADPRTG            ;retrieve the current row from the keypad (leave in A reg)
*Start Process Row
LDAB #KEYPADCNTCOLS         ;retrieve the coloumn count and ...
STAB KEYPADCOLNUM          ;... initialize the number of columns
KEYPADINNER   LSLA                       ;rotate the PortG values to find if next bit is set
BCS  KEYPADSKIPKEYCAPTURE  ;if carry isn't set then don't capture the key
LDAB KEYPADCURRENT         ;retrieve the current key value
STAB KEYPADKEYCHK          ;store the current key value
LDAB KEYPADFLAGS           ;retrieve the set of flags
ORAB #KEYPADFLAGPRE         ;set the "key is being pressed" flag
ORAB #KEYPADFLAGPRO         ;set the "ready to process" flag
STAB KEYPADFLAGS           ;store the resulting flag set
KEYPADSKIPKEYCAPTURE                     ;target for jumping over the key kapture
DEC  KEYPADCURRENT         ;decrement current key value
DEC  KEYPADCOLNUM          ;decrement column number
BNE  KEYPADINNER           ;check next column
*End Process Row
LSR  KEYPADSMASK           ;rotate the mask to set the next entry point
DEC  KEYPADROWNUM          ;decrement row number
BNE  KEYPADOUTTER          ;check next row
PULA                       ;restore the A reg state
PULB                       ;restore the B reg state
PULX                       ;restore the X reg state
RTS                        ;return to sender *weg*
* KEYPADLAST END ******************************************************************
***********************************************************************************
* User Error                                                                      *
*                                                                                 *
* PURPOSE:  Indicates to the user that an error has occured                       *
*                                                                                 *
* USE:      Call the function                                                     *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
ERRFLASHES    EQU  4                     ;20000 c / (3c + 3c) -- pause 1/100th sec
ERRSHOWTIME   EQU  2
ERRPORTB      EQU  $1004
****************** CODE START ****************
ERRORDISPLAY  PSHB                       ;save the B reg state
PSHA                       ;save the A reg state
CLR  ERRPORTB              ;clear out the LED lights display
LDAA #ERRSHOWTIME          ;load the time (in x/100ths) to pause
LDAB #ERRFLASHES           ;load port B with number of flashes to execute
DISPLAYERRLP  JSR  DELAY10X              ;pause for x/10th second
COM  ERRPORTB              ;turn on all port be lights
JSR  DELAY10X              ;pause for x/10th second
COM  ERRPORTB              ;turn off all port be lights
DECB                       ;count off a completed loop
BNE  DISPLAYERRLP          ;show next flash if not done
PULA                       ;restore the A reg state
PULB                       ;restore the A reg state
RTS                        ;return to sender *weg*
* Password Rejected END ***********************************************************
***********************************************************************************
* Display LED Value At Pos                                                        *
*                                                                                 *
* PURPOSE:  Display a specific value in LED                                       *
*                                                                                 *
* USE:      Reg B = what position value to display (0-4)                          *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
DISPLAYKEYPB  EQU  $1004
********************* CODE *******************
DISPLAYKEYTABLE                          ;values of display mask
FCB  %00000000             ;dummey value
FCB  %10000000             ;1 (leftmost)
FCB  %01000000             ;2 (second from left)
FCB  %00100000             ;3 (second from right)
FCB  %00010000             ;4 (rightmost)
****************** CODE START ****************
DISPLAYKEY    PSHX                       ;save the X reg state
PSHB                       ;save the B reg state
CLR  DISPLAYKEYPB          ;clear the display in port B
TSTB                       ;make sure position is not set to 0
BEQ  DISPLAYKEYEND         ;jump to end if it is
LDX  #DISPLAYKEYTABLE
ABX
LDAB 0, X                  ;retrieve the display mask of current digit
STAB DISPLAYKEYPB          ;store the digit mask to display into port B
DISPLAYKEYEND PULB                       ;restore the B reg state
PULX                       ;restore the X reg state
RTS                        ;return to sender *weg*
* Display LED Value At Pos END ****************************************************
***********************************************************************************
* PAUSE BY X/100th SECOND                                                         *
*                                                                                 *
* PURPOSE:  Pauses program execution for X/10th seconds. X is indicated by the    *
*           value in the A register                                               *
*                                                                                 *
* USE:      Load the A register with the number of 1/10th seconds to pause       *
*                                                                                 *
* MODIFIES: Flags                                                                 *
*                                                                                 *
***********************************************************************************
********************* DATA *******************
PAUSE100thVAL EQU  3333                  ;20000 c / (3c + 3c) -- pause 1/100th sec
PAUSE10thVAL  EQU  10                    ;bring pause time incrments up to a 10th
****************** CODE START ****************
DELAY10X      PSHX                       ;save the X reg state
PSHB                       ;save the B reg state
PSHA                       ;save the A reg state
PAUSE10th     LDAB #PAUSE10thVAL         ;set B reg to count of 10
PAUSE100th    LDX  #PAUSE100thVAL        ;load X with 1/100th worth of counter
PAUSEINNER    DEX                        ;count down one in pause loop
BNE  PAUSEINNER            ;continue loop if not done with 1/100th pause
DECB                       ;count down another 1/100 sec
BNE PAUSE100th             ;continue loop if not done with 1/10th pause
DECA                       ;decrement user specified pause count
BNE  PAUSE10th             ;continue loop if not done with this pause
PULA                       ;restore the A reg state
PULB                       ;restore the B reg state
PULX                       ;restore the X reg state
RTS                        ;return to sender *weg*
* PAUSE END ***********************************************************************
ENDOFCODE