ubox.lib reference

Version 1.2.0

Control functions

The supported controls are: cursor and joystick (port 1 and port 2).

In the case of cursor, space key is used as fire 1 and the “m” key as fire 2.

For one button joysticks, ubox_read_keys can be used to provide an alternative fire 2 button using the keyboard.

ubox_read_ctl

uint8_t ubox_read_ctl(uint8_t control);

Read the control identified by control and return the status of it.

Possible control values are:

Control Description
UBOX_MSX_CTL_CURSOR Cursor for move, space for fire 1 and “m” for fire 2
UBOX_MSX_CTL_PORT1 Joystick on port 1
UBOX_MSX_CTL_PORT2 Joystick on port 2
UBOX_MSX_CTL_NONE No control is selected. This is the default output of ubox_select_ctl

The control status is a bit map with the following values:

Mask Bit
UBOX_MSX_CTL_UP 0
UBOX_MSX_CTL_DOWN 1
UBOX_MSX_CTL_LEFT 2
UBOX_MSX_CTL_RIGHT 3
UBOX_MSX_CTL_FIRE1 4
UBOX_MSX_CTL_FIRE2 5

Example:

if (ubox_read_ctl(UBOX_MSX_CTL_CURSOR) & UBOX_MSX_CTL_UP)
{
     // in the cursor, UP is on
}

ubox_read_keys

uint8_t ubox_read_keys(uint8_t row);

Reads a row of the keyboard matrix and returns a bit map with the state of the keys in that row.

It is important to remember that there are different keyboard layouts and that there is no reliable way of detecting 100% of them.

Constants for the QWERTY layout are provided as UBOX_MSX_KEY_*, and that covers the most common models.

Example:

// read row 7 that includes RET, SEL, BS, STOP, TAB, ESC, F5 and F4
uint8_t keys = ubox_read_keys(7);

if (keys & UBOX_MSX_KEY_ESC)
{
     // ESC key is pressed
}

ubox_select_ctl

uint8_t ubox_select_ctl(void);

Waits for trigger on cursor (space or “m”) or any of the joysticks, and returns the selected control.

See ubox_read_ctl for possible control values.

Interrupt and clock functions

ubox_init_isr

void ubox_init_isr(uint8_t wait_ticks);

Installs and initializes the interrupt handler.

wait_ticks is the maximum number of interrupts that ubox_wait will wait. This value divides the frequency at which the machine generates the vsync interrupt (50Hz for PAL and 60Hz for NTSC).

Some common values are:

wait ticks PAL NTSC
1 50 FPS 60 FPS
2 25 FPS 30 FPS
3 16.6 FPS 20 FPS

Where FPS is the number of frames per second desired to update the game logic.

Example:

// ubox_wait will wait for 2 ints (25 FPS)
ubox_init_isr(2);

This function must be called once before any of the interrupt and clock functions are used.

The installed interrupt handler uses HTIMI_HOOK instead of replacing the BIOS handler.

The interrupt handler will save all registers. The shadow registers are not preserved or used.

For performance reasons the BIOS keyboard buffer and key repeat functionality are disabled, and because of that some BIOS functions, such as CHGET, won’t work.

ubox_reset_tick

void ubox_reset_tick(void);

Sets ubox_tick to zero.

ubox_tick is a 8-bit global variable that is incremented on every interrupt.

ubox_set_user_isr

void ubox_set_user_isr(void (*fn)(void));

Installs a user interrupt handler.

The function pointed by fn doesn’t need to preserve any registers because that is done by the main interrupt handler.

It is recommended that the user interrupt handler is short and uses the minimal amount of CPU cycles.

Example:

uint8_t tick = 0;

void my_isr()
{
     // count interrupts
     ++tick;
}

ubox_set_user_isr(my_isr);

ubox_wait

void ubox_wait(void);

Waits for a maximum wait_ticks interrupts (see ubox_init_isr).

This function counts the interrupts (ticks) between between current call to ubox_wait and the previous one, and if less than wait_ticks ticks have passed, it will wait.

This is used to ensure that the game loop used time is constant and hence the game plays smooth in case some updates are faster than others.

If the time passed between current ubox_wait call and the previous is larger than wait_ticks, no waiting happens. This may mean that the game loop takes longer than expected and, if that happens frequently, it would be recommended to increase wait_ticks value when calling ubox_init_isr.

Example:

// 25 FPS on PAL, 30 FPS on NTSC
ubox_init_isr(2);

// game loop example
while (1)
{
     update_controls();

     update_entities();
     draw_entities();

     // ensure that one loop takes at least 2 interrupts
     ubox_wait();
}

ubox_wait_for

void ubox_wait_for(uint8_t frames);

Waits for frames frames.

This is used to wait a fixed amount of time measured in frames.

Because frames is 8-bit value, this funcion can only wait for 255 frames in one single call.

Example:

// assuming PAL and wait_ticks 2
// wait for 10 seconds
ubox_wait_for(250);

Screen and VDP functions

These functions are not necessarily MSX 1 specific, but only MSX 1 functionality is documented.

Both the tiles and sprite functions target Screen 2 (256x192 pixels graphics mode).

The VRAM layout for Screen 2 is as follows:

Address range Description
0x0000-0x17ff Background tiles
0x1800-0x1aff Background tile map
0x1b00-0x1b7f Sprite attributes
0x2000-0x37ff Background colors
0x3800-0x3fff Sprite patterns

ubox_disable_screen

void ubox_disable_screen(void);

Disables the screen.

Any content drawn to the screen won’t be visible until the screen is enabled with ubox_enable_screen.

Note that ubox_set_mode also enables the screen.

ubox_enable_screen

void ubox_enable_screen(void);

Enables the screen.

ubox_get_vsync_freq

uint8_t ubox_get_vsync_freq(void);

Returns the default interrupt frequency according to the BIOS.

Possible values are:

Value Frequency
0 60Hz
1 50Hz

ubox_read_vm

void ubox_read_vm(uint8_t *dst, uint16_t len, const uint8_t *src);

Reads a block of len bytes from src in VMEM (video memory) to dst in memory.

ubox_set_colors

void ubox_set_colors(uint8_t fg, uint8_t bg, uint8_t border);

Changes the screen colors.

First it sets FORCLR (foreground) to fg, BAKCLR (background) to bg and BDRCLR to border, and then makes them active.

Example:

// sets all three colours to black
ubox_set_colors(1, 1, 1);

ubox_set_mode

void ubox_set_mode(uint8_t mode);

Sets the screen mode to mode.

This is a list of the different MSX 1 modes:

Mode Name Description
0 Screen 0 40x24 text mode
1 Screen 1 32x24 colored text mode
2 Screen 2 256x192 graphics mode
3 Screen 3 64*48 block graphics multicolor mode

Example:

// sets Screen 2
ubox_set_mode(2);

ubox_wait_vsync

#define ubox_wait_vsync() do { \
    __asm; \
    halt \
    __endasm; \
} while(0)

This macro waits for the vsync interrupt.

Interrupts must be enabled or this code will block indefinitely.

Example:

ubox_wait_vsync();
// code to run after the int

ubox_write_vm

void ubox_write_vm(uint8_t *dst, uint16_t len, const uint8_t *src);

Writes a block of len bytes from src in memory to dst in VRAM (video memory).

Example:

// copy 4 sprites attributes from a buffer to the
// sprite attribute table in Screen 2 mode
ubox_write_vm((uint8_t*)0x1b00, 4 * 4, buffer);

ubox_wvdp

void ubox_wvdp(uint8_t reg, uint8_t data);

Writes data to the reg VDP register.

This function is used to setup the VDP, for example to enable 16x16 sprites.

The VDP has 8 registers, from 0 to 7. For example, it is common to use register 1 to enable 16x16 sprites.

The control bits in register 1 are:

Bit Description
0 Enable sprite zoom (x2)
1 Enable 16x16 sprites (default is 8x8)
2 Not used
3 Enable Mode M2, Screen 3 (block)
4 Enable Mode M1, Screen 0 (text)
5 Enable v-blank interrupt
6 Enable screen output control
7 VRAM size control (0: 4K, 1: 16K)

Please refer to Portar Doc for further info on VDP registers.

Example:

// reg 1: activate sprites, v-blank int on, 16x16 sprites
ubox_wvdp(1, 0xe2);

Sprite functions

All the functions require screen 2 (256x192 graphics mode, see ubox_set_mode).

struct sprite_attr

struct sprite_attr {
    uint8_t y;
    uint8_t x;
    uint8_t pattern;
    uint8_t attr;
};

Structure to define sprite attributes.

Field Description
x The horizontal position of the sprite on the screen.
y The vertical position of the sprite on the screen. This coordinate starts in -1 (0xff) instead of 0.
pattern The index in the sprite pattern table. When 16x16 sprites are enabled, the lower two bits are ignored (4 regular 8x8 sprites form one 16x16 sprite).
attr The sprite attributes. The bits 0-3 are used for color and bit 7 is EC (Early Clock).

When EC is enabled, the sprite is displaced 32 pixels to the left.

ubox_set_sprite_attr

void ubox_set_sprite_attr(const struct sprite_attr *attr, uint8_t sprite);

Sets the sprite attributes of sprite number sprite using the attributes pointed by attr.

sprite is the index in the sprite table of Screen 2.

See struct sprite_attr description for details on the sprite attributes.

Example:

ubox_set_sprite_attr(&player_sprite_attr, 0);

To set the attributes of multiple sprites that are contiguous in the sprite table, it is recommended to use ubox_write_vm. The sprite attribute table is in the memory address 0x1b00.

ubox_set_sprite_pat16

void ubox_set_sprite_pat16(const uint8_t *data, uint8_t pattern);

Sets the sprite pattern data pointed by data into pattern number pattern.

pattern is the index in the sprite pattern table of Screen 2.

This function will set a 16x16 pixels pattern. The pattern is equivalent to setting four 8x8 patterns (upper left, lower left, upper right and lower right).

See ubox_set_sprite_pat8 to set a 8x8 pixels pattern.

ubox_set_sprite_pat16_flip

void ubox_set_sprite_pat16_flip(const uint8_t *data, uint8_t pattern);

Sets the sprite pattern data pointed by data into pattern number pattern, flipping the pattern data horizontally.

pattern is the index in the sprite pattern table of Screen 2.

This function will set a 16x16 pixels pattern. The pattern is equivalent to setting four 8x8 patterns (upper left, lower left, upper right and lower right).

See ubox_set_sprite_pat8_flip to set a 8x8 pixels pattern.

ubox_set_sprite_pat8

void ubox_set_sprite_pat8(const uint8_t *data, uint8_t pattern);

Sets the sprite pattern data pointed by data into pattern number pattern.

pattern is the index in the sprite pattern table of Screen 2.

This function will set a 8x8 pixels pattern.

See ubox_set_sprite_pat16 to set a 16x16 pixels pattern.

ubox_set_sprite_pat8_flip

void ubox_set_sprite_pat8_flip(const uint8_t *data, uint8_t pattern);

Sets the sprite pattern data pointed by data into pattern number pattern, flipping the pattern data horizontally.

pattern is the index in the sprite pattern table of Screen 2.

This function will set a 8x8 pixels pattern.

See ubox_set_sprite_pat16_flip to set a 16x16 pixels pattern.

Tile functions

All the functions require screen 2 (256x192 graphics mode, see ubox_set_mode).

ubox_fill_screen

void ubox_fill_screen(uint8_t tile);

Fills the screen with the tile from current tile set identified by tile index.

See ubox_set_tiles for for information on how to set a tile set.

ubox_get_tile

uint8_t ubox_get_tile(uint8_t x, uint8_t y);

Returns the tile index at position (x, y).

x and y units are tiles, and both are 0 based.

ubox_put_tile

void ubox_put_tile(uint8_t x, uint8_t y, uint8_t tile);

Puts a tile from current tile set on the screen. The tile is identified by index tile and placed on position (x,y).

x and y units are tiles, and both are 0 based.

Example:

// put the tile with index 1 on the top left corner of the screen
ubox_put_tile(0, 0, 1);

This function is expensive and it performs two calls to the VDP that must keep the state between them. In case the interrupt handler performs operations with the VDP, this function shouldn’t be used.

To put multiple tiles in a row, use ubox_write_vm instead. The tile map is in the memory address 0x1800.

Example putting multiple tiles:

ubox_wait_vsync();
// write a complete row of tiles (32) from a buffer
ubox_write_vm((uint8_t *)0x1800, 32, buffer);

ubox_set_tiles

void ubox_set_tiles(const uint8_t *tiles);

Sets the current tile set to the tile set pointed by tiles.

The tile set is expected to have 256 tiles (8x8 pixels, 8 bytes per tile) and it will be loaded into the VDP in all three screen sections.

All the tiles functions use an index in this tile set (usually via a tile parameter).

ubox_set_tiles_colors

void ubox_set_tiles_colors(const uint8_t *colors);

Sets the current color table for current tile set to the color table pointed by colors.

The color table is expected to have the 8 color rows for each of the 256 tiles of the tiles table (8 rows, 8 bytes per tile). The colors will be loaded into the VDP in all three screen sections.


Copyright © 2020-2024 Juan J. Martinez jjm at usebox.net)
Licensed CC BY NC SA 4.0.