;Leung, Min Jee (Andy) & Kenneth Kwok ;Final Project: Black Jack .include "c:\users\k&a\8535def.inc" .device AT90S8535 .include "c:\users\k&a\final\macro.inc" ;*********************** .def hundreds=r2 .def tens =r3 .def ones =r4 .def rones=r5 .def rzeros=r6 .def tempran0 =r7 .def tempran1 =r8 .def tempran2 =r9 .def param1a =r10 .def param1b =r11 .def param2a =r12 .def param2b =r13 .def count =r14 ;counter for random number generation .def count1=r15 .def random =r17 .def temp =r16 ;temporary register .def savSREG =r18 ;save the status register .def TXbusy =r19 ;transmit busy flag .def RXchar =r20 ;a received character .def TXflash =r21 ;text to be sent is in flash if <>0 .def temp1 =r22 .def temp2 =r23 .def remainder=r24 .def random_ptr = r25 ;pointer to a card in the random array .def response = r26 .def mode = r27 .equ baud96 =25 ;9600 baud constant for 4Mhz crystal .equ tteen =13 .equ go ='g' ;0x67 ascii 'g' .equ stop ='s' ;0x73 ascii 's' .equ azero ='0' ;0x30 ascii '0' .equ one ='1' .equ two ='2' .equ n ='n' .equ r ='r' .equ q ='q' .equ hit ='h' .equ double ='d' .equ stand ='s' .equ tee = 'T' .equ jay = 'J' .equ cue = 'Q' .equ kay = 'K' .equ ay = 'A' .equ dee = 'D' .equ cee = 'C' .equ haych = 'H' .equ es = 'S' .equ space = ' ' ;************************************** .dseg ;define variable strings to be tranmitted from RAM ;if have time, implement player's name as well ;playername: .byte 11 ;no longer than 10 chars + a zero terminate Ppoints: .byte 1 ;to store player's points cards: .byte 10 ;to store the ten cards generated randomly bet: .byte 1 ;player's current bet Phand: .byte 1 ;player's current hand Dhand: .byte 1 ;dealer's current hand PAce: .byte 1 ; Ace = 0:no Ace in hand =1: has Ace in hand for player DAce: .byte 1 ; Ace = 0:no Ace in hand =1: has Ace in hand for dealer Busted: .byte 1 ; not 0: hand is greater than 21 BlackJack: .byte 1 ; not 0: hand is equal 21 Dsuit1: .byte 1 Dcardnum1: .byte 1 Dsuit2: .byte 1 Dcardnum2: .byte 1 Dsuit3: .byte 1 Dcardnum3: .byte 1 Dsuit4: .byte 1 Dcardnum4: .byte 1 Dsuit5: .byte 1 Dcardnum5: .byte 1 Psuit1: .byte 1 Pcardnum1: .byte 1 Psuit2: .byte 1 Pcardnum2: .byte 1 Psuit3: .byte 1 Pcardnum3: .byte 1 Psuit4: .byte 1 Pcardnum4: .byte 1 Psuit5: .byte 1 Pcardnum5: .byte 1 str_ptr: .byte 4 ;************************************** .cseg .org $0000 rjmp RESET ;reset entry vector reti reti reti reti reti reti reti reti rjmp T0ovfl reti rjmp RXdone ;UART receive done rjmp TXempty ;UART buffer empty reti reti reti reti nextround_txt: .db "Press 'n' to play next round or", 0x00 resetquit_txt: .db "Press 'r' to start a new game or", 0x00 resetquit_txt1: .db "Press 'q' to quit the game: ", 0x00 welcome_txt: .db "Welcome to try our Black Jack!", 0x00 welcome_txt1: .db "Please press 'g' to start the game: ", 0x00 win_txt: .db "You win!", 0x00 lose_txt: .db "You lose.", 0x00 tie_txt: .db "Tied Game!", 0x00 crlf: .db 0x0d, 0x0a, 0x00 ;carrage return/line feed ;define fixed strings to be tranmitted from flash- zero terminated junk: .db "This space stores junks.......................", 0x00 points: .db "Your Current Points: ", 0x00 bet_txt: .db "How many points do you want to bet? (1 or 2): ", 0x00 bust_txt: .db "Your hand is busted!", 0x00 action_dd_txt: .db "or 'd' for 'double down':", 0x00 action_ndd_txt: .db "Press 'h' for 'hit me', or 's' for 'stand': ", 0x00 bj_txt: .db "You have a Black Jack!", 0x00 dealer_txt: .db "Dealer's Hand: ", 0x00 player_txt: .db "Player's Hand: ", 0x00 dfirst_txt: .db "XX ", 0x00 junk2: .db "This space is somehow linked to junk....", 0x00 gameover: .db "You have no more points left. Game Over!", 0x00 RESET: ldi temp, LOW(RAMEND) ;setup stack pointer out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ldi temp,1 mov rones, temp ldi temp, 0 mov rzeros, temp ldi temp, 0b01011010 ; for random number generator mov count, temp ldi temp, 0b01000000 ; for random number generator mov count1, temp ;initial conditions clr TXbusy ;start out not busy on TX ldi RXchar, stop ;start out not running ;setup UART -- enable TXempty & RXdone int, and RX, TX pins ldi temp, 0b10111000 out UCR, temp ;set baud rate to 9600 ldi temp, baud96 out UBRR, temp ldi Temp,exp2(TOIE0);enable timer interrupt out TIMSK, Temp ldi temp, 0 out TCCR0, temp ser temp ;set PORTB to be out DDRB, temp ;all outputs ;out PORTB, temp out DDRD, temp ;intialize text pointer BEFORE turning on interrupts ;because RESET causes the TX empty flag to be SET ldi ZL, LOW(crlf<<1) ;do shift to convert word-addr to byte ldi ZH, HIGH(crlf<<1) sei ; enable global interrupts and wait for Rxdone interrupt ;now print three strings and wait for incoming character interrupt ;clr TXbusy ;start out not busy on TX ; display banner of "Welcome to try our Black Jack" out of reset ;now the pointer to the preset message tx_text_predefined crlf tx_text_predefined welcome_txt tx_text_predefined crlf tx_text_predefined welcome_txt1 ; wait for player to hit the "start" button sbi PORTB, 3 startWait: sub count, rones sbc count1, rzeros sbis PINC, 3 rjmp startWait ; rjmp startExit ;cp_go: cpi RXchar, go ;wait for go signal - a 'g' on the keyboard ; brne startWait ;startExit: cbi PORTB, 3 tx_text_predefined crlf ; ask player to enter his/her name if we have time to implement this ; rcall get_name ;store player's name into ram newGame: ; At the beginning, player has 10 points. ldi_ram Ppoints, 10 tx_text_predefined crlf rcall display_points nextGame: ; initialize some registers' values rcall get_random ldi_ram Phand, 0 ; player's current hand ldi_ram Dhand, 0 ; dealer's current hand ldi_ram PAce, 0 ; Ace = 0:no Ace in hand else: has Ace in hand for player ldi_ram DAce, 0 ; Ace = 0:no Ace in hand else: has Ace in hand for dealer ldi_ram Busted, 0 ; not 0: hand is greater than 21 ldi_ram BlackJack, 0 ; not 0: hand is equal 21 ;initialize all cards to -1 first -- this is for display purpose ldi_ram Dsuit1, -1 ldi_ram Dcardnum1, -1 ldi_ram Dsuit2, -1 ldi_ram Dcardnum2, -1 ldi_ram Dsuit3, -1 ldi_ram Dcardnum3, -1 ldi_ram Dsuit4, -1 ldi_ram Dcardnum4, -1 ldi_ram Dsuit5, -1 ldi_ram Dcardnum5, -1 ldi_ram Psuit1, -1 ldi_ram Pcardnum1, -1 ldi_ram Psuit2, -1 ldi_ram Pcardnum2, -1 ldi_ram Psuit3, -1 ldi_ram Pcardnum3, -1 ldi_ram Psuit4, -1 ldi_ram Pcardnum4, -1 ldi_ram Psuit5, -1 ldi_ram Pcardnum5, -1 mov random_ptr, rzeros ;first element in the array ; ask player how much he/she wants to bet for this game tx_text_predefined crlf tx_text_predefined bet_txt ;wait for player to enter the bet betWait: sbi PORTB, 6 sbi PORTB, 7 sbis PINC, 7 rjmp cp_b2 rjmp betExit1 cp_b2: sbis PINC, 6 rjmp betWait ; cpi RXchar, one ; breq betExit ; cpi RXchar, two ; brne betWait betExit2: ldi temp, 1 ld_ram bet, temp rjmp betExit betExit1: ldi temp, 2 ld_ram bet, temp betExit: cbi PORTB, 6 cbi PORTB, 7 tx_text_predefined crlf ; store player's bet into variable bet ; mov temp, Rxchar ; subi temp, azero ; convert from ascii to number ; ld_ram bet, temp ; deal 2 cards to dealer and 2 cards to player ; get the first random # into register random ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Dsuit1, Dcardnum1, DAce ; dealer's 1st card (hidden) st_ram temp, Dcardnum1 cpi temp, 10 brlt dc1_10 addi_ram Dhand, 10 rjmp dc1a_10 dc1_10: add_ram Dhand, Dcardnum1 dc1a_10: ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Psuit1, Pcardnum1, PAce ; player's 1st card st_ram temp, Pcardnum1 cpi temp, 10 brlt pc1_10 addi_ram Phand, 10 rjmp pc1a_10 pc1_10: add_ram Phand, Pcardnum1 pc1a_10: ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Dsuit2, Dcardnum2, DAce ; dealer's 2nd card st_ram temp, Dcardnum2 cpi temp, 10 brlt dc2_10 addi_ram Dhand, 10 rjmp dc2a_10 dc2_10: add_ram Dhand, Dcardnum2 dc2a_10: ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Psuit2, Pcardnum2, PAce ; player's 2nd card st_ram temp, Pcardnum2 cpi temp, 10 brlt pc2_10 addi_ram Phand, 10 rjmp pc2a_10 pc2_10: add_ram Phand, Pcardnum2 pc2a_10: ; display one of dealer's card and both of player's cards ldi mode, 0; display mode rcall display; display cards on screen depends on mode rcall check_bj ; store status of black jack into register BlackJack tst_ram BlackJack breq Pcard3 add_ram bet, bet; double the bet rjmp playerWon ;now player need to decide to choose "hit me", "stand" or "double down" ;response = 0:hit me; 1:double down; 2:stand Pcard3: ldi mode, 0 rcall get_response ; store player's action into register response cpi response, 0 brne doubleDown3_temp ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Psuit3, Pcardnum3, PAce rjmp dd3_after doubleDown3_temp: rjmp doubleDown3 ;branch too long dd3_after: st_ram temp, Pcardnum3 cpi temp, 10 brlt pc3_10 addi_ram Phand, 10 rjmp pc3a_10 pc3_10: add_ram Phand, Pcardnum3 pc3a_10: ldi mode, 1 rcall display st_ram temp, Phand rcall check_busted ; store status of busted into register Busted tst_ram Busted brne pl1a rcall check_bj ; store status of black jack into register BlackJack tst_ram BlackJack breq Pcard4a add_ram bet, bet; double the bet rjmp pw1 pl1a: tx_text_predefined bust_txt tx_text_predefined crlf rjmp pl1 ; branch too long doubleDown3: cpi response, 1 brne dt1a add_ram bet, bet ; double the bet ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z rjmp Pcard4a_after Pcard4a:rjmp Pcard4 dt1a: rjmp dt1 Pcard4a_after: mod random, 13, Psuit3, Pcardnum3, PAce st_ram temp, Pcardnum3 cpi temp, 10 brlt pc3_10a addi_ram Phand, 10 rjmp pc3a_10a pc3_10a: add_ram Phand, Pcardnum3 pc3a_10a: rjmp temp_tag1 dt1: rjmp dt2 pl1: rjmp pl2 ; branch too long pw1: rjmp pw2 temp_tag1: ldi mode, 1 rcall display st_ram temp, Phand rcall check_busted ; store status of busted into register Busted tst_ram Busted brne pl2a rcall check_bj ; store status of black jack into register BlackJack tst_ram BlackJack breq dt2a add_ram bet, bet; double the bet rjmp pw2 pl2a: tx_text_predefined bust_txt tx_text_predefined crlf rjmp pl2 dt2a: rjmp dt2 Pcard4: ldi mode, 1 rcall get_response ; store player's action into register response cpi response, 0 brne dt2 ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Psuit4, Pcardnum4, PAce st_ram temp, Pcardnum4 cpi temp, 10 brlt pc4_10 addi_ram Phand, 10 rjmp pc4a_10 pc4_10: add_ram Phand, Pcardnum4 pc4a_10: rjmp temp_tag2 dt2: rjmp dt3 pl2: rjmp pl3 ; branch too long pw2: rjmp pw3 temp_tag2: ldi mode, 2 rcall display st_ram temp, Phand rcall check_busted ; store status of busted into register Busted tst_ram Busted brne pl3a rcall check_bj ; store status of black jack into register BlackJack tst_ram BlackJack breq Pcard5 add_ram bet, bet; double the bet rjmp pw3 pl3a: tx_text_predefined bust_txt tx_text_predefined crlf rjmp pl3 Pcard5: ldi mode, 1 rcall get_response ; store player's action into register response cpi response, 0 brne dt3 ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Psuit5, Pcardnum5, PAce st_ram temp, Pcardnum5 cpi temp, 10 brlt pc5_10 addi_ram Phand, 10 rjmp pc5a_10 pc5_10: add_ram Phand, Pcardnum5 pc5a_10: rjmp temp_tag3 dt3: rjmp dealersTurn pl3: rjmp pl4 ; branch too long pw3: rjmp pw4 temp_tag3: ldi mode, 3 rcall display st_ram temp, Phand rcall check_busted ; store status of busted into register Busted tst_ram Busted brne pl4a rcall check_bj ; store status of black jack into register BlackJack tst_ram BlackJack breq dealersTurn add_ram bet, bet; double the bet rjmp pw4 pl4a: tx_text_predefined bust_txt tx_text_predefined crlf rjmp pl4 dealersTurn: ;need to find out player's hand first AceHand PAce, Phand ldi ZL, LOW(Phand) ;ld_ram @1, temp1 ldi ZH, HIGH(Phand) st Z, temp1 st_ram temp, Phand AceHand DAce, Dhand cp temp, temp1 brlt pl4 cpi temp1, 16 ; dealer stops dealing if its hand is greater than 16 brlt Dcard3 cp temp1, temp breq pt4 brlt pw4 cp temp, temp1 brlt pl4 Dcard3: ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Dsuit3, Dcardnum3, DAce rjmp temp_tag4 pt4: rjmp pt5 pl4: rjmp pl5 ; branch too long pw4: rjmp pw5 temp_tag4: st_ram temp, Dcardnum3 cpi temp, 10 brlt dc3_10 addi_ram Dhand, 10 rjmp dc3a_10 dc3_10: add_ram Dhand, Dcardnum3 dc3a_10: st_ram temp, Dhand rcall check_busted ; store status of busted into register Busted tst_ram Busted brne pw5a st_ram temp, Phand AceHand DAce, Dhand cp temp, temp1 brlt pl5a rjmp pw5a_after pw5a: rjmp pw5 pw5a_after: cpi temp1, 16 ; dealer stops dealing if its hand is greater than 16 brlt Dcard4 cp temp1, temp breq pt5 brlt pw5 cp temp, temp1 brlt pl5 Dcard4: ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Dsuit4, Dcardnum4, DAce st_ram temp, Dcardnum4 cpi temp, 10 brlt dc4_10 addi_ram Dhand, 10 rjmp dc4a_10 pl5a: rjmp pl5 dc4_10: add_ram Dhand, Dcardnum4 dc4a_10: rjmp temp_tag5 pt5: rjmp pt6 pl5: rjmp pl6 ; branch too long pw5: rjmp pw6 temp_tag5: st_ram temp, Dhand rcall check_busted tst_ram Busted brne pw6a st_ram temp, Phand AceHand DAce, Dhand cp temp, temp1 brlt pl6a rjmp pw6a_after pw6a: rjmp pw6 pw6a_after: cpi temp1, 16 ; dealer stops dealing if its hand is greater than 16 brlt Dcard5 cp temp1, temp breq pt6 brlt pw6 cp temp, temp1 brlt pl6 Dcard5: ldi ZL, LOW(cards) ldi ZH, HIGH(cards) add r30, random_ptr inc random_ptr ld random, Z mod random, 13, Dsuit5, Dcardnum5, DAce st_ram temp, Dcardnum5 cpi temp, 10 brlt dc5_10 addi_ram Dhand, 10 rjmp dc5a_10 pl6a: rjmp pl6 dc5_10: add_ram Dhand, Dcardnum5 dc5a_10: rjmp temp_tag6 pt6: rjmp playerTie pl6: rjmp playerLost ; branch too long pw6: rjmp playerWon temp_tag6: st_ram temp, Dhand rcall check_busted tst_ram Busted brne playerWon st_ram temp, Phand AceHand DAce, Dhand cp temp, temp1 breq playerTie brlt playerLost cp temp1, temp brlt playerWon playerWon: add_ram Ppoints, bet ldi mode, 4 rcall display rjmp next playerTie: ldi mode, 5 rcall display rjmp next playerLost: sub_ram Ppoints, bet ldi mode, 6 rcall display st_ram temp, Ppoints cpi temp, 1 ; Ppoints <= 0? brge next ;game over ;now player need to choose "new game" or "quit." ;game = 0:new; 1:quit; ;difference between get_next1 & get_next2 is the display tx_text_predefined gameover tx_text_predefined crlf rcall get_next1; store player's decision into register game tst temp1 breq newGame_tag rjmp reset newGame_tag: rjmp newGame ;now player need to choose "next round," "new game" or "quit." ;game = 0:next; 1:new; 2:quit; next: rcall get_next2; store player's decision into register game cpi temp1, 0 brne new rjmp nextGame new: cpi temp1, 1 breq newGame_tag rjmp reset T0ovfl: set ;Set T flag ldi temp, 0 ;Timer 0 off out TCCR0, temp ;Stop timer reti ; UART needs a character TXempty:in savSREG, SREG ;save processor status tst TXflash ;Is the string in flash memory? breq TXram ;If not, it is in RAM inc ZL ;get the next char from flash lpm ;and put it in r0 rjmp TXfls TXram: inc ZL ;get the next char from RAM ld r0,Z TXfls: tst r0 ;if char is zero then exit breq TXend out UDR, r0 ;otherwise transmit it rjmp TXexit ;exit until next char TXend: clr TXbusy ;no more chars cbi UCR, UDRIE ;clear the TXempty interrupt TXexit: out SREG, savSREG ;restore proc status reti ;back to pgm ; UART read a character RXdone: in savSREG, SREG ;save processor status in RXchar, UDR ;get the character out SREG, savSREG ;restore proc status reti ;back to pgm ;***************************** ;subroutine TXwait: tst TXbusy ;now wait for the tranmission to finish brne TXwait ret ;--------------------------------- check_bj: AceHand PAce, Phand cpi temp1, 21 brne bjExit tx_text_predefined bj_txt tx_text_predefined crlf ldi_ram BlackJack,1 bjExit: ret ;--------------------------------- check_busted: cpi temp, 22 brlt bustExit ldi_ram Busted, 1 bustExit: ret ;--------------------------------- get_response: ldi RXchar, azero tx_text_predefined action_ndd_txt cpi mode, 0 brne responseWait tx_text_predefined action_dd_txt rjmp responseWait ; wait for player to enter his/her decision responseWait: sbi PORTB, 3 sbi PORTB, 4 sbi PORTB, 5 sbis PINC, 4 rjmp check_d ; cpi RXchar, hit ; brne check_d ldi temp1,3 ; then Wait 45ms to avoid debounce offwait1: rcall delay dec temp1 brne offwait1 clr response rjmp responseExit check_d: cpi mode, 0 brne check_s sbis PINC, 5 rjmp check_s ; cpi RXchar, double ; brne check_s ldi response, 1 rjmp responseExit check_s: sbis PINC, 3 rjmp responseWait ; cpi RXchar, stand ; brne responseWait ldi response, 2 responseExit: cbi PORTB, 3 cbi PORTB, 4 cbi PORTB, 5 tx_text_predefined crlf ret get_next1: tx_text_predefined crlf tx_text_predefined resetquit_txt tx_text_predefined crlf tx_text_predefined resetquit_txt1 ; wait for player to enter his/her decision next1Wait: sbi PORTD, 3 sbi PORTB, 2 sbis PINC, 2 rjmp check_q ; cpi RXchar, r ; brne check_q clr temp1 rjmp next1Exit check_q: sbis PINC, 0 rjmp next1Wait ; cpi RXchar, q ; brne next1Wait ldi temp1, 1 next1Exit: cbi PORTD, 3 cbi PORTB, 2 tx_text_predefined crlf ret ;-------------------------------- get_next2: tx_text_predefined crlf tx_text_predefined nextround_txt tx_text_predefined crlf tx_text_predefined resetquit_txt tx_text_predefined crlf tx_text_predefined resetquit_txt1 ; wait for player to enter his/her decision next2Wait: sbi PORTD, 3 sbi PORTB, 1 sbi PORTB, 2 sbis PINC, 1 rjmp check_n2 ; cpi RXchar, n ; brne check_n2 clr temp1 rjmp next2Exit check_n2: sbis PINC, 2 rjmp check_q2 ; cpi RXchar, r ; brne check_q2 ldi temp1, 1 rjmp next2Exit check_q2: sbis PINC, 0 rjmp next2Wait ; cpi RXchar, q ; brne next2Wait ldi temp1, 2 next2Exit: cbi PORTD, 3 cbi PORTB, 1 cbi PORTB, 2 tx_text_predefined crlf ret ;---------------------------------------------- ;get a random value from timer 0, and then find (random value mod 52) to get a number 0-51 ;which represents a card. repeat ten times to find ten card... if number is the same, we simply ;add 1 to the value and check again if the number has been outputted or not. ; for (i = 0; i < 10; i++) ; get random value (rv) from counter ; number[i] = rv mod (52-i) ; card number ;ag: for (j = 0; j