From 1abc56ed5dd52af310add7916bf9ff0ef73f2f12 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 13 Apr 2015 04:59:08 -0400 Subject: initial commit --- pokersquares.dasm | 2036 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2036 insertions(+) create mode 100644 pokersquares.dasm (limited to 'pokersquares.dasm') diff --git a/pokersquares.dasm b/pokersquares.dasm new file mode 100644 index 0000000..68b8f33 --- /dev/null +++ b/pokersquares.dasm @@ -0,0 +1,2036 @@ + +; pokersol.asm + +; by B. Watson + +; Tested on an NTSC 6-switch Atari 2600 +; Tested on z26 v1.46 on a windows machine +; Tested on xstella 1.1 on a linux machine + +; To build NTSC version: + +; dasm pokersol_027.asm -opokersol_027.bin -v3 -f3 + + +; To build PAL version: + +; dasm pokersol_027.asm -DPAL -opokersol_027.bin -v3 -f3 + + + + processor 6502 + include "vcs.h" + + seg.u data.0 + + org $80 + +card0ptr ds 50 +left_diff_ptr = card0ptr +right_diff_ptr = card0ptr+2 +ranks = card0ptr +suits = card0ptr+14 +pairs = suits+5 +trips = pairs+1 +quad = trips+1 +flush = quad+1 +tmp_cards = flush+1 ; 5 bytes +end_ptrs +tableau ds 25 ; the cards that have been played +stock ds 27 ; the rest of the cards +scoredig0 = stock ; 3 2-byte pointers +deck = tableau ; the whole deck (which gets shuffled, then the + ; first 25 cards get overwritten with the + ; blank tableau) +current_card ds 1 ; index into stock, points at card being placed +tmp ds 1 +tmp2 ds 1 +select_debnc ds 1 ; bit 7: 0=game display, 1=cribsheet. bits 0..4=debounce +playerpos ds 1 ; 5*y + x (or else $FF for `game not on' +framectr ds 1 +color0 ds 5 +random ds 2 +score ds 1 +score_frame ds 1 +sound_type ds 1 +sound_ctr ds 1 +btn_debnc ds 1 +joy_debnc ds 1 +last_joy ds 1 +bw_mask ds 1 ; $FF for color, $0F for B/W (ANDed with color values) +diff_shadow ds 1 ; shadows SWCHB bits for diff. switches +scroll_ctr ds 1 + + echo *-$80,"bytes of zero page used." + + if (*-$80) > ($7d) + echo "You're out of zero page! (Must be $7D or less bytes used)" + err + endif + + +; constants: + +RAND_SEED = $55 ; goes in random @ powerup, gets asl'd then goes in random+1 + + ifconst PAL +RED = $62 +CARD_COLOR = $0C +YELLOW = $28 +GREEN = $38 +VBLANK_TIME = 54 +OSCAN_TIME = 56 + else ; NTSC +RED = $34 ; was $32, looks great in color, crappy in B/W +CARD_COLOR = $0C ; white (don't need to bother with bw_mask for this) +YELLOW = $28 ; used to be $FC +GREEN = $BC ; used to be $B6 +VBLANK_TIME = 44 +OSCAN_TIME = 37 + endif + + +SND_BZZT = $8A ; hi nyb = D4-D1 of AUDF0, lo nyb = D3-D0 of AUDC0 +SND_BZZT_LEN = $06 ; frames to play sound for + +;these are OK +SND_PLACE = $22 +SND_PLACE_LEN = $03 + +SND_SCORE = $1A +SND_SCORE_LEN = $20 + + seg code + + org $F000 + +main_loop + lda #2 + sta VSYNC ; start blanking + sta WSYNC + sta WSYNC + lda #VBLANK_TIME + sta TIM64T ; go ahead & set timer + lda #0 + sta WSYNC + sta VSYNC ; 3 WSYNC's, then turn off VSYNC + +game_calc + inc framectr + lda framectr + and #1 + beq pos_miss + inc scroll_ctr +pos_miss + +; position missiles... + sta WSYNC + ldx #7 +mposloop + dex + bne mposloop + sta RESM0 ; 49 + sta RESM1 ; 52 + lda #$60 + sta HMM0 + lda #$F0 + sta HMM1 + +; position players + sta WSYNC + ldx #7 +posloop + dex + bne posloop + sta RESP0 ; 49 + sta RESP1 ; 52 + lda #$F0 + sta HMP1 + lda #$60 + sta HMP0 + sta WSYNC + sta HMOVE ; 2 + lda #CARD_COLOR ; 2 = 4 + sta COLUP0 ; 3 = 7 + sta COLUP1 ; 3 = 10 + ldy #0 ; 2 = 14 + stx color0 ; 3 = 17 + stx color0+1 ; 3 = 20 + stx color0+2 ; 3 = 23 + stx color0+3 ; 3 = 26 + stx color0+4 ; 3 = 29 + sta HMCLR ; 3 = 32 + +; setup pointers to card sprite data (25 of them!) +; note to self: saved 50 cycles by swapping roles of X and Y here +; (I had 2 sta zp,y's, which are actually sta.w, since there's no sta zp,y) +; there is still an lda zp,y (same deal), but not much I can do about this +; put it in stelladoc as an example... + +; these are already 0 from above +;ldy #0 +;ldx #0 +card_disp + sty tmp ; 3 + lda tableau,y ; 4 = 7 + tay ; 2 = 9 + lda lo_bytes,y ; 5 = 14 + sta card0ptr,x ; 4 = 18 + inx ; 2 = 20 + lda hi_bytes,y ; 5 = 23 + sta card0ptr,x ; 4 = 27 + inx ; 2 = 29 + ldy tmp ; 2 = 31 + iny ; 2 = 31 + cpy #25 ; 2 = 33 + bne card_disp ; 3 = 36 + + ldy #$0F + lda SWCHB + and #8 + beq bw_on + ldy #$FF +bw_on + sty bw_mask + +; set up card color bytes (1 per row) + +; card0 thru card0+4 are already 0 + ldx #0 +cbyte_loop + lda tableau,x + cmp #26 + rol color0 + lda tableau+5,x + cmp #26 + rol color0+1 + lda tableau+10,x + cmp #26 + rol color0+2 + lda tableau+15,x + cmp #26 + rol color0+3 + lda tableau+20,x + cmp #26 + rol color0+4 + inx + cpx #5 + bne cbyte_loop + + +; blink cursor + lda framectr + and #8 ; blink 8 frames, then don't blink 8 frames + beq no_blink + lda current_card + cmp #25 + beq no_blink ; dont blink if game is over + lda playerpos + asl + tax + lda #no_card + sta card0ptr+1,x + +no_blink +; lda framectr +; and #7 +; beq do_stick +; jmp no_stick + +do_stick + ;sta last_joy + lda INPT4 + and #$80 + ;cmp #$80 + bne not_hard + ;cmp last_btn + ;bne no_btn_debnc + lda btn_debnc + beq no_btn_debnc + dec btn_debnc + bne not_hard + ;bmi no_fire +no_btn_debnc + ;sta last_btn + lda #16 + sta btn_debnc + lda playerpos ; check & see if games is already on ($FF = no) + bpl place_card + lda #0 ; player pressed fire during shuffling + sta playerpos ; so start the game + sta current_card + ldx #24 + lda #52 ; blank card +blank_tableau + sta tableau,x + dex + bpl blank_tableau + ;bmi no_fire ; always branch + ; now the game is ready to begin, let's check left diff. switch + lda diff_shadow + and #64 + beq not_hard + lda stock ; if left `pro' difficulty, deal the 1st 5 cards to the + sta tableau+12 ; corners and center. *Damn* this makes the game harder! + lda stock+1 ; (thanks, Glenn!) + sta tableau + lda stock+2 + sta tableau+4 + lda stock+3 + sta tableau+20 + lda stock+4 + sta tableau+24 + lda #5 + sta current_card +not_hard + jmp no_fire + + +place_card ; player pressed fire while game is on + ldx current_card + ldy playerpos + lda #SND_BZZT + sta sound_type + lda #SND_BZZT_LEN + sta sound_ctr + lda tableau,y ; can't place a card where a card already is + cmp #52 ; 52 is `no card placed' + bne no_fire + lda stock,x + sta tableau,y + inc current_card + lda #SND_PLACE + sta sound_type + lda #SND_PLACE_LEN + sta sound_ctr +no_fire + + lda playerpos +; bmi no_stick + bpl check_stick + lda SWCHB + and #$C0 + sta diff_shadow + jmp no_stick + +; read joystick + +check_stick + lda SWCHA + and #$F0 + cmp #$F0 + beq no_stick + cmp last_joy + bne no_joy_debnc + dec joy_debnc + bpl no_stick +no_joy_debnc + sta last_joy + ldx #8 + stx joy_debnc + asl + bcs no_right + inc playerpos +no_right + asl + bcs no_left + dec playerpos +no_left + asl + bcs no_down + tax + lda playerpos + adc #5 + sta playerpos + txa +no_down + asl + bcs no_up + lda playerpos + sbc #4 ; subtract 5 (carry always clear) + sta playerpos +no_up + lda playerpos + bpl not_minus + clc + adc #25 + sta playerpos +not_minus + cmp #25 + bcc not_toohigh + sec + sbc #25 + sta playerpos +not_toohigh + +no_stick + + lda SWCHB + and #$01 + bne no_reset + jsr deal_deck ; player pressed game reset + lda #$FF ; $FF in playerpos means `game not on, so shuffle' + sta playerpos + +no_reset + +decode_score + lda current_card + cmp #25 + bne no_decode_score + lda #0 + sta tmp + sta tmp2 + ;sta tmp3 ; dont need this + lda #score_blank + sta scoredig0+1 + sta scoredig0+3 + sta scoredig0+5 + lda score +ck_hund + cmp #100 + bcc hundreds_done + inc tmp + sec + sbc #100 + bcs ck_hund +; adc #100 +hundreds_done +ck_tens + cmp #10 + bcc tens_done + inc tmp2 + sec + sbc #10 + bcs ck_tens +; adc #10 +tens_done + asl + asl + asl + sta scoredig0+4 ; ones always displayed, even if 0 + lda score + cmp #10 ; always draw tens digit if score >= 10 + bcc no_tens + lda tmp2 + ;beq no_tens ; leave tens blank if score < 10 - this caused Jake's bug + asl + asl + asl + sta scoredig0+2 +no_tens + lda tmp + beq no_hund ; leave hunds blank if score < 100 + asl + asl + asl + sta scoredig0 +no_hund + +no_decode_score + + lda #0 + sta COLUBK + sta COLUPF + sta PF0 + sta PF1 + sta PF2 + +; play sounds + lda sound_ctr + bne play_sound +; lda #$00 + sta AUDV0 + sta AUDF0 + beq sound_done + +play_sound + lda sound_ctr + and #$07 + sta AUDV0 + lda sound_type + tax + and #$F0 + lsr + lsr + lsr + sta AUDF0 + stx AUDC0 + dec sound_ctr + +sound_done + +;NEW: +; +; x = select_debnc & 0x7f; + + lda select_debnc + and #$7f + tax + +; if (x != 0) select_debnc--; +; + + beq no_dec_sd + dec select_debnc +no_dec_sd + +; if (select_pressed) { + + lda SWCHB + and #2 + bne sel_not_pressed + +; if (x == 0) { + + cpx #0 + bne sel_not_pressed + +; select_debnc ^= 0x80; /* toggle hi bit */ + + lda select_debnc + eor #$80 + +; select_debnc |= 0x10; /* set delay to 0x10 frames */ + + ora #$10 + sta select_debnc + +; } +; } + +sel_not_pressed +wait_timer + lda INTIM + bne wait_timer ; busy-wait for timer to expire + sta WSYNC + sta VBLANK + sta WSYNC ; wby do I need these 2?? + lda #6 + sta NUSIZ0 + lda #2 + sta NUSIZ1 + sta WSYNC + + + + ifconst PAL + ldx #8 +pal_top_loop + sta WSYNC + dex + bne pal_top_loop + endif + +; +; if (select_debnc & 0x80) +; inst_kernel(); +; else +; kernel(); + + lda select_debnc + bpl kernel + jmp inst_kernel + + +kernel + ;lda #CARD_COLOR + ;sta COLUP0 + ;ldx #192 + + mac cardloop + lda #0 + sta COLUBK + lda #%11111110 + sta GRP0 + sta GRP1 + lda #2 + sta WSYNC + sta ENAM0 + sta ENAM1 + lda #%11111111 + sta GRP0 + sta GRP1 + sta PF0 + sta PF1 + sta PF2 + ldx color0+{1} ; 3 + lda colPF0,x ; +4 = 7 + sta PF0 ; +3 = 11 + lda colPF1,x ; +4 = 15 + sta PF1 ; +3 = 18 + lda colPF2,x ; +4 = 22 + sta PF2 ; +3 = 25 + ;lda #$0 + ;sta PF0 + + ldy #11 +.cardloop0 + + lda #0 ; 65 + sta.w COLUPF ; 70 + + lda (card0ptr+{1}*10+0),y ; 5 + sta WSYNC ; 0 + sta GRP0 ; 3 + lda (card0ptr+{1}*10+2),y ; 5 = 8 + sta GRP1 ; 3 = 11 + lda (card0ptr+{1}*10+8),y ; 5 = 16 + tax ; 2 = 18 + txs ; 2 = 20 + lda (card0ptr+{1}*10+6),y ; 5 = 25 + tax ; 2 = 32 + + nop ; 2 = 42 + lda #RED ; 2 = 34 + and bw_mask ; 3 = 37 + sta COLUPF ; 3 = 40 + + lda (card0ptr+{1}*10+4),y ; 5 = 47 + sta GRP0 ; 3 = 50 + stx GRP1 ; 3 = 53 + tsx ; 2 = 55 + stx GRP0 ; 3 = 58 + +; #define LAME_CUT_AND_PASTE + nop ; 2 = 58 + nop ; 2 = 60 + nop ; 2 = 62 + lda #0 ; 2 = 64 + sta.w COLUPF ; 4 = 68 + + lda (card0ptr+{1}*10+0),y ; 5 + sta WSYNC ; 0 + sta GRP0 ; 3 + lda (card0ptr+{1}*10+2),y ; 5 = 8 + sta GRP1 ; 3 = 11 + lda (card0ptr+{1}*10+8),y ; 5 = 16 + tax ; 2 = 18 + txs ; 2 = 20 + lda (card0ptr+{1}*10+6),y ; 5 = 25 + tax ; 2 = 32 + + nop ; 2 = 42 + lda #RED ; 2 = 34 + and bw_mask ; 3 = 37 + sta COLUPF ; 3 = 40 + + lda (card0ptr+{1}*10+4),y ; 5 = 47 + sta GRP0 ; 3 = 50 + stx GRP1 ; 3 = 53 + tsx ; 2 = 55 + stx GRP0 ; 3 = 58 + + dey ; 2 = 60 + bpl .cardloop0 ; 2/3 + + lda #0 ; 65 + nop ; 67 + sta COLUPF ; 70 + sta WSYNC + sta PF0 + sta PF1 + sta PF2 + lda #%11111111 + sta GRP0 + sta GRP1 + sta WSYNC + lda #0 + sta ENAM0 + sta ENAM1 + lda #%11111110 + sta GRP0 + sta GRP1 + sta WSYNC + iny + sty GRP0 + sty GRP1 + + sta WSYNC + sta WSYNC + endm ; end of mac cardloop + + cardloop 0 + cardloop 1 + cardloop 2 + cardloop 3 + cardloop 4 + + sta WSYNC + ldx #31 + lda playerpos +; bmi kill_rest ; this branch is too far! + bpl k_ok + ;jmp kill_rest + jmp scroll_title_or_blank +k_ok + lda current_card + ;jmp draw_score ; very temporary! + cmp #25 +; beq kill_rest ; this branch is too far! + bne k_ok2 + jmp draw_score +k_ok2 + sta WSYNC + + lda #0 + sta NUSIZ0 + sta NUSIZ1 + lda #%11111110 + sta GRP0 + lda #2 + sta WSYNC + sta ENAM0 + lda #%11111111 + sta GRP0 + ldx current_card + lda stock,x + tax + lda lo_bytes,x + sta tmp + lda hi_bytes,x + sta tmp+1 + cpx #26 + ldx #$00 + bcc last_card_black + ldx #$3 +last_card_black + txs + ldy #11 + lda #RED ; 2 + and bw_mask ; 3 + sta COLUPF ; 3 +draw_last_card + repeat 2 + sta WSYNC ; 3 + lda (tmp),y ; 5 + sta GRP0 ; 3 + tsx ; 2 + stx PF2 ; 3 + ldx #6 + dex + bne *-1 + stx PF2 + +;;; waste 16 cycles (with sta.w below) +; repeat 8 ; sketchy... 2*8=16 bytes total +; nop +; repend + +; waste 16 cycles, without the sta.w below +; lda (tmp),y ; this is 7*2=14 bytes total, plus we lose the sta.w below +; lda (tmp),y +; lda (tmp),y +; nop +; +; lda #red +; and bw_mask +; sta colubk ; sta.w colubk + repend + dey + bpl draw_last_card + + sta WSYNC + lda #%11111111 + sta GRP0 + iny + sty PF2 + sta WSYNC + sty ENAM0 + lda #%11111110 + sta GRP0 + sta WSYNC + sty GRP0 + + + ldx #2 +kill_rest + lda #YELLOW + and bw_mask + sta COLUP0 + sta COLUP1 + sta WSYNC + dex + bne kill_rest + + lda diff_shadow + and #64 + bne ld_on + lda #score_blank + sta left_diff_ptr+1 + jmp ld_off +ld_on + lda #left_diff_hard + sta left_diff_ptr+1 +ld_off + + lda diff_shadow + bpl rd_on + lda #score_blank + sta right_diff_ptr+1 + jmp rd_off +rd_on + lda #right_diff_hard + sta right_diff_ptr+1 +rd_off + + + lda #0 + sta NUSIZ0 + sta NUSIZ1 + ldy #7 +kr_diff_loop + sta WSYNC + lda (left_diff_ptr),y + sta GRP0 + lda (right_diff_ptr),y + sta GRP1 + dey + bpl kr_diff_loop + sta WSYNC + lda #0 + sta GRP0 + sta GRP1 + jmp end_kernel + +draw_score + lda #2 + sta NUSIZ0 + lda #0 + sta NUSIZ1 + ldy #7 + lda score + cmp #25 + bcc lt_25 + cmp #40 + bcc lt_40 + lda #GREEN + bne ds_color +lt_25 + lda #RED + bne ds_color +lt_40 + lda #YELLOW + +ds_color + and bw_mask + sta COLUP1 + sta COLUP0 + +ds_loop + sta WSYNC + lda (scoredig0),y ; 5 + sta GRP0 ; 3 = 8 + lda (scoredig0+2),y ; 5 = 13 + sta GRP1 ; 3 = 16 + ldx #4 ; 2 = 18 +ds_delay + dex + bne ds_delay ; @ end of loop, 37 cyc. + + lda (scoredig0+4),y ; 5 = 42 + sta GRP0 ; 3 = 45 + + sta WSYNC + lda (scoredig0),y ; 5 + sta GRP0 ; 3 = 8 + lda (scoredig0+2),y ; 5 = 13 + sta GRP1 ; 3 = 16 +; repeat 16 +; nop +; repend ; 48 + ldx #4 +ds_delay1 + dex + bne ds_delay1 ; @ end of loop, 47 cyc. + lda (scoredig0+4),y ; 5 = 52 + sta GRP0 ; 3 = 55 + + dey + + bpl ds_loop + sta WSYNC + lda #0 + sta GRP0 + sta GRP1 + ldx #14 + jmp kill_rest + +scroll_title_or_blank + ; X is 31 on entry, always + sta WSYNC + lda scroll_ctr + bpl do_scroll +start_freeze + ldx #0 + beq do_freeze +do_scroll + ;stx COLUBK + lsr + lsr + ;lsr + tax +do_freeze + ldy #13 +; sty COLUPF +do_sblank + ;ldx #0 +scr_loop + tya + ;asl + eor bw_mask + sta WSYNC ; 0 + sta.w COLUPF + lda #0 ; 2 + sta PF0 ; 3 + lda t_left_pf1,x ; 4 + sta PF1 ; 3 + lda t_left_pf2,x ; 4 + sta PF2 ; 3 + ;nop ; 2 + ;nop ; 2 + nop ; 2 + nop ; 2 + nop ; 2 + nop ; 2 + lda t_right_pf0,x ; 4 + sta PF0 ; 3 + nop ; 2 + nop ; 2 + nop ; 2 + lda t_right_pf1,x ; 4 + sta PF1 ; 3 + lda t_spade,y ; 2 + sta PF2 ; 3 +; + sta WSYNC ; 0 + lda t_left_pf1,x ; 4 + sta PF1 ; 3 + lda t_left_pf2,x ; 4 + sta PF2 ; 3 + lda #0 + sta PF0 + nop + nop + nop + nop + nop + nop + lda t_right_pf0,x + sta PF0 + nop + nop + nop + lda t_right_pf1,x + sta PF1 + lda t_spade,y ; 2 + sta PF2 + inx + dey + bpl scr_loop + sta WSYNC + lda #0 + sta PF0 + sta PF1 + sta PF2 + ldx #1 + jmp kill_rest + + echo *-kernel,"bytes of kernel code" +end_kernel + ifconst PAL + ldx #18 +pal_bot_loop + sta WSYNC + dex + bne pal_bot_loop + endif + + lda #OSCAN_TIME + sta TIM64T + +overscan + + + lda #2 + sta VBLANK + + ldx #$FF + txs + lda current_card + cmp #25 + bne not_score + jsr calc_score +not_score + lda playerpos + bpl finish_overscan + jsr shuffle + +finish_overscan + lda INTIM + bne finish_overscan + + jmp main_loop + +; suits is 5 elements, each element is the suit (0-4) of the card +; ranks is 13 elements, each elem. is how many of that card we have + +; this routine only gets called when current_card == 25 +calc_score + ldy score_frame + bne no_score_sound + + lda #SND_SCORE + sta sound_type + lda #SND_SCORE_LEN + sta sound_ctr + +no_score_sound + cpy #12 + bne ok_to_score + rts +ok_to_score + lda #0 + ldx #28 +clear_vars + sta card0ptr,x + dex + bpl clear_vars + +; note to self: surely we can eliminate either X or A here.. + + tya ; Y came from ldy score_frame, above. + tax + ;ldx score_frame + cpx #5 ; is this hand #5 or greater? + bcs copy_vert_hands ; if so, it's vertical, otherwise: + +; X is 0-4, copy tableau+X*5 thru tableau+X*5+4 to tmp_cards + + stx tmp ; in C: y = x*5; + ;txa ; a is already == x + asl + asl + adc tmp ; carry already clear + tay + ldx #4 +hcc_loop + lda tableau,y + sta tmp_cards,x + iny + dex + bpl hcc_loop + bmi done_copying ; may need to convert to jmp later + +copy_vert_hands + cpx #10 ; is X>=10? + bcs copy_diag_hands ; if so, we're done with vert hands + +; X is 5-9 +; for (int i=0; i<5; i++) { tmp_cards[i] = tableau[ 5*i + (X-5) ]; } +; /* damn, it's easier in C :) */ + + lda tableau-5,x + sta tmp_cards + lda tableau,x + sta tmp_cards+1 + lda tableau+5,x + sta tmp_cards+2 + lda tableau+10,x + sta tmp_cards+3 + lda tableau+15,x + sta tmp_cards+4 + jmp done_copying + +copy_diag_hands + lda diff_shadow + bmi no_mo_copying ; don't score diags if right difficulty = pro (a) +;X is 10 or 11 + +; if X is 10, we need: tableau +0, +6, +12, +18, +24 (offset 0, step 6) +; if X is 11, we need: tableau +4, +8, +12, +16, +20 (offset 4, step 4) + + txa + and #1 ; now 0 or 1 + asl + asl ; now 0 or 4 + tax ; X will hold offset into tableau: 0 for x==10, 4 for x==11 + lsr ; now 0 or 2 + eor #2 ; now 2 or 0 + adc #4 ; now 6 or 4 (don't need to clc, carry always clear) + sta tmp ; step: 6 for x==10, 4 for x==11 + + ldy #4 +diag_loop + ;ldx tmp + lda tableau,x + sta tmp_cards,y + txa + clc ; maybe not need + adc tmp ; add offset + ;sta tmp + tax + dey + bpl diag_loop + bmi done_copying + +no_mo_copying + rts + +done_copying + inc score_frame +; this sucks! + ldx #4 +split_loop + lda tmp_cards,x +sub_loop + sec + sbc #13 + bcc no_subtract + inc suits,x + bne sub_loop ; should always branch +no_subtract + adc #13 ; carry should already be clear + ;tay + ;inc ranks,y ;arrrgh. illegal addr. mode! + stx tmp + tax + inc ranks,x + ldx tmp +end_split_loop + dex + bpl split_loop + +; lda suits+1 ; debug code +; sta score +; rts + +; ldx #3 +;ck_flush +; lda suits,x +; cmp #5 +; beq got_flush +; dex +; bpl ck_flush +; bmi done_flush + + + lda suits + cmp suits+1 + bne done_flush + cmp suits+2 + bne done_flush + cmp suits+3 + bne done_flush + cmp suits+4 + bne done_flush + +got_flush + inc flush + bne pre_ck_straight ; if flush, don't bother checking for pairs/trips/etc. +done_flush + + ldx #12 +ck_quad + lda ranks,x + cmp #4 + bne not_quad + lda #16 ; if we got 4 of a kind, that's all we got + jmp add_A_to_score ; so don't check for more stuff +not_quad + dex + bpl ck_quad + + ldx #12 +ck_trip + lda ranks,x + cmp #3 + bne no_trip + inc trips + bne done_trips ; if we got trips, we only got it once +no_trip + dex + bpl ck_trip + +done_trips + ldx #12 +ck_pair + lda ranks,x + cmp #2 + bne no_pair + inc pairs ; might have 2 pair, keep checking +no_pair + dex + bpl ck_pair + +pre_ck_straight + lda ranks + sta ranks+13 ; duplicate ace as high card + ldx #9 +ck_straight + lda ranks,x + and ranks+1,x + and ranks+2,x + and ranks+3,x + and ranks+4,x + bne got_straight + dex + bpl ck_straight + bmi done_checking +got_straight + and flush ; did we get a straight flush? + bne got_straight_flush ; if so, jump + lda #12 ; otherwise, score 12 for straight + bne add_A_to_score +got_straight_flush + lda #30 + bne add_A_to_score + +done_checking +; done checking, now total 'em up + + lda flush + beq test_trips + lda #5 + bne add_A_to_score + +; at this point, we have 1 of: +; nothing pair 2pair trips fullhouse + +test_trips + lda trips + beq no_trips + and pairs ; should be 0 or 1 + bne got_full_house ; if (trips && pairs), we got full house, yay! + lda #6 ; otherwise, 6 points for trips + bne add_A_to_score +got_full_house + lda #10 + bne add_A_to_score +no_trips + +; at this point, we have 1 of: nothing pair 2pair + + +test_pairs + lda pairs + beq add_A_to_score + cmp #2 + beq score_2_pair + lda #1 + bne add_A_to_score +score_2_pair + lda #3 + +add_A_to_score + clc + adc score + sta score + + rts + + +; tya +; ora #6 +; sta.w COLUPF + +END_CODE = * + echo END_CODE-$f000,"bytes of code" + + org $F900 +BEGIN_DATA + echo *-END_CODE , "bytes of code space free" + include "pftitle.inc" +END_TITLE = * + + org $Fa00 + echo *-END_TITLE, "bytes wasted in TITLE data area:",END_TITLE,"-",*-1 + include "pokersol.inc" + + +; SUBROUTINES +; +; these were moved here because there was a small (132-byte) chunk of space +; wasted by the next `align 256'. There are still 5 bytes of this left. + +inst_kernel ; this kernel displays the instructions + sta WSYNC + ldy #pf_bytes + tya + ora #6 + and bw_mask + sta COLUPF +ik_draw_pf + lda #2 + sta tmp +ik_one_line + sta WSYNC ; 0 + lda left_pf0,y ; 4 + sta PF0 ; 3 = 7 + lda left_pf1,y ; 4 = 11 + sta PF1 ; 3 = 14 + lda left_pf2,y ; 4 = 15 + sta PF2 ; 3 = 18 + ldx right_pf2,y ; 4 = 26 + tya + ora #6 + and bw_mask + sta COLUPF + lda right_pf0,y ; 4 = 41 + sta PF0 ; 3 = 44 + lda right_pf1,y ; 4 = 22 + sta PF1 ; 3 = 37 + stx PF2 ; 3 = 47 + dec tmp ; 5 = 52 + bpl ik_one_line ; 2 = 54 + dey ; 2 = 56 + bpl ik_draw_pf ; 3 = 59 + + sta WSYNC + lda #0 + sta COLUPF + ;sta WSYNC + + jmp end_kernel + +deal_deck + ldx #0 + stx current_card + stx score_frame + stx score +deal_loop + txa + sta deck,x + inx + cpx #52 + bne deal_loop + rts + +; shuffle deck +shuffle + ldy #50 +shuffle_loop + lda random ; 3 + lsr ; +2 = 5 + lsr ; +2 = 7 + sbc random ; +3 = 10 + lsr ; +2 = 12 + ror random+1 ; +5 = 17 + ror random ; +5 = 17 + bcs noswap ; +3 = 20 + lda deck,y ; +4 = 24 ; if we got a 1 (carry), swap card with the one after it + ldx deck+1,y ; +4 = 28 + stx deck,y ; +4 = 32 + sta deck+1,y ; +4 = 38 +noswap + dey ; +2 = 40 + bpl shuffle_loop ; +3 = 43 + rts + +left_diff_hard + hex 00 c3 c3 18 18 c3 c3 00 + +END_PF = * + + align 256 + echo *-END_PF, "bytes wasted in PF data area: ", END_PF, "-", *-1 +score_font +sf0 + byte %00111100 + byte %01111110 + byte %11100111 + byte %11000011 + byte %11000011 + byte %11100111 + byte %01111110 + byte %00111100 +sf1 + byte %01111110 + byte %01111110 + byte %00011000 + byte %00011000 + byte %00011000 + byte %01111000 + byte %00111000 + byte %00011000 +sf2 + byte %11111111 + byte %01111111 + byte %00110000 + byte %00011100 + byte %00000110 + byte %01100011 + byte %11111111 + byte %01111110 +sf3 + byte %01111110 + byte %11111111 + byte %01100011 + byte %00000110 + byte %00011100 + byte %00000110 + byte %00000011 + byte %11111111 +sf4 + byte %00000110 + byte %00000110 + byte %11111111 + byte %11111111 + byte %11000110 + byte %11100110 + byte %01110110 + byte %00110110 +sf5 + byte %01111100 + byte %11111110 + byte %01100111 + byte %00001110 + byte %01111100 + byte %01100000 + byte %01111111 + byte %01111111 +sf6 + byte %01111110 + byte %11111111 + byte %11000111 + byte %11001110 + byte %11111100 + byte %11100000 + byte %01110011 + byte %00111110 +sf7 + byte %11100000 + byte %01110000 + byte %00111000 + byte %00011100 + byte %00001110 + byte %00000111 + byte %11111111 + byte %11111111 +sf8 + byte %01111110 + byte %11100111 + byte %11000011 + byte %01100110 + byte %00111100 + byte %01100110 + byte %01100110 + byte %00111100 +sf9 + byte %01111100 + byte %11001110 + byte %00000111 + byte %00111111 + byte %01110011 + byte %11100011 + byte %11111111 + byte %01111110 +no_card + repeat 14 + byte 1 + repend + +; cards are A B C D E from left to right, bits 4 3 2 1 0 in color0+row +; so, RED BLACK BLACK RED RED would be $13, which is used as an offset +; into each of the colPF* tables in turn + +; PF2: xxBBxxAA +; PF0: xxCC.... (bottom 4 bits are unused anyway) +; PF1: DDxxEExx (remember, PF1 is forwards!) + +; (bits marked xx are 0) + +; each colPF* table is a list of what byte to put in that PF +; register, for each of the 32 possible red/black arrangements. + +; 1 bits are red (COLUPF), 0 bits are black (COLUBK) + +colPF2 + repeat 8 + byte $00 + repend + repeat 8 + byte $30 + repend + repeat 8 + byte $03 + repend + repeat 8 + byte $33 + repend + +colPF0 + repeat 4 + hex 00 00 00 00 30 30 30 30 + repend + +colPF1 + repeat 8 + hex 00 0C C0 CC + repend + + + +; jumped to by reset vector (crammed in here to fill up $22 byte wasted space) + +initvcs + sei + cld + ldx #$ff + txs + lda #0 +iloop + sta 0,x + dex + bne iloop + lda #RAND_SEED + sta random + asl + sta random+1 + dex + stx playerpos + +; initialize deck + jsr deal_deck + jmp main_loop + +score_blank + repeat 10 + byte 0 + repend + +END_MISC = * + align 256 + echo *-END_MISC, "bytes wasted in MISC data area: ", END_MISC, "-", *-1 +cards + +; suit sprite data + mac spade + byte %11000111 + byte %01101101 + byte %00000001 + byte %10000011 + byte %11000111 + byte %11101111 + byte %11111111 + endm + + mac heart + byte %11101111 + byte %11000111 + byte %10000011 + byte %00000001 + byte %00010001 + byte %10111011 + byte %11111111 + endm + + mac diam + byte %11101111 + byte %11000111 + byte %10000011 + byte %00000001 + byte %10000011 + byte %11000111 + byte %11101111 + endm + + mac club + byte %11000111 + byte %11101111 + byte %00101001 + byte %00111001 + byte %11000111 + byte %11000111 + byte %11111111 + endm + +; rank sprite data + + mac rank1 + byte %10111011 + byte %10000011 + byte %10111011 + byte %11010111 + byte %11101111 + endm + + mac rank2 + byte %10000011 + byte %11011111 + byte %11100111 + byte %10111011 + byte %11000111 + endm + + mac rank3 + byte %10000111 + byte %11111011 + byte %11100111 + byte %10111011 + byte %11000111 + endm + + mac rank4 + byte %11111011 + byte %10000011 + byte %10111011 + byte %11011011 + byte %11101011 + endm + + mac rank5 + byte %11000111 + byte %10111011 + byte %11100111 + byte %11011111 + byte %11000011 + endm + + mac rank6 + byte %11000111 + byte %10111011 + byte %10000111 + byte %10111111 + byte %11000011 + endm + + mac rank7 + byte %11011111 + byte %11101111 + byte %11110111 + byte %11111011 + byte %10000011 + endm + + mac rank8 + byte %11000111 + byte %10111011 + byte %11000111 + byte %10111011 + byte %11000111 + endm + + mac rank9 + byte %10000111 + byte %11111011 + byte %11000011 + byte %10111011 + byte %11000111 + endm + + mac rank10 + byte %00010011 + byte %10101101 + byte %10101101 + byte %00101101 + byte %10110011 + endm + + mac rankj + byte %11001111 + byte %10110111 + byte %11110111 + byte %11110111 + byte %11100011 + endm + + mac rankq + byte %11001011 + byte %10110111 + byte %10111011 + byte %10111011 + byte %11000111 + endm + + mac rankk + byte %10110111 + byte %10101111 + byte %10011111 + byte %10101111 + byte %10110111 + endm + + +spades1 + spade + rank1 +spades2 + spade + rank2 +spades3 + spade + rank3 +spades4 + spade + rank4 +spades5 + spade + rank5 +spades6 + spade + rank6 +spades7 + spade + rank7 +spades8 + spade + rank8 +spades9 + spade + rank9 +spades10 + spade + rank10 +spadesj + spade + rankj +spadesq + spade + rankq +spadesk + spade + rankk +clubs1 + club + rank1 +clubs2 + club + rank2 +clubs3 + club + rank3 +clubs4 + club + rank4 +clubs5 + club + rank5 +clubs6 + club + rank6 +clubs7 + club + rank7 +clubs8 + club + rank8 + + align 256 +clubs9 + club + rank9 +clubs10 + club + rank10 +clubsj + club + rankj +clubsq + club + rankq +clubsk + club + rankk +hearts1 + heart + rank1 +hearts2 + heart + rank2 +hearts3 + heart + rank3 +hearts4 + heart + rank4 +hearts5 + heart + rank5 +hearts6 + heart + rank6 +hearts7 + heart + rank7 +hearts8 + heart + rank8 +hearts9 + heart + rank9 +hearts10 + heart + rank10 +heartsj + heart + rankj +heartsq + heart + rankq +heartsk + heart + rankk +diam1 + diam + rank1 +diam2 + diam + rank2 +diam3 + diam + rank3 + + align 256 +diam4 + diam + rank4 +diam5 + diam + rank5 +diam6 + diam + rank6 +diam7 + diam + rank7 +diam8 + diam + rank8 +diam9 + diam + rank9 +diam10 + diam + rank10 +diamj + diam + rankj +diamq + diam + rankq +diamk + diam + rankk + +blank_card + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + byte %11111111 + +; lookup table of sprite data +; (saves us having to multiply by 12 during vblank & kernel) +lo_bytes + byte spades1, >spades2, >spades3, >spades4, >spades5 + byte >spades6, >spades7, >spades8, >spades9, >spades10 + byte >spadesj, >spadesq, >spadesk + byte >clubs1, >clubs2, >clubs3, >clubs4, >clubs5 + byte >clubs6, >clubs7, >clubs8, >clubs9, >clubs10 + byte >clubsj, >clubsq, >clubsk + byte >hearts1, >hearts2, >hearts3, >hearts4, >hearts5 + byte >hearts6, >hearts7, >hearts8, >hearts9, >hearts10 + byte >heartsj, >heartsq, >heartsk + byte >diam1, >diam2, >diam3, >diam4, >diam5 + byte >diam6, >diam7, >diam8, >diam9, >diam10 + byte >diamj, >diamq, >diamk, >blank_card, >no_card + +right_diff_hard + hex 82 44 28 10 28 44 82 00 + + +END_DATA = * + + org $FFFC + echo *-END_DATA, "bytes wasted in CARDS data area: ", END_DATA, "-", *-1 + word initvcs + word initvcs + + echo *-BEGIN_DATA,"bytes of data" + +; Changelog + +; 12/15/01: + +; Fix Q and A in card sprite data + +; various font fixes to score_font, looks a little better + +; make crib sheet more readable (UPPERCASE, 3x5 font, inverse video numbers) + +; make Select act as a toggle for crib sheet + +; 12/8/01: + +; add scrolling title to shuffle loop (what a pain) + +; 12/2/01: + +; use missiles for 9-pixel-wide cards + +; adjust RED YELLOW GREEN constants for better B/W greys + +; fix minor bug: 39 was green, should be 40 & up only (fencepost error) + +; 12/1/01: + +; color cribsheet + +; fix score bug Jake found + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; TODO LIST +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; PAL version... probably a compile-time option. + +; STARTED ON: +; optimize, optimize, optimize! (specifically, get rid of macros & repeats) +; I now have 482 bytes free in the code area from $F000-$FA00 +; update: I now have 604 bytes free, *and* I've added diagonals since then! + +; play testing! (by someone other than me!) + +; STARTED ON: get rid of `magic numbers', make them constants + +; force shuffling at bootup. Possible shuffle 256 times before starting +; main_loop (nobody would ever notice), then shuffle until 10 frames after +; the button is pressed *and released* to avoid would-be cheaters. + +; get one random bit per frame, whether we need one or not. + +;;;;; +; +; Stuff I may do, if I can free up some more RAM/ROM: +; +;;;;; + +; replace the `cursor' with the ball? would give us permanently red cursor, +; would keep the cursor the same color no matter what card +; is under it. + +; score each hand as it's completed? means we would have to display the +; card to be played and the score at the same time... + +; perhaps we could set up card pointers during the kernel, during the 5 scans +; between cardloops? Have to check the timing on this, but it would free up +; 40 bytes of RAM (!) If we do this, we can then keep track of deck state +; in between hands, instead of starting each shuffling round with an +; ordered deck! This is only going to be do-able if I'm using the ball for +; the cursor... + +; perhaps slow down scoring & flash the row/col being scored? + +; 2-player mode? (all we really have to do is score vert & horiz separately) + +;;;;; +; +; Stuff that was on the TODO list that is mostly or all done: +; +;;;;; + +; DONE: +; make Select act like a toggle instead of having to hold it down to see +; the crib sheet. + +; DONE: Clean up score font some (3, 5, 8 at least) + +; DONE: Use better-looking playfield for crib sheet (now it's in color, +; should I use a 4x5 uppercase-only font too? + +; DONE: use missiles for 9-pixel-wide symmetrical cards. It came out OK, +; and changing no_card gave me a border on the right even when the cursor's +; there. + +; DONE: +; clean up huge nasty block card shape data: use macros so at least the source +; only has one each of each card/rank. After this is done, center the ranks +; (assume 9-pixel-wide cards, even if I don't actually use them) + +; DONE: +; Add scrolling title/copyright during shuffle (in kill_rest). Not sure +; whether to use PF* or GRP* 48-pixel routine. + +; DONE: center the cards on the display, ref. Manuel's post 11/22/01 + +; DONE: +; serious bug: the 10's digit of the score isn't displayed if it's zero, +; even if it needs to be (100 shows up as 1 0). Thanks to Jake Patterson +; for pointing this out. + +; (mostly) DONE: Sound + +; DONE: Help/Scoring screen (SELECT) + +; (I think) DONE: Figure out what caused the glitch (screenshot: graphics_glitch.jpg) + +; DONE: joystick debounce + +; DONE: Make sure calc_score doesn't eat too many cycles (just test on real hardware +; & see if it glitches) + +; DONE: Blank leading zeroes in score + +; DONE: +; Decide whether royal flush should be 36 points or 30 like other +; straight flushes (Hoyle says 30, so do online rules, but I like 36... Also +; the best 5x5 grid would then be worth 254 points!).. I haven't decided +; whether or not to do this, but I have decided to hard-code it instead of +; making it optional (so people can compare their scores without having to +; take into account how the scoring was done). +; +; I've decided not to bother with 36-point royal flushes. It doesn't really +; add anything to the game, and adds cycles to the calc_score routine. + +; DONE: color the score? (red=below 25, yellow=25 to 40, grn=40 & up?) + +; DONE: Make left difficulty actually make the game harder + +; DONE: Add some kind of indicator to let the player know whether he's about to play +; the hard or easy game (H or E in 4th card column?) + +; DONE: implement color/bw switch + +; DONE: Make right difficulty control whether diagonals are scored or not (only +; poll during the shuffle) + +; DONE: add an indicator to let the player know whether diags. will be scored. + -- cgit v1.2.3