First post, just trying to clarify a few things as I've only been reading documentation for about a day.
First question is, how many name table entries can be reasonably updated in a vblank?
Second is, are name tables always internal to the PPU and accessed via auto incrementing regs or can they be mapped in from the cart? Is there any other way to access or swap out a name table via mappers, etc?
Third, can non active name tables be written while the current frame is being drawn, or does this still require PPU cycles to handling the I/O from the CPU to the name table via the $200x ports? eg: thinking along the lines of double buffering the name tables by writing to one, and swapping them on vblank, etc.
I love assembly and doing impossible things on primitive hardware, and my primary interest is some awesome parallax/layering effects I've seen in this video:
http://www.youtube.com/watch?v=ltuRuGM271QParticularly Bucky O'Hare and Mitsumi ga Tooru where there is the appearance of a genuine layering effect going on and not just hblank subdivision. Specifically, the effect where a simple tiled background is scrolled behind the foreground in a very convincing way that mimics layering. Obviously the NES doesn't have layers, and this is a bit more than just simply breaking and subdividing the screen on hblank.
What I began to think, is you have 2-4 very simple repeating background tiles, and then you have 8 versions of those tiles each scrolled a single column of pixels such that you can achieve the affect of scrolling with
tile animation for those tiles that are to appear in the background. Obviously you are limited to very simple repeating background mosaics as you need 8 tiles in the pattern table for each background tile.
At first I was thinking just update the background tiles in the name table once per frame based on the current scroll value, but then I'm under the impression you barely have enough time to update 1 row or column of name table values let alone upload an entirely new 960 byte name table once per frame. In the two examples I mentioned, it's a significant amount of tiles to update, nearly 50% of the entire name table. So this is probably not possible with a standard ROM using the PPU's internal name table RAM (#1 and #2?)
Then I began to imagine what could be done with mappers. Instead of CHR-ROM you have CHR-RAM, and actually update the 2-4 tiles themselves in pattern RAM (256-1024 bytes depending on if we mean 8x tiles or 16x metatiles). CHR-RAM can have enough room for two pattern banks, then you could have infinitely more time to work on a game frame during vdraw by double buffering. Majority of the tiles would be duplicated in both CHR-RAM banks except the ones being animated. Doubting this now as it's very inefficient to duplicate two tile sets just to double buffer the animation of a handful of BG tiles.
Am I on the right track here? Or is it simpler?
I know there can be up to 4 name tables (#1 #2 built into PPU ram, #3 and #4 mirrored unless provided by cart?), is it possible to update the others that aren't being used during vdraw and then switch?
I haven't attempted to peek inside with an emulator yet, was hoping to figure it out on my own.
I'm pretty dead set that it HAS to be tile animation to achieve the appearance of scrolling BG tiles since there is obviously no way to achieve layering on the NES. Question is, by upating pattern tables, name tables or both. Name tables seems to be the most logical due to the aforementioned inefficiency of having two copies of the same pattern table with just 4 tiles being animated. I imagine ultimately it can't be done without a mapper implementing muliple per frame switchable pattern and name tables in a CHR-RAM which is also accessible by the CPU.
If 2 or more independent name tables (#3 and #4?) can be mapped from a CHR-RAM which can also be mapped into CPU address space as well, and a cart bank switch and PPU name table pointer change can be achieved within a vblank, then this basically becomes trivial. I'm leaning on this as the solution employed by the mentioned games.
I just watched that video.
Almost all the games seen there used split screen horizontal scrolling, sometimes with the assistance of mapper IRQs. Mega Man 3 also added some star sprites to enhance the effect.
Among games in that video, Bucky O Hare, Battletoads (many stages, including the Ice Cavern level), Sword Master, Mitsume ga Tooru achieved Parallax scrolling by changing the graphics of tiles. Of those games, only Battletoads used CHR-RAM. The rest used CHR-ROM bankswitching, and a lot of copies of similar tiles drawn at a different horizontal position.
Bee 52 also performs some parallax effects by updating both the tile graphics and nametables.
Now to answer questions...
Quote:
First question is, how many name table entries can be reasonably updated in a vblank?
I was updating as many as 224 tiles per frame when I did Chu Chu Rocket, and that involved going 4 scanlines into the frame. 192 tiles is more sane.
Quote:
Second is, are name tables always internal to the PPU and accessed via auto incrementing regs or can they be mapped in from the cart? Is there any other way to access or swap out a name table via mappers, etc?
Name tables are normally in the PPU's RAM (not strictly inside the PPU itself, it's a different chip), but the cartridge can select them (mirroring selection), or even bypass the PPU's RAM (four screen mirroring, MMC5).
Quote:
Third, can non active name tables be written while the current frame is being drawn, or does this still require PPU cycles to handling the I/O from the CPU to the name table via the $200x ports? eg: thinking along the lines of double buffering the name tables by writing to one, and swapping them on vblank, etc.
Non-active nametables can't be written to if the PPU is rendering something else. If you try writing the the PPU while it's drawing something, you get crap all over the screen (see
"Mind Control Trilogy" demo *shudders*). But you can update a non-active nametable over the course of several frames (during vblank time), and not see the stuff getting drawn in.
Oh forgot about CHR-ROM bank switching. Whats the smallest amount of CHR-ROM that can be switched?
So split CHR-ROM into bank frames and then use one of those frames to switch in the animated tile set for the appropriate amount of BG pixel scroll while the rest remains static.
exdeath wrote:
Second is, are name tables always internal to the PPU and accessed via auto incrementing regs or can they be mapped in from the cart? Is there any other way to access or swap out a name table via mappers, etc?
They can be mapped in from the cartridge. The CIRAM /CE signal is used to select the internal PPU memory or the cartridge memory.
Quote:
Third, can non active name tables be written while the current frame is being drawn, or does this still require PPU cycles to handling the I/O from the CPU to the name table via the $200x ports? eg: thinking along the lines of double buffering the name tables by writing to one, and swapping them on vblank, etc.
No; the PPU address and data ports cannot be used while rendering. However, if you are double buffering it could work if you have two CHR RAM chips on the cartridge for name tables (or even pattern tables too), and have one of them connected to the PPU and the other connected to the CPU, and have a register to swap them.
Quote:
What I began to think, is you have 2-4 very simple repeating background tiles, and then you have 8 versions of those tiles each scrolled a single column of pixels such that you can achieve the affect of scrolling with tile animation for those tiles that are to appear in the background. Obviously you are limited to very simple repeating background mosaics as you need 8 tiles in the pattern table for each background tile.
Another possibility is to use sprites.
Quote:
Then I began to imagine what could be done with mappers. Instead of CHR-ROM you have CHR-RAM, and actually update the 2-4 tiles themselves in pattern RAM (256-1024 bytes depending on if we mean 8x tiles or 16x metatiles). CHR-RAM can have enough room for two pattern banks, then you could have infinitely more time to work on a game frame during vdraw by double buffering. Majority of the tiles would be duplicated in both CHR-RAM banks except the ones being animated. Doubting this now as it's very inefficient to duplicate two tile sets just to double buffer the animation of a handful of BG tiles.
Yes, this could be one way, although bankswitched CHR ROM is another possibility.
Quote:
I know there can be up to 4 name tables (#1 #2 built into PPU ram, #3 and #4 mirrored unless provided by cart?), is it possible to update the others that aren't being used during vdraw and then switch?
No, I told you that already. You could do what is suggested above.
Quote:
I'm pretty dead set that it HAS to be tile animation to achieve the appearance of scrolling BG tiles since there is obviously no way to achieve layering on the NES. Question is, by upating pattern tables, name tables or both. Name tables seems to be the most logical due to the aforementioned inefficiency of having two copies of the same pattern table with just 4 tiles being animated. I imagine ultimately it can't be done without a mapper implementing muliple per frame switchable pattern and name tables in a CHR-RAM which is also accessible by the CPU.
If 2 or more independent name tables (#3 and #4?) can be mapped from a CHR-RAM which can also be mapped into CPU address space as well, and a cart bank switch and PPU name table pointer change can be achieved within a vblank, then this basically becomes trivial. I'm leaning on this as the solution employed by the mentioned games.
You would need dual-ported RAM (unless you use the switching I mentioned above), but it could work.
The MMC5 mapper has some RAM mapped to CPU address space, which can be used as name tables, but if it is set to use as name tables then it is write-only and can only be written during rendering (you can write $00 there outside of rendering, but not anything else).
Quote:
Oh forgot about CHR-ROM bank switching. Whats the smallest amount of CHR-ROM that can be switched?
It depends on the mapper.
exdeath wrote:
Oh forgot about CHR-ROM bank switching. Whats the smallest amount of CHR-ROM that can be switched?
Of all the mappers that I've looked through when paging through the
wiki, the finest granularity I've seen has been
eight 1KiB sections independently banked.
Thanks for the replies.
CHR-ROM bank switching in one of several pre-animated BG tile sets as a subset of the active pattern table appears to be the simplest and most efficient method so it's probably what I was looking for. Once per frame: calculate scroll offset for the BG layer, calculate the appropriate tile set modulo, wait on vblank, bank switch it into the active pattern ROM region, done.
I completely forgot about the possibility of bank switching CHR-ROM rather than just PRG-ROM
This also solves the problem of being limited in BG layer varieties where you are now limited to the 512KB or so in the cart (or rather what the mapper supports).
lidnariq wrote:
exdeath wrote:
Oh forgot about CHR-ROM bank switching. Whats the smallest amount of CHR-ROM that can be switched?
Of all the mappers that I've looked through when paging through the
wiki, the finest granularity I've seen has been
eight 1KiB sections independently banked.
That would be perfect.
1K = 64 tiles in the fake BG layer at a time.
8k CHR-ROM in the cart for 64 tiles x 8 versions (each scrolled by 1 pixel)
That's quite more variety than I anticipated even.
And that's if you literally had 8 versions of each tile and didn't use clever mosaic patterns to allow layering and reuse.
Could still employ CHR-RAM in order to take advantage of compression though. 8 x 1k of duplicate column rotated tile sets is begging for compression.
So looks like TLROM/Mapper 4/MMC3 is what is required at minimum.
Without downloading and trying them all out, which NES emulator has the best dev support?
Something like Visual Boy Advance for GBA would be awesome. VBA can show all memory locations, trace, and OAM/tile/map/palette memory real time.
FCEUX has alot of debugging features. You can view the NameTables, PPU Pattern Tables, all memory, etc. It is fairly accurate but not the most accurate emulator.
exdeath wrote:
8k CHR-ROM in the cart for 64 tiles x 8 versions (each scrolled by 1 pixel)
Most of these games have actually 16 versions, some even have 32 (Metal Storm being one of them, I don't think it's shown in the video you posted). The number of rotations depends on the width of the pattern being rotated, not on the width of a single tile. If you had only 8 rotations, you'd need to modify the name tables in order to perform this trick with patterns wider than 8 pixels.
Quote:
Could still employ CHR-RAM in order to take advantage of compression though. 8 x 1k of duplicate column rotating tile sets is begging for compression.
If you had some RAM to spare, you could even just store the original version of the pattern, and rotate it in RAM as necessary. Traditional compression wouldn't be of much use, because it would make the process of copying tiles from ROM to VRAM much slower, severely reducing the number of tiles you can update each frame. Unless you have some RAM available, so you can pre-decompress the graphics there (but then I'd rather just rotate them in RAM like I said before.).
Quote:
So looks like TLROM/Mapper 4/MMC3 is what is required at minimum.
You could use simpler mappers if you used CHR-RAM, but if you're going for CHR-ROM, then yeah, the MMC3 is about the minimum required for this kind of effect (and it's the mapper used in most of the games in the video you posted).
Quote:
Without downloading and trying them all out, which NES emulator has the best dev support?
FCEUX has a lot of debugging features, but it's not particularly accurate (it seems to emulate some things at a higher level instead of performing each minuscule task that the original hardware does). Nintendulator (which also has some debugging features) and Nestopia (no debugging tools at all) are much more accurate in this aspect. As a general rule, when developing for the NES, don't ever trust a single emulator. Also, unless you are doing something really tricky that relies on very well timed tasks and/or accesses to PPU registers at unconventional times, your program
should work well on most common emulators (if it doesn't, you are probably messing something up).
tokumaru wrote:
exdeath wrote:
8k CHR-ROM in the cart for 64 tiles x 8 versions (each scrolled by 1 pixel)
Most of these games have actually 16 versions, some even have 32 (Metal Storm being one of them, I don't think it's shown in the video you posted). The number of rotations depends on the width of the pattern being rotated, not on the width of a single tile. If you had only 8 rotations, you'd need to modify the name tables in order to perform this trick with patterns wider than 8 pixels.
Right... need to be able to display any 8 pixel wide portion of the entire pattern within a tile without changing the name table.
Holy crap I just watched Metal Storm Level 3-1 where they have THREE layers going. No surprise that the rest of the tile set is relatively simple; most of the CHR-ROM is probably eaten up by all the various BG tiles in all their scrolling and overlapping permutations.
I see... It's a 4 x 4 tile repeating pattern, so 32 copies of those, and the vertical scrolling later is just an additional sequential animation baked into each of the 32 scroll sets giving the illusion of 2 scrolling layers in one.... clever.
The attribute table restrictions are glaringly obvious in the scrolling backgrounds... the entire contiguous background "layer" is stuck at 4 colors. Though there is palette manipulation (Battle Toads).
It's actually bank switching the 2k region at $0800-$0FFF (bottom half of pattern table 0) with up to 32 copies of the animated sequences. Though only 1k is used for the animated tiles, the second 1k is just other random tiles packed with that frame. Simplifies the mapper by going with 2k granularity, but wastes 1K of pattern memory since the animated tile frames aren't packed with anything else relevant (looks like cinematic and title screen graphics). This limits the foreground to 128 tiles.
Additionally that 1k region contains ALL of the animated tiles used for all BGs packed together that are animated together all the time. The entirety of all the parallax layer tiles for the entire game occupies 32k of the 256k CHR-ROM. Some are 32 x 32 pixel regions animated in one direction, other parts are smaller sections like 8 x 16 rotated up 8 frames, then rotated right 16 frames, then replaced with another pattern for the remaining 8 frames, etc. So some levels must only bank switch 8 times for the simple 1 tile wide patterns.
Very cool. Learned a lot tonight, thanks.
zzo38 wrote:
exdeath wrote:
Second is, are name tables always internal to the PPU and accessed via auto incrementing regs or can they be mapped in from the cart? Is there any other way to access or swap out a name table via mappers, etc?
They can be mapped in from the cartridge. The CIRAM /CE signal is used to select the internal PPU memory or the cartridge memory.
Does this apply with the entire 16k address space, including the palette? Or just the name tables.
eg: how does the PPU respond to CIRAM /CE = A12 AND A13 (held inactive at $3xxx), would it attempt to fetch palette reads from the cart?
Or is CIRAM /CE only valid for $2000-2FFF and ignored otherwise?
I read "This signal is used as an input to enable the internal 2k of VRAM" meaning it's only for the 2k internal name table RAM and if you set CIRAM /CE high at all then you have to bring all or nothing 2k minimum 4k max external name table RAM and it's ignored for all other addresses outside of $2000-2FFF.
The palette is stored in separate memory inside the PPU. It cannot be bankswitched. /WR appears not to be asserted externally for this space. /RD is still asserted for $3F00-$3FFF if you try to read back, but the behavior for that is sort of complicated and hard to describe unless you fully understand the normal video memory read back delay.
PPU bus access: (slightly generalized from hardware, but should be accurate.)
You have A0-A13, /A13, D0-D7, /WR and /RD. /A13 is usually connected to /CE of the CIRAM to enable it for addresses 2000-3FFF (3F00 and higher is palette).
Likewise, A13 is usually used to enable the C-ROM or C-RAM (/CE) on the cart (which is then mapped into 0000-1FFF).
Palette and Sprites (OAM) are internal to the PPU chip. OAM is not mapped to a VRAM address.
Woot!
My first NES program!
Code is a little messy, took some trial an error to figure out MMC3 / mapper 4.
Code:
lda #%00000001
sta $8000
In this mode, 2k pages are swapped at pattern memory $0800-FFF. What I learned via trial and error:
1) The value written to $8001 to select the CHR-ROM page is the number of a page, not an address. So 0 = the 1k page at PPU $0000, 1 = 1k page at $0400, 2 = 1k page at $0800 and so on.
2) The page must be 2k aligned in the mode I'm using. Selecting page 0 and 1 select the same 2k page from $0000-$07FF, page 2 and 3 = the same 2k page from $0800-$0FFF, etc.
So using nesasm, showing the bank layout:
Code:
.ineschr 3
.inesmap 4
.bank 2
.org $0000
.incbin "bg4k.chr" ;initial background
.incbin "spr4k.chr" ; initial sprite
.bank 3
.org $2000
.incbin "anim2k_1.chr"
.incbin "anim2k_2.chr"
.incbin "anim2k_3.chr"
.incbin "anim2k_4.chr"
.bank 4
.org $4000
.incbin "anim2k_5.chr"
.incbin "anim2k_6.chr"
.incbin "anim2k_7.chr"
.incbin "anim2k_8.chr"
nesasm semantics = 3 x 8k banks of CHR-ROM
But my code for the purposes of MMC3 /mapper 4 views it as 24 x 1k pages or 12 x 2k pages. Page numbers written to $8001 are in the form of 1024k x page_no and must be aligned to the size of the page frame (2k in my case).
Is this correct?
exdeath wrote:
Woot!
My first NES program!
Code is a little messy, took some trial an error to figure out MMC3 / mapper 4.
Code:
lda #%00000001
sta $8000
In this mode, 2k pages are swapped at pattern memory $0800-FFF. What I learned via trial and error:
1) The value written to $8001 to select the CHR-ROM page is the number of a page, not an address. So 0 = the 1k page at PPU $0000, 1 = 1k page at $0400, 2 = 1k page at $0800 and so on.
2) The page must be 2k aligned in the mode I'm using. Selecting page 0 and 1 select the same 2k page from $0000-$07FF, page 2 and 3 = the same 2k page from $0800-$0FFF, etc.
AttachmentLooking good! Maybe try some dark tiles too, put them to the right of the walls.
You should look in to doing those simpler backgrounds with CHR-RAM on UNROM or something, you can probably get a better effect and more backround varieties since it's only one tile.
Dwedit wrote:
exdeath wrote:
Woot!
My first NES program!
Code is a little messy, took some trial an error to figure out MMC3 / mapper 4.
Code:
lda #%00000001
sta $8000
In this mode, 2k pages are swapped at pattern memory $0800-FFF. What I learned via trial and error:
1) The value written to $8001 to select the CHR-ROM page is the number of a page, not an address. So 0 = the 1k page at PPU $0000, 1 = 1k page at $0400, 2 = 1k page at $0800 and so on.
2) The page must be 2k aligned in the mode I'm using. Selecting page 0 and 1 select the same 2k page from $0000-$07FF, page 2 and 3 = the same 2k page from $0800-$0FFF, etc.
AttachmentLooking good! Maybe try some dark tiles too, put them to the right of the walls.
Like shadows/translucency like Mitsumi ga Tooru? Only have to modify the attribute table and have a light and dark version of two palettes.
Changed the colors so the darker palette showed better. Not much room with grey/black/white when you end up with 2 blacks trying to make it darker.
3gengames wrote:
You should look in to doing those simpler backgrounds with CHR-RAM on UNROM or something, you can probably get a better effect and more backround varieties since it's only one tile.
I can make the effect much better using CHR-ROM bank switching like I'm doing now.
I have an entire 2k page of CHR-ROM being bank switch. There is only 1 tile in the BG layer because this was a programming exercise and not a pixel art and art program exercise
Took me long enough to create 8 versions of 1 stupid simple tile by hand in NESST.
You should use powers-of-2 for sizes of your PRG and CHR chips. Some emulators will have trouble interpreting how to map 24KB into a 32KB space, since a 24KB ROM chip doesn't exist (I seem to remember the PowerPak having some trouble with this). I know it may seem like a waste of space, but you have to keep in mind that a ROM file is essentially a copy of what an actual cart would contain, and the ROMs in actual carts always come in powers-of-2 sizes.
EDIT: Oh, and a small artistic advice - I know this is just a tech demo, but once you put actual graphics in you should consider making the background slightly misaligned from the foreground (vertically), otherwise it might just look like small blocks sliding over big ones, as opposed to 2 interdependently scrolling layers. Reducing the contrast of the background blocks might help too (the back outline sometimes appears to "snap" to the foreground when the layers are horizontally aligned).
You know what would look cool? An "underwater effect" where you combine half speed parallax scrolling with "wavy background" like effects, except done to the tile graphics itself. I haven't seen this done anywhere before.
But then you'd need an insane amount of tiles... With an 8-pixel wide pattern you need 8 versions of the pattern. If you're gonna make that pattern wavy, with say, 4 frames of animation, you'd need to apply the 4 frames to each of the 8 copies, for a total of 32 versions of the pattern (which doesn't sound so bad for such a small pattern, but just think about 16 and 32-pixel wide patterns). That way you could calculate what bank to switch in based on the current animation frame (which changes at a constant rate) and the position of the camera.
There's a level in Metal Storm that has some vertical animation on the background patterns, but this animation is tied to the horizontal movement of the camera. When the camera moves right, the bars go up, when the camera moves left, the bars go down, if the camera doesn't move, the bars don't either. This makes no sense, and just looks silly. If the wavy effect worked like that (i.e. the water would only wave when the camera was moving) it would look just as silly.
Dwedit wrote:
I meant with CHR RAM.
Oh, that would make more sense, storage-wise. On the other hand, to keep things consistent you'd have to apply the wavy animation to the foreground tiles as well, and since the amount of patterns you can update each frame with CHR-RAM is fairly limited, you'd have to keep the variety of underwater blocks fairly low. Another option would be to use the "pool" approach to representing water, where the foreground tiles are not considered to be submerged.
I smell 32KB to 64KB of CHR-RAM with MMC3 and just have loading screens to load and modify each tile set to be able to be used. I mean, it'd work. One design problem is you'd probably need to either have the full background use the same tile, or a background colored one, and use the left and right 1 pixel of the metatiles empty, so a 16x16 area would be 14x16, but it'd work.
I was thinking a waterfall with palette animation running top to bottom which is running all the time, then parallax left to right.
HDMA would be cool for wavy effects, but it would affect the whole screen.
Speaking of palettes whats the deal with being gypped out of 1 color per 4 color palette? Color 0 is tied together in all 4 attribute palettes resulting in only 3 unique colors each. 12 colors + black for the entire BG without resorting to palette swaps mid frame.
I suppose with a more varied background with say clouds on the top and grass on the bottom, you could swap the 4 colors used by the BG "layer".
Oh now here is an interesting question.
How to .bank more than 64k CHR ROM banks in NESASM?
8th bank orgs at $E000 and $10000 is invalid for bank 9 even though mapper 4 supports 256kb of CHR ROM.
exdeath wrote:
Speaking of palettes whats the deal with being gypped out of 1 color per 4 color palette? Color 0 is tied together in all 4 attribute palettes resulting in only 3 unique colors each. 12 colors + black for the entire BG without resorting to palette swaps mid frame.
Yup, that's how it works. Color 0 is shared among all palettes. If it helps, you can think of color 0 as the background color, and each palette has 3 colors + transparency (transparent areas will show the background color). It doesn't have to be black though, the actual color can be anything.
BTW, swapping palettes mid frame on the NES is pretty tricky... first because using $2006 and $2007 will screw up the scroll, which you'll have to reset when you're finished, second because a single HBlank is too little time to change even one color and fix the scroll, and third because when rendering is disabled and $2006 is pointing to the palette, the color it's pointing to
gets rendered to the screen, causing "rainbow" effects. Because of these issues, not many games changed the palette mid screen, unless it was for a clearly separated area, like an status bar.
exdeath wrote:
How to .bank more than 64k CHR ROM banks in NESASM?
Can't help you with NESASM, I hate it to death. =)
New BG tiles courtesy Mitsumi ga Tooru.
32 x 32 x 64, but I realized 3/4 of the way through that I should have done 32 x 32 x 32 and shift back and forth 16 pixels every 4 rows in the name table.
Either way it's the same amount of CHR-ROM, it would just free up space for another 32 x 32 x 32 pattern for another level.
Anybody know a good editor? Editing name tiles with NESST one tile at a time for the whole screen is getting old.
As for NESASM I just stopped giving .orgs.
.org $0000 for first 8k CHR-ROM, after that just specify banks and tack on as many .incbins as you want.
16 byte NES header
16k PRG-ROM mirrored at $8000-$BFFF and $C000-$FFFF
128k CHR-ROM 72k + 56k dummy space to pad to 128k; 4k initial BG, 4k initial sprite, and 32 frames of 2k pages with animation
There is ALOT of wasted empty space and duplicate data in my 72k. I'm going to work on cleaning that up next and come up with a more pleasant tile set as soon as I find a convenient editor. Then it's time to start playing with sprite 0 and hblank scrolls.
Hmm why did I get into this.... hopefully to learn how the PPU works intimately and write my own in VHDL with user programmable palettes and RGB output; direct drop in replacement RGB PPU via FPGA? Why hasn't this been done yet? Plenty of people have implemented the entire NES in a FPGA already, but people are still robbing PC10 chips and getting screwy palettes for RGB.
exdeath wrote:
I'm going to work on cleaning that up next and come up with a more pleasant tile set as soon as I find a convenient editor.
I remember people saying good things about YY-CHR. IMO, tile editors will never be as good as actual drawing programs, so I'd much rather draw my tiles in MSPaint/Photoshop/GIMP and just convert them to CHR. Apparently you can copy from these programs and paste into YY-CHR.
Quote:
Then it's time to start playing with sprite 0 and hblank scrolls.
Sprite 0 hits are kinda lame when compared to MMC3 IRQs... =)
You might want to look into asm6. It has less bugs than NESASM I think.
Yea, I and from my exprience- it's easy to convert the code from NESASM to ASM6.
Nice effect, BTW.(test.zip).
Also, Tokumaru is right
OK wow... just thought of some other possibilities. With 32 frames of 2k of tiles being swapped, you can add many more tile animations, and they don't all have to be rotated by only 1 pixel per frame. Some can be faster, some can be slower, and not every row or column has to be updated at the same rate.
Additionally you can have animated single metatiles like candles, etc, though they would best be mixed up in the foreground due to attribute limits.
I imagine all sorts of effects even before throwing in hblank screen splits on top of it.
But the active 2KB frame IS dictated by the scroll position. In order to have other animations independent from the scroll you'd need to use another CHR slot. You could have the background use the pattern table that's divided into 1KB chunks instead, use 1 slot for parallax patterns (you could mix 32x32-pixel patterns with 16x16-pixel ones) and another slot for constant animations such as waterfalls, candles flickering, and so on. The disadvantage is that the sprite side side would be divided into 2KB chunks, which may or may not be a problem depending on how you are animating the main character.
Yeah it would be hilarious to see candles stop flickering when the player stops moving.
I happen to use NESASM (actually, Unofficial MagicKit, which corrects some bugs and adds some new features), so I can help with that. Bank address $10000 is invalid because it is not in the 6502 CPU address space; you can use the same .ORG for multiple banks; the .ORG specifies address used at runtime, not the address in the file, except 13 low bits are used to determine the offset within the bank, too. (If you require something more complicated than this, notice that Unofficial MagicKit allows you to place code in a .EMU section which will run at compile time, if you need it.)
zzo38 wrote:
I happen to use NESASM (actually, Unofficial MagicKit, which corrects some bugs and adds some new features), so I can help with that. Bank address $10000 is invalid because it is not in the 6502 CPU address space; you can use the same .ORG for multiple banks; the .ORG specifies address used at runtime, not the address in the file, except 13 low bits are used to determine the offset within the bank, too. (If you require something more complicated than this, notice that Unofficial MagicKit allows you to place code in a .EMU section which will run at compile time, if you need it.)
Right, I just did
.org $0000
.incbin
...
...
...
...
.incbin
Hi, I'd just like to say the demo looks good !
However it would look even better if, instead of using a darker palette on the same background tile for shadows, it would use a hand made darker version of the tile (using the same palette). Since you're using an entiere 2kb of tiles for the rotation, you'd want to put all this space to good use.
It could make the shadows less blocky and more progressive. Here it's very obvious the shadows are 16x16 blocks which looks a bit corny.
Damn it NESASM!
Just spent a good 30 minutes trying to upgrade from 16k to 32k program ROM.
.inesprg 2
Change interrupt vector bank to .org $FFFA
No go...
Then I realized from when I only specified .inesprg 1 that I had a .bank 0 and .bank 1 which I simply followed along some tutorials from day one... 2 banks when I have .inesprg 1... so 4 banks for inesprg 2? And it worked >.>
So .bank is always 8k segments... and inesprg is 16k segments... wtfbbqchkn?!
So .inesprg measures "banks" in 16k, .bank statement measures in 8k.. at least the mapper works in 8k prog banks so something matches.
Think I'm understanding the purpose of "banks" in NESASM... really just so the assembler lays out PRG-ROM and CHR-ROM appropriately, the only purpose.
Went ahead and added a 8k SRAM too, for future use of course.
exdeath wrote:
Think I'm understanding the purpose of "banks" in NESASM... really just so the assembler lays out PRG-ROM and CHR-ROM appropriately, the only purpose.
The only reason for the .bank stuff in NESASM is that it was originally a PC-Engine assembler, and PCE uses 8 KB banks. That's a lot of so called newbie friendliness down the drain when it introduces arbitrary requirements like this. (I, too, used NESASM when I first started and was baffled by ".bank", especially because the tutorial I used didn't explain why it was like that, just said "you have to do it like this".)
exdeath wrote:
Damn it NESASM!
Then I realized from when I only specified .inesprg 1 that I had a .bank 0 and .bank 1 which I simply followed along some tutorials from day one... 2 banks when I have .inesprg 1... so 4 banks for inesprg 2? And it worked >.>
So .bank is always 8k segments... and inesprg is 16k segments... wtfbbqchkn?!
Yes. This is because of the way the iNES header works; read the documentation. It does make sense to me, at least.
Quote:
Think I'm understanding the purpose of "banks" in NESASM... really just so the assembler lays out PRG-ROM and CHR-ROM appropriately, the only purpose.
Well, yes; the purpose of banks in NESASM (always 8K, no exceptions) is to write the output. After the header, all 8K banks (with bank 0 first) is send to output.
Remember: .ORG uses only the low 13 bits for the address within the bank; the rest of the address specified with .ORG is used only for computing the addresses of labels.
Just saw some of the things MMC5 does... total hard on. How is it able to take over so much of the PPU hardware like removing the attribute table limit and increasing the PPU addressable tile count from 256 to 16,384?
Brings its own VRAM so I guess it can swap attribute bits on a per tile fetch basis watching the CHR ROM A/D lines and can swap tile banks mid frame.
Nvm I get it. You see the A/D lines for both the chr rom and nametable fetches you can do whatever you want within the granularity of one clock and one 8 bit data bus read.
There's a sequence of reads that the PPU does when it renders:
Read nametable byte
Read attribute byte
Read tile byte 1
Read tile byte 2
If you have a mapper in there that watches for the first read, then you can force the attribute read to do something else.
Dwedit wrote:
There's a sequence of reads that the PPU does when it renders:
Read nametable byte
Read attribute byte
Read tile byte 1
Read tile byte 2
If you have a mapper in there that watches for the first read, then you can force the attribute read to do something else.
Yeah I wasn't thinking. You have complete address and data bus going to cart, you can do whatever you want down to every single byte fetch.
What a shame the palettes can't be brought outside.
So just started messing with MMC3 IRQs. Just experimenting with split screen for all of 5 minutes.
Got it working but the line seems indefinite. +/- 1 which I've read about.
And the scroll is messed up on the line separating the two screens.
So it looks like 119 lines 0 scroll, 1 line like 10-50 scroll then remaining 120 lines 20 scroll. Just ordered a PowerPak so haven't tried on real hardware yet.
IRQ handler is simply
Code:
Pha
Lda #$01
Sta $E000
Lda #$20
Sta $2005
Pla
Rti
Which is under 12 cycles.
Wondering if I need to turn off drawing first or if a black border region is required to simply deal with it.
Honestly haven't tried very hard, but at work right now and just looking for things to think about before I get back at it.
I don't remember the exact timing, but IIRC the IRQ fires kinda late in the scanline, so there might not be enough time to update the scroll before the PPU does its internal scrolling maintenance. If this is the case, the fine X scroll (pixel 0-7) would update (it's updated immediately), but the coarse scroll (tile 0-31) wouldn't be updated until the next scanline, resulting in a glitchy scanline. You could try delaying your scroll change until the end of the next scanline, with some timed code before the write to $2005.
EDIT: There's no need to turn off rendering. You just have to be sure that the $2005 write finishes before the X scroll is reset internally. I searched and it seems that the
X scroll is reset on cycle/pixel 257, and the
MMC3 IRQ fires at cycle 260, so you really have to wait until the next scanline.
IRQ fires at dot 260, and the fetches to load the first tiles of the next scanline begin at 320.
Here is your current IRQ handler, with execution times in dots (assuming NTSC or RGB system). Internally, an IRQ or NMI is performed by
replacing the input to the instruction decoder with $00 (which is the opcode for BRK), so I'll show the IRQ's entry as "Brk" in the following.
Code:
xxx xxxxx ; 0-18: wait for current instruction to finish
Brk $00 ; 21: enter IRQ
Pha ; 9
Lda #$01 ; 6
Sta $E000 ; 12
Lda #$20 ; 6
Sta $2005 ; 12
Pla
Rti
So it takes 66 to 82 dots before the write completes.
Technically you don't need to store any particular value into $E000 for MMC3, and you might as well make the $2005 write happen as early as possible. This one completes the write in 48-66 dots:
Code:
xxx xxxxx ; 0-18: wait for current instruction to finish
Brk $00 ; 21: enter IRQ
Pha ; 9
Lda #$20 ; 6
Sta $2005 ; 12
Sta $E000
Pla
Rti
So trigger the IRQ handler a scanline early, write only the coarse scroll value, and then write the new fine scroll value during the
next horizontal blank.
Good stuff. Currently reading the loopy doc on scrolling.
3 dots per CPU clock?
exdeath wrote:
Currently reading the loopy doc on scrolling.
It has some good info for when you need to change the vertical scroll mid frame, which is significantly more complex than changing just the horizontal scroll.
Quote:
3 dots per CPU clock?
On NTSC, yes. On PAL it's 3.2 dots.
exdeath wrote:
So just started messing with MMC3 IRQs. Just experimenting with split screen for all of 5 minutes.
Got it working but the line seems indefinite. +/- 1 which I've read about.
And the scroll is messed up on the line separating the two screens.
So it looks like 119 lines 0 scroll, 1 line like 10-50 scroll then remaining 120 lines 20 scroll. Just ordered a PowerPak so haven't tried on real hardware yet.
The accuracy is good with the actual mmc3. But from what I'm told the power pak's isn't so great. It tends to jump back and forth a few scan lines on some games... So keep that in mind, it's not necessarily the mmc3 as much as it's the power pak.
infiniteneslives wrote:
The accuracy is good with the actual mmc3. But from what I'm told the power pak's isn't so great. It tends to jump back and forth a few scan lines on some games... So keep that in mind, it's not necessarily the mmc3 as much as it's the power pak.
This might have been true back when PowerPak was released, but I haven't had any problems like that with the loopy's latest mappers (or my own save state mappers). Still good to keep that what you said in mind of course.
Also the MMC5 mapper file for the PowerPAK may not be complete, I don't think it is. So don't assume the PowerPAK running a game with complex operation to mean it will work on the original mapper exactly the same. Simple mappers you can likely count on to operate just about identically, like MMC1.
Yeah, well see what happens once I properly implement mid frame scrolling first.
Just writing xpos trivially to $2005 on IRQ doesn't cut it apparently.
Trying to get more clarification on the course vs fine scroll and when and where to write them.
Ill have to play with nops to experiment with the timing.
So the value written to $2005 has a diff meaning during rendering than a simple scroll integer?
Oh I get it now.
Earlier it was said modifying the palette mid frame was tricky if not impossible due to screwing up the scroll.... Now I know... because its using the same address registers internally while rendering and screwing up the PPUs current location.
exdeath wrote:
because its using the same address registers internally while rendering and screwing up the PPUs current location.
Exactly. When you set the scroll during VBlank you are actually setting the initial value of the VRAM address register, which is used during rendering to fetch tiles and such. The only part of the scroll that's not related to the VRAM address register is the fine X scroll, and that's the reason it takes effect immediately on writes to $2005.
During rendering, these register have to be manipulated according certain rules:
You can write to $2005 freely, but it affects the temporary address register. Since the screen is drawn from top to bottom, every scanline the X part of the VRAM register is reloaded with the temporary register, but the Y part is never reloaded, and this is the reason you can't change the vertical scroll mid frame through $2005 - the value you write is never copied from the temporary register to the address register.
In order to modify the Y scroll you have to use $2006, which forces the contents of the temporary register to be copied over to the address register. However, since $2006 was meant for writing/reading data to/from VRAM (pattern tables, name/attribute tables and palettes), it masks off the top 2 bits of the written address (not necessary for accessing $0000-$3FFF), one of which is necessary to control the scroll, meaning you can't fully set the scroll with $2006 alone (that and the fact that the fine X scroll is a separate thing). Hence the need for mixed $2005/$2006 writes.
All that complexity is because of the vertical scroll. For the horizontal scroll you should be OK doing what tepples said: set the coarse scroll during HBlank (after cycle 257, which is when the value from the temporary register is copied, meaning the value you wrote will not be used just yet), and then during the next HBlank you set the fine scroll. You will obviously be wasting some time this way, since you can't change the scroll right as the IRQ fires and you have to wait yet another scanline to set the fine scroll, but that's what's require for a clean, unnoticeable split. If you pay attention, you'll see that most commercial games don't have such a clean split (even high profile games like SMB3), and you can easily see glitches because of badly timed scroll changes.
IMO, the most notorious case of glitchy scroll changes in a commercial game is Mega Man 3. The stage select screen has very noticeable glitches right above Shadow Man, and so does the top of the weapon selection menu, and at various times when the background is used for special effects the ground is severely affected.
It's definitely a fine scroll issue, as the messed up line is never +/- 8 pixels from the line above it.
So I guess that's where I'm missing:
1) when, how, and where to write "fine" scroll vs "coarse" scroll. Do these HAVE to be written separately? It does not appear that simply writing once to $2005 with appropriate delay is enough; I just go from overshooting the end of the current line to messing up the next line with a single extra NOP.
2) how to determine next hblank knowing that the IRQ is called at dot 260 of the current line.
Top part of screen scrolls, and I'm trying to fix the bottom part at scroll $20 on MMC3 IRQ at line 120. IRQ just acks the mmc3 int, then tries to nop until next hblank before writing $20 to $2005. As I keep adding nops, I see the line stabilized from left to right with the glitches shrinking to the right, but just when Im down to the last couple pixels, one more NOP and bam the entire next line glitches.
To do mid-screen scrolling for horizontal and vertical scrolling, it's 4 writes:
2006/1 ---- NN-- (nametable select)
2005/2 VV-- -vvv (upper two bits of coarse V scroll, all bits of fine V scroll)
2005/1 ---- -hhh (fine horizontal scrolling) (takes effect immediately)
2006/2 VVVH HHHH (lower three bits of coarse V scroll, all bits of coarse H scroll)
* The first two writes only affect Loopy_T, so they can happen at any time during the scanline.
* The third write (setting fine X) should happen at dot 256 or later. Since writes take 4 CPU cycles (12 PPU dots) to finish, the store to $2005 instruction should begin at dot 244 or later.
* The fourth write should happen before dot 304. The store to $2006 instruction should begin before dot 292.
There's also another way to do it for just horizontal scrolling:
Write to 2005 between dot 256 and dot 304 to set the coarse scroll that will change after the next scanline, and fine scroll that will apply to the next scanline. So fine scroll applies immediately, and coarse scroll is lagged until the next scanline.
Write to 2005 one scanline later between dot 256 and dot 304 to set the coarse and fine scrolling.
I prefer the four write method, because you don't need to wait one scanline for it to finish. Even though you still need to calculate X and Y scrolling bits for the four writes.
exdeath wrote:
It does not appear that simply writing once to $2005 with appropriate delay is enough; I just go from overshooting the end of the current line to messing up the next line with a single extra NOP.
Yeah, one $2005 write isn't enough for a clean split. The X scroll is reset at cycle 257, just after the 256 visible pixels of the scanline, and for the coarse scroll to take effect on the next scanline it has to be changed before that. However, since the fine scroll takes effect immediately, anything before cycle 257 would be during the visible scanline, meaning you'd get glitches at the end of the scanline.
You can however do it all in one go with mixed $2005/$2006 writes (as Dwedit explained above).
Quote:
2) how to determine next hblank knowing that the IRQ is called at dot 260 of the current line.
Use timed code. You can just use NOPs at first (1 scanline is nearly 57 NOPs long) just to see how many cycles you have to burn, and then you can optimize the waiting code with a loop or something. You can never get things 100% synced though, since the CPU waits for the current instruction to finish before answering the IRQ, so your IRQ handler (and NMI handler too)will always jitter a bit, and you have to take that into account when operations have to happen at precise time intervals (I usually aim for the middle of the window, so that a little jittering is still inside the window).
Quote:
As I keep adding nops, I see the line stabilized from left to right with the glitches shrinking to the right, but just when Im down to the last couple pixels, one more NOP and bam the entire next line glitches.
That matches precisely the explanation I gave above.
OK lets see if I have this right:
MMC3 IRQ fires at dot 260 for the current line N after it's done rendering and N+1 is about to start.
It's too late to modify coarse scroll for the upcoming line N+1, so I have to write it for N+2. But I DO have to do it now, or at least before dot 256 of line N+1.
In doing so I affect the fine scroll for the soon to start N+1, which is why I have a line artifact that is coarse scrolled to the upper half of my screen but off by +/- 8 pixels because the fine scroll was reset.
So when I write the first write to $2005 at the start of the IRQ I need to have the coarse scroll for N+2, but mask in the old fine scroll from the previous line N so that the line N+1 happening immediately after the IRQ, which is unaffected by the coarse scroll change, continues to match the top half of the screen for just one more line while I wait a 1 line delay.
Then wait an entire line N+1.
Then during the hblank of link N+1, write $2005 again with the same coarse scroll but the new fine scroll.
Then my next question is, is there a diagram of the entire horizonal sweep with dot timing? Is is 341 dots per line where 0-255 is the active line or...?
My apologies if it's regarded as off topic, I felt the need to at least go into more depth of what I knew and attempt to see if the issue is indeed resolved.
thefox wrote:
infiniteneslives wrote:
The accuracy is good with the actual mmc3. But from what I'm told the power pak's isn't so great. It tends to jump back and forth a few scan lines on some games... So keep that in mind, it's not necessarily the mmc3 as much as it's the power pak.
This might have been true back when PowerPak was released, but I haven't had any problems like that with the loopy's latest mappers (or my own save state mappers). Still good to keep that what you said in mind of course.
I can't say for sure as I don't own a powerpak but someone came to me privately asking about Ninja Gaiden 3 specifically:
1. When you actually start the game, you have the health stuff on top and the "action part" below. The "action part" is what shakes.
2. After you go through the first exit, the shaking doesn't happen on the action screen, but I notice a line or two is missing from the bottom of the health bar.
I saw similar issues with my implementation of the MMC3 and realized the issue is CHR A12 being noisy as it's a poor clock source. Nintendo apparently had the same issue and added the 220pF cap to filter the signal. I added the cap to the NESDEV1 and it solved the issues. I suggested to this fellow to do the same with the powerpak and he also claimed it fixed everything. Perhaps he had an older powerpak and the capacitor as since been added IDK, but I don't see how this issue could be solved via mapper configuration inside the FPGA.
My remaining shimmer appears to be related to CHR-ROM bank switching in the IRQ.
I'm trying to play back the BG tile animation in one direction above the split, and reverse below the split. Of course this involves a bank switch mid frame to select the appropriate animate frame for the pattern data. I got it to line up but when scrolling it seems to lag behind 1-2 frames then line up when the scrolling stops, as if it's not completing the bank switch before the frame is over.
How long does a CHR-ROM bank switch take with MMC3?
It takes effect ASAP as far as I know.
Congrats! You now have something that not many games do, a clean split.
exdeath wrote:
Then my next question is, is there a diagram of the entire horizonal sweep with dot timing?
I don't think so, but that would be cool to have.
Quote:
Is is 341 dots per line where 0-255 is the active line or...?
There are definitely 341 PPU clock cycles in one scanline, but I think
they are typically numbered 1-341 rather than 0-340. That would make the visible portion 1-256, the rest is HBlank.
Quote:
How long does a CHR-ROM bank switch take with MMC3?
Bankswitching is instantaneous.
EDIT: Nintendulator appears to number cycles starting from 0.
exdeath wrote:
How long does a CHR-ROM bank switch take with MMC3?
Not sure what you're using as your time reference exactly. But the bankswitch happens at the end (EDIT: ~mid cycle might be more accurate) of the CPU clock cycle in which you write to $8001 "data" register. So to answer your question I'd imagine you'd count the CPU cycles in your code from when the interrupt occurs until you write to $8001.
The CHR bankswitch is instantaneous after the CPU write completes, but there is still a lag because the PPU buffers up to 16 pixels ahead of the current dot.
12 pixels between starting the instruction and the instruction finishing, then (depending on when the write finishes and fine X scrolling) between 5 and 16 pixels will be remaining in the shift register, and will use the old graphics.
So it's anywhere between 17 and 28 pixels of lag. Plan for the highest number. If the write finishes by dot 309 (begins by dot 297), there will be no glitches.
It's getting there, just need to figure out why the tile animations in before and after the split (playing in opposite directions) line up when motion is stopped, but jump by +/- 1 pixel while in motion.
Nothing is changing except the frame counter that is inc/dec by the L/R keys during vblank.
You should try to get your "plan" set in stone before Vblank happens.
Then the next frame is dedicated to executing that "plan".
Nothing that happens during execution of the current frame should change the "plan" you are currently executing.
Then when your computations are all done, you have next frame's "plan" ready for the next frame. But you are still executing the current "plan".
It's like page flipping or double buffering, but for a few variables instead of a screen.
This looks like a problem of overwriting things too early.
Ahaha got it.
Was reading the frame counter I use for scroll value and switching bank, then reading controller and updating frame counter. So if the frame counter changed that frame after the initial bank switch it was +/- 1 once the IRQ was called so the bottom half of the screen always had the tile animations +/- 1 while in motion.
Final version for tonight. Maybe.
The neat thing is that you could also make the top part scroll independently of the bottom, but still have the same apparent parallax position as the bottom.
Make a big game object out of background tiles that moves by scrolling. As long as the edges are square of course.
I don't think any games ever did this effect.
Dwedit wrote:
The neat thing is that you could also make the top part scroll independently of the bottom, but still have the same apparent parallax position as the bottom.
Make a big game object out of background tiles that moves by scrolling. As long as the edges are square of course.
I don't think any games ever did this effect.
Right. Just a matter of computing the proper BG tile animation offset and getting the CHR-ROM bank switch right to keep the BG layer aligned and scrolling together to give the illusion of being one seamless layer. Sky tiles in the top animating very slowly... rock tiles animating faster, and then the "two" foregrounds scrolling at diff rates.
I don't know why I'm having so much fun with this. I almost think it's more fun than SNES, GBA, and PS2 just because the hardware is so limiting. Seeing "3" layers on a NES is hilarious. Nothing beats the PS2's DMAC though.
Here's some basic information I've collected about the timing of the NTSC PPU (I guess the only differences for PAL would be the longer VBlank of 70 scanlines and the lack of skipped cycles on the pre-render scanline):
Code:
Scanlines
---------
0 to 19: vertical blank period; PPU doesn't make memory accesses; status flags are cleared at the end;
20: nothing is rendered; PPU makes all normal memory accesses; 1 cycle shorter on odd frames if rendering is enabled;
21 to 260: picture is rendered;
261: nothing is rendered; could have been part of the vertical blank;
Cycles
------
0 to 255: picture is rendered; 32 tiles are read from name, attribute and pattern tables;
0 to 255: sprites are evaluated;
251: vertical scroll is incremented;
256 to 319: sprite patterns are fetched;
257: horizontal scroll is reset;
304: scroll is reset on the pre-render scanline;
260: MMC3 IRQ fires if BG = $0xxx and SPR = $1xxx;
320 to 335: 2 tiles are read from name, attribute and pattern tables for the next scanline;
324 of the previous scanline: MMC3 IRQ fires if BG = $1xxx and SPR = $0xxx (abnormal);
336 to 339: index of the next tile to be fetched is read twice from name tables;
340: PPU does nothing; not present on pre-render scanline of odd frames if rendering is enabled;
Please correct me if you see any mistakes.
Dwedit wrote:
The neat thing is that you could also make the top part scroll independently of the bottom, but still have the same apparent parallax position as the bottom.
Make a big game object out of background tiles that moves by scrolling. As long as the edges are square of course.
I don't think any games ever did this effect.
Some Megaman games used background scrolling for large boss objects when they try to ram you.
Hblank scroll is used because the BG tiles on the top half don't change.
I'm sure others have done similar.
The parallax effect is limited to repeating seamless horizontal spans.
I meant when combined with parallax scrolling, not just the big object as background effect.
Dwedit wrote:
I meant when combined with parallax scrolling, not just the big object as background effect.
No point. Most large bosses are already bank switching large chunks of CHR-RAM to animate the sprites, basically the same thing, but without the limiting repeating seamless tile set imposed by parallax faking.
Wow this demo roks ! 3 faked layers on the NES it really looks awesome. It's a shame you didn't read my previous comment, though, because those blocky shadows could easily be improved.
Working on it. I'm more interested in learning proper implementation in hardware.
I'm a programmer with two left brains, not an artist.
Doing 32 versions of the rocks in primitive tools was repetitious and brain damaging bad enough. I have since cleaned up my nametable to use only 16 tiles instead of 32 and will be in the process of switching to a 1k animated CHR bank.
No going to bother with secondary things like shadows until I have a pretty enough tile set and map to be worth the extra polish.
YY-CHR lets you horizontally move blocks of graphics very easily.
Where it says "x8" is the zoom setting. Reduce this, and it fits more tiles into the editing area.
Get the editing area to be 32x32 pixels, then hit the "Shift to Right" button. Instant shifted graphics. Just need to copy paste a bunch of times, and hit it again.
It's a two minute job to copy-paste-shift in YY-CHR.
Any good map/nametable editors that can create maps of infinite H/V size?
exdeath wrote:
Any good map/nametable editors that can create maps of infinite H/V size?
I don't think so. Name table editors usually work screen-by-screen, and there are no generic map editors that I know of for the NES. This subject comes up every once in a while, but every time we discuss this we come to the conclusion that a generic map editor that satisfies the needs of all different kinds of games would be too complex to make, and nobody feels like trying.
Yeah, one would generally need to make a custom map editor for a specific game. That's possible, but first I'd have to know what data format your engine is using. Or if you haven't figured that out yet, first I'd have to see what an entire map might look like, along with how wide and tall they're allowed to be, so that I can help you design a data format.
Wow, You have some skill, mister!
Quote:
3 faked layers on the NES it really looks awesome.
3? I can only see 2.
First: Text box and solid bricks.
Second: Moving background.
Quote:
I'm a programmer with two left brains, not an artist.
Are you kiding? Not only effect is great, but Graphics too! I feel so jelaous of you
As for map editor, I find
MapEd Pro to be very good one. The only problem is that it do not support objects. So no sprite based objects can be placed, just pure map.
Lol graphics are just programmer art stolen from random games.
3 layers = rocks in bg + playfield bricks + stationary dialog window.
True, its not a overlapping layer, but its scrolled independently such that it appears to be another layer.
You could do the effect in a dozen of minutes really.
Just do the 1st version of the "nice" shadow, copy paste it to the next bank, switch it one pixel to the right (tools allows to do that easily) and add a pixel of shadow, repeat 16 times.
If I do that Ill wait for my powerpak and even do a black checkerboard dither overlay to the original tiles and make it look really nice with NTSC butchering.
Bucky O'Hare has probably the most extensive use of parallax/split effects. It does CHR cycling parallax backgrounds for many levels. Lots of levels have 3 or 4 splits onscreen for multiple large moving objects. I can't think of any other NES game that goes quite so far with it. I don't think it ever does CHR and split effects at the same time, though.
Checkerboard dithering doesn't look too good on the NES, it creates some diagonal patterns that are quite annoying. In fact, getting dithering right on the NES is kinda hard IMO.
rainwarrior wrote:
Bucky O'Hare has probably the most extensive use of parallax/split effects.
It probably is.
This effect for example is very impressive... 2 large layers independently moving in front of a static (although repetitive) layer. And it can even be done without the luxury of CHR bankswitching and scanline counters.
tokumaru wrote:
rainwarrior wrote:
Bucky O'Hare has probably the most extensive use of parallax/split effects.
It probably is.
This effect for example is very impressive... 2 large layers independently moving in front of a static (although repetitive) layer. And it can even be done without the luxury of CHR bankswitching and scanline counters.
One side is stationary in the name table but slightly off screen. Scroll towards it 4 pixels at a time while adding 1 column of 8 pixel tiles in the name table to the leading edge of the opposite side with each scroll. Thus it looks like both sides are coming at you at an equal speed of 4 pixels at a time from both sides. Use sprites (the spikes) to cover up the resulting attribute table artifacts every other frame as a result of updating 8 pixel tiles at a time on the one side.
Finally animate the BG tile so that it appears static while scrolling. Two frames of each tile at pixel offset 0 and 4 will do. This part does require CHR ROM bank switching in order to update that many BG tiles instantly. Everything else is just name table updates, scrolling, and hiding the attribute table artifacts, really no different from what you do when scrolling and updating tiles in a side scroller.
It is impressive though, how simple it is. I think I might try that tonight real quick.
exdeath wrote:
This part does require CHR ROM bank switching in order to update that many BG tiles instantly.
Not really. With a pattern as repetitive as that it would be trivial to upload the appropriate tiles to CHR-RAM every frame. Or you could even use a 4-pixel wide pattern instead and not change the background at all.
Quote:
I think I might try that tonight real quick.
Maybe you should try a vertical variant (columns of spikes coming from the ceiling), just to be a little original. You just have to be careful in order to not line up more than 8 sprites in a row.
Yes but I'd consider CHR-RAM to be as "special support" or even above CHR-ROM bank switching.
Vertical would be tricky with the sprite limits... more reason to try it.
Crude right now, needs some clean up and polish but here we go.
I cheated and avoid messing with the attribute table just yet, no sprites yet, etc. Work in progress but demonstrates the effect.
Could even have a scrolling 2 screen room with 2k of VRAM on the cart for X scroll. 16 versions of the BG tile (8 horizontal x 2 4 pix vertical) and you could even have the BG parallax scrolling horizontally while the floor and ceiling are moving up and down.
Hit a small snag initially, totally forgot about 16 bit arithmetic handling dynamic name table updates on a 8 bit CPU
Sped it up and added a delay at the extents to be something more like what you would see in a game.
With a moving pattern that simple, you don't even need to animate the CHR data. Swapping to a secondary nametable, or palette animation would work too.
Dwedit wrote:
With a moving pattern that simple, you don't even need to animate the CHR data. Swapping to a secondary nametable, or palette animation would work too.
Yeah it's just a place holder.
Interesting! That would be really cool in a game.
tokumaru wrote:
Interesting! That would be really cool in a game.
This !
Messing around a little more.
Next up probably dynamically updating attribute tables so I can put the BG parts on their own palette.
Hmm attribute table handling is getting out of hand when you start having features split across attribute bytes, having to read/mask/write, skip every other frame, etc.
So I'm going to rethink my approach by using display lists that instead just have address, count, and data and just blast per frame changes to the name table/attribute table with a unique display list per frame of animation. Then the code just simplifies to a simple array loop [lugging bytes into 2006/2007.
The code using LDA/STA sequences was already hard coded to a specific screen, so that doesn't matter. The display lists will be smaller than the code I'm using now currently since they will be the same exact data without the opcode bytes and STA addresses, and will clean up the code considerably into a generic reusable loop. I won't even have to do address calculations or offset by the frame count, since everything will be pre-computed in the addresses in the display list.
Since this is just a demo and not a game, I guess that cheating with pre-computed data is OK.
Is it cheating though? It's not a simple case of adding a row/column to the name/attribute table as in regular scrolling.
The changes made per frame are unique and specific to the "room" being shown and are in a fixed pattern tied to the layout of the "room", thus the data is hard coded and tied to the screen being shown regardless of being a game or demo.
Making them as display lists tied to the "room" is no different than pre-computed name/attribute tables for a given room.
Making them as display lists makes the "room" animation data driven and straight forward to manipulate as data belonging to the "room" rather than having to write/modify unique specific code for every single room
I suppose it could be argued another alternative would be to do an array copy from the existing name/attribute table and just bring down the parts I want one row at a time. But doing that is far more cumbersome because again, there are lots of random breaks in what gets copied, it's not just straight rows/cols, so you will always need some unique data/code saying what to copy and when.
6 tile row starting at (x, y), 4 tile row starting at (x2, y2), etc.
If anything I'll look to compressing the display lists by simply referencing the existing name table and how many tiles to copy so the data (tile index bytes) isn't duplicated in the display lists.
Well, to me it's cheating if it can't be implemented in a game. I guess that if you were to do it exactly like in Bucky O'Hare, where this happens in a room with no scrolling, it wouldn't be cheating. However, if this was part of a larger scrolling map, hardcoding VRAM updates would be harder because this special section would have to play nice with the scrolling engine, which is very dynamic.
I do like demos, but in the end, what matters to me is that things are feasible in actual games. =) If it works well inside the game engine and feels like it belongs there, I guess don't mind that the data necessary for special effects is pre-calculated.
The biggest trouble I'm having is the read/modify/write required with the attribute table if I am to modify the attribute data in place instead of blowing it away with a display list.
Due to the auto-incrementing nature of $2006/$2007, it would require writing the same address twice, to LDA $2007 an attribute byte, mask in the affected row (either bits 0-3 or 4-7), then STA to zero page in order to LDAx2 the address again, STAx2 the SAME address again , re-LDA the saved attribute byte from zero page, and STA $2007 it. Just seems highly inefficient to me. All that address reading/writing to modify a single attribute byte.
Of course I could do a read pass to ram, modify in ram, then a write pass, haven't tried that yet. It IS only 8 bytes of attribute data after all per vertical animation frame (of only a nibble of each is actually being updated). But again the data is broken up into regions, not just straight across, so the address setting to $2006 is going to have to be coded in specific to the level geometry.
I thought about just doing a reading the attribute data from the original source in PRG-ROM, modifying, and writing IT to avoid that problem, but it's still messy. I'm going to experiment with this too: read non incrementing row from ROM, modify and write to incrementing VRAM to duplicate downward, then erasing would be trivially recopying the original ROM table back to VRAM 1 line at a time in reverse.
The display list solution is just more elegant, and from the perspective of a level designer doesn't require special code that is tied to the tile layout of the level data.
It could be easily modified to work with scrolling by simply adding offsets when loading the base address from the display list.
Regardless of how I implement it, the code or precomputed data IS going to be tied to the geometry of the scene, there is no avoiding that since the rows/columns are broken up into varying regions, making it "special case".
I think it's time to invest in a generic name table/attribute table row/column copy library.
I was thinking with 2k CHR-ROM I would do 2 scrolling screens of vertically animated floor/ceiling, but I got to thinking, that's not enough... I eventually want to be able to scroll indefinitely so I need to be able to copy any arbitrary row/column at any scroll offset. Display lists will become significant in size and data duplication with anything more than a few screens.
I am starting to think like some of the Super Mario World levels where the entire level is navigating a maze where the ceiling is moving up and down.
exdeath wrote:
Due to the auto-incrementing nature of $2006/$2007, it would require writing the same address twice, to LDA $2007 an attribute byte, mask in the affected row (either bits 0-3 or 4-7), then STA to zero page in order to LDAx2 the address again, STAx2 the SAME address again , re-LDA the saved attribute byte from zero page, and STA $2007 it. Just seems highly inefficient to me. All that address reading/writing to modify a single attribute byte.
A common solution to that problem is keeping a copy of the attribute tables in RAM at all times. I do this in my scrolling engine.
Slightly amusing that its called NMI when it can be disabled and ignored.
Yeah, it's a bit ironic, but not so nonsensical when you realize that the name is because the CPU has no way of disabling them. Since the PPU is the one that generates NMIs though, it has the power to disable them.
EDIT: In other words, the CPU is always forced to accept NMIs, but if no other component is generating them, there's nothing to accept.
Any experience on the best way to store large maps?
As my own NxM array or consecutively packed single screens/native name tables ?
Name table approach seems like a pain having to compute tile locations across table boundaries so I'm leaning against it. Only thing going for it is making and exporting single screens of data is trivial while arbitrary NxM map makers with NES attribute alignment has poor existing tools. I suppose I could write a tool to interleave 1024 byte nam files into a single array.
Including an additional NxM byte array for tile properties, I can quickly see PRGROM getting eaten alive as well for large contiguous scrolling maps. As in 8k bank switchable areas for even a small 1x4 or 2x2 map.
The 1024 byte nametables are 2x arrays of data already. Best way to store them? Cheaply, probably metatiles. After that, probably some either RLE scheme, or an LZ scheme.
LZ and its special case RLE generally need a lot of RAM into which to decompress levels. That's fine if you can afford to put an extra SRAM on your game's board. There are two solutions, however, that work with very limited RAM like that of the NES. One is meta-metatiles, used in various ways by Blaster Master, Mega Man series, Sonic the Hedgehog series, The Legend of Zelda, and Super Mario Land. In this, each metatile is made up of smaller metatiles. Another is object-based level encoding, used by Super Mario Bros. series. In this, a map is a list of objects that have width and height of often multiple tiles, and rendering an area consists of determining which objects overlap it.
Yeah, also forgot to mention. The way it scrolls matters too. If it scrolls 8-ways, you'll probably never get a great low-ram usage and speed out of it. horizontal? LZ might work best, but then RLE with 15 different metatile streams with extra RAM to buffer the next screen write would probably be okay. Although still LZ would probably be better. But it all depends on your situation. You have to decide whatt works best for your situation and implement it all yourself.
Can anyone try this on a PowerPak?
download/file.php?id=58Someone sent me this and said it wasn't working.
https://www.youtube.com/watch?v=siRdo5eio88Looks like a mapper / CHR-ROM issue.
Works fine on 4 emulators I've used and the same technique in my first parallax test worked fine.
The only thing I changed was reconfigured the mapper to use 1k CHR-ROM banks.
Hmm 6 banks instead of 8, pretty sure I made sure it was power of 2 earlier...
Here it is again at any rate.
exdeath wrote:
Hmm 6 banks instead of 8, pretty sure I made sure it was power of 2 earlier...
Here it is again at any rate.
Works on the PowerPak after this fix.
The one you just posted runs fine from my powerpak.
Cool thanks. Yeah I noticed in the header it said 6 CHR-ROM banks instead of 8, not sure what happened.
Oh I know, it was initially 4 (BG + SPR + 8 x 1k pages) then I added a double animation to the BG tile and expanded it to 6 by the additional 8k without thinking
My PowerPak just shipped, w00t, so excited.
Here's a video capture:
OD2vZ-3-g_w
Also I'd guess that you're not doing something else exactly correct because when I run it on the
NESDEV1 I get some funky results with your *ORIGINAL* crush. Basially I have to run some other ROM first that appears to be prepping the PPU properly, before I can play your ROM. Otherwise if I just run your ROM initially I get a bunch of garbage/static. If I prep things with a different ROM I see your visual effects but the colors and tiles are mixed up a bit but it *kinda* works. FYI You usually don't see these types of issues with the powerpak since it sets up the PPU and everything for you before your game even starts. Are you waiting long enough before writing to the PPU? Or clearing $2002 before polling? When I run your latest version I can't get it to do anything, just blank screen...
Based on the latest reports I guess it works on the powerpak though. I still have to reset to start your game. I don't think you have to hit reset on the powerpak.
Not sure if it helps or you're concerned about all this but I saw
similar issues when making my first demo here. My problems resolved after hitting reset. For your ROM I see a different tile set every time I hit reset... Eventually If I hit reset enough I'm left with white screen.
It's possible I've got an issue somewhere in my hardware but my MMC3 has been pretty solid for awhile now. If you're interested I could try it on other devices I have sitting around as well.
No proper initialization of anything, just power on and go to town. I'll look into that for future builds.
Right now just kinda experimenting and feeling out the platform and dev tools and learning things like this. I haven't done any console dev since the PS2 was new in stores
Of course it works on PowerPak, the bootloader/OS probably does a hot transfer to the game ROM with everything nice and ready.
Yeah it doesn't wait for the PPU warm up before writing the palette. So, it doesn't work on the PowerPak (either) after a reset.
It really is a shame that no emulator emulates the boot up behavior.
Minor nitpick but it's annoying not having blt/bgt/ble /bge aliases. Takes me a second to think about which branch opcode to use.
exdeath wrote:
Minor nitpick but it's annoying not having blt/bgt/ble /bge aliases. Takes me a second to think about which branch opcode to use.
That's what macros are for.
I actually went verbose with mine and call them jl_unsigned, jge_unsigned etc.
I don't see this playing into the demo you've got now, but it's just a thought that occurred to me: Many games create a parallax effect by changing the scroll mid-frame (often multiple times). It's trickier because it requires timed code (or a suitable mapper), but it might be cool to change CHR banks mid-frame to get a similar effect combined with the parallax effect you've already got. You know, in case three layers aren't enough for you.
Yes, I've considered it and will probably do so when I go back to that one. All the techniques including clean split scrolling with timed code and bank switching in hblank are already present in the "test" demo. Implementing more would be trivial. I'm limited by my ability to create assets at the moment. For real use in a game setting I was thinking a sky parallax at the top, a dirt/rock/hill parallax in the mid to bottom, and a non square dilapidated Castlevania/Faxanadu (sp?) themed brick structure in the foreground with bars/windows and holes and a wavy top to show the background layers with chimneys and trees and such extending up through both bg layers to emphasize them. Its just a ton of tiles to make so its not my priority right now.
Currently have moved on to experimenting with sprites, animation, and player action flow.
Then some basic tile/nametable/coordinate/scroll libraries, collision detecting and event triggers, and tie it all together. Already working on a bank layout that would all the effects shown in both to occur in the same rom where each level init brings its own NMI for unique level by level effects, etc.
One baby step at a time.
rainwarrior wrote:
Here's a video capture:
OD2vZ-3-g_wYou know, I think this effect may work quite nicely with a scrolling room actually (as long as it's just horizontal scrolling). Seems like it may be doable in a game actually.
There's one problem though... the player also adds to the sprite limit count =P Any parts of the levels that are made out of sprites would need to take this into account. Since they're sprites, maybe it'd be a good idea to make hollow walls or and stuff like that, at least to give some extra room (also adds to the parallax effect as those parts aren't tied to tile alignment).
Don't know how you guys ran these on PowerPak, neither of them worked on mine.
For starters, I had to enable the right mirroring mode on the MMC3, it appears to override any PPU settings. Emulators have this wrong it seems as I never encountered it before. Both test.nes and crush.nes scrolled around garbage data instead of mirroring properly. I played around with x/y scroll values to see and sure enough the horizontal/vertical mirroring wasn't what it was supposed to be.
lda #$01
sta $A000
Fixed the garbage name table mirror on both and got "crush.nes" working perfect on the PowerPak (Ive added proper reset code to both).
Next is what appears to be a Y scroll problem with "test.nes" where I'm seeing intermittent frames where the bottom half of the screen split at line Y=50 is aligned to Y=0 almost every couple frames where it appears to be overlaid over the correct version.
Hitting reset a couple times gets lucky and resolved the problem for good until the next reset.
This did give me some ideas about Sonic the Hedgehog style water effects though via frame interleaving and time multiplexing. Could put the whole screen under water by a) flipping name tables to all water tiles every other frame and b) animating the water tiles.
Apply some hblank sine waves and it might look pretty cool, and you'd get the automatic slow down from 60 fps to 30 fps being under water
Sik wrote:
rainwarrior wrote:
Here's a video capture:
OD2vZ-3-g_wYou know, I think this effect may work quite nicely with a scrolling room actually (as long as it's just horizontal scrolling). Seems like it may be doable in a game actually.
There's one problem though... the player also adds to the sprite limit count =P Any parts of the levels that are made out of sprites would need to take this into account. Since they're sprites, maybe it'd be a good idea to make hollow walls or and stuff like that, at least to give some extra room (also adds to the parallax effect as those parts aren't tied to tile alignment).
Right, so no contiguous horizontal span of "chomper" edge can be more than 6 tiles wide (assuming 2 x 8 tile player sprite) and no two horizontal spans can coexist on the same tile row. This is only for the top layer, the bottom layer is static, but the top layer is getting real time single tile name table updates, hence need for sprites to hide the attribute glitches every other tile of movement.
Also no enemies.
Mine has no sprites yet, which is why I'm limited to the background sharing the same attribute value as the top layer.
Bucky O'Hare doesn't have this problem since it's horizontally oriented so it's 1 BG sprite per row leaving 7 for objs.
The other limitation is the top section repeats and can't have any detail that doesn't repeat and tile vertically, otherwise features would scroll off the top of the screen or require a significan't amount of name table updates to move the entire top half rather than just copying the previous row.
A few small details here and there in the top would be ok since its only needing to insert 32 tiles per frame for the scroll effect, plenty of room left to copy down a few inner tile features.
Hmm found my bug.
Something to do with reading $2002 for vblank status for my main loop was screwing up the scroll registers.
Looked something like this:
Code:
vblank:
lda $2002
pbl vblank
; read controller and update x_scroll
jmp vblank
nmi:
pha
lda #$00 ; top half screen coming up at 0,0
sta $2005
sta $2005
lda #$4F
sta $E000
sta $C000
sta $C001
sta $E001
pla
rti
irq:
lda x_scroll
sta $E000
; do 06/05/05/06 timed code writes,
rti
Something about having an NMI handler and then when that quits, returning to a main loop that immediately reads from $2002 multiple times in a waitvblank loop. Since my NMI would finish and I'd still be in vblank, my main loop would quickly run multiple times reading from $2002 (but no other registers).
Somehow this was clobbering my scroll values, not sure how. I didn't write to anything else in my vblank loop.
I had NMI set scroll to 0,0 for the start of the frame and enable IRQ for the scanline break. The IRQ just did the 06/05/05/06 writes for the split. So the IRQ runs, it splits the bottom half, alls good... get to the NMI, reset screen position to 0,0 and somehow between there and my mainloop before IRQ or NMI triggers again the scroll gets all messed up and I see rapidly flashing alternating images. I know the problem now so I can reproduce it at will for demonstration.
I'm assuming the best course of action would be to set a flag in my NMI that is set at the start of my main loop and cleared at the end of the NMI that gives my main loop the go ahead to proceed and not touch the vid regs outside of NMI and IRQ.
I'm trying to think why I had both.... it looks pretty stupid looking at it right now. At any rate I've cleaned it up, works flawlessly on a real NES now. What I am going to do now is something like this:
Code:
mainloop:
lda #$00
sta READY
; read controller and update x_scroll and do "game" stuff
not_ready:
lda READY
beq not_ready
jmp mainloop
nmi:
pha
lda #$00 ; top half screen coming up at 0,0
sta $2005
sta $2005
lda #$4F
sta $E000
sta $C000
sta $C001
sta $E001
lda #$01
sta READY
pla
rti
irq:
lda x_scroll
sta $E000
; do 06/05/05/06 timed code writes,
rti
Make the main loop that waits for VBlank do something like this:
Code:
WaitForNMI:
LDA Frame
.Loop:
CMP Frame
BEQ .Loop
RTS
and at the end of your NMI, just do a INC Frame to advance the counter. Loading values from $2002 would work, but it's not a good solution.
Right.
Also explains why I SWORE my main loop was running multiple times per frame sometimes.... /facepalm
Code:
vblank:
lda $2002
bpl vblank:
; do stuff
jmp vblank
Total fail....
Going to go hide now.
Also forgot to add, BIT $2002 for the start of your NMI, and then also you'll need to enable NMI on $2000 register.
And lastly, it'll make it skip frames, not make more. But yeah just program it not to rely on $2002 reading just to make sure the code stays somewhat clean.
exdeath wrote:
Also no enemies.
You can still add enemies in areas that don't overlap, as those won't have sprite-based walls.
Sik wrote:
exdeath wrote:
Also no enemies.
You can still add enemies in areas that don't overlap, as those won't have sprite-based walls.
If the enemy is higher than the lowest part of the ceiling when it's all the way down, there will be 8+ sprites in a row horizontally.
Sure, would take careful planning of the level layout.
I never acknowledge the NMI (i.e. BIT $2002) and I never had any problems. I don't think this is mandatory. Some people use it as insurance against misaligned $2005/$2006 writes, but I'd rather not use this kind of insurance so I can actually see any possible bugs and fix them (you should be writing to $2005/$2006 in pairs).
As I suspected my sprite test is 9000% smoother now thanks to my stupid documented above.
Also explains why I didn't have any acceleration... it maxed out in 1 iteration...
exdeath wrote:
For starters, I had to enable the right mirroring mode on the MMC3, it appears to override any PPU settings. Emulators have this wrong it seems as I never encountered it before.
Depends on the initialization value that the mapper uses for the mirroring. PowerPak is no better than emulators in this regard, it'll use whatever init values the mapper author decided to use. I guess my save state mappers happened to use the correct initial mirroring for your ROM.
And now thinking about it, I think I deliberately changed the mirroring initialization value to horizontal mirroring to make the mappers compatible with Karnov, which has been assigned iNES MMC3 even though it doesn't use MMC3.
The only thing that emulators arguably get wrong, from NES developers point of view, is that they don't spit out warnings when the entire mapper state hasn't been initialized.
Seem to have uncovered another bug in my code running on a real NES that didn't surface before now. I get one pixel of vertical jitter in my screen split. Everything after the split is right where it needs to be, but the bottom half the the screen is unstable and jumps up and down by a single scan line now and again.
What's weird is it's randomly present or not present after a reset. If you manage to reset and it goes away, it never comes back. Likewise if you reset enough times and it happens, it will stay there.
Code:
irq:
pha
sta $E000
; v = line 80 = $50 = $%01 010 000
lda #$00
sta $2006 ; nametable select
lda #%01000000 ; VV-- -vvv
sta $2005
lda #%0000000 ; ---- -hhh
sta $2005
lda #%01000000 ; VVVH HHHH
sta $2006
pla
rti ; return from interrupt
MMC3 IRQ is set to trigger at 7F and I originally had some delays to split the screen at line 80.
I've stripped out everything not relevant and replaced everything with constants so no carry issues, etc,
Not worried about the timing and clean split and scanline glitch right now. This code above exactly as is will jitter the entire bottom half up and down by a single line randomly.
Code:
irq:
pha
sta $E000
txa
pha
ldx #$FF
.waste
dex
bne .waste
; v = 80 = $50 = $%01 010 000
lda #$00
sta $2006 ; nametable select
lda #%01000000 ; VV-- -vvv
sta $2005
lda #%0000000 ; ---- -hhh
sta $2005
lda #%01000000 ; VVVH HHHH
sta $2006
pla
tax
pla
rti ; return from interrupt
This code however works fine, other than delaying screen split 11-12 scan lines. Could not reproduce the jitter at all.
Any ideas? I could probably use what I've found to insert additional scan lines between the IRQ and the scroll, but I hate not knowing why.
Note again, that the 06/05/05/06 code is not timed in either and BOTH exhibit the normal flickering scanline at the split location, but the top code will randomly cause the whole bottom part of the split to jitter up and down by 1 whole line.
I've sat here for 15 mins hitting reset on the second one. What you see there is literally the only thing changed. The only relationship I see is writing 05/06 too close to the line where the IRQ fires.
Hmm nvm maybe... I think the vertical scroll jitter is just another artifact of not timing the writes correctly. I just thought I had because it worked in the emulator. The veritical jitter of the whole part of the screen is another possible artifact that I just don't see on an emulator.
Throwing in some button reads to shift the value of the .waste loop in real time so I can see if the jitter occurs only when the visible break occurs past dot 256 (eg: fine x is good but somehow v gets delayed or messed up due to IRQ entry latency variations).
Still can't think of a reason it happens randomly between resets.
Ok so I altered the second example with $10 initialized to 1 so it wont loop at all, but then put in controller code to inc/dec $10.
So it behaves like the first example now, I can load the rom, and press reset a few times until it comes up jittery. However moving the loop delay around with the controller never gets rid of the jitter no matter where it is, it's constantly there.
No.. wait I just hit a few spots where the jitter stops completely.
My theory right now is
a) it's just a classic mistimed 06/05/05/06 write problem with respect to the current PPU cycles and vvv is getting clobbered somehow, and
b) it only happens randomly having something to do with PPU/CPU synchronization throwing off the exact cycle of the writes that are too close to their respective write deadlines without enough window for error.
But wait... if I reset until it's not jittering initially, I CANNOT get it to jittter at all.
Are you on the powerpak? Because the jitter of the entire screen below scanline that it's firing is the same issue that was explained to me by another powerpak owner that I brought up previously.
I saw the same thing in my implementation of the MMC3 and presumably Nintendo did as well. It's due to noise on the CHR A12 line a little extra noise will cause the clocking circuitry to clock an extra time or two and as a result the whole screen jumps up a scanline or two. I saw this on SMB3 and especially in KLAX (J). Kevtris saw the same thing with his FPGA implementation as well. Although he explained it was due to the improper length of filtering consecutive CHR A12 edges. I found that changing the length of digital filtering would affect this but didn't have enough fine tuning to get rid of it completely.
In any event adding a 220pF capacitor on the CHR A12 line cleared everything up for me. Original MMC3 boards have 220pF capacitors and don't have problems. The powerpak doesn't have a capacitor as far as I know. The guy I talked to added a capacitor to CHR A12 on his power pak and solved the problem for him. Obviously I can't be sure that's your issue but it sure sounds like it could be.
If you haven't already it'd be worth upgrading to thefox's save state mappers his MMC3 doesn't have the issue from what he reports. Otherwise if that doesn't work I'd suggest adding a ~220pF capacitor to the CHR A12 INPUT line to GND near the fpga and see if it helps.
If you're seeing it on some resets and not others it sounds like the digital filter may not be set to the proper length of CPU cycles. That would lead me to believe updating your mappers may very well solve the issue.
I went to thefox's MAP04.MAP and haven't been able to reproduce it.
Went back to the one I had before, it's gone there as well....
Are the FPGA I/O pin settings stored in flash instead of SRAM or something? Thought pin skew and all that was part of the bit file.
No that wasn't it.
I mixed up and cycled through three diff MAP04.MAP files and never went back to the one with the problem. I finally figured out I had no less than 3 versions of MAP04.MAP and tried them all.
Problem tested and resolved 100%
Loopy's MAP04.MAP is the one that seems to be the problem.
powerpak_loopy MAP04.MAP 11/17/11 <--- this one causes the jitter
POWERPAK134105 MAP04.MAP 10/17/09 <--- this one works fine
save-state-mappers-1.5 MAP04.MAP 10/07/11 <--- this one works fine
Heh never thought to consider hardware. Glad that's behind me after wasting a few hours looking for a software problem.
Now that this can of worms has been opened, whats the recommended mapper configuration, say, coming from a clean CF card?
We told you before: when it comes to mappers, you can't trust the PowerPak 100%.
Ok now I'm just being silly...
Wowzers! That's insane to see with the NES. Congrats!
Seriously though you should start waiting the 3 frames for the PPU to warm up before writting to it. I really want to see this on my NES/TV instead of emulators!
Here's the guidance:
http://wiki.nesdev.com/w/index.php/PPU_power_up_stateShould be a simple copy paste
How exactly are you adding the 4th pillars/hills layer? Are you using a mix of sprites and background? I'm really having a hard time seeing how you pulled this off exactly...
infiniteneslives wrote:
Seriously though you should start waiting the 3 frames for the PPU to warm up before writting to it.
This is another thing the PowerPak doesn't let you debug... since it takes care of initializing the system, the program works fine even if it doesn't wait the 2~3 frames the PPU needs to warm up.
infiniteneslives wrote:
Wowzers! That's insane to see with the NES. Congrats!
Seriously though you should start waiting the 3 frames for the PPU to warm up before writting to it. I really want to see this on my NES/TV instead of emulators!
Here's the guidance:
http://wiki.nesdev.com/w/index.php/PPU_power_up_stateShould be a simple copy paste
How exactly are you adding the 4th pillars/hills layer? Are you using a mix of sprites and background? I'm really having a hard time seeing how you pulled this off exactly...
It's already implemented. Works on the powerpak flawlessly with the latest MAP04.MAP from the PowerPak home page or the save state mapper. I've included the init code in everything I've done so far as well as patched up some other things like explicitly setting the mapper mirror state in case the PowerPak/cart/emu doesn't have the required initial state, etc.
There are two MMC3 IRQ hblank splits to get the text box, the middle clusters of stuff, and the floor. That's why none of vertically overlap. Then the final background is just animated CHR-ROM.
This is only useful for pure side scrollers on the same flat level ground, like Zelda II fights in the grass or Kung Fu kind of stuff. To make it useable in a game, I'd have to bring the last split up higher, have cutoffs on the background tiles so they aren't abruptly cut off by the hblank change, and then devote some vertical space to the bottom for things to jump on/over.
To make up for it, there could be a MMC3 IRQ to put a foreground and then scroll it every line from then on out aka Sonic.
Or if you have the CHR ROM to spare, any tiles from the BG that also vertically lap into the playable foreground area could be animated as well so you don't have to have cut offs (eg: most commercial games have a distinct dither to black fade that always occurs on a scanline/tile boundary, aka no vertical overlap).
The other limitation is everything that lies on top of the furthest background is distinctively square and obviously tiled. If you had an irregular shape it would either have to sit in a obvious box of solid color, breaking up the overlay effect, or you'd quickly exhaust your CHR-RAM buy having 32 copies of any metatile that had background showing through behind it.
infiniteneslives wrote:
How exactly are you adding the 4th pillars/hills layer?
Since the very beginning of this topic we have been talking about how this effect is done. The hills/pillars scroll normally, but CHR bankswitching is used to delay the movement of the background rocks to make it look like they're scrolling slower. In order to have full control of the position of the rocks, 32 versions of the background pattern are necessary (since it's 32 pixels wide), and the appropriate one is selected for each frame depending on the scroll.
Damn, can't do Sonic the Hedgehog waterfall transparency effects thanks do the anti-dot crawl even-odd thing they do. Vertical lines actually show up as vertical lines... so NES > Genesis? Lol.
Well it is on a PVM RGB monitor but it's still a composite signal. And checkerboard dithers show up as a diagonal rainbow.
Oh well there is always time multiplexing aka Sonic the Hedgehog shield and water.
tokumaru wrote:
infiniteneslives wrote:
Seriously though you should start waiting the 3 frames for the PPU to warm up before writting to it.
This is another thing the PowerPak doesn't let you debug... since it takes care of initializing the system, the program works fine even if it doesn't wait the 2~3 frames the PPU needs to warm up.
Partially true, but it can actually be debugged by pressing RESET right after starting the game, because PPU requires the warm-up time after reset as well. On my save state mappers you have to hold down A button so it doesn't display the menu, though.
exdeath wrote:
Damn, can't do Sonic the Hedgehog waterfall transparency effects thanks do the anti-dot crawl even-odd thing they do.
If you keep rendering disabled until the start of rendering, that one dot is never skipped, so every frame has the same length. You could do this by making sure sprite 0 hit gets set somewhere in the frame, disabling rendering in the vblank, and then wait for sprite 0 hit flag to be cleared (which happens at the end of vblank), and then enabling rendering again.
BTW, very nice demo.
BTW what's in a MAP file exactly? I thought it was just raw FPGA SRAM bit data, but I'm wondering how you put a title screen in it. Is that ROM data coded into the FPGA or...?
exdeath wrote:
BTW what's in a MAP file exactly? I thought it was just raw FPGA SRAM bit data, but I'm wondering how you put a title screen in it. Is that ROM data coded into the FPGA or...?
The .MAP file also contains a small 6502 stub that takes care of shoving the mapper to the FPGA and other stuff. It's followed by the FPGA configuration data. I didn't use the 6502 stub to load the menu though, I put it in the FPGA Block RAM (3KB of that on the PowerPak FPGA if my memory serves me right). I could've put it in WRAM, and in hindsight probably should have (so that the Block RAM could be used for other purposes, like 4 screen mirroring), but this was easier to do at the time.
thefox wrote:
exdeath wrote:
Damn, can't do Sonic the Hedgehog waterfall transparency effects thanks do the anti-dot crawl even-odd thing they do.
If you keep rendering disabled until the start of rendering, that one dot is never skipped, so every frame has the same length. You could do this by making sure sprite 0 hit gets set somewhere in the frame, disabling rendering in the vblank, and then wait for sprite 0 hit flag to be cleared (which happens at the end of vblank), and then enabling rendering again.
Still don't think it would work from what I've experimented with. 256 dots vs 320 dots isn't packed close enough to really bleed, and the NES actually puts out a REALLY friggin clean signal for NTSC. Then again the monitor I'm using is a Sony PVM 20M4U. Still I expected more blending just due to the NTSC encoding alone regardless of display.
thefox wrote:
tokumaru wrote:
infiniteneslives wrote:
Seriously though you should start waiting the 3 frames for the PPU to warm up before writting to it.
This is another thing the PowerPak doesn't let you debug... since it takes care of initializing the system, the program works fine even if it doesn't wait the 2~3 frames the PPU needs to warm up.
Partially true, but it can actually be debugged by pressing RESET right after starting the game, because PPU requires the warm-up time after reset as well. On my save state mappers you have to hold down A button so it doesn't display the menu, though.
But you can't catch everything since you cant start from power up. I found issues in my beaver pong and in driar where you had to press reset after power to get things to be drawn correctly. Maybe warmup takes less time from reset than power up. So you'll catch gross violations of several frames from reset but not small one frame warmup violations.
I'm still curious how you did this though, the only thing I can think of for the vertical boundaries is that you used sprites for boundary but background to fill. The horizontal boundaries are less mystifying with the use of the scanline counter.
infiniteneslives wrote:
I'm still curious how you did this though, the only thing I can think of for the vertical boundaries is that you used sprites for boundary but background to fill. The horizontal boundaries are less mystifying with the use of the scanline counter.
He's not using sprites. If you debug the demo you'll see that it never even touches the sprite-related registers (which is actually a bad thing, he should have put the sprites off screen). The trick is much simpler than you think. The background (rocks) is a virtual layer of sorts, because the CHR-ROM contains several rotated version of it, so no matter what the real scroll is, you can load a rotated version of the background that will make it seem like the scroll is different for the background.
Let me try to explain it another way: Think of a static scene, and then the "camera" moves 1 pixel to the right. Normally, this would cause everything in the screen (foreground and background) to move one pixel left, however, he bankswitches a new CHR for the background, where the rocks are shifted 1 pixel right, which visually nullifies the fact that the whole pattern table moved 1 pixel left. This will make it seem like the foreground scrolled, but the background didn't. The next time the camera moves, the backgrouns is allowed to move as well, so this causes the foreground to move every frame but the background only moves every other frame, which makes it look like it's moving slower than the foreground.
Ahh you explanation wasn't what I couldn't figure out but I realized where I was thinking wrong. In the original demos the floor was the background so I had it in my head it still was. I understand what's going on with the bricks and CHR ROM. I realize the simple fact the floor is the split screen with the scanline counter. I guess I didn't think of it because the screen split is more commonly used for static SMB3 style menu bars.
Hills- normal PPU scrolled background
Rocks- CHR-ROM bankswitching of the background for slower visual effect.
Floor- scanline counter used for screen split and then CHR-ROM bankswitched for faster visual effect.
Banner- another screen split? So this would have different mirroring to prevent it from scrolling, and the bricks around the edge are just CHR-ROM bankswitched. But really you'd be switching them at a different speed than the scrolling background.... This one's got me stumped now.
Must have more layers!!! Any ideas of how you could do another? I'm guessing you're not stopping here.
So does the scrolling look a lot more clean/smooth on the NES with CRT? It's pretty jumpy/skippy in my emulator. Hopefully the next release has the PPU warmup so I can see it for myself
It's smooth as silk in Nestopia and on real hardware. FCEUX is just really jerky for some reason.
Here's the breakdown.
NMI:
-read input, inc/dec x_scroll
-set scroll to 0,0 so the dialog box doesn't move
-bank switch CHR-ROM to animate the rock layer by x_scroll, but twos compliment the index into the bank selection to reverse the animation so the relative motion matches the scrolling versions below the split to make the rocks seamless
-set up MMC3 for IRQ at line 80-1
-reset an irq index to 2
IRQ:
-dec irq index, if zero go to irq 2
- irq1: breaks at 80 for the dialog box
- timed 06/05/05/06 writes set scroll to (x_scroll, 80) without artifacts
- bank switch CHR-ROM this time just normal forward animation
- set up next MMC3 irq counter in another 128 scanlines from now
- end irq
- irq2: breaks at 208-1 for the floor
- timed 06/05/05/06 writes to set scroll to (x_scroll<<1, 80) without artifacts
- end irq
I've already added the PPU warm up, it works on a PowerPak after reset. Have you tried my last link?
I could add another layer just by increasing the rock frames from 32 to 64, shift the rocks to moving every other frame completely rotating in 64 frames, then overlay something else like a mesh or cloud or something that rotates every frame and repeats twice from (0-31 and 32-63). This is what I do in my crush demo, except it's only a single 8x8 tile with 8 and 16 frames instead. I borrowed this animation within an animation technique in a single tile from Metal Storm. It's very limiting as a) both repeating patterns are going to be duplicated every 32 x 32 pixels and b) both "layers" are restricted to the same attribute limiting each "layer" within the metatile to 1-2 colors each.
Any other layers would have to be achieved with more scanline irqs or additional bank switched CHR-ROM animated at different speeds within the same 32-64 frames (or use another bank and switch is slower). The more layers added the more useless it seems to be in a real game though as you quickly squish down the area available for foreground since there can be no vertical features overlapping the scanline splits. To be useful in a game you'd need at least half the screen height scrolling together with the only "overlap" being the rock layer tiles set within the playable area. eg: my "hills/pillars and floor would have to scroll together and be the playable area (platforms etc) and I'd have to shift the other splits up and down to make room for scroll effects above and below the playable area. See games like Ninja Gaiden and Sword Master where the interactive playfield is very crude and limited to simply side scrolling level ground due to the many scanline split background sections.
What could also be done is a thin cloud/sky layer above or instead of the dialog box, and then a per scanline scrolled grass/hills/sand/water pattern in the fore-foreground below the floor, things like that. Another option is time multiplexing in another name table every other frame scrolling at different speeds, but this would be limited to semi translucent features like clouds in the top and water in the bottom. It would strobe a bit but this is how games like Sonic the Hedgehog do their water in Chemical Plant Zone, etc.
Lastly, sprites can be used for things such as poles, trees, clouds, meshes/bushes in the foreground, which could scroll independently of anything else, with careful consideration of the 8 sprites per line limit.
But at this point I think I've proven to myself that I've mastered the effect and it's time to move on
WTF why does nesasm assemble JMP ($xxxx) to 4C instead of 6C?
NESASM uses [] for indirection, instead of the standard (). One of the reasons it sucks.
I think you should use square brackets for indirection, not only for jmp, but also for any other addressing mode that uses indirection like (aa),Y and (aa,X)
Or - just avoid NESASM. I mean seriously. It's the nesticle of the 6502 assemblers.
Yeah, NESASM3 isn't the best when you use it without reading into how it works. But when you do use it's syntax, it works a lot better. But it's not the greatest, but it's nowhere near the nesticle of compilers. That's a joke.
My guess is because it supports paranthesis for order of operations, but the developers didn't feel like going through the extra trouble to parse the text for the special assembly cases that use paranthesis.
Code:
.db ($20+3)*2
;becomes
.db $46;
;So...
.dw ($2000)
;becomes
.dw $2000
;And so...
jmp ($2000)
;Is assembled as the wrong jmp,
;because it doesn't detect the indirection. It just assumes you're using
;() to control the order of an equation
At least... that's my guess as to why. Easier to just switch to [] to avoid ambiguity for the parser. Meanwhile, it creates ambiguity for everyone used to the normal way. (Yes, Kasumi has flip-flopped on this issue.)
Should you continue to want to use nesasm (I do), be aware that (indirect),y is also affected and needs braces.
3gengames wrote:
But when you do use it's syntax, it works a lot better.
It shouldn't have its own syntax to begin with... 6502 assembly has a established syntax, and there's no reason to mess with it except to confuse programmers. I guess it's OK for assemblers to offer macros and other special features with differentiated syntax, but there's absolutely no reason to mess with the basic language.
tokumaru wrote:
NESASM uses [] for indirection, instead of the standard (). One of the reasons it sucks.
I happen to prefer [] for indirection, it make sense to me. I think MagicKit is good (especially the Unofficial MagicKit, which adds many features). Use () for parentheses in expressions like you do in C and so on.
Therefore: If you use MagicKit, please learn it at first!! (Otherwise, don't use it. But I suggest to learn NESASM/MagicKit, and then use it.)
Kasumi wrote:
My guess is because it supports paranthesis for order of operations, but the developers didn't feel like going through the extra trouble to parse the text for the special assembly cases that use paranthesis.
At least... that's my guess as to why. Easier to just switch to [] to avoid ambiguity for the parser. Meanwhile, it creates ambiguity for everyone used to the normal way. (Yes, Kasumi has flip-flopped on this issue.)
Should you continue to want to use nesasm (I do), be aware that (indirect),y is also affected and needs braces.
Yes, this is how it work. I also think it just makes more sense to use [] for indirection like C does.
tokumaru wrote:
It shouldn't have its own syntax to begin with... 6502 assembly has a established syntax, and there's no reason to mess with it except to confuse programmers. I guess it's OK for assemblers to offer macros and other special features with differentiated syntax, but there's absolutely no reason to mess with the basic language.
I disagree...well, I suppose you could make a option to change this if people prefer () for indirection like the standard 6502 assembly does, in case this is what you want.
MagicKit also uses < for zero page addressing, a feature I like but I don't think it is a standard 6502 assembly code.
6502x86!
I'm fine with it, just caught me off guard. Traced my code and saw jumping to the middle of nowhere even though the operand address was correct then noticed the 4C opcode.
I recall I used [] already for 16 bit copy operations using [nnnn], y already.
I hope you mean [zp],y because [$nnnn],y doesn't exist.
Not sure what your next step is, but I was playing around with the FME7 today and was reminded of one of my favorite parallax/layer effects in
Batman ROJ with the upper cloud effects. I'm guessing it's just bankswitching but the 4 layers in the clouds looks pretty good IMO, I can see how some might consider it too busy but it looks a lot better on the NES/TV than the youtube video.
The 4 layers in the ROTJ clouds are 32, 24, 16, and 8 pixels in width. Every two frames, these move exactly 4, 3, 2, and 1 pixels respectively. Thus, they all loop every 8 ticks ( 32/4 = 24/3 = 16/2 = 8/1 = 8 ).
The FME-7 with 1k CHR banking makes this not terribly wasteful. It's taking up half of 8 x 1k banks. Though, there seem to be a lot of "filler" tiles marking unused space in the CHR. The character animations are mostly done with 1k CHR paging as well.
rainwarrior wrote:
The FME-7 with 1k CHR banking makes this not terribly wasteful. It's taking up half of 8 x 1k banks. Though, there seem to be a lot of "filler" tiles marking unused space in the CHR. The character animations are mostly done with 1k CHR paging as well.
Well if you want 8 full 1K CHR banks and a scanline counter at the same time RAMBO-1 (mapper 64) would be the likely choice. Otherwise you can use FME-7 (mapper 69) and it's CPU cycle counter instead of a scanline counter. The RAMBO-1 is the most versatile MMC3 like mapper with 8 full 1K chr banks and a counter that is switchable between scanlines and CPU cycles. Beware though, the RAMBO-1 fires IRQs a few (~5 dots I thinks) later than MMC3. It also lacks WRAM but I don't think exdeath cares, and in reality we can add WRAM if we'd like.
Working on this right now. Still have a lot of tweaking to do.
You know what my wife just suggested when she saw the 4-layer demo? That it would make a good fighting game! The text box could become health bars (character portraits should be sprites though, because of palette limitations), and the parallax would look amazing as the fighters moved back and forth.
These layering effects are really cool, but hard to put in a platformer, so a fighting game might be the best way to showcase a number of interesting landscapes. And since you're not using any sprites for the effect, they're all free for some decent-sized sprites. Just make sure that the flickering doesn't get too annoying.
Also, fighting games are easy to program, since they don't have to deal with level maps (you wouldn't even have to deal with realtime name table updates, since arenas that are 2 screens wide are more than enough). The difficult part is drawing all the sprite animations!
But to avoid flicker from hell, you'll probably need to make the sprites about as small as they are in Shaq Fu. But that makes a platform-fighting hybrid like Smash Bros. more practical.
IMO, there's an acceptable amount of flicker between "flicker-free" and "flicker from hell". There's a pirate Street fighter III for the NES with incredibly colorful characters that aren't particularly small, and the flickering is not very annoying IMO.
Here's a video of the game, but that's just so you know what game I'm talking about, because YouTube videos don't run at 60fps so you can't see how the flickering really is.
The
TMNT fighting game for the NES is another example of good sprite usage, but they aren't as colorful as in Street Fighter (each fighter uses a single palette here). This game even has parallax effects in the background too.
The characters in Shaq Fu (
video) are close to that size.
Yeah, that size is great, considering it's the NES we're talking about.
The street fighter game is worse than it could be because the movement is really choppy. With decent, smooth animation, the flickering would be even less noticeable.
Some fighting games with small characters that were quite playable that could be an example how it could look like -
Mortal Kombat fan port for ZX Spectrum,
King Of Fighters for Game Boy.
But then Game Boy has twice the relative sprite coverage: ten 8-pixel sprites across a 160-pixel-wide screen (50%), compared to eight 8-pixel sprites across a 256-pixel-wide screen (25%) for the NES.
Wow the MK on ZX was pretty neat. I have no idea really what that system was like but it seemed pretty cool.
Shiru wrote:
Wow, the animation in this is abysmal... you can literally see the bitmap refreshing...
Quote:
It always amazes me how bad the coloring is in these SD fighting games for the Game Boy Color and the Neo Geo Pocket Color. Skin is always white, outlines are always black, so there's only one color left to give the character any identity. For crying out loud, these platforms have the word "color" in their names, how is it acceptable that the characters look so monochromatic?
Still tweaking the handling, any feedback?
Yes you can jump forever going left or right in one direction, not worried about that right now.
The handling when you land or change directions while walking still feels a little slippery to me.
tokumaru wrote:
It always amazes me how bad the coloring is in these SD fighting games for the Game Boy Color and the Neo Geo Pocket Color. Skin is always white, outlines are always black, so there's only one color left to give the character any identity. For crying out loud, these platforms have the word "color" in their names, how is it acceptable that the characters look so monochromatic?
Maybe that's why it's called Color not Color
s.
Reminds me of the greyscale trick on the Ti-85/86
Use some RAM for a second 1 bit per pixel frame buffer, hook a timer interrupt to display one buffer for 1/3 of a second, the other buffer for 2/3 of a second, 4 shades of grey.
exdeath wrote:
Still tweaking the handling, any feedback?
Jump should not jump again until you let go of the button and press it again. Maybe make the height of the jump dependent on how long you hold the button.
MottZilla wrote:
tokumaru wrote:
It always amazes me how bad the coloring is in these SD fighting games for the Game Boy Color and the Neo Geo Pocket Color. Skin is always white, outlines are always black, so there's only one color left to give the character any identity. For crying out loud, these platforms have the word "color" in their names, how is it acceptable that the characters look so monochromatic?
Maybe that's why it's called Color not Color
s.
I always thought Gameboy color referred to the colored plastic cases since there are more Gameboy color variants than colors it can display on screen.
The monochrome Game Boy systems with color cases were called
"Play It Loud Series" if I remember correctly.
They do the black/skin/clothes thing because the solid black outline makes up for the slow LCD.
tepples wrote:
They do the black/skin/clothes thing because the solid black outline makes up for the slow LCD.
The Game Boy Color LCD wasn't nearly as slow/blurry as the one in the B/W versions. A lot of games didn't bother with black outlines and everyone could see the sprites just fine... even in other fighting games (Mortal Kombat 4 for example had really ugly sprites, but they had varied color schemes).
I seriously should hang around here more often.
exdeath wrote:
Damn, can't do Sonic the Hedgehog waterfall transparency effects thanks do the anti-dot crawl even-odd thing they do. Vertical lines actually show up as vertical lines... so NES > Genesis? Lol.
You can always pull off a Project MD and toggle between two opposite patterns every frame.
tokumaru wrote:
3gengames wrote:
But when you do use it's syntax, it works a lot better.
It shouldn't have its own syntax to begin with... 6502 assembly has a established syntax, and there's no reason to mess with it except to confuse programmers. I guess it's OK for assemblers to offer macros and other special features with differentiated syntax, but there's absolutely no reason to mess with the basic language.
Reminds me of how every 68000 assembler has its own flavor of the language making the code impossible to port unless you limit yourself to the basic features (meaning forget about using things like local labels).
tokumaru wrote:
Here's a video of the game, but that's just so you know what game I'm talking about, because YouTube videos don't run at 60fps so you can't see how the flickering really is.
Hah, I used to have this game on cartridge, that thing was so popular that a magazine over here even dedicated two pages to it with the full move list =P And yeah, there's quite some sprite overlaying so that adds to the flickering too. The flickering is horrible when a character is lying on the floor though (for obvious reasons), though at least it's just at feet level.
By the way, from where is that rock texture from those test ROMs?
Rock texture is from Mitsume ga Tooru.
It's one of the many games from this video
http://www.youtube.com/watch?v=ltuRuGM271Q that inspired me to mess around on NES and see what I could do.