Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
Yeah, the disassembly is really useful -- not only for TASing, but also for resynching runs, and, as it turns out, for synching it on console as well. Anyways, only 6 more days until all finals are done and I can make that über hack that displays the low byte of v-int run counter at all frames with no loss of time...
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
Hmm you mentioned vines using VInt counter before, is that S3 only and not S&K?
The vines in Angel Island actually get updated by the same function that updates the ring animation; so whenever you are in a level and not in a lag frame. The issue with them is that unlike some other things (the oscillating numbers platforms depend on, for instance), they are never reset. This is actually more important for real time speed runners, as they have to hard-reset the game between attempts or the vines will be in the "wrong" place.
notaz wrote:
I'm having problems with Aquatic Ruin 2 desync, there are 2 pauses before boss fight starts, inserting a frame to any of them, or delaying the pauses themselves doesn't seem to help. Here is how it desyncs, and I couldn't spot any difference after frame inserts:
I take you mean the animals at the end? That is a bit mea culpa: I talked all about animal generation and forgot to mention that they use the v-int run counter to determine the direction they go (it has been a while since I manipulated animals in S1 or S2...). Specifically, they use bit 4 of the v-int run counter at the time they land. Meaning you need to add potentially up to 31 frames to get the animal manipulation to synch. The good news is that the pauses to synch animal appearance can be made concurrently with this. You can probably find how many frames to get animals generating at the right time, then add 8 frames at a time until they all turn the right way.
notaz wrote:
and I wonder what the reason for delaying the last hit?
As WST said, it is to glitch the boss: due to a coding error, when you hitting on a specific frame (there are actually two distinct ones for this boss) you cause a double-update to the boss' subroutine counter, making him jump from "exploding" to "blasting away". Some other bosses also have this same coding error, but they cause crashes instead (Oil Ocean boss, Silver Sonic in Death Egg), and so does one badnik (the dinosaur-like badnik in Hill Top).
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
I tried the simplest hack for S3K which replaces score with VInt counter (so only updated when score changes), and this is the result:
Interesting idea.
notaz wrote:
So the difference seems to be 31.
I take it that this is including the 2+13=15 frames you added? If so, those screenshots would indicate 16 more lag frames than what Gens emulates. Straining your good will, could you check where those frames come from? I would hope it is from before the level starts...
And by the way, these 16 lag frames don't affect the moving platform, vines or ring animations, so this is just plain old curiosity.
notaz wrote:
(also it seems my camera scans bottom-to-top, what's up with that?)
It is not that it scans bottom-to-top; rather, the camera and TV/genesis are neither exactly synchronized nor are likely to be using the same frequency. In this case, your camera likely records at either 30 or 60 fps, while the TV/Genesis is outputting at 60/1.001 fps; thus, your camera is taking snapshots progressively earlier in relation to the TV output, with the effect that you get a rolling dark band going up.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
Maybe we could use a ROM hack for this, replace ring counter with that, or something. Different drawing routine may affect timing but maybe not too much and it would be enough for debug.. What is the RAM address of that counter?
The full counter is at $FFFFFE0C; the game generally uses only the byte at $FFFFFE0F for the purposes I mentioned, and generally masks it with a small number one less than a power of two (1, 3, 7, 15, ...).
notaz wrote:
Unfortunately I can only do 30fps video..
To be fair, the 30fps one would allow deducing it within a frame in this case, so I may have been exaggerating...
notaz wrote:
What would also help is getting rid of excessive input. For example at the Knuckles emerald cutscene, Tails' left input starts way before game accepts input, which got me confused as inserting 10 frames (for example) before input starts made Tails walk left too much and I got even different desyncs. I usually add more frames for a test, and reduce until minimum needed is found, but it didn't work here until I replaced all excessive frames (33) with no-input.
That has been reduced too, to "only" about 10 frames in that case; I suppose I could go around removing needless input, but it will delay the TAS even further.
notaz wrote:
feos wrote:
Is gpgx so far off to test on?
It's somewhere in between of Gens and real hardware. Seems to be closer to Gens according to floor tiles and almost kills CPZ boss in S2, but also desyncs right there.
That is interesting to know; I had very little information about gpgx accuracy other than "better than Gens".
notaz wrote:
OK it worked, needed 203 frame long pause. Next desync - Aquatic Ruin 2 animal manipulations, are those hard to fix up? I could instead resync at Casino Night 1 start I guess, like I used to do in S1..
In both S1 and S2, you can fix the manipulation by adding some frames in pauses before the boss starts exploding; specifically, either 3 to 7 frames or 9 to 10 frames in pauses. Both assume that the frames where start is pressed to pause and unpause were added along with blank spaces between them; if you edit frames to turn them into pause/unpause, you need to add from 1 to 7 frames. If nothing else differs (a big if in S1, especially in Labyrinth zone -- lag is liable to be different), the animal manipulation should work once you add the required amount of pauses. If something does differ, and the animal manipulation desynchs after a point, you can add or remove delays right before the desynch point (preferably during an already present pause).
If you are curious: it has to be before the boss starts exploding, as the explosions also use the PRNG for positioning, and they also depend on the v-int run counter in the same way that the animals do.
notaz wrote:
I've tried toying with this too, and it seems S2 is optimized to not redraw score/rings until they change, so replacing them is not that useful. I've tried to force redrawing every frame, and that caused things to drift and desync, as expected..
Considering that only the last byte of the v-int run counter will be relevant in the vast majority of cases, the last byte of the v-int run counter can be displayed in hex this method:
editing the HUD's sprite mappings to have 256 frames, one for each possible hex value; the v-int run counter is used as an index, and the mappings can be done so as to have the same number of sprite pieces as the original mappings, with the same size (to make the VDP happy too, though I doubt it would affect synch).
disable blinking of rings and timer by removing the code responsible.
replace the score/ring/time text with hex digits, so the art does not have to be uploaded to the VDP every frame.
optimize the code so it takes the same number of cycles as the original code, adding dummy code as needed (the differences caused by rings/timer blinking need to be accounted for, but the TAS never comes near enough a time over for the latter to matter).
This adds a lot of data, but this additional data will not cause any additional delays; it can actually be generated through macros in the disassembly. Done this way, nothing will be sent to the VDP which wasn't sent already, the VDP will have to draw the same amount of stuff, and the code will take the same time to run on the 68k side. Basically, it can be done without adding any delays to the game other than things that aren't at all emulated (such as bus contention, memory refresh cycles, etc.). Just give me a few days (as I have finals all over the next week) and I will write this.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
Exodus is not open source yet, and while it is the most accurate emulator for Genesis, it is not perfect yet, specially the released version: it demonstrably has incorrect timings on several instances (for example, waterlines on Angel Island on S3).
One would also need to figure out the movie format it uses, although I suspect it should be relatively easy.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
When you say "uses PRNG", do you mean it derives some larger values from those low bits only, or does it also mix in some previous RNG state?
Hm, the draft version of this section was more clear on this point; I wonder what happened to it? Anyway: it is generally used as a "gate": if the low bits fit a given pattern, then an action will be performed which uses the PRNG. A concrete example: animals in S2 capsules are generated when the low 3 bits of the v-int routine are zero; when this happens, the PRNG is called to generate a random number to decide where the animal is going to be placed horizontally (relative to center of capsule) and the PRNG is called again to determine which kind of animal is going to be generated. So a more correct description would be "triggers use of the PRNG".
notaz wrote:
marzojr wrote:
Directly as a source of entropy: in Sky Sanctuary, the boss reseeds the PRNG using the v-int run counter directly.
This looks like a showstopper to me. By the time we arrive at Sky Sanctuary (assuming it's possible at all) this "universal timer" will have a lot larger value in console than in Gens, so it's basically impossible to get the value needed by TAS here.
This one is actually not that bad; the TAS only needs two values for the boss fight, and they are quite easy to get if you pause long enough before the PRNG is seeded. Several versions of the TAS were done by pasting the input from earlier versions of the TAS and adding pauses through TASEditor. The only issue is that you would need to play the entire run from the beginning for each attempt, unless you found a way to obtain the value of the v-int run counter at the start of the level.
notaz wrote:
marzojr wrote:
The function that updates them is called right before the function that updates the ring animation frame, which means they both got called at a different frequency on console than they did on emulator
What made you arrive at this conclusion? Both ring animation phase and the platform differ from emulation, but they still may be in sync with each other. Or do I miss something?
You didn't miss anything, what I wrote was unclear; you are right, the ring animations and the platform are indeed in synch. What I was going on about was that they were apparently emulation was out of synch with console, which didn't make sense: based on the evidence given by the screenshots, there are at least 9 frames of difference between console and emulator in those two screenshots: rings have 4 different sprites that are cycled through, and each sprite lasts for 8 frames; so 9 frames in the best case scenario, but potentially up to 23 frames to go from ring sprite in emulator to console. This is why I asked this question:
marzojr wrote:
Hm. How many waiting frames (if any) did you have to add to the flame transition?
Your response was mostly something I expected:
notaz wrote:
2 frames had to be inserted before input starts around Knuckles emerald cutscene.
13 frames inserted before spindash after flame transition to avoid the spindash become useless because of screen lock.
There is the difference in platform (and ring) positions between emulator and console: 15 frames is almost in the middle of the 9 to 23 interval. And I asked specifically about the transition because I figured out that staying as quiet as possible in it caused up to 20 frames of difference because the game is loading act 2 there. I wasn't expecting the 2 frames before the emerald cutscene, though, but they also make sense -- there is some art loading nearby too.
I need to check a few things, but it may potentially be possible add these frames as pauses -- looking at the code, it may be possible to regain the time lost to these added frames by using pauses to let stuff decompress while the game is paused (but I need to check whether or not it will help at all... only one of the decompression methods allow decompression during pauses, and I think that the other one is used to detect when the transintion is complete, so it might make no difference).
marzojr wrote:
Note that this only counts frames where the game reads inputs, as it's the only thing that microcontroller uses to advance frames.
Unfortunately, those are exactly the kinds of frames that are causing a problem for this platform. For what is worth, the next iteration of the TAS will not use this platform...
Edit: this came through as I wrote the reply:
notaz wrote:
I've tried messing with Sonic 2 and it seems to be a lost cause too. Inserting frames at the start of the level to attempt to manipulate boss panels affects all other objects too, so the move desyncs earlier.
You want to insert frames in the form of a pauses before the 17th second: specifically, before the tipping floor objects are loaded. The number of frames in pauses is more annoying: it can be up to 255 frames... yes, those platforms are one of those annoying things in S2. It may be possible to reduce the amount of work in this case if the approximate difference in v-int run count between emulator and console can be inferred; it may be possible to do that from the video, actually, but I'd need a 60 fps video to compare frame by frame with the run.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
FYI, Sonic 2 actually does not generally load any more stuff mid-level than Sonic 1 does; the exception being Tails and his tails, and some levels having more animated tiles than S1 levels do (but this is always uncompressed art which is just transferred through DMA). S3 and S&K actually load a load more stuff (including decompressing art) a lot of time. Both of the decompression methods used in S3 and S&K are designed to work across multiple frames, but one of them can cause lag on occasion (this one is also used in S1 and S2 to load boss art, capsule and animal art, score tally art, and some art at the start of the level). Either of them can cause some drifting of computation because of something important: not all instruction latencies are correctly emulated by Gens (or Regen, or Kega) because they are based on official Motorola manuals that have since been proven incorrect for some instructions. This can make the resulting DMA transfers to be off by one or more frames, which can further throw off the timing of future decompression and DMAs.
Moreover, Gens also does not emulate other things that are important for timing, such as bus contention (for example, with the z80) -- and even if it did, it would probably be off, as the exact timings are still unknown (but under research). Kega does not fare not much better as far as the z80 goes, because it does not emulate bus requests (which, ironically, Gens does), and this is disastrously bad for S3 and S&K runs because of the way that the driver works.
But that is not all bad news -- the Sonic games tend to be resilient to these timing innacuracies. This is because each zone (S3 and S&K) or act (S1 or S2) is generally independent of each other, with very little information carrying on from one zone/act into subsequent zones/acts. The games also not only tends to use little in the way of randomness, going as far as resetting the PRNG seed at the start of each act (zone in S3 and S&K). Each level has its own unique "universal timer", which is the number of non-lag frames that elapsed from the start of the zone/act, and a set of oscillating numbers that, well, oscillate from the start of the zone/act. And all of this is reset when a zone/act starts, so only in-level delays affect them.
There are a few things that do carry over, and they are annoying. One example are the swinging vines in Angel Island in S3: they run based on the number of frames spent on levels -- any levels -- and is only reset when you do a hard reset.
The other main thing that carries on is what is incorrectly called the "universal timer": the vertical interrupt handler run counter. This counter is incremented whenever the vertical interrupt handler is called, which is once per frame; but this does not happen when display is disabled (for example, because there is a lot of data that is going to be transferred to VRAM by DMA, generally only at the start of levels or when changing game modes) or because interrupts in general, or v-int in particular, are disabled (the latter never happens in unhacked Sonic games after initial boot). In a way, it is the number of frames since power on, except for those frames (lag and non-lag) that were never generated because the VDP wasn't generating the v-int signal.
This counter is used as a weak source of entropy:
Its low bits are used to determine if an event will occur: these event may or may not use the full PRNG for details. Examples: signpost sparkles in S3/S&K (uses PRNG), explosions from bosses in all games (uses PRNG), animals coming from capsules (uses PRNG), starting state of Chemical Plant tipping pipe sections (does not use PRNG), starting state of Wing Fortress platforms (does not use PRNG), and many others.
Directly as a source of entropy: in Sky Sanctuary, the boss reseeds the PRNG using the v-int run counter directly.
(1) is bad because it can throw off the PRNG, and will complicate luck manipulation; but it is not that bad because you generally have to waste less time in pauses to fix the issue (with the exception of the Wing Fortress platforms, where you may have to wait up to 240 frames). (2) is exceptionally bad because you need to either infer what value it currently has, or use progressively longer pauses until you have a sequence of PRNG values that match the result of the TAS.
Other than different timings leading to possible additional lag frames, the v-int run counter is the major source of desynchs in S2, S3 and S&K. It is very important in S1 too, but S1 engine has a lot of additional lag to deal with which make it arguably as important as the v-int run counter.
But where the bad news come is here: that platform is based on the oscillating numbers I mentioned. They do not run when the game is paused. They should be cycling once per (non-lag) frame from the first frame of the zone until the current moment: the function is called only in one place in the entirety of S3&K code, in the main level loop, and before the loop, the numbers are reset to a default state. The function that resets the state of these numbers is also only ever called once in the entirety of S3&K. The function that updates them is called right before the function that updates the ring animation frame, which means they both got called at a different frequency on console than they did on emulator (whether they were more or less frequently called is hard to say with a single screenshot). I am at a loss to explain this difference in frequency, considering these functions should have been called once per non-lag frame.
Hm. How many waiting frames (if any) did you have to add to the flame transition?
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
(not that there was much choice when people started doing Genesis TASes, if only at least Fusion was open source..).
I noticed this bit in your last reply. While it is true that Fusion is generally more accurate than Gens, it is nowhere near perfect and it does not emulate lots of things that woule be needed for a run to synch. Regen would be a better bet, as it is more accurate, but even it is not accurate enough. For example, neither of them emulate the z80 competing with the 68k for bus access, neither of them emulate the z80 being stopped during DMA when accessing 68k space, and a few other things. Some more info: http://sonicresearch.org/forums/index.php?showtopic=1335&p=38684 (interestingly, there is a quirk with z80 busreq that is correctly emulated on Gens but not on Kega that can lock up a real Genesis on some rare cases).
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
I would like to avoid a loader, but maybe it won't be possible. I was going to work on a reset circuit which would reset everything when the clock dividers were in phase to fix this issue.
Oh, I had forgotten to reply to this on my previous post: I had asked around about resets some time ago (for an issue in Gens), and what I got was this (reposting from the issue):
marzojr wrote:
Here is some information on soft resets I got from talking to Tiido/TmEE:
TmEE wrote:
The general process is that reset button goes to some ASIC where the signal is debounced and the ASIC will spit out the real reset signal (VRES).
There's also the Power On Reset (MRES, SRES) signal that does initial reset, that one also resets the VDP and IO chip, and is also fed to MegaCD in inverted form (FRES). MegaCD will not see further resets from MD side.
32X sees both SRES and VRES. The 32X generates its own power on reset and it overrides SRES on MD side, so 32X can extend power on reset until its own is ready, ensuring proper operation. 32X does react to VRES too, but what exctly happens I don't know.
I have not done a whole lot with 32X and done nothing with MCD as far as programming goes.
He gave me some links, one to a forum thread (http://gendev.spritesmind.net/forum/viewtopic.php?t=1262) and several for chip schematics.
The thread lists the time that VRES stays asserted and that there is an additional signal (ZRES) that is asserted at the same time as VRES and goes to the z80 and the ym2612. ZRES does not get deasserted on its own; the 68k needs to deassert it after the reset.
In a nutshell, for a soft reset:
* for plain Genesis: VRES is fed to 68000 for 128 VCLKs (16.7us); ZRES is fed to the z80 and ym2612, and remains asserted until the 68000 does something to deassert it; VDP and IO chip are unaffected.
* for Sega CD: soft resets reset only the Genesis side, as above, except for the initial power-on reset.
* for 32X, there is little information as far as soft resets go.
Researching based on this information, I came up with:
From the M68000UM.PDF document, the reset loads the longword at $000000 into the supervisor stack pointer, then reads the longword at $000004 into PC, then initializes the interrupt level in the status register to 7. No other registers are affected by a reset.
From the Z80UM.PDF document, a reset clears the interrupt enable, PC and registers I and R, then sets interrupt status to mode 0.
I couldn't find any solid information on the behavior of the ym2612 under reset, except for "System reset, initialize registers".
So no, neither the VDP nor the IO chip care about soft resets.
In fact, Sega's default initialization code even relies on this behavior from the IO chip: it uses the IO chip's state to determine if this is a soft or a hard reset, and sets the Genesis to a known state by clearing everything on the latter case.
Sega's default initialization code also accounts for the VDP's behavior by having an apparently useless read from the VDP control port: this is meant to clear the internal write-pending flag in the VDP. I would wager that it is this, not DMA, which causes issues in homebrew: the VDP will be expecting the second half of a command longword to trigger a DMA operation, and anything written to it will fit the bill. I would wager it is this because whenever the VDP is doing DMA from 68k to the VDP, it disconnects the 68k from the bus; any access by the 68k to its addressing space (say, fetching an instruction, or fetching the reset vector from ROM) causes it to lock up until the DMA is done. So a DMA that persists across reset must finish before the 68k proceeds (it is only on DMA copy and DMA fill that the 68k can go on).
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
There are of course exceptions like Sonic, which is very forgiving to wrong timing,
Indeed, the Sonic games are forgiving enough that their runs can all probably be synched in hardware by adding or removing enough delays to compensate for lag differences, maybe adding occasional pauses. Even the animal manipulation (and other similar luck manipulation) can probably be made to work in this manner. It would be an ungrateful process, but it would be doable.
The synch process would go about much more smoothly, and would be much less painful, if there was a way to read some values from RAM near desynch points.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
notaz wrote:
Also looking down at the end of Labyrinth 2 is playing with fire and actually crashes the game on real hardware, but replacing 2 last frames of pressing down with nothing resolves the issue.
Yeah, there is a race condition in the game that causes this. It is harder to trigger on Gens as it does not perfectly emulate the hardware timing, but it is doable.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
If it helps in any way, there is a new any% run for S3&K on the way which would probably swipe back the star once published; I just have to finish the Doomsday zone of the accompanying newgame+ update.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
This. It was the first TAS I ever saw, shown to me by a colleague. By then, it had already been obsoleted twice; he had shown me an encode, and my colleague wasn't aware of TASVideos himself. After I discovered TASVideos, and I found out it was made in frame advance, my thoughts were along the lines of "hey, I can do that too!".
After getting Gens rerecording and half an hour later, I came to the conclusion that no, I could not; at least, not yet. So I decided to start with something easier. The second TAS I saw was this one, and I was already aware of the Tails in Sonic 1 hack; so I decided to try it, as Sonic 1 is a lot simpler, even as Tails, than S3&K. The rest shows up on the forum history.
Edit: Huh; links show up even in spoiler tags. CSS error, maybe?
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
Breaking Scrap Brain Zone 3 even more with Tails:
Link to video
It is also possible with Knuckles, and he is probably faster than Tails. Sonic, however, can't do it as this trick requires spindash speeds.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
Yeah, I really need to fix that game resources page, the innacuracies and weasel words are too grating to me now.
Anyways: when you are rolling and you jump, you have no horizontal control. Meaning the aerial speed cap is irrelevant after a rolling jump (spindash and jump also counts). In Sonic 1, the ground speed cap is also irrelevant when you are rolling because you can't accelerate when rolling (except for slope-based acceleration).
When you roll out of a legde, the aerial speed cap is relevant because you didn't jump from a rolling state. Likewise, jumping from a running state, running off ledges, or hitting springs that launch you up also make you susceptible to the aerial speed cap.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
creaothceann wrote:
I don't really understand how the signal encoding works, but afaik a console can have faster or slower pixel clocks.
Indeed, the difference between H40 and H32 modes in the Genesis is the VDP's clock — it is slower in H32 mode, using the same frequency as the SMS and the NES.
creaothceann wrote:
So even if we know that it outputs 256 pixels per line, they may be a bit compressed or stretched compared to "regular" pixels - and theoretically this area may be placed anywhere depending on when the console starts outputting the pixels.
These consoles don't output 256 pixels per line — they output 288 pixels per line, of which 256 are the game image. In a TV with little or no overscan, the 288-pixel active image would be stretched across the TV set. But because real TVs have overscan, part of this is hidden; this led TV broadcasters and console devs used less of the active image for content to make sure everything important was visible (this happened with lines too).
The game image is ideally as centered as possible in the active image to make sure it isn't clipped to the left or to the right (or top and bottom).
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
Performance = emulation accuracy is overrated, you want the game to play fast and be responsive.
Stability = emulation should be as accurate as possible without going overboard and slowing the thing down to a crawl.
Accuracy = emulation should be as accurate as possible, and speed be damned; there will be faster computers in a nearby future, and perfect accuracy is paramount (say, for archival purposes).
Casual gaming = you play sometimes for your own amusement; you just want the thing to play well. If something happens differently in the emulator and on console, you probably won't notice.
Longplay = you want to make a video showing as much of a game as possible (probably aiming for 100% completion), and you want the emulator to be accurate without sacrificing speed. Ideally, anything you show would be possible to do on console, and since you are unlikely to exploit any glitches, this is enough.
Tool-Assisted Speedrun = you want to bring the game down to its knees and make it cry for mercy; speed of emulation is irrelevant, since you will be working on frame advance anyway. You want as much accuracy as possible to make sure that the game breaking bugs you use are not due to inaccurate or buggy emulation.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
TD;DR: Yes, the NES has borders; the above discussion talked about SMS too much, but what it says is common to ALL consoles intended for CRTs. And an image is not stretched to fit a CRT except horizontally.
The long version: I will try to explain this in a different way that will hopefully make it clear why. I will again focus on NTSC; NTSC, PAL and SECAM differ in details (such as number of lines, or number of frames per second), but their workings are the same. I will not make the mistake of focusing on any given console, TV, video recorder or anything else to avoid confusing the issue even more.
NTSC has 525 lines; no more, no less. These are split into two 262.5-line fields (or 262-line fields, for progressive display, as in consoles) which are drawn alternatively to the even rows and odd rows (progressive display uses the same set of rows always). The field rate is 60 Hz for black & white, or 60/1.001 for color signals (due to the added requirement in terms of bandwidth, as well as for backwards compatibility with older TVs). For interlaced display, this means one 525-line image per frame at 30/1.001 Hz, for progressive display this is a 262-line image per "frame" at 60/1.001 Hz. I will ignore interlaced displays from now on because they are generally irrelevant for consoles (but Sonic 2 2p mode says hi).
Of the 262 lines in progressive display in NTSC, 243 make up the active display; the rest are used for vertical retrace of the electron beams. Thus your video must output 243 lines per field, and 19 lines' worth for the vertical blanking. If it outputs any less, the video will roll over. Thus, ANY console, VCR, or whatever that outputs NTSC signals needs to output 262 lines worth of video, of which 243 need to have actual image data (again, progressive display). Borders count as needing image data, as different CRTs have different overscan sizes; so the NES, too, has vertical borders.
Now comes the lines, also known as scanlines. First off, there is a fundamental difference between CRTs (for which NTSC, PAL and SECAM were developed for originally) and modern displays (LCDs, plasma, etc): while CRTs have a discrete number of scanlines, a scanline in a CRT is controlled by an analog signal. This means that it technically has infinite resolution, if you can manage to generate a signal fast enough; but in truth, the signal will most likely wash out the details if it is too fast, and may not even work with most older TVs and cables. Put in other words, a "pixel" is whatever width your analog video signal makes it. This is usually incorrectly referred to "stretching" or "extending" the image.
The signal used to generate the center image in the NES, SMD, SNES and H32 Genesis is around 5.37 MHz signal; if you do the math, this means about* 341 "pixels" per scanline; of these, 288 "pixels" are in the active region (the rest are for horizontal retrace of the electron beams, and are in overscan). Thus, anything that generates a signal with that frequency will have to generate 341 "pixels" of signal, 288 of which compose the active image. Since a NES image is 256 pixels wide, it needs to generate a border to fill the image region (this is required because of the frequency of the generated signal); so the NES, too, has horizontal borders.
As I mentioned above, overscan varies by TVs, and even as the set ages; this applies for scanlines too. The blanking part is always in overscan; but part of the active image data is likely to also be on overscan. Consoles used a "safe" region of the active image that comprised about either 80% or 90% in vertical and horizontal ranges. This changed over time as TVs were better manufactured and more powerful consoles were made.
* Result depends on really high precision numbers and some rounding, so results may vary depending on which numbers you use
Edit: And for what is worth, I am taking a class on digital processing of sound and video that covers a lot of stuff.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
feos wrote:
tl;dr:
We need SMS emulator video output fixed, to add those borders.
Strictly speaking, the same would be true for NES, SNES, Genesis, and so on; they are all technically wrong if they don't generate the borders, then have the image stretched to 4:3. It is just worse for the SMS because it uses less lines for the game than the others.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
creaothceann wrote:
[1] That last odd line isn't used by consoles in progressive mode and probably has very minimal impact on aspect ratio calculations.
That last odd line is quite literally the difference between progressive and interlaced modes: if you draw 262.5 lines every frame, hblank will start in the middle of a line every other half frame; thus, every other frame will be shifted down by one line, meaning you alternate between drawing the even and odd lines. The half-lines end up in the overscan area, so they aren't visible.
Progressive mode simply doesn't use that line (so it draws 262 lines every frame), so that the new image is drawn on the same lines as the previous image, replacing it instead of complementing it. So yeah, the last line is irrelevant in progressive mode.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
Warp wrote:
So the SMS stretched the 256x192 screen image into a non-4:3 aspect ratio (even though TV was 4:3)? So it did like a 4:3 -> 16:9 aspect ratio stretch (leaving the upper and lower borders of the TV empty)?
Lets start over; for simplicity, I will focus on NTSC and the SMS.
A (progressive) frame in NTSC has 262 lines; if a video game generated any less, the image would roll over as time passes. Of these 262 lines, 243 are "active" lines, meaning they are (potentially) visible on-screen. The remainder of the lines do not need to be generated (but the time they take must be accounted for; they make up the vblank interval, the time during which the electron guns are re-positioned to the top left of the screen).
Of these 243 active lines, the SMS uses 192 for the active game area (possibly to compensate for overscan). This means that a image with 192 lines needs 51 lines of border; the SMS generally does 27 lines at the top and the remaining 24 lines at the bottom. This is filled with the backdrop color, which may change along the way (see California Games screenshot for example).
The SMS also generates 284 pixels per line, of which 256 are the (potentially) visible pixels (also due to overscan); the remainder are also border pixels, filled with backdrop color; these are distributed as 13 to the left and 15 to the right. For reference, the full NTSC line length is equivalent to 342 SMS pixels; the "missing" 58 pixels are not generated, and they represent the time taken by the electron guns to re-position for the next line (hblank interval).
So the real image generated by the SMS is 284x243 in resolution. THIS is what has to be scaled to 4:3 aspect ratio (borders and all). You can then crop the borders a bit (keeping the 4:3 aspect ratio), since old CRTs did that to varying degrees (this is called overscan). Generating a 256x192 image is wrong, and scaling that to 4:3, or 16:9 or 16:10 or whatever is also wrong. And while you can scale the 256x192 image in such a way that the correct aspect ratio is achieved, you will miss out on the border color -- some games actively used this, even changing the backdrop color midway.
And one last thing: this scaling is done implicitly by the CRT: the exact timings of the generated video signal determine when the CRT will draw each pixel, and for how long. The video signal generated by the SMS is such that the 284 pixels generated each line take up the whole (active) NTSC line, so the pixels get stretched horizontally. So the only way in which it can be said that the SMS is doing the stretching is by giving a "too slow" video signal per line.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
Warp wrote:
I honestly find this a bit baffling. What exactly is the problem in explaining it? I believe I asked pretty simple questions. It's not like it's rocket science or something.
The issue is that CRTs have a fixed number of lines (how many depend on the standard), but they have no defined number of columns: depending on how fast your signal is, you will generate more or less pixels per line, but a line will always have the same size (with the pixels being stretched or compressed, depending on your signal speed). An example for the sake of clarity: in the Genesis, both the H40 mode (320 pixels/line) and H32 (256 pixels/line) will result in lines of the same length in a real CRT, with the result that the latter mode will have longer, nonsquare, pixels.
In the case of the SMS, this also happens (and for the NES, and so on); so leaving the image at 256x192 ("a nice 4:3" as you put it) results in incorrect aspect ratio because a real CRT will have nonsquare pixels in this case.
Experienced Forum User, Published Author, Experienced player
(758)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
TheYogWog wrote:
This brings up a good point I've been meaning to discuss, basically all of my ST movies right now begin from a "dirty" save state. What do I mean by this? Well, what I did to gain access to NG+ mode was to play back Marzojr's verification video in its entirety, then paused Gens at some point on the menu screen before his actual TAS began. From there, I may or may not have unpaused Gens and idled a while before again pausing and creating the "dirty" savestate that I use as the basis for all my ST movies currently. I would really like to establish a clean state to start all future NG+ST movies from, so I know that any movies starting from there could theoretically be acceptable for publication here. Could anyone please help explain how to do that? I have some ideas but I'm not sure I'd be doing it right, and I'd like to be as sure as possible, please.
In the submission notes of my newgame+ run I describe a procedure I developed to make the cleanest state possible; you may want to either use that save or generate a new one based on that procedure. The state is clean enough that the movie synchs if you hex-edit the movie to eliminate the savestate dependency and play it using the "dirty" SRAM.