I didn't know that was attested. (The name of the game it appears in reminds me of Freudian psychology.)lidnariq wrote:By the way, here's FCEUX's implementation of CNROM with PRG RAM.
Ruby Runner motion test
Moderator: Moderators
Re: Ruby Runner motion test
Re: Ruby Runner motion test
At present, developers are effectively limited to mappers that include the specific combinations of attributes that people in the past have needed for their games. Need the ability to switch tile sets on certain rows? MMC2 and MMC4 can do that by using "shift" tiles. Need scan-line IRQ supprt? MMC3 supports that. Need both? Sorry.lidnariq wrote:No, I think I understood what you meant. It's still not for anyone. It's still a solution in search of a problem.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.
The NES has always supported a "language" beyond 6502 assembly language: the language of electrons. Wire in a circuit to do what you want, and it will do what you want. Something like 74hc74 and an RC timing bodge (to delay A12 relative A0 and A5) could be used to do a two-way or four-way tile split easily. Something like a 74hc253 could be used to add IRQ support for a single split-screen in a side-scroller.
Many numbered mappers represent a number of related circuits, but there can sometimes be confusion as to what all of the parameters are supposed to mean. What I would envision as a typical process would be for a developer to visit a web page for a general family of mappers, specify a number of options, and receive from that some combination (depending upon the web page) of the following:
1. A schematic for a precise circuit (i.e. a boilerplate schematic with a few customization points filled in).
2. A fab-ready board layout for the exact circuit (a boilerplate layout with filled-in gaps for customization)
3. One or more JEDEC file(s) for various CPLD-based carts like INL-ROM.
4. A bytecode source file for the cart description.
5. A bytecode binary file that could be given to an emulator.
The first three parts could be done on a web page fairly straightforwardly using a little Javascript, but they wouldn't be any good for anyone wanting to emulate the game. Further, if any new options get added to the recipe (e.g. wire VRAM A10 to one of the CHR-bank-select bits), that would complicate emulation because it would be unclear whether there should be a new mapper number, or simply another parameter setting for an existing one.
[quote[]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.[/quote]
The only people I'd expect to be writing mapper code directly would be hardware designers, who could either release mapper code for specific configurations, or have a customization page that could generate mapper code customized for the exact hardware options selected.
I would expect that most developers would use pre-existing mapper code or a use tool to customize a mapper for their particular needs. On something like an INL-ROM cart, a more expensive CPLD would be needed to support e.g. MMC3 than to support a mapper that was designed to include a set of features tailored to a specific game. I would guess that InfiniteNesLives could probably make a variation of the INL-ROM board which was just like the original, but with a simpler CPLD and save a couple bucks in parts cost.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.
Actually, that could be used as a form of DRM for people who want to allow people to download their games for use on emulators, but don't want people making carts of them. Release a version of the game binary that targets impractical hardware, and sell a cartridge version that uses practical hardware in a copy-protected CPLD. Reverse-engineering CPLDs is non-trivial if they have a few seemingly-spare resources and aren't meant to be duplicated. One may have a game that seems to work, except that on pirate carts the second level boss is unkillable because the real cart does something "interesting" that the pirate carts don't.Arguably, that's even worse, because it's easier to build things that can't inexpensively exist in hardware.Not a hardware description, but rather a description of what an emulator would need to do.
Someone could make an emulator-only game, but I'm not sure why they'd target a system with the color and sprite limitations of the NES if they weren't intending to make a cart of it. And someone who does want to make a cart of a game but doesn't understand hardware should stick to a hardware description made using a board vendor's tools.I'm not talking about what easily-implemented things it covers. I'm talking about what hard to implement things it permits.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.
Such problems most often arise in cases where emulated hardware can be described simply, but real hardware's behavior deviates from those descriptions (e.g. OAM-RAM corruption issues). I don't see that as being so much of an issue if one visits a web page for a board that has a bunch of customization points, picks some options, and receives a mapper emulation file.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.
More to the point, with the exception of speed issues, there isn't really much one could specify in a VM that couldn't be done in real hardware. There are many things that couldn't be produced for a price many people would want to pay, but it's not the emulator writer's job to pass such judgments.
Such auditing needs to be done separately by the maintainers of every emulator. And looking through the code you linked, I wouldn't say auditing seems particularly easy since it's often not at all clear who's responsible for ensuring that what things are in bounds. I haven't found any actual security holes, but I did find a lot of places that violate the "single source of truth" principle. For example, code which allocates memory for the requested RAM sizes, and then uses a switch statement to set up pointers to 8K blocks of it, but doesn't directly validate accesses to ensure that they're valid. There may be no security holes in the code as written, but the design is brittle, and if someone who doesn't understand it perfectly tries to tweak it to implement a slightly-different banking scheme, that could easily result in subtle security weaknesses if a malicious ROM causes the mapper to allocate less memory than it's going to try to use.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.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?
Running all accesses to run-time-computed addresses through centralized validating load/store routines (whether in a VM or simply as a coding practice) imposes a minimal run-time cost on modern hardware (since the code to perform such validation will be used enough to stay in cache), but makes it much easier to guard against malicious ROMs.
I didn't notice the "convenience functions" using any consistent strategy to ensure that they wouldn't overrun their memory allocations if e.g. code on a cartridge that supports different addressing modes sets parameters which would be valid for the current modes, but then switches to a mode where those parameters aren't valid. Such mistakes could happen in bytecode as well as in C code, but if they happen in bytecode the interpreter would catch them and signal them an error, without allowing the code to take over the real-world machine.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
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.
What fraction of an emulator's time is spent on mapper emulation, as opposed to all the other things the emulator has to do? I would expect that a moderately-optimized VM would involve one iteration of a loop likeAt 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.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.
Code: Select all
vmProc = vmState->cpuReadProc;
stepLimit = 10000;
do
{
vmProc = (*vmProc)(vmProc, vmState);
} while(vmProc && --stepLimit);
That's not the actual byte-handling logic, but merely code that sets up some tables for use by the byte-handling logic; it should hardly be surprising that a cart which doesn't really do much beyond basic read/write should be handled using the "handle common case" code.By the way, here's FCEUX's implementation of CNROM with PRG RAM.
If you don't like the idea of having a common machine-readable means of describing mappers in a way that emulators can process them, how would you suggest getting around the chicken-and-egg problems of people not wanting to use improved hardware techniques for fear of support, and emulator writers not wanting to support mappers that nobody will ever use? Bundling mapper byte code with an NES file would mean that if one's emulator can process mapper byte code, it will be able to play the NES file regardless of whether the author of the emulator ever heard about the mapper that it's using.
Re: Ruby Runner motion test
For what it's worth, I'm really digging supercat's idea for custom mapper support in emulators. I've always wanted something like that. It'll be hard to convince people to do things differently, though...
Re: Ruby Runner motion test
I'll ask the harder question (to everyone): is this really worth doing on the NES (or any preexisting classic console of said era)? Don't hastily reply: step away from the keyboard for a day and really think long and hard about it.
Re: Ruby Runner motion test
Actually, the JY Company mapper (#209) gives you both.supercat wrote:At present, developers are effectively limited to mappers that include the specific combinations of attributes that people in the past have needed for their games. Need the ability to switch tile sets on certain rows? MMC2 and MMC4 can do that by using "shift" tiles. Need scan-line IRQ supprt? MMC3 supports that. Need both? Sorry.
...did you mean some other part number? That's limited to choosing to generate an IRQ based on five inputs (A, B, 1G, 1Cn, 2Cn) ... I assume you meant to type the same '688 you mentioned last time.supercat wrote:Something like a 74hc253 could be used to add IRQ support for a single split-screen in a side-scroller.
And your VM doesn't particularly resemble such language of electrons. Writing things for the language you've specified doesn't resemble "oh, I put a latch here clocked by that thing and the output enable tied to this other thing", but instead implies sequentiality.The NES has always supported a "language" beyond 6502 assembly language: the language of electrons.
Which I'm supposed to accept is somehow better than a build of an emulator that supports the mapper directly...? Because emulator choice or something? Nevermind that the bytecode is an opaque box and if the result doesn't do what you think it should, you have to be familiar with the bytecode language and maybe your emulator has a VM debugger so that you can figure out what's going wrong... which gets back to the same starting point: you're arguing that the bytecode is somehow easier to understand than the language the emulator is already written in.5. A bytecode binary file that could be given to an emulator.
You are dramatically overestimating the complexity of adding emulator support in the emulators' native language. Even a bunch of times.The only people I'd expect to be writing mapper code directly would be hardware designers, who could either release mapper code for specific configurations, or have a customization page that could generate mapper code customized for the exact hardware options selected.
DRM is an antifeature in my book, and any argument that presupposes it being a good thing is going to face extra scrutiny. DRM is nothing more, and nothing less, than a way to take things that could be permanent and make them transient and irrecoverable, excused as a way to make a buck (regardless of whether it actually does) at the cost of all future people forever after.Actually, that could be used as a form of DRM
But even if it weren't: the VM bytecode would be too dense and easily-reverse-engineered of a target to be useful DRM.
Because they either don't know, or don't care. People who write music for NSF, because it was defined to support all the different famicom expansion audio at the same time don't care that using multiple expansions at the same time is unrealistic. NSF supports it.Someone could make an emulator-only game, but I'm not sure why they'd target a system with the color and sprite limitations of the NES if they weren't intending to make a cart of it.
People wrote ROM hacks and/or translations that targeted oversize MMC3 before all-new-parts reproductions were available. They didn't know that that wasn't something they could get. Sometimes they didn't understand or didn't care (e.g. the patch that removed this size enforcement from Nintendulator's source)
So, I'm supposed to accept that vendor lock-in is a good thing?And someone who does want to make a cart of a game but doesn't understand hardware should stick to a hardware description made using a board vendor's tools.
That is exactly what I'm saying is.There are many things that couldn't be produced for a price many people would want to pay, but it's not the emulator writer's job to pass such judgments.
If it can't ever have been affordably reproduced, it isn't an NES game. This isn't some arbitrary definition, this is actually the only thing that's internally consistent.
And every maintainer will have already written the relevant abstractions in support.Such auditing needs to be done separately by the maintainers of every emulator.
That's the entire point of the abstractions. Use the abstractions, can't get an out-of-bounds access. Don't use the abstractions, and your code is suspect and should be treated with extreme prejudice.And looking through the code you linked, I wouldn't say auditing seems particularly easy since it's often not at all clear who's responsible for ensuring that what things are in bounds.
You don't get to disregard the safety of their preexisting abstractions when you're presenting an argument in favor of your own abstraction.
... did you look at the same code I did?I didn't notice the "convenience functions" using any consistent strategy to ensure that they wouldn't overrun their memory allocations if e.g. code on a cartridge that supports different addressing modes sets parameters which would be valid for the current modes, but then switches to a mode where those parameters aren't valid.
what do you think FCEUX's setprg and setchr, and Nestopia's SwapBank, and Mesen's SelectXxxPage functions do?
why would you even think that they would be vulnerable?
why would you even think that's something that should be handled at this level, instead of inside the abstraction?
(it turns out that a bunch of games already rely on the upper bits being discarded)
My argument is:Such mistakes could happen in bytecode as well as in C code, but if they happen in bytecode the interpreter would catch them and signal them an error, without allowing the code to take over the real-world machine.
A VM to emulate this is
1- fragile
2- slow
3- easy to have subtly wrong "safe" surfaces
4- easy to expose attack surfaces
5- everyone's implementation will be subtly different
In contrast, your argument is that all C ever is forever unsafe. That's not a good argument.
In practice, audio emulation seems to be the heaviest, because resampling or band-limited synthesis. Optionally, postprocessing like the NTSC filter or shaders. After that, all that's basically left is the CPU and PPU emulation, and you'll have the mapper overhead on every single cycle of each... possibly dozens of cycles of VM bytecode.What fraction of an emulator's time is spent on mapper emulation, as opposed to all the other things the emulator has to do?
That's my entire point. You gave a VM machine code implementation of CNROM with PRG RAM, I pointed out that the abstraction already handles that tidily.it should hardly be surprising that a cart which doesn't really do much beyond basic read/write should be handled using the "handle common case" code.
I'll assume you want to talk about mapper 96 or MMC4 instead: the native FCEUX abstraction is still cleaner and easier to understand than the corresponding VM source would be. Cleaner, faster, not any more vulnerable.
By involving someone who can make the hardware in the first place and making sure that what they want can actually be done. Conveniently, at that time, they'll already have a manufacturer lined up.how would you suggest getting around the chicken-and-egg problems of people not wanting to use improved hardware techniques for fear of support, and emulator writers not wanting to support mappers that nobody will ever use?
(this was my 8288th post, the bus controller (permitting multiple masters, e.g. DMA or FPU) in the original IBM PC)
Re: Ruby Runner motion test
In all earnestness, what's keeping you from playing around in the source to existing emulators?tokumaru wrote:For what it's worth, I'm really digging supercat's idea for custom mapper support in emulators. I've always wanted something like that. It'll be hard to convince people to do things differently, though...
Re: Ruby Runner motion test
Although I am a programmer, I have little experience with modifying other people's code (I feel very insecure about making modifications to things I don't have a complete understanding of) and compiling desktop applications (I'm more of a script and web guy). But even if I was used to doing those things, it sounds counterproductive to code the same functionality for several different emulators, each using a different architecture for handling mappers, and having to re-apply those changes every time a new version of each emulator comes out, possibly having to deal with architectural changes.
IMO, implementing a mapper in a single language, only once, certainly beats having to constantly fiddle with several different code bases. And there's also the distribution issue: other people won't be able to play my custom mapper games with their preferred setups, they'll have to use the modified emulators I supply (if their licences allow it), and that may not even include their favorite emulators or operating systems. It's a hassle not only for the programmers but also for their audience.
It is possible that your new mapper is eventually Incorporated in the official versions of well maintained emulators, but it just sounds so much better to have this process completely automated, you know?
IMO, implementing a mapper in a single language, only once, certainly beats having to constantly fiddle with several different code bases. And there's also the distribution issue: other people won't be able to play my custom mapper games with their preferred setups, they'll have to use the modified emulators I supply (if their licences allow it), and that may not even include their favorite emulators or operating systems. It's a hassle not only for the programmers but also for their audience.
It is possible that your new mapper is eventually Incorporated in the official versions of well maintained emulators, but it just sounds so much better to have this process completely automated, you know?
Last edited by tokumaru on Wed May 01, 2019 5:15 pm, edited 1 time in total.
Re: Ruby Runner motion test
As for the NES, not much other than that I don't see how to build a .NET application (Mesen) or Win32 application (FCEUX debugging version) under Linux.lidnariq wrote:In all earnestness, what's keeping you from playing around in the source to existing emulators?
As for the Game Boy, half of SameBoy's debugging features are Mac-only, and bgb is closed source. But then it wouldn't need mappers as much anyway because of its built-in timers and 1-screen mirroring, except perhaps for a multicart.
Re: Ruby Runner motion test
The main arguments I see against it are essentially:
A) The odds of any significant amount of emulators gaining support for such a concept at this point in time is low, people will keep using nestopia, fceux, and others for a variety of reasons for a very long time. Unless whoever designed such a system decides to implement it themselves in multiple emulators, adoption will remain low.
B) Mapper logic can actually become a large part of CPU usage (e.g MMC5), especially for everything that watches the VRAM bus and reacts to it. This means the behavior either needs to a) be very roughly approximated for the purpose of super fast emulators (e.g QuickNES) or implemented with cycle accuracy with as much optimization as possible for cycle accurate emulators. Having a "VM" in the way here could potentially greatly affect speed-focused emulators, and would likely slow down accuracy-focused emulators some more. Personally if I'm going to make Mesen any slower, I'd rather use the extra CPU time to improve accuracy rather than implement a highly customizable "build-your-own-mapper" system :p
In the end you're designing a potentially complex system, that will have its own bugs in different emulators and which will very likely reduce performance. The benefit is that a handful of people may create their own mappers for it and presumably be able to run it on all emulators (but that's unlikely to happen because the majority of popular NES emulators are barely maintained these days). Not to mention that unless someone goes and correctly reimplements all 350+ existing NES/Famicom mappers using that new system, emulators will still have to implement regular mappers, on top of this new system.
A) The odds of any significant amount of emulators gaining support for such a concept at this point in time is low, people will keep using nestopia, fceux, and others for a variety of reasons for a very long time. Unless whoever designed such a system decides to implement it themselves in multiple emulators, adoption will remain low.
B) Mapper logic can actually become a large part of CPU usage (e.g MMC5), especially for everything that watches the VRAM bus and reacts to it. This means the behavior either needs to a) be very roughly approximated for the purpose of super fast emulators (e.g QuickNES) or implemented with cycle accuracy with as much optimization as possible for cycle accurate emulators. Having a "VM" in the way here could potentially greatly affect speed-focused emulators, and would likely slow down accuracy-focused emulators some more. Personally if I'm going to make Mesen any slower, I'd rather use the extra CPU time to improve accuracy rather than implement a highly customizable "build-your-own-mapper" system :p
In the end you're designing a potentially complex system, that will have its own bugs in different emulators and which will very likely reduce performance. The benefit is that a handful of people may create their own mappers for it and presumably be able to run it on all emulators (but that's unlikely to happen because the majority of popular NES emulators are barely maintained these days). Not to mention that unless someone goes and correctly reimplements all 350+ existing NES/Famicom mappers using that new system, emulators will still have to implement regular mappers, on top of this new system.
All it takes is literally 2 packages (mono-devel & SDL2) and running "make" in the project's root folder :ptepples wrote:not much other than that I don't see how to build a .NET application (Mesen)
Re: Ruby Runner motion test
Yeah, I expect this to remain a dream, at least for now. It would be great to have emulators that behave just like an actual console, which can take any mapper and just work, because the mapper is entirely inside the cartridge. Bundling the mapper definition along with the ROM itself would mimic that perfectly, it'd be awesome. But it will take more than a handful of developers wanting to combine a few features from different mappers to make that happen. If this doesn't bring any sensible benefits for the masses, the chances of adoption are pretty low.
Even if you, as a game programmer, create your own emulator and games using a dynamic mapper system, other emulators authors are more likely to just implement hardcoded versions of your mappers (if your games are popular enough) than change how their emulators work. People have been doing emulation the same way for decades now, and while a few people are experimenting with different approaches (e.g. MetroBoy), most are perfectly OK with how things are.
Even if you, as a game programmer, create your own emulator and games using a dynamic mapper system, other emulators authors are more likely to just implement hardcoded versions of your mappers (if your games are popular enough) than change how their emulators work. People have been doing emulation the same way for decades now, and while a few people are experimenting with different approaches (e.g. MetroBoy), most are perfectly OK with how things are.
- rainwarrior
- Posts: 8734
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Ruby Runner motion test
My honest opinion is that the sense of scale in this comparison is very disproportionate.tokumaru wrote:IMO, implementing a mapper in a single language, only once, certainly beats having to constantly fiddle with several different code bases. And there's also the distribution issue: other people won't be able to play my custom mapper games with their preferred setups, they'll have to use the modified emulators I supply (if their licences allow it), and that may not even include their favorite emulators or operating systems. It's a hassle not only for the programmers but also for their audience.
Most NES mappers are a very small amount of code to support. On the order of a few hours or maybe even just minutes to actually write (especially if doing several at once).
Building a verilog simulator or whatever this universal mapper thing has to be, on the other hand, is probably about as complex as writing a whole emulator, in my estimation. Probably weeks of work, plus ongoing maintenance hunting down all the loose ends and bugs that come with an undertaking of this magnitude.
The maintenance work alone will completely overshadow the entire amount of work it would be to just implement the mappers natively like we've always had to do. I guarantee this. You can't just snap your fingers and come up with a system that will be able to handle any mapper you'd ever want to implement, with a spec and implementation that's robust enough to last forever. This is kind of like writing a whole second emulator for your emulator to use, for twice as much work and probably a lot worse performance, with additional collateral learning of some extra domain specific language for anyone who wants to implement a mapper. Not to mention how much of a barrier this is to anyone who wants to implement it from scratch.
My ballpark guess would be that you could write a traditional implementation of every extant NES mapper in a lot less time than it would take to get this dream system working. I could be wrong, but that's my honest estimate.
Re: Ruby Runner motion test
Yeah, I totally get that. I'm just pointing out that the current, "easy" way of creating new mappers (modify an emulator yourself, try to get actively developed emulators to support it) has its flaws, and that automating mapper support would be a great way to address those flaws, for good. I do get how hard this would be to implement, and that there would be performance implications.
Re: Ruby Runner motion test
I appreciate the responses about mapping emulation, and would like to continue them soon in on another thread on the emulation forum, but my main purpose in asking whether any research had been done was to avoid duplicating any existing efforts in sketching out a proposal. My goal isn't to recreate Verilog, but rather a DSL that is geared specifically toward the emulation of mappers. Verilog needs to deal with a large number of individual signals and timing relationships among them. Mappers generally have a small number of groups of signals which may be more sensibly treated as groups within 32-bit integers, and since the "virtual world" is stopped while a mapper is running, a sequential execution model will suffice.
It sounds as though the real-world mapper that's available and would be closest to what I want would be MMC2/MMC4 (either would probably work equally well). Those would get me up to 128 metatiles, but would leave a "load seam" across the top or bottom of the screen on PAL systems, and would also be more complicated (and thus more expensive) than should be necessary for the game. If I were designing a cart to optimally run the game as cheaply as possible without compromising gameplay, using back-in-the-day hardware, it would include:
It sounds as though the real-world mapper that's available and would be closest to what I want would be MMC2/MMC4 (either would probably work equally well). Those would get me up to 128 metatiles, but would leave a "load seam" across the top or bottom of the screen on PAL systems, and would also be more complicated (and thus more expensive) than should be necessary for the game. If I were designing a cart to optimally run the game as cheaply as possible without compromising gameplay, using back-in-the-day hardware, it would include:
- 64K or 128K of PRG-ROM, banked as a unit
- 2K or 8K of PRG-RAM
- A 2-bit register that would capture A0 and A5 and use those to select a tile set
- 2K of PPU-RAM wired for addresses 0x2000-0x1FFF, with address lines A0 and A5 disconnected, but one pin controlled by the CPU banking register
- A pair of 4-input NAND gates to allow PPU addresses 1 xx11 1xxx xxxx to be served by NIRAM rather than the external RAM (for attribute fetches)
- 64K of CHR-ROM wired using A0-A12 plus the two latched bits above and two bits from the CPU-side banking register
- A banking register.
- Nametable update time could be significantly reduced, from a per-metatile time of 28 cycles down to 11 or maybe even 8.
- The ability to use almost 256 tiles, rather than only 64 [some tiles would need to be reserved for sprites].
Re: Ruby Runner motion test
I sort of struggle to see what MMC2 / MMC4 would provide that a scanline IRQ couldn't, except for a modest amount of saved CPU cycles.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.
And if you can live without the DMC channel in your game's music, you may not even need a mapper-based IRQ, but could use the DMC channel's IRQ as explained on the wiki: https://wiki.nesdev.com/w/index.php/APU_DMC
Re: Ruby Runner motion test
I'm pretty sure you'd lose a lot of CPU time if you used this trick multiple times per frame, as one of the key elements of this technique is to waste CPU time to compensate for timing errors.Bananmos wrote:And if you can live without the DMC channel in your game's music, you may not even need a mapper-based IRQ, but could use the DMC channel's IRQ as explained on the wiki: https://wiki.nesdev.com/w/index.php/APU_DMC