iigs-game-engine/demos/smb/apu_sim.s

729 lines
17 KiB
ArmAsm
Raw Normal View History

2023-06-16 06:05:31 +00:00
; APU Sim
;
; Interactive driver for the APU emulation. Inspired by the liveNES ROM (https://github.com/plgDavid/livenes)
REL
use EDS.GSOS.Macs
; Keycodes
LEFT_ARROW equ $08
RIGHT_ARROW equ $15
UP_ARROW equ $0B
DOWN_ARROW equ $0A
SHADOW_REG equ $E0C035
2023-06-16 06:05:31 +00:00
KBD_REG equ $E0C000
KBD_STROBE_REG equ $E0C010
VBL_STATE_REG equ $E0C019
MOD_REG equ $E0C025
COMMAND_KEY_REG equ $E0C061
OPTION_KEY_REG equ $E0C062
; ReadControl return value bits
PAD_BUTTON_B equ $0100
PAD_BUTTON_A equ $0200
PAD_KEY_DOWN equ $0400
; Direct page space
MyUserId equ 0
LastKey equ 2
CursorRow equ 4
CursorCol equ 6
Tmp0 equ 128
Tmp1 equ 130
mx %00
phk
plb
sta MyUserId
stz CursorCol
stz CursorRow
jsr InitGraphics
jsr DrawStaticUI
2023-06-16 06:05:31 +00:00
jsr APUStartUp
sep #$30
2023-06-18 05:26:11 +00:00
lda #$f
jsl APU_STATUS_WRITE ; turn on the first four channels by default
2023-06-16 06:05:31 +00:00
rep #$30
:update
jsr DrawUI
:evtloop
; jsr DrawDynUI ; Always update to see changing internal APU values
2023-06-16 06:05:31 +00:00
jsr _ReadControl
bit #PAD_KEY_DOWN ; Only response to actual key presses
beq :evtloop
and #$007F
cmp #'q'
beq :done
cmp #UP_ARROW
bne *+8
jsr MoveUp
brl :update
cmp #DOWN_ARROW
bne *+8
jsr MoveDown
brl :update
cmp #LEFT_ARROW
bne *+8
jsr MoveLeft
brl :update
cmp #RIGHT_ARROW
bne *+8
jsr MoveRight
brl :update
cmp #' '
bne :not_spc
2023-06-16 06:05:31 +00:00
jsr Toggle
brl :update
:not_spc cmp #'a'
bne :not_a
lda show_border
eor #1
sta show_border
:not_a
2023-06-16 06:05:31 +00:00
brl :evtloop
:done
jsr APUShutDown
Quit
_QuitGS qtRec
qtRec adrl $0000
da $00
; Toggle an APU bit
Toggle
mx %11
sep #$30
lda CursorRow
asl
tax
jmp (:toggle1,x)
:toggle1 da Toggle4000,Toggle4001,Toggle4002,Toggle4003
da Toggle4008,Toggle400A,Toggle400B,ToggleNoop
da Toggle4004,Toggle4005,Toggle4006,Toggle4007
da Toggle400C,Toggle400E,Toggle400F,Toggle4015
ToggleNoop
brl ToggleExit
2023-06-16 06:05:31 +00:00
Toggle4000
lda APU_PULSE1_REG1
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE1_REG1_WRITE
brl ToggleExit
2023-06-16 06:05:31 +00:00
Toggle4001
lda APU_PULSE1_REG2
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE1_REG2_WRITE
brl ToggleExit
2023-06-16 06:05:31 +00:00
Toggle4002
lda APU_PULSE1_REG3
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE1_REG3_WRITE
brl ToggleExit
2023-06-16 06:05:31 +00:00
Toggle4003
lda APU_PULSE1_REG4
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE1_REG4_WRITE
brl ToggleExit
Toggle4004
lda APU_PULSE2_REG1
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE2_REG1_WRITE
brl ToggleExit
Toggle4005
lda APU_PULSE2_REG2
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE2_REG2_WRITE
brl ToggleExit
Toggle4006
lda APU_PULSE2_REG3
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE2_REG3_WRITE
brl ToggleExit
Toggle4007
lda APU_PULSE2_REG4
ldx CursorCol
eor ToggleTable,x
jsl APU_PULSE2_REG4_WRITE
brl ToggleExit
Toggle4008
lda APU_TRIANGLE_REG1
ldx CursorCol
eor ToggleTable,x
jsl APU_TRIANGLE_REG1_WRITE
brl ToggleExit
Toggle400A
lda APU_TRIANGLE_REG3
ldx CursorCol
eor ToggleTable,x
jsl APU_TRIANGLE_REG3_WRITE
brl ToggleExit
Toggle400B
lda APU_TRIANGLE_REG4
ldx CursorCol
eor ToggleTable,x
jsl APU_TRIANGLE_REG4_WRITE
brl ToggleExit
Toggle400C
lda APU_NOISE_REG1
ldx CursorCol
eor ToggleTable,x
jsl APU_NOISE_REG1_WRITE
brl ToggleExit
Toggle400E
lda APU_NOISE_REG3
ldx CursorCol
eor ToggleTable,x
jsl APU_NOISE_REG3_WRITE
brl ToggleExit
Toggle400F
lda APU_NOISE_REG4
ldx CursorCol
eor ToggleTable,x
jsl APU_NOISE_REG4_WRITE
brl ToggleExit
2023-06-16 06:05:31 +00:00
Toggle4015
lda APU_STATUS
ldx CursorCol
eor ToggleTable,x
jsl APU_STATUS_WRITE
bra ToggleExit
TogglePulse2
ToggleExit
rep #$30
rts
ToggleTable dfb $80,$40,$20,$10,$08,$04,$02,$01
; Cursor navigation
mx %00
MoveUp
lda CursorRow
bne :not_0
lda #6
sta CursorRow
rts
:not_0
cmp #8
bne :not_8
lda #15
sta CursorRow
rts
:not_8
2023-06-16 06:05:31 +00:00
dec
sta CursorRow
rts
MoveDown
lda CursorRow
cmp #6
bne :not_6
stz CursorRow
rts
:not_6
cmp #15
bne :not_15
lda #8
sta CursorRow
rts
:not_15
2023-06-16 06:05:31 +00:00
inc
sta CursorRow
rts
MoveLeft
lda CursorCol
dec
bpl :store
lda CursorRow
cmp #15
beq :skip
eor #8
sta CursorRow
:skip
2023-06-16 06:05:31 +00:00
lda #7
:store sta CursorCol
2023-06-16 06:05:31 +00:00
rts
MoveRight
lda CursorCol
inc
cmp #8
bcc :store
lda CursorRow
cmp #15
beq :skip
eor #8
sta CursorRow
:skip
2023-06-16 06:05:31 +00:00
lda #0
:store sta CursorCol
2023-06-16 06:05:31 +00:00
rts
; Read the keyboard and paddle controls and return in a game-controller-like format
mx %00
2023-06-16 06:05:31 +00:00
_ReadControl pea $0000 ; low byte = key code, high byte = %------AB
sep #$20
ldal OPTION_KEY_REG ; 'B' button
and #$80
beq :BNotDown
lda #>PAD_BUTTON_B
ora 2,s
sta 2,s
:BNotDown
ldal COMMAND_KEY_REG
and #$80
beq :ANotDown
lda #>PAD_BUTTON_A
ora 2,s
sta 2,s
:ANotDown
ldal KBD_STROBE_REG ; read the keyboard
bit #$80
beq :KbdNotDwn ; check the key-down status
and #$7f
ora 1,s
sta 1,s
cmp LastKey
beq :KbdDown
sta LastKey
lda #>PAD_KEY_DOWN ; set the keydown flag
ora 2,s
sta 2,s
bra :KbdDown
:KbdNotDwn
stz LastKey
:KbdDown
ldal KBD_REG
2023-06-16 06:05:31 +00:00
rep #$20
pla
rts
mx %00
InitGraphics
sep #$20
lda #$C1
stal $E0C029 ; screen on
ldal SHADOW_REG ; shadow on
and #$F7
stal SHADOW_REG
rep #$20
2023-06-16 06:05:31 +00:00
lda #0
ldx #0
:scbloop stal $012000,x
2023-06-16 06:05:31 +00:00
inx
inx
cpx #$7E00
bcc :scbloop
ldx #0
:palloop lda DefaultPalette,x
stal $019E00,x
2023-06-16 06:05:31 +00:00
inx
inx
cpx #$20
bcc :palloop
rts
DefaultPalette ENT
dw $0000,$0777,$0841,$072C
dw $000F,$0080,$0F70,$0D00
dw $0FA9,$0FF0,$00E0,$04DF
dw $0DAF,$078F,$0CCC,$0FFF
; UI string templates
PULSE1_TITLE str 'PULSE1'
PULSE2_TITLE str 'PULSE2'
TRIANGLE_TITLE str 'TRIANGLE'
NOISE_TITLE str 'NOISE'
CONTROL_TITLE str 'CONTROL'
2023-06-16 06:05:31 +00:00
PULSE_REG1_STR str 'DDLCVVVV'
PULSE_REG2_STR str 'EPPPNSSS'
PULSE_REG3_STR str 'TTTTTTTT'
PULSE_REG4_STR str 'LLLLLTTT'
TRIANGLE_REG1_STR str 'CRRRRRRR'
TRIANGLE_REG3_STR str 'TTTTTTTT'
TRIANGLE_REG4_STR str 'LLLLLTTT'
NOISE_REG1_STR str '--LCVVVV'
NOISE_REG3_STR str 'L---PPPP'
NOISE_REG4_STR str 'LLLLL---'
2023-06-16 06:05:31 +00:00
APU_STATUS_STR str '---DNT21'
ROW_SPAN equ {8*160}
DrawDynUI
ldx #{18*4}+{ROW_SPAN*5}
ldy #$3333
lda APU_PULSE1_LENGTH_COUNTER
jsr DrawByte
ldx #{18*4}+{ROW_SPAN*6}
ldy #$3333
lda APU_PULSE1_MUTE
jsr DrawByte
ldx #{18*4}+{ROW_SPAN*7}
ldy #$3333
lda APU_PULSE1_ENVELOPE
jsr DrawByte
ldx #{18*4}+{ROW_SPAN*8}
ldy #$3333
lda APU_PULSE1_CURRENT_PERIOD
jsr DrawWord
; Draw stuff that will never be updated
DrawStaticUI
ldx #{6*4}+{ROW_SPAN*3}
ldy #$1111
lda #PULSE1_TITLE
jsr DrawString
ldx #{22*4}+{ROW_SPAN*3}
ldy #$1111
lda #PULSE2_TITLE
jsr DrawString
ldx #{6*4}+{ROW_SPAN*10}
ldy #$1111
lda #TRIANGLE_TITLE
jsr DrawString
ldx #{22*4}+{ROW_SPAN*10}
ldy #$1111
lda #NOISE_TITLE
jsr DrawString
ldx #{22*4}+{ROW_SPAN*16}
ldy #$1111
lda #CONTROL_TITLE
jsr DrawString
2023-06-16 06:05:31 +00:00
DrawUI
jsr DrawPulse1
jsr DrawPulse2
jsr DrawTriangle
jsr DrawNoise
jsr DrawControl
jsr DrawCursor
rts
PULSE1_X equ 1
PULSE1_Y equ 5
DrawPulse1
ldx #{PULSE1_X*4}+{ROW_SPAN*PULSE1_Y}
2023-06-16 06:05:31 +00:00
ldy #$4444
lda #$4000
jsr DrawWord
ldy #PULSE_REG1_STR
lda APU_PULSE1_REG1
ldx #{{PULSE1_X+5}*4}+{ROW_SPAN*PULSE1_Y}
2023-06-16 06:05:31 +00:00
jsr DrawBitsHL
ldx #{PULSE1_X*4}+{ROW_SPAN*{PULSE1_Y+1}}
2023-06-16 06:05:31 +00:00
ldy #$4444
lda #$4001
jsr DrawWord
ldy #PULSE_REG2_STR
lda APU_PULSE1_REG2
ldx #{{PULSE1_X+5}*4}+{ROW_SPAN*{PULSE1_Y+1}}
2023-06-16 06:05:31 +00:00
jsr DrawBitsHL
ldx #{PULSE1_X*4}+{ROW_SPAN*{PULSE1_Y+2}}
2023-06-16 06:05:31 +00:00
ldy #$4444
lda #$4002
jsr DrawWord
ldy #PULSE_REG3_STR
lda APU_PULSE1_REG3
ldx #{{PULSE1_X+5}*4}+{ROW_SPAN*{PULSE1_Y+2}}
2023-06-16 06:05:31 +00:00
jsr DrawBitsHL
ldx #{PULSE1_X*4}+{ROW_SPAN*{PULSE1_Y+3}}
2023-06-16 06:05:31 +00:00
ldy #$4444
lda #$4003
jsr DrawWord
ldy #PULSE_REG4_STR
lda APU_PULSE1_REG4
ldx #{{PULSE1_X+5}*4}+{ROW_SPAN*{PULSE1_Y+3}}
2023-06-16 06:05:31 +00:00
jsr DrawBitsHL
rts
2023-06-16 06:05:31 +00:00
PULSE2_X equ 17
PULSE2_Y equ 5
DrawPulse2
ldx #{PULSE2_X*4}+{ROW_SPAN*PULSE2_Y}
ldy #$4444
lda #$4004
jsr DrawWord
2023-06-16 06:05:31 +00:00
ldy #PULSE_REG1_STR
lda APU_PULSE2_REG1
ldx #{{PULSE2_X+5}*4}+{ROW_SPAN*PULSE2_Y}
jsr DrawBitsHL
ldx #{PULSE2_X*4}+{ROW_SPAN*{PULSE2_Y+1}}
ldy #$4444
lda #$4005
jsr DrawWord
ldy #PULSE_REG2_STR
lda APU_PULSE2_REG2
ldx #{{PULSE2_X+5}*4}+{ROW_SPAN*{PULSE2_Y+1}}
jsr DrawBitsHL
ldx #{PULSE2_X*4}+{ROW_SPAN*{PULSE2_Y+2}}
ldy #$4444
lda #$4006
jsr DrawWord
ldy #PULSE_REG3_STR
lda APU_PULSE2_REG3
ldx #{{PULSE2_X+5}*4}+{ROW_SPAN*{PULSE2_Y+2}}
jsr DrawBitsHL
ldx #{PULSE2_X*4}+{ROW_SPAN*{PULSE2_Y+3}}
ldy #$4444
lda #$4007
jsr DrawWord
ldy #PULSE_REG4_STR
lda APU_PULSE2_REG4
ldx #{{PULSE2_X+5}*4}+{ROW_SPAN*{PULSE2_Y+3}}
jsr DrawBitsHL
rts
TRIANGLE_X equ 1
TRIANGLE_Y equ 12
DrawTriangle
ldx #{TRIANGLE_X*4}+{ROW_SPAN*TRIANGLE_Y}
ldy #$4444
lda #$4008
jsr DrawWord
ldy #TRIANGLE_REG1_STR
lda APU_TRIANGLE_REG1
ldx #{{TRIANGLE_X+5}*4}+{ROW_SPAN*TRIANGLE_Y}
jsr DrawBitsHL
2023-06-16 06:05:31 +00:00
ldx #{TRIANGLE_X*4}+{ROW_SPAN*{TRIANGLE_Y+1}}
ldy #$4444
lda #$400A
jsr DrawWord
ldy #TRIANGLE_REG3_STR
lda APU_TRIANGLE_REG3
ldx #{{TRIANGLE_X+5}*4}+{ROW_SPAN*{TRIANGLE_Y+1}}
jsr DrawBitsHL
ldx #{TRIANGLE_X*4}+{ROW_SPAN*{TRIANGLE_Y+2}}
ldy #$4444
lda #$400B
jsr DrawWord
ldy #TRIANGLE_REG4_STR
lda APU_TRIANGLE_REG4
ldx #{{TRIANGLE_X+5}*4}+{ROW_SPAN*{TRIANGLE_Y+2}}
jsr DrawBitsHL
rts
NOISE_X equ 17
NOISE_Y equ 12
DrawNoise
ldx #{NOISE_X*4}+{ROW_SPAN*NOISE_Y}
ldy #$4444
lda #$400C
jsr DrawWord
ldy #NOISE_REG1_STR
lda APU_NOISE_REG1
ldx #{{NOISE_X+5}*4}+{ROW_SPAN*NOISE_Y}
jsr DrawBitsHL
ldx #{NOISE_X*4}+{ROW_SPAN*{NOISE_Y+1}}
ldy #$4444
lda #$400E
jsr DrawWord
ldy #NOISE_REG3_STR
lda APU_NOISE_REG3
ldx #{{NOISE_X+5}*4}+{ROW_SPAN*{NOISE_Y+1}}
jsr DrawBitsHL
ldx #{NOISE_X*4}+{ROW_SPAN*{NOISE_Y+2}}
ldy #$4444
lda #$400F
jsr DrawWord
ldy #NOISE_REG4_STR
lda APU_NOISE_REG4
ldx #{{NOISE_X+5}*4}+{ROW_SPAN*{NOISE_Y+2}}
jsr DrawBitsHL
rts
; Draw the APU Status byte
CONTROL_X equ 17
CONTROL_Y equ 18
DrawControl
ldx #{CONTROL_X*4}+{ROW_SPAN*CONTROL_Y}
2023-06-16 06:05:31 +00:00
ldy #$4444
lda #$4015
jsr DrawWord
ldy #APU_STATUS_STR
lda APU_STATUS
ldx #{{CONTROL_X+5}*4}+{ROW_SPAN*CONTROL_Y}
2023-06-16 06:05:31 +00:00
jsr DrawBitsHL
rts
2023-06-16 06:05:31 +00:00
DrawCursor
2023-06-16 06:05:31 +00:00
lda CursorRow
asl
tax
lda row2screen,x ; Get the physical position of each logical row
2023-06-16 06:05:31 +00:00
asl
asl
asl
asl
asl
pha
asl
asl
clc
adc 1,s
asl
asl
asl
sta 1,s
2023-06-16 06:05:31 +00:00
lda CursorCol
clc
adc col2screen,x
2023-06-16 06:05:31 +00:00
asl
asl
clc
adc 1,s
tax
pla
lda #'_'
ldy #$FFFF
jsr DrawBottom
rts
row2screen dw 5,6,7,8,12,13,14,0,5,6,7,8,12,13,14,18 ; 16 logical rows, 0-7 are column 1, 8-15 column 2
col2screen dw 6,6,6,6,6, 6, 6, 0,22,22,22,22,22,22,22,22 ;
2023-06-16 06:05:31 +00:00
; Draw a byte as a series of bits using the template strings and
; the bit values to set the color
;
; x = screen coordinates
; y = string template
; a = byte value
DrawBitsHL
and #$00FF
xba
sta Tmp0
iny ; advance past string length byte
sty Tmp1
ldy #0
:loop
phy
lda (Tmp1),y
and #$00FF
ldy #$1111 ; dk. grey
asl Tmp0
bcc *+5
ldy #$FFFF ; white
jsr DrawChar
txa
clc
adc #4
tax
ply
iny
cpy #8
bcc :loop
rts
setborder
php
sep #$20
eorl $E0C034
and #$0F
eorl $E0C034
stal $E0C034
plp
rts
2023-06-16 06:05:31 +00:00
put App.Msg.s
put font.s
put apu.s