Monthly Archives: March 2013

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.