Code for cycling certain subpallettes on specific screens?

darkhog

New member
Can someone write me a code that cycles certain subpalette (in my case second bg subpal) on certain screens (with a screen flag set)? By cycling I mean 1st color becomes 2nd, 2nd 3rd, 3rd becomes 1st (we can't change bg color) each frame.
 

FrankenGraphics

New member
Facts we need to know:
-Updating the hardware palettes directly in a cycling fashion is tedious, takes time, and can only be done during VBLANK (a period the game needs for more essential stuff), because of reasons. I can explain if someone asks the question.
-Instead, we ideally want to cycle data in a shadow buffer that the NMI routine always (or conditionally) uploads to hardware palette memory anyway each frame.
-Disclaimer - i don't know if NESmaker uses such a buffer, but it should in order to be truly modular. Some games simply load Palette data directly from ROM to PPU, which can be straightforward at first, but limits your options to conveniently manipulate palettes without wasting ROM.

Okay, so here's the theoretical routine. I wrote it on the fly while composing this reply, no testing.

at the strike of some timer, call this routine (jsr PickPaletteToCycle) to cycle the palette one step.
You can choose which one by changing the literal constant (i set it to #0) to a value between 0-7, or to some variable of your choosing (also the same expected range).

Code:
PickPaletteToCycle:
;notice -- this routine will clobber anything that is in registers a, x and y. If something in a,x or y needs to be stored for later use, do so before calling this routine.
lda #0 ; you can replace this with another literal, or a variable if you wish (expected values 0-7. Don't go higher or you'll run into some other RAM section)
asl a
asl a ;these multiply your literal or variable with 4 so we can get the right offset for each palette in increments of 4.
tax
CyclePaletteRightOnce:
ldy PalDataInRAM+3,x ;pocket colour 3 in reg y
lda PalDataInRAM+2,x 
sta PalDataInRAM+3,x ;move colour 2 to 3
lda PalDataInRAM+1,x 
sta PalDataInRAM+2,x ;move colour 1 to 2 
sty PalDataInRAM+1,x ;move pocket (y) to 1
rts

IMPORTANT:
replace PalDataInRAM with whatever label NESmaker is using for its temporary RAM storage of palettes. That is, if it does. It also requires the RAM buffer to be identical in structure to the hardware palette structure in PPU RAM. Else you need to do some alterations to NESmaker, so that it does both those things, in order for this routine to function.

you can naturally make it cycle in the other direction if you prefer that.
 

Bucket Mouse

Active member
Are we talking about an effect like the question mark blocks in Super Mario Bros? Because there may be a way to do that baked into NESMaker already. An early beta video showed that off: https://youtu.be/ZRNqhP72oRU

You can see the ASM in that video, if it still works.

Also: how do you keep an effect specific to a certain screen? I need to know that for my own projects...
 

FrankenGraphics

New member
I assume this is the type of effect the OP wants to achieve, more or less?
flowofwater_nosprites.gif

snapshot from halfway through building level 3-B in our game-in-development Project Blue (shameless plug) that's supposed to be released in early 2019.

(It is actually using a quite different topology if you look underneath the surface. Each 'slot' in a palette definition can either be a simple unanimated colour, or a so-called "animation", which is a sequential string of up to 16 colours, each with its own duration metadata for each entry in that string. It is sort of wasted on this type of three-step flow since it requires three such animations, one for each palette slot, and is really geared towards more complex colour animations. As is, it spends 96 bytes when it could spend 0, haha. But the end result in this particular case is the same if i understood the request correctly. that sort of scheme can be done with less complex methods).
 

Mihoshi20

Member
I could see this coming in handy in many ways. Very classic for water effects and also the ? Blocks in many of the mario games. A lot of games also used them for cascading backdrops or flash effects. Very cool to see this implemented.
 

darkhog

New member
FrankenGraphics said:
I assume this is the type of effect the OP wants to achieve, more or less?
flowofwater_nosprites.gif

Yep, this is the sort of effect I want. Note that I'm looking for ready-made solutions, if I'd know how to make it myself, I'd just go and make it instead of making this thread and one for flicker routine.
 

FrankenGraphics

New member
Finally downloaded and had a look at the code. It looks like my code will work, it's just that NESmaker has a slightly different order in how it stores its palette buffer:

Code:
bckPal .dsb 16				;
	bckPalFade .dsb 16
	spriteSubPal_0 .dsb 4			;playerPal
	spriteSubPal_1 .dsb 4				;magicPal
	spriteSubPal_2 .dsb 4				;objPal1
	spriteSubPal_3 .dsb 4				;objPal2
	spritePalFade .dsb 16
(from line 120 in routines\variables\ZP_and_vars.asm, v.4.0.0)

So here's a table what happens if you feed my routine different values:
0-3 is directly affecting one of the background palettes
4-7 is directly affecting one of the background "fade" palettes
8-11 is directly affecting one of the sprite palettes
12-15 is directly affecting one of the sprite "fade" palettes.

So valid entries are not 0-7, but rather 0-15. I kind of assume "fade palettes" are generated from the normal palettes somehwhere in the code, but i haven't had a look.

Here's the routine with updated labels:
Code:
PickPaletteToCycle:
;notice -- this routine will clobber anything that is in registers a, x and y. If something in a,x or y needs to be stored for later use, do so before calling this routine.
lda #0 ; you can replace this with another literal, or a variable if you wish (expected values 0-15. Don't go higher or you'll run into some other RAM section)
asl a
asl a ;these multiply your literal or variable with 4 so we can get the right offset for each palette in increments of 4.
tax
CyclePaletteRightOnce:
ldy bckPal+3,x ;pocket colour 3 in reg y
lda bckPal+2,x 
sta bckPal+3,x ;move colour 2 to 3
lda bckPal+1,x 
sta bckPal+2,x ;move colour 1 to 2 
sty bckPal+1,x ;move pocket (y) to 1
rts


That's all you need to upcycle any subpalette one tick. Call this routine every x:th frame and you have animation. All you need to figure out is how to either hook up a timer to trig the routine, or write a new timer on your own. If you don't want to hook it up to preexisting timers and triggers in NESmaker, you can add variables to routines\variables\UserVariables.asm and define them there like so:
Code:
MyTimerVariable .dsb 1
for example. NESmaker conveniently allows for 256 user variables like this in RAM. Now you can use that label for your own purposes, like writing a small timer routine.

Note that I'm looking for ready-made solutions, if I'd know how to make it myself, I'd just go and make it instead of making this thread and one for flicker routine.

Well that's the thing. There are no ready made solutions - except the ones people are willing to write up and distribute for free in their spare time. Which is generally kind of a lot to ask. Most people rather work on their own projects. I just happened to be building my own library of code right when you asked, so it came at a convenient point and gave me a good reason to write such a feature, which is a win-win. But the typical customary thing over at NesDev.com, which has a pretty healthy community economy regarding this, is when you ask for for help, you're also expected show that you've taken the time to do some research (usually by reading up on 6502.org, the nesdev wiki, and/or search the forums for similar threads where the question might already have been answered in part or in full) - so you trade time for time, get more confident, and get to a point where you'll start to contribute to other people in need of help and advise. It's a pass this on economy. There's also the "give a man a fish/teach a man to fish" proverb.

Honestly IMO NESmaker should probably drop the "no coding required" subslogan. It is technically true, but sets too high expectations. If i understand it right, Joe is basically drowning in PM:s about peoples' feature requests, reasonable or not. Had there been any economy in it, he ought to have a technically informed secretary, haha. A lot of users will want to do more than is possible out of the box out of sheer creative drive, and to do that, coding is required.

All that said, please ask questions if something in my proposed solution is unclear.
 

dale_coop

Moderator
Staff member
You're exactly right FrankenGraphics. And I appreciate you spend to much of your (precious) time to reply and enlighten us.

NESMaker is a software that can help you making a game without coding. And it's true in a certain way... you can make a simple game without codings saying in limitations imposed by the tool.

A lot of modules will come in the next 2 months (cf the schedule on the official webpage). So more and more things will be able without coding.
Now of course, NESMaker is a "Trojan Horse", more you play / try and more you want to hack certain parts, wanted things that are not in the tool. Then you have to dig in and try to learn the ASM language (in the beta tutorial videos http://vimeo.com/joegranatoiv Joe made some video to teach how to code for NESMaker, it's very instructive)

I never did ASM code before NESMaker... I learn so much in the last few weeks than years trying before. Just with NESMaker and Joe's videos!
Thank you Joe
 

MistSonata

Moderator
Okay, so I've been messing around with some stuff and it looks like I was able to get it to work.

Unfortunately, FrankenGraphics, there's a couple things that were missing from your code.

Code:
PickPaletteToCycle:
    ;notice -- this routine will clobber anything that is in registers a, x and y. If something in a,x or y needs to be stored for later use, do so before calling this routine.
    LDA #0 ; you can replace this with another literal, or a variable if you wish (expected values 0-15. Don't go higher or you'll run into some other RAM section)
    ASL
    ASL ;these multiply your literal or variable with 4 so we can get the right offset for each palette in increments of 4.
    TAX
CyclePaletteRightOnce:
    LDY bckPalFade+3,x ;pocket colour 3 in reg y
    LDA bckPalFade+2,x 
    STA bckPalFade+3,x ;move colour 2 to 3
    LDA bckPalFade+1,x 
    STA bckPalFade+2,x ;move colour 1 to 2 
    STY bckPalFade+1,x ;move pocket (y) to 1
    LDA #$01
    STA updatePalettes ;; loading anything but zero into this value tells NESmaker it needs to update palettes.
    RTS

You have to use the bckPalFade variable, and you then need to store a non-zero number into the updatePalettes variable when you're done.

The one other thing I still need to figure out is how to use the frame timing variable in order to animate it, but until then I loaded the code into an AI script (minus the RTS, because those AI scripts get weird when you RTS) and made a monster that would cycle through this code. It took a bit of work to get it to execute the code at a decent pace, but it works!

OH NO, MY SHIP!!! :(
 

FrankenGraphics

New member
Thanks for the update!
Makes sense. It's common for many games to check if an update is pending, so the start of NMI can prioritize what it ought to do/not do during the Vblank period, rather than just uploading everything (including the same old data) every vblank. This is extra-important for scrolling games, since updating large strips of the nametables is heavy lifting/time intensive while rendering is on.

I need to have a look at what bckPalFade is supposed to do anyway. From your description it sounds like it is using it explicitly for new indata, and not the other way around, like i assumed.
That makes the prep routine kind of redundant; except that it rules out risks for human error. So if you wanted, you might as well load x with a specific value directly and skip right ahead to CyclePaletteRightOnce. If a literal, you can do it like so: LDX #n*4. The *4 is then calculated at assembly time, rather than runtime. Not that it makes that much of a difference in efficiency since the routine is only called once every few frames and the overhead is just a couple of cycles.

Haha, nice accident with the ship. Oh btw, i'm sure you meant nothing by it but just in case, i'd like to take the opportunity to say that my graphics are not free to reuse, modify, or repackage unless explicitly stated, or if private permission is given. That water is used in a game with commercial intentions and is supposed to be unique to that particular game. this GIF is not a problem for me, but please refrain from using it in any game.

Here's a general description for timers for anyone who comes across this thread:
Timers are a good building block that comes up a lot in game development. The principle is that they're one-byte variables, and you decrease them once every frame. When they reach zero, they "strike" (you check your timers with BEQ or BNE; equal or not equal, which in this case is just another way to say zero or not zero). You then set them to a new value of 1-255, which is the interval of your timer. For timers that need more time than 256 frames, you can set one timer to decrease only when another timer strikes. That base timer then serves as a time multiplier. Typically, several long-range timers depend on the same base per-frame timer. Here, though, we want it to strike several times per second, so a simple 0-255 timer will suffice. You sometimes also need some extra of condition to be able to pause or reset timers prematurely, depending on context. Or in this case you can have the timer running free and simply ignore its strikes when it is not in use.

Warning/tip:
with this sprite cycling scheme, be aware that after disabling the cycling, you will want to overwrite the palette one last time with a preset palette so you don't leave with colours being shuffled in the wrong order 2/3 of the time. Like if you for example want to be able to freeze water still, as in castlevania 3. In many cases this sort of thing is not a worry if your screen switch procedure involves refreshing the palettes anyway.

----
edit: updated the second paragraph because my stream of words didn't make sense.
 

MistSonata

Moderator
FrankenGraphics said:
Haha, nice accident with the ship. Oh btw, i'm sure you meant nothing by it but just in case, i'd like to take the opportunity to say that my graphics are not free to reuse, modify, or repackage unless explicitly stated, or if private permission is given. That water is used in a game with commercial intentions and is supposed to be unique to that particular game. this GIF is not a problem for me, but please refrain from using it in any game.

Don't worry, it was just for demonstration purposes.

FrankenGraphics said:
Here's a general description for timers for anyone who comes across this thread:
Timers are a good building block that comes up a lot in game development. The principle is that they're one-byte variables, and you decrease them once every frame. When they reach zero, they "strike" (you check your timers with BEQ or BNE; equal or not equal, which in this case is just another way to say zero or not zero). You then set them to a new value of 1-255, which is the interval of your timer. For timers that need more time than 256 frames, you can set one timer to decrease only when another timer strikes. That base timer then serves as a time multiplier. Typically, several long-range timers depend on the same base per-frame timer. Here, though, we want it to strike several times per second, so a simple 0-255 timer will suffice. You sometimes also need some extra of condition to be able to pause or reset timers prematurely, depending on context. Or in this case you can have the timer running free and simply ignore its strikes when it is not in use.

There already seems to be something like this in "HandleGameTimer.asm", except that it counts up instead by using the carry flag.

Code:
HandleGameTimer:
	DEC gameTimer
	BNE dontUpdateGameTimer
	LDA gameTimerLo
	CLC
	ADC #$01
	STA gameTimerLo
	LDA gameTimerHi
	ADC #$00
	STA gameTimerHi

FrankenGraphics said:
Warning/tip:
with this sprite cycling scheme, be aware that after disabling the cycling, you will want to overwrite the palette one last time with a preset palette so you don't leave with colours being shuffled in the wrong order 2/3 of the time. Like if you for example want to be able to freeze water still, as in castlevania 3. In many cases this sort of thing is not a worry if your screen switch procedure involves refreshing the palettes anyway.

NESmaker already seems to refresh palettes when screen switching, so that's not a problem

Convoy_Avenger said:
Has anyone gotten this working in a game/sample they can show off yet? Would love to see it in action.

There's a link to a video at the bottom of my previous post.
 

FrankenGraphics

New member
yeah that timer is using a 16bit base (if gameTimerLo wraps around, add carry to gameTimerHi). The third variable (gameTimer, appearing first), seems to effectively be a start/pause mechanism for the timer block (edit: either that or a time base for GameTimerLo) It must be 0 after the DECrease in order to do one uptick; else, no action is taken here.
 

MistSonata

Moderator
It seems like gameTimer itself is tied to the day/night cycle, it resets to the variable stored as #DayNightSpeed after jumping to the DoAlarm subroutine, but that seems to be set to 0 currently. Right now it means that gameTimerLo is the actual framecount, but once the #DayNightSpeed is changed it'll make the count for gameTimerLo and gameTimerHi slower...
 

FrankenGraphics

New member
If you want to construct your own timer, you don't need to use a separate pause variable btw. you can use conditions like bpl and bmi by reading the N flag.

in signed math/twos' complement, any value above $7F is considered to be a negative. Loading something that's #$80 or above thus sets the N flag and anything that's #$7F or below will clear it, which you can test.
Code:
updateMyTimer:
lda myTimer
bmi skipAhead ;if N is set, don't update this timer
dec
bne skipAhead
;if zero, do something, set a flag or whatever, and reset the timer to up to #$7f here if you want it to re-run, or to #$80 if you want it to halt.
skipAhead:
;next routine goes here.

so for example, if myTimer is set to #$80, it is paused. if you decrease or subtract it manually, next time the update routine is run, it will start to count down.

That means this timer has a max length of about two seconds on NTSC, which is still plenty for quick effects like palette slot cycling. If you want to make effects like this consistent across NTSC and PAL, you ought to bind timers like this to either a master timer or a variable duration that has a compensating time base for the two standards.

That's just one possibility. Since you can check for zero, and then for wraparound using the N flag on the next frame, you can check for two separate things on consecutive frames with the help of one countdown timer.

Or if you want to update several timers using the same scheme, you can declare them next each other in RAM and replace
Code:
lda MyTimer
with
Code:
lda MyTimers,x
where x will pick which timer to update, provided that you've loaded x with an appropriate value. You can optionally iterate this routine in a loop so that it goes through all your timers. x is typically counted down too so that when it wraps around (bmi), you know that it has done all your timers.

btw another way to write the same routine that you found, is to use the +1 trick. you'll encounter this often in other peoples' code, because it saves the programmer from defining multiple variables that are supposed to be the same, and may in some cases increase code clarity (not in the example given though haha):

Code:
HandleGameTimer:
	DEC gameTimer
	BNE dontUpdateGameTimer
	LDA gameTimerLo
	CLC
	ADC #$01
	STA gameTimerLo
	LDA gameTimerLo+1
	ADC #$00
	STA gameTimerLo+1

It doesn't make much sense here since the label "gameTimer" is already occupied, but this is why you see variables like ptr and ptr+1 whenever you're using a 16bit word.
if a variable called, say, ptr (traditional shorthand for pointer) is using cpu address $00, ptr+1 is using cpu address $01.

So no effective change between doing it like this or doing it like so:
ptrLo
ptrHi

except some programmers think one is more convenient than the other. As you saw with my shuffling example draft, the + method becomes a lot more convenient when you're working with address ranges bigger than just two bytes.
 

SeaFoodAndButter

New member
Honestly IMO NESmaker should probably drop the "no coding required" subslogan. It is technically true, but sets too high expectations.

I totally agree. It is tech true, but it is actually pretty misleading. You can only make a very basic and generic game. Without coding, you can't really make the game "you want."

The problem is, because NESMaker was heavily promoted as an interface that allows people with no coding knowledge to make a game, it appeared to many that the door to making a game had been opened to them; but this is not necessarily the case. I would argue that there are more people in the NESMaker community that don't know how to code than do; and this percentage will only increase. This is a direct result of how NESMaker was and still is marketed "Make a Game without Coding!" This is also why Joe's inbox and this forum are getting flooded with coding questions and help messages. Tons of people thought they code finally make a game despite the fact they don't know how to code 6502 (or anything really). That's just the facts ya know?

And I agree with your fish and fisherman proverb on priniciple. However, if you tell someone they can have and eat a fish if they come over, then when they come they find out what you said was tech true, but you left out the part that you expected them to know how to steer a boat in turbulant water, know where the fish are, bring their own fishing pole because they need to catch and clean their own fish. You're just letting them use your boat, bait, and grill, you'd probably feel a bit mislead right?

That's like Burger King saying "Have it Your Way!" Then when you get there they tell you, "Of course, you can have whatever burger you want, you just need to know how to cook it, the grill, pantry, and kitchen are over there, good luck." I mean, you COULD probably go make something, but it's not going to be a Burger King burger. This is sort of the situation going on right now for many people.

Also, I wouldnt assume people don't know how to code because they are lazy or haven't put in any effort, I think an assumption like that is an oversimplification.

I know nothing about coding other than I understand the extreme basics of how it works. This is not for a lack of trying. I just dont understand how to take my ideas and get the code to make it happen.

It's not that I'm not willing to fish, it's that I don't know how. And the type of fishing we are talking about here isn't simply taking a fishing pole and some worms down to the local pond. It's more like having to learn to navigate an ocean liner in deep sea water to track down an endangered species of whale that requires special rigs and equipment to get on board and a very specific refining process to extract and preserve a certain chemical that is found in a specific body part. It would take a long time to learn to fish in that sense.

I completely understand that there is no way around coding. I accept it. I'm just going to have to do my best to get something made and hope that 1) I can get some folks to help me big time and 2) hope that I can start to understand how to code what I want.

Making a game is actually a pretty big undertaking and a major time consuming project to commit to. It's not like fishing in a small pond. People need to know this before deciding to get into NESMaker, not "Make a Game without Coding!"

It's going to take a lot more than than a simple afternoon's fishing lesson at the local pond.
 

FrankenGraphics

New member
I would argue that there are more people in the NESMaker community that don't know how to code than do; and this percentage will only increase.
I'm a bit more optimistic about this. NESmaker can and is already acting as a portal which as conveniently as possible in our current time will help teach people to write or at least modify assembly code.

And you can still make a relatively wide range of games with NESmaker as-is, especially as the modules library grows. It's just that those games might not match your ambition exactly. But it's a start. And i think it is good practice in game design and who knows, you might catch a thing or two about programming without even noticing. Basically noones' first game was a masterpiece (actually, few games in general are, haha).

I don't have a computer science background and i'm pretty sure i'm under average in math skills, if that's any consolation. Everything i've learned is by reading scanned books, asking questions, and doing experiments in late hours the last couple of years whenever something has piqued my curiosity enough to step out of my usual artist role.

There's a lot of technical jargon surrounding programming, especially when you're this close to the hardware, and it kind of has to be that way in order to be able to communicate about it. So that may seem like steering an ocean liner into deep water to go fishing, but i think it's more like learning a foreign alphabet - you need a rosetta stone. Just take it slow, and it'll come more and more naturally. Meanwhile, ask many questions, use code snippets, dare modify them by what means you have and watch what happens.

If you want a fast express train to learning the building blocks of game development, i cannot recommend GameMaker enough. It has great entry-level tutorials built-in for learning basic building blocks like objects, timers, actions, conditions, events, and so on. You can have some basic games up an running and learned a lot from it in a couple of hours. Those experiences can be invaluable if you decide that *some* programming may be your cup of tea, after all.
 

SeaFoodAndButter

New member
I'm a bit more optimistic about this. NESmaker can and is already acting as a portal which as conveniently as possible in our current time will help teach people to write or at least modify assembly code.
I agree. Maybe I just had a bad day or something and was venting too much. I agree, i love NESMaker. I don't want to sound pessimistic, I just want to sound realistic. Plus, I already invested $100 so I'm not quiting! LOL.

I understand what you mean about codes taking time to write and figure out, and maybe people don't want to spend all their free time writing code for the things other people want. But, I'm just saying, there's a lot of people that need help. - me included.

Man, I cannot write code to save my life. The only coding I have really done are very basic things - mostly editing - that is it.
If I had people to help me, I could deff. make a great game.

Here's what I got so far, with some help from others on starts screens, paths, hud advice, a tiny bit of coding, and following the tutorials.

Lime Green is the layout for level 1 which is going to be a basic tutorial/learn the controls and fight easy enemies.

https://www.youtube.com/watch?v=lFY5lngCrJY&feature=youtu.be
 
Top Bottom