Wednesday, 11 April 2018

Tiny 2018 Update

Haha, I've been quiet for almost 2 months!

I'm in America right now, but I've still been ploughing on with DOSJUN. I've added music support for a certain tracker format, wrote new graphics loading code to hopefully avoid some of those horrible "out of memory" errors and done a lot of planning for the setting and denizens.

I realise that there's still plenty of work to be done. However, it is slightly further away from "I want to make a game" than it was. The scope is starting to creep a little, but I'm still fairly confident that I can release a playable version of the game this year. I'm thinking that I'll come back and add more content later, because J and I have come up with some excellent ideas to make the game deeper.

Friday, 26 January 2018


DOSJUN is alive and well. Here's a quick look at the current progress.

You can walk around

You can load and save (in safe spots)

There are scripted events

You can fight random encounters

Technically, there's a lot going on in the background to deal with this short list.

A first person view that uses slices of textures

A scripting language (and compiler)

A dungeon editor (items and monsters too!)

It is my eventual goal to not only release this game when finished, but also annotate the code well enough that people can actually learn from it.

Progress has been slow for a variety of reasons: I play a lot of games (mostly long ones), I don't always want to program after doing it for hours at my day job, I watch people stream gameplay quite a bit. These things have been true for years, but I want to commit to this project a little harder than before.

I will release the game this year. At the very least, I can release a version then add more content later if the story remains unfinished. There will be at least 5 hours of work every week on it. Making the engine easy to extend has been important to me since the beginning; an example post-release task would be removing the hard-coded character creation and using scripting instead.

I'm also thinking about streaming the programming work. This might seem odd, but I recently caught someone using Rust to write a roguelike and enjoyed the experience, so there must be like minds out there. It should be a novelty for many current devs to see C and DOS!

Sunday, 5 November 2017


I'm in London, so there isn't a great deal of work getting done right now.

Yesterday, I had the pleasure of attending the Distant Worlds 30th Anniversary concert at the Albert Hall. Here's the setlist (ignore the location). There's an interesting spread, though few of the 8- and 16-bit games make an appearance. The Theme of Love on a real harp was beautiful, though. Also, the Victory theme on kazoo.

Yes of course I've been to a CeX. I found a Last Story Limited Edition, and seeing as I own a European Wii now, I snapped it up. More Nobuo music to listen to. :)

Sorry for the short post. In the past few months I've been alternately working on DOSJUN, trying not to lose in the TrueAchievements contest and being tired from work. See you soon.

Sunday, 11 June 2017

Teach Yourself Game Programming in 21 Days - Day 8

This is the chapter I've been waiting for.

I'd messed around with coding and writing games before (on an ancient Casio handheld, among other things) but this chapter made me seriously reconsider everything I'd written until then. It's called "Warp Speed, Anyone?" and it's all about optimising code; optimising for speed, that is. A game can be utterly beautiful, but if it isn't responsive, then it's probably not going to be very good.

The first thing the author mentions is compiler optimisation. Essentially, a compiler is free to reorganise or eliminate code that it deems is in the wrong place or unnecessary. Generally the compiler lets you control how much it tries to 'help' you, which is good, because sometimes it can make the wrong assumptions and make it virtually impossible to track down bugs. Knowing how to write code is one thing; being able to debug the resulting assembly language is another. I've done this a few times in my life, so it's a skill I have (kind of) but I will point out that it's often not the best use of your time. Accordingly, André recommends leaving compiler optimisation settings low, despite the potential speed increase. Games have some of the most complicated code out there; you want it to work, first.

The next major subject is that of the memory model. This will be completely alien to anybody who hasn't worked with DOS before. Early on in IBM's history, the decision was made to separate code (executable memory) from data (read-only memory) by the use of segments. This prevents code from overwriting itself. This is a good idea. However, as the PCs of the time had very little memory, each of these segments was only 64KiB large. This was a bad idea, but nobody knew just how much storage was going to expand in the years to come.

All of the programs I've written so far have fit into the Tiny memory model; only one segment required for both code and data. For a little future-proofing, I've been compiling with Compact (one code, many data) but the author actually recommends Medium (many code, one data)! The reason given is that having only one data segment means it's easier to write inline assembly, because DS always has the same value. If more than 64K of memory is needed (and it will be), it will have to be allocated from the FAR heap, which slows down data access slightly. This might be how DOSJUN ends up; it has a lot of code already. I'll have to write 'far' next to more of my pointers.

The next part makes me sad. The Plot_Pixel_Fast function a large part of the book code has been using is an important candidate for improvement; every use involves a function call and pushing of three parameters, which seems like slight overkill considering all it's doing is setting one byte. My solution to this would be to declare the function as a macro, but the author chooses instead to declare the function's parameters as globals, then add a new Plot_Pixel_Global function which uses these globals. André was probably going for maximum compatibility here, but I can't help but note he missed a trick.

Next come standard techniques - aliasing structures or pointers to temporary variables so they don't have to be repeatedly dereferenced (compilers probably do this automatically) and unrolling loops to reduce the time spent incrementing a counter and jumping. There's also a mention of marking certain important variables as 'register' to ask the compiler to optimise them differently.

Then, lookup tables. This is an easy measure to implement in future programs. It's just a matter of trading memory for execution time. This was already done in Chapter 5 to store the results of sin and cos calculations, but it could be done for a lot more... I'm thinking of using the technique for DOSJUN's graphics.

The largest treatment is given to the technique of fixed-point numbers. The gist is to use integers to store non-integral amounts by keeping some of the bits for the fractional part. This allows us to use the efficient integer addition operations instead of the slower floating point calculations that are offloaded to the co-processor. This is the largest code listing in the chapter, and it has been dutifully typed out here.

The chapter finishes with a fairly lengthy and snarky look at DOS extenders, a sad but necessary evil in the transition period between real mode and protected mode processing. This enabled 32-bit programs on the otherwise 16-bit DOS. I'm not sure if I'll need this for DOSJUN, but I hope not, because it's something I've never done. I think it would be quite bizarre to write a DOS program that required 4GB of RAM. Also, I'd have to find a free online one, or write my own.

Despite the dearth of code, this was a difficult chapter to get through as it is quite dense and there's no pictures for me to take! The next chapter is about playing sounds, which would be great if I could get it to work.

Sunday, 28 May 2017

Introducing... DOSJUN

It would be remiss of me to merely type out a few words while reading through a programming book from over 20 years ago. Actually developing a video game using what I (re)learn would make a lot more sense. To that end...

It's been a dream of mine for ages to create a dungeon crawler. It's also a lot of work; I've lost count of the number of times I've started making a game only to abandon it or find some other project to throw myself into. Hopefully, this time can be different.

While I haven't settled on any mechanics yet (other than having 6 party members and there being health and mana, apparently) there is a bit of work done on the graphics engine. I'm also attempting to lay my code out in vaguely sensible ways. Feel free to follow along as I attempt to finally finish something.

Friday, 26 May 2017

Teach Yourself Game Programming in 21 Days - Day 7

There's been something quite obvious missing from our game programming so far. Every time we've handled input, we've been using C's kbhit() and getch() functions. If you've messed around with the demos, you'll have noticed that they suck. That is, holding down a key will result in keypresses based on your OS settings, so input will merrily be processed for some time after you release the key. Also, getch() is quite difficult to use with things like the arrow keys. The reason for that is simple: keyboards are weird.

Every time you hit a key, it sends what's called a scan code to the PC. This is one or more bytes. Another, similar code is sent when you release the key. The keyboard driver's job is to transform these random-looking series of bytes into something that software can sensibly use. Of course, we're programming for DOS, so... you have to write the keyboard driver. I previously did this when I was messing about with OS programming. Typing all those scan codes in was so fun, and I got to do it again!

However, there's more to video games than keyboards. At the time, joysticks ruled the gaming world thanks to their use with Atari and Commodore machines, so naturally some people decided to release them for PCs, too. Coding for them isn't as tedious as for the keyboard, but there is an additional stickler in that every joystick's range of movement is somewhat different. This lead to the universal 'joystick calibration' screen in DOS games where you would be required to waggle it around so it knows what extents to scale your joystick input by. André dutifully gives code for this, presented to you in the joytst demo.

The last input device that the author considers is the mouse; an extremely important tool for strategy games which happily has the easiest driver code of all. mousetst presents what is possibly the simplest paint program of all time. As with many of the demos, it's ripe for improvement. The most galling thing is that it paints one 2×2 block of pixels at a time, but doesn't update fast enough to smoothly draw lines.

This ends the first week of the course. It has covered sprite graphics, vector graphics, loading images from disk, screen transitions, tile-based game worlds, scrolling and input devices. That's enough for a very low-tech game, but we're clearly missing things like sound, AI, physics and special effects; perhaps even multiplayer or networking. There are also more nebulous topics like good game design and playtesting. Still lots to go, and I'm not sure two more weeks are enough to cover it.

Sunday, 21 May 2017

Teach Yourself Game Programming in 21 Days - Day 6

This is an important chapter, for sure. It's titled "Real-Time Animation and Effects", which is a little odd considering that's pretty much all we've been doing until this point. However, games are written in a fundamentally different way to that existing code, and that's because of something called a double buffer.

If you've been running the programs up to this point, you'll notice that the display flickers, seemingly at random. This is because we're updating the screen while it's being drawn. Console hardware has a variety of ways around this problem; from my time with the Game Boy, I know it's very common for screen drawing to be done during the Vertical Blank Interrupt. This means you'll never see a half-drawn frame, unless the game lags heavily. André recommends a similar method for the PC, though without the use of a hardware interrupt. It polls the VGA status register to work out what's happening (see vertical), and waits until it's safe to do an update.

Because we have to maintain this separate buffer which represents the frame to-be-drawn, it requires as much memory as the screen does. This isn't too bad; our typical display resolution of 320x200 mandates a buffer of 63KiB. At the time a typical PC might have 2MiB of RAM, so it was a viable technique. Now, PCs have massive stacks of high-performance memory (mine has 8GiB) and buffering is done by specialised graphics hardware, but it's neat to see how these tricks changed development.

Of course, that means all of our functions that write to the screen should now write to the double buffer instead, so this chapter adds a lot of stuff to our quickly-growing game library.

As a child, the most exciting part was when the author started to describe scrolling. This is a fundamental technique to pretty much all 2D games; either by swapping in new rooms when you enter them or smoothly moving with the player character. You probably won't be surprised to learn that early console hardware was specialised for this, but with the PC you have to do it all manually. Reading this, all kinds of ideas for games burst into my head, and they really haven't stopped coming since. Combined with the quickly-following discussion of using cell-based game worlds to reduce memory use, I was hooked to games (and game development) for life.

I recommend you try out robo because it's a decent beginning for a platformer. Again, I had to recreate the graphics, so excuse my terrible pixels.

There was one listing from the book that I didn't type out; it's called paper and it uses colour rotation to achieve animation. Essentially, the same paper aeroplane is drawn at different points on the same image, but in different colours. Then, the code loads that single image and rapidly changes which palette registers are black and non-black. In this way, very little work is being done by the processor. I don't think there are many wide uses for this technique, but it is interesting nonetheless.

As always, the code is available here.