TIC-80 icon indicating copy to clipboard operation
TIC-80 copied to clipboard

Sync() does not change vbank 1 palette

Open KeplerElectronics opened this issue 2 years ago • 16 comments

So, My current project is set up such that some elements draw in vbank 0, and others draw in vbank 1, and different worlds of the game are held in different "content" banks accessed using sync().

However, when I call sync() to go to content bank 1, it does not render using the vbank 1 palette from content bank 1, but rather with the one from content bank 0.

To explain with images, This is the vbank 1 palette from content bank 1;

image

This is the vbank 1 palette from bank 0;

image

This is how it renders in-game, using the correct palette indices, but the wrong palette;

image

I cannot find any information on whether this is intentional behavior or unintentional behavior, although, as a different vbank palette is specified for each content bank in the editor, I would expect that it would change alongside the sprites and map data.

Is this an issue anyone else has run into?

KeplerElectronics avatar Jul 01 '22 17:07 KeplerElectronics

However, when I call sync() to go to content bank 1, it does not render using the vbank 1 palette from content bank 1, but rather with the one from content bank 0.

You'll need to be more specific, calling sync doesn't render anything...

VBANK0 and VBANK1 should have nothing to do with the 8 banks of cartridge RAM thought.

You can sync cartridge bank 4 or 6 and then draw to EITHER VBANK0 or VBANK1... they are entirely unrelated to SCREEN banks 0, 1, 2, 3, etc.

joshgoebel avatar Jul 01 '22 17:07 joshgoebel

it does not render using the vbank 1 palette from content bank 1

I also can't parse this, as there is only a single VBANK1 in all the hardware... so there is only a single VBANK1 palette (not one per "content bank"), etc...

joshgoebel avatar Jul 01 '22 17:07 joshgoebel

The only open question is how does sync SCREEN work with vbanking... and my guess would be that it syncs cartridge data into the ACTIVE vbank, though I could be mistaken.

joshgoebel avatar Jul 01 '22 17:07 joshgoebel

I guess my issue was that, since each content bank allows the definition of a separate vbank1 palette, I assumed that calling sync() would also change the palette to that defined in each content bank. It might be worth reworking this functionality in the future since that does not appear to be how it works (as you said there is only one vbank1 palette).

As this is not currently the functionality, is it possible to change the vbank1 palette using poke? When I was looking into the RAM layout, I am seeing that the addresses are identical to that of vbank0 for palette swaps, and there is no apparent location for vbank1's palette in ram (at least as it is currently documented).

KeplerElectronics avatar Jul 01 '22 18:07 KeplerElectronics

since each content bank allows the definition of a separate vbank1 palette

It does not. Could you point to any specific places on the wiki that lead to this conclusion? (if I can spot it I'd be happy to clean it up)

you said there is only one vbank1 palette

There is only a single VBANK0 and a single VBANK1. Those existing in _active RAM. sync copies "ROM" from the cartridge to RAM (or burns RAM to the cartridge "ROM"). I would expect copying a bank into memory would overwrite the active bank - whether it was bank 0 or bank 1. If you confirm that's not the case I would consider that a bug.

is it possible to change the vbank1 palette using poke?

Sure. But you have to swap banks first:

vbank(1)
-- poke whatever here
vbank(0)

and there is no apparent location for vbank1's palette in ram

It's at the same place as vbank1's palette. This is documented on the RAM layout:

https://github.com/nesbox/TIC-80/wiki/RAM#vram

joshgoebel avatar Jul 01 '22 18:07 joshgoebel

For example:

vbank(1)
sync(screen | palette, 3)
vbank(0)

Should copy the SCREEN and PALETTE from cartridge BANK3 into VRAM (specifically VBANK1).

joshgoebel avatar Jul 01 '22 18:07 joshgoebel

Could you point to any specific places on the wiki that lead to this conclusion? (if I can spot it I'd be happy to clean it up)

It's less a place on the wiki that led to that conclusion, but the editor itself. If you look back at the two sprite editor images I shared in the initial post, the palette on both images is set to bank 1, and each is allowed to have a separate palette defined.

(cropped here for ease)

image

image

Thanks for pointing out having to bank before poking, I hadn't realized that was the trick to write to vbank 1's palette, and as such got confused when the ram layout specified them as existing at the same addresses.

KeplerElectronics avatar Jul 01 '22 18:07 KeplerElectronics

For example:

vbank(1)
sync(screen | palette, 3)
vbank(0)

Should copy the SCREEN and PALETTE from cartridge BANK3 into VRAM/VBANK1.

I also can't quite get this to function properly, it refuses to run if I take it exactly as is, though it does work if I do

vbank(1)
sync(32 | 128,1)
vbank(0)

Figured I'd toss it here in case someone else has the same issue and comes here, I've used issues on here to find solutions in the past.

KeplerElectronics avatar Jul 01 '22 19:07 KeplerElectronics

but the editor itself.

Ah... I see now... because our save file format groups the palettes together... so you're right, you have 16 palettes... spread across 8 banks. Sometimes I forget how different the cartridge format is.

sync(32 | 128,1)

Yeah, I was using the same placeholders the wiki does, you'd need to define those or use constants.


So now the question is what happens when you do:

vbank(0) -- just to start from a normal place
sync(palette, 3)

Are you saying that only updates VBANK0 and not VBANK1? Are you doing your drawing using vbank(1) or inside OVR? You'd need to be using vbank1 to get those colors...

joshgoebel avatar Jul 01 '22 19:07 joshgoebel

So now the question is what happens when you do:

vbank(0) -- just to start from a normal place
sync(palette, 3)

So if I place this into my code before bank switching, it works as you'd expect, it pulls the palette over from cartridge bank 3, only changing vbank 0, which is expected, as we have not called vbank(1) first.

Now, if we do

 vbank(1)
 sync(palette, 3)

it does change vbank1's palette, but it changes it to the vbank 0 palette specified in cartridge bank 3 instead of the vbank1 palette.

KeplerElectronics avatar Jul 01 '22 19:07 KeplerElectronics

it pulls the palette over from cartridge bank 3, only changing vbank 0, which is expected,

Actually I'm not sure that's expected - or I don't think it's 100% clear what should happen.

When the cartridge "boots" BOTH palettes are synced from cart BANK0 into VBANK0 and VBANK1... so it seems quite reasonable that this might also happen when you call sync also.

it does change vbank1's palette, but it changes it to the vbank 0 palette specified in cartridge bank 3 instead o

I'd say that's a bug.

sync(palette, 3)

One other thing that could be fooling you is that you can only call sync ONCE per frame... if you call it a second time it will do nothing so code liek this will never do anything useful (whatever you think it should/might do):

vbank(0)
sync(palette, 3)
vbank(1)
sync(palette, 3)

The second call to sync will do nothing at all.

joshgoebel avatar Jul 01 '22 19:07 joshgoebel

@nesbox It sounds like sync may not be taking vbank into account - that the default palette is always getting copied over the "active vbank" palette... I'm thinking we should likely copy BOTH palettes from a bank into vbank0.palette and vbank1.palette (same as happens at boot). This would be a potentially breaking change though.

I didn't test this, I'm going solely based on this report.

joshgoebel avatar Jul 01 '22 19:07 joshgoebel

I realize this issue is a bit old, but could this be solved by adding another bitflag to sync() for vbank1 palettes?

nununoisy avatar Sep 13 '22 19:09 nununoisy

Again, pretty sure this is a bug - not something we need another flag for - but obviously it's not currently a high priority issue, sorry.

joshgoebel avatar Sep 13 '22 19:09 joshgoebel

Fair enough. I'm willing to write a PR, I just need to know what approach would be preferred.

nununoisy avatar Sep 13 '22 20:09 nununoisy

I still concor with myself:

I'm thinking we should likely copy BOTH palettes from a specified bank into vbank0.palette and vbank1.palette (same as happens at boot).

IE, just another "magic" feature of the hardware. I feel like we need @nesbox to weigh in those because technically it's a breaking change of anyone relying on the current "broken" behavior.

Since this was fairly recent change though I'm thinking perhaps we can just accept that if we call the current behavior a bug...

joshgoebel avatar Sep 14 '22 16:09 joshgoebel

added palette syncing for both vbanks simultaneously 9f5744646b5c9c943b9719f7a085f8abb9b52f36

nesbox avatar Feb 05 '23 13:02 nesbox

Hello, I believe this issue persists to this day. I am using the Pro version 1.0.2164.

This is what I have in the sprite editor. Bank 0: image

image image

Bank 1: image

image image

This is what I have during runtime. Sync to bank 0, sync(32,0): image

Sync to bank 1, sync(32,1): image

Vbank1 should be red.

AshBC91 avatar Apr 30 '23 02:04 AshBC91