As people visiting the Newbie board may remember, I'm diving into an original NES project using MMC5 (possibly eventually getting a cartridge release on the Retro VGS game console). It's gonna be a Legend of Zelda clone with more story, I'm tentatively calling it "Blade Story".
So here it is, at what I consider the true beginning: title screen, and then being able to walk around a single overworld screen. Pretty early of course, but hey if anyone wants to try out my first attempt at programmer art mixed with programmer music and programmer gameplay, have at it
http://www.dreamzle.com/blade/bladestory_7_7.nesP.S. - Man this thing makes me miss the Gameboy Color's Z80 chip - just having a couple virtual 16-bit registers like BC, HL would be so nice, I can see why Nintendo thought using a 6502 would dissuade third-parties from programming it if they were used-to Z80.
In at least my coding style, the 6502's virtual 16-bit registers are $00-$01 and $02-$03. I reserve $00-$0F for local variables.
Zero page was supposed to make up for lack of registers.
When I loaded it FCEUX 2.2.2 with "new PPU" it didn't load anything right. It did look fine with "old PPU", but it may not be running properly in all emulators/hardware. Music is working fine, though.
If you're shooting for a physical release, do you have someone who can produce new mmc5 compatible boards? afaik nobody does that yet, and real mmc5 boards are not readily available.
From my tests it's working in FCEUx 2.2.2 (old PPU), PUnes, Nintendulator, and...one other emulator I forget the name of, Nestopia? It looks like the new FCEUx PPU isn't getting the extended attribute data, that's probably something to do with the fact that you can only write to the extended attribute table while the screen is being drawn (opposite of normal PPU stuff). It could be an incorrect assumption on either mine or the emulator writer's part about whether you can read the MMC5 interrupt flag that says if the screen is being drawn, without actually turning on the MMC5 scanline interrupt. I'll be adding a scanline effect soon (for a HUD at the top of the screen, possibly with its own BG palettes) so I'll be able to test that case out.
As for physical release, I'm not actually targeting the NES but assuming I get far enough along,
the Retro VGS. That's a game console that's going to be Kickstartered soon, it uses physical cartridges, and includes an FPGA that can be loaded up with whatever classic consoles they get cores for (or custom cores). It was mentioned in an interview they were going to license cores from Kevtris, and I know his NES core includes MMC5 support, so I'm hoping that's true.
So are you saying that you can't really do an NES release because the boards for an MMC5 haven't been made yet? Why haven't they been made yet?
Also for the title screen. Try going over to pixeljoint.com and see if anyone can do a nice title screen for a decent price.
Erockbrox wrote:
So are you saying that you can't really do an NES release because the boards for an MMC5 haven't been made yet? Why haven't they been made yet?
The MMC5 is a ludicrously complicated mapper, extending the NES awfully close to its intrinsic limits. It allows for direct addressing of up to 256 KiB of CHR with 8x8 attributes (using 14 bits for tile # and 2 bits for palette #), up to 8 separate sprite banks when using 8x16 sprites, two extra sound channels, an extra nametable, up to 64 KiB of PRG-RAM that can be banked almost anywhere, vertical (separate left-and-right sections) splits, a hardware multiplier, as well as "ordinary" things like a scanline IRQ.
It's possible to choose a subset of that and get new boards made, but cloning the full MMC5 is well into "real" FPGA territory, making it a fairly expensive endeavor. And the MMC5 had a small enough circulation that getting donor PCBs for any non-trivial number would be relatively hard, too.
On the other hand, it sounds like he's "only" (so far) using the MMC5 for its 8x8 attributes. We've
got a
few ideas for
ways to implement that without adding much hardware...
Yeah, MMC5 makes it hard if I ever want to test on an actual NES - I'd probably have to take apart a Castlevania 3 or Uncharted Waters or something and solder my own ROM chips in. I guess loopy has an early MMC5 core for the PowerPak cart, but as far as I can find it isn't complete.
But, since I was a kid I always heard great things about MMC5, and because I already had to learn to program the NES from scratch and used to program the Gameboy Color (which is quite similar to an NES with MMC5), I thought it'd be extra fun to also write my game for MMC5. Plus, skilled pixel artists are hard to find these days, so I wanted to make their job as easy as possible when I do get one. So the less limitations the better - one palette for char, no real char limit for backgrounds. And the musician can use all the main channels for music, and I'd still have two more MMC5 channels for sound effects.
Even if you can find a reliable source for MMC5 boards, the two more channels will not play on an unmodified NES.
An Analogue NT, though...
Dreamwriter wrote:
Yeah, MMC5 makes it hard if I ever want to test on an actual NES - I'd probably have to take apart a Castlevania 3 or Uncharted Waters or something and solder my own ROM chips in. I guess loopy has an early MMC5 core for the PowerPak cart, but as far as I can find it isn't complete.
I believe
Loopy's last MMC5 mapper is "complete" for NES. It's incomplete for Famicom. i.e. it has everything except the expansion sound.
If you're really interested in expansion sound, though, I'd maybe suggest the VRC6 instead? It's a very capable mapper, but the sound in particular is very straight-forward to use and versatile. It doesn't have some of MMC5's bells and whistles (e.g. multiplier, expanded attributes, etc.) but it's pretty beefy, and its expansion sound is better. It's also very fully implemented on the PowerPak and Everdrive.
Neat! It's cool so see other people making Zelda clones on the NES!
I gave the demo a try, and came across one notable issue--
When the player touches the top, and/or the right sides of the screen, this causes one of their sprites to offset by a single pixel. I can't say why this would be happening, though.
I *was* going to upload a screenshot, but Imgur is being a butt, today. (busy server)
Why not just use the attachment feature?
Yeah, I've seen the player breaking apart - thanks. I'm not going to allow the player to walk off the border anyways, I'm planning on doing the transition when the player touches the chars at the edge of the screen. That's the next thing I'm adding, support for special chars like that and a couple test screens to walk between. After that it's the HUD at the top and doing a palette swap between the HUD and the rest.
I don't want to be rude but I tried you demo and while the music was promising and felt very "nessish" I don't see in it's current state why you would require the MMC5 mapper. Are you over-engineering your project by any chance? I didn't follow any nes thread recently but I felt I had to comment on this one since I often over-engineered my project in the past so I tought I should comment on it ^-^;;;
Maybe you should try with a more common mapper then switch to MMC5 only if you requires it. Not many games really requires such level of mapper and I'm sure other people on nesdev will tell you the same thing.
Good luck on your project.
You're right that in its current state MMC5 is mostly being wasted (except for the random 8x8 tile palette entry here and there). But realize that everything you see and hear is eventually going to be replaced with professional quality art and music, what's there is my placeholder programmer art.
Also, I like the MMC5, it was fun to figure out its quirks and stuff. By now the engine and pipeline are already set up for multiple char banks and whatnot, and I've used the simple scanline counter (though not in the current demo)
Little update: I now have the player walking back and forth between two screens, each with their own tileset if needed (well, I mean tiles in a different bank, though the only real difference is in my extended atrribute table, so I could mix and match if I wanted). And I wrote a full BG collision system going on rather than just basing collisions on which visual tile is in a spot (it involves creating a map by overwriting the visual map with number-tiles representing the different collision types). I need to organize my screen loading code, though, I didn't do a good enough job making it generic for any screen when I first setup screen drawing.
Next up after the organization: a HUD at the top of the screen with its own palette set.
Got my HUD area at the top, with its own set of 4 BG palette entries being reloaded, for a total of 5 BG palettes total on the screen! It's got a little bit of corruption underneath due to trying to fix the scroll after disabling the PPU, but the palette reloading is all done in the Hblank area off the screen.
You can try it out here if you like:
http://www.dreamzle.com/blade/bladestory_7_23.nesYou can walk to the second screen if you go south, to return to the top screen you must walk north through the HUD around the same region, because I didn't draw the placeholder test maps taking a HUD into account.
I think next I'll do a simple animation of the character walking, and then give her a sword she can swing.
How come one of the first things you've implemented is a 5th palette for the HUD, but you don't even have background art that needs it yet? (Plenty of games are quite content to have a single "reserved" palette and work with only 3. I'm just curious why this feature became such a priority for you?)
Some suggestions:
1. Generally at least the top and bottom 8 lines of the picture aren't visible on NTSC (sometimes a few more). You might want to lower the top of your HUD by 8 or maybe 16 pixels to make sure it's visible?
2. You should also hide sprites until the HUD is finished rendering so that the player and other sprites go under it, instead of on top. If you need sprites on for a sprite-0 test, alternatively you could prevent sprites on the bottom 8 pixels of the HUD by placing 8 sprites there with high priority. (Any sprites above the bottom 8 pixels, you can just eliminate by checking their Y coordinate.)
3. During screen transitions your music gets paused noticeably. You should leave NMI running and play your music there, so that it interrupts the screen rebuild to keep the music in time.
4. Don't re-enable rendering immediately when you're done rebuilding the screen. Wait until the next NMI to write to $2001, so that you can set up the scroll correctly, or your first frame will be misaligned every time.
5. Collision should halt the player on each axis separately. If I'm touching a tree vertically, holding diagonally should still let me move horizontally. The lack of diagonal motion against a blocker has a rather frustrating feel.
6. Walking north from the southern screen, you can get stuck inside the rock.
7. Reset does not clear sprites, and the title screen does not render correctly afterward. (Are you properly blanking memory on reset, or relying on emulators that set it to zero?)
8. Consider a button press to advance the "once upon a time" screen. This is very tedious to wait through, especially when trying to test.
Some more that I noticed when trying out the ROM in NDX:
1) Don't use $0D for black, it can cause problems with some TVs.
2) Make sure to initialize your sprites before doing OAM DMA:
Attachment:
unitialized-sprites.png [ 34.64 KiB | Viewed 2274 times ]
Thanks for the great suggestions!
rainwarrior wrote:
How come one of the first things you've implemented is a 5th palette for the HUD, but you don't even have background art that needs it yet? (Plenty of games are quite content to have a single "reserved" palette and work with only 3. I'm just curious why this feature became such a priority for you?)
Well, I don't have any background art at all yet, really - I'm currently not planning on being the artist on this project, the art currently in the game is all programmer-art I created primarily for testing the engine. When I do get an artist, I want them to have as few limitations as possible, because these days great pixel-artists skilled at working with limited palettes are a rarity, so the more I can help them out from the start, the better. It's also one of the big reasons for using MMC5, being able to use as many tiles per map as the artist desires, and not having to worry about keeping palettes on 16x16 boundaries.
And if I do end up doing all the art myself, I *definitely* need all the help I can get - heck, I dedicated an entire palette to a rock!
Also, as an oldschool Gameboy programmer I love pushing systems to do more than they were really designed to do, it's a fun challenge. I had a lot of fun in this case figuring out the timing of getting the palette reloading with minimal corruption (now I just need to get rid of the scroll corruption on the bottom edge).
Dreamwriter wrote:
I had a lot of fun in this case figuring out the timing of getting the palette reloading with minimal corruption (now I just need to get rid of the scroll corruption on the bottom edge).
It's worth noting that this is the kind of thing you should test on real hardware. These fine timing details often vary a lot from one emulator to another, so it's better to calibrate them according to the real hardware.
That said, the mid-screen scroll change should be easier to get right than the palette change. Since you have rendering disabled for the palette update already, using the $2006/5/5/6 combo and enabling rendering near the start of the next HBlank should do the trick.
Walking on the status bar. Hi.
It looks to me like you room data is still full screen even though the HUD is covering it. Start designing the rooms shorter. And you might want to compress your data. This is just from loading room 1. Look at all those 01's. It will save alot of ROM space to compress this and load it somewhere in the RAM as collision info.
dougeff wrote:
And you might want to compress your data.
At least start using metatiles (which are a form of compression), because raw screens will use up all your ROM pretty quickly.
It's worse than you may think - each screen is composed of the basic nametable map, the extended attributes map, and a collision map, all three the size of the full screen (though soon minus the size of the HUD). Plus the 4 palettes. Don't worry, I plan on eventually implementing compression, probably PUcrunch to be specific. I just want to finalize the BG creation pipeline first (I thought I had, but it's kind-of a pain).
After each new feature I go in and solidify and clean up the code, this time I also implemented many of your suggestions too so I posted the new build if anyone's interested:
http://www.dreamzle.com/blade/bladestory_7_24.nes
New art style - looks less RPG and more Zelda. Maybe a bit too much Zelda...
Attachment:
bladestory.png [ 3.73 KiB | Viewed 2089 times ]
love the "programmer art"
It kind of reminds me of Microsoft Paint art.
I'm having problems setting the scroll values mid-scanline, can someone tell me what I'm doing wrong? It works fine if SCROLL_X and SCROLL_Y are #0, but anything else and I get weird results (for example, after a certain point SCROLL_X scrolls in both X and Y). I'm trying to do the $2006, $2005, $2005, $2006 trick.
Code:
; Set scroll, adding current scanline
lda PPUSTATUS ; reset scroll status
; In-scanline scroll = PPUADDR,PPUSCROLL,PPUSCROLL,PPUADDR
; ((Y & %11000000) >> 6) | ((Y & %00000011) << 4) | (N << 2)
; Simplified to just (N << 2)
lda #%00000100
sta PPUADDR
; X
lda SCROLL_X
sta PPUSCROLL
; Y
lda SCROLL_Y
adc #32 ; Add current scanline+1 to scroll
sta PPUSCROLL
; ((X & %11111000) >> 3) | ((Y & %00111000) << 2)
; Compute munged Y
and #%00111000
asl
asl
sta HBLANK_TEMP ; Store munged Y in Temp
lda SCROLL_X
lsr
lsr
lsr
ora HBLANK_TEMP ; Or munged X with munged Y
sta PPUADDR
I understand it's not optimized as it can be (and I'm eventually going to move the scroll-pos munging out of there, since this code is in the middle of scanline drawing), I'm just trying to get it to work first.
The order you write to PPUSCROLL is backwards from what you intend. (here it's Y first, then X.) Also, there will be visible corruption on-screen between the 3rd and 4th writes if you change fine X.
If you don't change fine X, consider the faster PPUADDR-only method.
Thanks a lot, just swapping the X and Y in PPUSCROLL worked like a charm. I'll get you next time, PPU!
Here's the demo if anyone's interested, scrolling with HUD (with its own HUD palette):
http://www.dreamzle.com/blade/scroll_demo.nes
Is there some reason you're trying to find the hardest way to do everything? Zelda didn't need MMC5 or use complicated scrolling tricks. Learning how to use them is cool and all, but it can also be a form of procrastination. One way artists spark creativity is to force some kind of limitation... Today I'm only going to use blues. Embrace the limitations, say to yourself, "I can make it work with only 4 palettes for background"
"Procrastination" because you spend all your time solving technical problems rather than programming your game.
Actually, The Legend of Zelda did use complicated scrolling tricks, to put their own HUD at the top of the screen - if you want a HUD at the top that doesn't scroll, but your game uses vertical scrolling, you have to. Zelda used sprite-0 collision instead of the MMC5 scanline IRQ, but in the end the technique is basically the same.
And as I've mentioned before, I am not going to be the artist on this, and I can't guarantee that the artist will be amazing at limited-color and limited-tile pixel art, so I'm trying to make their job as easy as possible. And why wouldn't I, when I'm doing this in my spare time? I have no deadlines, and at worst I end up with a good general reusable MMC5 game engine with some nice special tricks.
OK, you're right about zelda. My memory is shitty.
Darn, I just ran into a technical limitation I hadn't realized: just how little time there is per vblank on NES. Only being able to update a couple rows of chars per frame while still updating other things like sprites throws my 4-row HUD under a bus if I want vertical scrolling, since I'd have to update all 4 rows plus the actual scroll-reveal row every scroll update. I can't get around it by keeping the HUD on another nametable, because when using MMC5 extended mode all nametables share the same extended palette/char table.
The only solution I can think of that doesn't involve dropping extended mode or the BG HUD is to use the MMC5 vertical split for a side HUD, but that would be insane (and I'd lose my extra HUD palette). That or turn the HUD off during scrolls, which seems rather janky (admittedly, with the Zelda-style scrolling I had planned on it's not as bad, but still janky).
Dreamwriter wrote:
I can't get around it by keeping the HUD on another nametable, because when using MMC5 extended mode all nametables share the same extended palette/char table.
Can't you turn off the extended nametable behavior for just the HUD?
Most of the NES games I've seen, with free bidirectional scrolling, either use a sprite health bar, or no HUD.
Though, it is an interesting puzzle. Can it be done? And, can it be done without lots of attribute glitches.
Edited.
Lots of games have glitch free status bars combined with bidirectional scrolling. Some of them use name table layout tricks, but since you seem to be stuck with a single name table (unless it's indeed possible to disable extended attributes for part of the screen, and you're OK with that) I think that the solution that would work best in your case is the solution used in Crystalis: simply use mapper IRQs to skip the hud during the rendering of the playfield, and always keep it in the same place. Look at a name table viewer while playing some Crystalis and you'll see how it works.
Check how ROM City Rampage did it, perhaps? Of course, you'll have to rip it out of Retro City Rampage. But it's an MMC5 game with extended attributes, a HUD and multdirectional scrolling. (Though it doesn't try to use extra palette for the HUD, so if that's part of the problem this is a bad suggestion.)
1.70 MB gif of what ROM City Rampage's HUD/Nametable updating looks like:
http://i.imgur.com/pP6VDps.gif
Crystalis is a great example, but it does have those attribute table glitches I mentioned. And a nice big line of a glitch, right at the split screen.
Kasumi wrote:
1.70 MB gif of what ROM City Rampage's HUD/Nametable updating looks like:
http://i.imgur.com/pP6VDps.gifLooks like the Crystalis trick to me. If you pause, you can see that whatever is right above and right below the status bar in the name table connect directly in the final render. Also notice that there's a blank row above the status bar in the final render, so that the gameplay window can scroll smoothly without glitches.
dougeff wrote:
Crystalis is a great example, but it does have those attribute table glitches I mentioned. And a nice big line of a glitch, right at the split screen.
Yeah, lots of commercial games were glitchy. The technique is perfectly valid, though, you just have to time it right.
I think I see, don't just use the scanline IRQ once for the HUD at the top of the screen, but also a second and third time to adjust hardware scrolling to show the lines above the HUD as if they were directly connected to lines below the HUD. Tricksy hobbitses! Sounds like a plan...
Disabling extended attributes while rendering a HUD on a second nametable is something I considered trying and might actually work (the HUD is all on char bank 0 and only using one palette), but pushing MMC5 that way is a dangerous thing to do when I don't actually have access to the hardware I'm developing for yet, to test how that MMC5 implementation handles it. The way I'm testing now I've got four emulators, and if what I'm doing doesn't look mostly the same on all four, then chances are I'm doing something wrong or dangerous even if one of the four is doing exactly what I want. As long as I'm not doing anything tricky/out of the ordinary for MMC5 I should be fine with this testing method, worst case is I might need to tweak timing a bit once I can get the game on hardware.
tokumaru wrote:
dougeff wrote:
Crystalis is a great example, but it does have those attribute table glitches I mentioned. And a nice big line of a glitch, right at the split screen.
Yeah, lots of commercial games were glitchy. The technique is perfectly valid, though, you just have to time it right.
Some of the glitchiness of Crystalis might have something to do with the fact that it uses DPCM samples.
Re: glitchy
I'm not trying to complain about Crystalis or its technique. I'd love to see more games like this. My point is, don't expect it to look as nice as an SNES (or later) game.
It doesn't have to look like a SNES game to be glitch free. It is perfectly possible to have a status bar and multidirectional scrolling on the NES without glitches, but you have to spend some calibrating the timing to make sure it's solid, and professional developers back in the day had deadlines that prevented them from spending time fixing things like these.
Any thought to your sound engine? Will you be sticking with the plain 2a0x for audio or will you be using MMC5 pulses too?
Right now I'm using Famitone to play back Famitracker music. I was planning on using the additional mmc5 voices, possibly for sound effects allowing me to use the full NES sound system for music.