mirror of
https://github.com/deater/dos33fsprogs.git
synced 2025-01-19 15:30:08 +00:00
lovebyte: add music to plasma
This commit is contained in:
parent
7f98b47120
commit
67d993a9ed
31
demos/lovebyte2024/plasma/Makefile
Normal file
31
demos/lovebyte2024/plasma/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
include ../../../Makefile.inc
|
||||
|
||||
DOS33 = ../../../utils/dos33fs-utils/dos33
|
||||
TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft
|
||||
LINKERSCRIPTS = ../../../linker_scripts
|
||||
EMPTYDISK = ../../../empty_disk/empty.dsk
|
||||
|
||||
all: plasmag.dsk
|
||||
|
||||
plasmag.dsk: HELLO PLASMAG_TINY
|
||||
cp $(EMPTYDISK) plasmag.dsk
|
||||
$(DOS33) -y plasmag.dsk SAVE A HELLO
|
||||
$(DOS33) -y plasmag.dsk BSAVE -a 0x4000 PLASMAG_TINY
|
||||
|
||||
###
|
||||
|
||||
HELLO: hello.bas
|
||||
$(TOKENIZE) < hello.bas > HELLO
|
||||
|
||||
###
|
||||
|
||||
PLASMAG_TINY: plasmag_tiny.o
|
||||
ld65 -o PLASMAG_TINY plasmag_tiny.o -C $(LINKERSCRIPTS)/apple2_4000.inc
|
||||
|
||||
plasmag_tiny.o: plasmag_tiny.s gr_gbascalc.s make_tables.s
|
||||
ca65 -o plasmag_tiny.o plasmag_tiny.s -l plasmag_tiny.lst
|
||||
|
||||
###
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.lst HELLO PLASMAG_TINY
|
4
demos/lovebyte2024/plasma/TODO
Normal file
4
demos/lovebyte2024/plasma/TODO
Normal file
@ -0,0 +1,4 @@
|
||||
optimize music code:
|
||||
+ depending on alignment can hard-code the high value for track0/track1
|
||||
+ check the frequencies, high freq might always be 0
|
||||
|
34
demos/lovebyte2024/plasma/ay3_write_regs.s
Normal file
34
demos/lovebyte2024/plasma/ay3_write_regs.s
Normal file
@ -0,0 +1,34 @@
|
||||
;=====================
|
||||
;=====================
|
||||
;=====================
|
||||
; ay3 write regs
|
||||
;=====================
|
||||
;=====================
|
||||
;=====================
|
||||
; write all 14 registers at AY_REGS
|
||||
|
||||
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
|
||||
|
||||
|
68
demos/lovebyte2024/plasma/interrupt_handler.s
Normal file
68
demos/lovebyte2024/plasma/interrupt_handler.s
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
167
demos/lovebyte2024/plasma/mA2E_2.s
Normal file
167
demos/lovebyte2024/plasma/mA2E_2.s
Normal file
@ -0,0 +1,167 @@
|
||||
; Made with version 1.0 (2024 Lovebyte)
|
||||
peasant_song:
|
||||
; register init
|
||||
|
||||
track0:
|
||||
|
||||
; A: 'A 5' 57
|
||||
; B: 'A 5' 57
|
||||
.byte $04 ; frame=2 A=0 L=2
|
||||
; A: 'C 6' 60
|
||||
.byte $05 ; frame=4 B=0 L=2
|
||||
; B: 'C 6' 60
|
||||
.byte $14 ; frame=6 A=1 L=2
|
||||
; A: 'F 5' 53
|
||||
.byte $15 ; frame=8 B=1 L=2
|
||||
; B: 'F 5' 53
|
||||
.byte $24 ; frame=10 A=2 L=2
|
||||
; A: 'G 5' 55
|
||||
.byte $2D ; frame=16 B=2 L=6
|
||||
; B: 'G 5' 55
|
||||
.byte $34 ; frame=18 A=3 L=2
|
||||
; A: 'E 5' 52
|
||||
.byte $35 ; frame=20 B=3 L=2
|
||||
; A: 'E 5' 50
|
||||
; B: 'E 5' 52
|
||||
.byte $44 ; frame=22 A=4 L=2
|
||||
; A: 'D 5' 57
|
||||
; B: 'D 5' 50
|
||||
.byte $50 ; frame=24 A=5 L=0
|
||||
.byte $45 ; frame=24 B=4 L=2
|
||||
; B: 'A 5' 57
|
||||
.byte $00 ; frame=26 A=0 L=0
|
||||
.byte $55 ; frame=26 B=5 L=2
|
||||
; A: 'E 5' 52
|
||||
.byte $05 ; frame=28 B=0 L=2
|
||||
; B: 'E 5' 52
|
||||
.byte $44 ; frame=30 A=4 L=2
|
||||
; A: 'A 5' 57
|
||||
.byte $45 ; frame=32 B=4 L=2
|
||||
; B: 'A 5' 57
|
||||
.byte $04 ; frame=34 A=0 L=2
|
||||
; A: 'C 6' 60
|
||||
.byte $05 ; frame=36 B=0 L=2
|
||||
; B: 'C 6' 60
|
||||
.byte $14 ; frame=38 A=1 L=2
|
||||
; A: 'F 5' 53
|
||||
.byte $15 ; frame=40 B=1 L=2
|
||||
; B: 'F 5' 53
|
||||
.byte $24 ; frame=42 A=2 L=2
|
||||
; A: 'G 5' 55
|
||||
.byte $2D ; frame=48 B=2 L=6
|
||||
; B: 'G 5' 55
|
||||
.byte $34 ; frame=50 A=3 L=2
|
||||
; A: 'E 5' 52
|
||||
.byte $35 ; frame=52 B=3 L=2
|
||||
; A: 'E 5' 50
|
||||
; B: 'E 5' 52
|
||||
.byte $44 ; frame=54 A=4 L=2
|
||||
; A: 'D 5' 45
|
||||
; B: 'D 5' 50
|
||||
.byte $50 ; frame=56 A=5 L=0
|
||||
.byte $45 ; frame=56 B=4 L=2
|
||||
; B: 'A 4' 45
|
||||
.byte $60 ; frame=58 A=6 L=0
|
||||
.byte $55 ; frame=58 B=5 L=2
|
||||
; A: 'E 4' 40
|
||||
.byte $65 ; frame=60 B=6 L=2
|
||||
; B: 'E 4' 40
|
||||
.byte $74 ; frame=62 A=7 L=2
|
||||
; last: a=-1 b=7 len=2
|
||||
.byte $75 ; frame=64 B=7 L=2
|
||||
.byte $ff
|
||||
track1:
|
||||
|
||||
; A: 'A 4' 57
|
||||
; B: 'A 4' 45
|
||||
; A: 'A 4' 60
|
||||
; B: 'A 4' 45
|
||||
.byte $00 ; frame=4 A=0 L=0
|
||||
.byte $69 ; frame=4 B=6 L=4
|
||||
; B: 'B 4' 47
|
||||
.byte $10 ; frame=6 A=1 L=0
|
||||
.byte $65 ; frame=6 B=6 L=2
|
||||
; A: 'C 5' 53
|
||||
; B: 'C 5' 48
|
||||
.byte $85 ; frame=8 B=8 L=2
|
||||
; B: 'A 4' 45
|
||||
.byte $20 ; frame=10 A=2 L=0
|
||||
.byte $95 ; frame=10 B=9 L=2
|
||||
; B: 'D 5' 50
|
||||
.byte $69 ; frame=14 B=6 L=4
|
||||
; A: 'G 5' 55
|
||||
.byte $55 ; frame=16 B=5 L=2
|
||||
; B: 'D 5' 50
|
||||
.byte $34 ; frame=18 A=3 L=2
|
||||
; A: 'C 5' 52
|
||||
; B: 'C 5' 48
|
||||
.byte $55 ; frame=20 B=5 L=2
|
||||
; A: 'B 4' 50
|
||||
; B: 'B 4' 47
|
||||
.byte $40 ; frame=22 A=4 L=0
|
||||
.byte $95 ; frame=22 B=9 L=2
|
||||
; A: 'C 5' 57
|
||||
; B: 'C 5' 48
|
||||
.byte $50 ; frame=24 A=5 L=0
|
||||
.byte $85 ; frame=24 B=8 L=2
|
||||
; B: 'A 4' 45
|
||||
.byte $00 ; frame=26 A=0 L=0
|
||||
.byte $95 ; frame=26 B=9 L=2
|
||||
; A: 'E 5' 52
|
||||
.byte $65 ; frame=28 B=6 L=2
|
||||
; A: 'A 4' 57
|
||||
; B: 'A 4' 45
|
||||
.byte $48 ; frame=32 A=4 L=4
|
||||
; A: 'A 4' 60
|
||||
; B: 'A 4' 45
|
||||
.byte $00 ; frame=36 A=0 L=0
|
||||
.byte $69 ; frame=36 B=6 L=4
|
||||
; B: 'B 4' 47
|
||||
.byte $10 ; frame=38 A=1 L=0
|
||||
.byte $65 ; frame=38 B=6 L=2
|
||||
; A: 'C 5' 53
|
||||
; B: 'C 5' 48
|
||||
.byte $85 ; frame=40 B=8 L=2
|
||||
; B: 'A 4' 45
|
||||
.byte $20 ; frame=42 A=2 L=0
|
||||
.byte $95 ; frame=42 B=9 L=2
|
||||
; B: 'A 4' 45
|
||||
.byte $69 ; frame=46 B=6 L=4
|
||||
; B: 'B 4' 47
|
||||
.byte $63 ; frame=47 B=6 L=1
|
||||
; A: 'D 5' 55
|
||||
; B: 'D 5' 50
|
||||
.byte $83 ; frame=48 B=8 L=1
|
||||
; B: 'D 5' 50
|
||||
.byte $30 ; frame=50 A=3 L=0
|
||||
.byte $55 ; frame=50 B=5 L=2
|
||||
; A: 'C 5' 52
|
||||
; B: 'C 5' 48
|
||||
.byte $55 ; frame=52 B=5 L=2
|
||||
; A: 'B 4' 50
|
||||
; B: 'B 4' 47
|
||||
.byte $40 ; frame=54 A=4 L=0
|
||||
.byte $95 ; frame=54 B=9 L=2
|
||||
; A: 'A 4' 45
|
||||
; B: 'A 4' 45
|
||||
.byte $50 ; frame=56 A=5 L=0
|
||||
.byte $85 ; frame=56 B=8 L=2
|
||||
; A: 'E 4' 40
|
||||
.byte $60 ; frame=60 A=6 L=0
|
||||
.byte $69 ; frame=60 B=6 L=4
|
||||
; last: a=7 b=-1 len=4
|
||||
.byte $78 ; frame=64 A=7 L=4
|
||||
.byte $FF ; end
|
||||
; Octave 0 : 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
; Octave 1 : 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
; Octave 2 : 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
; Octave 3 : 0 0 0 0 3 0 0 0 0 12 0 5
|
||||
; Octave 4 : 5 0 10 0 9 6 0 6 0 9 0 0
|
||||
; Octave 5 : 6 0 0 0 0 0 0 0 0 0 0 0
|
||||
; 10 notes allocated
|
||||
;.byte 57,60,53,55,52,50,45,40,47,48,
|
||||
frequencies_low:
|
||||
.byte $48,$3D,$5B,$51,$60,$6C,$91,$C1,$81,$7A
|
||||
frequencies_high:
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
; total len=21
|
21
demos/lovebyte2024/plasma/mockingboard_constants.s
Normal file
21
demos/lovebyte2024/plasma/mockingboard_constants.s
Normal 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
|
||||
|
119
demos/lovebyte2024/plasma/mockingboard_init.s
Normal file
119
demos/lovebyte2024/plasma/mockingboard_init.s
Normal 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:
|
210
demos/lovebyte2024/plasma/plasmag_tiny.s
Normal file
210
demos/lovebyte2024/plasma/plasmag_tiny.s
Normal file
@ -0,0 +1,210 @@
|
||||
; Plasma Tiny
|
||||
|
||||
; originally based on Plasmagoria code by French Touch
|
||||
|
||||
; trying to see how small I can get it
|
||||
|
||||
|
||||
; note can use $F000 (or similar) for color lookup to get passable
|
||||
; effect on fewer bytes
|
||||
|
||||
; 347 bytes -- initial with FAC
|
||||
; 343 bytes -- optimize init
|
||||
; 340 bytes -- move Table1 + Table2 to zero page
|
||||
; 331 bytes -- init not necessary
|
||||
; 319 bytes -- inline precalc + display + init lores colors
|
||||
; 316 bytes -- fallthrough in make_tiny
|
||||
|
||||
.include "hardware.inc"
|
||||
.include "zp.inc"
|
||||
|
||||
;Table1 = $8000
|
||||
;Table2 = $8000+64
|
||||
|
||||
|
||||
lores_colors_fine=$8100
|
||||
|
||||
;======================================
|
||||
; start of code
|
||||
;======================================
|
||||
|
||||
plasma_tiny:
|
||||
jsr HGR ; have table gen appear on hgr page1
|
||||
bit FULLGR
|
||||
|
||||
|
||||
|
||||
|
||||
;=================
|
||||
; init music
|
||||
|
||||
lda #0
|
||||
sta FRAME
|
||||
sta WHICH_TRACK
|
||||
|
||||
;===================
|
||||
; music Player Setup
|
||||
|
||||
tracker_song = peasant_song
|
||||
|
||||
; assume mockingboard in slot#4
|
||||
|
||||
; inline mockingboard_init
|
||||
|
||||
.include "mockingboard_init.s"
|
||||
|
||||
.include "tracker_init.s"
|
||||
|
||||
cli ; start music
|
||||
|
||||
jsr make_tables
|
||||
|
||||
bit LORES ; set lo-res
|
||||
|
||||
; ============================================================================
|
||||
; init lores colors (inline)
|
||||
; ============================================================================
|
||||
|
||||
init_lores_colors:
|
||||
ldx #0
|
||||
ldy #0
|
||||
|
||||
init_lores_colors_loop:
|
||||
lda lores_colors_lookup,X
|
||||
sta lores_colors_fine,Y
|
||||
iny
|
||||
sta lores_colors_fine,Y
|
||||
iny
|
||||
sta lores_colors_fine,Y
|
||||
iny
|
||||
sta lores_colors_fine,Y
|
||||
iny
|
||||
beq done_init_lores_colors
|
||||
|
||||
inx
|
||||
txa
|
||||
and #$f
|
||||
tax
|
||||
jmp init_lores_colors_loop
|
||||
|
||||
done_init_lores_colors:
|
||||
|
||||
;====================================
|
||||
; do plasma
|
||||
;====================================
|
||||
|
||||
do_plasma:
|
||||
; init
|
||||
|
||||
; lda #02
|
||||
; ldx #5
|
||||
;init_loop:
|
||||
; sta COMPT1,X
|
||||
; dex
|
||||
; bne init_loop
|
||||
|
||||
BP3:
|
||||
|
||||
; ============================================================================
|
||||
; Precalculate some values (inlined)
|
||||
; ROUTINES PRE CALCUL
|
||||
; ============================================================================
|
||||
precalc:
|
||||
lda PARAM1 ; self modify various parts
|
||||
sta pc_off1+1
|
||||
lda PARAM2
|
||||
sta pc_off2+1
|
||||
lda PARAM3
|
||||
sta pc_off3+1
|
||||
lda PARAM4
|
||||
sta pc_off4+1
|
||||
|
||||
; Table1(X) = sin1(PARAM1+X)+sin2(PARAM1+X)
|
||||
; Table2(X) = sin3(PARAM3+X)+sin1(PARAM4+X)
|
||||
|
||||
ldx #$28 ; 40
|
||||
pc_b1:
|
||||
pc_off1:
|
||||
lda sin1
|
||||
pc_off2:
|
||||
adc sin2
|
||||
sta Table1,X
|
||||
pc_off3:
|
||||
lda sin3
|
||||
pc_off4:
|
||||
adc sin1
|
||||
sta Table2,X
|
||||
|
||||
inc pc_off1+1
|
||||
inc pc_off2+1
|
||||
inc pc_off3+1
|
||||
inc pc_off4+1
|
||||
|
||||
dex
|
||||
bpl pc_b1
|
||||
|
||||
inc PARAM1
|
||||
inc PARAM1
|
||||
dec PARAM2
|
||||
inc PARAM3
|
||||
dec PARAM4
|
||||
|
||||
; ============================================================================
|
||||
; Display Routines
|
||||
; ROUTINES AFFICHAGES
|
||||
; ============================================================================
|
||||
|
||||
; Display "Normal"
|
||||
; AFFICHAGE "NORMAL"
|
||||
|
||||
display_normal:
|
||||
|
||||
ldx #23 ; lines 0-23 lignes 0-23
|
||||
|
||||
display_line_loop:
|
||||
|
||||
txa
|
||||
jsr GBASCALC
|
||||
|
||||
ldy #39 ; col 0-39
|
||||
|
||||
lda Table2,X ; setup base sine value for row
|
||||
sta display_row_sin_smc+1
|
||||
display_col_loop:
|
||||
lda Table1,Y ; load in column sine value
|
||||
display_row_sin_smc:
|
||||
adc #00 ; add in row value
|
||||
sta display_lookup_smc+1 ; patch in low byte of lookup
|
||||
display_lookup_smc:
|
||||
lda lores_colors_fine ; attention: must be aligned
|
||||
sta (GBASL),Y
|
||||
dey
|
||||
bpl display_col_loop
|
||||
dex
|
||||
bpl display_line_loop
|
||||
|
||||
; ============================================================================
|
||||
|
||||
inc COMPT1
|
||||
bne BP3
|
||||
|
||||
dec COMPT2
|
||||
bne BP3
|
||||
|
||||
beq do_plasma ; bra
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
lores_colors_lookup:
|
||||
.byte $00,$88,$55,$99,$ff,$bb,$33,$22,$66,$77,$44,$cc,$ee,$dd,$99,$11
|
||||
|
||||
|
||||
.include "make_tables.s"
|
||||
|
||||
.include "interrupt_handler.s"
|
||||
.include "mockingboard_constants.s"
|
||||
|
||||
; music
|
||||
.include "mA2E_2.s"
|
182
demos/lovebyte2024/plasma/play_frame.s
Normal file
182
demos/lovebyte2024/plasma/play_frame.s
Normal 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:
|
22
demos/lovebyte2024/plasma/tracker_init.s
Normal file
22
demos/lovebyte2024/plasma/tracker_init.s
Normal 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
|
||||
|
46
demos/lovebyte2024/plasma/zp.inc
Normal file
46
demos/lovebyte2024/plasma/zp.inc
Normal file
@ -0,0 +1,46 @@
|
||||
; zero page
|
||||
|
||||
; pre-defined applesoft vars
|
||||
|
||||
CH = $24
|
||||
CV = $25
|
||||
GBASL = $26
|
||||
GBASH = $27
|
||||
BASL = $28
|
||||
BASH = $29
|
||||
|
||||
COMPT1 = $30
|
||||
COMPT2 = $31
|
||||
|
||||
PARAM1 = $60
|
||||
PARAM2 = $61
|
||||
PARAM3 = $62
|
||||
PARAM4 = $63
|
||||
|
||||
AY_REGS = $70
|
||||
; through = $7F
|
||||
|
||||
SONG_L = $80
|
||||
SONG_H = $81
|
||||
SONG_OFFSET = $82
|
||||
SONG_COUNTDOWN = $83
|
||||
OCTAVE = $84
|
||||
REGISTER = $85
|
||||
A_COUNTDOWN = $86
|
||||
B_COUNTDOWN = $87
|
||||
|
||||
Table1 = $A0 ; 40 bytes ($28)
|
||||
Table2 = $D0 ; 40 bytes ($28)
|
||||
|
||||
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
|
159
demos/lovebyte2024/plasma/zx02_optim.s
Normal file
159
demos/lovebyte2024/plasma/zx02_optim.s
Normal 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
|
Loading…
x
Reference in New Issue
Block a user