flyer: merge it all together

This commit is contained in:
Vince Weaver 2022-01-11 20:37:11 -05:00
parent 923b6f35f7
commit b83c393541
10 changed files with 766 additions and 28 deletions

View File

@ -6,10 +6,12 @@ EMPTYDISK = ../../../empty_disk/empty.dsk
all: flyer_512.dsk
flyer_512.dsk: HELLO FLYER
cp $(EMPTYDISK) flyer_512.dsk
$(DOS33) -y flyer_512.dsk SAVE A HELLO
$(DOS33) -y flyer_512.dsk BSAVE -a 0x800 FLYER
flyer_512.dsk: FLYER
# 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15
dd if=/dev/zero of=flyer_512.dsk bs=256 count=560
dd conv=notrunc if=FLYER of=flyer_512.dsk bs=256 count=1
dd conv=notrunc if=FLYER of=flyer_512.dsk bs=256 count=1 seek=7 skip=1
###
@ -26,21 +28,16 @@ text8.zip: FLYER flyer.s file_id.diz flyer_512.dsk
####
####
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
###
FLYER: flyer.o
ld65 -o FLYER flyer.o -C ./apple2_800.inc
flyer.o: flyer.s
flyer.o: flyer.s \
ay3_write_regs.s flyer.s interrupt_handler.s \
mA2E_3.s mockingboard_constants.s mockingboard_init.s tracker_init.s
ca65 -o flyer.o flyer.s -l flyer.lst
####
clean:
rm -f *~ *.o *.lst HELLO FLYER *.zip
rm -f *~ *.o *.lst FLYER *.zip

View File

@ -0,0 +1,37 @@
;=====================
;=====================
;=====================
; ay3 write regs
;=====================
;=====================
;=====================
; write all 14 registers
; address in X
; data in A
ay3_write_regs:
ldx #13
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 ; 4
sta MOCK_6522_ORB1 ; latch_address on PB1 ; 4
sty MOCK_6522_ORB1 ; 4
; value
lda AY_REGS,X
sta MOCK_6522_ORA1 ; put value on PA1 ; 4
lda #MOCK_AY_WRITE ; ; 2
sta MOCK_6522_ORB1 ; write on PB1 ; 4
sty MOCK_6522_ORB1 ; 4
dex
bpl ay3_write_reg_loop
; rts

View File

@ -1,5 +1,9 @@
Tiny Text
Future Flyer
-
Textmode Hex Scroller
8-byte Intro for Apple II, Lovebyte 2021
Shapetable flyer with mockingboard music
512-byte boot-sector for Apple II, Lovebyte 2022
by Deater / dSr
music by mA2E
Note: assumes Mockingboard in Slot#4.
Music only plays on left speaker.

View File

@ -1,15 +1,20 @@
; Flyer
; 512 byte Apple II "boot sector" with graphics and Music
; by Vince `deater` Weaver, vince@deater.net --- d e s i r e ---
; 178 bytes -- original conversion from BASIC
; 176 bytes -- know HGR2 returns with A=0
; 172 bytes -- optimize page flip code
; 170 bytes -- assume XDRAW never got over X=256
; 504 bytes -- merge in the music code
; zero page locations
AY_REGS = $70
SONG_OFFSET = $82
SONG_COUNTDOWN = $83
HGR_COLOR = $E4
HGR_PAGE = $E6
HGR_SCALE = $E7
@ -19,6 +24,8 @@ HORIZON_LINE = $FE
FRAME = $FF
; soft-switches
KEYPRESS = $C000
KEYRESET = $C010
PAGE1 = $C054
PAGE2 = $C055
@ -32,9 +39,37 @@ HGLIN = $F53A ; line to (X,A), (Y)
DRAW0 = $F601
XDRAW0 = $F65D
.byte 2 ; number of sectors to load
; turn off drive motor
lda $C088,X ; turn off drive motor
; hopefully slot*16 is in X
flyer:
jsr HGR2 ; HGR2 HGR_PAGE=$40
sta FRAME ; A=0 after HGR2
sta FRAME ; A=0, Y=0 after HGR2
;===================
; music Player Setup
tracker_song = peasant_song
; assume mockingboard in slot#4
; inline mockingboard_init
.include "mockingboard_init.s"
.include "tracker_init.s"
; start the music playing
cli
animate_loop:
clc
@ -59,7 +94,10 @@ animate_loop:
cmp PAGE1,X
; clear screen
jsr HCLR
lda #$7f
jsr BKGND0
; jsr HCLR
;===============
; draw mountain
@ -165,8 +203,29 @@ reset_frame:
lda #0
done_frame:
sta FRAME
bob:
lda KEYPRESS
bmi quiet
jmp animate_loop
quiet:
lda #$3f
sta AY_REGS+7
end:
bne end
;=======================
; xdraw
;=======================
@ -216,3 +275,8 @@ ship_table:
; .byte $0
; music
.include "mA2E_3.s"
.include "interrupt_handler.s"
; must be last
.include "mockingboard_constants.s"

View File

@ -1,8 +0,0 @@
5 HOME
10 PRINT "TINY TEXT -- AN 8 BYTE APPLE II INTRO"
15 PRINT " BY DEATER / DSR"
20 PRINT CHR$(4)"CATALOG"
25 PRINT:PRINT "PRESS ANY KEY TO 'BRUN TINY_TEXT'"
30 GET A$
35 PRINT
40 PRINT CHR$(4)"BRUN TINY_TEXT"

View File

@ -0,0 +1,189 @@
;================================
;================================
; 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
; we don't use decimal mode so no need to clear it?
; A is saved in $45 by firmware
; we are assuming a II/II+/IIe here
txa
pha ; save X
tya
pha ; save Y
; inc $0404 ; debug (flashes char onscreen)
ay3_irq_handler:
;==========================================
; clear 6522 interrupt by reading T1C-L ; 4
bit MOCK_6522_T1CL
; drop note down after first
lda #$C
sta AY_REGS+8
sta AY_REGS+10
; 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
;============================
; see if still counting down
lda SONG_COUNTDOWN
bpl done_update_song
set_notes_loop:
;==================
; load next byte
ldy SONG_OFFSET
lda tracker_song,Y
;==================
; see if hit end
cmp #$FF
bne all_ok
;====================================
; if at end, loop back to beginning
lda #0 ; reset song offset
sta SONG_OFFSET
beq set_notes_loop ; bra
all_ok:
; see if note
; tay
; and #$C0
; cmp #$C0
; beq handle_timing
note_only:
; tya
; NNNNNLLC -- c=channel, n=note
tay
ldx #0
lsr
bcc channel_a
ldx #4 ; skip to C
channel_a:
and #$3
sta SONG_COUNTDOWN
; inc SONG_COUNTDOWN
tya
lsr
lsr
lsr
; and #$FE ; fine register value, want in X
; tax
; tya ; get note
; and #$1F
tay ; lookup in table
lda frequencies_low,Y
sta AY_REGS,X ; set proper register value
lda frequencies_high,Y
sta AY_REGS+1,X
lda #$F
sta AY_REGS+8
;============================
; point to next
; assume less than 256 bytes
inc SONG_OFFSET
lda SONG_COUNTDOWN
beq set_notes_loop ; bra
.include "ay3_write_regs.s"
; jsr ay3_write_regs
handle_timing:
; was timing
; tya
; and #$3f
; sta SONG_COUNTDOWN
; inc SONG_OFFSET
done_update_song:
dec SONG_COUNTDOWN
;=================================
; Finally done with this interrupt
;=================================
done_ay3_irq_handler:
pla
tay ; restore Y
pla
tax ; restore X
; on II+/IIe the firmware saves A in $45
; this won't work on a IIc/IIgs
lda $45 ; restore A
plp ; restore flags
rti ; return from interrupt ; 6
;============
; typical
; ???? cycles

311
demos/l/flyer_512/mA2E_3.s Normal file
View File

@ -0,0 +1,311 @@
peasant_song:
; register init
; A: 7
; C: 43
; none: a=-1 c=-1 len=0
; A: 19
; C: 38
; none: a=0 c=1 len=3
.byte $00 ; A=0 L=0
.byte $0F ; C=1 L=3
; A: 5
; none: a=2 c=3 len=2
.byte $10 ; A=2 L=0
.byte $1D ; C=3 L=2
; A: 7
; C: 34
; none: a=4 c=-1 len=1
.byte $22 ; A=4 L=1
; A: 7
; C: 31
; none: a=0 c=5 len=2
.byte $00 ; A=0 L=0
.byte $2D ; C=5 L=2
; A: 19
; C: 34
; none: a=0 c=6 len=3
.byte $00 ; A=0 L=0
.byte $37 ; C=6 L=3
; A: 5
; none: a=2 c=5 len=2
.byte $10 ; A=2 L=0
.byte $2D ; C=5 L=2
; A: 7
; C: 38
; none: a=4 c=-1 len=1
.byte $22 ; A=4 L=1
; A: 3
; C: 43
; none: a=0 c=3 len=2
.byte $00 ; A=0 L=0
.byte $1D ; C=3 L=2
; A: 15
; C: 39
; none: a=7 c=1 len=3
.byte $38 ; A=7 L=0
.byte $0F ; C=1 L=3
; A: 2
; none: a=8 c=9 len=2
.byte $40 ; A=8 L=0
.byte $4D ; C=9 L=2
; A: 3
; C: 34
; none: a=10 c=-1 len=1
.byte $52 ; A=10 L=1
; A: 3
; C: 31
; none: a=7 c=5 len=2
.byte $38 ; A=7 L=0
.byte $2D ; C=5 L=2
; A: 15
; C: 34
; none: a=7 c=6 len=3
.byte $38 ; A=7 L=0
.byte $37 ; C=6 L=3
; A: 2
; none: a=8 c=5 len=2
.byte $40 ; A=8 L=0
.byte $2D ; C=5 L=2
; A: 3
; C: 43
; none: a=10 c=-1 len=1
.byte $52 ; A=10 L=1
; A: 5
; C: 41
; none: a=7 c=1 len=2
.byte $38 ; A=7 L=0
.byte $0D ; C=1 L=2
; A: 17
; none: a=4 c=11 len=3
.byte $20 ; A=4 L=0
.byte $5F ; C=11 L=3
; C: 36
; none: a=12 c=-1 len=1
.byte $62 ; A=12 L=1
; A: 3
; none: a=-1 c=13 len=1
.byte $6B ; C=13 L=1
; A: 5
; C: 33
; none: a=7 c=-1 len=1
.byte $3A ; A=7 L=1
; A: 5
; C: 29
; none: a=4 c=14 len=2
.byte $20 ; A=4 L=0
.byte $75 ; C=14 L=2
; A: 17
; C: 33
; none: a=4 c=15 len=3
.byte $20 ; A=4 L=0
.byte $7F ; C=15 L=3
; A: 3
; none: a=12 c=14 len=2
.byte $60 ; A=12 L=0
.byte $75 ; C=14 L=2
; A: 5
; C: 39
; none: a=7 c=-1 len=1
.byte $3A ; A=7 L=1
; A: 2
; C: 38
; none: a=4 c=9 len=2
.byte $20 ; A=4 L=0
.byte $4D ; C=9 L=2
; A: 14
; C: 39
; none: a=10 c=3 len=3
.byte $50 ; A=10 L=0
.byte $1F ; C=3 L=3
; A: 0
; none: a=16 c=9 len=2
.byte $80 ; A=16 L=0
.byte $4D ; C=9 L=2
; A: 2
; C: 38
; none: a=17 c=-1 len=1
.byte $8A ; A=17 L=1
; A: 2
; C: 36
; none: a=10 c=3 len=2
.byte $50 ; A=10 L=0
.byte $1D ; C=3 L=2
; A: 14
; C: 34
; none: a=10 c=13 len=3
.byte $50 ; A=10 L=0
.byte $6F ; C=13 L=3
; A: 0
; none: a=16 c=5 len=2
.byte $80 ; A=16 L=0
.byte $2D ; C=5 L=2
; A: 2
; C: 33
; none: a=17 c=-1 len=1
.byte $8A ; A=17 L=1
; A: 7
; C: 43
; none: a=10 c=14 len=2
.byte $50 ; A=10 L=0
.byte $75 ; C=14 L=2
; A: 19
; none: a=0 c=1 len=3
.byte $00 ; A=0 L=0
.byte $0F ; C=1 L=3
; A: 5
; none: a=2 c=-1 len=2
.byte $14 ; A=2 L=2
; A: 7
; C: 41
; none: a=4 c=-1 len=1
.byte $22 ; A=4 L=1
; C: 38
; none: a=0 c=11 len=1
.byte $00 ; A=0 L=0
.byte $5B ; C=11 L=1
; A: 7
; C: 31
; none: a=-1 c=3 len=1
.byte $1B ; C=3 L=1
; A: 19
; none: a=0 c=6 len=3
.byte $00 ; A=0 L=0
.byte $37 ; C=6 L=3
; C: 34
; none: a=2 c=-1 len=1
.byte $12 ; A=2 L=1
; A: 5
; none: a=-1 c=5 len=1
.byte $2B ; C=5 L=1
; A: 7
; C: 36
; none: a=4 c=-1 len=1
.byte $22 ; A=4 L=1
; A: 3
; C: 43
; none: a=0 c=13 len=2
.byte $00 ; A=0 L=0
.byte $6D ; C=13 L=2
; A: 15
; none: a=7 c=1 len=3
.byte $38 ; A=7 L=0
.byte $0F ; C=1 L=3
; A: 2
; none: a=8 c=-1 len=2
.byte $44 ; A=8 L=2
; A: 3
; C: 41
; none: a=10 c=-1 len=1
.byte $52 ; A=10 L=1
; C: 43
; none: a=7 c=11 len=1
.byte $38 ; A=7 L=0
.byte $5B ; C=11 L=1
; A: 3
; C: 39
; none: a=-1 c=1 len=1
.byte $0B ; C=1 L=1
; A: 15
; none: a=7 c=9 len=3
.byte $38 ; A=7 L=0
.byte $4F ; C=9 L=3
; C: 38
; none: a=8 c=-1 len=1
.byte $42 ; A=8 L=1
; A: 2
; none: a=-1 c=3 len=1
.byte $1B ; C=3 L=1
; A: 3
; C: 34
; none: a=10 c=-1 len=1
.byte $52 ; A=10 L=1
; A: 5
; C: 36
; none: a=7 c=5 len=2
.byte $38 ; A=7 L=0
.byte $2D ; C=5 L=2
; A: 17
; none: a=4 c=13 len=3
.byte $20 ; A=4 L=0
.byte $6F ; C=13 L=3
; A: 3
; none: a=12 c=-1 len=2
.byte $64 ; A=12 L=2
; A: 5
; C: 34
; none: a=7 c=-1 len=1
.byte $3A ; A=7 L=1
; C: 36
; none: a=4 c=5 len=1
.byte $20 ; A=4 L=0
.byte $2B ; C=5 L=1
; A: 5
; C: 33
; none: a=-1 c=13 len=1
.byte $6B ; C=13 L=1
; A: 17
; none: a=4 c=14 len=3
.byte $20 ; A=4 L=0
.byte $77 ; C=14 L=3
; C: 31
; none: a=12 c=-1 len=1
.byte $62 ; A=12 L=1
; A: 3
; none: a=-1 c=6 len=1
.byte $33 ; C=6 L=1
; A: 5
; C: 33
; none: a=7 c=-1 len=1
.byte $3A ; A=7 L=1
; A: 2
; C: 29
; none: a=4 c=14 len=2
.byte $20 ; A=4 L=0
.byte $75 ; C=14 L=2
; A: 14
; C: 31
; none: a=10 c=15 len=3
.byte $50 ; A=10 L=0
.byte $7F ; C=15 L=3
; A: 0
; none: a=16 c=6 len=2
.byte $80 ; A=16 L=0
.byte $35 ; C=6 L=2
; A: 2
; C: 33
; none: a=17 c=-1 len=1
.byte $8A ; A=17 L=1
; A: 2
; none: a=10 c=14 len=2
.byte $50 ; A=10 L=0
.byte $75 ; C=14 L=2
; C: 36
; none: a=10 c=-1 len=1
.byte $52 ; A=10 L=1
; A: 14
; none: a=-1 c=13 len=2
.byte $6D ; C=13 L=2
; C: 29
; none: a=16 c=-1 len=1
.byte $82 ; A=16 L=1
; A: 0
; none: a=-1 c=15 len=1
.byte $7B ; C=15 L=1
; A: 2
; none: a=17 c=-1 len=1
.byte $8A ; A=17 L=1
; last: a=10 c=-1 len=2
.byte $54 ; A=10 L=2
.byte $FF ; end
; Octave 0 : 4 0 12 12 0 12 0 8 0 0 0 0
; Octave 1 : 0 0 4 4 0 4 0 4 0 0 0 0
; Octave 2 : 0 0 0 0 0 3 0 5 0 6 8 0
; Octave 3 : 6 0 6 4 0 3 0 6 0 0 0 0
; 18 notes allocated
;.byte 7,43,19,38,5,34,31,3,15,39,2,41,17,36,33,29,14,0,
frequencies_high:
.byte $02,$00,$01,$00,$02,$00,$00,$03,$01,$00,$03,$00,$01,$00,$00,$00,$01,$03
frequencies_low:
.byte $8C,$51,$46,$6C,$DC,$89,$A3,$36,$9B,$66,$66,$5B,$6E,$7A,$91,$B7,$B3,$D1
; total len=148

View File

@ -0,0 +1,16 @@
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 $CE,$C7 ; c7ce / 1.023e6 = .050s, 20Hz
.byte MOCK_AY_RESET,MOCK_AY_INACTIVE

View File

@ -0,0 +1,105 @@
; 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:
; 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
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,23 @@
tracker_init:
; setup initial ay-3-8910 values (this depends on song)
init_registers_to_zero:
ldx #13
lda #0
sta SONG_OFFSET ; also init song stuff
sta SONG_COUNTDOWN
init_loop:
sta AY_REGS,X
dex
bpl init_loop
; jsr ay3_write_regs
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