It is currently Fri Sep 20, 2019 1:46 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: Ruby Runner motion test
PostPosted: Sun Apr 28, 2019 5:21 pm 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 161
One of my ambitions is to produce a successor to Boulderdash which features smooth motion, as seen on the Amiga game "Emerald Mine", rather than the tile-at-a-time motion seen on Boulderdash. Preliminary testing on the NES seems promising, though I'm not sure what sort of mapper would be best. This CNROM demo demo only features two kinds of objects: the PGMs (Placeholder Graphic Monsters) and the PRGs (Placeholder Rock Graphics), but can accommodates dozens of 16x16 or 16x24 moving objects without flicker.

While this could probably be built into an interesting game using CNROM, going beyond that would open up some possibilities. Perhaps the biggest limitation with CNROM is a limit of 64 metatiles. This demo alone uses sixteen for the PGMs, and seven for the PRGs, and some other kinds of monsters I'd like to include could need 24 or more. A mapper that could use one tile set for the upper-left corner of each metatile, one for the upper right, one fro the lower left, and one for the lower right, could increase the number of usable metatiles to 256.

Beyond allowing more tiles, such a mapper could also reduce the number of vblank intervals necessary to process each screen update, thus perhaps avoiding the need for overly complex logic to coordinate screen updates with game logic.

Does the idea of such a game appeal to anyone? What sort of mapper should I target?


Attachments:
File comment: Motion test/demo for Ruby Runner
rrTest.nes [160.02 KiB]
Downloaded 202 times
Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 5:43 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21595
Location: NE Indiana, USA (NTSC)
Would it play anything like Crystal Mines, Exodus, and Joshua? If so, those were made on the Color Dreams mapper (#11), which is similar to GNROM (#66). These dynamically convert objects between sprites and background.

Another way to allow more metatiles is to let different objects share individual tiles.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 5:59 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11412
Location: Rio de Janeiro - Brazil
Smooth scrolling is very commonplace on the NES, no need to overthink that aspect. 4-screen (name table RAM on the cartridge) is the easy way out for glitch-free scrolling, but you can also use horizontal mirroring and hide scroll artifacts by masking the sides of the screen (Alfred Chicken, Felix the Cat) or use vertical mirroring and blank some of the top and/or bottom of the screen (Jurassic Park, Big Nose Freaks Out), or just live with a little bit of scroll artifacts, like so many NES games do (even huge hits like SMB 3).

The tile limit on the other hand is not that simple to get around. The only mapper that really did anything to increase the tile count for the entire screen is the MMC5, which has a mode that allows access to 16384 tiles simultaneously through the use of an extra tile map that adds 6 more bits to each name table entry, for a total of 14 bits, and 2 bits for per-tile palette selection. More often than not, the MMC5 is overkill though.

If you're up for creating your own mapper, sure, you could use the name table fetch address to select a different CHR bank for each metatile quadrant, but then you'd run into all the drawbacks of issuing a custom mapper, such as having to hack emulators to support it and finding a way to mass produce it if you want to sell cartridges.

Do you really expect to use more than 256 unique ties for the background? A good artist can do wonders with that amount, and 256 tiles doesn't necessarily equals 64 metatiles... A good artist will often reuse the same tiles in multiple metatiles. If you need different graphics on the same level but not in the same screen, you can also use CHR-RAM and dynamically change patterns as necessary, or use a mapper like the MMC3 and switch patterns in 64-tile chunks.

BTW, I'm not on my PC so I wasn't able to check out your demo yet.


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 6:08 pm 
Offline
User avatar

Joined: Wed Sep 07, 2005 9:55 am
Posts: 368
Location: Phoenix, AZ
If you're interested, I have a custom mapper that is based on the FME-7, but supports the extended attributes of the MMC5 and is able to do the bank-per-tile idea you mentioned. I have it working on the PowerPak and in Mesen.

_________________
. That's just like, your opinion, man .


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 6:13 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8564
Location: Seattle
supercat wrote:
A mapper that could use one tile set for the upper-left corner of each metatile, one for the upper right, one fro the lower left, and one for the lower right, could increase the number of usable metatiles to 256.
While the needed hardware – latch nametable A0 and A5 lines and use those to choose banks – certainly is easy enough, nothing like that already exists. (The closest is Mapper 96, which instead latches A8 and A9. That said, why do you have seven different rocks? (If they're frames of animation, or a theme that changes from level to level, that's what multiple CHR banks are for.)

You may find Dwedit's demake of Chu Chu Rocket inspiring.

Quote:
What sort of mapper should I target?
Any mapper with an IRQ makes shaving off the bottom easy. Battletoads used extended blanking to shave off the top, on a very minimal mapper. But note that if you do use extended blanking, you more-or-less have to use OAMDMA - more than about 20 scanlines of blanking will result in DRAM starting to lose its contents, which will usually move on-screen.


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 9:22 pm 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 161
lidnariq wrote:
That said, why do you have seven different rocks? (If they're frames of animation, or a theme that changes from level to level, that's what multiple CHR banks are for.)


Stationary rock, rock falling out of tile, rock falling into tile, rock sliding left out of tile, rock sliding left into tile, rock sliding right out of tile, and rock sliding right into tile.

The sixteen PGMs are move up/right/down/left out of tile, move up/right/down/left into tile, spin clockwise starting up/right/down/left, and spin counterclockwise starting up/right/down/left.

Using this approach means that it's only necessary to update the name tables once every game tick, rather than once every animation frame.


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 10:01 pm 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 161
tokumaru wrote:
Smooth scrolling is very commonplace on the NES, no need to overthink that aspect. 4-screen (name table RAM on the cartridge) is the easy way out for glitch-free scrolling, but you can also use horizontal mirroring and hide scroll artifacts by masking the sides of the screen (Alfred Chicken, Felix the Cat) or use vertical mirroring and blank some of the top and/or bottom of the screen (Jurassic Park, Big Nose Freaks Out), or just live with a little bit of scroll artifacts, like so many NES games do (even huge hits like SMB 3).


My present plan is to mask the sides of the screen with sprites that could also be used to show score, time left, etc. The only movable sprites would likely be a pair of sprites for a 16x16 player character. Hopefully, setting OAMADDR to 248 and writing 13 bytes would work (setting OAMADDR might corrupt the first two and last two sprites, but rewriting the last two sprites and setting the first two to non-displayed locations should render such corruption irrelevant). The animation technique I'm using requires that name table updates all become effective on the same frame as the tile set switches, which on the NES necessitates double-buffering. Trying to do partial updates in four quadrants seems unworkably complicated.

Quote:
The tile limit on the other hand is not that simple to get around. The only mapper that really did anything to increase the tile count for the entire screen is the MMC5, which has a mode that allows access to 16384 tiles simultaneously through the use of an extra tile map that adds 6 more bits to each name table entry, for a total of 14 bits, and 2 bits for per-tile palette selection. More often than not, the MMC5 is overkill though.

If you're up for creating your own mapper, sure, you could use the name table fetch address to select a different CHR bank for each metatile quadrant, but then you'd run into all the drawbacks of issuing a custom mapper, such as having to hack emulators to support it and finding a way to mass produce it if you want to sell cartridges.


It seems weird that nobody made any provision for that, given how many games are based on metatiles.

Quote:
Do you really expect to use more than 256 unique ties for the background? A good artist can do wonders with that amount, and 256 tiles doesn't necessarily equals 64 metatiles... A good artist will often reuse the same tiles in multiple metatiles. If you need different graphics on the same level but not in the same screen, you can also use CHR-RAM and dynamically change patterns as necessary, or use a mapper like the MMC3 and switch patterns in 64-tile chunks.


Different tiles are needed for different state transitions. On the game tick where a PRG (placeholder rock graphic) starts falling, it will be replaced with a "rock leaving downward" tile at the same time as the tile below will be replaced with a "rock entering from above" tile; these changes will occur when the tile set switches so the former tile contains most of the rock. In the other three tile sets, the "rock leaving downward" will show decreasing amounts of the rock while "rock entering from above" will show more and more. If the space below the "rock entering" space is vacant, then on the next gametick, the "rock leaving downward" will be replaced with a blank tile, "rock entering from above" will be replaced with "rock leaving downward", and the tile below that will be replaced with "rock entering from above". All of this must be synchronzied with switching back to the first tile bank.

Quote:
BTW, I'm not on my PC so I wasn't able to check out your demo yet.


It's pretty sweet.


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 10:07 pm 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 161
lidnariq wrote:
You may find Dwedit's demake of Chu Chu Rocket inspiring.


Based on the text, that sounds like the effect I'm after, though I wasn't particularly planning on using sprites for anything other than the player and for side-wall masking. The screen-shot links seemed to be broken, though.


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 10:25 pm 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 161
tepples wrote:
Would it play anything like Crystal Mines, Exodus, and Joshua? If so, those were made on the Color Dreams mapper (#11), which is similar to GNROM (#66). These dynamically convert objects between sprites and background.

Another way to allow more metatiles is to let different objects share individual tiles.


Crystal Mines looks a lot like the effect I'm after, though I don't know whether that game would have flicker problems if more than four many objects became active at once on a scan line, or 32 became active in total. The approach I'd be using for Ruby Runner wouldn't be affected by such issues.


Top
 Profile  
 
PostPosted: Sun Apr 28, 2019 11:13 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11412
Location: Rio de Janeiro - Brazil
supercat wrote:
Quote:
BTW, I'm not on my PC so I wasn't able to check out your demo yet.


It's pretty sweet.

Pretty sweet indeed!

Now I see why scrolling might be a problem, you're using the two name tables to double buffer the background updates... Well, since you have nearly all sprites at your disposal for masking the sides of the screen, I guess you can easily create enough of room for the scrolling seam.

As for the tile count, well, I guess there's not much you can do about it other than use a custom mapper. Even the extended graphics mode of the MMC5 wouldn't be a good solution, since it only provides extra attributes for 1 name table, so you wouldn't be able to double buffer the background animations. On the other hand, AFAIK, the MMC5 does require its extended attributes to be updated *during* rendering which mean you wouldn't need to double buffer that part. It'd still be a lot more data to manage per frame though.


Top
 Profile  
 
PostPosted: Mon Apr 29, 2019 6:56 am 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 161
tokumaru wrote:
Pretty sweet indeed!


Thanks. Have you ever seen that many smoothly-animated objects on a scan line without flicker? Although the PGM designs are a bit meh, I really like the way they transition between motions except for the way they continuously spin when trapped. Adding another four metatiles for stationary up/right/down/left might help but I didn't think it was necessary for the demo.

Quote:
Now I see why scrolling might be a problem, you're using the two name tables to double buffer the background updates... Well, since you have nearly all sprites at your disposal for masking the sides of the screen, I guess you can easily create enough of room for the scrolling seam.


The way the NES handles horizontal scrolling would have been painful, even if a cart had 8K of nametable RAM usable as double-buffered four-way scrolling, handling the address discontinuity after a variable number of columns would require a lot of extra work. Simpler to reset the scrolling registers every game tick, and draw tiles in the right places to line up with the new scroll values, since all tiles are being redrawn every gametick anyhow.

Quote:
As for the tile count, well, I guess there's not much you can do about it other than use a custom mapper. Even the extended graphics mode of the MMC5 wouldn't be a good solution, since it only provides extra attributes for 1 name table, so you wouldn't be able to double buffer the background animations. On the other hand, AFAIK, the MMC5 does require its extended attributes to be updated *during* rendering which mean you wouldn't need to double buffer that part. It'd still be a lot more data to manage per frame though.


I think MMC2 and MMC4 could easily almost double the number tiles, by having each row start with either a "switch to set 0" or "switch to set 1" tile. Going from 64 tiles to ~120 would be a big improvement. Not sure if I'd find myself wanting more than 120 tiles, but I can easily see 64 as being inadequate.

What if any research has been done with regard to designing a "universal mapper" emulation VM? I think it should be practical to write a C module which would export only one external symbol and import none, using function pointers for all communication with the parent emulator. Using a bytecode-based VM for each memory fetch would add some overhead, of course, but if the VM builds converts the bytecode program into a table of structures that describe the different instructions therein, I think it should be possible to limit the performance impact while still keeping the bytecode program completely sandboxed.


Top
 Profile  
 
PostPosted: Mon Apr 29, 2019 12:14 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8564
Location: Seattle
supercat wrote:
What, if any, research has been done with regard to designing a "universal mapper" emulation VM?
I don't think it's a good idea.

A bundled HDL block, regardless of whether "HDL" is "bytecode" or "Verilog" or "netlist" and regardless of whether it's opaque or not, isn't actually for anyone. It's not for emulator authors, because it's too fragile ("bad descriptions", but you can add "wrong API in the original design" and "too much complexity to support and/or too much of a performance hit" ). It's not for any singular emulator author, because it's not going to be easier for them to write the implementation in this HDL than in whatever convenience abstractions they've already implemented in the emulator's native language. It's not for game developers, because the skill to write in HDL is extremely unrelated to developing a game, and also unrelated to every other skill they'll already have and probably ever would have. It's not for end users, who don't care. It's not for DRM, because it's too easily reverse-engineered.

Furthermore, there's nothing that actually constrains things to something that can actually be built. At best one ends up with overhead for no benefit, at worst one ends up with people designing hardware that can't see a hardware release, at which point it's not an NES game.

Partly due to the large number of already-defined mappers, the emulator author already has a big incentive to make new mapper hardware very easy to write, so it's not like writing these descriptions in C or whatever is hard. It's not even like build time would be meaningfully improved: these aren't large code bases.



And yet... at the same time, I have to admit it would be really cool to have something that was an NES emulator connected to some kind of digital logic simulator, to allow one to plug virtual random 74xx and 40xx and ROMs and RAMs in. But I'd also probably never actually use it beyond proofs-of-concept.


Top
 Profile  
 
PostPosted: Mon Apr 29, 2019 3:24 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7582
Location: Canada
Wow this looks really nice. Interesting set of constraints on how objects move... so any object can only move to a currently empty space, and they all must synchronize to the same 8-frame sequence to start their movements? 8 frames to update the double-buffered nametable, during which the visible one is animated only by 4 CHR flips at 30fps?

As far as the mapper suggestions I'd put MMC3 at the top of the list with it's 4 x 1k CHR banking and ubiquitous support. If you restrict yourself to a subset of MMC3 features it can be even more practical to build in hardware too.

Otherwise any mapper with 1k CHR banking would probably be suitable? VRC6, VRC7, FME7, etc.

On the multidirectional scrolling front, VRC6 or N163 with CHR-RAM might be viable as a way to double-buffer 4-screen nametables, since they can both map CHR to nametable. Not sure how well you'd find emulator support for this. Otherwise MMC3 + 4-screen is very well supported and would be suitable for scrolling on 1 axis only, I suppose?


Top
 Profile  
 
PostPosted: Mon Apr 29, 2019 5:20 pm 
Offline

Joined: Thu Apr 18, 2019 9:13 am
Posts: 161
lidnariq wrote:
supercat wrote:
What, if any, research has been done with regard to designing a "universal mapper" emulation VM?
I don't think it's a good idea./quote]

I think you perhaps misunderstood my intention. i wasn't intending circuit-level emulation, but rather a VM with an instruction set focused on bit manipulation and 2/4/8-way branching. Using ca65, once one includes a file that sets up some macros and labels, something like CNROM, but with RAM at 0x6000, would be something like:


Code:
.word INIT,CPUREAD, CPUWRITE, PPUREAD, PPUWRITE, ... also define labels for debug read/write, etc.
INIT:
    LOADCONST32(8, 0x22000) ; Load virtual register 8 with 0x28000-0x6000
    LOADCONST8(9, 15) ; Load virtual register 9 with 15
    EXIT
CPUREAD:  ; 8-way branch on bits 13-15 of addr
    BRANCH8(CPUADDR, 13, DONE,DONE,DONE, RDRAM, RDROM, RDROM, RDROM, RDROM)
RDRAM:
    ADD(7, CPUADDR, 8) ; Compute R7=R8+CPUADDR
    READMEM(CPUDATA,7) ; CPUData = mem[R7]
    EXIT
RDROM:
    READMEM(CPUDATA,CPUADDR)
    EXIT
DONE:
    EXIT
CPUWRITE:
    BRANCH8(CPUADDR, 13, DONE,DONE,DONE, WRRAM, WRROM, WRROM, WRROM, WRROM)
WRRAM:
    ADD(7, CPUADDR, 8) ; Compute R7=R8+CPUADDR
    WRITEMEM(CPUDATA,7) ; mem[R7] = CPUData
    EXIT
WRROM:
    READMEM(7, CPUADDR)  ; R7 = mem[CPUADDR]
    ANDREG(CPUDATA,CPUDATA,7) ; CPUDATA &= R7
    ANDREG(7,CPUDATA,9)  ; R7 = CPUDATA & R9
    SHL(6,7,13) ; R6 = R7 << 13
    EXIT
PPUREAD:
    BRSET(PPUADDR,12, DONE) ; Go to DONE if PPUADDR.12 is set
    ADDREG(7,CPUADR,6) ; R7=CPUADDR + R6
    READMEM(PPUDATA,7)  ; PPUDATA = Mem[R7]
    EXIT
PPUWRITE:
    EXIT

Not a hardware description, but rather a description of what an emulator would need to do.


Quote:
A bundled HDL block, regardless of whether "HDL" is "bytecode" or "Verilog" or "netlist" and regardless of whether it's opaque or not, isn't actually for anyone. It's not for emulator authors, because it's too fragile ("bad descriptions", but you can add "wrong API in the original design" and "too much complexity to support and/or too much of a performance hit" ). It's not for any singular emulator author, because it's not going to be easier for them to write the implementation in this HDL than in whatever convenience abstractions they've already implemented in the emulator's native language. It's not for game developers, because the skill to write in HDL is extremely unrelated to developing a game, and also unrelated to every other skill they'll already have and probably ever would have. It's not for end users, who don't care. It's not for DRM, because it's too easily reverse-engineered.


Processing could be pretty simple. More complicated than a typical *single* mapper, but not by a huge amount.

Quote:
Furthermore, there's nothing that actually constrains things to something that can actually be built. At best one ends up with overhead for no benefit, at worst one ends up with people designing hardware that can't see a hardware release, at which point it's not an NES game.


There is a huge range of mappers that can be constructed by making a few cuts and jumps and maybe a "dead-bug" chip to an existing boards, or by reprogramming CPLDs.

Quote:
Partly due to the large number of already-defined mappers, the emulator author already has a big incentive to make new mapper hardware very easy to write, so it's not like writing these descriptions in C or whatever is hard. It's not even like build time would be meaningfully improved: these aren't large code bases.


What about the time required by an emulator author to examine someone else's code for a mapper before releasing it to the public, to ensure that it doesn't contain any security weaknesses that would allow a maliciously-constructed ROM to take over the real-world host machine? Using a sandboxed VM, even maliciously-crafted bytecode running a maliciously-crafted ROM file would be powerless to actually do anything to the host machine beyond wasting a lot of CPU cycles.


Top
 Profile  
 
PostPosted: Mon Apr 29, 2019 8:11 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8564
Location: Seattle
supercat wrote:
I think you perhaps misunderstood my intention. i wasn't intending circuit-level emulation, but rather a VM with an instruction set focused on bit manipulation and 2/4/8-way branching.
No, I think I understood what you meant. It's still not for anyone. It's still a solution in search of a problem.

You've invented a novel language that has nothing in common with skills already needed to develop a game. It's like how the SNES has two CPUs with radically different mnemonics albeit similar ISAs, and that posed yet another barrier towards people writing games for the SNES.

In order to take advantage of your VM, a developer needs to learn a novel assembler-like language. The set of people who this benefits is the specific set of people who like machine code enough more than C that they'd rather learn another kind of assembly instead of figuring out any existing emulator code base, and want third parties to maintain an interface so that they can still develop new and novel mappers.

Note that most of the current "best-of-breed" emulators grew support for both GTROM and UNROM512 pretty quickly after they saw hardware release.

Quote:
Not a hardware description, but rather a description of what an emulator would need to do.
Arguably, that's even worse, because it's easier to build things that can't inexpensively exist in hardware.

Quote:
There is a huge range of mappers that can be constructed by making a few cuts and jumps and maybe a "dead-bug" chip to an existing boards, or by reprogramming CPLDs.
I'm not talking about what easily-implemented things it covers. I'm talking about what hard to implement things it permits.

There's this phenomenon that's been observed repeatedly: when the emulated hardware is easier to use than the actual hardware, people treat the emulated hardware as authoritative. And if it does't enforce what can be built, things get designed that can't be built.

Quote:
What about the time required by an emulator author to examine someone else's code for a mapper before releasing it to the public, to ensure that it doesn't contain any security weaknesses that would allow a maliciously-constructed ROM to take over the real-world host machine?
No historical mapper is complex enough to do that. Even MMC5, which I'd suggest is the most complex, is pretty easy to audit. And honestly, even as grotesque as I find the COOLGIRL sort-of-a-flashcart, its code is pretty easy to audit if you're already familiar with the FCEUX abstractions.

But as far as mappers that people actually use for development? Have you looked at any existing emulator's mapper implementations?

Here's several emulators' implementations of mapper 96, the closest analog to the one you're floating:
FCEUX
Nestopia (note that this implementation is pedantically wrong, but irrelevantly so)
Mesen

Modern emulator and flashcart implementations of GTROM and UNROM512 have problems stemming from the Flash used, which is not something that would be easily solved by your VM.

For the most part, once an emulator author has written mapper support for the core set of licensed games (about 80 mappers), they'll have written all the convenience functions which do this the right way in the first place, and a module that didn't use them would be at best suspicious.

Quote:
Using a sandboxed VM, even maliciously-crafted bytecode running a maliciously-crafted ROM file would be powerless to actually do anything to the host machine beyond wasting a lot of CPU cycles.
At best it wastes a lot of CPU cycles. At worst it also wastes a lot of CPU cycles and involves extra code complexity with its own attack surfaces to achieve something that's more easily solved in the emulator's native programming language.

By the way, here's FCEUX's implementation of CNROM with PRG RAM.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google [Bot] and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group