I apologize if this is the wrong section, or if this question shouldn't be asked at all.
The NES biggest and most well known flaw was flicker, but another flaw that was somewhat persistent was slowdown. Slowdown seems to vary on a case by case scenario, and it appears you can't always pin the fault on "poor optimization"; sometimes the game is just poorly designed. First, I will start with games that seem to push a lot of objects around with little to no slowdown.
A well known example of a relatively fast game would be K.I.D.'s
Summer Carnival '92: RECCA. The game is undeniably fast, though this comes at the expense of intense flicker, and it will suffer from slowdown from time to time. Given it is a game from 1992, you can assume this was due to the programmers being very familiar with how the NES works. But then there's older games, such as TOSE's
Chubby Cherub from 1986 (skip to 7:48), where they push an obscene amount of stuff around with no slow down, though on occasion the graphics will start to flicker. And then there are pirated (!) games, like
Magic Dragon, that seems to not slow down at all, though the screen will start to roll once the sprite limit has been reached. And then there's a curiosity like
Gun Nac where you can choose framerate at the expense of flicker, or (attempt to) disable flicker at the expense of framerate; the results of the second option, thanks to the NES' scanline limitation, are dubious at best.
It also seems like, as time went on, programmers got lazier and lazier and didn't bother to do the best job they can do. Notorious examples of slowdown ridden games would be
Contra Force and
Parodius Da!, both late NES Konami games. Especially baffling since Konami has managed to put out games with much more on screen with less slowdown, such as Contra, Super C, and Gradius (when you're not on stage 5). Even Nintendo can be argued of not giving a shit, as
Kirby's Adventure, a game universally lauded as being 'advanced', can slowdown when there's next to nothing on screen. Even the demo will slow down when Kirby demonstrates the "Spark" power up at 1:14! While I can't find a video of it happen, even the NES' flagship title, Super Mario Bros, will slowdown when you simply exceed the scanline limit, not to mention it appears as if the fabric of reality itself is about to tear.
Sorry for the lengthy post, I just wanted to appear as if I am somewhat educated. The important questions are: how can a programmer combat slowdown? What will encourage slowdown? And finally, have any of you guys ever had to fight slowdown, or is slowdown born from poor design, poor optimization, and over-ambition?
Contrary to popular belief, there is no direct relation between the amount of sprites on the screen (or sprites being dropped) and slowdowns. That just seems to be the case because more often than not, "more sprites" means "more objects being processed", but that isn't always the case, since a game can have a shitload of tasks to perform and not show a single sprite, or it can have all sprites on screen at once but hardly spend any time processing them.
Slowdowns happen when the game engine can't finish the tasks of a single frame within the time it takes for the NES to display a frame. See, while the NES is rendering a picture to the screen, the game engine is running and preparing all the data for the next frame. This means moving all objects (which may need physics), testing for collisions between objects and the level map, testing for collisions between objects, scrolling the level map, advancing the current music and sound effect(s), and so on. When the NES finishes displaying the picture if goes "hey game, I'm done, now it's time for you to give me the data I need to draw the next frame". So, if the game engine didn't finish a new frame, it simply can't give the NES data for a new picture, so it responds "sorry, not now... maybe next time", so the same frame is displayed again. This is what slowdown is.
Since a lot of tasks involve objects, and the number of objects often varies as you move through the levels, they are usually the ones blamed for the slowdowns, but every task performed by the game engine has a part in it. For example, if the scrolling engine is slow, it's eating away precious time that could be used by more objects.
It's considered bad practice to optimize code prematurely, so most programmers will focus on getting the games running even if that means sacrificing some performance at first. The problem with commercial game development is that deadlines are always too tight, and there hardly is any time left for optimizations (hell, in many cases they can't even find time to fix actual bugs!), so it's no wonder that some big name games as not as efficient about their CPU/memory usage as they could have been.
tokumaru wrote:
It's considered bad practice to optimize code prematurely
Thank you for your response. I always had a theory where, if I ever hired an NES development team, I'd require them to make the game work first, and then optimize the game code as much as possible. Forgot to mention, since Contra Force was essentially a quick rebranding of a cancelled game, Arc Hound, it likely meant that the programmers just simply made the game work, and put it out to recuperate some of the development losses. Since you mentioned that having sprites on screen isn't exactly the root cause, I recall Contra Force having this gimmick of a "computer controlled character", which didn't work all too well and made the game unbearably slow, not like it was fast to begin with.
Speaking of the frames not being updated fast enough, would that be the main reason why Micronics developed games seem to hover at 15-20 FPS, despite the NES itself operating at 60 FPS? Micronics isn't alone, even the venerable Technos seemed to compromise framerate. Double Dragon, DD2, and RCR seem to run at 30 FPS, and RCR will drop to around 20FPS with two players.
OneCrudeDude wrote:
Since you mentioned that having sprites on screen isn't exactly the root cause, I recall Contra Force having this gimmick of a "computer controlled character", which didn't work all too well and made the game unbearably slow, not like it was fast to begin with.
Yeah, any kind of heavy processing will help causing slowdowns, it's just that "large amounts of active objects" is the most common type of heavy processing, since objects require physics, collisions, and dynamic generation of OAM data... all of that can be pretty slow.
Quote:
Speaking of the frames not being updated fast enough, would that be the main reason why Micronics developed games seem to hover at 15-20 FPS, despite the NES itself operating at 60 FPS?
Definitely. If you can't make your game engine run in a single frame, it's easier to make it always use 2 (or 3) frames instead and change the physics to move the objects twice (or 3 times) as much as they would in 1 frame. The apparent speed of the game will not be affected then (i.e. a character moving 3 pixels every 3 frames will cover the same distance in 1 second as a character moving 1 pixel every frame), only the animations will not look as smooth.
Speaking of framerates, modern games seem to have the ability to reduce their framerate when there's too much to process. Would it be possible to make an NES game run at, say 30FPS when there's too much to process, instead of simply slowing down? This will give the illusion that the game is moving fast, but it will draw every other frame instead.
OneCrudeDude wrote:
Would it be possible to make an NES game run at, say 30FPS when there's too much to process, instead of simply slowing down? This will give the illusion that the game is moving fast, but it will draw every other frame instead.
See my first post here:
viewtopic.php?f=21&t=10878Possible yes, but not desirable. It also brings into question playability/usability; so you choose to only update relevant graphics bits every other frame (hence 30fps); what do you do about joypad reading and response to that input? If you poll input at the same rate (every other frame), graphics vs. input are "in sync" but the end user might end up feeling like there's "input lag" of sorts. If you continue to poll at 60fps but only update graphics every other frame, the end user might feel like there's a mismatch in responsiveness between input and what's visually seen on the screen.
Try the game "Downtown Special - Kunio-kun no Jidaigeki Dayo Zenin Shuugou!" (find an area that has enemies on the screen) for what this feels like, then ask yourself if it's worth it.
When emulating you can eliminate slowdowns by adding more cpu time at the end of the frame before vertical blank in many games.
I'm not sure about your idea of skipping frame updates to maintain overall speed. I think that would look bad. I think some games might reduce slowdown by dividing processing tasks between even and odd frames. It's probably best to just do your best to reduce the chances of serious slowdowns. But I wouldn't worry too much about slowdowns that aren't as bad.
While I back up what tokumaru said for the most part, I'd still say that, if the sprites are handled "properly", this means metasprites are copied to individual sprites into shadow OAM every frame, a lot of sprites will tend to also greatly influence the CPU load, because decoding/moving all those metasprites into OAM with effects applied on them can take a lot of time.
So it's wrong to say a game slowing down is because lots of objects and not because lots of sprites. I could be one, the other, or (the most likely) a combination of both.
OneCrudeDude wrote:
Would it be possible to make an NES game run at, say 30FPS when there's too much to process, instead of simply slowing down? This will give the illusion that the game is moving fast, but it will draw every other frame instead.
Well, if your games normal speed is 60 FPS, then slowdown specifically means that it's then running at 30 FPS (or less). What matters is how the game's internal time is handled. Most NES games have a fixed time step, i.e. no matter how much time passes in real life, the in-game time is increased by the same amount on each frame. In other words, the game doesn't give a f about the FPS and accepts the slowdown if it happens. The reason they do this is that it's much easier to implement, especially given limited CPU resources. It also provides more consistent behavior.
The other thing is that if the game isn't structured in such a way that slowdown happens gracefully, very often it will be accompanied by rendering glitches, especially where a status bar or some kind of scroll split is involved. For example, TMNT's status bar will disappear on alternating frames during slowdown. Unless your game has no special rendering techniques, keeping it together despite slowdown usually requires careful planning and delegation of important timed tasks to the NMI (scroll splits, music, etc.).
OneCrudeDude wrote:
Speaking of framerates, modern games seem to have the ability to reduce their framerate when there's too much to process. Would it be possible to make an NES game run at, say 30FPS when there's too much to process, instead of simply slowing down? This will give the illusion that the game is moving fast, but it will draw every other frame instead.
I think this would be somewhat hard to implement on the NES. Modern platforms can dynamically adapt the physics in function of the time, so if a game is about to render a new frame and it detects that 50ms have passed since the last update, it will do all the physics calculations assuming that 50ms have passed in the game world as well. NES game however, sync the physics to logic frames. If a logic frame takes too long to finish and ends up using the time of 2 hardware frames, all physics calculations will still have used the parameters define for a single frame, hence the slowdown.
To fix this on the NES, you'd have to count missed frames and try to compensate for them in the next logic frame. I guess you could have tables with all the physics parameters for different frame counts (i.e. if an object accelerates 0.2 pixels/frame, it will accelerate 0.4 in 2 frames and 0,6 in 3), and before starting each logic frame the engine would check how many frames behind it is, so that it knows which set of values to use. The game would constantly be keeping track of the number of missed frames and trying to compensate for them.
The problem is that not everything can be solved with tables... if the current speed of an object is 4 pixels, and the game is 3 frames behind, you'll have to add that amount to its position 3 times, and that will need more CPU time, effectively increasing the probability of missed frames in the future. Another problem is that when you move greater distances to compensate for the lost time, you take the risk of having objects run through walls! For example, if a wall is 8 pixels thick, and your character moves 4 pixels per frame, there's no way he won't bump into the wall, but if he moves 12 pixels to compensate for 2 lost frames, he may go completely through the wall.
I'm so glad that my topic seems to have garnered many replies! As for the Kunio Kun game Koitsu mentioned, the abhorrent slowdown this game suffers is the main reason why I will never play the game. It looks cool and has some neat features, but the slowdown, oh my god. Thank you all, regardless, for the helpful information!
I also have another question that will likely be within the realm of impossibility. Would it be possible to carefully develop an NES game so that it doesn't suffer intense slowdown and ensures that everything else won't glitch out, like the health bar in TMNT? Technically speaking, there are plenty of slowdown free NES games, mostly because they don't have much going on in the first place. I don't think you would hold Friday the 13th over Recca because, unlike Recca, it doesn't slow down at all. Or is the NES, so to speak, too weak? Given it's hardware from 1983, that's to be expected, but I mean weak as in you can't do much more than sidescrollers with 3 enemies tops on screen. At least it's not the SNES.
OneCrudeDude wrote:
I also have another question that will likely be within the realm of impossibility. Would it be possible to carefully develop an NES game so that it doesn't suffer intense slowdown and ensures that everything else won't glitch out, like the health bar in TMNT?
It's straightforward to guarantee that a top status bar won't glitch because the CPU can just sit in a loop for the first 32 scanlines after the end of vertical blanking without losing too much processing time. It's much less so to guarantee that a bottom status bar won't glitch. Either the CPU has to sit in a loop for most of the frame (which drastically increases slowdown) or the cartridge has to contain an interval timer circuit that interrupts the CPU when it's time to draw the status bar. Many later NES games, such as the arcade-style TMNT games, contain an MMC3 ASIC, one of whose functions is to act as such an interval timer.
Quote:
Or is the NES, so to speak, too weak? Given it's hardware from 1983, that's to be expected, but I mean weak as in you can't do much more than sidescrollers with 3 enemies tops on screen. At least it's not the SNES.
Compare processors:
- NES: 1.8 MHz 6502, sprite display list transfer at 0.9 MHz, video memory transfer at 0.22 MHz
- Super NES: 3.0 MHz* 65816, video memory and sprite display list transfer at 2.7 MHz
One big advantage of the 65816 is ability to access arrays larger than 256 bytes, such as level maps, without having to "carry the 1" all the time. But the bigger advantage for quickly updating the screen is that the CPU also contains a DMA controller, allowing it to copy data to video memory 24 times as fast as the NES CPU can. (This is the same principle used by "Blast Processing" on the Genesis.) Another thing is that Super NES sprites can be 16x16 pixels, meaning the sprite code doesn't have to write as many entries to the display list for a large sprite. Even with the bigger sprites, Super NES games rarely flicker because each scanline on the Super NES can hold 34 slivers (8x1 pixel units) of sprites, compared to only 8 slivers on the NES.
* Estimated average speed. The CPU normally runs at 3.6 MHz, but it slows to 2.7 MHz when accessing RAM, and it pauses for a few cycles of each scanline for DRAM refresh.
The SNES comment was simply a joke on how the SNES has many games with intense slowdown, almost to the point where every other game that's not an RPG suffers from it. Especially insulting since the SNES is a much stronger console, but the NES has some games that would probably slow down a lot if they were ever ported.
Tokumaru hit on this a bit, but a bit more explanation.
A lot of modern game simulation steps take a floating point "delta time" for the frame as a parameter, and this gets multiplied or otherwise applied to every operation in the simulation for that frame. For example:
Code:
void simulate_motion(float delta_time)
{
position += velocity * delta_time;
}
When you can multiply with floating points, it is rather straightforward to propagate a time delta into everything you do. When there is more time between frames, you get a longer measured time delta, so the overall apparent speed of simulation won't slow down; accuracy will suffer as the delta becomes longer, but it will remain approximately correct as long as the delta does not become too long. It's normal to cap it at some maximum delta and just accept real slowdown if the framerate drop is too drastic to avoid the chaos that results when things get too inaccurate.
Having to use fixed point instead of floating point makes this kind of thing trickier to apply. On the NES you have no floating point, nor do you even have a multiplication instruction. It's not really sensible to take this approach.
A very simple way to deal with this is to count frames in your NMI and try to play catch-up by running the simulation that many times before trying to draw the frame. i.e. if the last frame took two frames to simulate and display, do two simulations for this frame before displaying. If your simulation is quick enough, it will keep up at a steady 30fps. If it is not, however, it will bog down, as the extra catch-up simulations result in longer and longer frame times, resulting in more frames to catch-up on, etc. like before you need to put a limit on the catch-up and just accept slowdown at some point in the interest of keeping the game running and playable. The advantage of this method, at least, is that no simulation accuracy is lost.
A second way, which tokumaru was getting at, is to have a separate lower-accuracy simulation to catch up for a lost frame, essentially a 2-for-1 update where the player would move twice as far, etc. just performing all the same calculations just with different numbers (probably with a lot of use of the ASL instruction). This is the same as having a longer delta time: less accurate, but maintains the apparent speed. This can be a lot more complicated to implement, and also it becomes a source of chaotic behaviour. You probably don't want to implement a 3-for-1 catch up version, this is probably only effective if you can keep the slowdown to a single missed frame. Again you have a cap beyond which you must simply accept slowdown to keep things running.
As you can see, this becomes a pretty complicated problem, made even worse by the limited architecture. This is the reason that NES games don't try to compensate for missed frames, and just try to keep the updates within a frame and accept slowdown if they can't.
A variable time delta causes
real noticeable problems in Quake 3.
Slowdown in SNES games has been
discussed in another topic.
Alright, so I learned today that the SNES' is technically just a bit inferior overall than the Genesis due to data cycles and stuff I forgot about, but a large portion of the slowdown stemmed more from the lack of good know-how as compared to the Genesis; you could argue that the 65816 was a no-name CPU against the 68000. Coded to the metal as efficiently as possible, it would be possible to create an SNES game that ran well, and possibly even hold it's own against the Genesis, even more-so if you decide to use cartridge add-ons.
Another is that slowdown, if it's ever encountered, should be left alone and hope that it's only brief enough that you wouldn't notice. Unfortunately, deadlines, poor management, and poor planning will take their toll on how a game runs. Sometimes games were just made to run and that's all, sometimes games were essentially aborted and simply finalized. Often times, the game designers just winged it.
The 65816 was not a no name CPU. Other systems used it too. The 65xx family of CPUs is very well known.
TMNT's status bar glitch results in the use of sprite hit zero being used to time a series of writes near the bottom of the screen to make the status bar appear there. But when the processing loads exceeds a certain amount the game misses it's cue to do this. This results in a frame being shown without the Status bar in position. By giving the game more cpu time which is easy in emulation, this problem can be totally eliminated. As tepples said, the other solution is to have an IRQ in the cartridge mapper hardware to generate an interrupt at the precise time so that regardless of CPU load the status bar will always be drawn correctly.
The NES unlike more modern systems doesn't have a ton of CPU time to perform calculations. Neither do the SNES or Genesis. You can achieve good results with each platform, avoiding terrible slowdowns. It all depends on how your game is programmed and how much you need to calculate in a given time period.
We don't need another SNES is "inferior" to the Genesis or vice versa topic. Both systems have advantages and disadvantages. Both games have great examples of games that are impressive and run very well. Both game examples of games with crazy slowdown as well.
MottZilla wrote:
TMNT's status bar glitch results in the use of sprite hit zero being used to time a series of writes near the bottom of the screen to make the status bar appear there. But when the processing loads exceeds a certain amount the game misses it's cue to do this. This results in a frame being shown without the Status bar in position. By giving the game more cpu time which is easy in emulation, this problem can be totally eliminated.
Except that the extra time provided by emulators is located past scanline 239, so as to not break raster effects created with timed code, which means that the sprite 0 hit still wouldn't be detect. I guess the emulator could let the user pick whether the extra time will be at the beginning of the frame or at the end.
Quote:
As tepples said, the other solution is to have an IRQ in the cartridge mapper hardware to generate an interrupt at the precise time so that regardless of CPU load the status bar will always be drawn correctly.
For status bars at the bottom of the screen, IRQs are indeed the way to go. Only games without any slowdown whatsoever can pull off a spite 0 hit after the game logic.
Quote:
We don't need another SNES is "inferior" to the Genesis or vice versa topic. Both systems have advantages and disadvantages. Both games have great examples of games that are impressive and run very well. Both game examples of games with crazy slowdown as well.
Agreed.
Dendy mode in an emulator provides 50 more lines of processing time between line 239 and vblank. PAL NES mode provides the extra time between vblank and line 0. PAL NES mode might fix TMNT 1's bottom status bar.
It's possible to
"abuse" one of the built-in audio interrupts as a timer to tell when to start looking for a sprite 0 hit, and a few games (Fire Hawk, Time Lord) do this.
tokumaru wrote:
Except that the extra time provided by emulators is located past scanline 239, so as to not break raster effects created with timed code, which means that the sprite 0 hit still wouldn't be detect. I guess the emulator could let the user pick whether the extra time will be at the beginning of the frame or at the end.
You're right it all depends on where/when the extra time is provided and how the game works, as well as the emulator. One idea would be to allow the user or some kind of database to detect games to choose a scanline number to have as the point for X number of extra CPU time. Most games probably don't need a huge amount of CPU time to eliminate slowdown. I think I tried with certain games to get a rough estimate of how many "extra scanlines" worth of time prevented slowdowns. I don't recall now.
If a later game has more slowdown than an earlier game by the same company, it could be that the earlier game engine was more custom made for that game, while the later game used a more versatile engine.
When I saw slowdown happen in Kirby's Adventure as a kid, I believe I literally thought it was intentional, making an action packed moment more poignant, like the much abused bullet time technique used in movies since the Matrix. (is it a bug or a feature?)
TV Tropes calls this slowdown "nature's bullet time", and in both Pokemon Puzzle League (N64) and Mega Man 9 (Wii), it's present on purpose.
I don't see how slowdown could possibly exist in a puzzle game, or what purpose it would serve. As for MM9, of course they're going to reference the two most glaring weaknesses of the NES Mega Man games. They're flicker heavy (due to how the graphics are designed) and slowdown prone (due to the graphics being layered).
As for bullet time, I always thought it'd be a neat way to sweep slowdown under the rug, maybe even have a blurb on the box saying "Features REAL TIME SLOW-MOTION ACTION". In that case, would it be possible to make the NES detect if slowdown is happening, and in turn make it darken the screen and make a "beeeewww" sound, to make it look Matrix-y?
I guess you would need to first test how many objects or whatever it takes to cause slowdown at a certain point in game and then make sure those conditions are met before darkening the screen.
OneCrudeDude wrote:
I don't see how slowdown could possibly exist in a puzzle game, or what purpose it would serve. As for MM9, of course they're going to reference the two most glaring weaknesses of the NES Mega Man games. They're flicker heavy (due to how the graphics are designed) and slowdown prone (due to the graphics being layered).
I don't know about Puzzle League, but in the original Panel de Pon there's no slowdown but chains and combos are rewarded with a few seconds of stopping time. Since the stack is constantly rising this gives you more time to make more chains/combos and to survive in general (if the stack hits the ceiling you loose). You would benefit from slowdown the same way.
In Megaman it's not always beneficial, if the slowdown suddenly stops you might be taken off guard and be shot in the face. But I see that they wants Megaman 9 to play like the original 6 games.
OneCrudeDude wrote:
I don't see how slowdown could possibly exist in a puzzle game, or what purpose it would serve.
Panel de Pon/Tetris Attack allows huge, screen-spanning combos in 2-player mode, especially when both players are removing garbage that the other player sent. Animating their removal from the screen slows the game down for both players.
OneCrudeDude wrote:
I don't see how slowdown could possibly exist in a puzzle game, or what purpose it would serve.
Non-scrolling games with a controlled number of objects on screen are less likely to have large variations of CPU load, meaning that puzzle games are among the steadiest ones, if you ignore slowdowns caused by occasional screen-sized effects (which more likely result from the low PPU bandwidth than increased CPU load).
Quote:
They're flicker heavy (due to how the graphics are designed) and slowdown prone (due to the graphics being layered).
Actually, I'd say that the sprite layering is partly responsible for the flickering, but it can't really be blamed for the slowdowns... I'm pretty sure the games would still lag even if no layering was used.
Quote:
As for bullet time, I always thought it'd be a neat way to sweep slowdown under the rug
True.
Quote:
REAL TIME SLOW-MOTION
I'm pretty sure this is a contradiction.
Quote:
In that case, would it be possible to make the NES detect if slowdown is happening, and in turn make it darken the screen and make a "beeeewww" sound, to make it look Matrix-y?
Yes, perfectly possible. I wouldn't turn on bullet time at the first sight of a dropped frame though, I'd probably wait for a few of them close together (say, 5 out of the last 10 frames). The effect also shouldn't be turned off too soon, so after a minimum amount of bullet time the engine would wait for a number of consecutive frames without lag (but I'd still fake the lag to the player during that time, since it's bullet time).
Having a global transposition feature in your music engine helps too, as you can just decrease it to -12 (down an octave) when lag begins and increase it back to 0 when lag ends.
Some games actually do have the music engine not update every frame when the game slows down. It's actually pretty annoying for the music not to continue to play properly despite whatever may be happening on screen. Speaking of slowdown, I think it's Bugs Bunny Birthday Blowout runs at 30fps all the time. However by overclocking it can actually run at 60fps I think. But I'm guessing either it was poor programming and they purposely tried to make it consistantly 30 frames or maybe it was a lucky accident that it remained consistent.
The "Real time slow-motion" thing was supposed to be a nod to those blurbs that were on some NES boxes. Granted most BS blurbs started to become less common with the NES and they were common for 2nd gen games. But I still have a different way for how "bullet time" could be executed. Let's take my prior theory of a game that doesn't slow down, whether it's been optimized to hell and back or if there's next to nothing happening on screen. Would it be possible to intentionally cause slowdown on the NES, after pressing a certain button combination?
OneCrudeDude wrote:
Would it be possible to intentionally cause slowdown on the NES, after pressing a certain button combination?
Yes, just skip updating the game world every other frame while in "slowdown mode".
MottZilla wrote:
Speaking of slowdown, I think it's Bugs Bunny Birthday Blowout runs at 30fps all the time. However by overclocking it can actually run at 60fps I think. But I'm guessing either it was poor programming and they purposely tried to make it consistantly 30 frames or maybe it was a lucky accident that it remained consistent.
The worst when it comes to this is probably the NES version of Parodius. The amount of slow down is basically proportional of the # of options you have.
No option = 60fps
One option = 30fps
Two options = 20fps
Three options = 15fps
Additionally, it will randomly go suddently much faster or much slower. Constant slowdown is not lagging anymore it's a ***** mess.
Fortunately the SNES version is much better.
tokumaru wrote:
OneCrudeDude wrote:
Would it be possible to intentionally cause slowdown on the NES, after pressing a certain button combination?
Yes, just skip updating the game world every other frame while in "slowdown mode".
Or you could just have a long loop of NOPs executed to burn up a predetermined amount of cpu time. That would be the easiest thing to do. Just a series of nops and using one of the registers as a counter. Not sure why you'd want to do that but I guess there are some difficult games that having a slowdown button would be helpful for. Maybe Silver Surfer?
MottZilla wrote:
Or you could just have a long loop of NOPs executed to burn up a predetermined amount of cpu time. That would be the easiest thing to do.
I's also pretty hacky and unreliable. How much time would the loop waste? Too little and a frame with few calculations will not lag, too much and a more complex frame might cause 2 skipped frames. I'd much rather have something like this wrapping the game logic:
Code:
IF (SlowMotionMode = TRUE) AND (MissedLastFrame = FALSE) THEN
[GAME LOGIC HERE]
END IF
Well that's true, if you want to have a consistent 30fps or something like that. But if you just wanted to see what X more CPU load would do, that's easy. And if you were hacking an existing game that might be easier.
Somewhat related question I've been meaning to ask, since I couldn't understand the wording. According to tepples, the NES' CPU does twice as much in each cycle as the SMS' CPU, and mentioned that a 1.8 MHz NES and a 3.6 MHz SMS is "a wash". Does that mean they both have roughly the same computational power? And how does the SMS fare with slowdown?
Perhaps "wash" wasn't the best word. But yes, I meant that at those clock speeds, those CPUs are comparable in what they can compute in one second.
I'm pretty sure slowdown works the exact same way on the SMS: if one frame isn't enough time for all the computations, graphic updates will be delayed until the next VBlank. It's true that, unlike the NES, the SMS can update the graphics while the screen is rendering, only not as fast as during VBlank, so I believe most programmers wouldn't go through the trouble of slowing down the updates just to be able to do them before the next VBlank, not to mention the visible tearing that would result from doing that.
Hmm, I guess I worded my question wrong. I meant to ask if the SMS had slowdown that would be classified as 'worse' than the NES. Then again, the SMS has a library that's only a fraction of the NES', so it'd be somewhat unfair.
For a game that's developed for hardware that's known in advance, slowdown is more of a software design and implementation problem than a hardware problem. It occurs where what the developer has attempted to make their game do exceeds their hardware's performance budget.
If you stay under the performance budget when designing/implementing your game, there will be no slowdown. It doesn't matter if the budget was larger or smaller, only whether you met the budget. Thus, slowdown was not really the hardware's fault, merely the developers trying to exceed its capability. Trying to compare SMS vs NES in terms of which system had more slowdown is futile, you are merely comparing how developers felt about their performance budgets.
It's a different story on a PC where the developer has no idea how powerful your CPU or GPU is ahead of time (aside from telling you some minimum or suggested requirement). In this case the developer has to allow for this, which is why on PC games you tend to get a variable framerate implementation rather than console-style slowdown. You also tend to get a lot of options for things like level of graphics detail, allowing the user to scale back the performance budget to meet their hardware's capabilities, so that the user can choose whether to favour framerate or detail.
I agree. You need to stop thinking about NES or SMS hardware as being somehow at fault or to blame in relation to slowdowns. Slowdowns are because the game is programmed in a way that situations where too much needs to be processed for a single frame occur. It doesn't matter how many sprites or enemies are on the screen, it matters how much CPU time is needed to keep having frame updates ready in time. How many enemies or objects are on screen certainly play a part, but the amount of CPU time each piece needs can vary greatly from game to game or even situation in the same game.
There really is no mystery behind slowdowns in general. Too much to compute each frame. A good example of some bad programming causing slowdown is Mega Man The Wily Wars on the Genesis. You'd think since the original game on a 6502 at 1.78mhz had very little slowdown that on a newer 68000 at 7.5mhz would have perhaps none at all right? Well just playing against CutMan in the first game, it slows down immediately as the battle starts. It runs slow the whole time. However if you have Gutsman's power you can throw the two blocks in the room and the slowdown goes away as I recall. So somehow those two blocks just being there somehow caused the framerate to drop below 60fps.
I've read various comments, some saying the game was programmed in C rather than ASM leading to inefficient code. We can be sure that something is being wasteful though given that the game logic certainly didn't have a problem before.
Final Fantasy V on the GBA shows quite a bit of slowdown in some things that the original game had no problems with at all. Even accounting for CPU time lost for soft synth, the GBA's cpu mops the floor with the SNES's cpu.
So yeah, you get what you get, I suppose. I know I've seen the following sorts of things in GBA code:
Code:
; r0 is being used as a counter for an inner loop of some sort
add r0, r0, #1
lsl r0, r0, #16
asr r0, r0, #16
cmp r0, #looptotal
So the code was written in C, and used the short datatype instead of the int data type for an inner loop variable, which just indicates lack of familiarity with the CPU (and C in general, because you should always use int for operations where no specific size is needed).
I'm sure NES code comes across the same thing; I remember reading in Disch's disassembly of Final Fantasy that some of the code uses zero page addresses without zero page addressing.
natt wrote:
I'm sure NES code comes across the same thing; I remember reading in Disch's disassembly of Final Fantasy that some of the code uses zero page addresses without zero page addressing.
I have come across commercial games doing the same thing, using absolute addressing where they could have/should have used ZP. I don't know if it was human error or a crappy assembler or what. Obviously you want good performance but at the end of the day a product that works is the end goal. Ofcourse there's action 52 which doesn't even seem to meet that basic goal.
MottZilla wrote:
the amount of CPU time each piece needs can vary greatly from game to game or even situation in the same game.
I think the question might have been whether a piece of code that computes a particular result, such as computing the trajectory of each object in a game, would need more time on the 6502 in the NES or on the Z80 in the SMS. That incidentally is the kind of question that inspired the great C64/Speccy flamewars on Usenet. But I will say something about the video chip: the fact that the Z80 in the SMS can write to VRAM during draw time is probably balanced out by the lack of hardware horizontal sprite flipping.
natt wrote:
I remember reading in Disch's disassembly of Final Fantasy that some of the code uses zero page addresses without zero page addressing.
Assuming it's not
LDA a,Y, which has no zero page counterpart: NESASM is descended from MagicKit, but is that descended from an NES-era assembler?
tepples wrote:
But I will say something about the video chip: the fact that the Z80 in the SMS can write to VRAM during draw time is probably balanced out by the lack of hardware horizontal sprite flipping.
And the inability to change vertical scroll mid-screen (meaning no raster stretching / instrument panel effects)...
The SMS does have a rather nice a function though. You can reserve a section of the tilemap for the top of the screen (it won't scroll), and IIRC you can do the same for a vertical column to the side of the screen (don't remember if it's left or right) - just not both at the same time.
tepples wrote:
natt wrote:
I remember reading in Disch's disassembly of Final Fantasy that some of the code uses zero page addresses without zero page addressing.
Assuming it's not
LDA a,Y, which has no zero page counterpart: NESASM is descended from MagicKit,
but is that descended from an NES-era assembler?
MagicKit looks a LOT like the assembler that Hudson made for the PCE, which Hudson probably adapted from their NES assembler.
OneCrudeDude wrote:
Alright, so I learned today that the SNES' is technically just a bit inferior overall than the Genesis due to data cycles and stuff I forgot about, but a large portion of the slowdown stemmed more from the lack of good know-how as compared to the Genesis; you could argue that the 65816 was a no-name CPU against the 68000. Coded to the metal as efficiently as possible, it would be possible to create an SNES game that ran well, and possibly even hold it's own against the Genesis, even more-so if you decide to use cartridge add-ons.
Another is that slowdown, if it's ever encountered, should be left alone and hope that it's only brief enough that you wouldn't notice. Unfortunately, deadlines, poor management, and poor planning will take their toll on how a game runs. Sometimes games were just made to run and that's all, sometimes games were essentially aborted and simply finalized. Often times, the game designers just winged it.
...and even with deadlines, they could've avoided most of the slowdowns in the first place if they just programmed the SNES like a game system, instead of programming it like a PC. I wouldn't be surprised if anyone used floating-point arithmetic on the SNES.
I plan to use a form of floating point in my next NES project, and I have a good reason for it: the player's bank account can range from 1 to 1 septillion (10^24). I've been prototyping addition, subtraction, and multiplication over the past few days, and I'm headed to division next.
As long as the player's funds don't change every frame, I think you'll be OK. Using floating-point math for physics on the other hand would be disastrous.
I traced the code of Super Ghouls 'n' Ghosts using bsnes debugger to find what was causing the slowdown. It has a routine that reads from a list of sprites, and generates the OAM buffer. What doesn't make sense is how they placed the size bit where the second priority bit is supposed to be, and it has to do extra shifting to get it out.
Did you try to optimize/fix it and reduce the slowdown?
Yes, and boy is this difficult to fix. I'm guessing that almost every routine in the game would need to be individually fixed to get the slowdown removed.
I posted a text file of asm patches I made that are supposed to reduce slowdown. I even tried to convert it to a fastROM.
psycopathicteen wrote:
What doesn't make sense is how they placed the size bit where the second priority bit is supposed to be, and it has to do extra shifting to get it out.
Unless perhaps there was only one priority bit on preliminary Super Famicom silicon, and the size bit was moved from there to the additional 32-byte block before launch. This way they could still use their subroutines that generated sprite tables in old SFC format and translate them to the final format afterward.
That actually does make a lot of sense.
It's possible; the SFC 1 year prior to release had only 32KB of RAM, and the Audio DSP had only 32KB of RAM (instead of 64K on release).
Do you have your patch ready as an IPS? And did you notice any significant reduction in slowdown?
I don't know what an IPS is. I think I can see a difference, but its very small. It lags with 3 wolves instead of 2, or something similar.
"Game Maker" was brought up in a few threads, so I looked up a few tutorials. Under the platform game tutorial it said that tiles are just part of the background, and invisible solid objects are placed over the background tiles. Now I understand that this is just a quirk in the "Game Maker" program, but it does make me want to ask if this was common practice in the NES/SNES days, because it is much faster to use a collision map than to map every solid block into an object.
The invisible solid objects in such a game form a collision map.
But the common practice as I understand it, at least in the NES era, was to build the nametables and the collision map from the same underlying data set in real time. For example, Super Mario Bros. decodes a column of 13 metatiles (totaling 16x208 pixels) at a time, writes it to the nametable, and then caches it for collision in a 32x13-metatile sliding window. Each metatile then has its own collision properties.
Nowadays it appears to be common practice to draw the scenery entirely with objects, but old consoles would definitely have a lot of trouble keeping track of many active objects. Games like SMB and SMW did use objects to create the backgrounds, but those were converted into tile maps before being used by the engine.
I think generally only something moving would be platformed on as an object and not part of a tile array. Or maybe some large flat surface or something like in Castlevania IV where there is rotation or SMW boss on the tilting land in lava. It is more efficient to have a tile array generally. Not collision related, but the NeoGeo makes all its major backgrounds and objects from what we call sprites. It only has a non scrolling simple background layer that's usually just for status bars and the credit display.
And since the PlayStation and the stripped down SGI Indy that is the N64, everything has been made from textured triangles or quadrilaterals.
Neo Geo sprites are sort of hybrids. They're actually maps made of 16x16-pixel tiles that are 1 tile wide and up to a screen tall. This makes it practical to have block puzzles like Magical Drop (16x16 pixel square grid), Puzzle Bobble/Bust-A-Move (16x16 pixel hex grid), and Joy Joy Kid/Puzzled (8x8 pixel square grid). A platformer like Super Mario Bros. might be done on a Neo Geo using about 20 such tile columns for the playfield.
Is there anyway of telling if a game is programmed in C, by looking at it's ASM code?
I know of no foolproof way to detect whether an unknown C compiler was used. Some techniques may help:
- Someone familiar with each of the major C compilers might be able to identify instruction sequences or memory model assumptions that a particular compiler makes. For example, ca65 has a separate native stack from the C stack in order to allow use of more than 256 bytes of automatic variables.
- Some games are written in a hosted mode, which means they use parts of the C standard library. One way to tell whether you're dealing with an implementation of the C standard library is by looking for data formats used by the C standard library. This is how NovaSquirrel and I detected Koei's use of C, by running strings on some Koei game and finding printf format strings.
I attempted to fix SGnG again, and I found another thing wrong with it. Many large objects are composed entirely from 8x8 sprites.
EDIT: Hey, if you remove support for 16x16 sprites, almost all slowdown goes away.
I expect that C code on the NES would have a few recognizable earmarks, regardless of which compiler was used.
Probably you would find a lot of poorly optimized code, especially with calls to common subroutines that would be part of its CRT.
Perhaps there would be a recognizable software stack, like the one CC65 has (this generates tons of calls to the CRT subroutines for the software stack), or alternatively you may find a lot of passing of variables on the hardware stack, which will involve TSX/TXS and frequent use of X indexed addressing with ranges probably around $00F0-00FD (e.g. if you saw something like LDA $00FA, X frequently enough, I would definitely start to suspect C). An assembly programmer is not likely to use the stack like this, since they will probably know which functions may call each other, and can manage parameters through ZP variables. A C compiler won't likely know this and has to use the stack, unless you explicitly avoid the stack by using global variables.
The number of original NES games using C is probably extremely small. It's been mentioned before that some of the KOEI games that were ports from PC systems to NES probably used some C code. That may be a hint for where to look (e.g. PC->NES ports, games that may have complex behaviour but don't need high performance). In recent homebrew there's probably several examples, but usually in this case the author will just tell you if you ask, which is much easier than trying to guess from disassembly.
Super Ghosts and Ghouls DOES have a software stack, and there is an awful lot of pushing and pulling.
Use of the stack on a 65xxx CPU is not considered grounds or justification for "it was probably written in C". While what rainwarrior and tepples both said is completely valid/true, but it isn't a definitive indicator that something was written in C.
The short version is that no, there is no definitive way by disassembling a game to accurately conclude "yes that code was generated by a compiler thus originally in C".
Also, food for thought: Super Ghouls and Ghosts (not Ghosts and Ghouls) was one of Capcom's first SNES/SFC titles. It's very likely that given what games they were working on at the time (circa late 80s/early 90s), much of the code was probably intended for a general-purpose engine that was used in other titles, or very possibly a hacked-up version of a previous engine.
I'm really not surprised about large mobs consisting of mainly 8x8 sprites, nor do I believe that is the direct source of the slowdown -- do you know why they did it that way? Almost certainly because if there's animation or changes that occur on a fairly granular level within the mob (e.g. an eye blinking, a hand opening/closing, etc.) then all that's required is that the engine refer to a different 8x8 tile in the nametable. You don't have to keep tons of 16x16 objdata laying around (wasting ROM space), nor do you have to resort to worse things like taking 16x16 objdata, shoving it into RAM, then splitting it up into 8x8 pieces yourself, modifying the part relevant, then recombining it all and updating VRAM.
If you really want a game that has slowdown that is intentional yet there have been a couple people that have looked at it (myself and Neill Corlett) and never figured out the root cause, try Gradius III for the SNES/SFC. Neill and I are both of the opinion the slowdown is intentional (to make the game easier for players given the huge number of objs on-screen), but neither of us were ever able to determine where/how this is done. Further efforts were needed but neither of us wanted to put in the extra time.
psycopathicteen wrote:
Super Ghosts and Ghouls DOES have a software stack, and there is an awful lot of pushing and pulling.
Could be macros. I wrote a macro system for huc6280 that looks more like 68k code. It creates shorter and cleaner looking code, but expanded it tends to look like compiled code a bit. It's great for prototyping my code, and if I need a speed increase - I'll rewrite that routine.
I'm only talking about clues, not rules. There are reasons/ways to do the opposite of what I've suggested in either assembly or C based programming. I'm only suggesting cases where a closer look may be warranted. You'll have to make an educated guess based on what you see, I couldn't say much based on what you've said so far.
psycopathicteen wrote:
I attempted to fix SGnG again, and I found another thing wrong with it. Many large objects are composed entirely from 8x8 sprites.
EDIT: Hey, if you remove support for 16x16 sprites, almost all slowdown goes away.
All that 8x8 meta-cell sprite decoding can take up quite a bit of cpu resource per frame.
Sprite handling almost takes 1/3 of the frame, due to all those 8x8 sprites, and the thing with the size bit being encoded where the priority bit is supposed to be.
How you profiled that I have no idea, but assuming that anecdotal number is true, that's still a third of a frame (I also don't know if by "frame" you mean outside or inside VBlank). If if takes up a third of VBlank time, so what? How does that definitively show "8x8 sprites are what's causing slowdown"? Does the amount of time being taken up vastly grow (i.e. extends outside of VBlank, or require every-other VBlank to be processed) if the number of mobs on-screen increases? Does it vastly shrink if that number diminishes?
Dunno about the "size bit vs. priority bit" thing -- no clue what that means/refers to, but that's because I'm not in the know on this one.
Sorry to voice my frustration, but man, your one-liners are frustrating sometimes. Games are highly complex things.
I don't expect the sprite management to be the only thing that is slow. Just something that is slow. I mean a 1/3 of a full frame. When I traced it through bsnes debugger, the frame was almost a full 262 lines, and about 90 scanlines was just organizing OAM.
The priority/size bit thing is this. SGnG has two OAM buffers, one for the actual DMA loading, and another where sprites get written to by the game logic, and then reorganized into the final OAM buffer. The latter has the size bit encoded where the 2nd priority bit is supposed to be and it has to do a lot of shifting to get it out.
koitsu wrote:
Dunno about the "size bit vs. priority bit" thing -- no clue what that means/refers to, but that's because I'm not in the know on this one.
Probably in the sprite metadata the bit that would be taken by the priority flag is repurposed to mean the sprite size.
I'm starting to see a difference between my hack, and the original.
[Reminder: Post the IPS, not the ROM]
tepples wrote:
Neo Geo sprites are sort of hybrids. They're actually maps made of 16x16-pixel tiles that are 1 tile wide and up to a screen tall. This makes it practical to have block puzzles like Magical Drop (16x16 pixel square grid), Puzzle Bobble/Bust-A-Move (16x16 pixel hex grid), and Joy Joy Kid/Puzzled (8x8 pixel square grid). A platformer like Super Mario Bros. might be done on a Neo Geo using about 20 such tile columns for the playfield.
Sort of reminds me of Atari/Amiga style sprites, except with a far greater number of them available to the programmer.