email sol follow sol wishlist Sol::News
^^^ That is an ad. Click here for other ways to support the site ^^^

Important note:

When linking to these pages, please use the URL: - it's permanent.

(1,0) (1,3) (-2,-1) (3,-1) (3,-3) (-2,-3)

Hunting Microspikes

January 30th, 2015 #

We've used Kahtoola Microspikes for some years now, and even bought some for some of our relatives. They are simply easiest way to survive in the slippery seasons in Finland, although you have to take them off whenever you go indoors (for example shopping). I've mentioned these on this blog before.

Now then, another relative of ours got interested in said spikes, so we promised to send a link to a local webstore that would sell them.. and couldn't find any. We did, however, find something oddly similar - "Snowline Chainsen Pro". I googled a bit and judged that these are probably some cheap knock-offs, but decided to dig a bit deeper.

The Kahtoola site lists patents. One of the patents describes the microspikes pretty clearly. The inventor is one "Jin-Hong Choi".

Snowline's CEO is one "MR. JIN-HONG CHOI". Interesting.

Googling even further I could find at least three separate websites for Snowline, with this one listing company history mentioning that in 2007 they "achieved export to American brand 'Kahtoola'." Other brands include "Mont-Bell", "Zamberlan", "Snake", "Koch Alpin", "Mt. DAX" and "Crazy Idea". Why their own brand is only now making headway internationally I have no idea.

So apparently Snowline is not a "cheap knockoff" like I first thought.

Speccy, Vol 7: SolarGun

January 23rd, 2015 #

As I mentioned in the previous blog post, I made a simple shmup for the zx spectrum. You can play it here on an online emulator (link depending on the online emulator and dropbox still existing, so if you're reading this on 2025, good luck on that). The .tap file that you can use with an emulator or actual hardware can be found here.

After I had decided to start working on a simple shmup, I went to IRC and said that I need name for a cheesy shmup, stat. Pekuja said SolarGun, which sounded good enough, so I ran with it.

To make the game I used pretty much all of the stuff I've built for the speccy so far - sprite routines, Image Spectrumizer for the logo, Mackarel to package the result. Code was compiled using SDCC (small device c compiler), along with z88dk, although I think the only part of z88dk I actually used is the .tap to .wav conversion to test with actual hardware.

For sound effects, I found a neat sfx editor called BeepFX by Shiru. Unfortunately even the shortest sound effects (by modern standards) were so long that they take more than a frame of rendering time. I reduced the couple of effects I used to a bare minimum, which is kinda sad, because the BeepFX is able to generate pretty nice sounds. Maybe for a turn based game? Hm.

Here's a video of some gameplay. I didn't try for a highscore =)

The game itself is pretty simple. Asteroids fly at you at increasing pace, shooting an asteroid gives you 10 points, dodging an asteroid gives you one point. You can sustain three asteroid hits with no problem, fourth one is game over time.

Back when I was doing first tests, I found that I could, basically, memcpy 64 scanlines worth of stuff to the screen in a frame (without doing anything else). That's 2kB of data. I've learned more efficient ways of moving stuff around since, but it's still a good yardstick (especially since the emulator I was using runs z80 code a bit too fast compared to actual speccy).

So since we can only copy 1/3 of the screen in a frame, double buffering is pretty much out. To make it look like we're scrolling a big image and have lots of sprites on the screen at the same time, I cheated a bit.

The game's logo (which took all of five minutes on Photoshop and Image Spectrumizer) takes 1/3 of the screen. The way I cheated with rendering, I could have used the whole screen, but this way the play area is 128 pixels high, which helped with the player's ship math (I could do 7.1 fixed point, basically).

The scrolling background is copied to the screen interlaced, 13 scanlines in a frame (so we draw the whole background every 10 frames or so). The enemy sprites are drawn once every three frames - or in other words, on each frame, we update 1/3 of the enemy sprites. The sprites are never cleared, instead the background draw takes care of that. This also creates a kind of motion blur effect on the sprites.

This also meant that I didn't need to worry about display beam racing. The sprites still blink just a little bit when they are written by CPU and read by ULA at the same time, but there's so much noise going on that you barely notice it.

Not only are the enemies drawn every third frame, their physics is also evaluated only on every third frame. This has the additional benefit of giving more accuracy to the movement - the enemies can move 1/3 of a pixel per frame without having to use fixed point math.

The player's ship - the focus point of player's attention - is drawn on every frame.

So in practise you're playing three separate games running at third of a full framerate at the same time, which is pretty convincingly 50Hz.

I timed things so that when you have the full set of sprites on screen we're still running at 50Hz, but whenever sound effect plays, it pushes the timing over the frame. The sound effects are pretty rare, though.

I use color attributes for a slight "vignette" effect, with darker colors on the edges. This is partially because I didn't want to handle sprite clipping with edges, and partially because otherwise things would have been (even more) monochromatic.

The attributes are also used for "explosions" (drawing a red blob around where an asteroid is cleared) and the player's shots. The player's gun is a slowly recharging mega-beam which slices through everything. There's probably a bug with the hit detection because the beam doesn't always wipe out asteroids it should.

Whenever either of those attribute effects are used, the next 16 frames are used to clear the attributes back to the original state, 1/16 at a time. This also creates the nice "blider" effect on the beam.

Gun charge meter and user's lives are also done with simple attribute changes.

The score.. Oh right. Printing out the score is a surprising problem - you see, there's no division (or modulo) opcode on the z80, so if we wanted to simply sprintf the score, that would probably eat significant amount of our frame time.

Enter binary coded decimal, a numeric encoding format so common that there's often special opcodes in various CPUs for it. Simply put, for each hex nibble we store a value from 0 to 9, and the rest (a-f) are illegal. If a nibble's value is over 9, we add 6 to the value, to roll it back to the legal range. In case of overflow, the next digit is incremented by one, and then we have to check if that is in the legal range, etc.

While relatively complicated (depending on how many digits you want to handle), it's still way cheaper than dividing by 10 a few times. The z80 also has an opcode for doing all this - DAA (decimal adjust after addition). Instead of using that, I wrote the same kind of logic in C. Probably a huge waste, but fast enough for this project.

Looking at the Mackarel memory maps, the game takes quite a lot of the memory, but there would still be plenty of room for more stuff if wanted:

Memory : 0       2       4       6       8       10      12      14      16
On load: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr

On boot: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr

Key    : r)om s)creen b)asic L)ow block C)ode block
         H)igh block .)unused -)reserved

The low block (L) contains the game logo. It is simply copied to video memory when the game starts. If there were more than one type of enemy at once, I could store the sprite data for various levels there. The memory below the 32k limit is considered "slow", because it is contended, and thus it's preferable to keep all code and data we want to play with above that limit. As a recap from earlier blog posts, accessing contended memory while the screen is drawing incurs at an additional speed penalty.

There's also some room above the code block (C), meaning that there's still room to add code before I'd have to start worrying about size optimization.

As before, all of the sources are available on github.

Speccy, Vol 6: Some Little Details

January 23rd, 2016 #

Over the new year's I decided that I wouldn't try to make "the best thing ever" for speccy and instead would make and release smaller things. To get things rolling, I decided to create a simple shoot-em-up, and while doing that I covered a couple of little details my earlier experiments had not, so let's look at these.

First bit is interrupts. The z80 has three interrupt modes; IM 1, which is on by default, hops into fixed address in ROM, IM 0 executes opcode from data bus (which may be whatever) rendering it completely useless, and IM 2 hops to an address in a lookup table indexed by a byte from the data bus (which may be whatever), which is awkward but not completely useless.

We could leave the interrupt to point at ROM, but since it does things like scanning the keyboard which takes variable amounts of time depending on what keys are pressed, and since we'd rather not have the ROM poking at RAM addresses, it's better to turn it off.

We could just disable interrupts and leave them disabled, but then we'd lose frame sync which isn't so nice. Okay, we could count instruction clock-cycles for the whole frame, but that would be insane.

So we're down to using the third interrupt mode.

The way the third mode works is that you create a table of addresses where the interrupt should jump, set one register to say where the table is, and then change the interrupt mode. Whenever the interrupt happens (near beginning of vertical retrace, or 50Hz), the z80 reads a byte from the bus, uses that as index to the table, and hops there. Another slight problem is that the addresses are 16 bit, but the index may be odd or even, meaning that in practise your interrupt address must be of form 0xXYXY - both bytes being the same.

The zx spectrum 48k ROM has a large chunk of 0xff:s in it. I presume they didn't need the whole 16k of ROM, and the unused bit was left to 0xff. Whatever the reason, there's a fun little trick we can do on the 48k speccy.

        ld a, #0x39 ; 0x39xx is a rom address with lots of ff's in 48k speccy
        ld i, a     ; set i
        ld hl, #0xffff
        ld (hl), #0xc9 ; 'ret'. Should be reti, but that's 2 bytes, and we aint got room for that.
        im 2 ; interrupt mode 2, which should now hop to 0xffff which has our ret instruction.

First we set the interrupt jump table address to point at the large chunk of 0xff:s, causing the interrupt to always jump to the address 0xffff. Then we poke the opcode for 'ret' to 0xffff, and finally we set the interrupt mode to 2. After this, whenever the interrupt happens, it just does 'ret'.

What we should be using is 'reti'. Unfortunately, opcode for 'reti' is 0xed4d, so it won't fit in our single byte. Another sneaky thing that could be done is relying on the fact that the memory loops, and put a partial opcode at the 0xffff address and use the first byte of ROM as the second part. If the resulting opcode is a relative jump backwards, we can then put whatever we'd want there.

The difference between 'ret' and 'reti' opcodes is that 'reti' is also decoded by a bunch of z80 peripheral chips, but that doesn't seem to matter on the zx spectrum, so we're fine.

Now that the interrupt handling is done, the next bit that was missing was user input.

If you look at how the speccy keyboard works, there's a 5-wire connector and a 8-wire connector to the keyboard membrane, and there are exactly 40 keys on the keyboard, split into eight 5-key groups.

These wires are connected to the port memory space on the z80, meaning we have eight i/o ports from which to read, and the bottom 5 bits of each of those ports represents a key on the keyboard. So, to read the whole keyboard state, we need to read from 8 ports.

If a key is down, its bit is zero. If a key is up, the bit is one.


Note that the bottom 8 bits of the port address is 0xFE, or 254 - yes, the same port where we write audio and border color.. everything is basically hooked to the same i/o port in the spectrum.

I wrote a simple inline assembly function that reads all those ports and puts the data into a byte array, and then through some C preprocessor trickery my keyboard use boils down to:

    if (KEYDOWN(SPACE)) fire();

But wouldn't it be nice to be able to control a game with a joystick instead? Unfortunately, because spectrum didn't come with a built in joystick port, there are at least four joystick standards for the spectrum. Two of these are the most prominent: the "interface-2" joystick and the "Kempston" joystick.

The interface-2 joystick was Sinclair's definition of the joystick port. Its input maps to keyboard ports directly (more specifically the numeric keys), so it's relatively easy to support via the keyboard code. The joysticks themselves used the same connector as the very widely used "Atari" standard, but the pins are wired differently because Sinclair wanted some vendor lock-in. Sigh. Anyway, the later "big" model speccys also have these ports built in.

If I ever get to fixing the 128k speccy I bought off ebay, I'll have to make a atari-speccy joystick port converter.

The Kempston interface uses the standard Atari pinout, but doesn't map to the keyboard. Instead, the Kempston state is read from port 0x1f, again five bits for left/right/up/down/fire. To support Kempston, I simply added another byte to read in my keyboard update function, and reading the joystick is just a matter of, for example, checking if "KEMPL" key is "down".

Since reading from random unconnected ports may result in any kind of result, one can't simply just assume that there's a joystick there and read all of them (and some incompatible joystick standards actually overlap, if a completionist wants to support everything out there), so the game needs to prompt for input preference from the user. A slight bummer, but users are totally used to that.

Return of the Recent Search Terms

January 22nd, 2016 #

A while ago someone mentioned that I haven't done a recent search terms post in a while. This is true. I figured I'd do one now, and looked back to see what dates I should include in the search, and was surprised to find that I didn't do a RST post last year at all!

Google has become depressingly good at filtering funny search results from the reports, however. Google analytics only gave about 600 keywords for the whole year(!), and from them, I only found the following mildly amusing ones.

You can find collection of older RSTs at this rather long page

avr circuit simulator for ubuntu atanua

Sorry, never got around to implementing it, even thought I got sources to an avr simulator and license to use it.

common stories of sol

I guess I do repeat myself sometimes.

concept of lookup table in graphics tutorial

Concept. Okay. First, calculate something. Then, realize you're calculating that exact same thing a lot. So how about storing the value and reusing the result. But you have a range of values. So instead of storing one value, you store a table of values. And that table is a lookup table. Not really limited to graphics, though. Common lookup tables in graphics (historically) are color lookup tables, screen offset tables, and trigonometric tables, such as sin and cos, for old enough machines where calculating those is really expensive.

death rally creators dos

That would be remedy entertainment.

how to make a audio engine in c++

Through a long, tedious, but also rather interesting learning process.

how to port dos program to windows

Learn DOS programming. Learn Windows programming. Not necessarily in that order. Now you know how.

how to use escapi

Look at the example source code, maybe?

want to make a mmo how to get started 2015

Same way as before: learn absolutely everything about everything first. And/or become rich.

webcam dll multi device support

Depends on the make and model of webcams. Some work, others don't. Most people don't use multiple webcams at once, and thus the developers don't always expect that.

white magic spells that work

Click here to feel better.

why are busses so loud

They are relatively heavy vehicles, and thus require rather a lot of energy to move, and acoustics isn't the primary concern. While I do believe that it would be possible to design a bus that's fairly silent, I trust that people would prefer just getting whereever they're going at a cheaper rate than ride on a bus that doesn't make so much noise.

Speccy, Vol 5: Making Releases

January 6th, 2016 #

After playing around with compressed loading screens and compressed application images, I ended up with a monstrosity of a build scheme.

It's no wonder most people don't bother with the compression..

On the left side of the graph you can see an example of a relatively complex project with couple C and couple assembly files being first compiled with their appropriate compilers and then linked, resulting in an intel hex (ihx) file. This file is typically converted to binary and then run through some .tap making utility, and we're done. Well, done-ish. But if we want a loading screen, and want both the loading screen and the application image to be compressed, things get a bit hairier.

First, you'll notice that we're compiling the hypothetical "unpack.asm" twice. This is because they're not position independent, and will have to run from different offsets. The compiled decompressors and then binarified and copy /b:d to a combined binary file which can then be tapified. On the loading screen side things are slightly more complicated because we need a specific bootstrap written in spectrum BASIC and the compressed loading screen image itself, but eventually we get a tap file from that branch as well. These tap files can be joined with another copy /b command to get the final tap file.

What the graph doesn't include is that since you pretty much always end up with compressed files of different sizes, you also end up with different loading offsets, which may mean patching the compiled binaries, or recompiling the boot-up assembly after manual changes. And you also need to care about all the offsets you want to load things into, and have to update build scripts and whatnot whenever these change.

Or you can do something a little fishy.

Introducing Mackarel, the one-stop solution for neat zx spectrum releases. Mackarel converts ihx files, generates the needed basic, generates loading screens if need be, compresses, patches binaries, and generates the final tap file in one swell swoop.

There's a couple different compression algorithms to pick from, but the defaults are picked so that you don't really have to care about it. If your compile chain doesn't generate ihx files, you can also feed binaries to Mackarel, but then you have to give the start address of the binary too.

On a more technical side, the compressed loading screen and combined basic bootstrap works pretty much the same way as described in my earlier post about compressed loading images, except that everything is self-contained within Mackarel and you don't need to call any compressors, etc. yourself. If no loading screen is provided, Mackarel will generate a simple one for you which typically takes, along with its decompressor, about 250 bytes.

The application image itself is compressed and loaded to the end of the memory space. Upon launching, the bootloader first copies itself to video memory, and also sets stack to point there. Running from video memory, it decompresses the application image to the desired start address, restores stack and hops to the beginning of the image. Assuming the application doesn't do anything wonky, it's clean to exit back to basic if you really want to.

As before, all of the code is available on github.

Happy 2016

January 6th, 2016 #

And the Pouet thread, too.

Haven't written a breakdown as of yet. Any interest?


Older news have been archived here: 2015 2014 2013 2012 2011 2010 2009 2008 2007 2006 2005 even older

^^^ That is an ad. Click here for other ways to support the site ^^^
Site design & Copyright © 2015 Jari Komppa
Possibly modified around: January 30 2016