I understand. That method wouldn't require having more tiles either, since the top of the top of the character and the bottom of the wall would already be present. But can't colors only be distributed per 16x16 blocks? That'd mean either the character or the wall would have to change its palette to the other's, which would look bad. I wouldn't mind the sprites per line limit so much, since one can tell fceux to ignore that anyways. What's the limit on sprites per screen though?You mean how the wall overlaps the characters? The best way to do that on the NES would be to use mask sprites... sprites with the same shape as the wall, with higher priority (lower OAM index) than the character sprites and with the "behind background" bit set.
When your character sprites and the mask sprites overlap, the PPU will first check which sprite has higher priority, and since the mask sprites appear first in the OAM they will win. Then, the PPU will try to draw the mask, but since it's configured to be behind the background, the background is displayed instead.
The only problem with this technique is that the sprite count raises quite quickly. You obviously wouldn't keep the masks in place at all times, only when necessary, but even then the limit of 8 sprites is reached fairly easily, so there will be some flickering.
Hello World
Moderator: Moderators
There's no need for any extra sprites for the player, but the mask must have the same shape of the wall. If the wall tiles themselves can't be used as a mask (it will happen depending on your use of color 0), you will need extra graphics.FinalZero wrote:I understand. That method wouldn't require having more tiles either, since the top of the top of the character and the bottom of the wall would already be present.
This is irrelevant. The background will be drawn as normal. The player will use its normal palette(s) also, and it doesn't matter what palette is used for the mask, as it will be hidden behind the background and will not be visible at all.But can't colors only be distributed per 16x16 blocks? That'd mean either the character or the wall would have to change its palette to the other's, which would look bad.
Maybe you didn't understand how this works exactly, so I'll try to explain a little better. Here's the background and sprite in place:

The player is in front of the background, which you don't want. The easiest solution, if that grass is drawn exclusively with color 0, is to set the "behind the background" bit of the character's sprites, so he'll show up in front of the grass but behind the wall. That's hardly the case though, because grass often isn't flat, and has pixels of other colors on it. Also, you might want to apply the effect in some other areas where the floor is not green at all. The solution that works for all of these cases, is a mask:

The black sprite is a mask (I only used black for the example, the actual color doesn't matter, it will not be seen), with the exact shape of the wall (this is important!). It is successfully hiding the character, because it has higher priority, so it's drawn on top. The only thing left to do is set the "behind" bit of the mask's sprites, which will cause the PPU to bring the background pixels to the front, achieving the desired result:

I hope you can see that there's no issue with palettes whatsoever. The only thing that makes this technique complex is that you will probably need some logic to detect when the player is "touching" the wall in order to put the mask(s) in place only when necessary, to minimize sprite use.
But then you are not making NES programs anymore, but FCEUX programs, don't you agree? If you are going to deliberately ignore a system limitation because an inaccurate copy of it doesn't have the same limitation you could just as well throw all the limitations out the window and making a PC game instead. save yourself the trouble of learning how to code for an ancient machine.I wouldn't mind the sprites per line limit so much, since one can tell fceux to ignore that anyways.
64 sprites per screen, because that's how many entries fit in OAM. You can have more if you interrupt rendering mid-frame for 5 scanlines or so to perform more sprite DMAs. Few games ever did that, because unless you have a reason to split your screen (like, there are 2 gameplay windows) you wouldn't want blank scanlines in the middle of the screen.What's the limit on sprites per screen though?
Oh, you're describing the same thing that SMB3 does for pipes. I'm not sure why I wasn't able to realize that one could use that for walls too...[tokumaru's text]
I suppose. Thinking about it further, I realize it wouldn't actually add any more sprites per line though, because the PPU would never get to drawing the one's with the lower priority.But then you are not making NES programs anymore, but FCEUX programs, don't you agree? If you are going to deliberately ignore a system limitation because an inaccurate copy of it doesn't have the same limitation you could just as well throw all the limitations out the window and making a PC game instead. save yourself the trouble of learning how to code for an ancient machine.
I see.64 sprites per screen, because that's how many entries fit in OAM. You can have more if you interrupt rendering mid-frame for 5 scanlines or so to perform more sprite DMAs. Few games ever did that, because unless you have a reason to split your screen (like, there are 2 gameplay windows) you wouldn't want blank scanlines in the middle of the screen.
-----
Another question:
1) DW3 and DW4 had a day/night cycle, and the people available to talk/interact with, and sometimes even the town itself, changed according to the time. How is this done? I assume every time one enters a time, the time is checked, and then the appropriate people (and there sprites) are added? But what about the town itself? Must a whole different map be stored in rom?
The basics of day/night can be done by screwing with the palette and/or the tint bits. Look at the difference in SMB1 between 1-1 and 3-1 for a crude idea of how to do this.
Zelda: ALTTP had a light and dark world with mostly the same outdoor map, and there was some sort of differential coding: objects in both worlds, objects in light world only, and objects in dark world only.
Zelda: ALTTP had a light and dark world with mostly the same outdoor map, and there was some sort of differential coding: objects in both worlds, objects in light world only, and objects in dark world only.
Once the time is entered, you have the responsibility of updating it. If you have NMIs enabled, like you should, you can update the time 60 times per second (NTSC).FinalZero wrote:1) DW3 and DW4 had a day/night cycle, and the people available to talk/interact with, and sometimes even the town itself, changed according to the time. How is this done?
You should check the time every frame, to decide whether it's time to change to day or night. Usually, modifying just the palette is enough to switch between day and night, but if you really need more extensive changes, nothing prevents you from changing the pattern tables or even the map.I assume every time one enters a time, the time is checked, and then the appropriate people (and there sprites) are added? But what about the town itself? Must a whole different map be stored in rom?
The problem with basing a game around a day/night cycle is that no NES mapper has a real-time clock. So when you save the game, turn off the power, and turn the power back on, the program has no idea how much time elapsed while the power was off. It's one of the reasons why the Animal Crossing concept never occurred to Nintendo developers during the NES era. (Here are the others.)
I've already watched the PPU of DW3 when it changes time (I left the PPU window open while playing through most of the game, actually.), and have seen how palette changes do it.The basics of day/night can be done by screwing with the palette and/or the tint bits. Look at the difference in SMB1 between 1-1 and 3-1 for a crude idea of how to do this.
Zelda: ALTTP had a light and dark world with mostly the same outdoor map, and there was some sort of differential coding: objects in both worlds, objects in light world only, and objects in dark world only.
It's not a realtime clock though; Instead, taking a step advances the time (maybe; sometimes it doesn't). Standing in place doesn't. I think it works well enough for a game like DW3.The problem with basing a game around a day/night cycle is that no NES mapper has a real-time clock. So when you save the game, turn off the power, and turn the power back on, the program has no idea how much time elapsed while the power was off. It's one of the reasons why the Animal Crossing concept never occurred to Nintendo developers during the NES era. (Here are the others.)
But did they store 2 different versions of the map? Or just the original and where the second deviated from it?Zelda: ALTTP had a light and dark world with mostly the same outdoor map, and there was some sort of differential coding: objects in both worlds, objects in light world only, and objects in dark world only.
So, I've mustered the strength and moral courage to try and do this again. I have some free time before university begins again in the fall.
* * *
So, here's a new round of questions:
1) The registers are only a byte large, right? How does one do/simulate math with 2 or more bytes?
2) What happens if you use JSR when the stack's empty?
3) What happens if you use JSR when the stack's already full?
4) What's the point of SEI and CLI? Are they used when games are paused and unpaused? How does BRK fit into this?
* * *
I'll post the code I'm trying to get to work soon.
* * *
So, here's a new round of questions:
1) The registers are only a byte large, right? How does one do/simulate math with 2 or more bytes?
2) What happens if you use JSR when the stack's empty?
3) What happens if you use JSR when the stack's already full?
4) What's the point of SEI and CLI? Are they used when games are paused and unpaused? How does BRK fit into this?
* * *
I'll post the code I'm trying to get to work soon.
With the carry flag.FinalZero wrote:1) The registers are only a byte large, right? How does one do/simulate math with 2 or more bytes?
Code: Select all
clc
lda a_lo
adc b_lo
sta result_lo
lda a_hi
adc b_hi
sta result_hiThe return address (minus one) is pushed, and the new address is loaded into the program counter.2) What happens if you use JSR when the stack's empty?
The same, except that the stack pointer wraps around within the $0100-$01FF page.3) What happens if you use JSR when the stack's already full?
Pause is a game state controlled by one of the game's variables. Each frame, the game moves the game pieces only if the game is not paused. It isn't necessarily related to anything in the hardware. SEI and CLI are used to change the CPU's interrupt priority level (CLI: IRQ and NMI; SEI: NMI only). This sort of interrupt is more connected with mappers.4) What's the point of SEI and CLI? Are they used when games are paused and unpaused?
BRK always performs a syscall to the IRQ vector, regardless of the CPU's interrupt priority level.How does BRK fit into this?
RTS on an empty stack pulls 16 bits of undefined data from the stack pointer (which again wraps around), adds one, and jumps there. I guess they didn't have enough transistors back in the late 1970s when the 6502 was designed to raise an interrupt on an attempt to wrap the stack.FinalZero wrote:I meant RTS, not JSR...
A couple more questions, this time about cc65.
1) is illegal, so C doesn't barf. I suppose there's no way to tell C to terminate strings with something other than '\0' (0x00), is there? I realize that it isn't that big of an issue anyways; Just move your font around so 0x00 is null, instead of something else.
2) Why is illegal though? Why does it think '0' is 0x00? Isn't it 0x30?
3) Is there a way to include a ca65 file in cc65 code? How about a binary?
1)
Code: Select all
#pragma charmap('\0', 0xFF)2) Why is
Code: Select all
#pragma charmap('0', 0xF0)3) Is there a way to include a ca65 file in cc65 code? How about a binary?
I realized the problem with 2) in my previous post. My code actually had: It was complaining about the 0x00. Apparently, one can't map anything from NOR to 0.
Code: Select all
#pragma charmap('0', 0x00)But what if I have code that depends on the assembly file? I mean, I have an asm file that has ".include "something.s"", and it uses variables/locations declared/defined there.cc65 itself generates an assembly file, so there is no problem to add an assembly file. Just assemble it and then give the linker object file. You can include binary files into an assembly file as usual.