A 16-bit fantasy console with mode 7, parallax, etc.

posted in Brunni
Published February 14, 2019
Advertisement

Brief presentation and history

As I was developing some small arcade-style games for my portfolio, I missed the fun of old-school graphics architectures, like the ability to easily deform the screen, recolor objects at runtime, etc. It turns out that developing this kind of raster effects is not easy at all. After all, I spent more than two years to develop this clone of Outrun called Highway Runners (link):

sc552x414.jpeg.5c3fa30fd795ecd79a0c377f636d2aca.jpeg

So I set myself to create a simple engine for these effects. Since I'm a huge fan of the arcade boards of the late 80s, I took this model: what if we still made this graphics architecture nowadays? Arcade machines of the time were often overpowered and sometimes required games to come with their own CPU, so what if we could just plug in modern CPU/memory and power the board with modern games?

Technical decisions

  • Since I wanted to make the games to be easy to share, I chose after some deliberation to go with Javascript. Although I would have loved other choices like Lua, mainly in order to be able to restrict the VM, I found Javascript to be much more fun to play with when hacking around with my API, plus it would save a lot of development time and would still be portable in case needed.
  • I wanted the game to load instantly, just like a ROM image, and have a simple programming model with named graphic data, something like `drawObject('mario', x, y)`, or `drawObject('mario', x, y, { palette: 'luigi'})`. So I made an architecture with multiple ROM areas (one for Palette, one for Sprite and one for Tilemap) which contains all graphics pre-baked at ROM build time.
    • Furthermore the graphics memory would all be accessible for read and write (for instance replace colors on the fly, swap tiles or sprites with others to animate the whole screen, add/remove objects in tilemaps).
  • Since it runs on the web, I wanted competitive space usage. For that I'd simply use PNG images for resources and putting indexed color data in the RGBA components. PNG are compressed as a variant of ZIP, thus providing additional compression for the whole ROM for free.
  • It should run entirely on the GPU through shaders (i.e. not drawing tile by tile, but one BG/sprite = one poly).
  • The additional step of building the ROM images could be cumbersome, but it was not avoidable if you wanted to define which hardware palettes were associated with what graphics (you don't want to create one palette per sprite, else you lose many of the advantages of indexed colors), and also for many advanced ideas, so I made the best of this; furthermore this can be implemented as a process that watches for any changes in the graphics directory and rebuilds the ROM + transpiles JS files instantly when needed.

Initially I went with limitations off-the-roof; the idea was:

  • "Infinite" full-screen BG layers with matrix transformation (baseline: 8 of them)
  • "Infinite" sprites of any size, as freely deformable quads (similar to the Sega Saturn), further transformable as a whole plane (initial tests showed that I could draw quite more of them than Pixi).
  • 4 or 8 bits per pixel (256 colors)
  • 32 bits RGBA master palette entries
  • 2048x2048 sprite data and map data textures (up to 16384x2048 sprite pixels, 4096x2048 map cells), 256x256 palette data (65536 colors).
  • BG layers can scroll, be splitted horizontally or vertically, scaled/rotated per line.

This architecture proved to be extremely powerful, but there was one catch: it just wasn't fun at all to make games with. After all, why bother with parallax when you can just overlay an infinite number of sprites or tilemaps? Why even bother with tilemaps, with palettes? And when do you know when your game is inefficient, when it might not run on some mobile devices? Good practices are not inferred through the API at all. There's not even stylistic guidelines, like 8 bit frameworks give you (simple colors, animations, avoid over-crowding the screen, etc.), you feel just as lost as with Unity, and it's not even as powerful. What I wanted deep within was to give people a glance at the fun of developing games in the 80s, and also a playful opportunity to learn.

Enter the FANTASY ZONE CONSOLE

It was clear, I needed to think about limitations. This framework wouldn't be for everyone, but what it was targeted at should be great. I'm living in Tokyo and know well the author of Pico8, who coined the term of "fantasy console". Since my original models were such as Sega System 16, Outrun hardware, Namco System 24, etc. I chose to go with 2 BG layers only, 256 sprites covering up to once the screen, add transparency effects but with no overlay support and only one effect for the whole scene. And see what I could do from there.

I would say that the most difficult task of the project in the end was to decide and experiment with these limitations. I've noticed that many people who make frameworks have problems defining it right for users because they only use it for one of their projects (usually a big one), or because they use graphics from existing games for their tests. I realized that I was guilty of all that too, and it's only when I started creating small games on my own (after all, if my framework is as simple and fun to use as I say, I should want to make loads of games with it!) that I realized that the human constraints for making graphics, code and music/sfx in 2019 are pretty different than that of 1980s. As much as you'd love animating the graphics of Castle Of Illusion, you will find yourself at trouble trying to draw something of similar quality! Therefore the framework should not be made to be used primarily with such graphics, but likely some simpler, lower resolution ones. And limitations should be there to guide you, prevent you from overworking the graphics, but rather instead toy with them in the code for instance.

The initial target as far as game styles go are:

  • Racing games (both Outrun "raster" or F-Zero "mode 7" style)
  • Platformers
  • Space shooters

I'm currently making a "top-view" platformer with it (pseudo-3D with the shadow on the ground to guide the player), I'll show a first demo soon.

Try it?

I'll continue with other blog posts about development, and especially what those constraints ended up to become exactly, but I've already got online a first version with some demos. It runs directly in modern browsers, although I know that there are some remaining issues on some browsers.

https://brunni132.github.io/vdp16-samples/

vdp-16-2.gifvdp-16-3.gif

Try it and let me know what you think :) any feedback is extremely valuable!

Previous Entry Spring physics
4 likes 3 comments

Comments

jbadams

Very cool, thanks for sharing!  Love this limited old-school development experiences, I'll have to give it a go sometime! :)

February 14, 2019 04:46 AM
Brunni

Thanks a lot for your feedback :) if you want to try let me know (I plan to release it shortly but I already have a working version) ;)

February 14, 2019 12:31 PM
arnero

Oldschool = racing the beam. Scanline rendering like  render man  but in real time. Instead of low frame rates one gets flickering.

Outrun uses this for the the road. Unfortunately MAME tells me that outrun draws the sprites to a frame buffer. Frankly, with 256 sprites on screen and on a straight section almost 256 sprites on a scanline this may be the better way.

Still I would dig old-school Outrun. 2 or 3 layers (with cyclic-z) for the waves and fields. Only some large sprites at the road ( let's say: max 16 Sprites per scanline. More like Hang-On. Hang-On front with Outrun background.

Also without a frame-buffer horizontal resolution can be higher than vertical. Sprite-X comparators have been quite fast for some time.

Also I like mode-7 and the sprite rotation on the GBA. Turrican or Sonic with real-time rotation of the avatar. Outrun with roll. Do sprites in after-burner flicker? Background-based ground in after-burner would be cool. 3 BG per scanline would need to nice thinning.

Outrun hardware could render two streets. So I could imagine a mode 7 for the street: Textured polys for the street and border, max 2 polys on one scan line, BG for the scenery.

Mario-Kart with real sprite scaling. Why SNES could not do it, I do not know. Genesis can tilt the background slightly but could not afford die area for scaling (+rotation). I do not grasp.

Also BG means: Character-based. Sprite means: Chunked bitmap graphics ( like on C64 ). While gate count was limited on NES and C64 there is no reason why the 16-bit computers could not render front to back, fetch on the fly and FiFO to smooth out the timing. Each character layer needs a cache to store the chars between scan lines (an reload on bad-line). Likewise a rota-zoom sprite reuses pixel data on the next line, so may not be able to be as large and hires.

z-ordered transparency is no problem: We do not use z-buffer, but have all z at every pixel. Of course, front to back rendering cannot cull anymore and opacity may just be forced by the empty FiFO.

Mode-7 on SNES is so brute force without any caching or chunks. I do not like. I would like characters to flicker away if the get smaller than 8px width (with 640px horizontal). 

When using rota-zoomer to do affine texture mapping on simple  Elite like space ships  shading (light/dark) may be important.

February 17, 2019 10:13 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement