Table of Contents

draw_direct.h

draw_direct.h provides macros and functions to support setting up draw operations by direct manipulation of blitter registers. The functions and macros are largely convenience functions for setting up the control registers for common operations, like drawing sprites or colored boxes.

In general the flow of Direct Drawing is:

  1. Set up either sprite or box mode with direct_prepare_sprite_mode or direct_prepare_box_mode
  2. Set values for the blitter parameters using the DIRECT_SET_ macros for SOURCE_X, SOURCE_Y, DEST_X, DEST_Y, WIDTH and HEIGHT
  3. Start the blitter with DIRECT_DRAW_START();
  4. Before modifying parameters to prepare the next drawing, ensure that the last drawing is finished with await_drawing();

Drawing Semantics

#define DIRECT_SET_DEST_X(x) vram[VX] = (x);
#define DIRECT_SET_DEST_Y(y) vram[VY] = (y);
#define DIRECT_SET_SOURCE_X(x) vram[GX] = (x) | direct_sprite_offset_x
#define DIRECT_SET_SOURCE_Y(y) vram[GY] = (y) | direct_sprite_offset_y
#define DIRECT_SET_WIDTH(w) vram[WIDTH] = (w);
#define DIRECT_SET_HEIGHT(h) vram[HEIGHT] = (h);
#define DIRECT_SET_COLOR(c) vram[COLOR] = ~(c);

`vram` points to the memory range that is alternately used for the Frame Buffer, the Sprite RAM, and the Blitter Control Registers. If the blitter is enabled (as done by calling one of the direct_prepare_ functions below) the first eight addresses in the VRAM range will map to the Blitter Control Registers.

Before using these, you'll need to call either direct_prepare_sprite_mode or direct_prepare_box_mode to ensure that the blitter control registers are ready to accept these parameters. (See below)

Functions

direct_prepare_sprite_mode

void direct_prepare_sprite_mode(SpriteSlot sprite);

Setup registers to draw sprites in direct mode Also checks for and awaits queued drawing operations

direct_quick_select_sprite

void direct_quick_select_sprite(SpriteSlot sprite);

Both this and direct_prepare_sprite_mode select the sprite slot to use but this skips other register settings and ONLY selects the sprite slot

direct_prepare_box_mode

void direct_prepare_box_mode();

Setup registers to draw colored boxes in direct mode Also checks for and awaits queued drawing operations

direct_tiled_mode

void direct_tiled_mode(bool enabled);

If enabled, sprite draws will repeat the same 16×16 grid from the source data

direct_transparent_mode

void direct_transparent_mode(bool enabled);

If enabled, sprite draws will treat color 0 as transparent instead of black

direct_clip_mode

void direct_clip_mode(clip_mode_t mode);

Set whether drawings will be clipped at screen edges or wrap around

direct_draw_sprite_frame

void direct_draw_sprite_frame(SpriteSlot sprite, char x, char y, char frame, char flip);

Draws a packed sprite as exported from Aseprite with a given X,Y position and frame number. A SpriteSlot is a handle given by allocate_sprite in sprites.h

Macros

DIRECT_SET_DEST_X

DIRECT_SET_DEST_X(x)

Sets the X position of the blitter's cursor into the framebuffer.

DIRECT_SET_DEST_Y

DIRECT_SET_DEST_Y(y)

Sets the Y position of the blitter's cursor into the framebuffer. Safe to modify during blits.

DIRECT_SET_SOURCE_X

DIRECT_SET_SOURCE_X(x)

Sets the X position of the blitter's cursor in the selected Sprite RAM page.

This macro also factors in the X offset bit, which is set or cleared by direct_prepare_sprite_mode or direct_quick_select_sprite based on the location of the selected SpriteSlot in Sprite RAM.

DIRECT_SET_SOURCE_Y

DIRECT_SET_SOURCE_Y(y)

Sets the Y position of the blitter's cursor in the selected Sprite RAM page. Safe to modify during blits.

This macro also factors in the Y offset bit, which is set or cleared by direct_prepare_sprite_mode or direct_quick_select_sprite based on the location of the selected SpriteSlot in Sprite RAM.

DIRECT_SET_WIDTH

DIRECT_SET_WIDTH(w)

Sets the width of the next blitter operation.

DIRECT_SET_HEIGHT

DIRECT_SET_HEIGHT(h)

Sets the height of the next blitter operation. Safe to modify during blits.

DIRECT_SET_COLOR

DIRECT_SET_COLOR(c)

Sets the color that will be used if the blitter is in solid color mode, as set by direct_prepare_box_mode.

DIRECT_DRAW_START

DIRECT_DRAW_START()

Use DIRECT_DRAW_START() to start a draw operation after setting the blit registers. This macro includes setting the draw_busy flag so that await_drawing() from gfx_sys.h works properly.

DIRECT_DRAW_CLEAR_IRQ

DIRECT_DRAW_CLEAR_IRQ()

Clears the IRQ flag that is set by the blitter when it completes a draw operation.

DIRECT_DRAW_SPRITE

DIRECT_DRAW_SPRITE(dst_x, dst_y, w, h, src_gx, src_gy)

Convenience macro for drawing a sprite, assuming that the sprite mode has already been set with direct_prepare_sprite_mode

DIRECT_DRAW_SPRITE

DIRECT_DRAW_SPRITE(dst_x, dst_y, w, h, c)

Convenience macro for drawing a colored box, assuming that the box mode has already been set with direct_prepare_box_mode

Examples

A basic tilemap drawing routine using Direct Draws

#include "gt/gametank.h"
#include "gt/gfx/sprites.h"
#include "gt/gfx/draw_direct.h"
#include "gt/banking.h"
#include "gen/assets/gfx.h"
 
/* Here is a tilemap rendering file that serves as an example of the Direct Drawing API
After calling direct_prepare_sprite_mode or direct_prepare_box_mode the blitter registers
are written to using vram[{registerName}]. When the parametrs are ready, use DIRECT_DRAW_START()
to start the blit which will also set the draw_busy flag so that await_drawing() functions correctly. */
 
SpriteSlot map_tile_gfx;
 
void load_tile_graphics() {
    map_tile_gfx = allocate_sprite(&ASSET__gfx__tileset_blue_bmp_load_list);
 
}
 
void draw_tile_map() {
    static char x, y, i, t;
    direct_prepare_sprite_mode(map_tile_gfx);
    direct_transparent_mode(false);
    push_rom_bank();
    change_rom_bank(ASSET__gfx__test1_bin_bank);
 
    x = 0;
    y = 0;
    i = 0;
    DIRECT_SET_DEST_Y(0);
    DIRECT_SET_WIDTH(16);
    DIRECT_SET_HEIGHT(16);
    while(i < 64) {
        t = ASSET__gfx__test1_bin_ptr[i];
        await_drawing();
        DIRECT_SET_DEST_X(x);
        DIRECT_SET_SOURCE_X(t << 4);
        DIRECT_SET_SOURCE_Y(t & ~15);
        DIRECT_DRAW_START();
        ++i;
        x += 16;
        if(x == 128) {
            x = 0;
            y += 16;
            DIRECT_SET_DEST_Y(y); //Incidentally, VY, GY, and Height are safe to set while a blit is still running.
        }
    }
    await_drawing();
 
    pop_rom_bank();
}