demosplash: work on 1k entry

This commit is contained in:
Vince Weaver 2023-01-30 08:53:53 -05:00
parent 5d3bdbce3a
commit 0507b6bd37
22 changed files with 1796 additions and 0 deletions

View File

@ -0,0 +1,78 @@
include ../../../Makefile.inc
DOS33 = ../../../utils/dos33fs-utils/dos33
TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft
EMPTYDISK = ../../../empty_disk/empty.dsk
PICTUREDSK = ~/research/picturedsk.git/picturedsk
LINKER_SCRIPTS = ../../../linker_scripts/
ZX02 = ~/research/6502_compression/zx02.git/build/zx02
all: apple_desire.dsk
###
apple_desire.dsk: HELLO APPLE_DESIRE AD
cp $(EMPTYDISK) apple_desire.dsk
$(DOS33) -y apple_desire.dsk SAVE A HELLO
$(DOS33) -y apple_desire.dsk BSAVE -a 0xc00 APPLE_DESIRE
$(DOS33) -y apple_desire.dsk BSAVE -a 0x6000 AD
###
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
###
submit: apple2_desire.zip
apple2_desire.zip: APPLE_DESIRE apple_desire.dsk
mkdir -p demosplash2022_apple2_desire
mkdir -p demosplash2022_apple2_desire/src
cp APPLE_DESIRE ./demosplash2022_apple2_desire
cp *.s ./demosplash2022_apple2_desire/src
cp *.inc ./demosplash2022_apple2_desire/src
cp file_id.diz ./demosplash2022_apple2_desire
cp apple_desire.dsk ./demosplash2022_apple2_desire
cp apple2_desire.mkv ./demosplash2022_apple2_desire
cp a2_desire_screen.png ./demosplash2022_apple2_desire
zip -r apple2_desire.zip demosplash2022_apple2_desire
####
APPLE_DESIRE: apple_desire.o
ld65 -o APPLE_DESIRE apple_desire.o -C $(LINKER_SCRIPTS)/apple2_c00.inc
apple_desire.o: apple_desire.s \
logo_intro.s zp.inc \
ay3_write_regs.s apple_desire.s interrupt_handler.s \
play_frame.s draw_letter.s freq.s freq_h.s bamps.s \
apple_logo.s \
mA2E_4.s mockingboard_constants.s mockingboard_init.s tracker_init.s
ca65 -o apple_desire.o apple_desire.s -l apple_desire.lst
####
APPLE_DESIRE.ZX02: APPLE_DESIRE
$(ZX02) -f APPLE_DESIRE APPLE_DESIRE.ZX02
AD: ad.o
ld65 -o AD ad.o -C $(LINKER_SCRIPTS)/apple2_6000.inc
ad.o: ad.s APPLE_DESIRE.ZX02
ca65 -o ad.o ad.s -l ad.lst
####
make_points: make_points.o
$(CC) -o make_points make_points.o
make_points.o: make_points.c
$(CC) $(CFLAGS) -c make_points.c
####
clean:
rm -f *~ *.o *.lst APPLE_DESIRE *.zip make_points

View File

@ -0,0 +1,26 @@
;
; by deater (Vince Weaver) <vince@deater.net>
.include "zp.inc"
.include "hardware.inc"
ad_start:
; size in ldsizeh:ldsizel (f1/f0)
lda #<src
sta zx_src_l+1
lda #>src
sta zx_src_h+1
lda #$c
jsr zx02_full_decomp
jmp $c00
.include "zx02_optim.s"
src:
.incbin "APPLE_DESIRE.ZX02"

View File

@ -0,0 +1,151 @@
; Apple II graphics/music in 1k
; by deater (Vince Weaver) <vince@deater.net>
; Zero Page
.include "zp.inc"
.include "hardware.inc"
apple2_desire:
; clear both pages of graphics
jsr HGR2
; Y is 0 here
dey ; color = $FF
sty HGR_BITS
lda #$20 ; clear page1
jsr BKGND+2
; A and Y are 0 now?
;===================
; music Player Setup
; assume mockingboard in slot#4
; inline mockingboard_init
.include "mockingboard_init.s"
.include "tracker_init.s"
cli ; enable music
.if 0
forever:
sta OUTL
sta LINE
lda #$d0
sta OUTH
line_loop:
lda LINE
jsr HPOSN ; (Y,X),(A) (values stores in HGRX,XH,Y)
; first top right
ldy #0
out_loop:
lda (OUTL),Y
sta (GBASL),Y
dey
bne out_loop
inc LINE
bne line_loop
end:
lda WHICH_TRACK
beq forever
.endif
.include "logo_intro.s"
;========================
; flip pages forever
main_loop:
lda FRAME
and #$80
; clc
; rol
asl
rol
tax
lda PAGE1,X
lda WHICH_TRACK
beq main_loop
rot_rot_rot:
lda #$0
jsr draw_apple
inc rot_rot_rot+1
bne blah
dec scale_smc
blah:
; beq main_loop
; lda AY_REGS+8
; sta HGR_SCALE
lda HGR_PAGE
eor #$60
sta HGR_PAGE
bne main_loop
.include "interrupt_handler.s"
.include "mockingboard_constants.s"
.include "apple_logo.s"
.include "draw_letter.s"
.include "freq.s"
.include "bamps.s"
letters_x:
.byte 14,62,110,154,176,220
letters_l:
.byte <letter_d,<letter_e,<letter_s,<letter_i,<letter_r,<letter_e
;letters_h:
; .byte >letter_d,>letter_e,>letter_s,>letter_i,>letter_r,>letter_e
;.align $100
.include "freq_h.s"
; logo
letter_d:
.include "./letters/d.inc"
letter_e:
.include "./letters/e.inc"
letter_s:
.include "./letters/s.inc"
letter_i:
.include "./letters/i.inc"
letter_r:
.include "./letters/r.inc"
; music
.include "mA2E_4.s"
.include "apple_shape.s"

View File

@ -0,0 +1,37 @@
draw_apple:
;=============================
; draw apple shape table logo
;=============================
; rotation in A
pha
scale_smc:
lda #10
sta HGR_SCALE
ldy #0
ldx #60
txa
; lda #60
jsr HPOSN ; set screen position to X= (y,x) Y=(a)
ldx #<apple_table ; point to bottom byte of shape address
ldy #>apple_table ; point to top byte of shape address
; ROT in A
; this will be 0 2nd time through loop, arbitrary otherwise
pla ; ROT
jmp XDRAW0 ; XDRAW 1 AT X,Y
; Both A and X are 0 at exit
; Z flag set on exit
; Y varies
;apple_table:
;.byte $27,$2c,$35,$8e,$24,$2c
;.byte $35,$be,$09,$24,$2c,$35,$be,$09
;.byte $20,$24,$8c,$12,$2d,$3c,$37,$2e
;.byte $0d,$25,$24,$4f,$39,$36,$2e,$00

View File

@ -0,0 +1,5 @@
apple_table:
.byte $27,$2c,$35,$8e,$24,$2c
.byte $35,$be,$09,$24,$2c,$35,$be,$09
.byte $20,$24,$8c,$12,$2d,$3c,$37,$2e
.byte $0d,$25,$24,$4f,$39,$36,$2e,$00

View File

@ -0,0 +1,32 @@
;=====================
;=====================
;=====================
; ay3 write regs
;=====================
;=====================
;=====================
; write all 14 registers at AY_REGS
ay3_write_regs:
; bytes
ldx #13 ; 2
ay3_write_reg_loop:
lda #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2
ldy #MOCK_AY_INACTIVE ; go inactive ; 2
stx MOCK_6522_ORA1 ; put address on PA1 ; 3
sta MOCK_6522_ORB1 ; latch_address on PB1 ; 3
sty MOCK_6522_ORB1 ; 3
; value
lda AY_REGS,X ; 2
sta MOCK_6522_ORA1 ; put value on PA1 ; 3
lda #MOCK_AY_WRITE ; ; 2
sta MOCK_6522_ORB1 ; write on PB1 ; 3
sty MOCK_6522_ORB1 ; 3
dex ; 1
bpl ay3_write_reg_loop ; 2
; rts

View File

@ -0,0 +1,98 @@
; pattern 0
; 0 -> F
; 48-> C
; 50-> A
; 52-> 9
; 54-> 8
; 56-> 7
; 58-> 6
; 60-> 5
; 62-> 4
bamps0:
; 0 15 30 45 48 50 52 54 56 58 60 62
.byte $FF,$FF,$FF,$3F,$2C,$2A,$29,$28,$27,$26,$25,$24
; pattern 1
; 0 -> F
; 9 -> C
;10 -> F
;20 -> C
;22 -> F
;29 -> C
;30 -> F
;31 -> C
;32 -> F
;40 -> C
; 48-> A
; 50-> 9
; 52-> 8
; 54-> 7
; 56-> 6
; 58-> 5
; 60-> 4
; 62-> 3
bamps1:
; 0 9 10 20 22 29 30 31 32 40 48 50 52 54 56 58 60 62
.byte $9F,$1C,$AF,$2C,$7F,$1C,$1F,$1C,$8F,$8C,$2A,$29,$28,$27,$26,$25,$24,$23
; pattern 2
; 0 ->F
; 13->C
; 14->F
; 15->C
; 16->F
; 24->C
; 26->9
; 28->8
; 30->7
; 32->F
; 45->C
; 46->F
; 47->C
; 48->F
; 56->C
; 58->9
; 60->7
; 62->6
bamps2:
; 0 13 14 15 16 24 26 28 30 32 45 46 47 48 56 58 60 62
.byte $DF,$1C,$1F,$1C,$8F,$2C,$29,$28,$27,$DF,$1C,$1F,$1C,$8F,$2C,$29,$27,$26
; pattern3
; 0->F
; 24->C
; 26->9
; 28->8
; 30->7
; 32->F
; 45->C
; 46->F
; 47->C
; 48->F
; 56->C
; 58->9
; 60->7
; 62->6
bamps3:
; 0 15 24 26 28 30 32 45 46 47 48 56 58 60 62
.byte $FF,$9F,$2C,$29,$28,$27,$DF,$1C,$1F,$1C,$8F,$2C,$29,$27,$26
; pattern4
; 0->0
; 60->F
; 61->C
; 62->F
; 63->C
; needs to immediately follow bamps3 for some reason?
bamps4:
; 0 15 30 45 60 61 62 63
.byte $F0,$F0,$F0,$F0,$1F,$1C,$1F,$1C
.align $100
deater_string:

View File

@ -0,0 +1,147 @@
;===============================
; draw desire letters, in order
;===============================
; X has color
draw_logo:
pha
jsr HCOLOR1 ; set color to X
ldx #5 ; draw 5 letters
letter_time:
lda letters_l,X ; get address
sta INL
lda #>letter_d ; assume on same page
sta INH
ldy letters_x,X ; get X offset
txa ; save X
pha
jsr draw_letter
pla
tax
dex
bpl letter_time
pla
jmp draw_apple
;========================
; draw letter
;========================
; so inefficient
; letter to draw in INL:INH
; Y is X offset
draw_letter:
sty LETTER_X ; store X-coord
lda LETTER_Y ; alternate up/down
eor #$8
sta LETTER_Y
ldy #$FF ; iterator
letter_loop:
hplot:
; setup X value
iny ; skip the new-line indicator
jsr get_x ; get adjusted x-coord in A
tax ; put in X
; setup Y value
jsr get_y ; get adjusted y-coord in A
ldy #0 ; set top of X value (FIXME)
jsr HPLOT0 ; plot at (Y,X), (A)
ldy SAVE_Y ; restore pointer
iny
hplot_to:
; get X value
jsr get_x ; get adjusted x-coord in A
pha ; save for later
lda #0 ; wrap if > 256
adc #0
tax
; get Y value
jsr get_y
tay ; put into Y
pla ; restore X value
jsr HGLIN ; line to (X,A),(Y)
ldy SAVE_Y
iny
; see if at end of line or of whole thing
lda (INL),Y ; get next value
bmi letter_done ; if negative, we are done
cmp #$7F
beq hplot
bne hplot_to
letter_done:
rts
;================
; get next X co-ord
; multipy by 2
; increment y
get_x:
lda (INL),Y ; get X value
asl ; need to multiply by 2
clc
adc LETTER_X
iny
rts
;================
; get next Y co-ord
; increment y
; save to SAVE_Y
get_y:
sty SAVE_Y ; save Y value on stack for later
lda (INL),Y ; get Y value
clc
adc LETTER_Y
rts

View File

@ -0,0 +1,12 @@
Apple2 Desire
-
1k Apple II demo for Demosplash 2022
it's actually hard to fit a Mockingboard track this small
also messing around with shape tables as per usual
by Deater / dSr
music by mA2E
Note: assumes Mockingboard in Slot#4.
Music only plays on left speaker.

View File

@ -0,0 +1,22 @@
; Octave 0 : 0 0 0 3 0 3 0 3 3 0 16 0
; Octave 1 : 45 0 0 19 0 23 0 0 0 0 5 0
; Octave 2 : 14 0 2 6 0 8 0 0 0 0 0 0
; Octave 3 : 0 0 0 1 0 1 0 2 0 0 2 0
; Octave 4 : 4 0 1 5 2 5 0 7 0 2 4 0
; Octave 5 : 3 0 4 1 5 2 0 0 0 0 0 0
; 30 notes allocated
;.byte 12,55,24,64,10,62,60,15,17,58,22,57,8,7,5,3,53,52,29,27,26,65,63,51,50,48,46,39,41,43,
frequencies_low:
.byte $D1,$51,$E8,$30,$49,$36,$3D,$36
.byte $DC,$44,$24,$48,$CF,$18,$B8,$6C
.byte $5B,$60,$6E,$9B,$B3,$2D,$33,$66
.byte $6C,$7A,$89,$CD,$B7,$A3
;frequencies_high:
;.byte $03,$00,$01,$00,$04,$00,$00,$03
;.byte $02,$00,$02,$00,$04,$05,$05,$06
;.byte $00,$00,$01,$01,$01,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00
; total len=61

View File

@ -0,0 +1,22 @@
; Octave 0 : 0 0 0 3 0 3 0 3 3 0 16 0
; Octave 1 : 45 0 0 19 0 23 0 0 0 0 5 0
; Octave 2 : 14 0 2 6 0 8 0 0 0 0 0 0
; Octave 3 : 0 0 0 1 0 1 0 2 0 0 2 0
; Octave 4 : 4 0 1 5 2 5 0 7 0 2 4 0
; Octave 5 : 3 0 4 1 5 2 0 0 0 0 0 0
; 30 notes allocated
;.byte 12,55,24,64,10,62,60,15,17,58,22,57,8,7,5,3,53,52,29,27,26,65,63,51,50,48,46,39,41,43,
;frequencies_low:
;.byte $D1,$51,$E8,$30,$49,$36,$3D,$36
;.byte $DC,$44,$24,$48,$CF,$18,$B8,$6C
;.byte $5B,$60,$6E,$9B,$B3,$2D,$33,$66
;.byte $6C,$7A,$89,$CD,$B7,$A3
frequencies_high:
.byte $03,$00,$01,$00,$04,$00,$00,$03
.byte $02,$00,$02,$00,$04,$05,$05,$06
.byte $00,$00,$01,$01,$01,$00,$00,$00
.byte $00,$00,$00,$00,$00,$00
; total len=61

View File

@ -0,0 +1,99 @@
;; HARDWARE LOCATIONS
KEYPRESS = $C000
KEYRESET = $C010
;; SOFT SWITCHES
CLR80COL = $C000 ; PAGE0/PAGE1 normal
SET80COL = $C001 ; PAGE0/PAGE1 switches PAGE0 in Aux instead
EIGHTYCOLOFF = $C00C
EIGHTYCOLON = $C00D
SPEAKER = $C030
SET_GR = $C050
SET_TEXT = $C051
FULLGR = $C052
TEXTGR = $C053
PAGE1 = $C054
PAGE2 = $C055
LORES = $C056 ; Enable LORES graphics
HIRES = $C057 ; Enable HIRES graphics
AN3 = $C05E ; Annunciator 3
PADDLE_BUTTON0 = $C061
PADDL0 = $C064
PTRIG = $C070
;; BASIC ROUTINES
NORMAL = $F273
HGR = $F3E2
HGR2 = $F3D8
HCLR = $F3F2
BKGND = $F3F6
HPOSN = $F411 ; (Y,X),(A) (values stores in HGRX,XH,Y)
HPLOT0 = $F457 ; plot at (Y,X), (A)
HCOLOR1 = $F6F0 ; set HGR_COLOR to value in X
HGLIN = $F53A ; line to (X,A),(Y)
DRAW0 = $F601
XDRAW0 = $F65D
XDRAW1 = $F661
;; MONITOR ROUTINES
HLINE = $F819 ;; HLINE Y,$2C at A
VLINE = $F828 ;; VLINE A,$2D at Y
CLRSCR = $F832 ;; Clear low-res screen
CLRTOP = $F836 ;; clear only top of low-res screen
SETGR = $FB40 ;; GR
SETCOL = $F864 ;; COLOR=A
TEXT = $FB36
TABV = $FB5B ;; VTAB to A
BELL = $FBDD ;; ring the bell
BASCALC = $FBC1 ;;
VTAB = $FC22 ;; VTAB to CV
HOME = $FC58 ;; Clear the text screen
WAIT = $FCA8 ;; delay 1/2(26+27A+5A^2) us
CROUT1 = $FD8B
SETINV = $FE80 ;; INVERSE
SETNORM = $FE84 ;; NORMAL
COUT = $FDED ;; output A to screen
COUT1 = $FDF0 ;; output A to screen
RESTORE = $FF3F
COLOR_BLACK = 0
COLOR_RED = 1
COLOR_DARKBLUE = 2
COLOR_PURPLE = 3
COLOR_DARKGREEN = 4
COLOR_GREY = 5
COLOR_MEDIUMBLUE = 6
COLOR_LIGHTBLUE = 7
COLOR_BROWN = 8
COLOR_ORANGE = 9
COLOR_GREY2 = 10
COLOR_PINK = 11
COLOR_LIGHTGREEN = 12
COLOR_YELLOW = 13
COLOR_AQUA = 14
COLOR_WHITE = 15
COLOR_BOTH_BLACK = $00
COLOR_BOTH_RED = $11
COLOR_BOTH_DARKBLUE = $22
COLOR_BOTH_DARKGREEN = $44
COLOR_BOTH_GREY = $55
COLOR_BOTH_MEDIUMBLUE = $66
COLOR_BOTH_LIGHTBLUE = $77
COLOR_BOTH_BROWN = $88
COLOR_BOTH_ORANGE = $99
COLOR_BOTH_PINK = $BB
COLOR_BOTH_LIGHTGREEN = $CC
COLOR_BOTH_YELLOW = $DD
COLOR_BOTH_AQUA = $EE
COLOR_BOTH_WHITE = $FF

View File

@ -0,0 +1,9 @@
5 HOME
10 PRINT "APPLE_DESIRE -- A 1K BYTE APPLE II INTRO"
15 PRINT " BY DEATER & MA2E / DSR"
20 PRINT CHR$(4)"CATALOG"
25 PRINT:PRINT "PRESS ANY KEY TO 'BRUN APPLE_DESIRE'"
30 GET A$
35 PRINT

View File

@ -0,0 +1,62 @@
;================================
;================================
; mockingboard interrupt handler
;================================
;================================
; On Apple II/6502 the interrupt handler jumps to address in 0xfffe
; This is in the ROM, which saves the registers
; on older IIe it saved A to $45 (which could mess with DISK II)
; newer IIe doesn't do that.
; It then calculates if it is a BRK or not (which trashes A)
; Then it sets up the stack like an interrupt and calls 0x3fe
; Note: the IIc is much more complicated
; its firmware tries to decode the proper source
; based on various things, including screen hole values
; we bypass that by switching out ROM and replacing the
; $fffe vector with this, but that does mean we have
; to be sure status flag and accumulator set properly
interrupt_handler:
php ; save status flags
cld ; clear decimal mode
; pha ; save A ; 3
; A is saved in $45 by firmware
txa
pha ; save X
tya
pha ; save Y
; inc $0404 ; debug (flashes char onscreen)
ay3_irq_handler:
bit MOCK_6522_T1CL ; clear 6522 interrupt by reading T1C-L ; 4
.include "play_frame.s"
.include "ay3_write_regs.s"
;=================================
; Finally done with this interrupt
;=================================
done_ay3_irq_handler:
pla
tay ; restore Y
pla
tax ; restore X
; pla ; restore a ; 4
; on II+/IIe (but not IIc) we need to do this?
interrupt_smc:
lda $45 ; restore A
plp ; restore flags
rti ; return from interrupt ; 6
;============
; typical
; ???? cycles

View File

@ -0,0 +1,30 @@
;================================
; draw the sorta vectored logo
;================================
; 908 bytes -- first display
; 916 bytes -- scroll down
; 914 bytes -- assume < 256 co-ords
; 908 bytes -- assume first co-oord is an HPLOT
; 906 bytes -- save value on stack rather than ZP
; discontinuity when improving the sound code
; 2BD bytes -- after really optimizing the draw code
show_logo:
; 101 0000
lda #80
sta LETTER_Y
ldx #$7 ; color white
lda #1 ; apple rotation
jsr draw_logo
lda #$20 ; switch HGR draw page
sta HGR_PAGE
lda #88
sta LETTER_Y
ldx #$0 ; color black
lda #63 ; apple rotation
jsr draw_logo

View File

@ -0,0 +1,448 @@
.align $100
channel_a_volume:
.byte 14,14,14,14,11,11,10,10
lengths:
.byte 0*8,1*8,2*8,4*8
tracks_l:
.byte <track4,<track0 ;,<track1,<track2,<track3
; assume all on same page
; tracks_h:
; .byte >track4,>track0 ;,>track1,>track2,>track3
bamps_l:
.byte <bamps4,<bamps0 ;,<bamps1,<bamps2,<bamps3
; bamps_h:
; .byte >bamps4,>bamps0 ;,>bamps1,>bamps2,>bamps3
track0:
; A: 12
; B: 55
; A: 12
.byte $00 ; frame=2 A=0 L=0
.byte $0D ; frame=2 B=1 L=2
; A: 24
; B: 64
.byte $04 ; frame=4 A=0 L=2
; A: 12
.byte $10 ; frame=6 A=2 L=0
.byte $1D ; frame=6 B=3 L=2
; A: 10
; B: 62
.byte $04 ; frame=8 A=0 L=2
; A: 12
; B: 60
.byte $20 ; frame=10 A=4 L=0
.byte $2D ; frame=10 B=5 L=2
; A: 15
.byte $00 ; frame=12 A=0 L=0
.byte $35 ; frame=12 B=6 L=2
; A: 17
; B: 58
.byte $3C ; frame=14 A=7 L=2
; A: 10
.byte $40 ; frame=16 A=8 L=0
.byte $4D ; frame=16 B=9 L=2
; A: 10
.byte $24 ; frame=18 A=4 L=2
; A: 22
.byte $24 ; frame=20 A=4 L=2
; A: 10
; B: 57
.byte $54 ; frame=22 A=10 L=2
; A: 8
; B: 58
.byte $20 ; frame=24 A=4 L=0
.byte $5D ; frame=24 B=11 L=2
; A: 7
; B: 57
.byte $60 ; frame=26 A=12 L=0
.byte $4D ; frame=26 B=9 L=2
; A: 5
; B: 55
.byte $68 ; frame=28 A=13 L=0
.byte $5D ; frame=28 B=11 L=2
; A: 3
; B: 53
.byte $70 ; frame=30 A=14 L=0
.byte $0D ; frame=30 B=1 L=2
; A: 12
; B: 52
.byte $78 ; frame=32 A=15 L=0
.byte $85 ; frame=32 B=16 L=2
; A: 12
.byte $00 ; frame=34 A=0 L=0
.byte $8D ; frame=34 B=17 L=2
; A: 24
.byte $04 ; frame=36 A=0 L=2
; A: 12
; B: 55
.byte $14 ; frame=38 A=2 L=2
; A: 10
.byte $00 ; frame=40 A=0 L=0
.byte $0D ; frame=40 B=1 L=2
; A: 12
.byte $24 ; frame=42 A=4 L=2
; A: 15
.byte $04 ; frame=44 A=0 L=2
; A: 17
.byte $3C ; frame=46 A=7 L=2
; A: 17
.byte $44 ; frame=48 A=8 L=2
; A: 17
.byte $44 ; frame=50 A=8 L=2
; A: 29
.byte $44 ; frame=52 A=8 L=2
; A: 29
.byte $94 ; frame=54 A=18 L=2
; A: 27
.byte $94 ; frame=56 A=18 L=2
; A: 26
.byte $9C ; frame=58 A=19 L=2
; A: 24
.byte $A4 ; frame=60 A=20 L=2
; A: 22
.byte $14 ; frame=62 A=2 L=2
; last: a=10 b=-1 len=2
.byte $54 ; frame=64 A=10 L=2
;.byte $ff
track1:
; A: 12
; B: 55
; A: 12
.byte $00 ; frame=2 A=0 L=0
.byte $0D ; frame=2 B=1 L=2
; A: 24
; B: 64
.byte $04 ; frame=4 A=0 L=2
; A: 12
.byte $10 ; frame=6 A=2 L=0
.byte $1D ; frame=6 B=3 L=2
; A: 10
; B: 62
.byte $04 ; frame=8 A=0 L=2
; A: 12
; B: 64
.byte $20 ; frame=10 A=4 L=0
.byte $2D ; frame=10 B=5 L=2
; A: 15
.byte $00 ; frame=12 A=0 L=0
.byte $1D ; frame=12 B=3 L=2
; A: 17
; B: 65
.byte $3C ; frame=14 A=7 L=2
; A: 10
.byte $40 ; frame=16 A=8 L=0
.byte $AD ; frame=16 B=21 L=2
; A: 10
.byte $24 ; frame=18 A=4 L=2
; A: 22
.byte $24 ; frame=20 A=4 L=2
; A: 10
; B: 64
.byte $54 ; frame=22 A=10 L=2
; A: 8
; B: 65
.byte $20 ; frame=24 A=4 L=0
.byte $1D ; frame=24 B=3 L=2
; A: 7
; B: 64
.byte $60 ; frame=26 A=12 L=0
.byte $AD ; frame=26 B=21 L=2
; A: 5
; B: 62
.byte $68 ; frame=28 A=13 L=0
.byte $1D ; frame=28 B=3 L=2
; A: 3
; B: 60
.byte $70 ; frame=30 A=14 L=0
.byte $2D ; frame=30 B=5 L=2
; A: 12
; B: 52
.byte $78 ; frame=32 A=15 L=0
.byte $35 ; frame=32 B=6 L=2
; A: 12
.byte $00 ; frame=34 A=0 L=0
.byte $8D ; frame=34 B=17 L=2
; A: 24
.byte $04 ; frame=36 A=0 L=2
; A: 12
.byte $14 ; frame=38 A=2 L=2
; A: 10
.byte $04 ; frame=40 A=0 L=2
; A: 12
.byte $24 ; frame=42 A=4 L=2
; A: 15
.byte $04 ; frame=44 A=0 L=2
; A: 17
.byte $3C ; frame=46 A=7 L=2
; A: 17
.byte $44 ; frame=48 A=8 L=2
; A: 17
.byte $44 ; frame=50 A=8 L=2
; A: 29
.byte $44 ; frame=52 A=8 L=2
; A: 29
.byte $94 ; frame=54 A=18 L=2
; A: 27
.byte $94 ; frame=56 A=18 L=2
; A: 26
.byte $9C ; frame=58 A=19 L=2
; A: 24
.byte $A4 ; frame=60 A=20 L=2
; A: 22
.byte $14 ; frame=62 A=2 L=2
; last: a=10 b=-1 len=2
.byte $54 ; frame=64 A=10 L=2
;.byte $ff
track2:
; A: 15
; B: 63
; A: 15
.byte $38 ; frame=2 A=7 L=0
.byte $B5 ; frame=2 B=22 L=2
; A: 27
.byte $3C ; frame=4 A=7 L=2
; A: 15
.byte $9C ; frame=6 A=19 L=2
; A: 17
; B: 62
.byte $3C ; frame=8 A=7 L=2
; A: 17
; B: 60
.byte $40 ; frame=10 A=8 L=0
.byte $2D ; frame=10 B=5 L=2
; A: 29
; B: 58
.byte $40 ; frame=12 A=8 L=0
.byte $35 ; frame=12 B=6 L=2
; A: 17
; B: 53
.byte $90 ; frame=14 A=18 L=0
.byte $4D ; frame=14 B=9 L=2
; A: 12
; B: 55
.byte $40 ; frame=16 A=8 L=0
.byte $85 ; frame=16 B=16 L=2
; A: 12
.byte $00 ; frame=18 A=0 L=0
.byte $0D ; frame=18 B=1 L=2
; A: 24
.byte $04 ; frame=20 A=0 L=2
; A: 12
.byte $14 ; frame=22 A=2 L=2
; A: 12
.byte $04 ; frame=24 A=0 L=2
; A: 12
.byte $04 ; frame=26 A=0 L=2
; A: 24
.byte $04 ; frame=28 A=0 L=2
; A: 12
.byte $14 ; frame=30 A=2 L=2
; A: 15
; B: 51
.byte $04 ; frame=32 A=0 L=2
; A: 15
.byte $38 ; frame=34 A=7 L=0
.byte $BD ; frame=34 B=23 L=2
; A: 27
.byte $3C ; frame=36 A=7 L=2
; A: 15
.byte $9C ; frame=38 A=19 L=2
; A: 17
; B: 55
.byte $3C ; frame=40 A=7 L=2
; A: 17
; B: 53
.byte $40 ; frame=42 A=8 L=0
.byte $0D ; frame=42 B=1 L=2
; A: 29
; B: 51
.byte $40 ; frame=44 A=8 L=0
.byte $85 ; frame=44 B=16 L=2
; B: 50
.byte $90 ; frame=45 A=18 L=0
.byte $BB ; frame=45 B=23 L=1
; A: 17
; B: 48
.byte $C3 ; frame=46 B=24 L=1
; B: 46
.byte $40 ; frame=47 A=8 L=0
.byte $CB ; frame=47 B=25 L=1
; A: 12
; B: 48
.byte $D3 ; frame=48 B=26 L=1
; A: 10
.byte $00 ; frame=52 A=0 L=0
.byte $CF ; frame=52 B=25 L=3
; A: 12
.byte $26 ; frame=56 A=4 L=3
; last: a=0 b=-1 len=8
.byte $10 ; frame=64 A=0 L=8
;.byte $ff
track3:
; A: 15
; B: 39
; A: 15
.byte $38 ; frame=2 A=7 L=0
.byte $DD ; frame=2 B=27 L=2
; A: 27
.byte $3C ; frame=4 A=7 L=2
; A: 15
.byte $9C ; frame=6 A=19 L=2
; A: 17
; B: 41
.byte $3C ; frame=8 A=7 L=2
; A: 17
; B: 43
.byte $40 ; frame=10 A=8 L=0
.byte $E5 ; frame=10 B=28 L=2
; A: 29
; B: 46
.byte $40 ; frame=12 A=8 L=0
.byte $ED ; frame=12 B=29 L=2
; A: 17
; B: 48
.byte $90 ; frame=14 A=18 L=0
.byte $D5 ; frame=14 B=26 L=2
; A: 12
; B: 43
.byte $40 ; frame=16 A=8 L=0
.byte $CD ; frame=16 B=25 L=2
; A: 12
.byte $00 ; frame=18 A=0 L=0
.byte $ED ; frame=18 B=29 L=2
; A: 24
.byte $04 ; frame=20 A=0 L=2
; A: 12
.byte $14 ; frame=22 A=2 L=2
; A: 12
.byte $04 ; frame=24 A=0 L=2
; A: 12
.byte $04 ; frame=26 A=0 L=2
; A: 24
.byte $04 ; frame=28 A=0 L=2
; A: 12
.byte $14 ; frame=30 A=2 L=2
; A: 15
; B: 51
.byte $04 ; frame=32 A=0 L=2
; A: 15
.byte $38 ; frame=34 A=7 L=0
.byte $BD ; frame=34 B=23 L=2
; A: 27
.byte $3C ; frame=36 A=7 L=2
; A: 15
.byte $9C ; frame=38 A=19 L=2
; A: 17
; B: 48
.byte $3C ; frame=40 A=7 L=2
; A: 17
; B: 51
.byte $40 ; frame=42 A=8 L=0
.byte $CD ; frame=42 B=25 L=2
; A: 29
; B: 53
.byte $40 ; frame=44 A=8 L=0
.byte $BD ; frame=44 B=23 L=2
; A: 17
; B: 58
.byte $90 ; frame=46 A=18 L=0
.byte $85 ; frame=46 B=16 L=2
; A: 12
; B: 55
.byte $40 ; frame=48 A=8 L=0
.byte $4D ; frame=48 B=9 L=2
; A: 12
.byte $00 ; frame=50 A=0 L=0
.byte $0D ; frame=50 B=1 L=2
; A: 24
.byte $04 ; frame=52 A=0 L=2
; A: 12
.byte $14 ; frame=54 A=2 L=2
; A: 12
.byte $04 ; frame=56 A=0 L=2
; A: 12
.byte $04 ; frame=58 A=0 L=2
; A: 24
.byte $04 ; frame=60 A=0 L=2
; A: 12
.byte $14 ; frame=62 A=2 L=2
; last: a=0 b=-1 len=2
.byte $04 ; frame=64 A=0 L=2
.byte $ff
track4:
; A: 12
; A: 12
.byte $04 ; frame=2 A=0 L=2
; A: 24
.byte $04 ; frame=4 A=0 L=2
; A: 12
.byte $14 ; frame=6 A=2 L=2
; A: 10
.byte $04 ; frame=8 A=0 L=2
; A: 12
.byte $24 ; frame=10 A=4 L=2
; A: 15
.byte $04 ; frame=12 A=0 L=2
; A: 17
.byte $3C ; frame=14 A=7 L=2
; A: 10
.byte $44 ; frame=16 A=8 L=2
; A: 10
.byte $24 ; frame=18 A=4 L=2
; A: 22
.byte $24 ; frame=20 A=4 L=2
; A: 10
.byte $54 ; frame=22 A=10 L=2
; A: 8
.byte $24 ; frame=24 A=4 L=2
; A: 7
.byte $64 ; frame=26 A=12 L=2
; A: 5
.byte $6C ; frame=28 A=13 L=2
; A: 3
.byte $74 ; frame=30 A=14 L=2
; A: 12
.byte $7C ; frame=32 A=15 L=2
; A: 12
.byte $04 ; frame=34 A=0 L=2
; A: 24
.byte $04 ; frame=36 A=0 L=2
; A: 12
.byte $14 ; frame=38 A=2 L=2
; A: 10
.byte $04 ; frame=40 A=0 L=2
; A: 12
.byte $24 ; frame=42 A=4 L=2
; A: 15
.byte $04 ; frame=44 A=0 L=2
; A: 17
.byte $3C ; frame=46 A=7 L=2
; A: 17
.byte $44 ; frame=48 A=8 L=2
; A: 15
.byte $46 ; frame=52 A=8 L=3
; A: 12
.byte $3E ; frame=56 A=7 L=3
; B: 51
.byte $06 ; frame=60 A=0 L=3
; B: 53
.byte $BD ; frame=62 B=23 L=2
; last: a=-1 b=16 len=2
.byte $85 ; frame=64 B=16 L=2
.byte $FF ; end

View File

@ -0,0 +1,21 @@
init_addresses:
.byte <MOCK_6522_DDRB1,<MOCK_6522_DDRA1 ; set the data direction for all pins of PortA/PortB to be output
.byte <MOCK_6522_ACR,<MOCK_6522_IER ; Continuous interrupts, clear all interrupts
.byte <MOCK_6522_IFR,<MOCK_6522_IER ; enable interrupt on timer overflow
.byte <MOCK_6522_T1CL,<MOCK_6522_T1CH ; set oflow value, start counting
.byte <MOCK_6522_ORB1,<MOCK_6522_ORB1 ; reset ay-3-8910
; note, terminated by the $ff below
init_values:
.byte $ff,$ff ; set the data direction for all pins of PortA/PortB to be output
.byte $40,$7f
.byte $C0,$C0
.byte $e7,$4f ; 50Hz
.byte MOCK_AY_RESET,MOCK_AY_INACTIVE
; c7ce / 1.023e6 = .050s, 20Hz
; 9c40 / 1.023e6 = .040s, 25Hz
; 4fe7 / 1.023e6 = .020s, 50Hz
; 411a / 1.023e6 = .016s, 60Hz

View File

@ -0,0 +1,120 @@
; Mockingboad programming:
; + Has two 6522 I/O chips connected to two AY-3-8910 chips
; + Optionally has some speech chips controlled via the outport on the AY
; + Often in slot 4
; TODO: how to auto-detect?
; References used:
; http://macgui.com/usenet/?group=2&id=8366
; 6522 Data Sheet
; AY-3-8910 Data Sheet
;========================
; Mockingboard card
; Essentially two 6522s hooked to the Apple II bus
; Connected to AY-3-8910 chips
; PA0-PA7 on 6522 connected to DA0-DA7 on AY
; PB0 on 6522 connected to BC1
; PB1 on 6522 connected to BDIR
; PB2 on 6522 connected to RESET
; left speaker
MOCK_6522_ORB1 = $C400 ; 6522 #1 port b data
MOCK_6522_ORA1 = $C401 ; 6522 #1 port a data
MOCK_6522_DDRB1 = $C402 ; 6522 #1 data direction port B
MOCK_6522_DDRA1 = $C403 ; 6522 #1 data direction port A
MOCK_6522_T1CL = $C404 ; 6522 #1 t1 low order latches
MOCK_6522_T1CH = $C405 ; 6522 #1 t1 high order counter
MOCK_6522_T1LL = $C406 ; 6522 #1 t1 low order latches
MOCK_6522_T1LH = $C407 ; 6522 #1 t1 high order latches
MOCK_6522_T2CL = $C408 ; 6522 #1 t2 low order latches
MOCK_6522_T2CH = $C409 ; 6522 #1 t2 high order counters
MOCK_6522_SR = $C40A ; 6522 #1 shift register
MOCK_6522_ACR = $C40B ; 6522 #1 auxilliary control register
MOCK_6522_PCR = $C40C ; 6522 #1 peripheral control register
MOCK_6522_IFR = $C40D ; 6522 #1 interrupt flag register
MOCK_6522_IER = $C40E ; 6522 #1 interrupt enable register
MOCK_6522_ORANH = $C40F ; 6522 #1 port a data no handshake
; right speaker
MOCK_6522_ORB2 = $C480 ; 6522 #2 port b data
MOCK_6522_ORA2 = $C481 ; 6522 #2 port a data
MOCK_6522_DDRB2 = $C482 ; 6522 #2 data direction port B
MOCK_6522_DDRA2 = $C483 ; 6522 #2 data direction port A
; AY-3-8910 commands on port B
; RESET BDIR BC1
MOCK_AY_RESET = $0 ; 0 0 0
MOCK_AY_INACTIVE = $4 ; 1 0 0
MOCK_AY_READ = $5 ; 1 0 1
MOCK_AY_WRITE = $6 ; 1 1 0
MOCK_AY_LATCH_ADDR = $7 ; 1 1 1
;========================
;========================
; Mockingboard Init
;========================
;========================
; Left channel only
mockingboard_init:
;=========================
; Initialize the 6522s
; Reset Left AY-3-8910
;===========================
; ldx #$FF
; stx MOCK_6522_DDRB1
; stx MOCK_6522_DDRA1
; inx ; #MOCK_AY_RESET $0
; stx MOCK_6522_ORB1
; ldx #MOCK_AY_INACTIVE ; $4
; stx MOCK_6522_ORB1
; sei ; disable interrupts, is this necessary?
;=========================
; Setup Interrupt Handler
;=========================
; NOTE: we don't support IIc as it's a hack
; traditionally Mockingboard on IIc was rare
;=========================
; Initialize the 6522s
; Reset Left AY-3-8910
;===========================
; entries=10
; 14 + 2*entries = 34 bytes
; assume Y=0 on entry?
; ldy #0 ; 2
init_it_loop:
lda init_values,Y ; 3
ldx init_addresses,Y ; 3
bmi doneit ; 2
iny ; 1
sta $c400,X ; 3
bne init_it_loop ; 2
doneit:
;========================
; set up interrupt
; Vector address goes to 0x3fe/0x3ff
lda #<interrupt_handler ; 2
sta $03fe ; 3
lda #>interrupt_handler ; 2
sta $03ff ; 3
;=========
; 10

View File

@ -0,0 +1,161 @@
play_frame:
;============================
; see if still counting down
lda SONG_COUNTDOWN
bpl done_update_song
set_notes_loop:
;==================
; load next byte
; ldy SONG_OFFSET ; Y = offset into song
track_smc:
lda track4;,Y ; get next byte into A
;==================
; see if hit end
cmp #$ff ; FF means we hit end
bne not_end
;====================================
; if at end, loop back to beginning
; ldy WHICH_TRACK ; get current track in Y
; iny ; increment track
; cpy #5 ; see if off end
; bne no_wrap
ldy #1 ; loop to track 1
no_wrap:
sty WHICH_TRACK
lda tracks_l,Y ; self-modify track
sta track_smc+1
; lda tracks_h,Y ; enforce in same page
; sta track_smc+2
lda bamps_l,Y ; self modify B-amplitude
sta bamp_smc+1
; lda bamps_h,Y ; enforce in same page
; sta bamp_smc+2
; lda #0 ; reset song offset
; sta SONG_OFFSET
jmp set_notes_loop ; bra ; try again in new track
not_end:
; NNNNNEEC -- c=channel, e=end, n=note
pha ; save note
and #1
asl
tax ; put channel offset*2 in X
pla ; restore note
pha
and #$6 ; get note length
lsr
tay
lda lengths,Y ; lookup in table
sta SONG_COUNTDOWN ;
pla
lsr
lsr
lsr ; get note in A
tay ; lookup in table
lda frequencies_high,Y ; get high frequency
sta AY_REGS+1,X ; put in AY register
lda frequencies_low,Y ; get low frequency
sta AY_REGS,X ; also put in AY register
;============================
; point to next
; assume less than 256 bytes
inc track_smc+1 ; SONG_OFFSET
done_update_song:
;=================================
; coundown song
dec SONG_COUNTDOWN ; if length was 0, means there
; was another note starting at same
; time, so go back and play that too
bmi set_notes_loop
;===============================
;===============================
; things that happen every frame
;===============================
;===============================
;=================================
; rotate through channel A volume
lda FRAME ; repeating 8-long pattern
and #$7
tay
lda channel_a_volume,Y
sta AY_REGS+8 ; A volume
;=================================
; handle channel B volume
chanb:
; lda FRAME
; and #$7
tya
bne bamps_skip
lda BAMP_COUNTDOWN ; b-amp conutdown
bne bamps_good
bamp_smc:
lda bamps4 ; get new value
pha
and #$f ; bottom 4 its is ampllitude
sta AY_REGS+9 ; B volume
pla
lsr ; top 4 bits are length
lsr
lsr
lsr
sta BAMP_COUNTDOWN
inc bamp_smc+1 ; increment to next location
; assumes on same page
; and less than 256
bamps_good:
dec BAMP_COUNTDOWN ; countdown
bamps_skip:
;=================================
; inc frame counter
inc FRAME

View File

@ -0,0 +1,15 @@
tracker_init:
; setup initial ay-3-8910 values (this depends on song)
; claer out $70-$90
init_registers_to_zero:
ldx #$20 ; init registers to zero
lda #0
init_loop:
sta AY_REGS,X
dex
bpl init_loop
lda #$38 ; ABC channels on
sta AY_REGS+7 ; $07 mixer

View File

@ -0,0 +1,42 @@
; zero page
; pre-defined applesoft vars
HGR_BITS = $1C
CH = $24
CV = $25
GBASL = $26
GBASH = $27
BASL = $28
BASH = $29
AY_REGS = $70
; through = $7D
FRAME = $80
BAMP_COUNTDOWN = $81
WHICH_TRACK = $82
SONG_COUNTDOWN = $83
OUR_ROT = $A5
HGR_X = $E0
HGR_XH = $E1
HGR_Y = $E2
HGR_COLOR = $E4
HGR_PAGE = $E6
HGR_SCALE = $E7
OUTL = $F4
OUTH = $F5
LINE = $F6
SAVE_Y = $F7
LETTER_X = $F8
LETTER_Y = $F9
COUNT = $FA
INL = $FD
INH = $FE
TEMP = $FF

View File

@ -0,0 +1,159 @@
; De-compressor for ZX02 files
; ----------------------------
;
; Decompress ZX02 data (6502 optimized format), optimized for speed and size
; 138 bytes code, 58.0 cycles/byte in test file.
;
; Compress with:
; zx02 input.bin output.zx0
;
; (c) 2022 DMSC
; Code under MIT license, see LICENSE file.
ZP=$80
offset = ZP+0
ZX0_src = ZP+2
ZX0_dst = ZP+4
bitr = ZP+6
pntr = ZP+7
; Initial values for offset, source, destination and bitr
;zx0_ini_block:
; .byte $00, $00, <comp_data, >comp_data, <out_addr, >out_addr, $80
;--------------------------------------------------
; Decompress ZX0 data (6502 optimized format)
zx02_full_decomp:
; Get initialization block
; ldy #7
;copy_init: lda zx0_ini_block-1, y
; sta offset-1, y
; dey
; bne copy_init
sta ZX0_dst+1 ; page to output to in A
zx_src_l:
ldy #$dd
sty ZX0_src
zx_src_h:
ldy #$dd
sty ZX0_src+1
ldy #$80
sty bitr
ldy #0
sty offset
sty offset+1
sty ZX0_dst ; always on even page
; Decode literal: Ccopy next N bytes from compressed file
; Elias(length) byte[1] byte[2] ... byte[N]
decode_literal:
jsr get_elias
cop0: lda (ZX0_src), y
inc ZX0_src
bne plus1
inc ZX0_src+1
plus1: sta (ZX0_dst),y
inc ZX0_dst
bne plus2
inc ZX0_dst+1
plus2: dex
bne cop0
asl bitr
bcs dzx0s_new_offset
; Copy from last offset (repeat N bytes from last offset)
; Elias(length)
jsr get_elias
dzx0s_copy:
lda ZX0_dst
sbc offset ; C=0 from get_elias
sta pntr
lda ZX0_dst+1
sbc offset+1
sta pntr+1
cop1:
lda (pntr), y
inc pntr
bne plus3
inc pntr+1
plus3: sta (ZX0_dst),y
inc ZX0_dst
bne plus4
inc ZX0_dst+1
plus4: dex
bne cop1
asl bitr
bcc decode_literal
; Copy from new offset (repeat N bytes from new offset)
; Elias(MSB(offset)) LSB(offset) Elias(length-1)
dzx0s_new_offset:
; Read elias code for high part of offset
jsr get_elias
beq exit ; Read a 0, signals the end
; Decrease and divide by 2
dex
txa
lsr ; @
sta offset+1
; Get low part of offset, a literal 7 bits
lda (ZX0_src), y
inc ZX0_src
bne plus5
inc ZX0_src+1
plus5:
; Divide by 2
ror ; @
sta offset
; And get the copy length.
; Start elias reading with the bit already in carry:
ldx #1
jsr elias_skip1
inx
bcc dzx0s_copy
; Read an elias-gamma interlaced code.
; ------------------------------------
get_elias:
; Initialize return value to #1
ldx #1
bne elias_start
elias_get: ; Read next data bit to result
asl bitr
rol ; @
tax
elias_start:
; Get one bit
asl bitr
bne elias_skip1
; Read new bit from stream
lda (ZX0_src), y
inc ZX0_src
bne plus6
inc ZX0_src+1
plus6: ;sec ; not needed, C=1 guaranteed from last bit
rol ;@
sta bitr
elias_skip1:
txa
bcs elias_get
; Got ending bit, stop reading
exit:
rts