Category Archives: Blog

Atari hardware project idea

A few days ago, I started thinking about how difficult it’s becoming to find a good monitor for my Atari, especially one that I can easily bring with me on demo parties and such.

Then it occurred to me that my CosmosEx that is mounted inside the ST have a Raspberry Pi inside it, with both an HDMI and a composite video out. What it also have is a high speed connector for camera hardware, capable of streaming HD video in realtime. What I realised is that, with some custom hardware with an FPGA one could get the video signal directly from the shifter and feed it to the Pi in realtime. It would take is a pretty simple program on the Pi to display the ST:s video output on any screen.

After studying the schematics for the STe and ST, the respective shifter seems to output 4bit (for STe, 3bit on ST) digital RGB values that is then turned into an analog signal. Hooking into these pins should be fairly simple, and together with the pixel clock and the sync signals, an FPGA should be able to convert the color data and send it as an image through the CSI-2 port to the Pi.

My problem is that I know very little of FPGA and hardware development. I would like to be able to build this by myself, but if some pro could help out, that would be awesome.

demicode on twitch!

I recently got the idea to stream some of my programming sessions on twitch, and yesterday I created a twitch account for this purpose. I don’t know if there ever will be a real schedule, but I’ll try to stream as often and regularly as I can.

The current project I’m coding on the stream is a new game for the Atari STe that I got inspired to do the past weekend. The goal is to make a small metroid-vania style game, with pretty simple gameplay. I got the idea after once again finishing the excellent DARC for Sega Master System.

The game will be very short but if people like it and my interest don’t disappear, I will instead make a sequel with maybe more content. I’m keeping my ambition low so I don’t get overwhelmed by expectation. Keep your fingers crossed that it will get finished eventually.

Summer activities

Hey, I made a couple of Atari ST intros this summer. First up was Bacon, which was released at Sommarhack 2015. I started to plan it when there was still snow outside, but I did almost all of the coding the during the week before the party.

The release was thrown together for High Coast Hack in Härnösand four weeks later. As I had participated with an intro the last to years, I wanted to have something this year as well. So I grabbed some old code and a sound sample, re-coded it for overscan and added an intro pic. As the previous intro, most of the coding was done during the week before the compo. I called it C-c-compo filler.

That’s it for now!

Work in progress

This blog has not seen much action lately, but my coding has been more or less constant. There are code for a few more platforms in my Hello World project, and a few month ago I started writing some code for a SEGA Mega Drive game. It’s no secret that the SMD are one of the platforms that now have a Hello World implementation. I just need to take time to finish up a blog post about it. There are actually two other posts in the pipeline, for the Atari 8bits and Gameboy, even though the Gameboy code is far from working perfectly.

I recently purchased a Skunkboard, which is a development cartridge for the Atari Jaguar. The Jaguar hardware is pretty cool, even though it’s far from bug free, it seems really cool and I can’t wait to get some time free to do some actual work on it. One of my colleagues at work started with a cross platform game project for the Mega Drive and Amiga with a friend of his, and I got the idea to port the game for the Jaguar. I’ll have to wait a while until their code is in a more stable state before I can start porting, but it will be a very interesting project.

Now I better get started with the jumping and colliding code for my Mega Drive game.

Hello Gameboy Advance

Last weekend while digging around on one of my USB sticks, I found some old test code I wrote for the GBA over 10 years ago. I though the files were lost forever, so I was quite happy that I found them. The code itself was written in an obscure assembler for Windows, so my first goal was to port it to a more modern tool that preferably could cross assemble on both my PC and Mac. I decided to give the vasm a try. After some initial problems with strange syntax and me not understanding what the error messages meant, I got it to assemble into a binary file. To my surprise, the resulting binary could be loaded into the emulator and it worked the way it should! From there I cleaned up the code, removing stuff I didn’t need for the Hello World Project and added the result to the repository.

The code

This is by far the shortest example to date. The video mode I chose made it very easy to draw graphics on screen, and the setup required is minimal. A short note before we continue; the semantics of the data types are not the same as on the 68k processor. On Arm, a word is 32-bit, while on the 68k it’s 16-bit. This can occasionally cause some confusion, at least it has for me when my focus was not high enough.

At the beginning we tell the assembler to use the arm instruction set (which is 32 bit, as opposed to the thumb instruction set that has 16 bit instructions). Then we tell it that the following code will be executed at position 0x08000000, which is where the GBA ROM entry point is.

The first instruction we run makes a jump (branch) over the ROM header. After the branch, we define the GBA header. I have no idea why the values in the header are what they are or if they are correct, but this is what my old code did, and the emulators I’ve tried haven’t complained yet.

Lets begin by setting the display mode. By setting Mode 4, we get 256 colour chunky graphics mode, i.e. each byte in the graphics memory corresponds to the color at that position in the palette. In Mode 4, only background 4 is used, so we need to enabled that background layer.

Time to setup the palette. Since the graphics only consists of two colours, we read both colours from the palette data in one go and writes them to the palette memory. Each entry in the palette consists of two bytes, with packed RGB data, 5 bits per channel. The least significant bits are the red channel, the next 5 bits are green and finally 5 bits representing the blue channel. The most significant bit is ignored.

Time to update the screen with some pixels. Here we setup two nested loops, on for row and one for column. For each pixel on each row, a color entry is read from the pixel data and written to screen. To optimize a bit, we handle four pixels at a time, and also, it is not possible to write just one byte to the VRAM; doing so will result in the same value being written to the other byte in the other half of the 16-bit location.

There is one thing in the loop above that might be hard to understand without further explanation. I’m thinking about the [r4,#4]! syntax. What is does is access the data pointed to by r4 + 4 bytes; the exclamation mark at the end indicates that the r4 register will be updated with the same offset that was used in the access. So, 4 will be added to r4 after the data access. r3 and r4 will therefore increase after each read/write, so the source and destination addresses will be updated for every iteration in the loop.

We have reached the end of the executable code and here we just enter an infinite loop by jumping to the same location forever.

Now all code is done and we reach the data. First we have two entries of colour data; black and white. These are the values that are written to the palette register.

And finally the graphics data. Same graphics as the other examples, except here we have indexed colour mode, so 0 means colour 0 in palette, and 1 means colour 1 in palette. Simple as that.

That is it. I’m quite fond of the ARM assembly language, it’s quite readable compared to, oh say PowerPC assembler code.

Links

There are many site on the internet dedicated to programming Gameboy and Gameboy Advance. Here are a few links that might be useful. Since the original version of my code was written over 10 years ago, I can’t give links to the resources I used initially, but I hope the links below fill your needs.

Hello Sega Master System

Long overdue, it time for another Hello World hack, and this time it’s for the 8bit console Sega Master System (SMS). Based on the Z80 it will be the first system in this series that is not based on the Motorola M68000 CPU. I learned to code the SMS in 2005, and have release two tiny demo hacks under the alias blind io (you can find them here if really want to see them).

The major difference between the SMS and the Atari ST and Amiga is how the graphics hardware works. Most 8- and 16bit consoles, are based on tiled graphics and sprites. What this meas is that the screen is split into blocks of 8 by 8 pixels, and what tile is displayed one of those blocks is read from a tile map. Sprites are also blocks of pixels, but can be moved freely around the screen. The number of sprites are limited and only a few of them can be displayed on the same scanline due to restrictions in the hardware.

The tool used to assemble the code to a ROM image is called WLA DX. It is a great tool and can assemble code and produce ROM images for several different platforms. In this post, I’m going leave out most of the directives that tell the assembler about the output format and such, and focus on the Z80 code. For the full source, you can go the project on bitbucket.

The code

To start off, we tell the assembler to place the following code at address 0. This is where the Master System fetches starts to execute once the logo has been displayed.

In interrupt mode 1, the cpu jumps to address $38 when an interrupt occurs.
Only the VDP can trigger normal interrupts on the SMS, either every VBL and/or
every scanline. Address $66 is where the CPU jumps when a non-maskable interrupt occurs. This happens to be connected to the Pause button on the Master System. For us, lets just ignore the interrupts and return immediately.

Now we can do the thing we came here to do; show some graphics. First we must setup the VDP, which is the video controller. A bit further down in the listing, there is a section of register values for the video chip, and here is the code that writes these values to the data port connected to the VDP.

otir is an interesting command. It actually does several things. First off, it takes the byte pointed to by hl and output it to the port contained in register c and increases hl by one. Then it decreases the value in register b, and if the result is not 0, the program counter is changed to run the same command again.

Once the VDP configuration is done, we upload the graphics data tiles to the tile RAM inside the VDP. The address in the VDP to where we want to place the tiles is $4020 which we output to VDP control port ($bf). The highest two bits are in reality not part of the address, but tells the VDP that we want to write to the video ram (VRAM). By using offset $20 in VRAM, we leave the first tile empty so all unused blocks on the screen are left black. Note: Running this on real hardware will probably leave some junk on screen since the content of the VRAM might not be initialized to 0.

Then we setup the registers for another otir instruction. The port to write data to the VDP is $be, and it’s quicker to decrease $bf by one than to write the new value to the register.

Now we have uploaded the tile data, but we must still set the colour palette. Same procedure as when we uploaded graphics data, by the colour palette address is $c000 (actually the two highest bytes indicate that we should write to colour memory (CRAM), and the following zeros indicate offset in CRAM), and the number of bytes in the palette is 16.

One thing remains, we must tell the VPD what tiles to display at what position. Since we uploaded the tile data to tile number 1 to 6, we should write values 1 to six in the first 6 entries in the tile map. Tile map entries are 16 bit, so we need to write a 0 every second byte. In the code below, we write 0 to register e and writes that after we have written the value in register a, which we use to count from 1 to 6. The last thing we to is just loop forever.

Here comes the VDP setup data. If you want to know what all these bits and values mean, I suggest you go to the development section of the SMS Power homepage in the link at the bottom of this post.

The palette is quite straight forward. RGB data with 2 bits each. This give us a palette of 64 possible colours. 16 entries. There are actually two different palettes you can use on the Master System, one for background tiles and on for the sprites. Since no sprites are used in this short sample code, we only set the tile palette.

Here comes the tile data. It’s the same graphics as with the Atari and Amiga version, but it has been converted to tiles. The tiles are 8*8 pixels with four bitplanes where the first four bytes of data are the four bitplanes for the first row etc. This means that every tile is 32 bytes of data.

That is it really. For more info see the links below. I apologize for any errors and weird stuff in this blog post, it’s also 5 in the morning and I have written most of this post during the night.

The next installment in this blog series might come sooner than you think. 🙂

Links

  • Z80 CPU User Manual – All you need to know about the Z80
  • SMS POWER! – A goldmine for Sega Master System lovers.
  • MEKA – Emulator with debugging possibilities.
  • WLA DX – Multi platform cross assembler

Hello Amiga OCS

amiga-screenshot

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.

Links

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

 

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!

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.