551 lines
19 KiB
Plaintext
551 lines
19 KiB
Plaintext
%include include\gigatron.i
|
|
%include include\macros.i
|
|
|
|
vram EQU 0x0800
|
|
|
|
midiStreamPtr EQU 0x82
|
|
midiCommand EQU midiStreamPtr + 0x02
|
|
midiChannel EQU midiStreamPtr + 0x04
|
|
midiDelay EQU midiStreamPtr + 0x06
|
|
midiNote EQU midiStreamPtr + 0x08
|
|
midiScratch EQU midiStreamPtr + 0x0A
|
|
|
|
vbase EQU 0x90
|
|
pixels EQU 0x92
|
|
xPos EQU 0x94
|
|
yPos EQU 0x96
|
|
xVel EQU 0x98
|
|
yVel EQU 0x9A
|
|
i EQU 0x9C
|
|
frame EQU 0x9E
|
|
scratch EQU 0xA0
|
|
pixel EQU 0xA2
|
|
random EQU 0xA4
|
|
skip EQU 0xA6
|
|
xyAbs EQU 0xA8
|
|
colour EQU 0xAA
|
|
ii EQU 0xB0
|
|
jj EQU 0xB1
|
|
kk EQU 0xB2
|
|
ll EQU 0xB3
|
|
xx EQU 0xB4
|
|
yy EQU 0xB5
|
|
|
|
xyPosArray EQU 0x600
|
|
xyVelArray EQU 0x680
|
|
|
|
|
|
numStars EQU 40 ; max 64, (arrays are fixed at a maximum size of 64)
|
|
|
|
|
|
_startAddress_ EQU 0x0200 ; entry point for the code, if this is missing defaults to 0x0200
|
|
|
|
_callTable_ EQU 0x007E ; call addresses are automatically stored here by the assembler, it grows downwards
|
|
; this is optional, if you choose not to use it, then you must use the LDWI xxxx, CALL _vAC paradigm
|
|
; *NOTE* gt1 spec only allows for one zero page segment, .vasm files use this for the call table
|
|
; do *NOT* make this address higher than 0x00BE, it will conflict with future ROM loading mechanisms
|
|
; do *NOT* define constants, (DB or DW), between 0x30 -> 0x44 and 0xc0 -> 0xFF, these addresses are
|
|
; used by the loader and the vCPU stack, you can create variables in these areas as long as you don't
|
|
; corrupt your nested CALL return addresses on the stack
|
|
|
|
_singleStepWatch_ EQU i ; the single step debugger watches this variable location to decide when to step,
|
|
; choose a variable that is updated often
|
|
|
|
start EQU 0x200
|
|
loopInit EQU 0x300
|
|
vBlank EQU 0x400
|
|
clearScreen EQU 0x08A1
|
|
clearScreen_0 EQU 0x09A1
|
|
resetAudio EQU 0x0AA1
|
|
playMidi EQU 0x0BA1
|
|
midiStartNote EQU 0x0CA1
|
|
midiSegment EQU 0x0DA1
|
|
|
|
|
|
; look up table that retrieves skip values based on max velocity component
|
|
skipLut EQU 0x500
|
|
skipLut DB 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
|
DB 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F
|
|
DB 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F
|
|
DB 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07
|
|
DB 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0x07
|
|
DB 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03
|
|
DB 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03
|
|
DB 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
|
DB 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
|
|
|
; look up table that is used to return (abs({-8...8} - {0}) <<4)
|
|
xyAbsLut EQU 0x590
|
|
xyAbsLut DB 0x80 0x70 0x60 0x50 0x40 0x30 0x20 0x10 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80
|
|
|
|
; look up table that retrieves colours
|
|
colourLut EQU 0x5A0
|
|
colourLut DB 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15
|
|
DB 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A 0x2A
|
|
DB 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F 0x3F
|
|
|
|
|
|
start CALL resetAudio
|
|
CALL clearScreen
|
|
|
|
LDWI vram
|
|
STW vbase ; vram base address
|
|
STW pixels ; pixel address
|
|
|
|
LDWI skipLut
|
|
STW skip
|
|
LDWI xyAbsLut
|
|
STW xyAbs
|
|
LDWI colourLut
|
|
STW colour
|
|
|
|
LDWI xyPosArray
|
|
STW xPos
|
|
LDWI xyPosArray + 1
|
|
STW yPos
|
|
|
|
LDWI xyVelArray
|
|
STW xVel
|
|
LDWI xyVelArray + 1
|
|
STW yVel
|
|
|
|
LD giga_frameCount
|
|
STW frame
|
|
|
|
init LDI numStars
|
|
ST i
|
|
|
|
; center position
|
|
rand_vel CALL randPos
|
|
CALL randVel
|
|
|
|
INC xPos
|
|
INC xPos
|
|
INC yPos
|
|
INC yPos
|
|
|
|
INC xVel
|
|
INC xVel
|
|
INC yVel
|
|
INC yVel
|
|
|
|
LD i
|
|
SUBI 0x01
|
|
ST i
|
|
BGT rand_vel
|
|
|
|
LD giga_frameCount ; Start checking midi stream immediately
|
|
ST midiDelay
|
|
|
|
CALL loopInit
|
|
|
|
|
|
loopInit LDWI giga_rand1
|
|
;LDWI SYS_Random_34
|
|
;STW giga_sysFn
|
|
;SYS 34
|
|
STW random
|
|
|
|
LDI numStars
|
|
ST i
|
|
|
|
LDWI xyPosArray
|
|
STW xPos
|
|
LDWI xyPosArray + 1
|
|
STW yPos
|
|
|
|
LDWI xyVelArray
|
|
STW xVel
|
|
LDWI xyVelArray + 1
|
|
STW yVel
|
|
|
|
; main loop
|
|
loop LDW yVel ; high nibble of yVel is max(abs(xVel), abs(yVel)), (0x10...0x80}
|
|
PEEK
|
|
ANDI 0xF0
|
|
STW scratch
|
|
LutPeek skip scratch
|
|
STW scratch
|
|
LD giga_frameCount
|
|
ANDW scratch
|
|
BNE pickcolour
|
|
|
|
counter LDW xVel ; increment counter per star, (embedded in high nibble of xVel)
|
|
PEEK
|
|
ADDI 0x10
|
|
POKE xVel
|
|
|
|
pickcolour LDW xVel ; high nibble of xVel is counter
|
|
PEEK
|
|
ANDI 0xF0
|
|
SUBI 0x30
|
|
BGE maxcolour
|
|
|
|
LDW xVel ; counter indexes into colourLut
|
|
PEEK
|
|
ANDI 0xF0
|
|
STW scratch
|
|
LutPeek colour scratch
|
|
BRA pixelcolour
|
|
|
|
maxcolour LDI 0x3F
|
|
pixelcolour ST pixel
|
|
|
|
erase LDW xPos
|
|
DEEK
|
|
ADDW vbase
|
|
STW pixels
|
|
LDI 0x00
|
|
POKE pixels
|
|
|
|
CALL velocity
|
|
|
|
; x position bounds checking
|
|
xbounds LDW xPos
|
|
PEEK
|
|
BLE xyreset
|
|
SUBI 0xA0
|
|
BGE xyreset
|
|
|
|
; y position bounds checking
|
|
ybounds LDW yPos
|
|
PEEK
|
|
BLE xyreset
|
|
SUBI 0x6E
|
|
BLT draw
|
|
|
|
; reset
|
|
xyreset CALL randPos
|
|
CALL randVel
|
|
CALL velocity ; origin
|
|
LDI 0b00010101
|
|
ST pixel
|
|
|
|
; generate vram address
|
|
draw LDW xPos
|
|
DEEK
|
|
ADDW vbase
|
|
STW pixels
|
|
LD pixel
|
|
POKE pixels ; plot new pixel
|
|
|
|
INC xPos
|
|
INC xPos
|
|
INC yPos
|
|
INC yPos
|
|
|
|
INC xVel
|
|
INC xVel
|
|
INC yVel
|
|
INC yVel
|
|
|
|
CALL playMidi
|
|
|
|
LD i
|
|
SUBI 0x01
|
|
ST i
|
|
BGT loop
|
|
|
|
CALL vBlank
|
|
BRA loopInit
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; subroutines
|
|
vBlank LD giga_frameCount
|
|
SUBW frame
|
|
BEQ vBlank
|
|
LD giga_frameCount
|
|
STW frame
|
|
RET
|
|
|
|
|
|
; random position
|
|
randPos LD i
|
|
ANDI 0x03
|
|
ADDW random
|
|
PEEK
|
|
ANDI 0x03
|
|
ADDI 0x4E
|
|
POKE xPos
|
|
|
|
LD i
|
|
ADDI 0x01
|
|
ANDI 0x03
|
|
ADDW random
|
|
PEEK
|
|
ANDI 0x03
|
|
ADDI 0x3A
|
|
POKE yPos
|
|
RET
|
|
|
|
; random velocity
|
|
randVel LD i
|
|
ADDI 0x02
|
|
ANDI 0x03
|
|
ADDW random
|
|
PEEK ; x velocity
|
|
ANDI 0x0F
|
|
POKE xVel
|
|
STW scratch
|
|
LutPeek xyAbs scratch
|
|
ORW scratch
|
|
POKE xVel ; high nibble = abs(xvel)
|
|
|
|
LD i
|
|
ADDI 0x03
|
|
ANDI 0x03
|
|
ADDW random
|
|
PEEK ; y velocity
|
|
ANDI 0x0F
|
|
POKE yVel
|
|
STW scratch
|
|
LutPeek xyAbs scratch
|
|
ORW scratch
|
|
POKE yVel ; high nibble = abs(yvel)
|
|
|
|
ANDI 0xF0 ; max(xVel&0xF0, yVel&0xF0)
|
|
STW scratch
|
|
LD xVel
|
|
PEEK
|
|
ANDI 0xF0
|
|
SUBW scratch
|
|
BGT randVel0
|
|
LD xVel
|
|
PEEK
|
|
ANDI 0x0F
|
|
POKE xVel ; xvel high nibble = 0
|
|
RET ; yvel high nibble = yVel&0xF0
|
|
|
|
randVel0 LD xVel
|
|
PEEK
|
|
ANDI 0xF0
|
|
STW scratch
|
|
LD yVel
|
|
PEEK
|
|
ANDI 0x0F
|
|
ORW scratch
|
|
POKE yVel
|
|
LD xVel
|
|
PEEK
|
|
ANDI 0x0F
|
|
POKE xVel ; xvel high nibble = 0
|
|
RET ; yvel high nibble = xVel&0xF0
|
|
|
|
; position += velocity
|
|
velocity LDW xPos
|
|
PEEK
|
|
STW scratch
|
|
LDW xVel
|
|
PEEK
|
|
ANDI 0x0F
|
|
SUBI 0x08 ; {0x0...0xF} -> {-8...+8} - {0}
|
|
BLT x_vel0
|
|
ADDI 0x01
|
|
x_vel0 ADDW scratch
|
|
POKE xPos
|
|
|
|
LDW yPos
|
|
PEEK
|
|
STW scratch
|
|
LDW yVel
|
|
PEEK
|
|
ANDI 0x0F
|
|
SUBI 0x08 ; {0x0...0xF} -> {-8...+8} - {0}
|
|
BLT y_vel0
|
|
ADDI 0x01
|
|
y_vel0 ADDW scratch
|
|
POKE yPos
|
|
RET
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; clears the viewable screen
|
|
clearScreen LDWI SYS_Draw4_30 ; setup 4 pixel SYS routine
|
|
STW giga_sysFn
|
|
LDWI 0x0000 ; 4 pixels of colour
|
|
STW giga_sysArg0
|
|
STW giga_sysArg2
|
|
|
|
LDI giga_yres / 2 ; counters
|
|
ST jj
|
|
LDI giga_xres / 4
|
|
ST ii
|
|
|
|
LDWI 0x0800 ; top line
|
|
STW xx
|
|
LDWI 0x7F00 ; bottom line
|
|
STW kk
|
|
PUSH ; save clearScreen's caller return address
|
|
CALL clearScreen_0 ; jump to clearScreen_0
|
|
|
|
; clear left and right edge single pixel vertical strips, (for screen shake)
|
|
clearStrips STW scratch
|
|
LDI 0x00
|
|
POKE scratch
|
|
LDW scratch
|
|
ADDI 0x5F
|
|
STW scratch
|
|
LDI 0x00
|
|
POKE scratch
|
|
RET
|
|
|
|
clearScreen_0 POP ; restore clearScreen's caller return address
|
|
clearS_loop LDW xx
|
|
STW giga_sysArg4 ; top line
|
|
SYS 30
|
|
|
|
LDW kk
|
|
STW giga_sysArg4 ; bottom line
|
|
SYS 30
|
|
|
|
LD xx ; 4 horizontal pixels
|
|
ADDI 0x04
|
|
ST xx
|
|
LD kk ; 4 horizontal pixels
|
|
ADDI 0x04
|
|
ST kk
|
|
LoopCounterTo1 ii clearS_loop
|
|
|
|
; clear one extra pixel wide stripes for screen shake
|
|
PUSH ; top
|
|
LDW xx
|
|
CALL clearStrips
|
|
POP
|
|
PUSH ; bottom
|
|
LDW kk
|
|
CALL clearStrips
|
|
POP
|
|
|
|
INC yy ; next top line
|
|
LD ll ; next bottom line
|
|
SUBI 0x01
|
|
ST ll
|
|
|
|
LDI 0x00 ; reset xx, kk and ii
|
|
ST xx
|
|
ST kk
|
|
LDI giga_xres / 4
|
|
ST ii
|
|
LoopCounterTo1 jj clearS_loop
|
|
RET
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
resetAudio LDWI 0x0000
|
|
STW midiCommand
|
|
STW midiDelay
|
|
STW midiNote
|
|
LDWI giga_soundChan1 + 2 ; keyL, keyH
|
|
STW midiChannel
|
|
STW midiScratch
|
|
LDWI ffe00 ; midi score
|
|
STW midiStreamPtr
|
|
|
|
LDI 0x04
|
|
ST ii
|
|
|
|
resetA_loop LDI giga_soundChan1 ; reset low byte
|
|
ST midiScratch
|
|
LDWI 0x0300
|
|
DOKE midiScratch ; wavA and wavX
|
|
INC midiScratch
|
|
INC midiScratch
|
|
LDWI 0x0000
|
|
DOKE midiScratch ; keyL and keyH
|
|
INC midiScratch
|
|
INC midiScratch
|
|
DOKE midiScratch ; oscL and oscH
|
|
INC midiScratch + 1 ; increment high byte
|
|
LoopCounterTo1 ii resetA_loop
|
|
RET
|
|
|
|
|
|
playMidi LDI 0x10 ; keep pumping soundTimer, so that global sound stays alive
|
|
ST giga_soundTimer
|
|
LD giga_frameCount
|
|
SUBW midiDelay
|
|
BEQ playM_start
|
|
RET
|
|
|
|
playM_start PUSH
|
|
playM_process LDW midiStreamPtr
|
|
PEEK ; get midi stream byte
|
|
STW midiCommand
|
|
LDW midiStreamPtr
|
|
ADDI 0x01
|
|
STW midiStreamPtr
|
|
LDI 0xF0
|
|
ANDW midiCommand
|
|
XORI 0x90 ; check for start note
|
|
BNE playM_endnote
|
|
|
|
CALL midiStartNote ; start note
|
|
BRA playM_process
|
|
|
|
playM_endnote XORI 0x10 ; check for end note
|
|
BNE playM_segment
|
|
|
|
CALL midiEndNote ; end note
|
|
BRA playM_process
|
|
|
|
|
|
playM_segment XORI 0x50 ; check for new segment
|
|
BNE playM_delay
|
|
|
|
LDW midiStreamPtr ; midi score
|
|
DEEK
|
|
STW midiStreamPtr ; 0xD0 new midi segment address
|
|
BRA playM_process
|
|
|
|
playM_delay LD giga_frameCount ; midiDelay = (midiCommand + peek(frameCount)) & 0x00FF
|
|
ADDW midiCommand
|
|
ST midiDelay
|
|
POP
|
|
RET
|
|
|
|
|
|
midiStartNote LDWI giga_notesTable ; note table in ROM
|
|
STW midiScratch
|
|
LDW midiStreamPtr ; ROM pointer = (Peek(midiStreamPtr) - 11)*2) + giga_notesTable
|
|
PEEK
|
|
SUBI 11
|
|
LSLW
|
|
ADDW midiScratch
|
|
STW midiScratch
|
|
LUP 0x00 ; get ROM midi note low byte
|
|
ST midiNote
|
|
LDW midiScratch
|
|
LUP 0x01 ; get ROM midi note high byte
|
|
ST midiNote + 1
|
|
LDW midiCommand
|
|
ANDI 0x03 ; get channel
|
|
ST midiScratch + 1
|
|
LDI 0x00
|
|
ST midiScratch
|
|
LDW midiScratch
|
|
ADDW midiChannel ; channel address
|
|
STW midiScratch
|
|
LDW midiNote
|
|
DOKE midiScratch ; set note
|
|
LDW midiStreamPtr
|
|
ADDI 0x01 ; midiStreamPtr++
|
|
STW midiStreamPtr
|
|
RET
|
|
|
|
|
|
midiEndNote LDW midiCommand
|
|
ANDI 0x03 ; get channel
|
|
ST midiScratch + 1
|
|
LDI 0x00
|
|
ST midiScratch
|
|
LDW midiScratch
|
|
ADDW midiChannel ; channel address
|
|
STW midiScratch
|
|
LDWI 0x0000
|
|
DOKE midiScratch ; end note
|
|
RET
|
|
|
|
|
|
%include midi.i
|