Skip to content

Instantly share code, notes, and snippets.

@tlindner
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tlindner/f269f2c5649b503e9f41 to your computer and use it in GitHub Desktop.
Save tlindner/f269f2c5649b503e9f41 to your computer and use it in GitHub Desktop.
Snake for Microware's OS-9
********************************************************************
* Snake - Animate slithering snake in window
*
* $Id$
*
* Edt/Rev YYYY/MM/DD Modified by
* Comment
* ------------------------------------------------------------------
* 1 2014/10/08 tim lindner
* Started writing code.
nam Snake
ttl Animate slithering snake in window
ifp1
use defsfile
endc
* Here are some tweakable options
DOHELP set 1 1 = include help info
STACKSZ set 32 estimated stack size in bytes
PARMSZ set 256 estimated parameter size in bytes
* Module header definitions
tylg set Prgrm+Objct
atrv set ReEnt+rev
rev set $00
edition set 1
mod eom,name,tylg,atrv,start,size
org 0
bail_flag rmb 1
windowx rmb 1
windowy rmb 1
time rmb 3
RND rmb 3
snakesize rmb 1
head rmb 1
IOBUF rmb 4
IOBUF2 rmb 4
cleartop equ . everything up to here gets cleared at start
* Finally the stack for any PSHS/PULS/BSR/LBSRs that we might do
snakebuffer rmb 80*2
rmb STACKSZ+PARMSZ
size equ .
* The utility name and edition goes here
name fcs /Snake/
fcb edition
* Place constant strings here
IFNE DOHELP
HlpMsg fcb C$LF
fcc /Use: Snake <size>/
fcb C$LF
fcb C$CR
fcc / Size is less than window width./
fcb C$LF
fcb C$CR
HlpMsgL equ *-HlpMsg
ENDC
*
* Here's how registers are set when this process is forked:
*
* +-----------------+ <-- Y (highest address)
* ! Parameter !
* ! Area !
* +-----------------+ <-- X, SP
* ! Data Area !
* +-----------------+
* ! Direct Page !
* +-----------------+ <-- U, DP (lowest address)
*
* D = parameter area size
* PC = module entry point abs. address
* CC = F=0, I=0, others undefined
* This routine skip over spaces and commas
*
* Entry:
* X = ptr to data to parse
* Exit:
* X = ptr to first non-whitespace char
* A = non-whitespace char
SkipSpcs lda ,x+
cmpa #C$SPAC
beq SkipSpcs
leax -1,x
rts
* The start of the program is here.
* Before any command line processing is done, we clear out
* our static memory from U to cleartop, then determine the
* size of our data area (minus the stack).
start pshs u,x save registers for later
leax <cleartop,u point to end of area to zero out
IFNE H6309
subr u,x subtract U from X
tfr x,w and put X in W
clr ,-s put a zero on the stack
tfm s,u+ and use TFM to clear starting at U
leas 1,s clean up the stack
ELSE
pshs x save end pointer on stack
clrnxt clr ,u+ clear out
cmpu ,s done?
bne clrnxt branch if not
leas 2,s else clear stack
ENDC
puls x,u and restore our earlier saved registers
lda ,x+ get first char
cmpa #C$CR CR?
lbeq ShowHelp
* Process command line (a single number)
nextChar suba #'0' Convert ASCII number to value
adda snakesize,u add stored value with new value
sta snakesize,u store new snake size
lda ,x get next char
cmpa #C$CR CR?
lbeq clDone
lda #10
ldb snakesize,u multiply current snake size by 10
mul
stb snakesize,u
lda ,x+ get next char
bra nextChar
clDone cmpb #80
ble timeSeed
ldb #80
stb snakesize,u
* Get Time packet to seed PRNG
timeSeed leax time,u
os9 F$Time
* Turn off cursor
leax IOBUF,u
lda #$05 05 20 is turn off cursor code
sta ,x
lda #$20
sta 1,x
ldy #2 Length of buffer
lda #1 Output path (stdout)
os9 I$Write Send the value to the device driver
* Add intercept
leax IR,pcr
os9 F$Icpt
* Clear screen
leax IOBUF,u
lda #$0c load 'clear screen' code for VDGINT/WINDINT
sta ,x
ldy #1 Length of buffer
lda #1 Output path (stdout)
os9 I$Write Send the value to the device driver
* get window size
lda #1 Output Path (stdout)
ldb #SS.ScSiz Request screen size
os9 I$Getstt Make requst
tfr x,d
decb
stb windowx,u
tfr y,d
decb
stb windowy,u
* compare parameter with window width
ldb snakesize,u
cmpb windowx,u
lbpl ShowHelp bail if parameter is larger than window
* fill snake buffer with initial X coordinate for snake positions
* figure out starting horizontal position of tail
clra
ldb snakesize,u
lsrb divide snake size by 2
stb ,-s
ldb windowx,u
lsrb divide window width by 2
subb ,s+ subtract half snake length from half window width
addb #$20 Offset Horizontal position for VDGINT and WINDINT
leax snakebuffer,u
lda snakesize,u
filloopx stb ,x++
incb
deca
bne filloopx fill snake buffer with initial horizontal coordinates
* Figure out starting vertical of snake body
ldb windowy,u
lsrb divide window height by 2
addb #$20 Offset vertical position for VDGINT or WINDINT
leax snakebuffer+1,u
lda snakesize,u
filloopy stb ,x++
deca
bne filloopy fill snake buffer with initial vertical coordinates
* Draw initial snake
leax IOBUF,u
lda #$02
sta 0,x
lda #'*'
sta 3,x
ldy #4 Length of buffer
lda snakesize,u
pshs u
leau snakebuffer,u
idrlp ldb ,u+
stb 1,x
ldb ,u+
stb 2,x
exg a,b
lda #1 Output path (stdout)
os9 I$Write Send the value to the device driver
exg b,a
deca
bne idrlp Initial draw loop
puls u
lda snakesize,u set head pointer to snake size minus one
deca
sta head,u
* Offset Window size for VDGINT and WINDINT
ldd windowx,u
addd #$2020
std windowx,u
* Set up IOBUF2 for Easing
lda #$02
sta IOBUF2,u
lda #' '
sta IOBUF2+3,U
MainLoop equ *
* Erase tail
leay snakebuffer,u
leax IOBUF2,u
ldb head,u
incb
cmpb snakesize,u
bne mlcont1
clrb
mlcont1 stb head,u Store new head offset
lslb
ldd b,y offset into table pointer
sta 1,x
stb 2,x
ldy #4
lda #1 Output path (stdout)
os9 I$Write Send the value to the device driver
* Find position for new head
* Set Reg X to point to current head position
copyhead ldb head,u get head index
lslb
leax snakebuffer,u
abx advance X to correct position
lsrb
bne mlcont2 if not zero
ldb snakesize,u get snake buffer size
mlcont2 decb Back up one index
lslb multiply by two
leay snakebuffer,u point y to start of buffer
leay b,y advance Y to correct position
ldd ,y load coordinates
std ,x save coordinates
* pick random number
pick ldb #$4
lbsr RAND
deca
beq goLeft
deca
beq goDown
deca
beq goRight
* Remember: coordinates are pre-offset by a value of $20
goUp ldb 1,x
cmpb #$20
beq pick
decb
stb 1,x
bra drawHead
goDown ldb 1,x
incb
cmpb windowy,u
beq pick
stb 1,x
bra drawHead
goLeft ldb ,x
cmpb #$20
beq pick
decb
stb ,x
bra drawHead
goRight ldb ,x
cmpb windowx,u
beq pick
incb
stb ,x
bra drawHead
drawHead ldd ,x
std IOBUF+1,u
lda #$1
ldy #$4
leax IOBUF,u
os9 I$Write Send the value to the device driver
lda bail_flag
bne ExitOK
ldx #$1
os9 F$Sleep
lbra MainLoop
ExitOk bsr bail
clrb
Exit os9 F$Exit
IR lda #$ff
sta bail_flag,u
rti
* Turn on cursor
bail leax IOBUF,u
lda #$05 05 21 is turn on cursor code
sta ,x
lda #$21
sta 1,x
ldy #2 Length of buffer
lda #1 Output path (stdout)
os9 I$Write Send the value to the device driver
rts
ShowHelp equ *
IFNE DOHELP
leax >HlpMsg,pcr point to help message
ldy #HlpMsgL get length
lda #$02 std error
os9 I$Write write it
ENDC
bra ExitOk
* THIS IS A FAST MEDIUM GRADE RANDOM NUMBER GENERATOR
* From SYMMETRY by Robert Gault, 1993
* LENGTH OF NON-REPEATING SEQUENCE = 16,777,215
* INTERMEDIATE OUTPUT 0 - 255 OR 0 - .996078431 STEPS OF .003921568
* ENTER: REG.B = N+1
* EXIT: REG.A = 0 TO N
* REG.B = FRACTIONAL PART OF N
RAND LDA RND+2,u GET 19TH BIT
ANDA #%00100000
LSLA ALIGN IT WITH 24TH BIT
LSLA FASTER THAN SHIFTING TO RIGHT
LSLA
ROLA
EORA RND+2,u XOR BITS 19&24
LSRA RESULT TO CARRY
ROR RND,u FEED RESULT INTO RANDOM NUMBER
ROR RND+1,u AND SHIFT TO THE RIGHT
ROR RND+2,u
LDA RND,u
MUL
RTS
emod
eom equ *
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment