surfaces

Libtonc’s Surface system provides the basic functionality for drawing onto graphic surfaces of different types.

  • srfBmp8: 8bpp linear (Mode 4 / affine BGs)

  • srfBmp16: 16bpp bitmaps (Mode 3/5 / regular BGs to some extent)

  • srfChr4c: 4bpp tiles, column-major (Regular tiled BG)

  • srfChr4r: 4bpp tiles, row-major (Regular tiled BG, OBJs)

For each of these, procedures exist for the most important drawing options: plotting, lines and rectangles. For BMP8/BMP16 and to some extent CHR4C, there are blitters as well.

Column-major vs row-major

A (4bpp) tiled surface is formed when each tilemap entry references a unique tile (this is done by prepMap). The pixels on the tiles will then uniquely map onto pixels on the screen. There are two ways of map-layout here: row-major indexing and column-major indexing. The difference if is that tile 1 is to the right of tile 0 in the former, but under it in the latter.

e.g. on a 30x20 tile screen:

Row-major:
  0  1  2  3 ...
  30 31 32 33 ...
  60 61 62 63 ...

Column-major:
  0 20 40 60 ...
  1 21 41 61 ...
  2 22 41 62 ...

With 4bpp tiles, the column-major version makes the Y coordinate match up nicely with successive words. For this reason, column-major is usually preferred over row-major.


Types

type SurfaceKind = enum
  • srfNoneNo specific type.
  • srfBmp1616bpp linear (bitmap/tilemap).
  • srfBmp88bpp linear (bitmap/tilemap).
  • srfChr4r4bpp tiles, row-major.
  • srfChr4c4bpp tiles, column-major.
type Surface = object

    Field    

    Type    

    Description    

data ptr uint8

Surface data pointer.

pitch uint32

Scanline pitch in bytes.

width uint16

Image width in pixels.

height uint16

Image width in pixels.

bpp uint8

Bits per pixel.

kind SurfaceKind

Surface type (not used that much).

palSize uint16

Number of colors.

palData ptr Palette

Pointer to palette.

Note

While Tonc has one Surface type, below we provide several distinct versions of it. This allows us to simplify the names of procedures via overloading, and it becomes impossible to call the wrong procedure on the wrong kind of surface.

type SurfaceBmp16 = distinct Surface

16bpp linear (bitmap/tilemap).

type SurfaceBmp8 = distinct Surface

8bpp linear (bitmap/tilemap).

type SurfaceChr4r = distinct Surface

4bpp tiles, row-major.

type SurfaceChr4c = distinct Surface

4bpp tiles, column-major.

type SomeSurface = Surface | SurfaceBmp16 | SurfaceBmp8 | SurfaceChr4c | SurfaceChr4r
type SurfacePtr = ptr Surface
type SurfaceBmp16Ptr = ptr SurfaceBmp16
type SurfaceBmp8Ptr = ptr SurfaceBmp8
type SurfaceChr4cPtr = ptr SurfaceChr4c
type SurfaceChr4rPtr = ptr SurfaceChr4r
type SomeSurfacePtr = ptr SomeSurface

Variables

These allow you to access the bitmap mode drawing targets as surfaces. This seems overkill, you might prefer to use the bitmap drawing routines directly instead.

let m3Surface: SurfaceBmp16
var m4Surface: SurfaceBmp8
var m5Surface: SurfaceBmp16
let bmp16Tab: SurfaceProcTab
let bmp8Tab: SurfaceProcTab
let chr4cTab: SurfaceProcTab

Common Procedures

proc init(srf: var Surface, ty: SurfaceKind, data: pointer, width, height: cuint, bpp: cuint, pal: ptr Palette)

Initalize a surface for ty-formatted graphics.

Prefer to use the type-specific init procedures below instead.

proc copyColors(dst, src: SomeSurface, count: cuint)

Copy count colors from src’s palette to dst’s palette.

proc getPtr(srf: SomeSurface, x, y: cuint): pointer

Get the byte address of coordinates (x, y) on the surface.

proc getPtr(srf: SomeSurface, x, y: cuint, stride: cuint): pointer

Inline version of getPtr(). Use with caution.

proc setPtr(srf: var SomeSurface, `ptr`: pointer)

Set the data-pointer for surface srf.

proc align(width: cuint, bpp: cuint): cuint

Get the word-aligned number of bytes for a scanline.

Width:

Number of pixels.

Bpp:

Bits per pixel.

proc setPal(srf: var SomeSurface, pal: ptr Palette, size: cuint)

Set the palette pointer and its size.


16bpp bitmap surfaces

Routines for 16bpp linear surfaces. For use in modes 3 and 5. Can also be used for regular tilemaps to a point.

proc init(srf: var SurfaceBmp16, data: pointer, width, height: cuint)

Initalize a 16bpp bitmap surface.

Srf:

Surface to initialize.

Data:

Pointer to the surface memory.

Width:

Width of surface.

Height:

Height of surface.

proc getPixel(src: SurfaceBmp16, x, y: cint): uint32

Get the pixel value of src at (x, y).

proc plot(dst: SurfaceBmp16, x, y: cint, clr: uint32)

Plot a single pixel on a 16-bit buffer; inline version.

Dst:

Destination surface.

X:

X-coord.

Y:

Y-coord.

Clr:

Color.

proc hline(dst: SurfaceBmp16, x1, y, x2: cint, clr: uint32)

Draw a horizontal line on an 16bit buffer.

Dst:

Destination surface.

X1:

First X-coord.

Y:

Y-coord.

X2:

Second X-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc vline(dst: SurfaceBmp16, x, y1, y2: cint, clr: uint32)

Draw a vertical line on an 16bit buffer.

Dst:

Destination surface.

X:

X-coord.

Y1:

First Y-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc line(dst: SurfaceBmp16, x1, y1, x2, y2: cint, clr: uint32)

Draw a line on an 16bit buffer.

Dst:

Destination surface.

X1:

First X-coord.

Y1:

First Y-coord.

X2:

Second X-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc rect(dst: SurfaceBmp16, left, top, right, bottom: cint, clr: uint32)

Draw a rectangle in 16bit mode.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc frame(dst: SurfaceBmp16, left, top, right, bottom: cint, clr: uint32)

Draw a rectangle in 16bit mode.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc blit(dst: SurfaceBmp16, dstX, dstY: cint, width, height: cuint, src: SurfaceBmp16, srcX, srcY: cint)

16bpp blitter. Copies a rectangle from one surface to another.

Dst:

Destination surface.

DstX:

Left coord of rectangle on dst.

DstY:

Top coord of rectangle on dst.

Width:

Width of rectangle to blit.

Height:

Height of rectangle to blit.

Src:

Source surface.

SrcX:

Left coord of rectangle on src.

SrcY:

Top coord of rectangle on src.

Note

The rectangle will be clipped to both src and dst.

proc floodfill(dst: SurfaceBmp16, x, y: cint, clr: uint32)

Floodfill an area of the same color with new color clr.

Dst:

Destination surface.

X:

X-coordinate.

Y:

Y-coordinate;

Clr:

Color.


8bpp bitmap surfaces

Routines for 8bpp linear surfaces. For use in mode 4 and affine tilemaps.

proc init(srf: var SurfaceBmp8, data: pointer, width, height: cuint, pal: ptr Palette)

Initalize an 8bpp bitmap surface.

Srf:

Surface to initialize.

Data:

Pointer to the surface memory.

Width:

Width of surface.

Height:

Height of surface.

Pal:

Pointer to the surface’s palette.

proc getPixel(src: SurfaceBmp8, x, y: cint): uint32

Get the pixel value of src at (x, y); inline version.

proc plot(dst: SurfaceBmp8, x, y: cint, clr: uint32)

Plot a single pixel on a 8-bit buffer; inline version.

Dst:

Destination surface.

X:

X-coord.

Y:

Y-coord.

Clr:

Color.

proc hline(dst: SurfaceBmp8, x1, y, x2: cint, clr: uint32)

Draw a horizontal line on an 8-bit buffer.

Dst:

Destination surface.

X1:

First X-coord.

Y:

Y-coord.

X2:

Second X-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc vline(dst: SurfaceBmp8, x, y1, y2: cint, clr: uint32)

Draw a vertical line on an 8-bit buffer.

Dst:

Destination surface.

X:

X-coord.

Y1:

First Y-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc line(dst: SurfaceBmp8, x1, y1, x2, y2: cint, clr: uint32)

Draw a line on an 8-bit buffer.

Dst:

Destination surface.

X1:

First X-coord.

Y1:

First Y-coord.

X2:

Second X-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc rect(dst: SurfaceBmp8, left, top, right, bottom: cint, clr: uint32)

Draw a rectangle in 8-bit mode.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc frame(dst: SurfaceBmp8, left, top, right, bottom: cint, clr: uint32)

Draw a rectangle in 8-bit mode.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc blit(dst: SurfaceBmp8, dstX, dstY: cint, width, height: cuint, src: SurfaceBmp8, srcX, srcY: cint)

16bpp blitter. Copies a rectangle from one surface to another.

Dst:

Destination surface.

DstX:

Left coord of rectangle on dst.

DstY:

Top coord of rectangle on dst.

Width:

Width of rectangle to blit.

Height:

Height of rectangle to blit.

Src:

Source surface.

SrcX:

Left coord of rectangle on src.

SrcY:

Top coord of rectangle on src.

Note

The rectangle will be clipped to both src and dst.

proc floodfill(dst: SurfaceBmp8, x, y: cint, clr: uint32)

Floodfill an area of the same color with new color clr.

Dst:

Destination surface.

X:

X-coordinate.

Y:

Y-coordinate;

Clr:

Color.


4bpp tiled surfaces, column-major

proc init(srf: var SurfaceChr4c, data: pointer, width, height: cuint, pal: ptr Palette)

Initalize a surface for 4bpp column-major tiles.

Srf:

Surface to initialize.

Data:

Pointer to the surface memory.

Width:

Width of surface.

Height:

Height of surface.

Pal:

Pointer to the surface’s palette.

proc getPixel(src: SurfaceBmp16, x, y: cint): uint32

Get the pixel value of src at (x, y).

proc plot(dst: SurfaceChr4c, x, y: cint, clr: uint32)

Plot a single pixel on a 4bpp tiled surface; inline version.

Dst:

Destination surface.

X:

X-coord.

Y:

Y-coord.

Clr:

Color.

Note

Fairly slow. Inline plotting functionality if possible.

proc hline(dst: SurfaceChr4c, x1, y, x2: cint, clr: uint32)

Draw a horizontal line on a 4bpp tiled surface.

Dst:

Destination surface.

X1:

First X-coord.

Y:

Y-coord.

X2:

Second X-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc vline(dst: SurfaceChr4c, x, y1, y2: cint, clr: uint32)

Draw a vertical line on a 4bpp tiled surface.

Dst:

Destination surface.

X:

X-coord.

Y1:

First Y-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc line(dst: SurfaceChr4c, x1, y1, x2, y2: cint, clr: uint32)

Draw a line on a 4bpp tiled surface.

Dst:

Destination surface.

X1:

First X-coord.

Y1:

First Y-coord.

X2:

Second X-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc rect(dst: SurfaceChr4c, left, top, right, bottom: cint, clr: uint32)

Render a rectangle on a 4bpp tiled canvas.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color-index.

proc frame(dst: SurfaceChr4c, left, top, right, bottom: cint, clr: uint32)

Draw a rectangle on a 4bpp tiled surface.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc blit(dst: SurfaceChr4c, dstX, dstY: cint, width, height: cuint, src: SurfaceChr4c, srcX, srcY: cint)

Blitter for 4bpp tiled surfaces. Copies a rectangle from one surface to another.

Dst:

Destination surface.

DstX:

Left coord of rectangle on dst.

DstY:

Top coord of rectangle on dst.

Width:

Width of rectangle to blit.

Height:

Height of rectangle to blit.

Src:

Source surface.

SrcX:

Left coord of rectangle on src.

SrcY:

Top coord of rectangle on src.

Note

The rectangle will be clipped to both src and dst.

proc floodfill(dst: SurfaceChr4c, x, y: cint, clr: uint32)

Floodfill an area of the same color with new color clr.

Dst:

Destination surface.

X:

X-coordinate.

Y:

Y-coordinate;

Clr:

Color.

Note

This routines is probably very, very slow.

proc prepMap(srf: SurfaceChr4c, map: ptr ScrEntry | ptr UncheckedArray[ScrEntry], se0: ScrEntry)

Prepare a screen-entry map for use with chr4.

Srf:

Surface with size information.

Map:

Screen-blocked map to initialize.

Se0:

Additive base screen-entry.

proc getPtr(srf: SomeSurface, x, y: cuint, stride: cuint): pointer

Inline version of getPtr(). Use with caution.


4bpp tiled surfaces, row-major

proc init(srf: var SurfaceChr4r, data: pointer, width, height: cuint, pal: ptr Palette)

Initalize a surface for 4bpp row-major tiles.

Srf:

Surface to initialize.

Data:

Pointer to the surface memory.

Width:

Width of surface.

Height:

Height of surface.

Pal:

Pointer to the surface’s palette.

proc getPixel(src: SurfaceChr4c, x, y: cint): uint32

Get the pixel value of src at (x, y); inline version.

proc plot(dst: SurfaceChr4r, x, y: cint, clr: uint32)

Plot a single pixel on a 4bpp tiled surface; inline version.

Dst:

Destination surface.

X:

X-coord.

Y:

Y-coord.

Clr:

Color.

Note

Slow as fuck. Inline plotting functionality if possible.

proc hline(dst: SurfaceChr4r, x1, y, x2: cint, clr: uint32)

Draw a horizontal line on a 4bpp tiled surface. :dst: Destination surface. :x1: First X-coord. :y: Y-coord. :x2: Second X-coord. :clr: Color.

Note

Does normalization, but not bounds checks.

proc vline(dst: SurfaceChr4r, x, y1, y2: cint, clr: uint32)

Draw a vertical line on a 4bpp tiled surface.

Dst:

Destination surface.

X:

X-coord.

Y1:

First Y-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc line(dst: SurfaceChr4r, x1, y1, x2, y2: cint, clr: uint32)

Draw a line on a 4bpp tiled surface.

Dst:

Destination surface.

X1:

First X-coord.

Y1:

First Y-coord.

X2:

Second X-coord.

Y2:

Second Y-coord.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc rect(dst: SurfaceChr4r, left, top, right, bottom: cint, clr: uint32)

Render a rectangle on a tiled canvas.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color-index. Octupled if > 16.

proc frame(dst: SurfaceChr4r, left, top, right, bottom: cint, clr: uint32)

Draw a rectangle on a 4bpp tiled surface.

Dst:

Destination surface.

Left:

Left side of rectangle;

Top:

Top side of rectangle.

Right:

Right side of rectangle.

Bottom:

Bottom side of rectangle.

Clr:

Color.

Note

Does normalization, but not bounds checks.

proc prepMap(srf: SurfaceChr4r, map: ptr ScrEntry | ptr UncheckedArray[ScrEntry], se0: ScrEntry)

Prepare a screen-entry map for use with chr4.

Srf:

Surface with size information.

Map:

Screen-blocked map to initialize.

Se0:

Additive base screen-entry.

proc getPtr(srf: SurfaceChr4c, x, y: cint): ptr uint32

Special pointer getter for chr4: start of in-tile line.