lovebyte: making progress

This commit is contained in:
Vince Weaver 2024-02-04 01:03:17 -05:00
parent 6364166744
commit e35ca28dea
22 changed files with 1930 additions and 2 deletions

View File

@ -0,0 +1,49 @@
include ../../../Makefile.inc
DOS33 = ../../../utils/dos33fs-utils/dos33
TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft
EMPTYDISK = ../../../empty_disk/empty.dsk
LINKERSCRIPTS = ../../../linker_scripts/
all: xcircle.dsk
xcircle.dsk: HELLO XCIRCLE
cp $(EMPTYDISK) xcircle.dsk
$(DOS33) -y xcircle.dsk SAVE A HELLO
$(DOS33) -y xcircle.dsk BSAVE -a 0xc00 XCIRCLE
###
submit: xcircle.zip
xcircle.zip: XCIRCLE xcircle.s file_id.diz xcircle.dsk
mkdir -p lovebyte2023_xcircle
cp XCIRCLE ./lovebyte2023_xcircle
cp xcircle.s ./lovebyte2023_xcircle
cp file_id.diz ./lovebyte2023_xcircle
cp xcircle.dsk ./lovebyte2023_xcircle
cp monitor.txt ./lovebyte2023_xcircle
cp xcircle_screen.png ./lovebyte2023_xcircle
cp xcircle_720p.mp4 ./lovebyte2023_xcircle
zip -r xcircle.zip lovebyte2023_xcircle
####
####
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
###
XCIRCLE: xcircle.o
ld65 -o XCIRCLE xcircle.o -C $(LINKERSCRIPTS)/apple2_c00.inc
xcircle.o: xcircle.s
ca65 -o xcircle.o xcircle.s -l xcircle.lst
####
clean:
rm -f *~ *.o *.lst HELLO XCIRCLE *.zip

View File

@ -0,0 +1,7 @@
5 HOME
10 PRINT " XCIRCLE"
20 PRINT CHR$(4)"CATALOG"
25 PRINT:PRINT "PRESS ANY KEY TO 'BRUN XCIRCLE'"
30 GET A$
35 PRINT
40 PRINT CHR$(4)"BRUN XCIRCLE"

View File

@ -0,0 +1,57 @@
; Xcircle
; draws a circle pattern
; by Vince `deater` Weaver / DsR
; zero page locations
GBASL = $26
GBASH = $27
HGR_SCALE = $E7
HGR_ROTATION = $F9
; ROM locations
HGR2 = $F3D8
HPOSN = $F411
XDRAW0 = $F65D
XDRAW1 = $F661
HPLOT0 = $F457
xcircle:
lda #$20
sta HGR_SCALE
sta HGR_ROTATION
jsr HGR2 ; Hi-res, full screen ; 3
; Y=0, A=0 after this call
; A and Y are 0 here.
; X is left behind by the boot process?
tiny_loop:
ldy #0
ldx #140
lda #96
jsr HPOSN ; set screen position to X= (y,x) Y=(a)
; saves X,Y,A to zero page
; after Y= orig X/7
; A and X are ??
;tiny_loop:
ldx #<our_shape ; load $E2 into A, X, and Y
ldy #>our_shape ; our shape table is in ROM at $E2E2
inc HGR_ROTATION
lda HGR_ROTATION
jsr XDRAW0 ; XDRAW 1 AT X,Y
; Both A and X are 0 at exit
; Z flag set on exit
; Y varies
beq tiny_loop ; bra
our_shape = $E2E2
;our_shape:
;.byte $1a,$2d,$00

View File

@ -0,0 +1,49 @@
include ../../../Makefile.inc
DOS33 = ../../../utils/dos33fs-utils/dos33
TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft
EMPTYDISK = ../../../empty_disk/empty.dsk
LINKERSCRIPTS = ../../../linker_scripts/
all: gcircle.dsk
gcircle.dsk: HELLO GCIRCLE
cp $(EMPTYDISK) gcircle.dsk
$(DOS33) -y gcircle.dsk SAVE A HELLO
$(DOS33) -y gcircle.dsk BSAVE -a 0xc00 GCIRCLE
###
submit: gcircle.zip
gcircle.zip: GCIRCLE gcircle.s file_id.diz gcircle.dsk
mkdir -p lovebyte2023_gcircle
cp GCIRCLE ./lovebyte2023_gcircle
cp gcircle.s ./lovebyte2023_gcircle
cp file_id.diz ./lovebyte2023_gcircle
cp gcircle.dsk ./lovebyte2023_gcircle
cp monitor.txt ./lovebyte2023_gcircle
cp gcircle_screen.png ./lovebyte2023_gcircle
cp gcircle_720p.mp4 ./lovebyte2023_gcircle
zip -r gcircle.zip lovebyte2023_gcircle
####
####
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
###
GCIRCLE: gcircle.o
ld65 -o GCIRCLE gcircle.o -C $(LINKERSCRIPTS)/apple2_c00.inc
gcircle.o: gcircle.s
ca65 -o gcircle.o gcircle.s -l gcircle.lst
####
clean:
rm -f *~ *.o *.lst HELLO GCIRCLE *.zip

View File

@ -0,0 +1,63 @@
; Xdraw test
; use to prototype small xdraw effects
; by Vince `deater` Weaver / DsR
; zero page locations
GBASL = $26
GBASH = $27
HGR_SCALE = $E7
HGR_ROTATION = $F9
; ROM locations
HGR2 = $F3D8
HPOSN = $F411
XDRAW0 = $F65D
XDRAW1 = $F661
HPLOT0 = $F457
xdraw_test:
lda #$1
sta HGR_SCALE
sta HGR_ROTATION
jsr HGR2 ; Hi-res, full screen ; 3
; Y=0, A=0 after this call
; A and Y are 0 here.
; X is left behind by the boot process?
tiny_loop:
ldy #0
ldx #140
lda #96
jsr HPOSN ; set screen position to X= (y,x) Y=(a)
; saves X,Y,A to zero page
; after Y= orig X/7
; A and X are ??
ldx #<our_shape ; load $E2 into A, X, and Y
ldy #>our_shape ; our shape table is in ROM at $E2E2
inc HGR_ROTATION
lda HGR_ROTATION
; and #$7f
bne skip
inc HGR_SCALE
skip:
jsr XDRAW0 ; XDRAW 1 AT X,Y
; Both A and X are 0 at exit
; Z flag set on exit
; Y varies
beq tiny_loop ; bra
our_shape = $E2E0
;our_shape:
;.byte $1a,$2d,$00

View File

@ -0,0 +1,7 @@
5 HOME
10 PRINT " GCIRCLE"
20 PRINT CHR$(4)"CATALOG"
25 PRINT:PRINT "PRESS ANY KEY TO 'BRUN GCIRCLE'"
30 GET A$
35 PRINT
40 PRINT CHR$(4)"BRUN GCIRCLE"

View File

@ -0,0 +1,49 @@
include ../../../Makefile.inc
DOS33 = ../../../utils/dos33fs-utils/dos33
TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft
EMPTYDISK = ../../../empty_disk/empty.dsk
LINKERSCRIPTS = ../../../linker_scripts/
all: rainbow_squares.dsk
rainbow_squares.dsk: HELLO RAINBOW_SQUARES
cp $(EMPTYDISK) rainbow_squares.dsk
$(DOS33) -y rainbow_squares.dsk SAVE A HELLO
$(DOS33) -y rainbow_squares.dsk BSAVE -a 0xc00 RAINBOW_SQUARES
###
submit: rainbow_squares.zip
rainbow_squares.zip: RAINBOW_SQUARES rainbow_squares.s file_id.diz rainbow_squares.dsk
mkdir -p lovebyte2023_rainbow_squares
cp RAINBOW_SQUARES ./lovebyte2023_rainbow_squares
cp rainbow_squares.s ./lovebyte2023_rainbow_squares
cp file_id.diz ./lovebyte2023_rainbow_squares
cp rainbow_squares.dsk ./lovebyte2023_rainbow_squares
cp monitor.txt ./lovebyte2023_rainbow_squares
cp rainbow_squares_screen.png ./lovebyte2023_rainbow_squares
cp rainbow_squares_720p.mp4 ./lovebyte2023_rainbow_squares
zip -r rainbow_squares.zip lovebyte2023_rainbow_squares
####
####
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
###
RAINBOW_SQUARES: rainbow_squares.o
ld65 -o RAINBOW_SQUARES rainbow_squares.o -C $(LINKERSCRIPTS)/apple2_c00.inc
rainbow_squares.o: rainbow_squares.s
ca65 -o rainbow_squares.o rainbow_squares.s -l rainbow_squares.lst
####
clean:
rm -f *~ *.o *.lst HELLO RAINBOW_SQUARES *.zip

View File

@ -0,0 +1,7 @@
5 HOME
10 PRINT " RAINBOW_SQUARES"
20 PRINT CHR$(4)"CATALOG"
25 PRINT:PRINT "PRESS ANY KEY TO 'BRUN RAINBOW_SQUARES'"
30 GET A$
35 PRINT
40 PRINT CHR$(4)"BRUN RAINBOW_SQUARES"

View File

@ -0,0 +1,222 @@
; this was a weird effect that turns out to be because we're linking
; at the wrong address so it's just the effect when
; TL/TH holds the values $A0 $A0
; sierpinski-like demo
; based on the code from Hellmood's Memories demo
; by Vince `deater` Weaver <vince@deater.net>
; the simple sierpinski you more or less just plot
; X AND Y
; Hellmood's you plot something more or less like
; COLOR = ( (Y-(X*T)) & (X+(Y*T) ) & 0xf0
; where T is an incrementing frame value
; to get speed on 6502/Apple II we change the multiplies to
; a series of 16-bit 8.8 fixed point adds
; TODO:
; HPLOT timing
; MOVERIGHT timing
; MOVERIGHT MOVEDOWN timing
; LOOKUP TABLE timing
; zero page
HGR_BITS = $1C
GBASH = $27
MASK = $2E
COLOR = $30
HGR_X = $E0
HGR_Y = $E2
HGR_COLOR = $E4
;XX = $F7
XX_TH = $F8
XX_TL = $F9
;YY = $FA
YY_TH = $FB
YY_TL = $FC
;T_L = $FD
;T_H = $FE
SAVED = $FF
; Soft switches
FULLGR = $C052
PAGE1 = $C054
PAGE2 = $C055
LORES = $C056 ; Enable LORES graphics
; ROM routines
HGR = $F3E2
HGR2 = $F3D8
HPLOT0 = $F457
PLOT1 = $F80E ;; PLOT at (GBASL),Y (need MASK to be $0f or $f0)
GBASCALC= $F847 ;; take Y-coord/2 in A, put address in GBASL/H ( a trashed, C clear)
SETGR = $FB40
;.zeropage
;h.globalzp T_L,T_H
;================================
; Clear screen and setup graphics
;================================
sier:
jsr HGR2 ; set FULLGR, sets A=0
; lda #$5b ; start with multiplier 0
; sta T_L
; lda #$41 ; start with multiplier 0
; sta T_H
sier_outer:
ldy #0 ; YY starts at 0
sty YY_TL
sty YY_TH
sier_yloop:
; calc YY_T (8.8 fixed point add)
; save space by skipping clc as it's only a slight variation w/o
; clc
lda YY_TL
adc T_L
sta YY_TL
lda YY_TH
adc T_H
sta YY_TH
; txa ; YY ; plot call needs Y/2
; lsr
; php
; bcc even_mask
; ldy #$f0
; .byte $2C ; bit hack
;even_mask:
; ldy #$0f
; sty MASK
; jsr GBASCALC ; take Y-coord/2 in A, put address in GBASL/H ( a trashed, C clear)
; lda GBASH
;draw_page_smc:
; adc #0
; sta GBASH ; adjust for PAGE1/PAGE2 ($400/$800)
; plp
; jsr $f806 ; trick to calculate MASK by jumping
; into middle of PLOT routine
; reset XX to 0
ldx #0 ; XX
stx XX_TL
stx XX_TH
sier_xloop:
; want (YY-(XX*T)) & (XX+(YY*T)
; SAVED = XX+(Y*T)
; clc
txa ; XX
adc YY_TH
sta SAVED
; calc XX*T
; clc
lda XX_TL
adc T_L
sta XX_TL
lda XX_TH
adc T_H
sta XX_TH
; calc (YY-X_T)
tya ; lda YY
sec
sbc XX_TH
; want (YY-(XX*T)) & (XX+(YY*T)
and SAVED
and #$f0
beq white
black:
lda #00 ; black
.byte $2C ; bit trick
white:
lda #$ff ; green
sta HGR_COLOR
tya ; YY in A
ldy #0
; XX in X
jsr HPLOT0 ; plot at (Y,X), (A)
; at begin, stores A to HGR_Y
; X to HGR_X and Y to HGR_X+1
; destroys X,Y,A
; Y is XX/7
ldy HGR_Y
ldx HGR_X
inx ; XX
cpx #255
bne sier_xloop
iny ; YY
cpy #192
bne sier_yloop
; inc T
; clc
lda T_L
blah_smc:
adc #1
sta T_L
bcc no_carry
inc T_H
no_carry:
; speed up the zoom as it goes
; inc blah_smc+1
; x is 48
;flip_pages:
; lda draw_page_smc+1 ; DRAW_PAGE
; beq done_page
; inx
;done_page:
; X=48 ($30) PAGE1=$C054-$30=$C024
; ldy $C024,X ; set display page to PAGE1 or PAGE2
; eor #$4 ; flip draw page between $400/$800
; sta draw_page_smc+1 ; DRAW_PAGE
jmp sier_outer ; what can we branch on?
T_L: .byte $A0
T_H: .byte $A0

View File

@ -10,7 +10,7 @@ all: circles.dsk
circles.dsk: HELLO CIRCLES CIRCLES_FILL ARCS WEB PAC ORB ORB_TINY \
BRES.BAS BRESBOT.BAS BRESCOOL.BAS HORROR \
MID.BAS MIDBOT.BAS MIDCOOL.BAS BRESTEST.BAS ARCS_BOT \
TUNNEL WEB2
TUNNEL SQUARES WEB2
cp $(EMPTY_DISK)/empty.dsk circles.dsk
$(DOS33) -y circles.dsk SAVE A HELLO
$(DOS33) -y circles.dsk SAVE A BRES.BAS
@ -30,6 +30,7 @@ circles.dsk: HELLO CIRCLES CIRCLES_FILL ARCS WEB PAC ORB ORB_TINY \
$(DOS33) -y circles.dsk BSAVE -a 0x03f5 HORROR
$(DOS33) -y circles.dsk BSAVE -a 0x9600 ARCS_BOT
$(DOS33) -y circles.dsk BSAVE -a 0x0C00 TUNNEL
$(DOS33) -y circles.dsk BSAVE -a 0x0C00 SQUARES
$(DOS33) -y circles.dsk BSAVE -a 0x0C00 WEB2
###
@ -92,6 +93,15 @@ tunnel.o: tunnel.s
###
SQUARES: squares.o
ld65 -o SQUARES squares.o -C $(LINKER_SCRIPTS)/apple2_c00.inc
squares.o: squares.s
ca65 -o squares.o squares.s -l squares.lst
###
WEB2: web2.o
ld65 -o WEB2 web2.o -C $(LINKER_SCRIPTS)/apple2_c00.inc
@ -169,4 +179,5 @@ horror.o: horror.s
clean:
rm -f *~ *.o *.lst CIRCLES ARCS WEB CIRCLES_FILL PAC ORB \
BRES.BAS BRESBOT.BAS BRESCOOL.BAS BRESTEST.BAS \
MID.BAS MIDBOT.BAS MIDCOOL.BAS ORB_TINY HORROR TUNNEL WEB2
MID.BAS MIDBOT.BAS MIDCOOL.BAS ORB_TINY HORROR TUNNEL \
SQUARES WEB2

View File

@ -0,0 +1,57 @@
include ../../Makefile.inc
DOS33 = ../../utils/dos33fs-utils/dos33
EMPTY_DISK = ../../empty_disk
HGR2PNG = ../../utils/hgr-utils/png2hgr
LINKER_SCRIPTS = ../../linker_scripts
TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft
all: hgr_d2.dsk text_to_tiny
submit: hgr_d2_1k.zip
####
hgr_d2.dsk: HELLO D4
cp $(EMPTY_DISK)/empty.dsk ./hgr_d2.dsk
$(DOS33) -y hgr_d2.dsk SAVE A HELLO
$(DOS33) -y hgr_d2.dsk -t BIN -a 0x6000 BSAVE D4
####
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
####
mA2E_4.s: mA2E_4.txt text_to_tiny
./text_to_tiny mA2E_4.txt > mA2E_4.s
####
D4: d4.o
ld65 -o D4 d4.o -C $(LINKER_SCRIPTS)/apple2_6000.inc
d4.o: d4.s \
zp.inc hardware.inc \
mA2E_4.s \
mockingboard_init.s play_frame.s \
tracker_init.s ay3_write_regs.s interrupt_handler.s \
mockingboard_constants.s
ca65 -o d4.o d4.s -l d4.lst
####
text_to_tiny: text_to_tiny.o
$(CC) -o text_to_tiny text_to_tiny.o -lm
text_to_tiny.o: text_to_tiny.c
$(CC) $(CFLAGS) -c text_to_tiny.c
####
clean:
rm -f *~ *.o *.lst D4 HELLO text_to_tiny mA2E_2.s mA2E_3.s mA2E_4.s

View File

@ -0,0 +1,38 @@
mockingboard_init.s
assume slot #4
only one channel
sets up interrupt handler
tracker_init.s
clear mirror registers in ZP to 0
($70-$83?)
if any register always same, set it ($38 to mixer?)
play_frame.s
has amplitudes to rotate through on A/B channel
; NNNNEEEC -- c=channel, e=end, n=note
; 16 notes, 8 lengths, 2 channels
2024 Maze 02
Volumes:
Track0
A: D.C.A.9 if 4/8 long
D9 if 2 long
B: 9.5.4.3 if 4/8 long
95 if 2 long
Track1:
A: D.C.A.9 if 4/8 long
D9 if 2 long
B: Either all F or
F.C.B.A if 4/8 long
FB if 2 long

View File

@ -0,0 +1,6 @@
5 HOME
10 PRINT "TEST MUSIC FOR LOVEBYTE 2024"
20 PRINT CHR$(4);"CATALOG"
25 PRINT:PRINT "AUTOMATICALLY STARTING"
30 PRINT "]BRUN D2"

View File

@ -0,0 +1,68 @@
;================================
;================================
; 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,147 @@
'' TITLE: Mockingboard Tune 2 - 2024
' AUTHOR: mA2E / dSr
' COMMENTS:
'
' LOOP: 640
'
' BPM: 250
' TEMPO: 6
' FREQ: 1000000
' IRQ: 50
'
' LYRICS: 0
'
' ENDHEADER
-------
' 0
track0:
0 A 5-- ----- -----
1 ----- ----- -----
2 ----- A 5-- -----
3 ----- ----- -----
4 C 6-- ----- -----
5 ----- ----- -----
6 ----- C 6-- -----
7 ----- ----- -----
8 F 5-- ----- -----
9 ----- ----- -----
A ----- F 5-- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 G 5-- ----- -----
11 ----- ----- -----
12 ----- G 5-- -----
13 ----- ----- -----
14 E 5-- ----- -----
15 ----- ----- -----
16 D 5-- E 5-- -----
17 ----- ----- -----
18 A 5-- D 5-- -----
19 ----- ----- -----
1A ----- A 5-- -----
1B ----- ----- -----
1C E 5-- ----- -----
1D ----- ----- -----
1E ----- E 5-- -----
1F ----- ----- -----
20 A 5-- ----- -----
21 ----- ----- -----
22 ----- A 5-- -----
23 ----- ----- -----
24 C 6-- ----- -----
25 ----- ----- -----
26 ----- C 6-- -----
27 ----- ----- -----
28 F 5-- ----- -----
29 ----- ----- -----
2A ----- F 5-- -----
2B ----- ----- -----
2C ----- ----- -----
2D ----- ----- -----
2E ----- ----- -----
2F ----- ----- -----
30 G 5-- ----- -----
31 ----- ----- -----
32 ----- G 5-- -----
33 ----- ----- -----
34 E 5-- ----- -----
35 ----- ----- -----
36 D 5-- E 5-- -----
37 ----- ----- -----
38 A 4-- D 5-- -----
39 ----- ----- -----
3A ----- A 4-- -----
3B ----- ----- -----
3C E 4-- ----- -----
3D ----- ----- -----
3E ----- E 4-- -----
3F ----- ----- -----
' 1
track1:
0 A 5-- A 4-- -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 C 6-- A 4-- -----
5 ----- ----- -----
6 ----- B 4-- -----
7 ----- ----- -----
8 F 5-- C 5-- -----
9 ----- ----- -----
A ----- A 4-- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- D 5-- -----
F ----- ----- -----
10 G 5-- ----- -----
11 ----- ----- -----
12 ----- D 5-- -----
13 ----- ----- -----
14 E 5-- C 5-- -----
15 ----- ----- -----
16 D 5-- B 4-- -----
17 ----- ----- -----
18 A 5-- C 5-- -----
19 ----- ----- -----
1A ----- A 4-- -----
1B ----- ----- -----
1C E 5-- ----- -----
1D ----- ----- -----
1E ----- ----- -----
1F ----- ----- -----
20 A 5-- A 4-- -----
21 ----- ----- -----
22 ----- ----- -----
23 ----- ----- -----
24 C 6-- A 4-- -----
25 ----- ----- -----
26 ----- B 4-- -----
27 ----- ----- -----
28 F 5-- C 5-- -----
29 ----- ----- -----
2A ----- A 4-- -----
2B ----- ----- -----
2C ----- ----- -----
2D ----- ----- -----
2E ----- A 4-- -----
2F ----- B 4-- -----
30 G 5-- D 5-- -----
31 ----- ----- -----
32 ----- D 5-- -----
33 ----- ----- -----
34 E 5-- C 5-- -----
35 ----- ----- -----
36 D 5-- B 4-- -----
37 ----- ----- -----
38 A 4-- A 4-- -----
39 ----- ----- -----
3A ----- ----- -----
3B ----- ----- -----
3C E 4-- ----- -----
3D ----- ----- -----
3E ----- ----- -----
3F ----- ----- -----

View File

@ -0,0 +1,149 @@
'' TITLE: Mockingboard Tune 2 - 2024
' AUTHOR: mA2E / dSr
' COMMENTS:
'
' LOOP: 640
'
' BPM: 250
' TEMPO: 6
' FREQ: 1000000
' IRQ: 50
'
' LYRICS: 0
'
' ENDHEADER
-------
' 0
track0:
0 A 1-- A 5-- -----
1 ----- ----- -----
2 A 2-- ----- A 5--
3 ----- ----- -----
4 F 1-- C 6-- -----
5 ----- ----- -----
6 F 2-- ----- C 6--
7 ----- ----- -----
8 D 1-- F 5-- -----
9 ----- ----- -----
A D 2-- ----- F 5--
B ----- ----- -----
C D 1-- ----- -----
D ----- ----- -----
E D 2-- ----- -----
F ----- ----- -----
10 G 1-- G 5-- -----
11 ----- ----- -----
12 G 2-- ----- G 5--
13 ----- ----- -----
14 E 1-- E 5-- -----
15 ----- ----- -----
16 G 1-- D 5-- E 5--
17 ----- ----- -----
18 A 1-- A 5-- D 5--
19 ----- ----- -----
1A A 2-- ----- A 5--
1B ----- ----- -----
1C A 1-- E 5-- -----
1D ----- ----- -----
1E A 2-- ----- E 5--
1F ----- ----- -----
20 A 1-- A 5-- -----
21 ----- ----- -----
22 A 2-- ----- A 5--
23 ----- ----- -----
24 F 1-- C 6-- -----
25 ----- ----- -----
26 F 2-- ----- C 6--
27 ----- ----- -----
28 D 1-- F 5-- -----
29 ----- ----- -----
2A D 2-- ----- F 5--
2B ----- ----- -----
2C D 1-- ----- -----
2D ----- ----- -----
2E D 2-- ----- -----
2F ----- ----- -----
30 G 1-- G 5-- -----
31 ----- ----- -----
32 G 2-- ----- G 5--
33 ----- ----- -----
34 E 1-- E 5-- -----
35 ----- ----- -----
36 G 1-- D 5-- E 5--
37 ----- ----- -----
38 A 1-- A 4-- D 5--
39 ----- ----- -----
3A A 2-- ----- A 4--
3B ----- ----- -----
3C A 1-- E 4-- -----
3D ----- ----- -----
3E A 2-- ----- E 4--
3F ----- ----- -----
' 1
track1:
0 A 1-- A 4-- A 5--
1 ----- ----- -----
2 A 2-- ----- -----
3 ----- ----- -----
4 F 1-- A 4-- C 6--
5 ----- ----- -----
6 F 2-- B 4-- -----
7 ----- ----- -----
8 D 1-- C 5-- F 5--
9 ----- ----- -----
A D 2-- A 4-- -----
B ----- ----- -----
C D 1-- ----- -----
D ----- ----- -----
E D 2-- D 5-- -----
F ----- ----- -----
10 G 1-- ----- G 5--
11 ----- ----- -----
12 G 2-- D 5-- -----
13 ----- ----- -----
14 E 1-- C 5-- E 5--
15 ----- ----- -----
16 G 1-- B 4-- D 5--
17 ----- ----- -----
18 A 1-- C 5-- A 5--
19 ----- ----- -----
1A A 2-- A 4-- -----
1B ----- ----- -----
1C A 1-- ----- E 5--
1D ----- ----- -----
1E A 2-- ----- -----
1F ----- ----- -----
20 A 1-- A 4-- A 5--
21 ----- ----- -----
22 A 2-- ----- -----
23 ----- ----- -----
24 F 1-- A 4-- C 6--
25 ----- ----- -----
26 F 2-- B 4-- -----
27 ----- ----- -----
28 D 1-- C 5-- F 5--
29 ----- ----- -----
2A D 2-- A 4-- -----
2B ----- ----- -----
2C D 1-- ----- -----
2D ----- ----- -----
2E D 2-- D 5-- G 5--
2F ----- ----- -----
30 G 1-- D 5-- -----
31 ----- ----- -----
32 G 2-- C 5-- -----
33 ----- ----- -----
34 E 1-- B 4-- E 5--
35 ----- ----- -----
36 G 1-- A 4-- D 5--
37 ----- ----- -----
38 A 1-- ----- A 3--
39 ----- ----- -----
3A A 2-- ----- -----
3B ----- ----- -----
3C A 1-- ----- E 4--
3D ----- ----- -----
3E A 2-- ----- -----
3F ----- ----- -----

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 ; c7ce / 1.023e6 = .050s, 20Hz
.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,119 @@
; 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
;========================
; set up interrupt
; Vector address goes to 0x3fe/0x3ff
; can save 10 bytes if we load in memory so this
; is in the right place automatically
lda #<interrupt_handler ; 2
sta $03fe ; 3
lda #>interrupt_handler ; 2
sta $03ff ; 3
;=========
; 10
;=========================
; 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:

View File

@ -0,0 +1,182 @@
play_frame:
;===============================
;===============================
; things that happen every frame
;===============================
;===============================
;========================================
; patch b channel volumes based on track
lda WHICH_TRACK
and #$2
bne switch_to_b1
lda #<channel_b0_volume
.byte $2C ; bit trick
switch_to_b1:
lda #<channel_b1_volume
sta chb_smc1+1
sta chb_smc2+1
;==============================
; countdown for the volumes
lda FRAME
and #$f
bne no_inc_countdowns
inc A_COUNTDOWN
inc B_COUNTDOWN
no_inc_countdowns:
;=================================
; inc frame counter
inc FRAME
;=================================
; rotate through channel A volume
ldy A_COUNTDOWN
lda channel_a_volume,Y
sta AY_REGS+8
;=================================
; rotate through channel B volume
ldy B_COUNTDOWN
chb_smc1:
lda channel_b0_volume,Y
sta AY_REGS+9
;============================
; see if still counting down
lda SONG_COUNTDOWN
bpl done_update_song
set_notes_loop:
;==================
; load next byte
ldy SONG_OFFSET
track_smc:
lda track0,Y
;==================
; see if hit end
cmp #$ff
bne not_end
;====================================
; if at end, loop back to beginning
inc WHICH_TRACK
ldy WHICH_TRACK
cpy #4 ; looping, hard coded
bne no_wrap
ldy #0
sty WHICH_TRACK
no_wrap:
lda tracks_l,Y
sta track_smc+1
lda tracks_h,Y
sta track_smc+2
lda #0
sta SONG_OFFSET
beq set_notes_loop ; bra
not_end:
; NNNNEEEC -- c=channel, e=end, n=note
pha ; save note
and #1
tax
bne start_b_note
; reset A countdown
start_a_note:
ldy channel_a_volume
bne done_start_note ; bra
start_b_note:
chb_smc2:
ldy channel_b0_volume
done_start_note:
; set initial note volume
sty AY_REGS+8,X ; $08 set volume A or B
; reset countdown
ldy #0
sty A_COUNTDOWN,X
asl
tax ; mul channel offset by 2 for later
; as frequency registers 2 wide
pla ; restore note
pha
and #$E ; get length
asl ; it's NNNNEEEC
asl ; we want EEE * 8
sta SONG_COUNTDOWN ;
pla
lsr
lsr
lsr ; get note in A
lsr
tay ; lookup in table
lda frequencies_high,Y
sta AY_REGS+1,X
lda frequencies_low,Y
sta AY_REGS,X ; set proper register value
; visualization
blah_urgh:
sta $400,Y
inc blah_urgh+1
;============================
; point to next
; assume less than 256 bytes
inc SONG_OFFSET
done_update_song:
dec SONG_COUNTDOWN
bmi set_notes_loop
bpl skip_data
channel_a_volume:
.byte $D,$C,$A,$9
channel_b0_volume:
.byte $9,$5,$4,$3
channel_b1_volume:
.byte $F,$C,$B,$A
tracks_l:
.byte <track0,<track0,<track1,<track1
tracks_h:
.byte >track0,>track0,>track1,>track1
skip_data:

View File

@ -0,0 +1,564 @@
/* make music for tiny_music player */
#define VERSION "1.0 (2024 Lovebyte)"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
static int octave_adjust=0;
static int notes_used[12*8];
static int allocated_notes[12*8];
static int notes_allocated=0;
static int total_len=0;
unsigned short frequencies[]={
//C C# D D# E F F# G G# A A# B
0x7A3,0x735,0x6CD,0x66C,0x60F,0x5B8,0x566,0x518,0x4CF,0x48A,0x449,0x40B, //1
0x3D1,0x39A,0x366,0x336,0x307,0x2DC,0x2B3,0x28C,0x267,0x245,0x224,0x205, //2
0x1E8,0x1CD,0x1B3,0x19B,0x183,0x16E,0x159,0x146,0x133,0x122,0x112,0x102, //3
0x0F4,0x0E6,0x0D9,0x0CD,0x0C1,0x0B7,0x0AC,0x0A3,0x099,0x091,0x089,0x081, //4
0x07A,0x073,0x06C,0x066,0x060,0x05B,0x056,0x051,0x04C,0x048,0x044,0x040, //5
0x03D,0x039,0x036,0x033,0x030,0x02D,0x02B,0x028,0x026,0x024,0x022,0x020, //6
//0x01E,0x01C,0x01B,0x019,0x018,0x016,0x015,0x014,0x013,0x012,0x011,0x010,
//0x00F,0x00E,0x00D,0x00C,0x00C,0x00B,0x00A,0x00A,0x009,0x009,0x008,0x008,
};
static char last_note[4]="A#2";
int note_to_ed(char note, int flat, int sharp, int octave) {
int offset;
switch(note) {
case 'C': offset=0; break;
case 'D': offset=2; break;
case 'E': offset=4; break;
case 'F': offset=5; break;
case 'G': offset=7; break;
case 'A': offset=9; break;
case 'B': offset=11; break;
case 'R': offset=12; flat=0; sharp=0; octave=3; break;
default:
fprintf(stderr,"Unknown note %c\n",note);
return -1;
}
if (flat==1) offset--;
if (sharp==1) offset++;
if (sharp==2) offset+=2;
last_note[0]=note;
if (sharp==1) last_note[1]='#';
else last_note[1]=' ';
last_note[2]=octave+'0';
offset=((((octave+octave_adjust)-1)&0x7)*12)+offset;
// offset=((((octave+octave_adjust)-3)&0x3)<<4)|offset;
return offset;
}
static int debug=0;
static int line=0;
static int header_version=0;
static int current_frame=0;
struct note_type {
unsigned char which;
unsigned char note;
int sharp,flat;
int octave;
int len;
int enabled;
int freq;
int length;
int left;
int ed_freq;
int offset;
};
static int allocate_note(int which) {
int i;
for(i=0;i<notes_allocated;i++) {
if (allocated_notes[i]==which) return i;
}
allocated_notes[notes_allocated]=which;
notes_allocated++;
return notes_allocated-1;
}
static int get_note(char *string, int sp, struct note_type *n, int line) {
int freq;
int ch;
// fprintf(stderr,"VMW: Entering, sp=%d\n",sp);
/* Skip white space */
while((string[sp]==' ' || string[sp]=='\t')) sp++;
if (string[sp]=='\n') return -1;
/* return early if no change */
ch=string[sp];
// fprintf(stderr,"VMW: %d %d\n",ch,sp);
if (ch=='-') {
if (header_version==0) return sp+6;
else {
return sp+11;
}
}
/* get note info */
n->sharp=0;
n->flat=0;
n->ed_freq=-1;
n->note=ch;
sp++;
if (string[sp]==' ') ;
else if (string[sp]=='#') n->sharp=1;
else if (string[sp]=='-') n->flat=1;
else if (string[sp]=='=') n->flat=2;
else {
fprintf(stderr,"Unknown note modifier %c, line %d:%d\n",
string[sp],line,sp);
fprintf(stderr,"String: %s\n",string);
}
// printf("Sharp=%d Flat=%d\n",n->sharp,n->flat);
sp++;
n->octave=string[sp]-'0';
sp++;
sp++;
n->len=string[sp]-'0';
sp++;
if (n->note!='-') {
freq=note_to_ed(n->note,n->flat,n->sharp,
n->octave);
if (freq<0) fprintf(stderr,"Bad note line %d\n",line);
n->enabled=1;
n->length=0;
n->ed_freq=freq;
}
if (header_version==2) sp+=6;
return sp;
}
static int get_string(char *string, char *key, char *output, int strip_linefeed) {
char *found;
found=strstr(string,key);
found=found+strlen(key);
/* get rid of leading whitespace */
while(1) {
if ((*found==' ') || (*found=='\t')) found++;
else break;
}
strcpy(output,found);
/* remove trailing linefeed */
if (strip_linefeed) output[strlen(output)-1]=0;
return 0;
}
static void print_help(int just_version, char *exec_name) {
printf("\ntext_to_ed version %s by Vince Weaver <vince@deater.net>\n\n",VERSION);
if (just_version) exit(0);
printf("This created Electric Duet files\n\n");
printf("Usage:\n");
printf("\t%s [-h] [-v] [-d] [-o X] [-i X] textfile outbase\n\n",
exec_name);
printf("\t-h: this help message\n");
printf("\t-v: version info\n");
printf("\t-d: print debug messages\n");
printf("\t-o: Offset octave by X\n");
printf("\t-i: set second instrument to X\n");
exit(0);
}
static int write_note(int *a_last,int *b_last,int *c_last,int total_len) {
// this version
// NNNNEEEC
// NNNNNEEC
unsigned char temp_value;
unsigned char length=0;
if (*a_last>=0) {
/* note is shifted left by 3, channel 0 */
temp_value=(*a_last<<4)|0;
/* if no note b, use the passed in length */
if ((*b_last<0) && (*c_last<0)) {
if (total_len>7) {
fprintf(stderr,"Warning: length too big %d\n",total_len);
}
length=(total_len<<1);
temp_value|=length;
}
printf("\t.byte $%02X ; frame=%d A=%d L=%d\n",
temp_value,
current_frame,
*a_last,length>>1);//(*b_last<0)||(*c_last<0));
// (total_len)++;
*a_last=-1;
}
if (*b_last>=0) {
/* note is shifted left by 3, channel 1 */
temp_value=(*b_last<<4)|1;
if (total_len>7) {
fprintf(stderr,"Warning: length too big %d\n",total_len);
}
length=(total_len<<1);
temp_value|=length;
if (*c_last>=0) {
// temp_value|=2;
fprintf(stderr,"Error, shouldn't have C\n");
}
printf("\t.byte $%02X ; frame=%d B=%d L=%d\n",
temp_value,
current_frame,
*b_last,length>>1);
// (total_len)++;
*b_last=-1;
}
if (*c_last>=0) {
fprintf(stderr,"Unsupported C!\n");
// printf("\t.byte $%02X ; C=%d L=%d\n",
// (unsigned char)(*c_last<<3)|4|2,
// *c_last,1);
// (total_len)++;
// *c_last=-1;
}
return 0;
}
int main(int argc, char **argv) {
char string[BUFSIZ];
char *result;
char *in_filename;
char temp[BUFSIZ];
FILE *in_file=NULL;
//int attributes=0;
int loop=0;
int sp,external_frequency,irq;
struct note_type a,b,c;
int copt;
int total_length=0;
char song_name[BUFSIZ];
char author_name[BUFSIZ];
char comments[BUFSIZ];
char *comments_ptr=comments;
// unsigned char sharp_char[]=" #-=";
/* Parse command line arguments */
while ((copt = getopt(argc, argv, "dhvo:i:"))!=-1) {
switch (copt) {
case 'd':
/* Debug messages */
printf("Debug enabled\n");
debug=1;
break;
case 'h':
/* help */
print_help(0,argv[0]);
break;
case 'v':
/* version */
print_help(1,argv[0]);
break;
case 'o':
/* octave offset */
octave_adjust=atoi(optarg);
break;
default:
print_help(0,argv[0]);
break;
}
}
if (argv[optind]!=NULL) {
/* Open the input file */
if (argv[optind][0]=='-') {
in_file=stdin;
}
else {
in_filename=strdup(argv[optind]);
in_file=fopen(in_filename,"r");
if (in_file==NULL) {
fprintf(stderr,"Couldn't open %s\n",in_filename);
return -1;
}
}
}
/* Get the info for the header */
while(1) {
result=fgets(string,BUFSIZ,in_file);
if (result==NULL) break;
line++;
if (strstr(string,"ENDHEADER")) break;
if (strstr(string,"HEADER:")) {
get_string(string,"HEADER:",temp,1);
header_version=atoi(temp);
printf("Found header version %d\n",header_version);
}
if (strstr(string,"TITLE:")) {
get_string(string,"TITLE:",song_name,1);
}
if (strstr(string,"AUTHOR:")) {
get_string(string,"AUTHOR:",author_name,1);
}
if (strstr(string,"COMMENTS:")) {
get_string(string,"COMMENTS:",comments_ptr,0);
comments_ptr=&comments[strlen(comments)];
}
if (strstr(string,"FREQ:")) {
get_string(string,"FREQ:",temp,1);
external_frequency=atoi(temp);
}
if (strstr(string,"IRQ:")) {
get_string(string,"IRQ:",temp,1);
irq=atoi(temp);
}
if (strstr(string,"LOOP:")) {
get_string(string,"LOOP:",temp,1);
loop=atoi(temp);
}
}
a.which='A'; b.which='B'; c.which='C';
// algorithm
// get A,B,C
// int first=1;
// int a_last=0,b_last=0,same_count=0;
// int a_len=0,b_len=0,a_freq=0,b_freq=0;
int current_length=0;
int first=1;
int a_last=-1,b_last=-1,c_last=-1;
printf("; Made with version %s\n",VERSION);
printf("peasant_song:\n");
printf("; register init\n");
//printf("\t.byte $00,$00,$00,$00,$00,$00 ; $00: A/B/C fine/coarse\n");
//printf("\t.byte $00 ; $06\n");
//printf("\t.byte $38 ; $07 mixer (ABC on)\n");
//printf("\t.byte $0E,$0C,$0C ; $08 volume A/B/C\n");
//printf("\t.byte $00,$00,$00,$00 ; $09\n");
printf("\n");
while(1) {
result=fgets(string,BUFSIZ,in_file);
if (result==NULL) break;
line++;
a.ed_freq=-1;
b.ed_freq=-1;
c.ed_freq=-1;
a.length=0;
b.length=0;
c.length=0;
/* skip comments */
if (string[0]=='\'') continue;
if (string[0]=='-') continue;
if (string[0]=='*') continue;
if (string[0]=='t') { /* track */
if (!first) {
printf("; last: a=%d b=%d len=%d\n",a_last,b_last,current_length);
write_note(&a_last,&b_last,&c_last,current_length);
printf(".byte $ff\n");
}
printf("%s\n",string);
total_length=0;
current_frame=0;
current_length=0;
continue;
}
sp=0;
/* Skip line number */
while((string[sp]!=' ' && string[sp]!='\t')) sp++;
sp=get_note(string,sp,&a,line);
if (sp!=-1) sp=get_note(string,sp,&b,line);
if (sp!=-1) sp=get_note(string,sp,&c,line);
if (a.ed_freq>=0) {
a.offset=allocate_note(a.ed_freq);
notes_used[a.ed_freq]++;
printf("; A: '%s' %d\n",last_note,a.ed_freq);
}
if (b.ed_freq>=0) {
b.offset=allocate_note(b.ed_freq);
notes_used[b.ed_freq]++;
printf("; B: '%s' %d\n",last_note,b.ed_freq);
}
if (c.ed_freq>=0) {
c.offset=allocate_note(c.ed_freq);
notes_used[c.ed_freq]++;
printf("; C: %d\n",c.ed_freq);
}
if ((a.ed_freq>=0)||(b.ed_freq>=0)||(c.ed_freq>=0)) {
// now NNNNNNEC
if (!first) {
write_note(&a_last,&b_last,&c_last,
current_length);
}
// printf("; frame %d: a=%d b=%d len=%d\n",
// total_length,a_last,b_last,current_length);
total_length+=current_length;
current_length=0;
//if (!first) {
// printf("\t.byte $%02X ; L = %d\n",
// current_length|0xc0,current_length);
// printf("\n");
// current_length=0;
// total_len++;
//}
first=0;
}
if (a.ed_freq>=0) {
a_last=a.offset;
}
if (b.ed_freq>=0) {
b_last=b.offset;
}
if (c.ed_freq>=0) {
c_last=c.offset;
}
current_length++;
current_frame++;
}
printf("; last: a=%d b=%d len=%d\n",a_last,b_last,current_length);
write_note(&a_last,&b_last,&c_last,current_length);
// printf("\t.byte $FF ; end\n");
/* assume 32 notes or fewer */
printf("\t.byte $FF ; end\n");
total_len++;
int o,n;
for(o=0;o<6;o++) {
printf("; Octave %d : ",o);
for(n=0;n<12;n++) {
printf("%d ",notes_used[(o*12)+n]);
}
printf("\n");
}
printf("; %d notes allocated\n",notes_allocated);
printf(";.byte ");
for(n=0;n<notes_allocated;n++) {
printf("%d,",allocated_notes[n]);
}
printf("\n");
/* put these first as we use the high bit to end things? */
/* FIXME: sort these, helps with compression */
printf("frequencies_low:\n");
printf(".byte ");
for(n=0;n<notes_allocated;n++) {
printf("$%02X",(frequencies[allocated_notes[n]])&0xff);
if (n!=(notes_allocated-1)) printf(",");
total_len++;
}
printf("\n");
printf("frequencies_high:\n");
printf(".byte ");
for(n=0;n<notes_allocated;n++) {
printf("$%02X",(frequencies[allocated_notes[n]]>>8));
if (n!=(notes_allocated-1)) printf(",");
total_len++;
}
printf("\n");
printf("; total len=%d\n",total_len);
(void) irq;
(void) loop;
(void) external_frequency;
return 0;
}

View File

@ -0,0 +1,22 @@
tracker_init:
; setup initial ay-3-8910 values (this depends on song)
init_registers_to_zero:
ldx #$13 ; zero $70--$83
lda #0
; sta SONG_OFFSET ; also init song stuff
; sta SONG_COUNTDOWN
init_loop:
sta AY_REGS,X
dex
bpl init_loop
lda #$38
sta AY_REGS+7 ; $07 mixer (ABC on)
; lda #$0E
; sta AY_REGS+8 ; $08 volume A
; lda #$0C
; sta AY_REGS+9 ; $09 volume B
; sta AY_REGS+10 ; $0A volume C

View File

@ -0,0 +1,34 @@
; zero page
; pre-defined applesoft vars
CH = $24
CV = $25
GBASL = $26
GBASH = $27
BASL = $28
BASH = $29
AY_REGS = $70
SONG_L = $80
SONG_H = $81
SONG_OFFSET = $82
SONG_COUNTDOWN = $83
OCTAVE = $84
REGISTER = $85
A_COUNTDOWN = $86
B_COUNTDOWN = $87
OUR_ROT = $A5
HGR_X = $E0
HGR_XH = $E1
HGR_Y = $E2
HGR_COLOR = $E4
HGR_PAGE = $E6
HGR_SCALE = $E7
COUNT = $FB
FRAME = $FC
WHICH_TRACK = $FD