;; Emacs Mode Selection Info: -*-mode: ASM; coding: iso-latin-1-dos;-*- * ;; ******************************************************************************************** ;; File Name: Four_4.asm ;; Auther: John L. Weinrich ;; Date: 01/31/03 ;; Useage 4004 TIC-TAC-TOE Game ;; Description: ;; ;; This routine is used for the 4004 TIC-TAC-TOE Game. ;; ;; Assumptions: ;; This assembly code and all the included files assume the following: ;; ;; RAM Memory: 2048 X 4 (8 RAM banks, 4 RAMs/bank, 4 registers/RAM, 16 Char/Reg) ;; 256 status characters. ;; 2 I/O Port ;; RAM1: SPEAKER PITCH/write ;; RAM2: SPEAKER LEVEL/write ;; ;; ROM Memory: 4096 X 8 (16 ROMs @ 256 locations ;; 11 I/O Ports (3 - R/W, 4- Read, 4 - Write) ;; ROM0: MISC/read ;; ROM0: MISC/write ;; ROM3: DISPLAY HIGH IN/read ;; ROM3: DISPLAY HIGH OUT/write ;; ROM4: DISPLAY LOW IN/read ;; ROM4: DISPLAY LOW OUT/write ;; ROM5: KEYBOARD HIGH INPUT/read ;; ROM6: KEYBOARD LOW INPUT/read ;; ROM7: MISC2/write ;; ROM8: PAGE/write ;; ROM9: RANDOM NUMBER GENERATOR/read ;; ROM10: FPGA VERSION/read ;; ;; See "4004 FPGA Design" and "4004 Software Design " documents for more detail information. ;; ;; Registers used: ;; Memory used: ;; Entrance parameters: ;; Exit parameters: ;; Labels used: ;; ******************************************************************************************** ;; ******************************************************************************************** ;; Here are the assembler directives ;; What CPU to assemble for and where in memory to start ;; Also there is the all the include files ;; except subroutines. include "four_ALL.equ" ; Get all equates include "bitfuncs.inc" ; Include bit functions so that fin can be ; loaded from a label (upper 4 bits of address ; are loped off) include "four_04.equ" ; Get Page #3 equates cpu 4004 ; Tell assembler that the processor is a 4004 org CODE_LOCATION ; Set code start location in memory ;; ******************************************************************************************** ;; This is the begining of the get mode routine ;; ******************************************************************************************** ;; Clear display, turn cursor off GetPosition nop KeyNotValid1 jms GetChar ; Get charactor from keyboard ;; Get game mode selection ;; Get upper nibble from keyboard ldm RAM_BANK_0 ; Select RAM bank 0 dcl ; Send out RAM bank selection fim SRC_P,KYB_STATE_H_RAM ; Select high keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard high state charactor from RAM fim SCRATCH_1_P,'1' ; Get the number "1" sub SCRATCH_1_H ; Check that the upper nibble is a number jcn Z,GetLowNib ; Equal, now get lower nibble jms InitKYBD ; clear out any key presses jms Level15 ; Set level to "15" jms Pitch406HZ ; Set pitch to "sad" jms Beep ; Tell user that key was pressed jun KeyNotValid1 ; Not equal, prompt again ;; Get lower nibble from keyboard GetLowNib ldm RAM_BANK_0 ; Select RAM bank 0 dcl ; Send out RAM bank selection fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'1' ; Get the number "1" sub SCRATCH_1_L ; Check that the lower nibble is the number "1" jcn NZ,NotPos1 ; Equal fim UTILITY_1_P,POS1_RAM ; Select RAM game board position #1 jun Pos NotPos1 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'2' ; Get the number "2" sub SCRATCH_1_L ; Check that the lower nibble is the number "2" jcn NZ,NotPos2 ; Equal, set mode to 2 fim UTILITY_1_P,POS2_RAM ; Select RAM game board position #2 jun Pos NotPos2 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'3' ; Get the number "3" sub SCRATCH_1_L ; Check that the lower nibble is the number "3" jcn NZ,NotPos3 ; Equal, set mode to 3 fim UTILITY_1_P,POS3_RAM ; Select RAM game board position #3 jun Pos NotPos3 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'4' ; Get the number "4" sub SCRATCH_1_L ; Check that the lower nibble is the number "4" jcn NZ,NotPos4 ; Equal, set mode to 4 fim UTILITY_1_P,POS4_RAM ; Select RAM game board position #4 jun Pos NotPos4 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'5' ; Get the number "5" sub SCRATCH_1_L ; Check that the lower nibble is the number "5" jcn NZ,NotPos5 ; Equal, set mode to 5 fim UTILITY_1_P,POS5_RAM ; Select RAM game board position #5 jun Pos NotPos5 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'6' ; Get the number "6" sub SCRATCH_1_L ; Check that the lower nibble is the number "6" jcn NZ,NotPos6 ; Equal, set mode to 6 fim UTILITY_1_P,POS6_RAM ; Select RAM game board position #6 jun Pos NotPos6 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'7' ; Get the number "7" sub SCRATCH_1_L ; Check that the lower nibble is the number "7" jcn NZ,NotPos7 ; Equal, set mode to 7 fim UTILITY_1_P,POS7_RAM ; Select RAM game board position #7 jun Pos NotPos7 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'8' ; Get the number "8" sub SCRATCH_1_L ; Check that the lower nibble is the number "8" jcn NZ,NotPos8 ; Equal, set mode to 8 fim UTILITY_1_P,POS8_RAM ; Select RAM game board position #8 jun Pos NotPos8 fim SRC_P,KYB_STATE_L_RAM ; Select low keyboard state charactor src SRC_P ; Tell RAM of selection clb ; Make sure accumulator is clear rdm ; Get keyboard low state charactor from RAM fim SCRATCH_1_P,'9' ; Get the number "9" sub SCRATCH_1_L ; Check that the lower nibble is the number "9" jcn NZ,PosNotAvail ; Equal, set mode to 9 fim UTILITY_1_P,POS9_RAM ; Select RAM game board position #9 jun Pos PosNotAvail jms Level15 ; Set level to "15" jms Pitch406HZ ; Set pitch to "sad" jms Beep ; Tell user that key was pressed jun KeyNotValid1 ; Loop till valid key is pressed ;; Check to see if there is a X or O from a previous turn Pos src UTILITY_1_P ; Tell RAM of selection of board number clb rdm ; Get position #1 RAM charactor jcn NZ,PosNotAvail ; Previous turn X or O ;; Now set the X or O in RAM postion fim SRC_P,PLAYER_MARK_RAM ; Select player mark charactor src SRC_P ; Tell RAM of selection clb ; Make sure it is all clear rdm ; Get player mark charactor from RAM jcn Z,PosNotAvail ; Check for no player selected, ERROR src UTILITY_1_P ; Tell RAM of selection of board number dac ; Decrement accumulator jcn Z,PosX1 ; Now check for X charactor dac ; Decrement accumulatoa again jcn Z,PosO1 ; Now check foa O charactor jun PosNotAvail ; Neither X or O selected, ERROR PosX1 ldm PLAYER_X_CHAR ; Get X charactor wrm ; Write X charactor to RAM game board jun DonePos ; All done PosO1 ldm PLAYER_O_CHAR ; Get O charactor wrm ; Write O charactor to RAM game board jun DonePos ; All done DonePos jms Level5 ; Set level to "5" jms Pitch1116HZ ; Set pitch to "happy" jms Beep ; Tell user that key was pressed jun GetPosP4Rtn org CODE_LOCATION + 0100H ; ORG cause' jcn jump too large ;; First check for a X win ;; Check for 5,1,9 win CheckWin jms Check5X ; Check for X in position #5 jcn Z,Not519X ; Not 5, 1, 9 win jms Check1X ; Check for X in position #1 jcn Z,Not519X ; Not 5, 1, 9 win jms Check9X ; Check for X in position #9 jcn Z,Not519X ; Not 5, 1, 9 win jun XWin ; X has won ;; Check for 5,3,7 win Not519X jms Check5X jcn Z,Not537X jms Check3X jcn Z,Not537X jms Check7X jcn Z,Not537X jun XWin ;; Check for 5,4,6 win Not537X jms Check5X jcn Z,Not546X jms Check4X jcn Z,Not546X jms Check6X jcn Z,Not546X jun XWin ;; Check for 5,2,8 win Not546X jms Check5X jcn Z,Not528X jms Check2X jcn Z,Not528X jms Check8X jcn Z,Not528X jun XWin ;; Check for 1,2,3 win Not528X jms Check1X jcn Z,Not123X jms Check2X jcn Z,Not123X jms Check3X jcn Z,Not123X jun XWin ;; Check for 1,4,7 win Not123X jms Check1X jcn Z,Not147X jms Check4X jcn Z,Not147X jms Check7X jcn Z,Not147X jun XWin ;; Check for 7,8,9 win Not147X jms Check7X jcn Z,Not789X jms Check8X jcn Z,Not789X jms Check9X jcn Z,Not789X jun XWin ;; Check for 3,6,9 win Not789X jms Check3X jcn Z,Not369X jms Check6X jcn Z,Not369X jms Check9X jcn Z,Not369X jun XWin ;; Now check for a O win ;; Check for 5,1,9 win Not369X jms Check5O jcn Z,Not519O jms Check1O jcn Z,Not519O jms Check9O jcn Z,Not519O jun OWin ;; Check for 5,3,7 win Not519O jms Check5O jcn Z,Not537O jms Check3O jcn Z,Not537O jms Check7O jcn Z,Not537O jun OWin ;; Check for 5,4,6 win Not537O jms Check5O jcn Z,Not546O jms Check4O jcn Z,Not546O jms Check6O jcn Z,Not546O jun OWin ;; Check for 5,2,8 win Not546O jms Check5O jcn Z,Not528O jms Check2O jcn Z,Not528O jms Check8O jcn Z,Not528O jun OWin ;; Check for 1,2,3 win Not528O jms Check1O jcn Z,Not123O jms Check2O jcn Z,Not123O jms Check3O jcn Z,Not123O jun OWin ;; Check for 1,4,7 win Not123O jms Check1O jcn Z,Not147O jms Check4O jcn Z,Not147O jms Check7O jcn Z,Not147O jun OWin ;; Check for 7,8,9 win Not147O jms Check7O jcn Z,Not789O jms Check8O jcn Z,Not789O jms Check9O jcn Z,Not789O jun OWin ;; Check for 3,6,9 win Not789O jms Check3O jcn Z,Not369O jms Check6O jcn Z,Not369O jms Check9O jcn Z,Not369O jun OWin Not369O jun CheckDraw org CODE_LOCATION + 0200H ; ORG cause' jcn jump too large ;; First check for a X draw ;; Check for 5,1,9 draw CheckDraw fim SRC_P,PLAYER_MARK_RAM ; Select player mark charactor src SRC_P ; Tell RAM of selection clb ; Make sure it is all clear rdm ; Get player mark charactor from RAM jcn Z,CheckDrawO ; Check for draw O ;; Check for 5,1,9 draw CheckDrawX jms Check5O jcn NZ,XD519O jms Check1O jcn NZ,XD519O jms Check9O jcn NZ,XD519O jun NoXDraw ;; Check for 5,3,7 draw XD519O jms Check5O jcn NZ,XD537O jms Check3O jcn NZ,XD537O jms Check7O jcn NZ,XD537O jun NoXDraw ;; Check for 5,4,6 draw XD537O jms Check5O jcn NZ,XD546O jms Check4O jcn NZ,XD546O jms Check6O jcn NZ,XD546O jun NoXDraw ;; Check for 5,2,8 draw XD546O jms Check5O jcn NZ,XD528O jms Check2O jcn NZ,XD528O jms Check8O jcn NZ,XD528O jun NoXDraw ;; Check for 1,2,3 draw XD528O jms Check1O jcn NZ,XD123O jms Check2O jcn NZ,XD123O jms Check3O jcn NZ,XD123O jun NoXDraw ;; Check for 1,4,7 draw XD123O jms Check1O jcn NZ,XD147O jms Check4O jcn NZ,XD147O jms Check7O jcn NZ,XD147O jun NoXDraw ;; Check for 7,8,9 draw XD147O jms Check7O jcn NZ,XD789O jms Check8O jcn NZ,XD789O jms Check9O jcn NZ,XD789O jun NoXDraw ;; Check for 3,6,9 draw XD789O jms Check3O jcn NZ,XDraw jms Check6O jcn NZ,XDraw jms Check9O jcn NZ,XDraw NoXDraw jun CheckWinP4Rtn XDraw ldm RAM_BANK_0 ; Move RAM bank pointer to ACC dcl ; Select RAM bank fim SRC_P,GAME_STATUS_RAM ; Select RAM game status charactor src SRC_P ; Send out RAM charactor selection ldm GS_DRAW ; Get the value to initialize to wrm ; Write init data to storage location jun CheckWinP4Rtn ;; Now check for a O draw ;; Check for 5,1,9 draw CheckDrawO jms Check5X jcn NZ,OD519X jms Check1X jcn NZ,OD519X jms Check9X jcn NZ,OD519X jun NoODraw ;; Check for 5,3,7 draw OD519X jms Check5X jcn NZ,OD537X jms Check3X jcn NZ,OD537X jms Check7X jcn NZ,OD537X jun NoODraw ;; Check for 5,4,6 draw OD537X jms Check5X jcn NZ,OD546X jms Check4X jcn NZ,OD546X jms Check6X jcn NZ,OD546X jun NoODraw ;; Check for 5,2,8 draw OD546X jms Check5X jcn NZ,OD528X jms Check2X jcn NZ,OD528X jms Check8X jcn NZ,OD528X jun NoODraw ;; Check for 1,2,3 draw OD528X jms Check1X jcn NZ,OD123X jms Check2X jcn NZ,OD123X jms Check3X jcn NZ,OD123X jun NoODraw ;; Check for 1,4,7 draw OD123X jms Check1X jcn NZ,OD147X jms Check4X jcn NZ,OD147X jms Check7X jcn NZ,OD147X jun NoODraw ;; Check for 7,8,9 draw OD147X jms Check7X jcn NZ,OD789X jms Check8X jcn NZ,OD789X jms Check9X jcn NZ,OD789X jun NoODraw ;; Check for 3,6,9 draw OD789X jms Check3X jcn NZ,ODraw jms Check6X jcn NZ,ODraw jms Check9X jcn NZ,ODraw NoODraw jun CheckWinP4Rtn ;; Set status charactor in RAM whether draw, O win, or X win ODraw ldm RAM_BANK_0 ; Move RAM bank pointer to ACC dcl ; Select RAM bank fim SRC_P,GAME_STATUS_RAM ; Select RAM game status charactor src SRC_P ; Send out RAM charactor selection ldm GS_DRAW ; Get the value to initialize to wrm ; Write init data to storage location jun CheckWinP4Rtn ; All done, go home XWin ldm RAM_BANK_0 ; Move RAM bank pointer to ACC dcl ; Select RAM bank fim SRC_P,GAME_STATUS_RAM ; Select RAM game status charactor src SRC_P ; Send out RAM charactor selection ldm GS_XWIN ; Get the value to initialize to wrm ; Write init data to storage location jun CheckWinP4Rtn ; All done, go home OWin ldm RAM_BANK_0 ; Move RAM bank pointer to ACC dcl ; Select RAM bank fim SRC_P,GAME_STATUS_RAM ; Select RAM game status charactor src SRC_P ; Send out RAM charactor selection ldm GS_OWIN ; Get the value to initialize to wrm ; Write init data to storage location jun CheckWinP4Rtn ; All done, go home ;; Board checking routines ;; Returns a true/false in accumulator Check1X fim SRC_P,POS1_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes1X ; If X, return with true bbl FALSE ; Return false Yes1X bbl TRUE ; Return true Check2X fim SRC_P,POS2_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes2X ; If X, return with true bbl FALSE ; Return false Yes2X bbl TRUE ; Return true Check3X fim SRC_P,POS3_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes3X ; If X, return with true bbl FALSE ; Return false Yes3X bbl TRUE ; Return true Check4X fim SRC_P,POS4_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes4X ; If X, return with true bbl FALSE ; Return false Yes4X bbl TRUE ; Return true Check5X fim SRC_P,POS5_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes5X ; If X, return with true bbl FALSE ; Return false Yes5X bbl TRUE ; Return true Check6X fim SRC_P,POS6_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes6X ; If X, return with true bbl FALSE ; Return false Yes6X bbl TRUE ; Return true Check7X fim SRC_P,POS7_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes7X ; If X, return with true bbl FALSE ; Return false Yes7X bbl TRUE ; Return true Check8X fim SRC_P,POS8_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes8X ; If X, return with true bbl FALSE ; Return false Yes8X bbl TRUE ; Return true Check9X fim SRC_P,POS9_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_X_CHAR ; Get the X charactor sbm ; Test is game board position is an X jcn Z,Yes9X ; If X, return with true bbl FALSE ; Return false Yes9X bbl TRUE ; Return true Check1O fim SRC_P,POS1_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes1O ; If O, return with true bbl FALSE ; Return false Yes1O bbl TRUE ; Return true Check2O fim SRC_P,POS2_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes2O ; If O, return with true bbl FALSE ; Return false Yes2O bbl TRUE ; Return true Check3O fim SRC_P,POS3_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes3O ; If O, return with true bbl FALSE ; Return false Yes3O bbl TRUE ; Return true Check4O fim SRC_P,POS4_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes4O ; If O, return with true bbl FALSE ; Return false Yes4O bbl TRUE ; Return true Check5O fim SRC_P,POS5_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes5O ; If O, return with true bbl FALSE ; Return false Yes5O bbl TRUE ; Return true Check6O fim SRC_P,POS6_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes6O ; If O, return with true bbl FALSE ; Return false Yes6O bbl TRUE ; Return true Check7O fim SRC_P,POS7_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes7O ; If O, return with true bbl FALSE ; Return false Yes7O bbl TRUE ; Return true Check8O fim SRC_P,POS8_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes8O ; If O, return with true bbl FALSE ; Return false Yes8O bbl TRUE ; Return true Check9O fim SRC_P,POS9_RAM ; Select RAM game board position src SRC_P ; Send out RAM charactor selection clb ; Make sure accumulator is clear ldm PLAYER_O_CHAR ; Get the O charactor sbm ; Test is game board position is an O jcn Z,Yes9O ; If O, return with true bbl FALSE ; Return false Yes9O bbl TRUE ; Return true