New Demo - Sonic Green Hill Zone simulation on X16

Chat about anything CX16 related that doesn't fit elsewhere
User avatar
AndyMt
Posts: 326
Joined: Sun Jun 21, 2020 3:02 pm
Location: Switzerland

New Demo - Sonic Green Hill Zone simulation on X16

Post by AndyMt »



On 10/18/2021 at 11:59 PM, ZeroByte said:




EDIT: Yeah, that makes it run. Still no sound though, even if I un-click the mute icon. Strange.



The web based emulator has a white list for file extensions. The music files have to use the .BIN file extension, too.

I think allowed is only .PRG and .BIN, maybe .SEQ, don't remember.

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

New Demo - Sonic Green Hill Zone simulation on X16

Post by ZeroByte »


I'll have to try that.

That fixed it. Thanks!

john_e79
Posts: 22
Joined: Thu Aug 26, 2021 6:31 am

New Demo - Sonic Green Hill Zone simulation on X16

Post by john_e79 »



On 10/18/2021 at 11:02 PM, ZeroByte said:




The Background actually has 17 layers of scrolling. The clouds/tall mountains are the main BG scroll value. I created a table of 16 raster line values and the demo cycles through these, setting each one as the next line IRQ to trigger on.



When the main loop begins, it creates a table of scroll offsets based on the main BG's scroll value (which is 1/8 the FG scroll value). It divides BG scroll by 2 to create a "per line scroll amount" (delta). On each raster IRQ, the BG scroll is incremented by delta. After 16 iterations, the bottom row of water ripples will be scrolled at the same amount as the FG (this happens below the path, so you don't see it scrolling at the same speed as the FG though). All values (FG, BG, and per-rasterline) also keep a subpixel scroll amount, so the speed is very flexible - as low as 1/16 of a pixel per frame (FG scroll). This subpixel scroll amount is maintained through the creation of the 16 raster scroll values as well in order to keep it nice and smooth.



I did cheat for Sonic's Y coordinate though. The tile set is arranged very erratically. I'm convinced there must be meta-data in the tile numbers to indicate things like "vertical offset" that I'm just not seeing - and making a table of varying terrain heights from tile IDs was crazy, and required a linear search through the table, just to determine something as simple as how high Sonic is with the ground. So since the BG is fixed and repeating, I just fudged and made a "per column" table by hand and have the game cycle through that table with every 8px of scrolling performed. It works for this demo, but if I were to have more varied terrain or vertical scrolling for things like jumping or higher platforms, I'd have to do a lot more work to make Sonic properly collide with tiles. Not necessary here, so I took the path of least resistance. ?



 



This is really neat. I was just wondering what you might do though if you wanted to make the real game or a game like it, and you need Sonic to jump on a trampoline. Wouldn't that mean updating your IRQ table on every frame then, and skipping values that are temporarily off-screen? I was also wondering how vertical parallax might be accomplished.

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

New Demo - Sonic Green Hill Zone simulation on X16

Post by ZeroByte »



On 10/25/2021 at 1:02 AM, john_e79 said:




Wouldn't that mean updating your IRQ table on every frame then, and skipping values that are temporarily off-screen?



It already has to update on every frame anyway. At least it does with the method I'm using to calculate the per-raster scroll values. I've had exatly 0.0000 experience with parallax scrolling prior to this demo, so I was really experimenting a lot to find a mix of values that looked close enough to the original game.



Calculating the scroll values:

One of the tasks in the main loop is to calculate all scroll values (jsr doscroll)

I use 16.8 fixed point values for FG and BG scroll amounts, and 4.4 fixed point for sonic_speed. This gives a lot of flexibility in scroll amounts: 1/256 pixel scrolling resolution, and speed can be 1/16 pixel-per-frame up to ~16 pixels per frame. If I needed higher max or lower subpixel speed resolution, I'd just use 8.8 fixed point for speed.

FG scroll is easy:

FG_scroll += sonic_speed.

BG_scroll is just FG_scroll / 8 ( i.e. right-shift 3 times)

The raster calculations:

The BG scroll value becomes the baseline - if I want 16 divisions to reach the FG scroll value, I just right-shift BG_scroll one more time to obtain "delta" - and then increment scroll amount by delta 16 times, each value going into the raster scroll values table. This was where I did a lot of noodling around with the method because I've never done anything with even so much as simple multi-layer scrolling, let alone a smooth pseudo-3d effect like this. Long story short, since the hscroll is being increased linearly, the spacing of the raster IRQs should be linear as well in order to look continuous (as I've determined from experimenting - I didn't read any papers on the subject or anything - what's the fun in that?)



I did a little experimentation to find the exact raster lines to use for the IRQ triggers and put those into another table.

The IRQ handler itself:

The line IRQ simply reads the h_scroll amount from the current row of the table, writes it to VERA, updates the pointer, reads the next raster line number from the rasterlines table, and writes that into the LINE_IRQ register(s) of VERA.

Finally, it acks the IRQ, and exits. (using ply plx pla rti, NOT a jump into the Kernal - that's for VSYNC to do)

 

How would vertical scrolling affect this?

It depends on how far down the rabbit hole you want to go. The original game does not scroll the BG vertically on Green Hill Zone. It may LOOK like it does, but it's an illusion - the fact that it doesn't scroll vertically used to bother me when I first played the game back in the day. I always thought it did scroll but only very slowly - no it doesn't budge as far as I could see while observing for this project. Therefore, for an actual Sonic game engine, all it would need to do is make sure the water effect looks good all the way to the bottom of displayable screen, and you're done. Just update the actual tile content of the BG layer for more variety as you travel along....



But if you DID want to scroll vertically as well, you can do all kinds of things. Since the raster lines themselves are dictated by a table, you could easily update that table to account for vertical scrolling of the BG layer while computing the h_scroll amounts. In fact, it might work well enough to just keep a static table and use a "delta-y" variable that gets added in by the raster IRQ handler as it updates the LINE IRQ setting in VERA.

If you wanted to get ULTRA-fancy, and simulate a varying camera perspective on the pseudo-3d surface, you'd want to gradually increase the spacing between raster lines as the "camera" moves up (and the BG scrolls down) and crunch them together more as the "camera" goes down (and the BG scrolls up). This would totally not be worth doing on the water in GHZ because it's a very noisy paittern that's also undergoing palette rotation - your eye would not really pick up the subtle difference this makes with such a noisy pattern, but if it were something more akin to the floors in Street Fighter II, then that's how you'd do it.

 

Post Reply