Live playback

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Live playback
by on (#34145)
Hey NESDev,

I'm a NSF composer and I'm looking into playing live shows. I have a problem though. As most of you know, the Powerpack is unavailable and I'm still looking for one in outside sources. I wanted to know if one can get NSF playback with the Powepack Lite? I don't use any chip extensions in my NSFs.

by on (#34147)
I am in the process of installing my copyNES. I was planning on making an NSF cart with my power pack lite as soon as it's installed. I'll let you know how it turns out!

However, there is NO REASON I can see why the playback code wouldn't work on the powerpack lite! It's a flash cart that is supposed to contain a rom image. The NSF playback code is a rom like all others. Note that powerpack lite will NOT work outside of copyNES.

Good luck with your endeavors, I would like to hear your music.

by on (#34151)
Don't.

by on (#34153)
Don't what, and why not?

by on (#34155)
You must be new here. Familiarize yourself with NotTheCommonDose's posts first.

by on (#34156)
NotTheCommonDose wrote:
Don't.


I'm thinking it means "Don't attempt this" or "Don't even try" or something like that. I don't know, it could mean anything. It might mean "Don't eat bananas".

by on (#34256)
So I have USB copyNES installed, and have created a simple ROM to playback an NSF (using Nullsleep's x816 nsf cart guide).
I need to make the rom I made a standard iNES rom, however, so I've got to add the header. Should I add assembly to create a header to my rom, build it, and then rename it to .NES?

Edit: Also, to the author of the thread: Power Pak Lite with copyNES might not work for your live playback. After you copy your data to Power Pak Lite, you cannot turn off the NES or you lose your data.
It would still work if you flash the cart at your shows with a laptop, and then just leave the NES on.

The solution that I'm going to use is to develop a track select routine into Nullsleep's cartridge playback code and then just burn Eprom carts for live playback (burning eprom carts is no more complicated than installing copyNES). I want to avoid having a laptop at my shows at all costs (though there's certainly nothing wrong with having one, I have done it before).

by on (#34264)
Sure, an iNES file is just the ROM binary with a header prepended. So unless your assembler can generate the header automatically you'll have to slap one on yourself.

by on (#34266)
Thanks Mic - I am going to try that as a sanity check.

I am working on NESASM (w/ Nbasic) NSF playback code containing a track select routine.
I think this will be a simple ROM, but one that is totally essential for NES musicians. If we can do this it will have HUGE reverberations in nes music the world over.
We can't get new powerpaks right now, so we need a DIY solution!

by on (#34267)
NESASM automatically generates the header for you.

For example, these are the directives you'd use for a 40kB NROM:

.inesprg 2
.ineschr 1
.inesmir 1
.inesmap 0

by on (#34271)
Nevermind. I had a thought but I forgot it sorry. Please disregard "Don't"

by on (#34272)
And for another assembler, it might look like this:
Code:
.segment "INESHDR"
.byt 'N', 'E', 'S', 26  ; header
.byt 2  ; PRG size in 16384 byte units
.byt 1  ; CHR size in 8192 byte units
.byt 0  ; flags 6
.byt 0  ; flags 7
.res 8  ; pad to 16 bytes


by on (#34274)
Ok, here's my first pass: it's a mashup of Nullsleep's cart code and Bob Rost's startup code, written for NESASM. I want to nail playing back a single track before adding the track select routine to the main loop.

I'm new at NES programming. Really new. Sorry for suckness.
This compiles, but it doesn't play back or doanything in NESTOPIA. Any ideas of what I am doing wrong?

Code:
Edited with Celius's changes:
*************

.inesprg 1 ;//one PRG bank
   .ineschr 1 ;//one CHR bank
   .inesmir 0 ;//mirroring type 0
   .inesmap 0 ;//memory mapper 0 (none)   
   .org $A93F ; replace dashes with load address MINUS $80
   .bank 0   
   
   .incbin "guitthing2.nsf"
start:

   
   cld ;
   sei ;//disable interrupts
   lda #$00
   sta $2000
   sta $2001

   jsr vwait
   jsr vwait
   
   ldx #$00
   
   Clear_Sound:
   
     sta $4000,x       
     inx
     cpx #$0F
      bne Clear_Sound

   lda #$10      ; load accumulator with $10
   sta $4010   ; store accumulator in $4010
   lda #$00      ; load accumulator with 0
   sta $4011   ; clear these 3 registers that are
   sta $4012   ; associated with the delta modulation
   sta $4013   ; channel of the NES

   ldx #$ff
   txs                 ;//reset the stack
   lda #%00001111      ; enable all sound channels except
   sta $4015          ; the delta modulation channel      
   lda #$C0          ; synchronize the sound playback routine
   sta $4017          ; to the internal timing of the NES
   
   lda #$01      ; replace dashes with song number
   ldx #$00      ; replace with $00 for NTSC or $01 for PAL
   jsr $B200      ; replace dashes with init address

   
   lda #%10000000   ; enable vblank interrupts by setting the
   sta $2000      ; most significant bit of $2000
   

mainloop:
   jmp mainloop

nmi:
      lda $2002      ; read $2002 to reset the vblank flag
      lda #%00000000   ; clear the first PPU control register 
      sta $2000      ; writing 0 to it
      lda #%10000000   ; reenable vblank interrupts by setting
      sta $2000      ; the most significant bit of $2000
      jsr $B203      ; replace dashes with play address
      rti             ; return from interrupt routine
   
irq:
   rti
   
vwait:
   lda $2002
    bpl vwait
   rts



;//jump table points to NMI, Reset, and IRQ start points
   .bank 1
   .org $fffa
   .dw nmi, start, irq


http://rapidshare.com/files/122933198/g ... 2.nsf.html

by on (#34275)
You do JMP vwait, and then RTI. Change JMP to JSR, and RTI to RTS. If you really care to know why, RTI is ReTurn from Interrupt, and when you do that, it won't do what you want since you're in the reset area of your code. JSR (Jump to SubRoutine) allows you to jump from one area of your code to another and you can just do RTS (ReTurn from Subroutine) to go back to where you jumped from with a simple instruction. JMP just goes from one area of your code to another without remembering where you jumped from.

Edit:

Code:
*************
  ....

   jsr vwait
   jsr vwait

 .....
vwait:
   lda $2002
    bpl vwait
   rts
...


That's what you should change, in case I was unclear about anything.

by on (#34276)
Thanks Celius, that's great.
With your change, the generated rom is deffinitely busting through
Code:
   ldx #$00

Clear_Sound:
   
     sta $4000,x       
     inx
     cpx #$0F
      bne Clear_Sound


And beyond.
However, right now it just makes a single square beep. If I change that initial "ldx #$00" to "ldx #$01", it changes the duty of that single square beep. But that's all I can do with this code, hah, it's not playing back my nsf code for some reason. I successfully flashed it with copyNES and tried stepping through it with MICROBUG. I think I am not using the ".org" correctly, and that the assembler is missing the bulk of my NSF code. If I change the ".org" to $8000, it repeats the single square pulse infinitely!

I'm working on it constantly - but any more help would still rock and shock the casbah!

Also, Obe, do you use Famitracker? It has an export to .PRG function. CopyNES (and some other programs) can easily turn a .PRG file into an NES file (removing some of the work described in this thread). The NES file can then be flashed onto copyNES. It only works for one song at a time, though. Yep - the regular Power Pak is so much easier. But me, I need to playback NSFs live now, I've got to get on the road in August!

by on (#34278)
Code:
.inesprg 1 ;//one PRG bank
   .ineschr 1 ;//one CHR bank
   .inesmir 0 ;//mirroring type 0
   .inesmap 0 ;//memory mapper 0 (none)   
   .org $A93F ; replace dashes with load address MINUS $80
   .bank 0   
   
   .incbin "guitthing2.nsf"
start:


How large is your NSF? You've told NESASM that you only want one PRG bank (16kB). Does everything fit in 16kB?

You might want something like:

Code:
[code].inesprg 2 ;//Two PRG banks
   .ineschr 1 ;//one CHR bank
   .inesmir 0 ;//mirroring type 0
   .inesmap 0 ;//memory mapper 0 (none)
   
   .bank 0   
   .org $8000
   
   start:

   ; blah blah blah..

   .org $A93F ; replace dashes with load address MINUS $80
   .incbin "guitthing2.nsf"

   .bank 1
   .org $fffa
   .dw nmi, start, irq
[/code]

by on (#34280)
CopyNES DID throw an error when I tried to run it with 16kb - so I added another program bank and it flashed successfully, but still no NSF playback - but I wasn't changing the bank like I think you are doing. Thanks - this will be in my next build.

So does ".org" send the PC to the memory location next to it?

by on (#34281)
.org gives information to the assembler about how to resolve labels, and where in the ROM to place your code/data. PRG-ROM on the NES is mapped into the CPU's memory space starting at $8000.

by on (#34282)
After changing ".inesprg 1" to "inesprg 2", nestopia gives me "Corrupt file!" error. Can't check this on real hardware currently (away from my NES). Here's what the code looks like now:

Code:
   .inesprg 2 ;//two PRG bank
   .ineschr 0 ;//no CHR bank
   .inesmir 0 ;//mirroring type 0
   .inesmap 0 ;//memory mapper 0 (none)     
   .org $8000
   .bank 0   
 
   
start:


   cld ;
   sei ;//disable interrupts
   lda #$00
   sta $2000
   sta $2001

   jsr vwait
   jsr vwait
   
   ldx #$00
   
   Clear_Sound:
   
     sta $4000,x       
     inx
     cpx #$0F
      bne Clear_Sound

   lda #$10      ; load accumulator with $10
   sta $4010   ; store accumulator in $4010
   lda #$00      ; load accumulator with 0
   sta $4011   ; clear these 3 registers that are
   sta $4012   ; associated with the delta modulation
   sta $4013   ; channel of the NES

   ldx #$ff
   txs                 ;//reset the stack
   lda #%00001111      ; enable all sound channels except
   sta $4015          ; the delta modulation channel     
   lda #$C0          ; synchronize the sound playback routine
   sta $4017          ; to the internal timing of the NES
   
   lda #$01      ; replace dashes with song number
   ldx #$00      ; replace with $00 for NTSC or $01 for PAL
   jsr $B200      ; replace dashes with init address

   
   lda #%10000000   ; enable vblank interrupts by setting the
   sta $2000      ; most significant bit of $2000
   

mainloop:
   jmp mainloop

nmi:
      lda $2002      ; read $2002 to reset the vblank flag
      lda #%00000000   ; clear the first PPU control register
      sta $2000      ; writing 0 to it
      lda #%10000000   ; reenable vblank interrupts by setting
      sta $2000      ; the most significant bit of $2000
      jsr $B203      ; replace dashes with play address
      rti             ; return from interrupt routine
   
irq:
   rti
   
vwait:
   lda $2002
    bpl vwait
   rts

   .org $A9BF  ; load address of NSF (offset 0008)
   .incbin "guitthing2.nsf"

;//jump table points to NMI, Reset, and IRQ start points
   .bank 1
   .org $fffa
   .dw nmi, start, irq
   

by on (#34284)
I don't think there are any mapper 0 games with no CHR-ROM. Set ineschr to 1 instead.