Compare commits
2 commits
23fcb4ce95
...
808dd7c045
Author | SHA1 | Date | |
---|---|---|---|
|
808dd7c045 | ||
|
334e575752 |
5
tsfm_speccy_player/!build.bat
Normal file
5
tsfm_speccy_player/!build.bat
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
@echo off
|
||||||
|
bas2tap -a10 -spsgplay loader.bas loader.tap
|
||||||
|
sjasmplus main.asm --lst=main.lst
|
||||||
|
copy /b loader.tap+player.tap "moebius.tap"
|
||||||
|
pause
|
5
tsfm_speccy_player/.gitignore
vendored
Normal file
5
tsfm_speccy_player/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
*.tap
|
||||||
|
*.sna
|
||||||
|
*.obj
|
||||||
|
*.exe
|
||||||
|
*.lst
|
3
tsfm_speccy_player/loader.bas
Normal file
3
tsfm_speccy_player/loader.bas
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
10 BORDER 0 : PAPER 7 : INK 7 : CLEAR 24575
|
||||||
|
20 LOAD "moebius" CODE
|
||||||
|
100 RANDOMIZE USR 33155
|
229
tsfm_speccy_player/main.asm
Normal file
229
tsfm_speccy_player/main.asm
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
; moe-bius - zx/tsfm player
|
||||||
|
; --atemka 14.o8.2o25
|
||||||
|
|
||||||
|
device zxspectrum128
|
||||||
|
|
||||||
|
ivt equ 0x8000
|
||||||
|
isr equ 0x8181
|
||||||
|
codestart equ 0x8080
|
||||||
|
|
||||||
|
reg_buffer equ 0x5B00 ; basic variables :meatjob:
|
||||||
|
|
||||||
|
EMPTYTAP "player.tap"
|
||||||
|
|
||||||
|
; IM2 vector table - all 257 values for floating bus condition
|
||||||
|
org ivt
|
||||||
|
block 257, (isr >> 8) ; isr at 0x8181
|
||||||
|
|
||||||
|
; dummy ISR (vblank synchronization is done by HALT)
|
||||||
|
org isr
|
||||||
|
stack_top:
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
|
||||||
|
; entrypoint
|
||||||
|
start:
|
||||||
|
di
|
||||||
|
ld sp, stack_top
|
||||||
|
|
||||||
|
; set IM2 vector table to 0x80
|
||||||
|
ld a, high ivt
|
||||||
|
ld i, a
|
||||||
|
im 2
|
||||||
|
|
||||||
|
; enable interrupts
|
||||||
|
ei
|
||||||
|
.loop:
|
||||||
|
halt
|
||||||
|
|
||||||
|
; output OPN registers
|
||||||
|
; TODO
|
||||||
|
ld hl, test_dump
|
||||||
|
call player.reg_out
|
||||||
|
di
|
||||||
|
halt
|
||||||
|
|
||||||
|
; draw VU meters
|
||||||
|
.base = 0x4000 + 2048*2 + 32*6 + 19
|
||||||
|
ld bc, .base + 0 ; 10
|
||||||
|
call vumeter.draw_0 ; 17
|
||||||
|
.vu0 equ $-2
|
||||||
|
ld bc, .base + 2 ; 10
|
||||||
|
call vumeter.draw_0 ; 17
|
||||||
|
.vu1 equ $-2
|
||||||
|
ld bc, .base + 4 ; 10
|
||||||
|
call vumeter.draw_0 ; 17
|
||||||
|
.vu2 equ $-2
|
||||||
|
ld bc, .base + 7 ; 10
|
||||||
|
call vumeter.draw_0 ; 17
|
||||||
|
.vu3 equ $-2
|
||||||
|
ld bc, .base + 9 ; 10
|
||||||
|
call vumeter.draw_0 ; 17
|
||||||
|
.vu4 equ $-2
|
||||||
|
ld bc, .base + 11 ; 10
|
||||||
|
call vumeter.draw_0 ; 17
|
||||||
|
.vu5 equ $-2
|
||||||
|
|
||||||
|
; and jump to next frame
|
||||||
|
xor a : ld bc, 0x7FFD : out (c), a ; map fast page to fix 128k AY ports contention
|
||||||
|
jp .loop
|
||||||
|
|
||||||
|
test_dump:
|
||||||
|
db 0x2F, 0xFF ; prescaler reg
|
||||||
|
db 0x2D, 0xFF ; prescaler reg
|
||||||
|
db 0x30, 0x01
|
||||||
|
db 0x34, 0x21
|
||||||
|
db 0x38, 0x52
|
||||||
|
db 0x3C, 0x02
|
||||||
|
db 0x40, 0x32
|
||||||
|
db 0x44, 0x17
|
||||||
|
db 0x48, 0x1C
|
||||||
|
db 0x4C, 0x03
|
||||||
|
db 0x50, 0x1F
|
||||||
|
db 0x54, 0x1F
|
||||||
|
db 0x58, 0x1F
|
||||||
|
db 0x5C, 0x1F
|
||||||
|
db 0x60, 0x08
|
||||||
|
db 0x64, 0x0C
|
||||||
|
db 0x68, 0x11
|
||||||
|
db 0x6C, 0x09
|
||||||
|
db 0x70, 0x00
|
||||||
|
db 0x74, 0x00
|
||||||
|
db 0x78, 0x01
|
||||||
|
db 0x7C, 0x00
|
||||||
|
db 0x80, 0xC0
|
||||||
|
db 0x84, 0xB1
|
||||||
|
db 0x88, 0x52
|
||||||
|
db 0x8C, 0xF4
|
||||||
|
db 0x90, 0x00
|
||||||
|
db 0x94, 0x00
|
||||||
|
db 0x98, 0x00
|
||||||
|
db 0x9C, 0x00
|
||||||
|
db 0xB0, 0x28
|
||||||
|
db 0x28, 0x00
|
||||||
|
db 0xA4, 0x0C
|
||||||
|
db 0xA0, 0xA3
|
||||||
|
db 0x28, 0xF0
|
||||||
|
db -1
|
||||||
|
|
||||||
|
|
||||||
|
; ----------------------------------------------------
|
||||||
|
; vu meters
|
||||||
|
; orig by natt, rewritten by me
|
||||||
|
|
||||||
|
vumeter:
|
||||||
|
ld a, 0
|
||||||
|
call .get_address
|
||||||
|
ld [start.vu0], hl
|
||||||
|
ld a, 1
|
||||||
|
call .get_address
|
||||||
|
ld [start.vu1], hl
|
||||||
|
ld a, 2
|
||||||
|
call .get_address
|
||||||
|
ld [start.vu2], hl
|
||||||
|
ld a, 3
|
||||||
|
call .get_address
|
||||||
|
ld [start.vu3], hl
|
||||||
|
ld a, 4
|
||||||
|
call .get_address
|
||||||
|
ld [start.vu4], hl
|
||||||
|
ld a, 5
|
||||||
|
call .get_address
|
||||||
|
ld [start.vu5], hl
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
; DE - screen pos, A - register value
|
||||||
|
.get_address:
|
||||||
|
bit 4, a
|
||||||
|
jp nz, .get_e
|
||||||
|
and 0x0E
|
||||||
|
ld h, high .calltab
|
||||||
|
ld l, a
|
||||||
|
ld e, [hl] : inc l
|
||||||
|
ld d, [hl]
|
||||||
|
exd
|
||||||
|
ret
|
||||||
|
.get_e:
|
||||||
|
ld hl, .draw_e
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ------------------
|
||||||
|
; drawing routines
|
||||||
|
; DE - dst
|
||||||
|
.draw_e:
|
||||||
|
ld a, 0b00000000 : ld [bc], a : inc b ; 18
|
||||||
|
ld a, 0b11111111 : ld [bc], a : inc b ; 18
|
||||||
|
ld a, 0b11000011 : ld [bc], a : inc b ; 18
|
||||||
|
ld a, 0b11011111 : ld [bc], a : inc b ; 18
|
||||||
|
ld a, 0b11000111 : ld [bc], a : inc b ; 18
|
||||||
|
ld a, 0b11011111 : ld [bc], a : inc b ; 18
|
||||||
|
ld a, 0b11000011 : ld [bc], a : inc b ; 18
|
||||||
|
ld a, 0b11111111 : ld [bc], a : ret ; 24 = 150t per char
|
||||||
|
|
||||||
|
.draw_0:
|
||||||
|
.draw_1:
|
||||||
|
dup 7 : ld a, 0x00 : ld [bc], a : inc b : edup ; 18*7
|
||||||
|
dup 1 : ld a, 0x00 : ld [bc], a : ret : edup ; 24*1
|
||||||
|
.draw_2:
|
||||||
|
dup 6 : ld a, 0x00 : ld [bc], a : inc b : edup ; 18*6
|
||||||
|
dup 1 : ld a, 0xFF : ld [bc], a : inc b : edup ; 18*1
|
||||||
|
dup 1 : ld a, 0xFF : ld [bc], a : ret : edup ; 24
|
||||||
|
.draw_3:
|
||||||
|
dup 5 : ld a, 0x00 : ld [bc], a : inc b : edup ; 18*5
|
||||||
|
dup 2 : ld a, 0xFF : ld [bc], a : inc b : edup ; 18*2
|
||||||
|
dup 1 : ld a, 0xFF : ld [bc], a : ret : edup ; 24
|
||||||
|
.draw_4:
|
||||||
|
dup 4 : ld a, 0x00 : ld [bc], a : inc b : edup ; 18*4
|
||||||
|
dup 3 : ld a, 0xFF : ld [bc], a : inc b : edup ; 18*3
|
||||||
|
dup 1 : ld a, 0xFF : ld [bc], a : ret : edup ; 24
|
||||||
|
.draw_5:
|
||||||
|
dup 3 : ld a, 0x00 : ld [bc], a : inc b : edup ; 18*3
|
||||||
|
dup 4 : ld a, 0xFF : ld [bc], a : inc b : edup ; 18*4
|
||||||
|
dup 1 : ld a, 0xFF : ld [bc], a : ret : edup ; 24
|
||||||
|
.draw_6:
|
||||||
|
dup 2 : ld a, 0x00 : ld [bc], a : inc b : edup ; 18*2
|
||||||
|
dup 5 : ld a, 0xFF : ld [bc], a : inc b : edup ; 18*5
|
||||||
|
dup 1 : ld a, 0xFF : ld [bc], a : ret : edup ; 24
|
||||||
|
.draw_7:
|
||||||
|
dup 1 : ld a, 0x00 : ld [bc], a : inc b : edup ; 18*1
|
||||||
|
dup 6 : ld a, 0xFF : ld [bc], a : inc b : edup ; 18*6
|
||||||
|
dup 1 : ld a, 0xFF : ld [bc], a : ret : edup ; 24
|
||||||
|
|
||||||
|
align 256
|
||||||
|
.calltab:
|
||||||
|
dw .draw_0, .draw_1, .draw_2, .draw_3, .draw_4, .draw_5, .draw_6, .draw_7
|
||||||
|
|
||||||
|
; player include
|
||||||
|
include "player.asm"
|
||||||
|
|
||||||
|
code_end
|
||||||
|
|
||||||
|
; -------------------------------------------------
|
||||||
|
; music pages
|
||||||
|
page 0
|
||||||
|
emptytap "page0.tap"
|
||||||
|
org 0xC000
|
||||||
|
align 256
|
||||||
|
;incbin "!music/200_percent_partyfinal.2.6.psg.packed"
|
||||||
|
savetap "page0.tap",CODE,"page0",0xC000,$-0xC000
|
||||||
|
|
||||||
|
|
||||||
|
; splash screen
|
||||||
|
emptytap "splash.tap"
|
||||||
|
org 0x4000
|
||||||
|
splash:
|
||||||
|
block 6144, 0
|
||||||
|
block 768, (0<<3)|(7<<0)
|
||||||
|
;incbin "200a.scr"
|
||||||
|
savetap "splash.tap",CODE,"splash",0x4000,$-0x4000
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
; ----------------------------------------------------
|
||||||
|
total_codelength equ code_end-codestart
|
||||||
|
|
||||||
|
display "total: ", /a, total_codelength, " bytes"
|
||||||
|
|
||||||
|
savesna "moebius.sna", start
|
||||||
|
savetap "player.tap",CODE,"moebius",codestart,total_codelength
|
||||||
|
|
176
tsfm_speccy_player/opmfile.inc
Normal file
176
tsfm_speccy_player/opmfile.inc
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
; OPM v0 stream data, stream-independent commands
|
||||||
|
OPM_STREAM_END_FRAME equ 0xFF ; end of frame, next channel
|
||||||
|
OPM_STREAM_END equ 0xFE ; end of stream, stop here or loop to OPM_STREAM_LOOP stream point
|
||||||
|
OPM_STREAM_NOP equ 0xFD ; nop
|
||||||
|
OPM_STREAM_NEW_ORDER equ 0xFC ; nop, marks new order
|
||||||
|
OPM_STREAM_SET_FRAME_RATE equ 0xFB ; word rate (as in opm_header_t::frame_rate)
|
||||||
|
OPM_STREAM_LOOP equ 0xFA ; set loop point here
|
||||||
|
|
||||||
|
; delay commands
|
||||||
|
OPM_STREAM_DELAY_INT32 equ 0xF9 ; dword delay
|
||||||
|
OPM_STREAM_DELAY_INT16 equ 0xF8 ; word delay
|
||||||
|
OPM_STREAM_DELAY_INT12 equ 0xD0 ; D0..DF - 0..4095 frames delay (hibyte in low 4 bits of command)
|
||||||
|
OPM_STREAM_DELAY_SHORT equ 0xC0 ; C0..CF - 1..16 frames delay
|
||||||
|
|
||||||
|
; back reference
|
||||||
|
OPM_STREAM_BACKREF equ 0xE0 ; E0..EF - word backrefpos (12 bit), byte frames
|
||||||
|
|
||||||
|
; OPN control stream commands
|
||||||
|
OPM_CTRL_EXTCH3 equ 0x00 ; 00..7F - ext. CH3 op1-3 frequency
|
||||||
|
OPM_CTRL_TIMER_CSM equ 0x80 ; 80..9F - set timer/CSM/LFO frequency
|
||||||
|
OPM_CTRL_RHYTHM equ 0xA0 ; A0..BF - rhythm control
|
||||||
|
|
||||||
|
OPM_CTRL_CMD80_REG25 equ (1 << 0) ;
|
||||||
|
OPM_CTRL_CMD80_REG25_BIT equ 0 ; shift value for OPM_CTRL_CMD80_REG25
|
||||||
|
OPM_CTRL_CMD80_REG24 equ (1 << 1) ;
|
||||||
|
OPM_CTRL_CMD80_REG24_BIT equ 1 ; shift value for OPM_CTRL_CMD80_REG24
|
||||||
|
OPM_CTRL_CMD80_REG27 equ (1 << 2) ;
|
||||||
|
OPM_CTRL_CMD80_REG27_BIT equ 2 ; shift value for OPM_CTRL_CMD80_REG27
|
||||||
|
OPM_CTRL_CMD80_REG22 equ (1 << 3) ;
|
||||||
|
OPM_CTRL_CMD80_REG22_BIT equ 3 ; shift value for OPM_CTRL_CMD80_REG22
|
||||||
|
OPM_CTRL_CMD80_EOF equ (1 << 4) ;
|
||||||
|
OPM_CTRL_CMD80_EOF_BIT equ 4 ; shift value for OPM_CTRL_CMD80_EOF
|
||||||
|
|
||||||
|
OPM_CTRL_EXTCH3_OP1_HIGH equ (1 << 0) ;
|
||||||
|
OPM_CTRL_EXTCH3_OP1_HIGH_BIT equ 0 ; shift value for OPM_CTRL_EXTCH3_OP1_HIGH
|
||||||
|
OPM_CTRL_EXTCH3_OP1_LOW equ (1 << 1) ;
|
||||||
|
OPM_CTRL_EXTCH3_OP1_LOW_BIT equ 1 ; shift value for OPM_CTRL_EXTCH3_OP1_LOW
|
||||||
|
OPM_CTRL_EXTCH3_OP2_HIGH equ (1 << 2) ;
|
||||||
|
OPM_CTRL_EXTCH3_OP2_HIGH_BIT equ 2 ; shift value for OPM_CTRL_EXTCH3_OP2_HIGH
|
||||||
|
OPM_CTRL_EXTCH3_OP2_LOW equ (1 << 3) ;
|
||||||
|
OPM_CTRL_EXTCH3_OP2_LOW_BIT equ 3 ; shift value for OPM_CTRL_EXTCH3_OP2_LOW
|
||||||
|
OPM_CTRL_EXTCH3_OP3_HIGH equ (1 << 4) ;
|
||||||
|
OPM_CTRL_EXTCH3_OP3_HIGH_BIT equ 4 ; shift value for OPM_CTRL_EXTCH3_OP3_HIGH
|
||||||
|
OPM_CTRL_EXTCH3_OP3_LOW equ (1 << 5) ;
|
||||||
|
OPM_CTRL_EXTCH3_OP3_LOW_BIT equ 5 ; shift value for OPM_CTRL_EXTCH3_OP3_LOW
|
||||||
|
OPM_CTRL_EXTCH3_EOF equ (1 << 6) ;
|
||||||
|
OPM_CTRL_EXTCH3_EOF_BIT equ 6 ; shift value for OPM_CTRL_EXTCH3_EOF
|
||||||
|
|
||||||
|
OPM_CTRL_CMDA0_REG_MASK equ (0x0F << 0) ;
|
||||||
|
OPM_CTRL_CMDA0_REG_MASK_BIT equ 0 ; shift value for OPM_CTRL_CMDA0_REG_MASK
|
||||||
|
OPM_CTRL_CMDA0_EOF equ (1 << 4) ;
|
||||||
|
OPM_CTRL_CMDA0_EOF_BIT equ 4 ; shift value for OPM_CTRL_CMDA0_EOF
|
||||||
|
|
||||||
|
; OPN FM stream commands
|
||||||
|
OPM_FM_ADSR equ 0x00 ; 00..3F - set ADSR
|
||||||
|
OPM_FM_MUL_TL_EG equ 0x40 ; 40..7F - set MULT/TL/SSG-EG
|
||||||
|
OPM_FM_FREQ_FB_PAN equ 0x80 ; 80..9F - set frequency/feedback/panning
|
||||||
|
OPM_FM_KEY equ 0xA0 ; A0..BF - key on/off
|
||||||
|
|
||||||
|
OPM_FM_CMD00_REG50 equ (1 << 0) ;
|
||||||
|
OPM_FM_CMD00_REG50_BIT equ 0 ; shift value for OPM_FM_CMD00_REG50
|
||||||
|
OPM_FM_CMD00_REG60 equ (1 << 1) ;
|
||||||
|
OPM_FM_CMD00_REG60_BIT equ 1 ; shift value for OPM_FM_CMD00_REG60
|
||||||
|
OPM_FM_CMD00_REG70 equ (1 << 2) ;
|
||||||
|
OPM_FM_CMD00_REG70_BIT equ 2 ; shift value for OPM_FM_CMD00_REG70
|
||||||
|
OPM_FM_CMD00_REG80 equ (1 << 3) ;
|
||||||
|
OPM_FM_CMD00_REG80_BIT equ 3 ; shift value for OPM_FM_CMD00_REG80
|
||||||
|
OPM_FM_CMD00_OP_MASK equ (3 << 4) ;
|
||||||
|
OPM_FM_CMD00_OP_MASK_BIT equ 4 ; shift value for OPM_FM_CMD00_OP_MASK
|
||||||
|
|
||||||
|
OPM_FM_CMD40_REG30 equ (1 << 0) ;
|
||||||
|
OPM_FM_CMD40_REG30_BIT equ 0 ; shift value for OPM_FM_CMD40_REG30
|
||||||
|
OPM_FM_CMD40_REG40 equ (1 << 1) ;
|
||||||
|
OPM_FM_CMD40_REG40_BIT equ 1 ; shift value for OPM_FM_CMD40_REG40
|
||||||
|
OPM_FM_CMD40_REG90 equ (1 << 2) ;
|
||||||
|
OPM_FM_CMD40_REG90_BIT equ 2 ; shift value for OPM_FM_CMD40_REG90
|
||||||
|
OPM_FM_CMD40_EOF equ (1 << 3) ;
|
||||||
|
OPM_FM_CMD40_EOF_BIT equ 3 ; shift value for OPM_FM_CMD40_EOF
|
||||||
|
OPM_FM_CMD40_OP_SHIFT equ 4 ;
|
||||||
|
OPM_FM_CMD40_OP_MASK equ (3 << 4) ;
|
||||||
|
OPM_FM_CMD40_OP_MASK_BIT equ 4 ; shift value for OPM_FM_CMD40_OP_MASK
|
||||||
|
|
||||||
|
OPM_FM_CMD80_REGA4 equ (1 << 0) ;
|
||||||
|
OPM_FM_CMD80_REGA4_BIT equ 0 ; shift value for OPM_FM_CMD80_REGA4
|
||||||
|
OPM_FM_CMD80_REGA0 equ (1 << 1) ;
|
||||||
|
OPM_FM_CMD80_REGA0_BIT equ 1 ; shift value for OPM_FM_CMD80_REGA0
|
||||||
|
OPM_FM_CMD80_REGB0 equ (1 << 2) ;
|
||||||
|
OPM_FM_CMD80_REGB0_BIT equ 2 ; shift value for OPM_FM_CMD80_REGB0
|
||||||
|
OPM_FM_CMD80_REGB4 equ (1 << 3) ;
|
||||||
|
OPM_FM_CMD80_REGB4_BIT equ 3 ; shift value for OPM_FM_CMD80_REGB4
|
||||||
|
OPM_FM_CMD80_EOF equ (1 << 4) ;
|
||||||
|
OPM_FM_CMD80_EOF_BIT equ 4 ; shift value for OPM_FM_CMD80_EOF
|
||||||
|
|
||||||
|
OPM_FM_CMDA0_OP_SHIFT equ 0 ;
|
||||||
|
OPM_FM_CMDA0_OP_MASK equ (0x0F << 0) ;
|
||||||
|
OPM_FM_CMDA0_OP_MASK_BIT equ 0 ; shift value for OPM_FM_CMDA0_OP_MASK
|
||||||
|
OPM_FM_CMDA0_EOF equ (1 << 4) ;
|
||||||
|
OPM_FM_CMDA0_EOF_BIT equ 4 ; shift value for OPM_FM_CMDA0_EOF
|
||||||
|
|
||||||
|
; OPNA rhythm channel stream
|
||||||
|
OPN_RHYTHM_KEY equ 0x00 ; 00..7F - key on
|
||||||
|
OPN_RHYTHM_REGS1 equ 0x80 ; 80..9F - write reg set 1
|
||||||
|
OPN_RHYTHM_REGS2 equ 0xA0 ; A0..BF - write reg set 2
|
||||||
|
|
||||||
|
OPN_RHYTHM_KEY_EOF equ (1 << 6) ;
|
||||||
|
OPN_RHYTHM_KEY_EOF_BIT equ 6 ; shift value for OPN_RHYTHM_KEY_EOF
|
||||||
|
OPN_RHYTHM_CMD80_REG10 equ (1 << 0) ;
|
||||||
|
OPN_RHYTHM_CMD80_REG10_BIT equ 0 ; shift value for OPN_RHYTHM_CMD80_REG10
|
||||||
|
OPN_RHYTHM_CMD80_REG11 equ (1 << 1) ;
|
||||||
|
OPN_RHYTHM_CMD80_REG11_BIT equ 1 ; shift value for OPN_RHYTHM_CMD80_REG11
|
||||||
|
OPN_RHYTHM_CMD80_REG18 equ (1 << 2) ;
|
||||||
|
OPN_RHYTHM_CMD80_REG18_BIT equ 2 ; shift value for OPN_RHYTHM_CMD80_REG18
|
||||||
|
OPN_RHYTHM_CMD80_REG19 equ (1 << 3) ;
|
||||||
|
OPN_RHYTHM_CMD80_REG19_BIT equ 3 ; shift value for OPN_RHYTHM_CMD80_REG19
|
||||||
|
OPN_RHYTHM_CMDA0_REG1A equ (1 << 0) ;
|
||||||
|
OPN_RHYTHM_CMDA0_REG1A_BIT equ 0 ; shift value for OPN_RHYTHM_CMDA0_REG1A
|
||||||
|
OPN_RHYTHM_CMDA0_REG1B equ (1 << 1) ;
|
||||||
|
OPN_RHYTHM_CMDA0_REG1B_BIT equ 1 ; shift value for OPN_RHYTHM_CMDA0_REG1B
|
||||||
|
OPN_RHYTHM_CMDA0_REG1C equ (1 << 2) ;
|
||||||
|
OPN_RHYTHM_CMDA0_REG1C_BIT equ 2 ; shift value for OPN_RHYTHM_CMDA0_REG1C
|
||||||
|
OPN_RHYTHM_CMDA0_REG1D equ (1 << 3) ;
|
||||||
|
OPN_RHYTHM_CMDA0_REG1D_BIT equ 3 ; shift value for OPN_RHYTHM_CMDA0_REG1D
|
||||||
|
OPN_RHYTHM_REGS_EOF equ (1 << 4) ;
|
||||||
|
OPN_RHYTHM_REGS_EOF_BIT equ 4 ; shift value for OPN_RHYTHM_REGS_EOF
|
||||||
|
|
||||||
|
; OPN SSG tone stream commands (shared with AY chip type)
|
||||||
|
OPM_AYTONE_REGS equ 0x00 ; 00..7F - set volume and period low
|
||||||
|
OPM_AYTONE_PERIOD equ 0x80 ; 80..BF - set period
|
||||||
|
OPM_AYTONE_MASK equ 0xF0 ; F0..F7 - set tone/noise mask
|
||||||
|
|
||||||
|
OPM_AYTONE_CMD00_VOLUME_MASK equ (0x1F << 0) ;
|
||||||
|
OPM_AYTONE_CMD00_VOLUME_MASK_BIT equ 0 ; shift value for OPM_AYTONE_CMD00_VOLUME_MASK
|
||||||
|
OPM_AYTONE_CMD00_PERIOD_LOW equ (1 << 5) ;
|
||||||
|
OPM_AYTONE_CMD00_PERIOD_LOW_BIT equ 5 ; shift value for OPM_AYTONE_CMD00_PERIOD_LOW
|
||||||
|
OPM_AYTONE_CMD00_EOF equ (1 << 6) ;
|
||||||
|
OPM_AYTONE_CMD00_EOF_BIT equ 6 ; shift value for OPM_AYTONE_CMD00_EOF
|
||||||
|
|
||||||
|
OPM_AYTONE_CMD80_PERIOD_HIGH equ (0xF << 0) ;
|
||||||
|
OPM_AYTONE_CMD80_PERIOD_HIGH_BIT equ 0 ; shift value for OPM_AYTONE_CMD80_PERIOD_HIGH
|
||||||
|
OPM_AYTONE_CMD80_PERIOD_LOW equ (1 << 4) ;
|
||||||
|
OPM_AYTONE_CMD80_PERIOD_LOW_BIT equ 4 ; shift value for OPM_AYTONE_CMD80_PERIOD_LOW
|
||||||
|
OPM_AYTONE_CMD80_EOF equ (1 << 5) ;
|
||||||
|
OPM_AYTONE_CMD80_EOF_BIT equ 5 ; shift value for OPM_AYTONE_CMD80_EOF
|
||||||
|
|
||||||
|
OPM_AYTONE_MASK_TONE equ (1 << 0) ;
|
||||||
|
OPM_AYTONE_MASK_TONE_BIT equ 0 ; shift value for OPM_AYTONE_MASK_TONE
|
||||||
|
OPM_AYTONE_MASK_NOISE equ (1 << 1) ;
|
||||||
|
OPM_AYTONE_MASK_NOISE_BIT equ 1 ; shift value for OPM_AYTONE_MASK_NOISE
|
||||||
|
OPM_AYTONE_MASK_EOF equ (1 << 2) ;
|
||||||
|
OPM_AYTONE_MASK_EOF_BIT equ 2 ; shift value for OPM_AYTONE_MASK_EOF
|
||||||
|
|
||||||
|
; OPN SSG envelope/noise stream commands (shared with AY chip type)
|
||||||
|
OPM_AYENV_REGS equ 0x00 ; 00..7F - set noise and period low
|
||||||
|
OPM_AYENV_ENVTYPE equ 0x80 ; 80..BF - set env type and period low
|
||||||
|
OPM_AYENV_PERIOD_FULL equ 0xF0 ; F0..F7 - set full envelope period
|
||||||
|
|
||||||
|
OPM_AYENV_CMD00_NOISE_MASK equ (0x1F << 0) ;
|
||||||
|
OPM_AYENV_CMD00_NOISE_MASK_BIT equ 0 ; shift value for OPM_AYENV_CMD00_NOISE_MASK
|
||||||
|
OPM_AYENV_CMD00_PERIOD_LOW equ (1 << 5) ;
|
||||||
|
OPM_AYENV_CMD00_PERIOD_LOW_BIT equ 5 ; shift value for OPM_AYENV_CMD00_PERIOD_LOW
|
||||||
|
OPM_AYENV_CMD00_EOF equ (1 << 6) ;
|
||||||
|
OPM_AYENV_CMD00_EOF_BIT equ 6 ; shift value for OPM_AYENV_CMD00_EOF
|
||||||
|
|
||||||
|
OPM_AYENV_CMD80_ENV_TYPE equ (0xF << 0) ;
|
||||||
|
OPM_AYENV_CMD80_ENV_TYPE_BIT equ 0 ; shift value for OPM_AYENV_CMD80_ENV_TYPE
|
||||||
|
OPM_AYENV_CMD80_PERIOD_LOW equ (1 << 4) ;
|
||||||
|
OPM_AYENV_CMD80_PERIOD_LOW_BIT equ 4 ; shift value for OPM_AYENV_CMD80_PERIOD_LOW
|
||||||
|
OPM_AYENV_CMD80_EOF equ (1 << 5) ;
|
||||||
|
OPM_AYENV_CMD80_EOF_BIT equ 5 ; shift value for OPM_AYENV_CMD80_EOF
|
||||||
|
|
||||||
|
OPM_AYENV_CMDF0_PERIOD_LOW equ (1 << 0) ;
|
||||||
|
OPM_AYENV_CMDF0_PERIOD_LOW_BIT equ 0 ; shift value for OPM_AYENV_CMDF0_PERIOD_LOW
|
||||||
|
OPM_AYENV_CMDF0_PERIOD_HIGH equ (1 << 1) ;
|
||||||
|
OPM_AYENV_CMDF0_PERIOD_HIGH_BIT equ 1 ; shift value for OPM_AYENV_CMDF0_PERIOD_HIGH
|
||||||
|
OPM_AYENV_CMDF0_EOF equ (1 << 2) ;
|
||||||
|
OPM_AYENV_CMDF0_EOF_BIT equ 2 ; shift value for OPM_AYENV_CMDF0_EOF
|
566
tsfm_speccy_player/player.asm
Normal file
566
tsfm_speccy_player/player.asm
Normal file
|
@ -0,0 +1,566 @@
|
||||||
|
; if this code looks like HLL vomit, you're pretty close
|
||||||
|
; i used index registers since speed is not critical, it's a music compo player after all ;)
|
||||||
|
|
||||||
|
include "opmfile.inc"
|
||||||
|
|
||||||
|
module player
|
||||||
|
|
||||||
|
MAX_CHANNELS equ 16
|
||||||
|
MAX_STACK_DEPTH equ 4
|
||||||
|
|
||||||
|
; channel structures format
|
||||||
|
struct channel_stack_t
|
||||||
|
ptr dw 0
|
||||||
|
frames_to_play dw 0
|
||||||
|
ends
|
||||||
|
|
||||||
|
struct channel_struct_t
|
||||||
|
page db 0 ; base page with stream data
|
||||||
|
ptr dw 0 ; current pointer
|
||||||
|
frames_to_play dw -1 ; used for stack popping
|
||||||
|
delay dw 1
|
||||||
|
reload dw 1
|
||||||
|
stack_pos db 0 ; stack offset
|
||||||
|
stack block channel_stack_t*MAX_STACK_DEPTH, 0 ; stack
|
||||||
|
|
||||||
|
; reg cache
|
||||||
|
reg_extch3_fhi block 3, 0 ; extch3 block/fnum-high reg
|
||||||
|
reg_fhi db 0 ; block/fnum-high reg
|
||||||
|
reserved block 2, 0
|
||||||
|
ends
|
||||||
|
|
||||||
|
struct player_struct_t
|
||||||
|
ch3_ofs_ch0 dw 0
|
||||||
|
ch3_ofs_ch1 dw 0
|
||||||
|
chip_idx db 0 ; current chip active
|
||||||
|
channel_idx db 0
|
||||||
|
end_of_frame db 0
|
||||||
|
do_next_op db 0
|
||||||
|
ssg_r7 block 2, 0
|
||||||
|
ends
|
||||||
|
|
||||||
|
; instantinate structures
|
||||||
|
align 256
|
||||||
|
player_channels:
|
||||||
|
channel_struct_t 0, 0 ; TODO: fill start offsets here
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
channel_struct_t 0, 0
|
||||||
|
|
||||||
|
player_struct player_struct_t player_channels+(channel_struct_t*(3+0)), player_channels+(channel_struct_t*(3+8))
|
||||||
|
|
||||||
|
; -----------------------------
|
||||||
|
; -----------------------------
|
||||||
|
; OPN register dump output
|
||||||
|
; in: HL - registers in (reg:data) byte pairs, reg==0xFF - return
|
||||||
|
reg_out:
|
||||||
|
ld bc, 0xFFFD
|
||||||
|
ld de, 0x00C0 ; 0xFFBF compensated for outi
|
||||||
|
|
||||||
|
; select 1st chip
|
||||||
|
ld a, 0b11111000
|
||||||
|
out (c), a
|
||||||
|
.loop:
|
||||||
|
ld b, d
|
||||||
|
ld a, [hl]
|
||||||
|
inc a ; test for 0xFF terminator
|
||||||
|
ret z
|
||||||
|
outi
|
||||||
|
ld b, e
|
||||||
|
outi
|
||||||
|
dup 4: nop : edup ; delay
|
||||||
|
jp .loop
|
||||||
|
|
||||||
|
; ------------------------
|
||||||
|
; pop from stack
|
||||||
|
; in: IX - channel context
|
||||||
|
; trashes A, DE
|
||||||
|
pop_stack:
|
||||||
|
dec [ix + channel_struct_t.stack_pos] ; --chctx->stack_pos;
|
||||||
|
ld l, [ix + channel_struct_t.stack_pos] : ld h, 0 ; hl = chctx->stack_pos;
|
||||||
|
add hl, hl ; *= 2
|
||||||
|
add hl, hl ; *= 4
|
||||||
|
ld de, channel_struct_t.stack
|
||||||
|
add hl, de
|
||||||
|
ld de, ix
|
||||||
|
add hl, de ; hl = st = chctx->stack + chctx->stack_pos;
|
||||||
|
|
||||||
|
ld e, [hl] : inc l
|
||||||
|
ld d, [hl] : inc l ; de = st->ptr
|
||||||
|
ld [ix + channel_struct_t.ptr], de ; chctx->ptr = st->ptr
|
||||||
|
|
||||||
|
ld e, [hl] : inc l
|
||||||
|
ld d, [hl] ; de = st->frames_to_play
|
||||||
|
ld [ix + channel_struct_t.frames_to_play], de ; chctx->frames_to_play = st->frames_to_play
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ------------------------
|
||||||
|
; push to stack
|
||||||
|
; in: IX - channel context
|
||||||
|
; trashes A, DE
|
||||||
|
push_stack:
|
||||||
|
ld l, [ix + channel_struct_t.stack_pos] : ld h, 0 ; hl = chctx->stack_pos;
|
||||||
|
add hl, hl ; *= 2
|
||||||
|
add hl, hl ; *= 4
|
||||||
|
ld de, channel_struct_t.stack
|
||||||
|
add hl, de
|
||||||
|
ld de, ix
|
||||||
|
add hl, de ; hl = st = chctx->stack + chctx->stack_pos;
|
||||||
|
|
||||||
|
ld de, [ix + channel_struct_t.ptr]
|
||||||
|
ld [hl], e : inc l
|
||||||
|
ld [hl], d : inc l ; st->ptr = chctx->ptr
|
||||||
|
|
||||||
|
ld de, [ix + channel_struct_t.frames_to_play]
|
||||||
|
ld [hl], e : inc l
|
||||||
|
ld [hl], d : inc l ; st->frames_to_play = chctx->frames_to_play
|
||||||
|
|
||||||
|
inc [ix + channel_struct_t.stack_pos]
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ------------------------
|
||||||
|
; set delay
|
||||||
|
; in: HL - stream ptr
|
||||||
|
; out: DE - delay, trashes A
|
||||||
|
set_delay:
|
||||||
|
ld a, [hl]
|
||||||
|
cp OPM_STREAM_DELAY_INT16
|
||||||
|
jp z, .int16
|
||||||
|
and 0xF0
|
||||||
|
cp OPM_STREAM_DELAY_INT12
|
||||||
|
jp z, .int12
|
||||||
|
cp OPM_STREAM_DELAY_SHORT
|
||||||
|
jp z, .short
|
||||||
|
ret
|
||||||
|
|
||||||
|
.int16:
|
||||||
|
inc hl
|
||||||
|
ldi de, [hl]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.int12:
|
||||||
|
ld a, [hl] : inc hl : and 0x0F : ld d, a
|
||||||
|
ld e, [hl] : inc hl
|
||||||
|
ret
|
||||||
|
|
||||||
|
.short:
|
||||||
|
ld a, [hl] : and 0x0F : inc a : ld e, a : ld d, 0
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ------------------------------------------
|
||||||
|
; parse AY channel stream
|
||||||
|
; HL - stream data, IX- channel context, IY - register buffer, CF - do next op
|
||||||
|
parse_ay_channel_stream:
|
||||||
|
ld b, [hl]
|
||||||
|
; if ((*(data) & 0x80) == OPM_AYTONE_REGS) {
|
||||||
|
ld a, b : and 0x80 : cp OPM_AYTONE_REGS
|
||||||
|
jp nz, .not_regs
|
||||||
|
|
||||||
|
; volume and period low
|
||||||
|
; opn_write_reg(chip_index, 8 + ch, (mask & OPM_AYTONE_CMD00_VOLUME_MASK));
|
||||||
|
inc hl
|
||||||
|
ld a, [player_struct.channel_idx]
|
||||||
|
add 8
|
||||||
|
ldi [iy], a
|
||||||
|
ld a, b : and OPM_AYTONE_CMD00_VOLUME_MASK
|
||||||
|
ldi [iy], a
|
||||||
|
|
||||||
|
; if (mask & OPM_AYTONE_CMD00_PERIOD_LOW) opn_write_reg(chip_index, 0 + (ch<<1), *data++);
|
||||||
|
bit OPM_AYTONE_CMD00_PERIOD_LOW_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ld a, [player_struct.channel_idx]
|
||||||
|
add a
|
||||||
|
ldi [iy], a
|
||||||
|
ldi a, [hl]
|
||||||
|
ldi [iy], a
|
||||||
|
|
||||||
|
1:
|
||||||
|
; if (mask & OPM_AYTONE_CMD00_EOF) endOfFrame = true;
|
||||||
|
bit OPM_AYTONE_CMD00_EOF_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ld a, b : ld [player_struct.end_of_frame], a
|
||||||
|
|
||||||
|
1:
|
||||||
|
scf
|
||||||
|
ret
|
||||||
|
|
||||||
|
.not_regs:
|
||||||
|
; if ((*(data) & 0xC0) == OPM_AYTONE_PERIOD) {
|
||||||
|
ld a, b : and 0xC0 : cp OPM_AYTONE_PERIOD
|
||||||
|
jp nz, .not_period
|
||||||
|
|
||||||
|
; period low/high
|
||||||
|
; opn_write_reg(chip_index, 1 + (ch<<1), (mask & OPM_AYTONE_CMD80_PERIOD_HIGH));
|
||||||
|
inc hl
|
||||||
|
ld a, [player_struct.channel_idx]
|
||||||
|
add a
|
||||||
|
add 1
|
||||||
|
ldi [iy], a
|
||||||
|
exa
|
||||||
|
ld a, b : and OPM_AYTONE_CMD80_PERIOD_HIGH
|
||||||
|
ldi [iy], a
|
||||||
|
exa
|
||||||
|
|
||||||
|
; if (mask & OPM_AYTONE_CMD80_PERIOD_LOW) opn_write_reg(chip_index, 0 + (ch << 1), *data++);
|
||||||
|
bit OPM_AYTONE_CMD80_PERIOD_LOW_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
dec a
|
||||||
|
ldi [iy], a
|
||||||
|
ldi a, [hl]
|
||||||
|
ldi [iy], a
|
||||||
|
1:
|
||||||
|
|
||||||
|
; if (mask & OPM_AYTONE_CMD00_EOF) endOfFrame = true;
|
||||||
|
bit OPM_AYTONE_CMD80_EOF_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ld a, b : ld [player_struct.end_of_frame], a
|
||||||
|
|
||||||
|
1:
|
||||||
|
scf
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.not_period:
|
||||||
|
; if ((*(data) & 0xF8) == OPM_AYTONE_MASK) {
|
||||||
|
ld a, b : and 0xF8 : cp OPM_AYTONE_MASK
|
||||||
|
jp nz, .not_mask
|
||||||
|
|
||||||
|
inc hl
|
||||||
|
push de, hl, ix
|
||||||
|
|
||||||
|
; ctx->ssg_r7[chip_index] &= ~(((1 << 3) | (1 << 0)) << ch);
|
||||||
|
ld a, [player_struct.chip_idx] : ld e, a
|
||||||
|
ld d, 0
|
||||||
|
ld ix, player_struct.ssg_r7
|
||||||
|
add ix, de ; ix = ctx->ssg_r7[chip_index]
|
||||||
|
|
||||||
|
ld a, [player_struct.channel_idx] : ld e, a
|
||||||
|
ld hl, .mask_channel
|
||||||
|
add hl, de
|
||||||
|
ld a, [ix] : and [hl] ; a = ctx->ssg_r7[chip_index] &= ~(((1 << 3) | (1 << 0)) << ch);
|
||||||
|
|
||||||
|
srl e : srl e
|
||||||
|
ld hl, .mask_lookup
|
||||||
|
add hl, de
|
||||||
|
or [hl] : ld [ix], a ; ctx->ssg_r7[chip_index] |= (mask_lookup[mask & 3] << ch);
|
||||||
|
|
||||||
|
pop hl, de, ix
|
||||||
|
|
||||||
|
; if (mask & OPM_AYTONE_MASK_EOF) endOfFrame = true;
|
||||||
|
bit OPM_AYTONE_MASK_EOF_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
|
||||||
|
ld a, b : ld [player_struct.end_of_frame], a
|
||||||
|
1:
|
||||||
|
|
||||||
|
scf
|
||||||
|
ret
|
||||||
|
|
||||||
|
.mask_lookup:
|
||||||
|
.p = 0
|
||||||
|
dup 3
|
||||||
|
db ((0<<3)|(0<<0)) << .p, ((0<<3)|(1<<0)) << .p, ((1<<3)|(0<<0)) << .p, ((1<<3)|(1<<0)) << .p
|
||||||
|
.p = .p + 1
|
||||||
|
edup
|
||||||
|
.mask_channel:
|
||||||
|
.p = 0
|
||||||
|
dup 3
|
||||||
|
db ~(((1<<3)|(1<<0)) << .p)
|
||||||
|
.p = .p + 1
|
||||||
|
edup
|
||||||
|
|
||||||
|
.not_mask:
|
||||||
|
.done:
|
||||||
|
and a ; clear carry
|
||||||
|
ret
|
||||||
|
|
||||||
|
; parse AY envalope/noise stream
|
||||||
|
; HL - stream data, IX- channel context, IY - register buffer, CF - do next op
|
||||||
|
parse_ay_envnoise_stream:
|
||||||
|
ld b, [hl]
|
||||||
|
; if ((*(data) & 0x80) == OPM_AYENV_REGS) {
|
||||||
|
ld a, b : and 0x80 : cp OPM_AYENV_REGS
|
||||||
|
jp nz, .not_regs
|
||||||
|
|
||||||
|
; opn_write_reg(chip_index, 6, (mask & OPM_AYENV_CMD00_NOISE_MASK));
|
||||||
|
inc hl
|
||||||
|
ldi [iy], 6
|
||||||
|
ld a, b : and OPM_AYENV_CMD00_NOISE_MASK
|
||||||
|
ldi [iy], a
|
||||||
|
|
||||||
|
; if (mask & OPM_AYENV_CMD00_PERIOD_LOW) opn_write_reg(chip_index, 11, *data++);
|
||||||
|
bit OPM_AYENV_CMD00_PERIOD_LOW_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ldi [iy], 11
|
||||||
|
ldi a, [hl]
|
||||||
|
ldi [iy], a
|
||||||
|
1:
|
||||||
|
|
||||||
|
; if (mask & OPM_AYENV_CMD00_EOF) endOfFrame = true;
|
||||||
|
bit OPM_AYENV_CMD00_EOF_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ld a, b : ld [player_struct.end_of_frame], a
|
||||||
|
1:
|
||||||
|
|
||||||
|
scf
|
||||||
|
ret
|
||||||
|
|
||||||
|
.not_regs:
|
||||||
|
; if ((*(data) & 0xC0) == OPM_AYENV_ENVTYPE) {
|
||||||
|
ld a, b : and 0xC0 : cp OPM_AYENV_ENVTYPE
|
||||||
|
jp nz, .not_envtype
|
||||||
|
|
||||||
|
; opn_write_reg(chip_index, 13, (mask & OPM_AYENV_CMD80_ENV_TYPE));
|
||||||
|
inc hl
|
||||||
|
ldi [iy], 13
|
||||||
|
ld a, b : and OPM_AYENV_CMD80_ENV_TYPE
|
||||||
|
ldi [iy], a
|
||||||
|
|
||||||
|
; if (mask & OPM_AYENV_CMD80_PERIOD_LOW) opn_write_reg(chip_index, 11, *data++);
|
||||||
|
bit OPM_AYENV_CMD80_PERIOD_LOW_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ldi [iy], 11
|
||||||
|
ldi a, [hl]
|
||||||
|
ldi [iy], a
|
||||||
|
1:
|
||||||
|
|
||||||
|
; if (mask & OPM_AYENV_CMD80_EOF) endOfFrame = true;
|
||||||
|
bit OPM_AYENV_CMD80_EOF_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ld a, b : ld [player_struct.end_of_frame], a
|
||||||
|
1:
|
||||||
|
|
||||||
|
scf
|
||||||
|
ret
|
||||||
|
|
||||||
|
.not_envtype:
|
||||||
|
; if ((*(data) & 0xF8) == OPM_AYENV_PERIOD_FULL) {
|
||||||
|
ld a, b : and 0xF8 : cp OPM_AYENV_PERIOD_FULL
|
||||||
|
jp nz, .not_period
|
||||||
|
|
||||||
|
inc hl
|
||||||
|
; if (mask & OPM_AYENV_CMDF0_PERIOD_LOW) opn_write_reg(chip_index, 11, *data++);
|
||||||
|
bit OPM_AYENV_CMDF0_PERIOD_LOW_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ldi [iy], 11
|
||||||
|
ldi a, [hl]
|
||||||
|
ldi [iy], a
|
||||||
|
1:
|
||||||
|
; if (mask & OPM_AYENV_CMDF0_PERIOD_HIGH) opn_write_reg(chip_index, 12, *data++);
|
||||||
|
bit OPM_AYENV_CMDF0_PERIOD_HIGH_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ldi [iy], 12
|
||||||
|
ldi a, [hl]
|
||||||
|
ldi [iy], a
|
||||||
|
1:
|
||||||
|
; if (mask & OPM_AYENV_CMDF0_EOF) endOfFrame = true;
|
||||||
|
bit OPM_AYENV_CMDF0_EOF_BIT, b
|
||||||
|
jp nz, 1f
|
||||||
|
ld a, b : ld [player_struct.end_of_frame], a
|
||||||
|
1:
|
||||||
|
|
||||||
|
scf
|
||||||
|
ret
|
||||||
|
|
||||||
|
.not_period:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; parse channel stream
|
||||||
|
; in: IX - stream struct, IY - register buffer, BC - stream parser procedure, A - channel index
|
||||||
|
parse_stream:
|
||||||
|
; endOfFrame = false;
|
||||||
|
xor a : ld [player_struct.end_of_frame], a
|
||||||
|
|
||||||
|
; if (--chctx->stream.delay == 0) {
|
||||||
|
ld de, [ix+channel_struct_t.frames_to_play]
|
||||||
|
dec de
|
||||||
|
ld [ix+channel_struct_t.frames_to_play], de
|
||||||
|
ld a, d
|
||||||
|
or e
|
||||||
|
ret z
|
||||||
|
|
||||||
|
; save proc ptr
|
||||||
|
ld bc, .proc
|
||||||
|
|
||||||
|
; load stream pointer
|
||||||
|
ld a, [ix+channel_struct_t.page]
|
||||||
|
ld bc, 0x7FFD
|
||||||
|
out (c), a
|
||||||
|
ld de, [ix+channel_struct_t.ptr]
|
||||||
|
exd ; hl = chctx->stream.ptr
|
||||||
|
|
||||||
|
.tok_loop:
|
||||||
|
ld a, [player_struct.end_of_frame] : and a : jp nz, .end_of_frame
|
||||||
|
|
||||||
|
; call stream parser proc
|
||||||
|
call 0 ; :grins:
|
||||||
|
.proc
|
||||||
|
jp c, .tok_loop ; token handled
|
||||||
|
|
||||||
|
; handle common tokens
|
||||||
|
ld b, [hl]
|
||||||
|
|
||||||
|
; if ((*data & 0xF0) == OPM_STREAM_BACKREF) {
|
||||||
|
ld a, b : and 0xF0 : cp OPM_STREAM_BACKREF
|
||||||
|
jp nz, .not_backref
|
||||||
|
|
||||||
|
; TODO
|
||||||
|
; back reference, nested call :)
|
||||||
|
; int distance = ((*(data + 0) & 0x0F) << 8) | (*(data + 1));
|
||||||
|
ld a, b : and 0x0F : ld d, a : inc hl
|
||||||
|
ldi e, [hl] ; de = distance
|
||||||
|
ldi a, [hl] ; int frames_to_play = *(data + 2); data += 3
|
||||||
|
exd : ld [ix + channel_struct_t.ptr], de ; chctx->stream.ptr = data + 3;
|
||||||
|
|
||||||
|
push af, de, hl
|
||||||
|
call push_stack
|
||||||
|
pop hl, de, af
|
||||||
|
and a : sbc hl, de ; data -= distance;
|
||||||
|
|
||||||
|
; chctx->stream.frames_to_play = frames_to_play; // hack?
|
||||||
|
ld e, a : ld d, 0 : ld [ix + channel_struct_t.frames_to_play], de
|
||||||
|
jp .tok_loop
|
||||||
|
|
||||||
|
.not_backref
|
||||||
|
ld a, b
|
||||||
|
cp OPM_STREAM_END
|
||||||
|
jp z, .tok_end_of_stream
|
||||||
|
cp OPM_STREAM_END_FRAME
|
||||||
|
jp z, .tok_end_of_frame
|
||||||
|
|
||||||
|
; then it's most likely an delay
|
||||||
|
call set_delay
|
||||||
|
ld [ix + channel_struct_t.delay], de
|
||||||
|
|
||||||
|
; fetch next token until it's end of frame
|
||||||
|
jp .tok_loop
|
||||||
|
|
||||||
|
.tok_end_of_stream:
|
||||||
|
ld de, -1
|
||||||
|
ld [ix + channel_struct_t.delay], de
|
||||||
|
jp .end_of_frame
|
||||||
|
|
||||||
|
.tok_end_of_frame:
|
||||||
|
inc hl
|
||||||
|
.end_of_frame:
|
||||||
|
|
||||||
|
; chctx->stream.delay = chctx->stream.reload;
|
||||||
|
ld de, [ix + channel_struct_t.delay]
|
||||||
|
ld [ix + channel_struct_t.reload], de
|
||||||
|
|
||||||
|
; // decrement samples to play counter
|
||||||
|
; if (--chctx->stream.samples_to_play == 0) {
|
||||||
|
push hl
|
||||||
|
ld hl, [ix + channel_struct_t.frames_to_play]
|
||||||
|
dec hl
|
||||||
|
ld [ix + channel_struct_t.frames_to_play], hl
|
||||||
|
ld a, h : or l
|
||||||
|
pop hl
|
||||||
|
jp nz, .not_pop
|
||||||
|
|
||||||
|
.pop_loop:
|
||||||
|
call pop_stack ; todo: kludge below, fixme
|
||||||
|
push hl
|
||||||
|
ld hl, [ix + channel_struct_t.frames_to_play]
|
||||||
|
dec hl
|
||||||
|
ld [ix + channel_struct_t.frames_to_play], hl
|
||||||
|
ld a, h : or l
|
||||||
|
pop hl
|
||||||
|
jp z, .pop_loop ; to parse nested backrefs
|
||||||
|
ret
|
||||||
|
|
||||||
|
.not_pop:
|
||||||
|
exd
|
||||||
|
ld [ix+channel_struct_t.ptr], de
|
||||||
|
ret
|
||||||
|
|
||||||
|
; -----------------------------
|
||||||
|
; -----------------------------
|
||||||
|
; play one tick!!!
|
||||||
|
; trashes all registers
|
||||||
|
play_tick:
|
||||||
|
ld iy, reg_buffer
|
||||||
|
|
||||||
|
; play AY only for now
|
||||||
|
|
||||||
|
; chip_index = 0;
|
||||||
|
xor a : ld [player_struct.chip_idx], a
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 4, 0, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 4)
|
||||||
|
ld bc, parse_ay_channel_stream
|
||||||
|
ld a, 0 : ld [player_struct.channel_idx], a
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 5, 1, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 5)
|
||||||
|
ld bc, parse_ay_channel_stream
|
||||||
|
ld a, 1 : ld [player_struct.channel_idx], a
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 6, 2, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 6)
|
||||||
|
ld bc, parse_ay_channel_stream
|
||||||
|
ld a, 2 : ld [player_struct.channel_idx], a
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 7, 0, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 7)
|
||||||
|
ld bc, parse_ay_envnoise_stream
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
ldi [iy], 7
|
||||||
|
ld a, [player_struct.ssg_r7 + 0]
|
||||||
|
ldi [iy], a
|
||||||
|
|
||||||
|
; chip_index = 1;
|
||||||
|
xor a : ld [player_struct.chip_idx], a
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 4, 0, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 4)
|
||||||
|
ld bc, parse_ay_channel_stream
|
||||||
|
ld a, 0 : ld [player_struct.channel_idx], a
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 5, 1, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 5)
|
||||||
|
ld bc, parse_ay_channel_stream
|
||||||
|
ld a, 1 : ld [player_struct.channel_idx], a
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 6, 2, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 6)
|
||||||
|
ld bc, parse_ay_channel_stream
|
||||||
|
ld a, 2 : ld [player_struct.channel_idx], a
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
; opmplay_parse_stream(ctx, ctx->channels + 7, 0, opmplay_parse_ay_channel_stream);
|
||||||
|
ld ix, player_channels + (channel_struct_t * 7)
|
||||||
|
ld bc, parse_ay_envnoise_stream
|
||||||
|
call parse_stream
|
||||||
|
|
||||||
|
ldi [iy], 7
|
||||||
|
ld a, [player_struct.ssg_r7 + 0]
|
||||||
|
ldi [iy], a
|
||||||
|
|
||||||
|
|
||||||
|
; terminate list
|
||||||
|
ldi [iy], -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
Loading…
Reference in a new issue