asm file with a dcm sample?
Moderator: Moderators
-
- Posts: 34
- Joined: Fri Feb 22, 2019 10:05 am
asm file with a dcm sample?
Hello. I'm having a hard time trying to integrate dcm data into a single asm file. If I put raw DPCM samples extracted from a Famtracker file into the RODATA section, what are the parameters needed for the NES to convert them to sound? Thanks!
Re: asm file with a dcm sample?
Here are excerpts from my speech synth. The data being input through (speech_lo),y is one byte speed select, next byte sample number. Kinda dumb that I used words for the lookup tables though, could have been like .byte <((voc00-$C000)/$40). You need to write $4010,$4011,$4012,$4013 and $4015. The sample(s) need to be at $C000 or higher, and they should begin on a 64 byte boundary.
Sounds like you're using ca65, If you post your linker config, that would help.
Code: Select all
ldy #0
lda (speech_lo),y
ora #%10000000
sta $4010
lda #$40
sta $4011
iny
lda (speech_lo),y
asl
tax
lda sample_length_index,x
sta $4013
lda sample_addr_index,x
sta $4012
lda #%00010000
sta $4015
sample_addr_index:
.word (voc00-$C000)/$40
.word (voc01-$C000)/$40
.word (voc02-$C000)/$40
sample_length_index:
.word (voc01-voc00)/16 ; a
.word (voc02-voc01)/16 ; ae
.word (voc03-voc02)/16 ; aw
.segment "SAMPLES" ; $C000 - $FFF9
voc00: .incbin "set1\a.dmc"
voc01: .incbin "set1\ae.dmc"
voc02: .incbin "set1\aw.dmc"
-
- Posts: 34
- Joined: Fri Feb 22, 2019 10:05 am
Re: asm file with a dcm sample?
Can you write the configuration values for "SAMPLES" because the segment doesn't exist in my compilier's cfg file. Also, for the linker config, all I'm using is typing this in command prompt:Memblers wrote: ↑Sun Jan 02, 2022 11:19 pm Here are excerpts from my speech synth. The data being input through (speech_lo),y is one byte speed select, next byte sample number. Kinda dumb that I used words for the lookup tables though, could have been like .byte <((voc00-$C000)/$40). You need to write $4010,$4011,$4012,$4013 and $4015. The sample(s) need to be at $C000 or higher, and they should begin on a 64 byte boundary.
Sounds like you're using ca65, If you post your linker config, that would help.Code: Select all
ldy #0 lda (speech_lo),y ora #%10000000 sta $4010 lda #$40 sta $4011 iny lda (speech_lo),y asl tax lda sample_length_index,x sta $4013 lda sample_addr_index,x sta $4012 lda #%00010000 sta $4015 sample_addr_index: .word (voc00-$C000)/$40 .word (voc01-$C000)/$40 .word (voc02-$C000)/$40 sample_length_index: .word (voc01-voc00)/16 ; a .word (voc02-voc01)/16 ; ae .word (voc03-voc02)/16 ; aw .segment "SAMPLES" ; $C000 - $FFF9 voc00: .incbin "set1\a.dmc" voc01: .incbin "set1\ae.dmc" voc02: .incbin "set1\aw.dmc"
Code: Select all
ca65 filename.asm -o filename.o -t nes
ld65 filename.o -o filename.nes -t nes
Re: asm file with a dcm sample?
speech_lo...
It looks like a pointer to the data stream. For a pointer to work (mode = indirect indexed with y) you need 2 zeropage variables, the first is the LSB the second is the MSB
.segment "ZEROPAGE"
speech_lo: .res 1
speech_hi: .res 1
It looks like a pointer to the data stream. For a pointer to work (mode = indirect indexed with y) you need 2 zeropage variables, the first is the LSB the second is the MSB
.segment "ZEROPAGE"
speech_lo: .res 1
speech_hi: .res 1
nesdoug.com -- blog/tutorial on programming for the NES
-
- Posts: 34
- Joined: Fri Feb 22, 2019 10:05 am
Re: asm file with a dcm sample?
Here's my poorly written asm code (featuring my favorite internet celebrity the Tourette's Guy). Plus the char and the famitracker file. Is there something I'm doing wrong?
- Attachments
-
- tourettes guy.chr
- (8 KiB) Downloaded 45 times
-
- fuck.ftm
- (3.04 KiB) Downloaded 49 times
-
- tourettesguy.asm
- (15.45 KiB) Downloaded 46 times
-
- tourettesguy.nes
- (72.02 KiB) Downloaded 51 times
Re: asm file with a dcm sample?
Using 'ld65 -t nes' has it use its built-in nes.cfg. To use a custom one instead, use 'ld65 -C nes.cfg'. I have added one line to the built-in config to add the SAMPLES segment (I did not test it), save this as 'nes.cfg' (or whatever filename you want) and put it in the same folder as your source files.
Later on, if you need to make your own config, it can be easier than it looks (without the compiler related stuff in the built-in one). Here's the config I use in my speech program.
Going for something simple, if you want to just play the one sample, forget about the lda (speech_lo),y stuff. Instead, we can try something like this:
Code: Select all
SYMBOLS {
__STACKSIZE__: type = weak, value = $0300; # 3 pages stack
}
MEMORY {
ZP: file = "", start = $0002, size = $001A, type = rw, define = yes;
# INES Cartridge Header
HEADER: file = %O, start = $0000, size = $0010, fill = yes;
# 2 16K ROM Banks
# - startup
# - code
# - rodata
# - data (load)
ROM0: file = %O, start = $8000, size = $7FFA, fill = yes, define = yes;
# Hardware Vectors at End of 2nd 8K ROM
ROMV: file = %O, start = $FFFA, size = $0006, fill = yes;
# 1 8k CHR Bank
ROM2: file = %O, start = $0000, size = $2000, fill = yes;
# standard 2k SRAM (-zeropage)
# $0100-$0200 cpu stack
# $0200-$0500 3 pages for ppu memory write buffer
# $0500-$0800 3 pages for cc65 parameter stack
SRAM: file = "", start = $0500, size = __STACKSIZE__, define = yes;
# additional 8K SRAM Bank
# - data (run)
# - bss
# - heap
RAM: file = "", start = $6000, size = $2000, define = yes;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
HEADER: load = HEADER, type = ro;
STARTUP: load = ROM0, type = ro, define = yes;
LOWCODE: load = ROM0, type = ro, optional = yes;
ONCE: load = ROM0, type = ro, optional = yes;
CODE: load = ROM0, type = ro, define = yes;
RODATA: load = ROM0, type = ro, define = yes;
DATA: load = ROM0, run = RAM, type = rw, define = yes;
SAMPLES: load = ROM0, type = ro, define = yes, start = $C000;
VECTORS: load = ROMV, type = rw;
CHARS: load = ROM2, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}
Code: Select all
MEMORY {
ZP: start = $00, size = $100, type = rw;
RAM: start = $200, size = $600, type = rw;
WRAM: start = $6000, size = $2000, type = rw;
PRG: start = $8000, size = $8000, type = ro, file = %O;
}
SEGMENTS {
CODE: load = PRG, type = ro, start = $8000;
RODATA: load = PRG, type = ro;
DATA: load = RAM, type = bss;
WRAM: load = WRAM, type = rw;
ZEROPAGE: load = ZP, type = zp;
BSS: load = RAM, type = bss, define = yes;
SAMPLES: load = PRG, type = ro, start = $C000;
VECTORS: load = PRG, type = ro, start = $FFFA;
}
Code: Select all
produceFuckSound:
ldy #$00
lda #$0F ; $00-$0F are playback speeds
sta $4010
lda #$40
sta $4011
lda #<((dmc_fuck_end - dmc_fuck) / 16)
sta $4013
lda #<((dmc_fuck - $C000) / 64)
sta $4012
lda #%00010000
sta $4015
rts
.segment "SAMPLES"
dmc_fuck:
.incbin "fuck.dmc"
dmc_fuck_end:
-
- Posts: 34
- Joined: Fri Feb 22, 2019 10:05 am
Re: asm file with a dcm sample?
Ah! There we go! Thank ye! It worked!Memblers wrote: ↑Tue Jan 04, 2022 3:57 am Using 'ld65 -t nes' has it use its built-in nes.cfg. To use a custom one instead, use 'ld65 -C nes.cfg'. I have added one line to the built-in config to add the SAMPLES segment (I did not test it), save this as 'nes.cfg' (or whatever filename you want) and put it in the same folder as your source files.
Later on, if you need to make your own config, it can be easier than it looks (without the compiler related stuff in the built-in one). Here's the config I use in my speech program.Code: Select all
SYMBOLS { __STACKSIZE__: type = weak, value = $0300; # 3 pages stack } MEMORY { ZP: file = "", start = $0002, size = $001A, type = rw, define = yes; # INES Cartridge Header HEADER: file = %O, start = $0000, size = $0010, fill = yes; # 2 16K ROM Banks # - startup # - code # - rodata # - data (load) ROM0: file = %O, start = $8000, size = $7FFA, fill = yes, define = yes; # Hardware Vectors at End of 2nd 8K ROM ROMV: file = %O, start = $FFFA, size = $0006, fill = yes; # 1 8k CHR Bank ROM2: file = %O, start = $0000, size = $2000, fill = yes; # standard 2k SRAM (-zeropage) # $0100-$0200 cpu stack # $0200-$0500 3 pages for ppu memory write buffer # $0500-$0800 3 pages for cc65 parameter stack SRAM: file = "", start = $0500, size = __STACKSIZE__, define = yes; # additional 8K SRAM Bank # - data (run) # - bss # - heap RAM: file = "", start = $6000, size = $2000, define = yes; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; HEADER: load = HEADER, type = ro; STARTUP: load = ROM0, type = ro, define = yes; LOWCODE: load = ROM0, type = ro, optional = yes; ONCE: load = ROM0, type = ro, optional = yes; CODE: load = ROM0, type = ro, define = yes; RODATA: load = ROM0, type = ro, define = yes; DATA: load = ROM0, run = RAM, type = rw, define = yes; SAMPLES: load = ROM0, type = ro, define = yes, start = $C000; VECTORS: load = ROMV, type = rw; CHARS: load = ROM2, type = rw; BSS: load = RAM, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; }
Going for something simple, if you want to just play the one sample, forget about the lda (speech_lo),y stuff. Instead, we can try something like this:Code: Select all
MEMORY { ZP: start = $00, size = $100, type = rw; RAM: start = $200, size = $600, type = rw; WRAM: start = $6000, size = $2000, type = rw; PRG: start = $8000, size = $8000, type = ro, file = %O; } SEGMENTS { CODE: load = PRG, type = ro, start = $8000; RODATA: load = PRG, type = ro; DATA: load = RAM, type = bss; WRAM: load = WRAM, type = rw; ZEROPAGE: load = ZP, type = zp; BSS: load = RAM, type = bss, define = yes; SAMPLES: load = PRG, type = ro, start = $C000; VECTORS: load = PRG, type = ro, start = $FFFA; }
Code: Select all
produceFuckSound: ldy #$00 lda #$0F ; $00-$0F are playback speeds sta $4010 lda #$40 sta $4011 lda #<((dmc_fuck_end - dmc_fuck) / 16) sta $4013 lda #<((dmc_fuck - $C000) / 64) sta $4012 lda #%00010000 sta $4015 rts .segment "SAMPLES" dmc_fuck: .incbin "fuck.dmc" dmc_fuck_end: