FCEUX + Midframe Palette Swap

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
Lucradan
Posts: 99
Joined: Wed Sep 21, 2016 12:08 pm

Re: FCEUX + Midframe Palette Swap

Post by Lucradan » Tue Nov 05, 2019 8:19 pm

tokumaru wrote: One alternative would be to point your IRQ vector to RAM, so you could select different handlers without any delays whatsoever (always make sure no IRQs fire while you're changing the address, or the program might crash).
Could you clarify on how to do this properly? I'm not getting it.

If I point the IRQ vector to a location in RAM, won't it try and execute code stored in RAM at that position?

lidnariq
Posts: 8786
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: FCEUX + Midframe Palette Swap

Post by lidnariq » Tue Nov 05, 2019 8:43 pm

Exactly. So you'd probably want to put JMP $xxyy in RAM for that.

Another option is instead to have JMP (indirect) in ROM, and only put the two bytes of the pointer in RAM instead of three bytes of an instruction. It's a little slower, however.

tepples
Posts: 21752
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: FCEUX + Midframe Palette Swap

Post by tepples » Tue Nov 05, 2019 9:32 pm

Busy waiting on $2002 bit 7 is fine in init code. Once the game is running, you'll need something that avoids a race condition that causes you to miss frames. Here's the simplest working way to wait for NMI:

Code: Select all

nmi_handler:  ; point vector $FFFA here
  inc nmis
  rti

ppu_vsync:
  lda nmis
@loop:
  cmp nmis
  beq @loop
  rts

User avatar
tokumaru
Posts: 11466
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: FCEUX + Midframe Palette Swap

Post by tokumaru » Tue Nov 05, 2019 9:38 pm

Sorry, I could have explained it better. And yeah, you do lose 3 cycles and 3 bytes from the JMP instruction in RAM, so there is a bit of a delay compared to pointing the vector straight to ROM.

Please do note that I was just mentioning an alternative way to implement multiple IRQ/NMI handlers, but there's nothing wrong with the way you were doing it.

User avatar
tokumaru
Posts: 11466
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: FCEUX + Midframe Palette Swap

Post by tokumaru » Tue Nov 05, 2019 9:54 pm

tepples wrote:

Code: Select all

nmi_handler:  ; point vector $FFFA here
  inc nmis
  rti

ppu_vsync:
  lda nmis
@loop:
  cmp nmis
  beq @loop
  rts
This is a direct alternative to polling $2002 - just poll nmis instead. Clean and simple.

However, this method of time keeping still has the disadvantage that you don't get the opportunity to run vblank tasks that can't be delayed - there are important things that are usually timed from vblank, such as status bars or sound engines, and you'll end up with visible or audible glitches if you miss the start of vblank, because these things won't be processed for a frame.

This is fine if you know for sure that your game engine never lags (easy to guarantee in simpler games with a limited number of active objects, but hard otherwise), or if you just don't care about music slowdowns or whatever, but if you're looking for a more robust way to handle vblanks, you should be handling NMIs the same way you're handling IRQs: use some sort of indirection so you can switch between different handlers in different parts of the game, and have each handler decide which tasks are critical and must be performed even during lag frames, and which will have to wait until the next vblank.

User avatar
rainwarrior
Posts: 7677
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: FCEUX + Midframe Palette Swap

Post by rainwarrior » Tue Nov 05, 2019 10:32 pm

Looking into this a bit more, the $00 grey was a problem with FCEUX. It seems to store $00 at $3F10/4/8/C for some reason. I've never noticed partly because I only ever looked at mid-screen palette changes to the background ($3F00) range before. That's a bit odd. I have filed an issue about it, will probably fix it myself later.

Edit: have fixed it, the problem was visual-only. It's available now as an interim build, but leaving the PR open for a few days first in case anyone has comments.
Last edited by rainwarrior on Wed Nov 06, 2019 12:11 am, edited 2 times in total.

User avatar
Lucradan
Posts: 99
Joined: Wed Sep 21, 2016 12:08 pm

Re: FCEUX + Midframe Palette Swap

Post by Lucradan » Wed Nov 06, 2019 12:06 am

Code: Select all

nmi_handler:  ; point vector $FFFA here
  inc nmis
  rti

ppu_vsync:
  lda nmis
@loop:
  cmp nmis
  beq @loop
  rts
This is what I ended up doing. I already had the frame counter in the NMI. The only warning I see with this is if I trigger an IRQ during this wait loop. That IRQ must restore the accumulator before RTI.

User avatar
Lucradan
Posts: 99
Joined: Wed Sep 21, 2016 12:08 pm

Re: FCEUX + Midframe Palette Swap

Post by Lucradan » Wed Nov 06, 2019 2:13 pm

Thank you everyone! You're AWESOME! I got it the IRQ handlers fixed and timed perfectly with Mesen. It takes 24 scanlines to change all the palettes. That's 3 lines per palette: 1 line to change the colors during hblank, one line to reset the scroll, and one line to relatch the IRQ (done outside the IRQ handler). I'm good with this for now.

You can see the current ROM below. Select "Continue" on the main menu to go to the Battle Screen. I reattached the input handlers to "ATTACK" menu option so you can see the damage label animation. I have a bunch more work to do, but it's coming together nicely.
Attachments
L5R.nes
(768.02 KiB) Downloaded 30 times

Post Reply