Tepples made a comment about this game's samples being a little bit obscure and I guess I took it as a dare to figure it out.
Python decoder:
http://rainwarrior.ca/projects/nes/bigbird_samples.py
Dumped samples:
http://rainwarrior.ca/projects/nes/Sesame%20Street%20-%20Big%20Bird's%20Hide%20&%20Speak%20(USA).wav
So, the samples actually decode to 8-bit samples, which is a bit bizarre. They just get an LSR before writing $4011. The reason it's so strange is because the compressed sample format is a fixed 5-bits per sample stream which index a 32 byte lookup table for the output; at the beginning of the stream, and at every 20th sample, the lookup table is reset with a 4-bit selection code; there are 16 different lookup tables which map to different ranges of output samples. So... they're decompressing 5-bit samples into 8-bit samples then throwing away a bit, so really they're only getting a compression ratio a bit worse than 5/7. A 5-bit value of 0 halts the sample and returns from playback.
I figured out the locations of samples by hand; there's a bunch of contiguous blocks. (Not sure if I missed any.) There's a mechanism to load and play a sample by a 3-byte pointer (basically bank select + pointer + a few extra bits of data). All of these pointers are stored in bank 2 but some of them are contiguous, some are not; there's not convenient table here. Where there's contiguous ones, they tend to splice words/sentences together out of the consecutive sounds.
As Tepples mentioned, the consonant sounds are often separated (and I think are used as common to many words). Some samples are broken into parts, I think so playback can return for an instant to do animation or something else quickly. The alphabet gets really weird; they tend to be stored in strings of ~30 sample blocks, or other strange combinations.
The following code is the decoding loop. It reads and outputs 8 5-bit samples from 5 bytes of memory, selecting a new lookup table every 20 bytes. It also bankswitches if the end of a bank is reached. Note that the code is interspersed with time wasting NOPs and JSRs to keep the samplerate consistent.
The unannotated disassembly was produced by DISASM6 v1.4, with help from FCEUX. The command line was:
disasm6 romname.nes -o 0xC000 -fs 0x3C010 -i
Python decoder:
http://rainwarrior.ca/projects/nes/bigbird_samples.py
Dumped samples:
http://rainwarrior.ca/projects/nes/Sesame%20Street%20-%20Big%20Bird's%20Hide%20&%20Speak%20(USA).wav
So, the samples actually decode to 8-bit samples, which is a bit bizarre. They just get an LSR before writing $4011. The reason it's so strange is because the compressed sample format is a fixed 5-bits per sample stream which index a 32 byte lookup table for the output; at the beginning of the stream, and at every 20th sample, the lookup table is reset with a 4-bit selection code; there are 16 different lookup tables which map to different ranges of output samples. So... they're decompressing 5-bit samples into 8-bit samples then throwing away a bit, so really they're only getting a compression ratio a bit worse than 5/7. A 5-bit value of 0 halts the sample and returns from playback.
I figured out the locations of samples by hand; there's a bunch of contiguous blocks. (Not sure if I missed any.) There's a mechanism to load and play a sample by a 3-byte pointer (basically bank select + pointer + a few extra bits of data). All of these pointers are stored in bank 2 but some of them are contiguous, some are not; there's not convenient table here. Where there's contiguous ones, they tend to splice words/sentences together out of the consecutive sounds.
As Tepples mentioned, the consonant sounds are often separated (and I think are used as common to many words). Some samples are broken into parts, I think so playback can return for an instant to do animation or something else quickly. The alphabet gets really weird; they tend to be stored in strings of ~30 sample blocks, or other strange combinations.
The following code is the decoding loop. It reads and outputs 8 5-bit samples from 5 bytes of memory, selecting a new lookup table every 20 bytes. It also bankswitches if the end of a bank is reached. Note that the code is interspersed with time wasting NOPs and JSRs to keep the samplerate consistent.
Code:
;-------------------------------------------------------------------------------
; entry into sample playback (MMC1 bank has been selected, ($02) is address of sample)
; sample playback also returns here to reset the lookup table every 13 bytes or so
; this first block selects the sample output lookup table
;-------------------------------------------------------------------------------
__f378: LDY #$01 ; $f378: a0 01
LDA ($02),y ; $f37a: b1 02 ; load $02+1 ---0
LSR ; $f37c: 4a
DEY ; $f37d: 88
LDA ($02),y ; $f37e: b1 02 ; load $02+0 210-
ROL ; $f380: 2a
AND #$0f ; $f381: 29 0f ; table = 4 bit value in A
STY $09 ; $f383: 84 09 ; $09 = 0 (used later)
ASL ; $f385: 0a
ASL ; $f386: 0a
ASL ; $f387: 0a
ASL ; $f388: 0a
ASL ; $f389: 0a ; A = table 210----- (low 3 bits as high 3 bits of A)
ROL $09 ; $f38a: 26 09 ; store table bit 3 in $09 temporarily
ADC #$17 ; $f38c: 69 17 ; A = A + $17 (tables all start at +$17 offset, note carry = 0 here)
STA $06 ; $f38e: 85 06 ; store low byte of table address
LDA $09 ; $f390: a5 09 ; A = table -------3 (high bit)
ADC #$fb ; $f392: 69 fb ; A = A + $FB (FB17 is address of lowest table, 4 byte value selects from 16 tables)
STA $07 ; $f394: 85 07 ; store high byte, ($06) now stores table
LDX #$03 ; $f396: a2 03 ; X = 3 (return here after 3 loops)
;-------------------------------------------------------------------------------
; load the first sample before entering 5-byte / 8-sample loop
;-------------------------------------------------------------------------------
LDA ($02),y ; $f398: b1 02 ; load $02 76543
LSR ; $f39a: 4a
LSR ; $f39b: 4a
LSR ; $f39c: 4a
BEQ __f40a ; $f39d: f0 6b ; terminating 0
INC $02 ; $f39f: e6 02 ; inc $02
BNE __f3a8 ; $f3a1: d0 05
INC $03 ; $f3a3: e6 03
JMP __f3ad ; $f3a5: 4c ad f3
__f3a8: NOP ; $f3a8: ea
NOP ; $f3a9: ea
JMP __f3ad ; $f3aa: 4c ad f3
__f3ad: JSR __f520 ; $f3ad: 20 20 f5 ; write sample
JMP __f3b3 ; $f3b0: 4c b3 f3 ; return to top of loop
;-------------------------------------------------------------------------------
; top of sample decoding loop
;-------------------------------------------------------------------------------
__f3b3: LDA ($02),y ; $f3b3: b1 02 ; load $02 54321
LSR ; $f3b5: 4a
AND #$1f ; $f3b6: 29 1f
BEQ __f40a ; $f3b8: f0 50 ; terminating 0
JSR __f514 ; $f3ba: 20 14 f5 ; delay
NOP ; $f3bd: ea
NOP ; $f3be: ea
NOP ; $f3bf: ea
NOP ; $f3c0: ea
NOP ; $f3c1: ea
NOP ; $f3c2: ea
JSR __f520 ; $f3c3: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f3c6: b1 02 ; load $02 ---76
ASL ; $f3c8: 0a
ROL ; $f3c9: 2a
ROL ; $f3ca: 2a
AND #$03 ; $f3cb: 29 03
STA $09 ; $f3cd: 85 09
JSR __f50a ; $f3cf: 20 0a f5 ; inc $02
LDA ($02),y ; $f3d2: b1 02 ; load $02 210--
AND #$07 ; $f3d4: 29 07
ASL ; $f3d6: 0a
ASL ; $f3d7: 0a
ORA $09 ; $f3d8: 05 09
BEQ __f40a ; $f3da: f0 2e ; terminating 0
JSR __f51d ; $f3dc: 20 1d f5 ; delay
NOP ; $f3df: ea
NOP ; $f3e0: ea
NOP ; $f3e1: ea
NOP ; $f3e2: ea
NOP ; $f3e3: ea
NOP ; $f3e4: ea
NOP ; $f3e5: ea
JMP __f3e9 ; $f3e6: 4c e9 f3
__f3e9: JSR __f520 ; $f3e9: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f3ec: b1 02 ; load $02 76543
LSR ; $f3ee: 4a
LSR ; $f3ef: 4a
LSR ; $f3f0: 4a
BEQ __f40a ; $f3f1: f0 17 ; terminating 0
JSR __f50a ; $f3f3: 20 0a f5 ; inc $02
JSR __f517 ; $f3f6: 20 17 f5 ; delay
JMP __f3fc ; $f3f9: 4c fc f3
__f3fc: NOP ; $f3fc: ea
JSR __f520 ; $f3fd: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
; every third pass through the loop we reset the table and restart
;-------------------------------------------------------------------------------
DEX ; $f400: ca ; decrement X
BNE __f406 ; $f401: d0 03
JMP __f378 ; $f403: 4c 78 f3 ; reset the lookup table if X = 0
;-------------------------------------------------------------------------------
__f406: LDA ($02),y ; $f406: b1 02 ; load $02 43210
AND #$1f ; $f408: 29 1f
__f40a: BEQ __f483 ; $f40a: f0 77 ; terminating 0
JSR __f514 ; $f40c: 20 14 f5 ; delay
NOP ; $f40f: ea
NOP ; $f410: ea
NOP ; $f411: ea
NOP ; $f412: ea
NOP ; $f413: ea
NOP ; $f414: ea
JSR __f520 ; $f415: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f418: b1 02 ; load $02 --765
ASL ; $f41a: 0a
ROL ; $f41b: 2a
ROL ; $f41c: 2a
ROL ; $f41d: 2a
AND #$07 ; $f41e: 29 07
STA $09 ; $f420: 85 09
JSR __f50a ; $f422: 20 0a f5 ; inc $02
LDA ($02),y ; $f425: b1 02 ; load $02 10---
AND #$03 ; $f427: 29 03
ASL ; $f429: 0a
ASL ; $f42a: 0a
ASL ; $f42b: 0a
ORA $09 ; $f42c: 05 09
BEQ __f483 ; $f42e: f0 53 ; terminating 0
NOP ; $f430: ea
NOP ; $f431: ea
NOP ; $f432: ea
NOP ; $f433: ea
NOP ; $f434: ea
NOP ; $f435: ea
JMP __f439 ; $f436: 4c 39 f4
__f439: JSR __f520 ; $f439: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f43c: b1 02 ; load $02 65432
LSR ; $f43e: 4a
LSR ; $f43f: 4a
AND #$1f ; $f440: 29 1f
BEQ __f483 ; $f442: f0 3f ; terminating 0
JSR __f514 ; $f444: 20 14 f5 ; delay
NOP ; $f447: ea
NOP ; $f448: ea
NOP ; $f449: ea
NOP ; $f44a: ea
NOP ; $f44b: ea
JMP __f44f ; $f44c: 4c 4f f4
JSR __f520 ; $f44f: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f452: b1 02 ; load $02 ----7
ASL ; $f454: 0a
JSR __f50a ; $f455: 20 0a f5 ; inc $02
LDA ($02),y ; $f458: b1 02 ; load $02 3210-
ROL ; $f45a: 2a
AND #$1f ; $f45b: 29 1f
BEQ __f483 ; $f45d: f0 24 ; terminating 0
JSR __f517 ; $f45f: 20 17 f5 ; delay
JSR __f520 ; $f462: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDY #$01 ; $f465: a0 01
LDA ($02),y ; $f467: b1 02 ; load $02+1 0----
LSR ; $f469: 4a
DEY ; $f46a: 88
LDA ($02),y ; $f46b: b1 02 ; load $02+0 -7654
JSR __f50a ; $f46d: 20 0a f5
ROR ; $f470: 6a
LSR ; $f471: 4a
LSR ; $f472: 4a
LSR ; $f473: 4a
BEQ __f483 ; $f474: f0 0d ; terminating 0
JSR __f549 ; $f476: 20 49 f5 ; triggers a bankswitch if appropriate
NOP ; $f479: ea
NOP ; $f47a: ea
NOP ; $f47b: ea
NOP ; $f47c: ea
JSR __f520 ; $f47d: 20 20 f5 ; do sample
JMP __f3b3 ; $f480: 4c b3 f3 ; loop
;-------------------------------------------------------------------------------
; when a 0 sample is read, this handles the very last sample
;-------------------------------------------------------------------------------
__f483: JSR __f50a ; $f483: 20 0a f5 ; do last sample
RTS ; $f486: 60 ; end of loop
;...............................................................................
; purpose of $f487 - $f509 not known, omitted
;...............................................................................
;-------------------------------------------------------------------------------
; increment ($02) address (sample data pointer)
;-------------------------------------------------------------------------------
__f50a: INC $02 ; $f50a: e6 02
BNE __f511 ; $f50c: d0 03
INC $03 ; $f50e: e6 03
RTS ; $f510: 60
__f511: NOP ; $f511: ea
NOP ; $f512: ea
RTS ; $f513: 60
;-------------------------------------------------------------------------------
; various delay subroutines
;-------------------------------------------------------------------------------
__f514: JSR __f51d ; $f514: 20 1d f5
__f517: JSR __f51d ; $f517: 20 1d f5
__f51a: JSR __f51d ; $f51a: 20 1d f5
__f51d: NOP ; $f51d: ea
NOP ; $f51e: ea
__f51f: RTS ; $f51f: 60
;-------------------------------------------------------------------------------
; looks up a table value from the table at ($06) based on the value in A
; delays for a bit, then stores the value (right shifted by 1) in 4011
;-------------------------------------------------------------------------------
__f520: TAY ; $f520: a8
LDA ($06),y ; $f521: b1 06 ; lookup sample
JMP __f53f ; $f523: 4c 3f f5
.hex 00 00 00 00 ; $f526: 00 00 00 00 ; empty space in code?
.hex 00 00 00 00 ; $f52a: 00 00 00 00
NOP ; $f52e: ea
__f52f: NOP ; $f52f: ea
__f530: NOP ; $f530: ea
NOP ; $f531: ea
NOP ; $f532: ea
NOP ; $f533: ea
NOP ; $f534: ea
NOP ; $f535: ea
NOP ; $f536: ea
NOP ; $f537: ea
NOP ; $f538: ea
NOP ; $f539: ea
NOP ; $f53a: ea
NOP ; $f53b: ea
NOP ; $f53c: ea
NOP ; $f53d: ea
NOP ; $f53e: ea
__f53f: LDY #$15 ; $f53f: a0 15 ; end of "empty" space?
__f541: DEY ; $f541: 88
BNE __f541 ; $f542: d0 fd ; loop 15 times to delay
LSR ; $f544: 4a ; discard pesky 8th bit
STA $4011 ; $f545: 8d 11 40 ; play sample
RTS ; $f548: 60
;-------------------------------------------------------------------------------
; automatically bankswitch if end of bank is reached
;-------------------------------------------------------------------------------
__f549: PHA ; $f549: 48
LDA $03 ; $f54a: a5 03
CMP #$bf ; $f54c: c9 bf
BNE __f572 ; $f54e: d0 22
LDA $02 ; $f550: a5 02
CMP #$c0 ; $f552: c9 c0
BCS __f558 ; $f554: b0 02 ; if ($02) > $bfc0
PLA ; $f556: 68
RTS ; $f557: 60
__f558: INC $019c ; $f558: ee 9c 01 ; increment bank in $019c
LDA $019c ; $f55b: ad 9c 01
JSR __f578 ; $f55e: 20 78 f5 ; bankswitch to bank in $019c
LDA $02 ; $f561: a5 02 ; ($02) -= $3fc0
SEC ; $f563: 38
SBC #$c0 ; $f564: e9 c0
STA $02 ; $f566: 85 02
LDA $03 ; $f568: a5 03
SBC #$bf ; $f56a: e9 bf
ORA #$80 ; $f56c: 09 80
STA $03 ; $f56e: 85 03
PLA ; $f570: 68
RTS ; $f571: 60
;...............................................................................
; sample lookup tables are stored at $fb17
;...............................................................................
; entry into sample playback (MMC1 bank has been selected, ($02) is address of sample)
; sample playback also returns here to reset the lookup table every 13 bytes or so
; this first block selects the sample output lookup table
;-------------------------------------------------------------------------------
__f378: LDY #$01 ; $f378: a0 01
LDA ($02),y ; $f37a: b1 02 ; load $02+1 ---0
LSR ; $f37c: 4a
DEY ; $f37d: 88
LDA ($02),y ; $f37e: b1 02 ; load $02+0 210-
ROL ; $f380: 2a
AND #$0f ; $f381: 29 0f ; table = 4 bit value in A
STY $09 ; $f383: 84 09 ; $09 = 0 (used later)
ASL ; $f385: 0a
ASL ; $f386: 0a
ASL ; $f387: 0a
ASL ; $f388: 0a
ASL ; $f389: 0a ; A = table 210----- (low 3 bits as high 3 bits of A)
ROL $09 ; $f38a: 26 09 ; store table bit 3 in $09 temporarily
ADC #$17 ; $f38c: 69 17 ; A = A + $17 (tables all start at +$17 offset, note carry = 0 here)
STA $06 ; $f38e: 85 06 ; store low byte of table address
LDA $09 ; $f390: a5 09 ; A = table -------3 (high bit)
ADC #$fb ; $f392: 69 fb ; A = A + $FB (FB17 is address of lowest table, 4 byte value selects from 16 tables)
STA $07 ; $f394: 85 07 ; store high byte, ($06) now stores table
LDX #$03 ; $f396: a2 03 ; X = 3 (return here after 3 loops)
;-------------------------------------------------------------------------------
; load the first sample before entering 5-byte / 8-sample loop
;-------------------------------------------------------------------------------
LDA ($02),y ; $f398: b1 02 ; load $02 76543
LSR ; $f39a: 4a
LSR ; $f39b: 4a
LSR ; $f39c: 4a
BEQ __f40a ; $f39d: f0 6b ; terminating 0
INC $02 ; $f39f: e6 02 ; inc $02
BNE __f3a8 ; $f3a1: d0 05
INC $03 ; $f3a3: e6 03
JMP __f3ad ; $f3a5: 4c ad f3
__f3a8: NOP ; $f3a8: ea
NOP ; $f3a9: ea
JMP __f3ad ; $f3aa: 4c ad f3
__f3ad: JSR __f520 ; $f3ad: 20 20 f5 ; write sample
JMP __f3b3 ; $f3b0: 4c b3 f3 ; return to top of loop
;-------------------------------------------------------------------------------
; top of sample decoding loop
;-------------------------------------------------------------------------------
__f3b3: LDA ($02),y ; $f3b3: b1 02 ; load $02 54321
LSR ; $f3b5: 4a
AND #$1f ; $f3b6: 29 1f
BEQ __f40a ; $f3b8: f0 50 ; terminating 0
JSR __f514 ; $f3ba: 20 14 f5 ; delay
NOP ; $f3bd: ea
NOP ; $f3be: ea
NOP ; $f3bf: ea
NOP ; $f3c0: ea
NOP ; $f3c1: ea
NOP ; $f3c2: ea
JSR __f520 ; $f3c3: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f3c6: b1 02 ; load $02 ---76
ASL ; $f3c8: 0a
ROL ; $f3c9: 2a
ROL ; $f3ca: 2a
AND #$03 ; $f3cb: 29 03
STA $09 ; $f3cd: 85 09
JSR __f50a ; $f3cf: 20 0a f5 ; inc $02
LDA ($02),y ; $f3d2: b1 02 ; load $02 210--
AND #$07 ; $f3d4: 29 07
ASL ; $f3d6: 0a
ASL ; $f3d7: 0a
ORA $09 ; $f3d8: 05 09
BEQ __f40a ; $f3da: f0 2e ; terminating 0
JSR __f51d ; $f3dc: 20 1d f5 ; delay
NOP ; $f3df: ea
NOP ; $f3e0: ea
NOP ; $f3e1: ea
NOP ; $f3e2: ea
NOP ; $f3e3: ea
NOP ; $f3e4: ea
NOP ; $f3e5: ea
JMP __f3e9 ; $f3e6: 4c e9 f3
__f3e9: JSR __f520 ; $f3e9: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f3ec: b1 02 ; load $02 76543
LSR ; $f3ee: 4a
LSR ; $f3ef: 4a
LSR ; $f3f0: 4a
BEQ __f40a ; $f3f1: f0 17 ; terminating 0
JSR __f50a ; $f3f3: 20 0a f5 ; inc $02
JSR __f517 ; $f3f6: 20 17 f5 ; delay
JMP __f3fc ; $f3f9: 4c fc f3
__f3fc: NOP ; $f3fc: ea
JSR __f520 ; $f3fd: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
; every third pass through the loop we reset the table and restart
;-------------------------------------------------------------------------------
DEX ; $f400: ca ; decrement X
BNE __f406 ; $f401: d0 03
JMP __f378 ; $f403: 4c 78 f3 ; reset the lookup table if X = 0
;-------------------------------------------------------------------------------
__f406: LDA ($02),y ; $f406: b1 02 ; load $02 43210
AND #$1f ; $f408: 29 1f
__f40a: BEQ __f483 ; $f40a: f0 77 ; terminating 0
JSR __f514 ; $f40c: 20 14 f5 ; delay
NOP ; $f40f: ea
NOP ; $f410: ea
NOP ; $f411: ea
NOP ; $f412: ea
NOP ; $f413: ea
NOP ; $f414: ea
JSR __f520 ; $f415: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f418: b1 02 ; load $02 --765
ASL ; $f41a: 0a
ROL ; $f41b: 2a
ROL ; $f41c: 2a
ROL ; $f41d: 2a
AND #$07 ; $f41e: 29 07
STA $09 ; $f420: 85 09
JSR __f50a ; $f422: 20 0a f5 ; inc $02
LDA ($02),y ; $f425: b1 02 ; load $02 10---
AND #$03 ; $f427: 29 03
ASL ; $f429: 0a
ASL ; $f42a: 0a
ASL ; $f42b: 0a
ORA $09 ; $f42c: 05 09
BEQ __f483 ; $f42e: f0 53 ; terminating 0
NOP ; $f430: ea
NOP ; $f431: ea
NOP ; $f432: ea
NOP ; $f433: ea
NOP ; $f434: ea
NOP ; $f435: ea
JMP __f439 ; $f436: 4c 39 f4
__f439: JSR __f520 ; $f439: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f43c: b1 02 ; load $02 65432
LSR ; $f43e: 4a
LSR ; $f43f: 4a
AND #$1f ; $f440: 29 1f
BEQ __f483 ; $f442: f0 3f ; terminating 0
JSR __f514 ; $f444: 20 14 f5 ; delay
NOP ; $f447: ea
NOP ; $f448: ea
NOP ; $f449: ea
NOP ; $f44a: ea
NOP ; $f44b: ea
JMP __f44f ; $f44c: 4c 4f f4
JSR __f520 ; $f44f: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDA ($02),y ; $f452: b1 02 ; load $02 ----7
ASL ; $f454: 0a
JSR __f50a ; $f455: 20 0a f5 ; inc $02
LDA ($02),y ; $f458: b1 02 ; load $02 3210-
ROL ; $f45a: 2a
AND #$1f ; $f45b: 29 1f
BEQ __f483 ; $f45d: f0 24 ; terminating 0
JSR __f517 ; $f45f: 20 17 f5 ; delay
JSR __f520 ; $f462: 20 20 f5 ; do sample
;-------------------------------------------------------------------------------
LDY #$01 ; $f465: a0 01
LDA ($02),y ; $f467: b1 02 ; load $02+1 0----
LSR ; $f469: 4a
DEY ; $f46a: 88
LDA ($02),y ; $f46b: b1 02 ; load $02+0 -7654
JSR __f50a ; $f46d: 20 0a f5
ROR ; $f470: 6a
LSR ; $f471: 4a
LSR ; $f472: 4a
LSR ; $f473: 4a
BEQ __f483 ; $f474: f0 0d ; terminating 0
JSR __f549 ; $f476: 20 49 f5 ; triggers a bankswitch if appropriate
NOP ; $f479: ea
NOP ; $f47a: ea
NOP ; $f47b: ea
NOP ; $f47c: ea
JSR __f520 ; $f47d: 20 20 f5 ; do sample
JMP __f3b3 ; $f480: 4c b3 f3 ; loop
;-------------------------------------------------------------------------------
; when a 0 sample is read, this handles the very last sample
;-------------------------------------------------------------------------------
__f483: JSR __f50a ; $f483: 20 0a f5 ; do last sample
RTS ; $f486: 60 ; end of loop
;...............................................................................
; purpose of $f487 - $f509 not known, omitted
;...............................................................................
;-------------------------------------------------------------------------------
; increment ($02) address (sample data pointer)
;-------------------------------------------------------------------------------
__f50a: INC $02 ; $f50a: e6 02
BNE __f511 ; $f50c: d0 03
INC $03 ; $f50e: e6 03
RTS ; $f510: 60
__f511: NOP ; $f511: ea
NOP ; $f512: ea
RTS ; $f513: 60
;-------------------------------------------------------------------------------
; various delay subroutines
;-------------------------------------------------------------------------------
__f514: JSR __f51d ; $f514: 20 1d f5
__f517: JSR __f51d ; $f517: 20 1d f5
__f51a: JSR __f51d ; $f51a: 20 1d f5
__f51d: NOP ; $f51d: ea
NOP ; $f51e: ea
__f51f: RTS ; $f51f: 60
;-------------------------------------------------------------------------------
; looks up a table value from the table at ($06) based on the value in A
; delays for a bit, then stores the value (right shifted by 1) in 4011
;-------------------------------------------------------------------------------
__f520: TAY ; $f520: a8
LDA ($06),y ; $f521: b1 06 ; lookup sample
JMP __f53f ; $f523: 4c 3f f5
.hex 00 00 00 00 ; $f526: 00 00 00 00 ; empty space in code?
.hex 00 00 00 00 ; $f52a: 00 00 00 00
NOP ; $f52e: ea
__f52f: NOP ; $f52f: ea
__f530: NOP ; $f530: ea
NOP ; $f531: ea
NOP ; $f532: ea
NOP ; $f533: ea
NOP ; $f534: ea
NOP ; $f535: ea
NOP ; $f536: ea
NOP ; $f537: ea
NOP ; $f538: ea
NOP ; $f539: ea
NOP ; $f53a: ea
NOP ; $f53b: ea
NOP ; $f53c: ea
NOP ; $f53d: ea
NOP ; $f53e: ea
__f53f: LDY #$15 ; $f53f: a0 15 ; end of "empty" space?
__f541: DEY ; $f541: 88
BNE __f541 ; $f542: d0 fd ; loop 15 times to delay
LSR ; $f544: 4a ; discard pesky 8th bit
STA $4011 ; $f545: 8d 11 40 ; play sample
RTS ; $f548: 60
;-------------------------------------------------------------------------------
; automatically bankswitch if end of bank is reached
;-------------------------------------------------------------------------------
__f549: PHA ; $f549: 48
LDA $03 ; $f54a: a5 03
CMP #$bf ; $f54c: c9 bf
BNE __f572 ; $f54e: d0 22
LDA $02 ; $f550: a5 02
CMP #$c0 ; $f552: c9 c0
BCS __f558 ; $f554: b0 02 ; if ($02) > $bfc0
PLA ; $f556: 68
RTS ; $f557: 60
__f558: INC $019c ; $f558: ee 9c 01 ; increment bank in $019c
LDA $019c ; $f55b: ad 9c 01
JSR __f578 ; $f55e: 20 78 f5 ; bankswitch to bank in $019c
LDA $02 ; $f561: a5 02 ; ($02) -= $3fc0
SEC ; $f563: 38
SBC #$c0 ; $f564: e9 c0
STA $02 ; $f566: 85 02
LDA $03 ; $f568: a5 03
SBC #$bf ; $f56a: e9 bf
ORA #$80 ; $f56c: 09 80
STA $03 ; $f56e: 85 03
PLA ; $f570: 68
RTS ; $f571: 60
;...............................................................................
; sample lookup tables are stored at $fb17
;...............................................................................
The unannotated disassembly was produced by DISASM6 v1.4, with help from FCEUX. The command line was:
disasm6 romname.nes -o 0xC000 -fs 0x3C010 -i