Hello Amiga OCS


Weeks later than I had originally planned, the Amiga OCS is now greeted with a small Hello World sample. Since this is my first time coding the Amiga, most of the time was spent on reading various hardware documentation on what registers to set and why. As I have somewhat more experience with the Atari ST, I will comment on the difference between the two platforms as well as trying to explain what the Amiga code does.

After some trial and error coding, I decided to write a more system friendly version for the Amiga, to keep the code-build-test cycle as quick as possible. It took way too much time to restart the emulator after every test.

The Amiga and Atari are both based on the Motorola 68000 CPU family, so I am well-versed in the assembly language. The OS and other hardware on the other hand, that was not as easy to get the grips on.

The first thing to do in our little program is to save the current state of all the registers our program will change, so we can restore them to the same state when the program exist. For the address of the default copper lists (more info on the copper later) I load the graphics.library via the OldOpenLibrary system call, and get the addresses for the two lists.

The address to the exec library, which is the core OS module of the Amiga that handles loading of libraries and other basic needs, can be found at position $4 in the memory.

Load “graphics.library” by placing the address to library name string in CPU register a1, and jump to the “OldOpenLibrary” function at offset -408 from the exec library.

The return value will be in d0.

Now the handle to the graphics.library is in register a1, where we can use it as an pointer. Now it’s time to get the address to where we want to save the register data and save the copper list addresses in that memory area. When we are done with that, we can close the graphics library.

Since a2 pointer de-reference used the post-increment syntax, the content of a2 is counted up by the size of data that was written. We continue to use this syntax as we save some other registers that we need to change later on.

Now that we have saved the registers, we can move to the core business – Setup the screen and draw some data to it.

First off, lets only enable DMA for bitplanes and copper. Writing to the DMA and IRQ registers with the highest bit (16) cleared, the functionality corresponding to the set bits will be disabled. To enable functionality, you must write the mask for the functionality you want to set plus the highest bit set. So writing $7fff will disable all, and $ffff will enable all.

Reusing the graphics from ST version, lets copy our graphics to screen. The Amiga screen is a bit different than of the ST. The bitplanes of the Atari are interleave, where on the Amiga, each bitplane is stored in one continuous block of memory.

Set up the copper data. Most of the data in the copper list have been prepared beforehand, but the address the the screen memory must be updated once the code is executing.

Write the address to our copper list data to the co-processor hardware register. Writing to the strobe register reloads the register and starts to execute the list.

Loop until the left mouse button is pressed.

Restore Registers. Like I mentioned before, the highest bit must be set to enable functionality.

Code is done! Now we have to add the graphics and data used by the program. The section statement below tells the assembler to put the data in the “chip memory”, which on the Amiga is memory that can be accessed by the DMA sub-system.

Define lib_name variable as a string containing the name of the graphics library that we load at the beginning of the code. The even statement informs the assembler that the statement should be placed on an even address, since reading 16- or 32-bit values from odd addresses result in an error.

Reuse graphics from the Atari ST version. Since both the Amiga and Atari ST both use bitplane graphics, the data can be reused without changes.

Finally we reach the copper list. The copper, with is kind of a good nick name for co-processor, is a processing unit that can execute a few simple types of instruction. The most common probably being writing data to a hardware register in the memory space of the hardware registers.

Just for fun I added a so called copper bar, or raster bar. To achieve the similar effect on Atari, a lot of more work is involved. Some day I might show you how it’s done on the ST.

The last entry in the copper list tells the copper to wait until it reaches a line that is below the end of the screen, and will therefore not do anything more.

BSS section where we reserve some memory for the registers we save. We also reserve memory enough for one bitplane at a resolution of 320*256.

That’s it. Assemble and run.

Disclaimer: I don’t know enough of the Amiga to say that this code does everything it’s supposed to do. It might have some unknown side effects that I am not aware of. There might also be factual errors in the blog post. Feel free to point them out if you find any.


Here are some useful links if you are interested in learning more and test some Amiga programming yourself.


Hello Atari ST

This is the first part of the Hello World Project.

As I’ve been an Atari ST owner since the late 80’s, and still code on my ST occasionally, it was an easy choice to begin with this platform. I could write most of this code without looking through documentation, with a few exceptions, like the OS function code number.

Before I begin to explain the code, I should tell you that this code is not very system friendly. You will not be able to exit the program, all you can do is reboot. After I wrote this code, I have started looking at the Amiga, and realized that it is quite handy to be more system friendly and exit the program in a more kind way. It will save you many reboots of the hardware/emulator while coding. It is very likely that I will return to this code later and fix those issues.

It is quite straight forward to get something draw on the screen on the ST. Just set the address to your allocated screen memory and move some data there. But to access the hardware registers that change the screen address and palette registers, we have to run our code in supervisor mode. This is special mode in the m68k processors where you can execute some privileged instructions and access protected memory areas. I will not go any deeper into the working of the m68k processor family, but if you are interested in programming the Atari, Amiga or any other machine containing an m68k processor, I recommend that you download the Programmers Reference Manual.

One way to run our code in supervisor mode is to call the XBIOS function Supexec, which calls a function in supervisor mode. Since this code is not system friendly, I decided to just stop and loop forever once the function has been completed.

The pea super_run instruction pushes the address to the function super_run to the stack, and the trap #14 instruction calls the XBIOS that then calls our function before it completes.

The first thing to do in our function is to fix the screen memory address and set the screen base registers to point to our allocated memory. At the very end of the source code, there is a SECTION BSS entry, which contains a label screen_mem followed by a ds.b statement. The ds.b declares that we want to allocate space. The ST screen memory always consist of 32000 bytes (unless you are really advanced and do some hardware tricks to achieve overscan, but that is another story).

On an ST, the screen address must be aligned on 256 bytes. Therefore we allocate 256 extra bytes, add 255 to the original address and then clears the lowest byte. If you don’t understand why, grab a pen and a piece of paper and do some calculations yourself.

To set the screen base address, there are two byte sized registers you must write to. As the memory address space of the ST is only 24 bits, and the lowest byte in the address must be 0, it is only the two middle bytes in the 32 bit address that are relevant. The higher of these should be written to $ff8201 and the lower to $ff8203. The last to instructions in the code block below takes care of that. Remember, the m68k is a big endian system.

Lets move on to the colors. The ST palette is stored at the address $ff8240 and contains 16 16-bit  wide (a word in the m68k lingo) registers with color data. Here is a little loop that sets all palette entries to black.

At address $ff8260 lies the screen mode register. By setting this to 0 we set the resolution to low res, which is 320 by 200 pixels.

Start copying data to the screen memory. In lo wres mode, the screen consists of four bitplanes, interleaved with 16 bit words for each plane. If you never used bitplanes, they can be a bit confusing at first, but since many of the old school platforms in one way or the other uses bitplanes, it can be a good idea to read up on them. I will not try to explain how they work just now.

The graphics i made is one bitplane (uses only one color and thus only need one bit per pixel), so we skip three bitplanes when copying data.

The screen base is set, our graphics is copied to the screen and the only thing that remains is to set palette entry 1 to our color of choice. Of course, if we had copied the graphics data to another bitplane than the first we would have to change another palette entry.

On plain ST the palette data consists three bits of data for each RGB channel in the lowest three nibbles. $700 would be red, $070 blue and $007 green.

Define the graphics in a data section. The data contains of binary data, where one bit corresponds to one pixel. 48 pixels wide and 6 pixels high.

And finally we declare some space for the screen memory that we referenced earlier. The difference between the DATA section and BSS section is that everything in the DATA section will be store as data in the binary file, whilst the BSS section will be allocated by the system at load time.  There is a flag in the executable file header that tell the OS whether the memory in the BSS section should be set to zero before the program starts. This is the default behaviour, but if the fast-load flag is set, the memory in the BSS section will be undefined when the program starts.

Any questions or complaints? Leave a comment!

Next up, Amiga OCS. In a future not so far away.

The Hello World Project

Since my time and energy are limited due to my full time day job, most projects I start have a tendency to stall before they really takes off. I’ve been thinking about how I can find the motivation to actually do things when I have time free time. Earlier this week I came up with an idea for the perfect project for me.

The Hello World Project

The idea I had was to make “Hello, World!” programs. That might not sound very hard, does it? No, and it also not very time consuming either. At least not in it’s simplest form. But this is not about making it easy. 

I am going to write Hello World programs for old school computers and consoles, in assembly language. Instead of just calling an os or bios function to write a string to the screen or console, I will access the hardware directly to output my Hello World graphics in whatever form I like, should it be a bitmap or using sprites or whatever else is available.

My interest in old school platforms and the the demoscene is what inspired me to do this. I want to learn about the hardware for the platforms I grew up with and saw all those cool demos on. When this project has started, people, including myself will hopefully have some example code as a starting point for other project, be it demos or games or anything else.

I will try to write blog entries for each platform, and the code will be available on the project page at bitbucket.

I hope to keep the motivation flowing!

Row Chaser no longer available

Since a few month back, I am no longer enrolled in Apples developer program for iOS. A side effect of this is that any application I had on App Store are no longer available. The major reason for this is that I don’t have an iOS device that can run anything newer than iOS 4, and my old iPhone 3G has troubles even running that.

I am planning to buy the new iPhone 5 when it is released. When that happen, I might enrol as a developer again. Whether or not I will re-release a bug fixed version of Row Chaser is another story.

In other news, I’m working on a postportem for Row Chaser – which might be ready in a not so distant future in a post very close to this one.

Project: Raindeer

About a year ago, I got fed up with just sitting around at home thinking of all the programming I could be doing, instead of watching TV-series. Triggered by a tweet someone in my feed retweeted, I decided to start with the project. The tweet was something like Make a game, not an engine, which made me realize that I had made two or three more or less working engines, but never actually used them. I decided to start fresh.

Inspired by a dream I had one night, I made up some game mechanics and a basic theme. This was the list of goals I had when starting the project.

  • Release the game, even if it’s not perfect.
  • Be platform agnostic. Use SDL, but try to abstract away the SDL dependency.
  • Don’t obsess over details. Even if code is not optimal, it will do fine as long as it’s bug free.
  • Try out new techniques I haven’t used yet.
  • Have fun. It’s fun to code, so code! Don’t ponder on the best way to solve things.
  • Learn from mistakes for future projects.

The first thing I did was to install a trac, and write down the project goal, basic game design and a project plan. And then I started to produce code.

At least that’s what was supposed to happen. Instead after creating the initial file structure and a skeleton project with some glue code, it took a halt. The two main reasons; I almost immediately forgot was I was set out to do. I started to think about the best way to do things. Even reading keyboard input, which in this case was really simple since SDL provides the hard part, felt like a major obstacle.

My first milestone – drawing a box on screen and moving it around the the arrow keys – was supposed to be done in the first week. Today, 10 months later there still is no box on screen. The input is working though, but when it comes to rendering, I have decided to add an abstraction layer on top of the rendering API (OpenGL in this case).

I just picked up the project again a few weeks ago, and I hope to get up to speed this time, and I think blogging about it might help.

An update will come soon, I hope.

Changes ahead

Since demicode have been more or less dormant for the last couple of  years, due to me having a day job to pay my rent , this site will change. From not being used at all  my intention is now to use this blog as a outlet for all my programming related blogging. I realized that incorporating such blog posts in my more personal blog, that I’ve had since the beginning of the previous decade, was not really what my handful of readers would appreciate.

So, this will now be the place where I blog about my programming, and in contrast to my personal blog, this one will be entirely in english.

So, what can you expect? Probably not that many posts, but when I do post the topics might be everything from hacking Z80 assembly for my SEGA Master System to web development or creating games for personal computer and consoles. And everything else tech related.

Lets see where this will lead.

New project started

Last weekend I had a meeting with my game designer friend at antroia where we decided what our next game should be. This time we could actually test the game play in analog form without the need of a prototype, and we both agreed that this game have the potential to be really good.

Since this game is more about thought and less about brainless poking the screen, I can cut the production time quite a bit. There is no need for scripting, no need for an advanced game engine and no need for OpenGL. The most important thing in this game will be your brain.

One more thing – this game will support the iPad.

Time flies

The plan was to update this page and have it at a near-final state when the games was released, but time as it seems, flies.
None of the sites I’ve made have ever had a final state anyway, so this site will probably be it constant change, just like the web is supposed to be.

A new beginning

After realizing that using drupal would be to aim a bit too high, I decided to use a more fitting system for this site. Due to laziness and recent work with other things, the game I’ve been working on has been postponed for quite some time now. We now aim to release it some time in the coming month, that is some time in January 2010, depending on how long it takes for apple to approve it.