Microcontrollers · In the CV
Tic-Tac-Toe on 8051
Programmed a keypad-controlled Tic-Tac-Toe game with a two-player mode and an AI opponent.
- 8051 (AT89C51)
- Assembly
- Proteus
About
A Tic-Tac-Toe game for the 8051 microcontroller, written in assembly and simulated in Proteus. It offers Player vs Player and Player vs AI modes, takes input from a keypad, shows the game status on an LCD, and detects valid moves, wins, draws and resets.
Source code
TicTacToe(Final).asm
ORG 0000H
CELL1 EQU 30H
CELL2 EQU 31H
CELL3 EQU 32H
CELL4 EQU 33H
CELL5 EQU 34H
CELL6 EQU 35H
CELL7 EQU 36H
CELL8 EQU 37H
CELL9 EQU 38H
CURPLAYER EQU 39H
MODEVAR EQU 3AH
MOVECOUNT EQU 3BH
SELCELL EQU 3CH
MARKTMP EQU 3DH
START:
MOV P0, #0FFH
MOV P1, #0FFH
MOV P2, #0FFH
MOV P3, #0FFH
LCALL DELAY_BIG
LCALL LCD_INIT
MODE_SCREEN:
LCALL SHOW_MODE_SELECT
WAIT_MODE_KEY:
LCALL SCAN_KEY
JZ WAIT_MODE_KEY
MOV R4, A
WAIT_MODE_RELEASE:
LCALL SCAN_KEY
JNZ WAIT_MODE_RELEASE
MOV A, R4
CJNE A, #2AH, CHECK_AI_MODE
MOV MODEVAR, #01H
SJMP MODE_DONE
CHECK_AI_MODE:
CJNE A, #23H, WAIT_MODE_KEY
MOV MODEVAR, #02H
MODE_DONE:
LCALL GAME_INIT
MAIN_LOOP:
LCALL SCAN_KEY
JZ MAIN_LOOP
MOV R4, A
WAIT_KEY_RELEASE:
LCALL SCAN_KEY
JNZ WAIT_KEY_RELEASE
MOV A, R4
CJNE A, #30H, NOT_ZERO_KEY
LCALL GAME_INIT
SJMP MAIN_LOOP
NOT_ZERO_KEY:
LCALL PROCESS_KEY
SJMP MAIN_LOOP
;---------------------------------
; INITIALIZE / NEW GAME
;---------------------------------
GAME_INIT:
MOV CELL1, #00H
MOV CELL2, #00H
MOV CELL3, #00H
MOV CELL4, #00H
MOV CELL5, #00H
MOV CELL6, #00H
MOV CELL7, #00H
MOV CELL8, #00H
MOV CELL9, #00H
MOV CURPLAYER, #01H
MOV MOVECOUNT, #00H
MOV SELCELL, #00H
MOV P0, #0FFH
MOV P2, #0FFH
SETB P1.6
SETB P1.7
LCALL SHOW_TURN
RET
;---------------------------------
; PROCESS ONLY 1 TO 9
; 0 = NEW GAME already handled
; * and # ignored during game
;---------------------------------
PROCESS_KEY:
CJNE A, #31H, CHECK_KEY_2
LCALL HANDLE_CELL_1
RET
CHECK_KEY_2:
CJNE A, #32H, CHECK_KEY_3
LCALL HANDLE_CELL_2
RET
CHECK_KEY_3:
CJNE A, #33H, CHECK_KEY_4
LCALL HANDLE_CELL_3
RET
CHECK_KEY_4:
CJNE A, #34H, CHECK_KEY_5
LCALL HANDLE_CELL_4
RET
CHECK_KEY_5:
CJNE A, #35H, CHECK_KEY_6
LCALL HANDLE_CELL_5
RET
CHECK_KEY_6:
CJNE A, #36H, CHECK_KEY_7
LCALL HANDLE_CELL_6
RET
CHECK_KEY_7:
CJNE A, #37H, CHECK_KEY_8
LCALL HANDLE_CELL_7
RET
CHECK_KEY_8:
CJNE A, #38H, CHECK_KEY_9
LCALL HANDLE_CELL_8
RET
CHECK_KEY_9:
CJNE A, #39H, IGNORE_KEY
LCALL HANDLE_CELL_9
RET
IGNORE_KEY:
RET
;---------------------------------
; CELL 1
;---------------------------------
HANDLE_CELL_1:
MOV SELCELL, #01H
MOV A, CELL1
JZ CELL1_EMPTY
LCALL INVALID_MOVE
RET
CELL1_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL1_PLACE_O
CELL1_PLACE_X:
MOV CELL1, #01H
CLR P0.0
SETB P2.0
LCALL AFTER_VALID_MOVE
RET
CELL1_PLACE_O:
MOV CELL1, #02H
SETB P0.0
CLR P2.0
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 2
;---------------------------------
HANDLE_CELL_2:
MOV SELCELL, #02H
MOV A, CELL2
JZ CELL2_EMPTY
LCALL INVALID_MOVE
RET
CELL2_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL2_PLACE_O
CELL2_PLACE_X:
MOV CELL2, #01H
CLR P0.1
SETB P2.1
LCALL AFTER_VALID_MOVE
RET
CELL2_PLACE_O:
MOV CELL2, #02H
SETB P0.1
CLR P2.1
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 3
;---------------------------------
HANDLE_CELL_3:
MOV SELCELL, #03H
MOV A, CELL3
JZ CELL3_EMPTY
LCALL INVALID_MOVE
RET
CELL3_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL3_PLACE_O
CELL3_PLACE_X:
MOV CELL3, #01H
CLR P0.2
SETB P2.2
LCALL AFTER_VALID_MOVE
RET
CELL3_PLACE_O:
MOV CELL3, #02H
SETB P0.2
CLR P2.2
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 4
;---------------------------------
HANDLE_CELL_4:
MOV SELCELL, #04H
MOV A, CELL4
JZ CELL4_EMPTY
LCALL INVALID_MOVE
RET
CELL4_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL4_PLACE_O
CELL4_PLACE_X:
MOV CELL4, #01H
CLR P0.3
SETB P2.3
LCALL AFTER_VALID_MOVE
RET
CELL4_PLACE_O:
MOV CELL4, #02H
SETB P0.3
CLR P2.3
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 5
;---------------------------------
HANDLE_CELL_5:
MOV SELCELL, #05H
MOV A, CELL5
JZ CELL5_EMPTY
LCALL INVALID_MOVE
RET
CELL5_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL5_PLACE_O
CELL5_PLACE_X:
MOV CELL5, #01H
CLR P0.4
SETB P2.4
LCALL AFTER_VALID_MOVE
RET
CELL5_PLACE_O:
MOV CELL5, #02H
SETB P0.4
CLR P2.4
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 6
;---------------------------------
HANDLE_CELL_6:
MOV SELCELL, #06H
MOV A, CELL6
JZ CELL6_EMPTY
LCALL INVALID_MOVE
RET
CELL6_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL6_PLACE_O
CELL6_PLACE_X:
MOV CELL6, #01H
CLR P0.5
SETB P2.5
LCALL AFTER_VALID_MOVE
RET
CELL6_PLACE_O:
MOV CELL6, #02H
SETB P0.5
CLR P2.5
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 7
;---------------------------------
HANDLE_CELL_7:
MOV SELCELL, #07H
MOV A, CELL7
JZ CELL7_EMPTY
LCALL INVALID_MOVE
RET
CELL7_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL7_PLACE_O
CELL7_PLACE_X:
MOV CELL7, #01H
CLR P0.6
SETB P2.6
LCALL AFTER_VALID_MOVE
RET
CELL7_PLACE_O:
MOV CELL7, #02H
SETB P0.6
CLR P2.6
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 8
;---------------------------------
HANDLE_CELL_8:
MOV SELCELL, #08H
MOV A, CELL8
JZ CELL8_EMPTY
LCALL INVALID_MOVE
RET
CELL8_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL8_PLACE_O
CELL8_PLACE_X:
MOV CELL8, #01H
CLR P0.7
SETB P2.7
LCALL AFTER_VALID_MOVE
RET
CELL8_PLACE_O:
MOV CELL8, #02H
SETB P0.7
CLR P2.7
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; CELL 9
;---------------------------------
HANDLE_CELL_9:
MOV SELCELL, #09H
MOV A, CELL9
JZ CELL9_EMPTY
LCALL INVALID_MOVE
RET
CELL9_EMPTY:
MOV A, CURPLAYER
CJNE A, #01H, CELL9_PLACE_O
CELL9_PLACE_X:
MOV CELL9, #01H
CLR P1.6
SETB P1.7
LCALL AFTER_VALID_MOVE
RET
CELL9_PLACE_O:
MOV CELL9, #02H
SETB P1.6
CLR P1.7
LCALL AFTER_VALID_MOVE
RET
;---------------------------------
; AFTER VALID MOVE
;---------------------------------
AFTER_VALID_MOVE:
INC MOVECOUNT
LCALL CHECK_WIN
JZ CHECK_DRAW_NOW
LCALL SHOW_WIN_SCREEN
LCALL WAIT_NEW_GAME
RET
CHECK_DRAW_NOW:
MOV A, MOVECOUNT
CJNE A, #09H, SWITCH_PLAYER_NOW
LCALL SHOW_DRAW_SCREEN
LCALL WAIT_NEW_GAME
RET
SWITCH_PLAYER_NOW:
MOV A, CURPLAYER
CJNE A, #01H, SWITCH_TO_X
SWITCH_TO_O:
MOV CURPLAYER, #02H
MOV A, MODEVAR
CJNE A, #02H, SHOW_O_MANUAL
LCALL SHOW_AI_TURN
LCALL DELAY_BIG
LCALL DELAY_BIG
LCALL AI_TURN
RET
SHOW_O_MANUAL:
LCALL SHOW_TURN
RET
SWITCH_TO_X:
MOV CURPLAYER, #01H
LCALL SHOW_TURN
RET
;---------------------------------
; INVALID MOVE MESSAGE
;---------------------------------
INVALID_MOVE:
LCALL LCD_CLEAR
MOV A, #80H
LCALL LCD_CMD
MOV DPTR, #MSG_INV1
LCALL LCD_PRINT
MOV A, #0C0H
LCALL LCD_CMD
MOV DPTR, #MSG_INV2
LCALL LCD_PRINT
LCALL DELAY_BIG
LCALL DELAY_BIG
LCALL SHOW_TURN
RET
CHECK_WIN:
; Row 1: 1,2,3
MOV A, CELL1
JZ CW_ROW2
CJNE A, CELL2, CW_ROW2
MOV A, CELL1
CJNE A, CELL3, CW_ROW2
MOV A, #01H
RET
CW_ROW2:
; Row 2: 4,5,6
MOV A, CELL4
JZ CW_ROW3
CJNE A, CELL5, CW_ROW3
MOV A, CELL4
CJNE A, CELL6, CW_ROW3
MOV A, #01H
RET
CW_ROW3:
; Row 3: 7,8,9
MOV A, CELL7
JZ CW_COL1
CJNE A, CELL8, CW_COL1
MOV A, CELL7
CJNE A, CELL9, CW_COL1
MOV A, #01H
RET
CW_COL1:
; Col 1: 1,4,7
MOV A, CELL1
JZ CW_COL2
CJNE A, CELL4, CW_COL2
MOV A, CELL1
CJNE A, CELL7, CW_COL2
MOV A, #01H
RET
CW_COL2:
; Col 2: 2,5,8
MOV A, CELL2
JZ CW_COL3
CJNE A, CELL5, CW_COL3
MOV A, CELL2
CJNE A, CELL8, CW_COL3
MOV A, #01H
RET
CW_COL3:
; Col 3: 3,6,9
MOV A, CELL3
JZ CW_DIAG1
CJNE A, CELL6, CW_DIAG1
MOV A, CELL3
CJNE A, CELL9, CW_DIAG1
MOV A, #01H
RET
CW_DIAG1:
; Diagonal 1: 1,5,9
MOV A, CELL1
JZ CW_DIAG2
CJNE A, CELL5, CW_DIAG2
MOV A, CELL1
CJNE A, CELL9, CW_DIAG2
MOV A, #01H
RET
CW_DIAG2:
; Diagonal 2: 3,5,7
MOV A, CELL3
JZ CW_NOWIN
CJNE A, CELL5, CW_NOWIN
MOV A, CELL3
CJNE A, CELL7, CW_NOWIN
MOV A, #01H
RET
CW_NOWIN:
MOV A, #00H
RET
SHOW_WIN_SCREEN:
LCALL LCD_CLEAR
MOV A, #80H
LCALL LCD_CMD
MOV A, CURPLAYER
CJNE A, #01H, SHOW_O_WIN
SHOW_X_WIN:
MOV DPTR, #MSG_XWIN
LCALL LCD_PRINT
SJMP SHOW_PRESS0_LINE
SHOW_O_WIN:
MOV DPTR, #MSG_OWIN
LCALL LCD_PRINT
SHOW_PRESS0_LINE:
MOV A, #0C0H
LCALL LCD_CMD
MOV DPTR, #MSG_NEW
LCALL LCD_PRINT
RET
SHOW_DRAW_SCREEN:
LCALL LCD_CLEAR
MOV A, #80H
LCALL LCD_CMD
MOV DPTR, #MSG_DRAW
LCALL LCD_PRINT
MOV A, #0C0H
LCALL LCD_CMD
MOV DPTR, #MSG_NEW
LCALL LCD_PRINT
RET
WAIT_NEW_GAME:
WAIT_NEW_GAME_KEY:
LCALL SCAN_KEY
JZ WAIT_NEW_GAME_KEY
CJNE A, #30H, WAIT_NEW_GAME_KEY
WAIT_NEW_GAME_RELEASE:
LCALL SCAN_KEY
JNZ WAIT_NEW_GAME_RELEASE
LCALL GAME_INIT
RET
;---------------------------------
; SHOW MODE SELECTION
;---------------------------------
SHOW_MODE_SELECT:
LCALL LCD_CLEAR
MOV A, #80H
LCALL LCD_CMD
MOV DPTR, #MSG_SEL1
LCALL LCD_PRINT
MOV A, #0C0H
LCALL LCD_CMD
MOV DPTR, #MSG_SEL2
LCALL LCD_PRINT
RET
;---------------------------------
; SHOW CURRENT TURN
;---------------------------------
SHOW_TURN:
LCALL LCD_CLEAR
MOV A, MODEVAR
CJNE A, #01H, SHOW_AI_MODE
SHOW_PVP_MODE:
MOV A, #80H
LCALL LCD_CMD
MOV DPTR, #MSG_PVP
LCALL LCD_PRINT
SJMP SHOW_PLAYER_LINE
SHOW_AI_MODE:
MOV A, #80H
LCALL LCD_CMD
MOV DPTR, #MSG_PVAI
LCALL LCD_PRINT
SHOW_PLAYER_LINE:
MOV A, CURPLAYER
CJNE A, #01H, SHOW_O_TURN
SHOW_X_TURN:
MOV A, #0C0H
LCALL LCD_CMD
MOV DPTR, #MSG_XTURN
LCALL LCD_PRINT
RET
SHOW_O_TURN:
MOV A, #0C0H
LCALL LCD_CMD
MOV DPTR, #MSG_OTURN
LCALL LCD_PRINT
RET
;---------------------------------
; KEYPAD SCAN
; RETURNS ASCII IN A
; A = 00H IF NO KEY
;---------------------------------
SCAN_KEY:
MOV P3, #0FFH
CLR P3.0
SETB P3.1
SETB P3.2
SETB P3.3
JNB P3.4, KEY_1
JNB P3.5, KEY_2
JNB P3.6, KEY_3
SETB P3.0
CLR P3.1
SETB P3.2
SETB P3.3
JNB P3.4, KEY_4
JNB P3.5, KEY_5
JNB P3.6, KEY_6
SETB P3.0
SETB P3.1
CLR P3.2
SETB P3.3
JNB P3.4, KEY_7
JNB P3.5, KEY_8
JNB P3.6, KEY_9
SETB P3.0
SETB P3.1
SETB P3.2
CLR P3.3
JNB P3.4, KEY_STAR
JNB P3.5, KEY_0
JNB P3.6, KEY_HASH
MOV A, #00H
RET
KEY_1:
MOV A, #31H
RET
KEY_2:
MOV A, #32H
RET
KEY_3:
MOV A, #33H
RET
KEY_4:
MOV A, #34H
RET
KEY_5:
MOV A, #35H
RET
KEY_6:
MOV A, #36H
RET
KEY_7:
MOV A, #37H
RET
KEY_8:
MOV A, #38H
RET
KEY_9:
MOV A, #39H
RET
KEY_0:
MOV A, #30H
RET
KEY_STAR:
MOV A, #2AH
RET
KEY_HASH:
MOV A, #23H
RET
SHOW_AI_TURN:
LCALL LCD_CLEAR
MOV A, #80H
LCALL LCD_CMD
MOV DPTR, #MSG_PVAI
LCALL LCD_PRINT
MOV A, #0C0H
LCALL LCD_CMD
MOV DPTR, #MSG_AITURN
LCALL LCD_PRINT
RET
AI_TURN:
LCALL AI_FIND_WIN
JNZ AI_HAVE_MOVE
LCALL AI_FIND_BLOCK
JNZ AI_HAVE_MOVE
MOV A, CELL5
JNZ AI_CHECK_C1
MOV A, #05H
SJMP AI_HAVE_MOVE
AI_CHECK_C1:
MOV A, CELL1
JNZ AI_CHECK_C3
MOV A, #01H
SJMP AI_HAVE_MOVE
AI_CHECK_C3:
MOV A, CELL3
JNZ AI_CHECK_C7
MOV A, #03H
SJMP AI_HAVE_MOVE
AI_CHECK_C7:
MOV A, CELL7
JNZ AI_CHECK_C9
MOV A, #07H
SJMP AI_HAVE_MOVE
AI_CHECK_C9:
MOV A, CELL9
JNZ AI_FIRST_EMPTY
MOV A, #09H
SJMP AI_HAVE_MOVE
AI_FIRST_EMPTY:
MOV A, CELL1
JNZ AI_FE2
MOV A, #01H
SJMP AI_HAVE_MOVE
AI_FE2:
MOV A, CELL2
JNZ AI_FE3
MOV A, #02H
SJMP AI_HAVE_MOVE
AI_FE3:
MOV A, CELL3
JNZ AI_FE4
MOV A, #03H
SJMP AI_HAVE_MOVE
AI_FE4:
MOV A, CELL4
JNZ AI_FE5
MOV A, #04H
SJMP AI_HAVE_MOVE
AI_FE5:
MOV A, CELL5
JNZ AI_FE6
MOV A, #05H
SJMP AI_HAVE_MOVE
AI_FE6:
MOV A, CELL6
JNZ AI_FE7
MOV A, #06H
SJMP AI_HAVE_MOVE
AI_FE7:
MOV A, CELL7
JNZ AI_FE8
MOV A, #07H
SJMP AI_HAVE_MOVE
AI_FE8:
MOV A, CELL8
JNZ AI_FE9
MOV A, #08H
SJMP AI_HAVE_MOVE
AI_FE9:
MOV A, CELL9
JNZ AI_NO_MOVE
MOV A, #09H
SJMP AI_HAVE_MOVE
AI_NO_MOVE:
RET
AI_HAVE_MOVE:
LCALL PLACE_O_BY_CELL
RET
AI_FIND_WIN:
MOV MARKTMP, #02H
LCALL FIND_TWO_IN_LINE
RET
AI_FIND_BLOCK:
MOV MARKTMP, #01H
LCALL FIND_TWO_IN_LINE
RET
FIND_TWO_IN_LINE:
; Line 1: 1,2,3
MOV A, CELL1
JNZ FT123_B
MOV A, CELL2
CJNE A, MARKTMP, FT123_B
MOV A, CELL3
CJNE A, MARKTMP, FT123_B
MOV A, #01H
RET
FT123_B:
MOV A, CELL2
JNZ FT123_C
MOV A, CELL1
CJNE A, MARKTMP, FT123_C
MOV A, CELL3
CJNE A, MARKTMP, FT123_C
MOV A, #02H
RET
FT123_C:
MOV A, CELL3
JNZ FT456_A
MOV A, CELL1
CJNE A, MARKTMP, FT456_A
MOV A, CELL2
CJNE A, MARKTMP, FT456_A
MOV A, #03H
RET
; Line 2: 4,5,6
FT456_A:
MOV A, CELL4
JNZ FT456_B
MOV A, CELL5
CJNE A, MARKTMP, FT456_B
MOV A, CELL6
CJNE A, MARKTMP, FT456_B
MOV A, #04H
RET
FT456_B:
MOV A, CELL5
JNZ FT456_C
MOV A, CELL4
CJNE A, MARKTMP, FT456_C
MOV A, CELL6
CJNE A, MARKTMP, FT456_C
MOV A, #05H
RET
FT456_C:
MOV A, CELL6
JNZ FT789_A
MOV A, CELL4
CJNE A, MARKTMP, FT789_A
MOV A, CELL5
CJNE A, MARKTMP, FT789_A
MOV A, #06H
RET
; Line 3: 7,8,9
FT789_A:
MOV A, CELL7
JNZ FT789_B
MOV A, CELL8
CJNE A, MARKTMP, FT789_B
MOV A, CELL9
CJNE A, MARKTMP, FT789_B
MOV A, #07H
RET
FT789_B:
MOV A, CELL8
JNZ FT789_C
MOV A, CELL7
CJNE A, MARKTMP, FT789_C
MOV A, CELL9
CJNE A, MARKTMP, FT789_C
MOV A, #08H
RET
FT789_C:
MOV A, CELL9
JNZ FT147_A
MOV A, CELL7
CJNE A, MARKTMP, FT147_A
MOV A, CELL8
CJNE A, MARKTMP, FT147_A
MOV A, #09H
RET
; Line 4: 1,4,7
FT147_A:
MOV A, CELL1
JNZ FT147_B
MOV A, CELL4
CJNE A, MARKTMP, FT147_B
MOV A, CELL7
CJNE A, MARKTMP, FT147_B
MOV A, #01H
RET
FT147_B:
MOV A, CELL4
JNZ FT147_C
MOV A, CELL1
CJNE A, MARKTMP, FT147_C
MOV A, CELL7
CJNE A, MARKTMP, FT147_C
MOV A, #04H
RET
FT147_C:
MOV A, CELL7
JNZ FT258_A
MOV A, CELL1
CJNE A, MARKTMP, FT258_A
MOV A, CELL4
CJNE A, MARKTMP, FT258_A
MOV A, #07H
RET
; Line 5: 2,5,8
FT258_A:
MOV A, CELL2
JNZ FT258_B
MOV A, CELL5
CJNE A, MARKTMP, FT258_B
MOV A, CELL8
CJNE A, MARKTMP, FT258_B
MOV A, #02H
RET
FT258_B:
MOV A, CELL5
JNZ FT258_C
MOV A, CELL2
CJNE A, MARKTMP, FT258_C
MOV A, CELL8
CJNE A, MARKTMP, FT258_C
MOV A, #05H
RET
FT258_C:
MOV A, CELL8
JNZ FT369_A
MOV A, CELL2
CJNE A, MARKTMP, FT369_A
MOV A, CELL5
CJNE A, MARKTMP, FT369_A
MOV A, #08H
RET
; Line 6: 3,6,9
FT369_A:
MOV A, CELL3
JNZ FT369_B
MOV A, CELL6
CJNE A, MARKTMP, FT369_B
MOV A, CELL9
CJNE A, MARKTMP, FT369_B
MOV A, #03H
RET
FT369_B:
MOV A, CELL6
JNZ FT369_C
MOV A, CELL3
CJNE A, MARKTMP, FT369_C
MOV A, CELL9
CJNE A, MARKTMP, FT369_C
MOV A, #06H
RET
FT369_C:
MOV A, CELL9
JNZ FT159_A
MOV A, CELL3
CJNE A, MARKTMP, FT159_A
MOV A, CELL6
CJNE A, MARKTMP, FT159_A
MOV A, #09H
RET
; Line 7: 1,5,9
FT159_A:
MOV A, CELL1
JNZ FT159_B
MOV A, CELL5
CJNE A, MARKTMP, FT159_B
MOV A, CELL9
CJNE A, MARKTMP, FT159_B
MOV A, #01H
RET
FT159_B:
MOV A, CELL5
JNZ FT159_C
MOV A, CELL1
CJNE A, MARKTMP, FT159_C
MOV A, CELL9
CJNE A, MARKTMP, FT159_C
MOV A, #05H
RET
FT159_C:
MOV A, CELL9
JNZ FT357_A
MOV A, CELL1
CJNE A, MARKTMP, FT357_A
MOV A, CELL5
CJNE A, MARKTMP, FT357_A
MOV A, #09H
RET
; Line 8: 3,5,7
FT357_A:
MOV A, CELL3
JNZ FT357_B
MOV A, CELL5
CJNE A, MARKTMP, FT357_B
MOV A, CELL7
CJNE A, MARKTMP, FT357_B
MOV A, #03H
RET
FT357_B:
MOV A, CELL5
JNZ FT357_C
MOV A, CELL3
CJNE A, MARKTMP, FT357_C
MOV A, CELL7
CJNE A, MARKTMP, FT357_C
MOV A, #05H
RET
FT357_C:
MOV A, CELL7
JNZ FT_NONE
MOV A, CELL3
CJNE A, MARKTMP, FT_NONE
MOV A, CELL5
CJNE A, MARKTMP, FT_NONE
MOV A, #07H
RET
FT_NONE:
MOV A, #00H
RET
PLACE_O_BY_CELL:
CJNE A, #01H, POC2
LCALL HANDLE_CELL_1
RET
POC2:
CJNE A, #02H, POC3
LCALL HANDLE_CELL_2
RET
POC3:
CJNE A, #03H, POC4
LCALL HANDLE_CELL_3
RET
POC4:
CJNE A, #04H, POC5
LCALL HANDLE_CELL_4
RET
POC5:
CJNE A, #05H, POC6
LCALL HANDLE_CELL_5
RET
POC6:
CJNE A, #06H, POC7
LCALL HANDLE_CELL_6
RET
POC7:
CJNE A, #07H, POC8
LCALL HANDLE_CELL_7
RET
POC8:
CJNE A, #08H, POC9
LCALL HANDLE_CELL_8
RET
POC9:
CJNE A, #09H, POC_DONE
LCALL HANDLE_CELL_9
RET
POC_DONE:
RET
;---------------------------------
; LCD ROUTINES
;---------------------------------
LCD_INIT:
MOV A, #33H
LCALL LCD_CMD
MOV A, #32H
LCALL LCD_CMD
MOV A, #28H
LCALL LCD_CMD
MOV A, #0CH
LCALL LCD_CMD
MOV A, #06H
LCALL LCD_CMD
MOV A, #01H
LCALL LCD_CMD
LCALL DELAY_BIG
RET
LCD_CLEAR:
MOV A, #01H
LCALL LCD_CMD
LCALL DELAY_BIG
RET
LCD_CMD:
CLR P1.0
LCALL LCD_WRITE
RET
LCD_DATA:
SETB P1.0
LCALL LCD_WRITE
RET
LCD_WRITE:
MOV R7, A
SWAP A
ANL A, #0FH
LCALL LCD_NIBBLE
MOV A, R7
ANL A, #0FH
LCALL LCD_NIBBLE
LCALL DELAY_SMALL
RET
LCD_NIBBLE:
RL A
RL A
MOV R6, A
MOV A, P1
ANL A, #0C3H
ORL A, R6
MOV P1, A
SETB P1.1
LCALL DELAY_SMALL
CLR P1.1
RET
LCD_PRINT:
NEXT_CHAR:
CLR A
MOVC A, @A+DPTR
JZ PRINT_DONE
LCALL LCD_DATA
INC DPTR
SJMP NEXT_CHAR
PRINT_DONE:
RET
;---------------------------------
; DELAYS
;---------------------------------
DELAY_SMALL:
MOV R5, #50
DS1:
DJNZ R5, DS1
RET
DELAY_BIG:
MOV R7, #40
DB1:
MOV R6, #255
DB2:
MOV R5, #255
DB3:
DJNZ R5, DB3
DJNZ R6, DB2
DJNZ R7, DB1
RET
;---------------------------------
; MESSAGES
;---------------------------------
MSG_SEL1:
DB '*:PVP #:AI', 00H
MSG_SEL2:
DB 'SELECT MODE', 00H
MSG_PVP:
DB 'MODE: PVP', 00H
MSG_PVAI:
DB 'MODE: PVAI', 00H
MSG_XTURN:
DB 'X TURN', 00H
MSG_OTURN:
DB 'O TURN', 00H
MSG_INV1:
DB 'INVALID MOVE', 00H
MSG_INV2:
DB 'TRY AGAIN', 00H
MSG_XWIN:
DB 'X WINS', 00H
MSG_OWIN:
DB 'O WINS', 00H
MSG_DRAW:
DB 'MATCH DRAW', 00H
MSG_NEW:
DB 'PRESS 0', 00H
MSG_AITURN:
DB 'AI TURN', 00H
END