aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2015-04-13 04:59:08 -0400
committerB. Watson <yalhcru@gmail.com>2015-04-13 04:59:08 -0400
commit1abc56ed5dd52af310add7916bf9ff0ef73f2f12 (patch)
treecd9c944a52f0aab06a1643a48067d65395080c5f
downloadpokersquares-1abc56ed5dd52af310add7916bf9ff0ef73f2f12.tar.gz
initial commitHEADmaster
-rw-r--r--LICENSE14
-rw-r--r--Makefile44
-rw-r--r--README107
-rw-r--r--pftitle.inc163
-rw-r--r--pokersol.inc392
-rw-r--r--pokersquares.dasm2036
-rw-r--r--pokersquares.pal.binbin0 -> 4096 bytes
-rw-r--r--pokersquares.release.binbin0 -> 4096 bytes
-rw-r--r--vcs.h158
9 files changed, 2914 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ee7d6a5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,14 @@
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+
+ Everyone is permitted to copy and distribute verbatim or modified
+ copies of this license document, and changing it is allowed as long
+ as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bc3e855
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,44 @@
+# Makefile for Poker Squares, public release version.
+
+# Assembler to use. Tested with DASM 2.20.09.
+DASM=dasm
+
+# Define PAL=1 to build PAL version (untested on real hardware)
+PAL=
+
+# Level of verbosity for dasm (0 to 3)
+VERBOSE=1
+
+# shouldn't need to edit or redefine anything below this point.
+PROJ=pokersquares
+INCLUDES=pftitle.inc pokersol.inc vcs.h
+
+ifeq ($(PAL),)
+PALFLAG=
+COMPARE=release
+else
+PALFLAG=-DPAL
+COMPARE=pal
+endif
+
+all: $(PROJ).bin check
+
+$(PROJ).bin: $(PROJ).dasm $(INCLUDES)
+ $(DASM) $(PROJ).dasm $(PALFLAG) \
+ -o$(PROJ).bin -f3 -v$(VERBOSE) -l$(PROJ).list -s$(PROJ).syms
+
+# cmp is silent, add echoes to proclaim our results to all and sundry:
+check: $(PROJ).bin
+ @cmp $(PROJ).bin $(PROJ).$(COMPARE).bin && \
+ ( echo ; echo '**********'; \
+ echo "* OK: $(PROJ).bin and $(PROJ).$(COMPARE).bin are identical" ; \
+ echo '**********' ; echo ) || \
+ ( echo ; echo '!!!!!!!!!!'; \
+ echo "! ERROR: $(PROJ).bin and $(PROJ).$(COMPARE).bin are different" ; \
+ echo '!!!!!!!!!!' ; echo ; exit 1 )
+
+clean:
+ rm -f $(PROJ).bin $(PROJ).syms $(PROJ).list
+
+pal: clean
+ $(MAKE) PAL=1
diff --git a/README b/README
new file mode 100644
index 0000000..36baa01
--- /dev/null
+++ b/README
@@ -0,0 +1,107 @@
+This is the source to the 2600 game Poker Squares.
+
+The game was released back in 2005. You can buy a copy, or just download
+the ROM image and manual, at the AtariAge store:
+
+https://www.atariage.com/software_page.html?SoftwareLabelID=2724
+
+During development, I posted sources to the old stellalist, but never
+did get around to releasing the source to the final version. So here it
+finally is.
+
+File list:
+
+pokersquares.dasm - The main source file, 6502 assembly with DASM syntax.
+
+pftitle.inc - Playfield data for the scrolling copyright message.
+
+pokersol.inc - Playfield data for the instructions.
+
+vcs.h - From the old mailing list. defines the standard VCS labels.
+ An old version of vcs.h, before all the fancy macros got
+ added.
+
+pokersquares.release.bin - The released binary. Can be downloaded
+ from AtariAge. This copy is the one I sent to
+ them in the first place (not that it matters;
+ they're identical).
+
+pokersquares.pal.bin - PAL binary. Untested, never released, sitting on
+ my hard drive for the past 10+ years.
+
+README - You're reading it.
+
+LICENSE - The WTFPL. Applies to all files except vcs.h.
+
+The first 4 files are the original source. I replaced my gnarly old
+Makefile with a cleaned-up and simpler one, and added the "make check"
+target to verify that the assembled binary matches the one downloaded
+from AtariAge.
+
+Building:
+
+The Makefile expects a more-or-less UNIX-like environment. This could be
+Linux, *BSD, Mac OSX, or Windows with msys or cygwin tools... or something
+else entirely (anyone still use BeOS? How about MinT on an Atari ST?)
+
+If you have GNU make and dasm installed and available on your $PATH, you
+should be able to just run 'make' (or maybe 'gmake'). The result is a 4K
+binary file called 'pokersquares.bin', which you can run with e.g. stella
+or z26, or burn to an EPROM and play on a real 2600. Also an assembly
+listing (pokersquares.list) and a symbol table dump (pokersquares.syms)
+are generated.
+
+To build the PAL version, 'make pal'. I've no idea if it'll work on
+real PAL hardware (never got a chance to test it), but at least Stella
+emulates it OK.
+
+If your dasm binary isn't installed on your $PATH, you can use a
+command like:
+
+ make DASM=/path/to/your/dasm
+
+If you don't have GNU make (maybe you're on a user-hostile OS that
+doesn't ship development tools, or maybe you don't like GNU), but you
+do have DASM, you can probably build with:
+
+ dasm pokersquares.dasm -opokersquares.bin -f3 -v1
+
+Notes:
+
+The *.inc files were generated with a perl script, which I seem
+to have lost (or maybe just forgotten the name of) in the last 10
+years. Basically, I "drew" the playfields in ASCII art with a text editor,
+then ran that through the perl script, which turned it into labels and
+.byte declarations for DASM's consumption.
+
+After the assembler does its thing, the newly-built binary is checked
+against either pokersquares.release.bin or pokersquares.pal.bin using
+the *nix 'cmp' command. If it complains that the files differ, the mostly
+likely cause is your DASM version.
+
+You might run into assembly errors with versions of DASM newer than
+about 2005. I used version 2.20.07 during development, and have just
+successfully built with 2.20.09. Note that these old versions of DASM
+can't be compiled as 64-bit code (or, they can be compiled, but crash
+when you try to run them).
+
+At the time of this writing, DASM development has just started back
+up. One of the developers' goals is compatibility with historic versions,
+so you might be able to use a very recent version.
+
+License:
+
+The file vcs.h came from the old stella mailing list. It's a collaborative
+work, added to by many list members. I don't recall there ever being a
+formal license for vcs.h, but it's considered a public domain work to
+the best of my knowledge. If I'm wrong on this, please correct me!
+
+Everything else in this directory is my own original work, released
+under the WTFPL. License terms can be found in the file LICENSE or at:
+
+http://www.wtfpl.net/txt/copying/
+
+Author:
+
+B. Watson, <yalhcru@gmail.com>. I can also be reached as Urchlay on
+FreeNode IRC in the ##atari channel.
diff --git a/pftitle.inc b/pftitle.inc
new file mode 100644
index 0000000..d5e805b
--- /dev/null
+++ b/pftitle.inc
@@ -0,0 +1,163 @@
+t_left_pf1
+ byte %11000100
+ byte %10101010
+ byte %11001010
+ byte %10001010
+ byte %10001010
+ byte %10000100
+ byte %00000000
+ byte %01100100
+ byte %10001010
+ byte %01001010
+ byte %00101010
+ byte %00100100
+ byte %11000010
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01110011
+ byte %10001000
+ byte %10111000
+ byte %10101001
+ byte %10111010
+ byte %10001010
+ byte %01110011
+ byte %00000000
+ byte %11000101
+ byte %10100101
+ byte %11000111
+ byte %10100111
+ byte %11000111
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ repeat 22
+ byte 0
+ repend
+
+t_left_pf2
+ byte %01110101
+ byte %00010101
+ byte %00110011
+ byte %00010101
+ byte %00010101
+ byte %01110101
+ byte %00000000
+ byte %00100101
+ byte %01010101
+ byte %01110101
+ byte %01010101
+ byte %01010101
+ byte %01010010
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %10001000
+ byte %01010101
+ byte %01010101
+ byte %01010100
+ byte %01010100
+ byte %01010100
+ byte %10001001
+ byte %00000000
+ byte %11100100
+ byte %01001010
+ byte %01001110
+ byte %01001010
+ byte %01001010
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ repeat 22
+ byte 0
+ repend
+
+t_right_pf0
+ byte %00110000
+ byte %01010000
+ byte %00110000
+ byte %01010000
+ byte %01010000
+ byte %01010000
+ byte %00000000
+ byte %00110000
+ byte %01010000
+ byte %00110000
+ byte %01010000
+ byte %01010000
+ byte %01010000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %11000000
+ byte %10010000
+ byte %10010000
+ byte %10010000
+ byte %10010000
+ byte %10010000
+ byte %11000000
+ byte %00000000
+ byte %11000000
+ byte %00100000
+ byte %01000000
+ byte %10000000
+ byte %01100000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ repeat 22
+ byte 0
+ repend
+
+t_right_pf1
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %11100110
+ byte %10001000
+ byte %11000100
+ byte %10000010
+ byte %10000010
+ byte %11101100
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %10000000
+ byte %00000000
+ byte %00100110
+ byte %01010101
+ byte %01010101
+ byte %01010101
+ byte %00100101
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ repeat 22
+ byte 0
+ repend
+
+t_spade
+ byte %11111110
+ byte %11000110
+ byte %11000110
+ byte %11101110
+ byte %11101110
+ byte %10101010
+ byte %10101010
+ byte %10000010
+ byte %10000010
+ byte %11000110
+ byte %11000110
+ byte %11101110
+ byte %11101110
+ byte %11111110
diff --git a/pokersol.inc b/pokersol.inc
new file mode 100644
index 0000000..67170fe
--- /dev/null
+++ b/pokersol.inc
@@ -0,0 +1,392 @@
+left_pf0
+ byte %00000000
+ byte %00110000
+ byte %01000000
+ byte %00100000
+ byte %00010000
+ byte %01100000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01000000
+ byte %01000000
+ byte %01110000
+ byte %01010000
+ byte %01010000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00110000
+ byte %01000000
+ byte %00100000
+ byte %00010000
+ byte %01100000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00010000
+ byte %00010000
+ byte %00110000
+ byte %00010000
+ byte %01110000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01110000
+ byte %01000000
+ byte %01100000
+ byte %01000000
+ byte %01110000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00010000
+ byte %00010000
+ byte %00110000
+ byte %00010000
+ byte %01110000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01110000
+ byte %00010000
+ byte %01110000
+ byte %01000000
+ byte %01110000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00010000
+ byte %00010000
+ byte %00110000
+ byte %01010000
+ byte %00110000
+ byte %00000000
+pf_bytes = [.-left_pf0]-1
+
+
+left_pf1
+ byte %00000000
+ byte %01010010
+ byte %01000010
+ byte %01000011
+ byte %01000010
+ byte %11100011
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00100100
+ byte %01010100
+ byte %01010110
+ byte %01010100
+ byte %00100111
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01001010
+ byte %01001010
+ byte %01001100
+ byte %01001010
+ byte %11101100
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %11101110
+ byte %10101000
+ byte %10101000
+ byte %10101000
+ byte %10101000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00100100
+ byte %01010100
+ byte %01010110
+ byte %01010100
+ byte %00100111
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %11101110
+ byte %10001010
+ byte %10001010
+ byte %10001010
+ byte %10001010
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01000101
+ byte %01000101
+ byte %01100111
+ byte %01010101
+ byte %01100010
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %10101110
+ byte %10100100
+ byte %11100100
+ byte %10100100
+ byte %01001110
+ byte %00000000
+
+left_pf2
+ byte %00000000
+ byte %11011100
+ byte %01000100
+ byte %01000100
+ byte %01000100
+ byte %01000101
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %11010100
+ byte %10010100
+ byte %10001100
+ byte %10010100
+ byte %11010100
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %10010101
+ byte %01010101
+ byte %01010111
+ byte %01010101
+ byte %10010010
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %10100111
+ byte %10100001
+ byte %11100001
+ byte %10100001
+ byte %10100001
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %11010100
+ byte %10010100
+ byte %10001100
+ byte %10010100
+ byte %11010100
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01010011
+ byte %01010100
+ byte %01110010
+ byte %01010001
+ byte %01010110
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %10101110
+ byte %10100100
+ byte %01100100
+ byte %10100100
+ byte %01101110
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000101
+ byte %00000101
+ byte %00000011
+ byte %00000101
+ byte %00000011
+ byte %00000000
+
+right_pf0
+ byte %00000000
+ byte %11010000
+ byte %00010000
+ byte %10010000
+ byte %01010000
+ byte %10010000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01010000
+ byte %01000000
+ byte %01000000
+ byte %01000000
+ byte %11010000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01000000
+ byte %01010000
+ byte %11010000
+ byte %01000000
+ byte %01010000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01100000
+ byte %10000000
+ byte %01000000
+ byte %00100000
+ byte %11000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %01010000
+ byte %01000000
+ byte %01000000
+ byte %01000000
+ byte %11010000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ byte %00000000
+ org [>.]*256+256
+
+right_pf1
+ byte %00000001
+ byte %00101001
+ byte %10101001
+ byte %00111001
+ byte %00101001
+ byte %10101001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %10110001
+ byte %10101001
+ byte %10101001
+ byte %10101001
+ byte %00110001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %10010001
+ byte %10010001
+ byte %10010001
+ byte %10010001
+ byte %10111001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %01110101
+ byte %01000001
+ byte %01100001
+ byte %01000001
+ byte %01110001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %10110001
+ byte %10101001
+ byte %10101001
+ byte %10101001
+ byte %00110001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+ byte %00000001
+
+right_pf2
+ byte %11111111
+ byte %10001000
+ byte %10101011
+ byte %10101001
+ byte %10101011
+ byte %10001000
+ byte %11111111
+ byte %11111111
+ byte %11111111
+ byte %10001000
+ byte %10101101
+ byte %10001101
+ byte %11101100
+ byte %10001101
+ byte %11111111
+ byte %11111111
+ byte %11111111
+ byte %10001000
+ byte %11101101
+ byte %10001101
+ byte %10111100
+ byte %10001101
+ byte %11111111
+ byte %11111111
+ byte %11111111
+ byte %10001000
+ byte %10101101
+ byte %10101101
+ byte %10101100
+ byte %10001101
+ byte %11111111
+ byte %11111111
+ byte %11111111
+ byte %11100011
+ byte %11101011
+ byte %11100011
+ byte %11111011
+ byte %11100011
+ byte %11111111
+ byte %11111111
+ byte %11111111
+ byte %11100011
+ byte %11101111
+ byte %11100011
+ byte %11111011
+ byte %11100011
+ byte %11111111
+ byte %11111111
+ byte %11111111
+ byte %11100011
+ byte %11101111
+ byte %11100111
+ byte %11101111
+ byte %11100011
+ byte %11111111
+ byte %11111111
+ byte %11111111
+ byte %11100011
+ byte %11110111
+ byte %11110111
+ byte %11110011
+ byte %11110111
+ byte %11111111
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 <urchlay@geocities.com>
+
+; 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,x
+ 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
+ sta scoredig0+2
+; sta scoredig0+4
+ 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
+ lda #>score_blank
+ sta left_diff_ptr+1
+ jmp ld_off
+ld_on
+ lda #<left_diff_hard
+ sta left_diff_ptr
+ lda #>left_diff_hard
+ sta left_diff_ptr+1
+ld_off
+
+ lda diff_shadow
+ bpl rd_on
+ lda #<score_blank
+ sta right_diff_ptr
+ lda #>score_blank
+ sta right_diff_ptr+1
+ jmp rd_off
+rd_on
+ lda #<right_diff_hard
+ sta right_diff_ptr
+ 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
+hi_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.
+
diff --git a/pokersquares.pal.bin b/pokersquares.pal.bin
new file mode 100644
index 0000000..688cf35
--- /dev/null
+++ b/pokersquares.pal.bin
Binary files differ
diff --git a/pokersquares.release.bin b/pokersquares.release.bin
new file mode 100644
index 0000000..01e0018
--- /dev/null
+++ b/pokersquares.release.bin
Binary files differ
diff --git a/vcs.h b/vcs.h
new file mode 100644
index 0000000..dbddf05
--- /dev/null
+++ b/vcs.h
@@ -0,0 +1,158 @@
+;
+; VCS system equates
+;
+; Vertical blank registers
+;
+VSYNC = $00
+;VS_Enable = 2
+;
+VBLANK = $01
+;VB_Enable = 2
+;VB_Disable = 0
+;VB_LatchEnable = 64
+;VB_LatchDisable = 0
+;VB_DumpPots = 128
+; I don't know a good name to un-dump the pots,
+; at least that makes sense.
+
+WSYNC = $02
+RSYNC = $03 ;for sadists
+;
+; Size registers for players and missiles
+;
+NUSIZ0 = $04
+NUSIZ1 = $05
+;P_Single = 0
+;P_TwoClose = 1
+;P_TwoMedium = 2
+;P_ThreeClose = 3
+;P_TwoFar = 4
+;P_Double = 5
+;P_ThreeMedium = 6
+;P_Quad = 7
+
+;M_Single = $00
+;M_Double = $10
+;M_Quad = $20
+;M_Oct = $40
+
+;
+; Color registers
+;
+COLUP0 = $06
+COLUP1 = $07
+COLUPF = $08
+COLUBK = $09
+
+;
+; Playfield Control
+;
+CTRLPF = $0A
+;PF_Reflect = $01
+;PF_Score = $02
+;PF_Priority = $04
+; Use missile equates to set ball width.
+
+REFP0 = $0B
+REFP1 = $0C
+;P_Reflect = $08
+
+PF0 = $0D
+PF1 = $0E
+PF2 = $0F
+RESP0 = $10
+RESP1 = $11
+RESM0 = $12
+RESM1 = $13
+RESBL = $14
+AUDC0 = $15
+AUDC1 = $16
+AUDF0 = $17
+AUDF1 = $18
+AUDV0 = $19
+AUDV1 = $1A ;duh
+
+;
+; Players
+;
+GRP0 = $1B
+GRP1 = $1C
+
+;
+; Single-bit objects
+;
+ENAM0 = $1D
+ENAM1 = $1E
+ENABL = $1F
+;M_Enable = 2
+
+HMP0 = $20
+HMP1 = $21
+HMM0 = $22
+HMM1 = $23
+HMBL = $24
+
+; Miscellaneous
+VDELP0 = $25
+VDEL01 = $26
+VDELP1 = $26
+VDELBL = $27
+RESMP0 = $28
+RESMP1 = $29
+HMOVE = $2A
+HMCLR = $2B
+CXCLR = $2C
+CXM0P = $30
+CXM1P = $31
+CXP0FB = $32
+CXP1FB = $33
+CXM0FB = $34
+CXM1FB = $35
+CXBLPF = $36
+CXPPMM = $37
+INPT0 = $38
+INPT1 = $39
+INPT2 = $3A
+INPT3 = $3B
+INPT4 = $3C
+INPT5 = $3D
+
+;
+; Switch A equates.
+;
+; There are more elegant ways than using all eight of these. :-)
+;
+SWCHA = $0280
+;J0_Right = $80
+;J0_Left = $40
+;J0_Down = $20
+;J0_Up = $10
+;J1_Right = $08
+;J1_Left = $04
+;J1_Down = $02
+;J1_up = $01
+;
+; Switch B equates
+;
+SWCHB = $0282
+;P0_Diff = $80
+;P1_Diff = $40
+;Con_Color = $08
+;Con_Select = $02
+;Con_Start = $01
+
+;
+; Switch Control
+;
+SWACNT = $281
+SWBCNT = $283
+
+;
+; Timer
+;
+INTIM = $0284
+TIM1T = $0294
+TIM8T = $0295
+TIM64T = $0296
+TIM1024T = $0297
+