; ============================================================
; Matrix Rain Effect with Digital Clock (Commodore PET)
; ============================================================
; Matrix-style falling characters + jiffy-clock HH:MM:SS
; Fully self-contained source
; From Petopia demo by Milasoft
; Can be modified for C64 or 128 as well
; ============================================================
* = $0401
; ------------------------------------------------------------
; BASIC stub: 10 SYS 1040
; ------------------------------------------------------------
!byte $19,$08,$0a,$00,$9e,$20,$28,$31,$30,$34,$30,$29
!byte 0,0,0
; ============================================================
; Initialization
; ============================================================
lda #147
jsr $ffd2 ; Clear screen
lda #0
sta TIMER
; ============================================================
; Seed random generator
; ============================================================
lda #21
sta .seedlo
lda #$1c
sta .seedhi ; seed random number generator
; ============================================================
; Initialize rain columns
; ============================================================
ldx #0
InitRain:
InitSpeed:
jsr RANDOM
cmp #9
bcs InitSpeed
sta SPEED,x
txa
sta RAINLO,x
inx
cpx #30 ; stop at 30 drips
bne InitRain
; ------------------------------------------------------------
; Initialize Y positions
; ------------------------------------------------------------
ldx #0
InitY:
lda RAINHIS
sta RAINHI,x
inx
cpx #30
bne InitY
; ============================================================
; Main Loop
; ============================================================
MainLoop:
VWait:
lda $e840
and #32
bne VWait ; wait for vsync to refresh
jsr $ffe4
cmp #32 ; space bar pressed?
bne NoToggle
lda #147
jsr $ffd2
inc .mode ; cycle mode
lda .mode
cmp #3
bne NoToggle
lda #0
sta .mode
jmp NoToggle
NoToggle:
cmp #32
bne +
jmp SkipDraw
+
lda .mode
cmp #1 ; clock only?
beq SkipRain
jsr DRAW ; make it rain
SkipRain:
lda .mode
cmp #2 ; rain only?
beq SkipDraw
jsr clockds ; show clock
SkipDraw:
jmp MainLoop
; ============================================================
; Draw Matrix Rain
; ============================================================
DRAW:
ldx #0
NextColumn:
ldy #0
lda RAINLO,x
sta $fd
lda RAINHI,x
sta $fe ; put pointer into ($fd)
lda $fe
cmp #$80
bcc SkipColumn ; less than $8000 (not ideal but it won't corrupt RAM)
cmp #$84
bcs SkipColumn ; greater than $8400 (off screen?)
jsr RANDOM ; get random character to put
sta ($fd),y
SkipColumn:
lda DEL,x
cmp SPEED,x ; load delay table to compare to speed
beq MoveDown ; do they match?
inc DEL,x ; no so increase delay wait
jmp Advance ; next please
MoveDown:
lda #0
sta DEL,x
lda RAINLO,x
sec
sbc #144
sta $fd
lda RAINHI,x
sbc #1 ; move up 10 lines. this is somewhat sloppy
sta $fe ; but it works. subtract 144 + 256 bytes = 400
lda $fe
cmp #$80
bcc SkipTail ; check boundaries $8000 and $8400
cmp #$84
bcc ClearTail
lda #$80
sta RAINHI,x ; we've reached the bottom
ResetX:
jsr RANDOM ; get random value
cmp #40 ; ensure its on screen
bcs ResetX ; we could AND #$28 but less appealing
sta RAINLO,x
ResetSpeed:
jsr RANDOM
cmp #5
bcs ResetSpeed
sta SPEED,x
inc TIMER
lda TIMER
cmp #60
bne Advance
jmp Advance
ClearTail:
lda #32
sta ($fd),y
SkipTail:
lda RAINLO,x
clc
adc #40
sta RAINLO,x
lda RAINHI,x
adc #0
sta RAINHI,x
Advance:
inx
cpx #30
beq +
jmp NextColumn
+ rts
; ============================================================
; Random Number Generator (LFSR)
; ============================================================
RANDOM:
lda .seedhi
lsr
rol .seedlo
bcc NoEOR
eor #$b4
NoEOR:
sta .seedhi
eor .seedlo
rts
; ============================================================
; Variables
; ============================================================
RAINLO !fill 40,0
RAINHIS !byte $7f,$80,$7f,$80,$7f,$80,$7f,$80,$7f,$80
!byte $7f,$80,$7f,$80,$7f,$80,$7f,$80,$7f,$80
!byte $80,$80,$80,$80,$7f,$80,$80,$80,$80,$80
RAINHI !fill 31,0
SPEED !fill 30,0
DEL !fill 30,0
wPOKE !fill 30,0
.seedlo !byte 0
.seedhi !byte 0
TIMER !byte 0
; ============================================================
; Clock Interface
; ============================================================
TIME = $8d ; Commodore PET Jiffy clock
clockds:
jsr LoadJiffyClock
lda ClkHourDigits
sta num+1
lda ClkHourTens
sta num
lda ClkMinTens
sta num+2
lda ClkMinDigits
sta num+3
jsr show
rts
; ============================================================
; Load Jiffy Clock (FULL ROUTINE)
; ============================================================
SECOND_JIFFIES = 60
MINUTE_JIFFIES = 60 * SECOND_JIFFIES
zptmp = $6e
zptmpB = $6f
remainder = $fc
LoadJiffyClock:
lda #13
sta $89cb
sta $8a1b
sei
lda TIME+2
ldx TIME+1
ldy TIME
cli
sta zptmp
stx remainder
sty remainder+1
lda #0
sta remainder+2
ldx #3
hhrol:
rol zptmp
rol remainder
rol remainder+1
rol remainder+2
dex
bne hhrol
ldx #5
hhdiv:
rol zptmp
rol remainder
rol remainder+1
rol remainder+2
sec
lda remainder
sbc #$c0
tay
lda remainder+1
sbc #$4b
sta zptmpB
lda remainder+2
sbc #$03
bcc hhi
sta remainder+2
lda zptmpB
sta remainder+1
tya
sta remainder
hhi:
dex
bne hhdiv
rol zptmp
ldx zptmp
jsr GetDigitChars
stx ClkHourTens
sty ClkHourDigits
lda remainder
sta zptmp
rol zptmp
rol remainder+1
rol remainder+2
rol zptmp
rol remainder+1
rol remainder+2
ldx #6
mmdiv:
rol zptmp
rol remainder+1
rol remainder+2
sec
lda remainder+1
sbc #<MINUTE_JIFFIES
tay
lda remainder+2
sbc #>MINUTE_JIFFIES
bcc mmi
sta remainder+2
tya
sta remainder+1
mmi:
dex
bne mmdiv
rol zptmp
ldx zptmp
jsr GetDigitChars
stx ClkMinTens
sty ClkMinDigits
lda remainder+1
sta zptmp
rol zptmp
rol remainder+2
rol zptmp
rol remainder+2
ldx #6
ssdiv:
rol zptmp
rol remainder+2
sec
lda remainder+2
sbc #SECOND_JIFFIES
bcc ssi
sta remainder+2
ssi:
dex
bne ssdiv
rol zptmp
ldx zptmp
jsr GetDigitChars
stx ClkSecTens
sty ClkSecDigits
rts
; ============================================================
; Digit conversion
; ============================================================
GetDigitChars:
txa
ldx #0
sec
tenloop:
sbc #10
bcc done10
inx
bcs tenloop
done10:
adc #'0'+10
tay
txa
clc
adc #'0'
tax
rts
; ============================================================
; Clock Display Rendering
; ============================================================
show:
lda ClkSecDigits
and #1
bne nodot
lda #$51
sta $81cb
lda #$20
sta $821b
jmp showdig
nodot:
lda #$20
sta $81cb
lda #$51
sta $821b
showdig:
ldx #0
stx position
nextdig:
lda #<NUMBERS
sta line+1
lda #>NUMBERS
sta line+2
ldx position
lda num,x
sec
sbc #'0'
asl
asl
asl
sta line+1
lda scrlo,x
sta $01
lda scrhi,x
sta $02
jsr drawdigit
inc position
ldx position
cpx #4
bne nextdig
rts
drawdigit:
ldy #0
line: lda $c000
ldx #0
bitloop:
asl
sta $a2
bcc spc
lda #$51
bcs put
spc: lda #$20
put:
sta ($01),y
lda $01
sta $bb
lda $02
clc
adc #8
sta $bc
lda #$0d
sta ($bb),y
lda $a2
iny
inx
cpx #8
bne bitloop
cpy #$f8
beq ddone
tya
adc #$20
tay
inc line+1
bcc line
ddone:
rts
; ============================================================
; Tables & Fonts
; ============================================================
scrlo !byte $6a,$73,$7e,$87
scrhi !byte $81,$81,$81,$81
!align 255,0
NUMBERS
!byte $7c,$c6,$c6,$c6,$c6,$c6,$7c,$00
!byte $18,$38,$18,$18,$18,$18,$7e,$00
!byte $7c,$c6,$06,$7c,$c0,$c6,$fe,$00
!byte $7c,$c6,$06,$1c,$06,$c6,$7c,$00
!byte $cc,$cc,$cc,$fe,$0c,$0c,$0c,$00
!byte $fe,$c6,$c0,$fc,$06,$c6,$7c,$00
!byte $7c,$c6,$c0,$fc,$c6,$c6,$7c,$00
!byte $fe,$c6,$0c,$18,$18,$18,$18,$00
!byte $7c,$c6,$c6,$7c,$c6,$c6,$7c,$00
!byte $7c,$c6,$c6,$7e,$06,$c6,$7c,$00
num !byte 0,0,0,0
position !byte 0
.clock !byte 0
LastSecond !byte 0
.mode
!byte 0
ClkSecTens !byte 0
ClkSecDigits !byte 0
ClkHourTens !byte 0
ClkHourDigits !byte 0
ClkMinTens !byte 0
ClkMinDigits !byte 0
Tutorial: How to create Matrix Rain on Commodore PET Machine
-
milasoft64
- Posts: 23
- Joined: Sat Mar 18, 2023 9:33 pm
- Are you a real person?: No... I am a spambot, delete my account!
