festro source with working wiper routine

This commit is contained in:
Dagen Brock 2012-11-25 20:19:03 -06:00
commit a1fdd32e93
1 changed files with 608 additions and 0 deletions

608
festro.s Normal file
View File

@ -0,0 +1,608 @@
**************************************************
* FESTRO
* @author Dagen Brock <dagenbrock@gmail.com>
* @date 2012-11-11
*
* Style Guide:
* ALLCAPS Apple II ROM "Constants"
* CamelCase function names
* ]loops loops (duh)
* GSomething Global application constants
* _myVar local variables
**************************************************
org $2000
typ #$ff
xc off ; 65c02
xc
lst off
**************************************************
* Global Addresses / Pointers
**************************************************
srcPtr equz $00
dstPtr equz $02
**************************************************
* Main Demo Controller
**************************************************
DemoMain
:mainLoop
jsr KeyHandler
lda GDemoState
asl
tax
jmp (DemoSubroutineTable,x)
bra :mainLoop
DemoSubroutineTable
dw HandleProdrop
dw HandleDigawrite
dw HandleProdrop
dw HandleSwipeWrite
dw HandleProdrop
dw P8Quit
HandleSwipeWrite
]initSwipe
ldx #$23 ; reset line indexes
:clearLoop stz _swipeLinesX,x ;
dex
bne :clearLoop
stz _swipeActive ; reset overall index
* @todo make parameters ******************************
lda #FireTextHeight
sta _swipeMaxHeight ; set max height
lda #FireTextWidth
sta _swipeMaxWidth ; set max width
lda #5
sta _swipeXOffset ; set x position
lda #6
sta _swipeYOffset ; set y position
** DA LOOP!!! does one full pass of all lines.. this is the OUTERMOST LOOP
:swipeLoop
lda #1
sta _swipeLinesDone ; set true... flips false every time we find a char
lda _swipeMaxHeight ; increment active set - once per loop, up to max height
cmp _swipeActive
beq :swipeMaxHit
inc _swipeActive
:swipeMaxHit
stz _swipeCurrLine ; start with line 0
:swipeLineLoop
lda _swipeCurrLine
ldx _swipeMaxWidth
jsr Multiply8x8 ; multiply bufferwidth * linenumber
sta srcPtr
stx srcPtr+1 ; store our multiplication offset
clc
adc #FireText ; and add the buffer location
sta srcPtr
lda srcPtr+1
adc #>FireText
sta srcPtr+1 ; srcPtr points to first character of that line in buffer
lda _swipeCurrLine
clc
adc _swipeYOffset ; linenumber + y-offset
asl ; x2 for pointer
tax
lda LoLineTable,x ; now convert to ZP pointer
clc
adc _swipeXOffset ; but also add our screen x-offset
sta dstPtr
bcc :noAdd
lda LoLineTable+1,x ; rolled our low-byte so add 1 to high-byte
inc
bra :skip
:noAdd lda LoLineTable+1,x
:skip sta dstPtr+1 ; destptr points to first character of where this line is positioned on screen
ldx _swipeCurrLine
lda _swipeLinesX,x
tay ; get current character index
lda (srcPtr),y ; get char from buffer
beq :lineIsDone ; was it #$00?
sta (dstPtr),y ; store char to screen
inc _swipeLinesX,x ; next char
stz _swipeLinesDone ; found a char so we always set this false
:lineIsDone
inc _swipeCurrLine
lda _swipeCurrLine
cmp _swipeActive
bne :swipeLineLoop
lda #20
tax
tay
jsr SimpleWait
lda _swipeLinesDone
beq :swipeLoop
inc GDemoState
jmp DemoMain
* for (line =0 ; line < active ; line ++ ) {
* sourceptr = bufferwidth * line
* destPtr = ^lores[line+yoffset] + xoffset
* ldy arrayX[line]
* lda (sourceptr),y
* if (a != 0)
* sta (destptr),y
* inc arrayX[line]
* else
* linesdone ++
* }
* if (linesdone == maxlines) return
* else swipepassloop
_swipeLinesDone db 0 ; how many lines are fully complete
_swipeCurrLine db 0 ; drawing loop line index
_swipeActive db 0 ; number of lines to be updating
_swipeLinesX ds 24 ; array with x position of each line
_swipeMaxHeight db #$0 ; set # lines in the source buffer
_swipeMaxWidth db #0 ; set # characters per line in the source buffer
_swipeXOffset db #$0 ; screen offset for placement
_swipeYOffset db #$0 ; screen offset for placement
FireTextHeight equ #12 ; buffer height
FireTextWidth equ #34 ; buffer width
ds \
FireText asc " _______ ______ ",00
asc " / ____(_)_______ / _/ /_ ",00
asc " / /_ / / ___/ _ \ / // __/ ",00
asc " / __/ / / / / __/ _/ // /_ ",00
asc "/_/ /_/_/ \___/ /___/\__/ ",00
asc " ",00
asc " __ __ __ ",00
asc " / / / /___ / / ",00
asc " / / / / __ \/ / ",00
asc " / /_/ / /_/ /_/ ",00
asc " \____/ .___(_) ",00
asc " /_/ ",00
**************************************************
* Demo-Part Controllers
**************************************************
HandleDigawrite
lda #40
tax
tay
jsr SimpleWait
ldx #0
]writeLoop
lda _digawriteString,x
beq ]writeDone
sta Lo11+17,x
inx
phx
lda #20
tax
tay
jsr SimpleWait
plx
bra ]writeLoop
]writeDone
lda #$30
tax
tay
jsr SimpleWait
inc GDemoState
jmp DemoMain
_digawriteString asc "DiGAROK",00
** Dropper routine - not specific to ProDrop per se
** - uses DSEG0
HandleProdrop
lda _prodropState
beq :prodropScan
jmp :prodropUpdate
:prodropScan
lda #$10
tax
tay
jsr SimpleWait ; we actually pause a bit just for dramatic effect
lda #0 ; start scan at line 0 every time
sta _prodropScanLine
lda #DSEG0 ; initialize destination pointer
sta dstPtr
lda #>DSEG0
sta dstPtr+1
]scanLineLoop
lda _prodropScanLine
rol ; (line * 2) for table index
tax
lda LoLineTable,x
sta srcPtr
lda LoLineTable+1,x
sta srcPtr+1
ldy #0
]scanCharLoop
lda (srcPtr),y
cmp #" "
beq ]nextChar
and #%01111111 ; clear high bit to indicate non-animated state
phy ; +1
phy ; +2
ldy #0
sta (dstPtr),y
iny
pla ; +1
sta (dstPtr),y
lda _prodropScanLine
iny
sta (dstPtr),y
iny
jsr GetRand
and #%0111111 ; decided to limit it to make the values a little
; closer together. #$00 - #$7f
; this particularly helps with gaps when nothing is
; falling because you started with few characters
sta (dstPtr),y
ply ; 0
lda dstPtr ; now add 4
clc
adc #$04
sta dstPtr
bcc ]nextChar
inc dstPtr+1 ; increment page (high byte)
]nextChar
iny
cpy #40
bne ]scanCharLoop
inc _prodropScanLine
lda _prodropScanLine
cmp #24
bne ]scanLineLoop
; we're done scanning
lda #$FF
sta (dstPtr) ; set terminator byte
inc _prodropState
jmp DemoMain
rts ;; @todo: add rts support to jmp table stuff?
]prodropAnimDone
lda #0
sta _prodropState ; uhg..reset state before exit so can be called again
inc GDemoState ; ugh again... not great.. using globals
jmp DemoMain
:prodropUpdate
lda #0 ; finished = false
sta _prodropAnimDone
:prodropUpdateLoop
lda #20
tax
tay
jsr SimpleWait
lda _prodropAnimDone
bne ]prodropAnimDone
lda #1 ; set finished = true before we start our char
sta _prodropAnimDone ; loop, any time we find active char set false
lda #DSEG0 ; initialize source pointer (our character buffer)
sta srcPtr
lda #>DSEG0
sta srcPtr+1
:prodropAnimLoop
]isChar
lda (srcPtr)
beq ]nextAnimChar
cmp #$FF ; array termination byte
beq :prodropUpdateLoop ; reset src pointer and do it all over
stz _prodropAnimDone ; hate to continually set this false, but we have time
cmp #$80 ; check for high bit
bcs ]dropIt ; not set? then we're animating it
ldy #3 ; check random wait state
lda (srcPtr),y
beq ]setCharAnim ; is 0 so set it to animate on next pass
dec ; otherwise decrement wait state
sta (srcPtr),y
bra ]nextAnimChar
]dropIt
ldy #2
lda (srcPtr),y ; get Y value
asl
tax
lda LoLineTable,x ; convert to ZP pointer
sta dstPtr
lda LoLineTable+1,x
sta dstPtr+1
ldy #1
lda (srcPtr),y ; get our X value
tay
lda #" "
sta (dstPtr),y
* breath... holy crap all that just to draw a space at X,Y
ldy #2
lda (srcPtr),y ; get Y value
inc ; move it down
cmp #24
beq ]charFinished
sta (srcPtr),y
asl
tax
lda LoLineTable,x ; convert to ZP pointer
sta dstPtr
lda LoLineTable+1,x
sta dstPtr+1
ldy #1 ; get X value
lda (srcPtr),y
tay
lda (srcPtr) ; get real character
sta (dstPtr),y ; draw that f***er!
bra ]nextAnimChar
]charFinished
lda #0
sta (srcPtr)
bra ]nextAnimChar
]setCharAnim
lda (srcPtr)
ora #%10000000 ; set high bit
sta (srcPtr)
]nextAnimChar
lda srcPtr
clc
adc #4 ; struct size
sta srcPtr
bcc :prodropAnimLoop
inc srcPtr+1 ; next page
bra :prodropAnimLoop
* done = true
* foreach DSEG0-blahblah
* if 00
* skip
* else
* done = false
*
* if highbit
* if random 0
* then strip high bit and continue (beep?)
* else dec random
* else
* store space at x,y
* inc y
* if y = 25
* stz over char
* else
* store char at x,y
_prodropAnimDone db 1 ; any time we find a character it flips this false
_prodropScanLine db 0 ; starts scanning at line 0
_prodropState db 0 ; starts with 0, which is scan mode
**************************************************
* Called by DemoMain
**************************************************
KeyHandler
lda KEY
cmp #$80
blt ]noKey
sta STROBE
sta GKeyEvent
cmp #"q"
beq P8Quit
]noKey rts
P8Quit jsr $bf00
dfb $65
da qparms
rts
qparms dfb 4
dfb 0
da $0000
dfb 0
da $0000
**************************************************
* Awesome PRNG thx to White Flame (aka David Holz)
**************************************************
GetRand
lda _randomByte
beq :doEor
asl
bcc :noEor
:doEor eor #$1d
:noEor sta _randomByte
rts
_randomByte db 0
**************************************************
* SafeWait
* -silly triple loop, preserves AXY
**************************************************
SimpleWait
sta _waitA
stx _waitX
sty _waitY
lda _waitA
:parentWait
ldx _waitX
:secondWait
ldy _waitY
:innerWait
dey
bne :innerWait
dex
bne :secondWait
dec
bne :parentWait
:waitDone
lda _waitA
ldx _waitX
ldy _waitY
rts
_waitA db 0
_waitX db 0
_waitY db 0
**************************************************
* Multiply8x8
* params: a,x = 8bit multipliers
* result: stored in _multiplyResult and returned in a,x
**************************************************
Multiply8x8
stz _multiplyResult
stz _multiplyResult+1
cmp #0 ; short circuit on A = 0
beq :multiplyDone
cpx #0 ; short circuit on X = 0
beq :multiplyDone
tay
:loop tya ; sorry, i suck at asm maths routines
clc
adc _multiplyResult
sta _multiplyResult
bcc :next
inc _multiplyResult+1
:next dex
bne :loop
:multiplyDone lda _multiplyResult
ldx _multiplyResult+1
rts
_multiplyResult dw 0000
**************************************************
* Apple Standard Memory Locations
* @todo: finalize as include?
**************************************************
CLRLORES EQU $F832
LORES EQU $C050
TXTSET EQU $C051
MIXCLR EQU $C052
MIXSET EQU $C053
KEY EQU $C000
STROBE EQU $C010
SPEAKER EQU $C030
VBL EQU $C02E
**************************************************
* Lores/Text lines
* @todo: finalize as include?
**************************************************
Lo01 equ $400
Lo02 equ $480
Lo03 equ $500
Lo04 equ $580
Lo05 equ $600
Lo06 equ $680
Lo07 equ $700
Lo08 equ $780
Lo09 equ $428
Lo10 equ $4a8
Lo11 equ $528
Lo12 equ $5a8
Lo13 equ $628
Lo14 equ $6a8
Lo15 equ $728
Lo16 equ $7a8
Lo17 equ $450
Lo18 equ $4d0
Lo19 equ $550
Lo20 equ $5d0
* the "plus four" lines
Lo21 equ $650
Lo22 equ $6d0
Lo23 equ $750
Lo24 equ $7d0
LoLineTable da Lo01,Lo02,Lo03,Lo04,Lo05,Lo06
da Lo07,Lo08,Lo09,Lo10,Lo11,Lo12
da Lo13,Lo14,Lo15,Lo16,Lo17,Lo18
da Lo19,Lo20,Lo21,Lo22,Lo23,Lo24
**************************************************
* Data Segments
**************************************************
ds \
DSEG0 ds 1024 ; General 1K Data Store
**************************************************
* Global Variables
**************************************************
GKeyEvent db 0 ; keypress - allow subroutines to access
GDemoState db 0 ; current demo state
**************************************************
* State 'Enumerators'
**************************************************
DemoStateProdrop equ #0 ; P8 screen shows and letters drop off
DemoStateDigawrite equ #1 ; writes 'DiGAROK' and pauses
DemoStateDigadrop equ #2 ; Really same as DemoStateProdrop
DemoStateFire equ #3 ; Fire has a lot going on so has own substates
DemoStateAppleText equ #4 ; Draws ascii apple + greets/shouts
DemoStateGRSprite equ #5 ; GR mode sprite anim plus bottom text writer
DemoStateExit equ #6 ; Not sure... draw info text? just quit?
ProdropStateScan equ #0 ; Scans all characters into our data structure
ProdropStateUpdate equ #1 ; Does one round of character updates, buffer&screen
ProdropStateDone equ #2 ; Really just to let the callee(s) know it's all done
FireStatePuff equ #0 ; flame code with custom heat (puff) generator
FireStateFire1 equ #1 ; lower rndhot? or not...
FireStateLetterK equ #2 ; draws K, waits, poof
FireStateLetterF equ #3 ; draws F, waits, poof
FireStateLetterE equ #4 ; draws E, waits, poof
FireStateLetterS equ #5 ; draws S, waits, poof
FireStateLetterT equ #6 ; draws T, waits, poof
FireStateKFEST equ #7 ; draws logo, waits, poof
FireStateFlareOut equ #8 ; maybe do a flame up or fizzle out
lst on
sav /code/festro.sys