mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-06-08 03:29:32 +00:00
Add configurable 240Hz, 120Hz and 60Hz APU update rates
This commit is contained in:
parent
ab202470a9
commit
b2ead87d25
173
demos/smb/Main.s
173
demos/smb/Main.s
|
@ -87,6 +87,7 @@ FTblTmp equ 228
|
|||
|
||||
; Initialize the sound hardware for APU emulation
|
||||
|
||||
lda #2 ; 0 = 240Hz, 1 = 120Hz, 2 = 60Hz (external)
|
||||
jsr APUStartUp
|
||||
|
||||
; Start up GTE to drive the graphics
|
||||
|
@ -119,6 +120,12 @@ FTblTmp equ 228
|
|||
pea #NESTileBlitter
|
||||
_GTESetAddress
|
||||
|
||||
; Install a custom tile callback to draw tiles directly on the screen w/proper palettes
|
||||
; pea userTileDirectCallback
|
||||
; pea #^NESDirectTileBlitter
|
||||
; pea #NESDirectTileBlitter
|
||||
; _GTESetAddress
|
||||
|
||||
; Get the address of a low-level routine that can be used to draw a tile directly to the graphics screen
|
||||
; pea rawDrawTile
|
||||
; _GTEGetAddress
|
||||
|
@ -132,8 +139,12 @@ FTblTmp equ 228
|
|||
; Initialize the graphics screen playfield (256x160). The NES is 240 lines high, so 160
|
||||
; is a reasonable compromise.
|
||||
|
||||
; pea #128
|
||||
; pea #184
|
||||
|
||||
pea #128
|
||||
pea #200
|
||||
|
||||
; pea #80
|
||||
; pea #144
|
||||
_GTESetScreenMode
|
||||
|
@ -183,6 +194,9 @@ FTblTmp equ 228
|
|||
pla
|
||||
sta OldOneSec
|
||||
|
||||
; Show the configuration screen
|
||||
; jsr ShowConfig
|
||||
|
||||
; Set an internal flag to tell the VBL interrupt handler that it is
|
||||
; ok to start invoking the game logic. The ROM code has to be run
|
||||
; at 60 Hz because it controls the audio. Bad audio is way worse
|
||||
|
@ -368,8 +382,15 @@ EvtLoop
|
|||
ldy #33
|
||||
jsr CopyNametable
|
||||
brl EvtLoop
|
||||
|
||||
:not_v
|
||||
cmp #'t' ; show VBL interrupt time
|
||||
bne :not_t
|
||||
lda show_vbl_cpu
|
||||
eor #1
|
||||
sta show_vbl_cpu
|
||||
brl EvtLoop
|
||||
:not_t
|
||||
|
||||
cmp #'q'
|
||||
beq Exit
|
||||
brl EvtLoop
|
||||
|
@ -394,6 +415,8 @@ nmiCount dw 0
|
|||
DPSave dw 0
|
||||
LastAreaType dw 0
|
||||
frameCount dw 0
|
||||
show_vbl_cpu dw 0
|
||||
|
||||
; Toggle an APU control bit
|
||||
ToggleAPUChannel
|
||||
pha
|
||||
|
@ -472,6 +495,17 @@ RenderFrame
|
|||
sta OldROMScrollEdge ; Stash a copy for the next round through
|
||||
lsr
|
||||
pha
|
||||
|
||||
; Get the player's Y coordinate and determine of we need to adjust the camera based on the physical play field size
|
||||
; sep #$20
|
||||
; ldal ROMBase+$b5 ; Player_Y_HighPos
|
||||
; xba
|
||||
; ldal ROMBase+$ce ; Player_Y_Position
|
||||
; rep #$20
|
||||
;
|
||||
; sec
|
||||
; sbc TopClip ; If we're hiding the
|
||||
|
||||
pea $0000
|
||||
_GTESetBG0Origin
|
||||
|
||||
|
@ -535,6 +569,122 @@ AreaPalettes dw WaterPalette,Area1Palette,Area2Palette,Area3Palette,Area4Pale
|
|||
SwizzleTables adrl AT0_T0,AT1_T0,AT2_T0,AT3_T0,AT2_T0
|
||||
SwizzlePtr adrl AT1_T0
|
||||
|
||||
; Draw PPU tiles to the screen for a UI
|
||||
;
|
||||
; 0 - 9 starts at tile 256
|
||||
; A - Z starts at tile 266
|
||||
; mushroom is $1CE = 462
|
||||
TILE_ZERO equ 256
|
||||
TILE_A equ 266
|
||||
TILE_SHROOM equ 462
|
||||
ShowConfig
|
||||
lda #0
|
||||
jsr SetAreaType
|
||||
lda #$0000
|
||||
stal $E19E00
|
||||
|
||||
ldx #TILE_SHROOM+TILE_USER_BIT
|
||||
:loop
|
||||
phx
|
||||
|
||||
phx
|
||||
pea $2000
|
||||
pea $0000 ; Bits 1-2, 5 and 7 are valid
|
||||
_GTEDrawTileToScreen
|
||||
|
||||
ldx #msg1
|
||||
ldy #$2000+{8*160}
|
||||
lda #$0000
|
||||
jsr ConfigDrawString
|
||||
|
||||
ldx #msg1
|
||||
ldy #$2000+{16*160}
|
||||
lda #$0001
|
||||
jsr ConfigDrawString
|
||||
|
||||
ldx #msg1
|
||||
ldy #$2000+{24*160}
|
||||
lda #$0002
|
||||
jsr ConfigDrawString
|
||||
|
||||
ldx #msg1
|
||||
ldy #$2000+{32*160}
|
||||
lda #$0003
|
||||
jsr ConfigDrawString
|
||||
|
||||
:waitloop
|
||||
pha
|
||||
_GTEReadControl
|
||||
pla
|
||||
bit #PAD_KEY_DOWN
|
||||
beq :waitloop
|
||||
|
||||
plx
|
||||
and #$007F
|
||||
cmp #LEFT_ARROW
|
||||
beq :decrement
|
||||
cmp #RIGHT_ARROW
|
||||
beq :increment
|
||||
rts
|
||||
|
||||
:increment
|
||||
inx
|
||||
inx
|
||||
:decrement dex
|
||||
bra :loop
|
||||
|
||||
; X = string pointer
|
||||
; Y = address
|
||||
|
||||
ConfigDrawString
|
||||
stx Tmp0
|
||||
sty Tmp1
|
||||
sta Tmp2
|
||||
lda (Tmp0)
|
||||
and #$00FF
|
||||
tax
|
||||
ldy #1
|
||||
:loop
|
||||
phx
|
||||
phy
|
||||
|
||||
lda (Tmp0),y
|
||||
and #$007F
|
||||
cmp #'A'
|
||||
bcc :not_letter
|
||||
sbc #'A'
|
||||
clc
|
||||
adc #TILE_A
|
||||
bra :draw
|
||||
:not_letter
|
||||
cmp #'0'
|
||||
bcc :skip
|
||||
sbc #'0'
|
||||
clc
|
||||
adc #TILE_ZERO
|
||||
:draw
|
||||
ora #TILE_USER_BIT
|
||||
pha
|
||||
pei Tmp1
|
||||
pei Tmp2 ; palette select
|
||||
_GTEDrawTileToScreen
|
||||
|
||||
:skip
|
||||
lda Tmp1
|
||||
clc
|
||||
adc #4
|
||||
sta Tmp1
|
||||
|
||||
ply
|
||||
plx
|
||||
|
||||
iny
|
||||
dex
|
||||
bne :loop
|
||||
rts
|
||||
|
||||
msg1 str 'HELLO 123'
|
||||
|
||||
; Take a PPU address and convert it to a tile store coordinate
|
||||
;
|
||||
; Inputs
|
||||
|
@ -1021,7 +1171,7 @@ CopyNametable
|
|||
ldx Tmp2 ; Nametable address
|
||||
lda PPU_MEM+$2000,x
|
||||
and #$00FF
|
||||
ora #$0100+TILE_USER_BIT ; USe top 256 tiles and set as a user-defined tile
|
||||
ora #$0100+TILE_USER_BIT ; Use top 256 tiles and set as a user-defined tile
|
||||
pha
|
||||
jsr GetPaletteSelect
|
||||
ora 1,s ; Merge bits 9 and 10 into the Tile ID that's on the stack
|
||||
|
@ -1072,6 +1222,10 @@ CopyNametable
|
|||
|
||||
; Trigger an NMI in the ROM
|
||||
triggerNMI
|
||||
sep #$30
|
||||
jsl quarter_speed_driver
|
||||
rep #$30
|
||||
|
||||
ldal ppuctrl ; If the ROM has not enabled VBL NMI, also skip
|
||||
bit #$80
|
||||
beq :skip
|
||||
|
@ -1617,20 +1771,25 @@ nmiTask
|
|||
|
||||
ldal singleStepMode
|
||||
bne :no_nmi
|
||||
; lda #1
|
||||
; jsr setborder
|
||||
|
||||
ldal show_vbl_cpu
|
||||
beq :no_show_1
|
||||
jsr incborder
|
||||
:no_show_1
|
||||
|
||||
jsr triggerNMI
|
||||
|
||||
; lda #0
|
||||
; jsr setborder
|
||||
:no_nmi
|
||||
ldal show_vbl_cpu
|
||||
beq :no_nmi
|
||||
jsr decborder
|
||||
|
||||
:no_nmi
|
||||
pld
|
||||
plb
|
||||
plp
|
||||
:skip
|
||||
rtl
|
||||
|
||||
mx %00
|
||||
|
||||
readInput
|
||||
|
|
110
demos/smb/apu.s
110
demos/smb/apu.s
|
@ -31,6 +31,7 @@ access_doc_ram_no_inc = *
|
|||
mx %00
|
||||
|
||||
APUStartUp
|
||||
stal apu_mode
|
||||
sei
|
||||
phd
|
||||
pea $c000
|
||||
|
@ -51,11 +52,16 @@ APUShutDown = *
|
|||
|
||||
jsr stop_playing
|
||||
|
||||
ldal apu_mode
|
||||
cmp #2
|
||||
beq :no_doc_interrupts
|
||||
|
||||
lda backup_interrupt_ptr ; restore old interrupt ptr
|
||||
stal sound_interrupt_ptr
|
||||
lda backup_interrupt_ptr+2
|
||||
stal sound_interrupt_ptr+2
|
||||
|
||||
:no_doc_interrupts
|
||||
cli
|
||||
pld
|
||||
clc
|
||||
|
@ -109,7 +115,7 @@ copy_instruments_to_doc
|
|||
lda #$0600
|
||||
jsr copy_noise
|
||||
|
||||
lda #$8000
|
||||
; lda #$8000
|
||||
; jsr gen_noise
|
||||
|
||||
rts
|
||||
|
@ -313,6 +319,10 @@ copy_register_config
|
|||
;--------------------------
|
||||
|
||||
setup_interrupt = *
|
||||
ldal apu_mode
|
||||
cmp #2 ; mode 2 = external driver at 60Hz
|
||||
beq :no_doc_interrupts
|
||||
|
||||
ldal sound_interrupt_ptr
|
||||
sta backup_interrupt_ptr
|
||||
ldal sound_interrupt_ptr+2
|
||||
|
@ -330,6 +340,19 @@ setup_interrupt = *
|
|||
sep #$20
|
||||
mx %10
|
||||
|
||||
ldal apu_mode
|
||||
beq :do_240hz
|
||||
lda #598
|
||||
ldy #598/256
|
||||
bra :set_timer_freq
|
||||
:do_240hz lda #1195
|
||||
ldy #1195/256
|
||||
|
||||
:set_timer_freq
|
||||
stal timer_sound_settings+1 ; low byte of timer frequency
|
||||
tya
|
||||
stal timer_sound_settings+3 ; high byte of timer frequency
|
||||
|
||||
jsr access_doc_registers
|
||||
|
||||
ldy #0
|
||||
|
@ -344,7 +367,7 @@ setup_interrupt = *
|
|||
|
||||
rep #$20
|
||||
mx %00
|
||||
|
||||
:no_doc_interrupts
|
||||
rts
|
||||
|
||||
interrupt_oscillator = 31
|
||||
|
@ -398,6 +421,7 @@ noise_sound_settings = *
|
|||
dfb $a0+noise_oscillator,0 ; mode register, set to free run
|
||||
|
||||
backup_interrupt_ptr ds 4
|
||||
apu_mode ds 2
|
||||
|
||||
;-----------------------------------------------------------------------------------------
|
||||
; APU internals
|
||||
|
@ -557,6 +581,45 @@ PULSE_CONST_VOL_FLAG equ $10
|
|||
NOISE_CONST_VOL_FLAG equ $10
|
||||
TRIANGLE_HALT_FLAG equ $80
|
||||
|
||||
mx %11
|
||||
quarter_speed_driver = *
|
||||
|
||||
phb
|
||||
phd
|
||||
|
||||
phk
|
||||
plb
|
||||
|
||||
pea $c000
|
||||
pld
|
||||
|
||||
ldx apu_frame_counter
|
||||
inx
|
||||
inx
|
||||
cpx #2*apu_frame_steps ; TODO: This is set by MSB in $4017 (4 or 5). 4 = PAL, 5 = NTSC.
|
||||
bcc *+4
|
||||
ldx #0
|
||||
stx apu_frame_counter
|
||||
jmp (:frame_counter_proc,x)
|
||||
:frame_counter_proc da :quarter_frame,:half_frame,:quarter_frame,:no_frame_60,:half_frame
|
||||
|
||||
; Quarter-speed interrupts (60Hz) -- clock four times in each handler
|
||||
:half_frame
|
||||
:quarter_frame
|
||||
jsr half_frame_clock
|
||||
jsr quarter_frame_clock
|
||||
jsr quarter_frame_clock
|
||||
jsr half_frame_clock
|
||||
jsr quarter_frame_clock
|
||||
jsr quarter_frame_clock
|
||||
|
||||
brl update_doc_registers
|
||||
:no_frame_60
|
||||
pld
|
||||
plb
|
||||
clc
|
||||
rtl
|
||||
|
||||
mx %11
|
||||
interrupt_handler = *
|
||||
|
||||
|
@ -588,9 +651,7 @@ interrupt_handler = *
|
|||
beq *+5
|
||||
brl :not_timer ; Only service timer interrupts
|
||||
|
||||
; Update the frame counter. We double-count so that frame counter can be used directly to dispatch to the
|
||||
; appropriate tick handler
|
||||
|
||||
; Update the frame counter and leave the doubled countin x-register for dispatch
|
||||
ldx apu_frame_counter
|
||||
inx
|
||||
inx
|
||||
|
@ -598,31 +659,30 @@ interrupt_handler = *
|
|||
bcc *+4
|
||||
ldx #0
|
||||
stx apu_frame_counter
|
||||
jmp (:frame_counter_proc,x)
|
||||
:frame_counter_proc da :quarter_frame,:half_frame,:quarter_frame,:no_frame,:half_frame
|
||||
|
||||
; Figure out which speed we are dispatching
|
||||
lda apu_mode
|
||||
beq :do_240hz_mode
|
||||
jmp (:apu_120hz_table,x)
|
||||
:do_240hz_mode jmp (:apu_240hz_table,x)
|
||||
:apu_240hz_table da :quarter_frame_240,:half_frame_240,:quarter_frame_240,no_frame,:half_frame_240
|
||||
:apu_120hz_table da :quarter_frame_120,:half_frame_120,:quarter_frame_120,no_frame,:half_frame_120
|
||||
|
||||
; Full speed emulation (240Hz)
|
||||
:half_frame jsr half_frame_clock
|
||||
:quarter_frame jsr quarter_frame_clock
|
||||
:half_frame_240 jsr half_frame_clock
|
||||
:quarter_frame_240 jsr quarter_frame_clock
|
||||
bra update_doc_registers
|
||||
|
||||
; Half-speed interrupts (120Hz) -- clock twice in each handler
|
||||
;:half_frame
|
||||
;:quarter_frame
|
||||
; jsr half_frame_clock
|
||||
; jsr quarter_frame_clock
|
||||
; jsr quarter_frame_clock
|
||||
|
||||
; Quarter-speed interrupts (60Hz) -- clock four times in each handler
|
||||
;:half_frame
|
||||
;:quarter_frame
|
||||
; jsr half_frame_clock
|
||||
; jsr quarter_frame_clock
|
||||
; jsr quarter_frame_clock
|
||||
; jsr half_frame_clock
|
||||
; jsr quarter_frame_clock
|
||||
; jsr quarter_frame_clock
|
||||
:half_frame_120
|
||||
:quarter_frame_120
|
||||
jsr half_frame_clock
|
||||
jsr quarter_frame_clock
|
||||
jsr quarter_frame_clock
|
||||
|
||||
; Apply any changes to the DOC registers
|
||||
update_doc_registers
|
||||
|
||||
jsr access_doc_registers
|
||||
|
||||
; Set the parameters for the first square wave channel.
|
||||
|
@ -802,8 +862,8 @@ interrupt_handler = *
|
|||
:high_pitch pla
|
||||
sta sound_data
|
||||
|
||||
:no_frame
|
||||
:not_timer
|
||||
no_frame
|
||||
ldal show_border
|
||||
beq :no_show2
|
||||
ldal border_color
|
||||
|
|
Loading…
Reference in New Issue
Block a user