Showing posts with label Blitz Basic. Show all posts
Showing posts with label Blitz Basic. Show all posts

Wednesday, 11 November 2020

Lunchtime Coder #3 - Atic Atac Room and Object Viewer

Ultimates Atic Atac has always been one of my fave old skool 8-bit games, so I decided to have a bit of fun with it and see if I could use modern code to read from a ZX Spextrum memory dump of the game and get the rooms to draw/render correctly.

GOAL To create a program that reads a ZX spectrum Atic Atac .sna file and recreates the rooms from the original code.

DEV 001 Read the file and be able to draw the outline of a basic room.

So this is pretty straight forward. With the help of a few Atic Atac fan sites, I found that all of Atic Atac's 13 different types of room are stored in a table as X and Y data points to draw lines between. It should be a case of working out the memory offset for the first room, then adding additional offset to allow for the room type.

I had a false start.. My .sna file was 48 kB, but the ZX Spectrum memory paging includes the 16 kB rom so before I started, I needed to pad my .sna file with 16 kB of dummy data.

Once that was done, I found the room draw co-ordinates without issue and worked out how to whip them up into a recognisable room.

Bizarrely, Room Type 7 has a co-ordinates error in at that draws the staircase incorrectly. I say bizarrely because I had never noticed an incorrectly drawn room in the game. When I checked an on line Atic Atac map, I founf that room type 7 isn't used in the game, and hence why the error never appears in the game. See below:

DEV 002 Input a game location, and get the correct room type in the correct colour drawn.

So its all very well just stepping through the room draw area, but I wanted to take it back a step and access the actual game location table so that for any game location, I could get the correct room type drawn in the correct colour.

Tell the program what Game location you want to draw. The program will read what type of room and what colour that location is, and then jump to that type of room and draw it.

e.g. I am in Game Location 12. Game Location 12 is a type 3 left to right corridor style of room coloured green. Set colour to green and go to the room type table and draw a type 9 room.

DEV 003 Input a game location, and get the correct room type in the correct colour drawn and get the correct objects added to the room.

As most of the work is done, Its a case of looking at the object table for that game location and reading the object type, x and y position and orientation, and then drawing the bitmap into place.

And.. Goal Achieved. I s'pose that I could colourise the objects and occasionally the orientation is coming out incorrect on some objects but in general, job done.

Could be very handy for an Atic Atac remake, being able to take basic data from the original game itself to draw an updated version.

Sunday, 27 September 2020

Lunchtime Coder #2 - BBC Micro Screen Graphics Viewer

After some success with the ZX Spectrum screen buffer interpreter ( See Post Here ) , I decided to have a go at an Acorn BBC Micro (Model B) screen interpreter.

It turned out to be a lot tougher going than I expected..

GOAL - To take a ".uef" BBC Micro Memory snapshot file, and interpret the screen buffer area of the memory into a display screen as would have been seen on the TV / monitor.

Fool that I am, I thought that this would be a reasonably straight forward process as it had been on the ZX spectrum however, the BBC Micro has different screen modes which have different resolutions and different colour depths. Also The start of the screen buffer is user definable and the colours available in that mode are also user definable.

This means that a lot of different values need to be read from the BBC Micro's memory before you can start to interpret the screen buffer into something understandable.

For the table below, the graphic resolutions for modes 3, 6 and 7 can be ignored as they are either text only or teletext based modes. Also there is only 8 colours listed for modes 2 and 7 as even though you can assign them to flash, there is still only 8 base colours.

I'm going to ignore the text only modes (Modes 3, 6 and 7) and concentrate specifically on the graphics screen modes.

A lot of BBC Micro games were done in Mode 2 or Mode 5. The horizontal resolution for those screens is reduced (160 instead of 320) however, each pixel in the screen buffer is drawn two pixels wide on screen, so that the overall picture on screen is still 320 pixels wide, but takes half the memory. The downside of this is that the screen is only half as detailed horizontally.

There are a lot of values in various BBC Micro memory locations that define how the graphics are drawn, and reading all of these is essential to be able to draw the screen correctly.

DEV 001 - A program that skips the ".euf" file header and footer, that reads the bytes from the BBC Micro memory dump part of the file, converts them into bits, writes the bits into an array so that the array is set out like the BBC Micro memory would be, and then reads the values required to draw the screen from the array. The output should be some values read from the array and converted into decimal.

There are three types of value to read and convert to decimal values:
1 - straight forward single Byte values
2 - Higher value spread over two bytes
3 - Higher two byte values with imaginary low byte that is always at 255.

You can see from the values below in DEV 001 that a number of other screen drawing related values can be derived from various BBC Micro memory locations.

DEV 002 - Now that we can read the values from the memory dump, lets try drawing something. The maximum resolution that the BBC micro can draw at is 640 x 256, so if we base the actual output display around a 1280 x 1024 size, this means that:

Mode 0 pixel is 2 x 4 interpreted pixels
Mode 1 Pixel is 4 x 4 interpreted pixels
Mode 2 pixel is 8 x 4 interpreted pixels
Mode 4 pixel is 4 x 4 interpreted pixels
Mode 5 pixel is 8 x 4 interpreted pixels

One thing I cant find in the BBC Micro memory or derive from the values in the memory is how it knows to draw wide pixels for mode 2 and mode 5, other than using a hard coded value of 320 for the screen width and then using the Current Graphics Window Right Column value.

A handy thing that I do remember from my childhood watching BBC micro games load first from tape, and then later on from disk, is that sometimes the loading game ran into the screen buffer and you could see the bits in the memory being loaded.

This would then draw garbage to parts of the screen, character by character, starting at the top left of the screen and working left to right and top to bottom.

When I say "Character by Character", a character is essentially an 8 x 8 square of pixels, and as the bits were drawn, they would again be drawn left to right, and top to bottom. (Later found to be incorrect.. see DEV 003).

With this in mind, the drawing "loop" should be 4 loops inside each other:

Outer loop 1 - Character Y position (derived from current text window top and bottom row
Outer Loop 2 - Character X psoition (derived from current text window left and right column)
Inner Loop 1 - Inside Character Pixel Y position ( 0 to 7 )
Inner Loop 2 - Inside Character Pixel X position ( 0 to 7 )

Then an x and y multiplication factor will be needed to draw the correct pixel size, depending on the mode being drawn.

Inside the four loops is the drawing program in four parts. Read from the screen display start memory location (adding an offset as you read and draw the bits) and decide what value the pixel is. Check what colour corresponds to that value. Draw the pixel. Update the offset to read the next pixels data.

Lets see how it looks:

What I've Got

What it should look like..

Obviously there is some issues here. Apart from the pixels being all over the place, there is also colour issues but.. I seem to have picked an odd one to start anyway as the screen mode is 1 (4 colours) and yet I can see 6 colours on screen on the proper one ?!

This routine works fine with mode 0, but mode 0 is simple to draw; 1 bit=1 pixel so read the bit and draw the pixel. Mode 1 and 4 have 2 bits per pixel, and to complicate this, the two associated bits are 3 bits apart. Four pixels per byte. Pixel 1 is bit 0 and 4, Pixel 2 is bit 1 and 5. Pixel 3 is bit 2 and 6 and Pixel 4 is bit 3 and 7.

Mode 0 - Works perfectly but is somewhat easier to draw than other modes; 1 bit per pixel

DEV 003 - After a lot of head scratching and staring at what I was drawing compared to what it should look like, I had a lightbulb moment!

I assumed that the pixels were drawn for evert mode as 8 pixels in a row before going to next row, and this is why Mode 0 worked, however I was wrong. Mode 0 works that way because it has 8 pixels per byte. What actually happens is a bytes worth of pixels is drawn (8, 4 or 2 pixels) and then you drop a row and draw the next byte and so on. So for mode 0, it will be draw 8 pixels then start the next row. For mode 1 and 4, it will draw 4 pixels and then start the next row and for mode 2 and 5, it will draw two pixels and start the next row.

This means that the amount of columns drawn is the difference between current text window left column and current text window right column but then multiplied by Bit Depth or Bits per pixel.

Bingo! Now we have something that looks a bit more like a BBC Micro screen.

However, While this looks good, It doesn't always work.


Case 1 - Citadel

Garbage and squished to the bottom of the display
Should be no garbage, and vertically central

There are two things wrong with this image;

1. You can see some garbage at the top of the screen. 2. The image is at the bottom of the screen, not centred as it should be.

The garbage at the top of the screen (The Top 8 rows of characters or top 64 rows of pixels) is because part of the screen buffer memory has been used as general memory.

You can also see from the values at the left that "Current Text Window Top Row" is set to 8, not 0. You can also see that the "Current Graphics Window Top Row" is set to 176, not 255

So its plausable that because the "Current Text Window Top Row" is set to 8, and the top 8 rows of characters are garbage, that the top 8 rows shouldn't be drawn. Thats pretty easy to fix.

There is also an offset for the picture of 24 pixels from the top, and 40 pixels from the bottom. Where that comes from, I do not know.. And what part the "Current Graphics Window Top Row" is set to 176, not 255 plays, again I do not know. None of these numbers leave you with 24 rows of pixels at the top.


Case 2 - Ultimate Title Screens

Whats in the screen buffer
What it Should look like

All of the screen data is there, but clearly the picture is narrower than the screen, although the current text window and current graphics window width settings are all set to max.

I guess that there is some different trickery going on here that doesn't conform to standard screen displaying, or some additional memory locations with settings that I should have included in the program.


Final Thought:

The BBC Micro used to get seriously knocked when compared to the ZX Spectrum and the Commodore 64 because of its limitations, however if you take a look at the screen shots below, you can see that this wasn't always deserved.

ZX Spectrum Atic Atac Start Screen
BBC Micro Atic Atac Start Screen

Lunchtime Coder #1 - Sinclair ZX Spectrum Bitmap and Graphics Buffer Viewer / Editor

As a small lunchtime coding project, I decided to write a ZX Spectrum bitmap viewer.

The idea of this was to arrange the bits in a ZX Spectrum ".sna", ".tzx", ".z80" or ".tap" file into columns of 8, 16, 24 or 32 bits wide in order to be able to view the game bitmaps.

The bits could be stepped through bit by bit or in larger steps and the display flipped upside down if required and if the bitmaps were upside down. When you found some interesting ones, you could snap them or if you wanted to, edit the bits to create custom game files.

The Viewer - Taking a Look at UPTG's "Underwurlde" Bitmaps.

The Snapshot Output.

With this done, I decided to add an extra mode; Screen Buffer Interpreter or TV Screen mode; A mode that would read the Screen Buffer part of the memory, and interpret it into what would actually be displayed on the TV / Monitor screen.

The ZX spectrum is pretty nifty when it comes to storing 16 colour graphics in a small amount of memory.

It has a single screen mode with a resolution of 256 x 192.

It could display 16 colours (well 15 really as two of the colours are Black). It achieved this by having a standard 8 colour pallette: Black, White, Red, Yellow, Green, Blue, Cyan and Magenta, and then having a brightnesses bit that allowed each of the colours to be displayed at two different brightness settings, with the exception of the previously mentioned Black colour. e.g. Red with Brightness bit set to 1 would have an RGB value of 255,0,0 whereas Red with Brightness bit set to 0 would have an RGB value of 215,0,0.

In normal screen buffer terms, If each pixel could be one of 15 colours, each pixel would need 4 bits to describe its colour. If that were the case with the ZX Spectrum, then 49,152 pixels at 4 bits per pixel would need 196,608 bits or 24,576 bytes or 24.5 kB of memory just for the screen buffer.

In a 48 kB ZX spectrum, that would leave you just 23.5 kB for the programing, and in a 16 kB ZX Spectrum, that would leave you no room for programing, and only half of the screen displayed.

Fortunately, Sinclair came up with a way of displaying 16 colours on screen but using considerably less memory, although this did have some limitations and lead to the infamous ZX Spectrum colour clash phenomenon.

Firstly, the actual graphics on screen are stored in just black and white, so that each pixel needs just one bit of memory; either 0 for black or 1 for white.

Then each 8 x 8 pixel square has an attribute byte. This byte has 3 bits for the foreground colour (Ink) and 3 bits for the background colour (Paper). There is then a Bright bit which if set to 1 makes both ink and paper as the brighter colour, rather than the darker colour, and then a flash bit that when set to 1, flashes the colour.

The total memory now used is 49,152 bits or 6 kB for the actual screen pixels, and then 768 bytes for the attributes (32 columns of 24 rows of 8 by 8 pixel squares).

So the whole screen fits in to less than 7 kB. Pretty clever, but comes with limitations. If you have two characters on screen of different colours, and they get close to each other, they will overlap onto each others Ink and Paper attributes, and this is where the infamous ZX Spectrum "Colour Clash" happens.

Note: The only other system I can think of with Colour Clash is the Arcade machine "Berzerk" by STERN, but the colour clash issue with Berzerk is for very different reasons.

The screen buffer part of the memory draws to the screen in a very specific way.
If you imagine the screen as an Excel spreadsheet with 192 rows and 256 columns, with each cell representing an on screen pixel.
To draw the screen, the bits are streamed from the memory to draw in black and white, firstly the whole of row 1, then row 9, then row 17, then row 25 and continuing to draw every eigth row for the top third of the screen.
The process is then repeated only this time starting at row 2, and every eighth row after for top half of screen, then starting at row 3, row 4 etc until you have drawn the whole top third of the screen in black and white.

Now the process is repeated only this time starting at row 65 to draw the middle third of the screen.

Finally the process repeated only this time starting at row 129 to draw the bottom third of the screen.

Once the whole screen is drawn in black and white, the screen attribute bytes are read and the Ink and Paint colours are applied, starting at the top left side of the screen and colouring each 8 x 8 square of pixels.

Screen Buffer in 8 bit width columns - Screen Attribute Bytes on RH side of Highlighted Square

Screen Buffer in 256 bit width - Screen Attribute Bytes at bottom of Highlighted Square
Screen Buffer Interpreted into Screen Display

This method of drawing the screen shouldn't be strange to anyone who owned a ZX Spectrum back in the day, as this is the order that the loading screens drew themselves when loading a game from tape. The bits were streamed from the tape into the first part of the ram, which was the screen buffer, and as they went into the memory, they started to slowly draw the loading screen in this secific order, as the video below shows.

Not exactly cutting edge, but a fun brain exercise for some boring lunchtimes.