Original Post

FORWARD: The forum system shrinks images. Click them for the full-size versions.
__________

It’s baffling, really. Perplexing. Curious, by anyone’s reckoning. I’m still not sure what all is going on, but I know that it’s in the way. That awesome project I’ve been working on? Virtual Boy can’t handle it. It’s too much for it to take!

You’ll remember my September progress report thread, wherein I mention a game yet don’t disclose its identity. The game was F-Zero Maximum Velocity, the first GBA game, and I aimed to remake it on Virtual Boy, because how cool would that be?

As mentioned, the project started out with a couple weeks of reverse-engineering. I hacked the GBA game to get its graphics and level data, which I then began implementing on Virtual Boy.

It was going quite well. A little scrolling here, a little affine there, a little optimizing over there… It all looked prettey good. Everything was taken from the GBA game, and care was taken to remain true to the original:

* All of the graphics came from the GBA game and were modified to work on Virtual Boy
* Palette animations on GBA weren’t possible, so an equivalent solution on VB was used
* The GBA game used two affine layers, but I used one on the VB project and got it working pretty well, even so far as to have the same scrolling graphics the game had beneath the track
* All graphical animations from the tracks were implemented, including all course features and the stuff off to the sides.
* As it’s on Virtual Boy, parallax was added for a depth effect, as seen in the screenshots.

As mentioned, the GBA game uses two affine layers, and I managed to get away with just one. The “floor”, as I call it, is the same size pixel-for-pixel as the track layer, but it scrolls at a slower rate and therefore extends off to the sides of the track quite a ways. In order to achieve that effect, I had to modify the floor maps to fit on a bigger canvas.

I spent a good week making a program to help me do just that, and it worked great. The plan was to make an all-in-one utility which would be released alongside the game (source code for both) so people would get a taste of game development even without being a developer themselves. I specifically wrote it in Java so people would be able to play with the code. (-:

The utility was useful because it did three things:

* Loaded the GBA ROM for extracting and saving data
* Modified floor maps
* Processed image files to convert them to the VB character format

I painstakingly went through the course floors, increasing their size, and driving around the track in-game to make sure the floor features appeared in the correct spots relative to the edges of the track, so that it would still “feel” the same as in the GBA game. More time was spent on the floors than any other part of the project.

In the GBA game, the tracks and floors are both compressed. I mean, they represent 4096×4096-pixel images, so they can’t just be stored in ROM as-is. I had a grand plan for this utility. See, I would implement the same compression algorithm used in the GBA game (compressors are harder to write than decompressors), then implement a level editor. The data produced by the utility would be in the same format as, and therefore compatible with, the GBA game. Buuuut, that’ll have to wait for another time.

When I finished my compressor, I verified it was working correctly by running it on the track and floor data from the GBA ROM. It worked correctly, and quite well: my data was 10%-15% smaller than the source data I pulled right out of Nintendo’s game!

I implemented the horizon layers, and those worked just fine. It was surprising, ’cause I wasn’t sure if the VB could handle that much graphics stuff going on. Then I implemented the minimap, and that’s when it hit the fan.

That little guy in the bottom-left corner. It’s a 64×64-pixel BG map with a single OBJ sprite over the top of it to indicate your position. With that in there, the VIP entered overtime and the framerate dropped to 25 fps. “No problem,” I thought, “I must have been at the edge of its processing power with those horizon layers. I’ll just disable one of those and see what I can do later on to reduce the total number of pixels drawn.”

It didn’t work. Removing both horizon layers didn’t work. And this isn’t one of those “turn off the left/right display flags” kinds of dealies, I outright refrained from configuring windows for the horizon layers and it still didn’t work. There’s something about the fact that the minimap overlaps the affine window that just hits the VIP too hard.

I modified the program so I could resize the affine window, and… well, in order to get it to run full-speed again, the window had to be prohibitively small. It was simply an un-salvageable situation. I discussed matters with dasi, and now I’m posting this thread.

Consulting Mario’s Tennis for some insight, I found that the game was taking up a mere half of the available screen real estate. Well no wonder it could run at 50fps!

I still have two months to put together a Virtual Fall submission and sample project for devkitV810, so I’m not out of the race. I just have to start over. Again. (-:
__________

Attached to this post is a zip file the last build of this F-Zero project. Controls are as follows:

Left D-Pad Left/Right: “Steer”
A Button: Move forward
L Button/R Button: Change current course
Select Button: Toggle 3D/2D mode
Start Button: Toggle minimap
Right D-Pad: Adjust affine window size (left/up make it smaller)

It runs just fine in Mednafen, but on the hardware it’ll be at 25fps unless you disable the minimap.

This is not a Virtual Fall submission. This is just letting you guys know what I was working on since I’m changing projects now.

20 Replies

This is really amazing. It is awesome that you are going to stick with it and try to get everything working. My Virtual Boy thanks you!

Lester Knight wrote:
It is awesome that you are going to stick with it and try to get everything working.

Wut? No. This is the exact opposite of what is going to happen. Sorry. (-:

It’s a classic case of Too Broke to Fix. The Virtual Boy’s affine functionality is just far too wimpy to pull off a game that relies on it like this.

Oh, I’m sorry. I got the impression that you were going to start over from scratch on the same project. =P

Phenomenal effort Guy! It’s a shame that the vb can’t do a game like this. So not even a black void on either side of the track could fix a game like this Ive noticed in VB games there’s usually alot of black in them that wouldn’t help out the VIP? also I wonder if you stuck the mini-map in the black void in the middle of the track. since the affine would’nt hit it maybe you could pull it off. Oh and also when the track hits the affine you could simply turn it off. Just an idea from a non programmer I just don’t want to see all of that wonderful work go to waste.

  • This reply was modified 10 years, 6 months ago by Morintari.

Cool demo, too bad it didn’t work out. I played around with the affine mode myself lately but I couldn’t get it to look the way I wanted.

Would you mind sharing the affine code/settings for the racing track?

thunderstruck wrote:
Would you mind sharing the affine code/settings for the racing track?

That’s akin to asking to see “the 3D code” for Faceball. (-: It’s not like it’s five lines of text that I can just paste into a forum post and call it good. There’s quite a bit of concept behind it, and the implementation isn’t trivial.

It’s something that’s better off for an article about perspective effects using affine windows.

What about using memcpy/blitting to manually draw the minimap to the framebuffers instead of using a world for it? Could that make it faster? You’d have to use a mask and AND/OR it in two steps to make it transparent of course.

I’m sure there are ways to make it work, but one of the goals of the project was to showcase libvue as a devkitV810 project. To get F-Zero the way I want it to be, it’ll have a lot of assembly optimizations and CPU rendering, which doesn’t make for a very good sample project since it’s going to be A) over the heads of most people who look at the source and B) fairly inflexible since it’s made for F-Zero and only F-Zero.

Though if anything, I’d rather offload the perspective viewport to the CPU for rendering and do all the 2D stuff with the VIP. VB’s affine feature is a joke not just in its poor processing capability, but the parallax setting is severely limited. If it can be done on the CPU, I’ll get the control I need to make it look the way I want.

Guy Perfect wrote:

thunderstruck wrote:
Would you mind sharing the affine code/settings for the racing track?

That’s akin to asking to see “the 3D code” for Faceball. (-: It’s not like it’s five lines of text that I can just paste into a forum post and call it good. There’s quite a bit of concept behind it, and the implementation isn’t trivial.

It’s something that’s better off for an article about perspective effects using affine windows.

I guessed it’s not that easy. I’ve experimented with the affine tilt demo DogP released in some thread. That one was about 20 lines or so.

I managed to tilt a bgmap and it looks okish after all. Still, the way your track looks like is what I was aiming for. I don’t wanted any movement or so. Just a bgmap titled so that it looks like a floor.

libgccvb and the tech scroll didn’t help me allot with this. I couldn’t find any demo (except for the affine tilt one) showing how this is supposed to work. I understand the basic principle of how the affine mode is supposed to work. I’m just having trouble getting around the math part.

thunderstruck wrote:

libgccvb and the tech scroll didn’t help me allot with this. I couldn’t find any demo (except for the affine tilt one) showing how this is supposed to work. I understand the basic principle of how the affine mode is supposed to work. I’m just having trouble getting around the math part.

Though the affine window can be used for a perspective effect, the specifics on how to use the affine window is a different matter entirely and depends wholly on how you code up your program. Scaling is the simplest transformation, though rotation isn’t too hard to grasp either. What you’re looking for is a form of projection, and you can’t just toss a couple of parameters to a function and make that work.

It doesn’t help that there are multiple ways to approach the problem. The way I did the perspective is just one way; it may not be the most flexible nor the fastest, but it’s flexible and fast enough for what I needed it to do.

Guy Perfect wrote:

Though the affine window can be used for a perspective effect, the specifics on how to use the affine window is a different matter entirely and depends wholly on how you code up your program. Scaling is the simplest transformation, though rotation isn’t too hard to grasp either. What you’re looking for is a form of projection, and you can’t just toss a couple of parameters to a function and make that work.

I actually throw a couple of parameters to a function to do the tilt but the result is not that great.

Guy Perfect wrote:
It doesn’t help that there are multiple ways to approach the problem. The way I did the perspective is just one way; it may not be the most flexible nor the fastest, but it’s flexible and fast enough for what I needed it to do.

Well, yeah… that’s the problem. My current way is not that great. Yours seemed to be better, that’s why I asked. I can understand that it is too complicated to write it into a forum post though.

Even though the project didn’t get finished this is a great effort! Props to you man for trying =D F-Zero was a killer idea.

Oh man, great idea. Sorry to hear it didn’t pan out. That said, I wouldn’t mind playing without a minimap… 🙂

jrronimo wrote:
That said, I wouldn’t mind playing without a minimap… 🙂

I hope you also wouldn’t mind playing without a boost indicator, timer, lap number, rank indicator, or any presence of your machine or other racers! (-:

Guy Perfect wrote:

jrronimo wrote:
That said, I wouldn’t mind playing without a minimap… 🙂

I hope you also wouldn’t mind playing without a boost indicator, timer, lap number, rank indicator, or any presence of your machine or other racers! (-:

Hmmm… that might make things a *little* more difficult… hahaha.

It would be a real shame for this project to get outright canned. Surely some compromises could be made? How about only the track is rendered, while everything else is black? Simpler textures? Is the affine window the only easy way to get the timer/boost indicator/minimap/etc to work? Does the game take on even more slowdown the more you add stuff to the affine window?

That said, I wouldn’t complain too much about a 25fps F-Zero.

SirGuntz wrote:

How about only the track is rendered, while everything else is black?

It’d be hard to see where you’re going. Drawing *anything* over the affine window spikes the rendering time.

SirGuntz wrote:

Simpler textures?

That’s not how the affine thing works. (-:

SirGuntz wrote:

Is the affine window the only easy way to get the timer/boost indicator/minimap/etc to work?

The affine window is responsible for displaying just the track.

SirGuntz wrote:

Does the game take on even more slowdown the more you add stuff to the affine window?

Presumably. I haven’t tried it because of the slowdown that already occurred.

SirGuntz wrote:

That said, I wouldn’t complain too much about a 25fps F-Zero.

Unfortunately, that doesn’t meet the project requirements. I’m not willing to do a 25fps F-Zero.

Oh well, that’s a really sad conclusion, the preview screens look amazing. 🙁

I know cost would be a huge issue, but would a grunt CPU on the cartridge board that could pre-render graphics help with keeping slowdown to a minimum? Or is the Virtual Boy not capable of that?

Custom rendering hardware in the cartridge would absolutely make it possible. The affine window can be replaced entirely by an ordinary character map, provided the characters were prepared in the cartridge ahead of time. It’d require the Y-match VIP interrupt to work (which Mednafen doesn’t implement), but it would work.

Maybe one of those flash cart developers will be nice enough to use a FPGA for their flash-y objectives, which could also act like a grunt CPU. 😉

Out of pure fantasy though, how hard would it be to implement a POV mode in VB F-Zero? I mean, if a grunt CPU could do status bars/etc with ease, surely covering the entire screen with the cockpit of a F-Zero machine wouldn’t be much more effort. 😛

Amazing effort either way on this project, it looks great, a shame the VB is incapable of the entire game. I wonder what your next project will be…

 

Write a reply

The forum ‘PVB Coding Competition 2013’ is closed to new topics and replies.