108 lines
5 KiB
Diff
108 lines
5 KiB
Diff
Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
See LICENSE.md for license information.
|
|
SPDX-License-Identifier: MIT
|
|
|
|
ntpIrqWindow.patch - bound NinjaTrackerPlus's interrupts-off stretches.
|
|
make/iigs.mk applies it to the replayer's source with patch --fuzz=0 before
|
|
Merlin32 assembles it.
|
|
|
|
NinjaTrackerPlus moves sample data into the DOC with interrupts masked,
|
|
~4 us a byte (measured under MAME), and the Z8530 SCC's receive FIFO only
|
|
lasts ~3.1 ms at 9600 baud (~2.3 ms under MAME). Two stretches outlast it:
|
|
- NTPstreamsound fills a stream's 512-byte DOC page with two unrolled
|
|
256-byte copies under its own SEI: ~2.4 ms. stream_window goes between
|
|
the halves: pending interrupts run there, then the DOC's mode and
|
|
address are put back for the second half. The stream's oscillators are
|
|
already halted, and its job is cleared first, so a refill interrupt left
|
|
pending by the slot's previous sound cannot stream into the page.
|
|
- The DOC interrupt handler refills every streaming oscillator that is
|
|
due before it returns, 256 bytes each: ~1 ms apiece, ~2.5 ms for two.
|
|
It returns after one instead; the DOC keeps its IRQ up for the rest, so
|
|
the handler is re-entered at once, after anything the ROM's interrupt
|
|
manager puts first (the SCC is on its fast path).
|
|
Both only while the word at offset 27 of the replayer (irq_window, right
|
|
after the documented jump table) is nonzero. The word after it, at offset
|
|
29 (playing_addr), holds the address of the replayer's playing flag, so
|
|
audio_full.c can see a song that does not loop come to its end. audio_full.c
|
|
sets it from hal.c's tight interrupt-latency bound before every
|
|
NTPstreamsound, so with the bound loose the replayer does exactly what it
|
|
always did.
|
|
|
|
The source is the installer's pinned ntpsources.zip (checksummed), so every
|
|
hunk applies exactly; a hunk that does not means NTP changed and this patch
|
|
must be revisited, so the build fails instead of guessing.
|
|
|
|
--- ninjatrackerplus.s
|
|
+++ ninjatrackerplus.s
|
|
@@ -138,6 +138,14 @@
|
|
; 1 byte channel (0-7 placed in the upper 4 bits, example: $00 for left, $10 for right)
|
|
jmp streamsound
|
|
|
|
+; irq_window (JoeyLib, offset 27): nonzero bounds the interrupts-off
|
|
+; stretches -- see stream_window and interrupt_handler_exit.
|
|
+irq_window dw 0
|
|
+
|
|
+; playing_addr (JoeyLib, offset 29): where the replayer keeps its playing
|
|
+; flag (0 once a song played once has ended), for jlAudioIsPlayingMod.
|
|
+playing_addr dw playing
|
|
+
|
|
*-------------------------------
|
|
|
|
; to stay out of the way, do not use the direct page at all
|
|
@@ -1301,6 +1309,7 @@
|
|
|
|
ldy streamsound_osc2
|
|
jsr stream_copy ;fill buffer with 512 bytes for first play
|
|
+ jsr stream_window ;JoeyLib: interrupts in between the halves, if asked
|
|
jsr stream_copy_no_init
|
|
|
|
mx %00 ;we're in 16bit mode on return
|
|
@@ -1383,6 +1392,31 @@
|
|
clc
|
|
rtl
|
|
|
|
+; stream_window (JoeyLib): between the two halves of streamsound's first
|
|
+; DOC fill, when irq_window is nonzero, let pending interrupts run, then
|
|
+; point the DOC back at the second half (a handler may have used it).
|
|
+; In and out: mx %00, Y = the stream's track * 2.
|
|
+ mx %00
|
|
+stream_window = *
|
|
+ lda irq_window
|
|
+ beq stream_window_1
|
|
+ sep #$20
|
|
+ mx %10
|
|
+ ldx streamsound_osc ;no refill job left pending from the slot's last sound
|
|
+ stz oscillator_job_tbl,x
|
|
+ cli
|
|
+ nop ;a pending interrupt is taken here
|
|
+ sei
|
|
+ jsr access_doc_ram
|
|
+ rep #$20
|
|
+ mx %00
|
|
+ lda stream_doc_page,y ;the page's second half
|
|
+ inc
|
|
+ xba
|
|
+ sta sound_address
|
|
+stream_window_1 = *
|
|
+ rts
|
|
+
|
|
mx %10
|
|
streamsound_copy = * ;copy a byte from stream structure to multiple doc registers
|
|
ldy streamsound_osc_count
|
|
@@ -1454,6 +1488,8 @@
|
|
ldx interrupt_job
|
|
jsr (interrupt_jump_tbl,x)
|
|
|
|
+ lda irq_window ;JoeyLib: one oscillator an interrupt when asked;
|
|
+ bne interrupt_handler_exit ;the DOC keeps its IRQ up for any others
|
|
]loop lda sound_control
|
|
bmi ]loop
|
|
|
|
@@ -1465,6 +1501,7 @@
|
|
lda sound_data
|
|
bpl interrupt_handler_loop
|
|
|
|
+interrupt_handler_exit = *
|
|
sep #$30
|
|
pld
|
|
plb
|