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#
type Surface = object#

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.


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: uint, bpp: uint, 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: uint)#

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

proc getPtr(srf: SomeSurface, x, y: uint): pointer#

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

proc getPtr(srf: SomeSurface, x, y: uint, stride: uint): 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: uint, bpp: uint): uint#

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: uint)#

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: uint)#

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: int): uint32#

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

proc plot(dst: SurfaceBmp16, x, y: int, 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: int, 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: int, 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: int, 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: int, 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: int, 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: int, width, height: uint, src: SurfaceBmp16, srcX, srcY: int)#

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: int, 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: uint, 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: int): uint32#

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

proc plot(dst: SurfaceBmp8, x, y: int, 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: int, 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: int, 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: int, 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: int, 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: int, 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: int, width, height: uint, src: SurfaceBmp8, srcX, srcY: int)#

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: int, 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: uint, 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: int): uint32#

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

proc plot(dst: SurfaceChr4c, x, y: int, 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: int, 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: int, 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: int, 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: int, 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: int, 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: int, width, height: uint, src: SurfaceChr4c, srcX, srcY: int)#

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: int, 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: uint16)#

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: uint, stride: uint): pointer#

Inline version of getPtr(). Use with caution.


4bpp tiled surfaces, row-major#

proc init(srf: var SurfaceChr4r, data: pointer, width, height: uint, 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: int): uint32#

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

proc plot(dst: SurfaceChr4r, x, y: int, 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: int, 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: int, 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: int, 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: int, 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: int, 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: uint16)#

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: int): ptr uint32#

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