User Tools

Site Tools


sd:a_guide_to_graphics_programming_on_the_sd-8516

A Guide to Graphics Programming on the SD-8516

This is a general guide to graphics programming. It's not necessarily intended for games, it could be useful for UI programmers as well.

Introduction

The SD_8516 has all the capabilities you would expect from a late 80s “next generation” microcomputer. It also has some powerful features that were usually only available on consoles. You will find that programming graphics on the SD-8516 is fun, easy and rewarding.

For BASIC programmers, you can skip the sections that have assembly code in them. These are most useful for Assembly, Forth and C coders who need to do manual memory management. BASIC covers all of this for you; if you program in BASIC you can just focus on the sections that deal with BASIC commands.

Before we begin, let's introduce some key concepts about graphics programming on the SD-8516, such as the various Modes, the Framebuffer, the PPU, and INT $18.

Graphics Modes

The text modes do not have graphics ability. They are solely used for representing text, so we won't discuss them here.

Beyond the text modes are the graphics modes:

Mode Resolution Colors Description
3 320×200 16 This is a standard 320x200x16 bread-and-butter mode meant to evoke the best of the 8-bit graphics era.
4 256×224 16

format! |

5 256×224 256 A “Super” version of Mode 4 that can support up to 256 colors.
7 320×200 256 An 8bpp version of mode 3. For those that want such a thing.
8 128×128 16 An homage to the PICO-8. 128×128 16 color mode.
9 512×256 256 Super hi-res double-bank mode (experimental)

Almost everything that is discussed here will be applicable to all graphics modes. So, we will use Mode 3 as an example and note anything you need to watch out for in other modes.

The Framebuffer

The SD-8516 uses a memory-mapped framebuffer. To render a frame, the Video Chip scans the framebuffer's memory and builds an image from that data. This happens at the refresh rate of your monitor, usually sixty times per second but faster if you have set your monitor to a higher refresh rate.

It's important to understand how the framebuffer works. It's very simple; the bytes in the framebuffer represent pixels. In 8bpp mode, each byte represents the color of one pixel on the screen. In 4bpp mode, each byte represents two pixels; the low-order nibble represents the even pixel and the high-order nibble represents the odd pixel. That means if you POKE a value into one byte, you are treating the screen like it's half resolution; many games worked this way to save code-space, such as Jumpman and King's Quest.

Therefore the BASIC command:

  POKE $020000, 1

will set the pixel at 0,0 to palette color 1 in an 8bpp mode, but it will set the pixels at 0,0 and 1,0 to palette color 1 in 4bpp mode.

Here's another example. If you want to set 0,0 to color 1 and 1,0 to color 2, you can do this:

  POKE $020000, $21

This sets the low nibble to 1 and the high nibble to 2. Remember, $21 is a hexidecimal number; each place in hex is 4 bits.

Framebuffer Memory Map

The framebuffer for mode 3 is stored in the first 32kb of Bank 2. Some modes, such as mode 5 and 7 use almost all of bank 2. Mode 9 uses both bank 2 and bank 3. Memory which isn't being used can be used by your programs; so if you're using Mode 3, you can store data in the second half of bank 2.

Accessing the Framebuffer

For BASIC, you can PEEK and POKE at framebuffer memory or use the PIXEL/PEXEL commands:

  10 LET A = PEXEL(10,10)
  20 LET A = A + 1
  30 PIXEL 10, 10, A

This program reads a pixel and updates it's color.

Packing and Unpacking pixels

For Assembly and other languages, you will need to pack and unpack the pixel. In Assembly you can use PAB and UAB, but in Forth or other languages you must mask the byte (and do a bit shift for the upper nibble).

In assembly:

  LDAL [$020000] ; read the byte at 0,0
  UAB            ; This command splits AL into AL=low nibble and BL = high nibble. 
  LDAL $0E       ; Set 0,0 to palette color $E (decimal 14)
  LDBL $0C       ; set 1,0 to palette color $C (decimal 12)
  PAB            ; Pack BL into high nibble of AL. AL is now $CE
  
  STAL [$020000] ; Stores $CE, the color of two pixels, in the framebuffer.

The stride of a 320×200 screen in 4bpp is 160 bytes. Therefore, if you wanted to deal with a pixel at location X, Y:

  LDELM $020000  ; load framebuffer base
  MUL Y, #160    ; Skip ahead to the correct row
  ADD ELM, Y
  
  MOV T, X
  AND T, #1      ; T is now whether X was even or odd.
  SHR X          ; Divide ELM by 2.
  ADD ELM, X     ; Skip forward by 1 byte per 2 pixels
  
  ; Elm now points to the even and odd pixel you need.
  LDAL [ELM]
  UAB            ; AL & BL now contain the even and odd pixel color

At this point, if T is 0 you can deal with the color in AL, and if T is 1 you can deal with the color in BL. When you're done,

  PAB
  STAL [ELM]     ; Write the pixels back into the framebuffer

For 8bpp modes you don't need to worry about this at all. The byte is the pixel.

The Three Main Systems

The SD-8516 has a PPU (picture processing unit) which aids in graphics programming. This is the fastest way to do graphics programming. Stellar BASIC uses the PPU to accelerate graphics performance, so BASIC programmers are already using the fast path here.

For Assembly programmers, there are two other systems. The KERNAL includes INT 0x18 which is a graphics services library. This library is the reference implementation for various graphics drawing algorithms. The main difference between drawing to the framebuffer yourself and using INT 18h is the price of an INT system call (essentially a CALL+RET).

The PPU is the second system. The PPU is accessed via INT 0x03 AH = $01. The subcommand is in AL. We will discuss each command and their calling conventions in the sections below.

The third system is a direct call to the PPU via an opcode. This is just like how the FPU works on older 80×86 systems; or how cartridges can add extra opcodes. The opcode instructions and their calling conventions will be discussed in the sections below.

1. Clearing the Screen

Clearing the screen is a good way to ensure a default initial state for a program.

In BASIC, the CLS command will clear the screen of the mode you are in.

For Assembly, INT 18h, AH=20h will clear the screen in a graphics mode.

  LDAH $20    ; Clear Screen
  INT 0x18

You can also use the PPU to do this. This way is very fast.

  LDA $0100   ; AH=$01 (PPU)  AL=$00 (Clear Screen)
  INT 0x03

2. Drawing (and reading) a Pixel

We've discussed how to do this in BASIC and Assembly above under “Accessing the Framebuffer” and “Packing and Unpacking Pixels”.

However, Assembly programmers will be pleased to know the PPU calls for this.

  LDA $0101   ; AH=$01 (PPU)  AL=$01 (plot_pixel)
  INT 0x03

or

  PPIXEL

PPIXEL is not faster than calling INT $3, however, you don't have to LDA $0100 and that can save time. In a loop where LDA can remain $0101 they are approximately as fast as each other.

The calling convention is X, Y, CK for X position, Y position, and pixel color. The PPU is mode-aware, so it will automatically do 4bpp pixel conversion for you.

To read from a pixel quickly you can load it from the framebuffer, or use the PPU:

  LDA $0102   ; AH=$01 (PPU)  AL=$02 (read_pixel)
  INT 0x03

The color will be returned in CL.

3. Drawing a Line

In BASIC, you can use the LINE command:

  LINE x1, y1, x2, y2, color

Assembly has AH=$12 INT 0x18:

  ; ============================================================================
  ; AH=21h - Draw Line (Bresenham's Algorithm)
  ; Input:  X = x0, Y = y0 (start point)
  ;         I = x1, J = y1 (end point)
  ;         CL = color
  ; Output: None
  ; ============================================================================

However, the fastest way to draw a line is with the PPU. The calling convention is to draw a line from X,Y to I,J in color CL.

  LDA $0103    ; AH=$01 (PPU)  AL=$03 (draw_line)
  INT 0x03

you can also use PLINE:

  PLINE

PLINE is like PPIXEL, it's sometimes faster to use PPIXEL than make a call to INT 0x03.

under construction

FIXME

sd/a_guide_to_graphics_programming_on_the_sd-8516.txt · Last modified: by appledog

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki