79 lines
2.7 KiB
C
79 lines
2.7 KiB
C
|
|
/**
|
||
|
|
* @file sprite_tables.c
|
||
|
|
* @brief The sprite state's power-on values, and the pattern bit order.
|
||
|
|
*
|
||
|
|
* The counterpart to src/graphics_tables.c: everything about sprites that is
|
||
|
|
* data rather than behaviour, kept away from the verbs so the verb file is
|
||
|
|
* verbs. Both things here are shared by every backend, which is the point --
|
||
|
|
* the bit order in particular is asserted once here rather than trusted in each
|
||
|
|
* adaptor that has to turn a pattern into pixels.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#include <akerror.h>
|
||
|
|
|
||
|
|
#include <akbasic/error.h>
|
||
|
|
#include <akbasic/sprite.h>
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief What SPRCOLOR's two registers hold before a program sets them.
|
||
|
|
*
|
||
|
|
* A C128 powers up with multicolour 1 at grey and multicolour 2 at yellow. They
|
||
|
|
* only matter to a multicolour sprite, so a program that never sets them and
|
||
|
|
* never asks for multicolour never sees them.
|
||
|
|
*
|
||
|
|
* register palette colour
|
||
|
|
* -------- ------- ------
|
||
|
|
* 1 12 medium grey
|
||
|
|
* 2 8 orange
|
||
|
|
*/
|
||
|
|
#define SHARED_COLOR_1_DEFAULT 12
|
||
|
|
#define SHARED_COLOR_2_DEFAULT 8
|
||
|
|
|
||
|
|
/** @brief The palette index a sprite has before SPRITE names one. White. */
|
||
|
|
#define SPRITE_COLOR_DEFAULT 2
|
||
|
|
|
||
|
|
akerr_ErrorContext *akbasic_sprite_state_init(akbasic_SpriteState *obj)
|
||
|
|
{
|
||
|
|
PREPARE_ERROR(errctx);
|
||
|
|
int i = 0;
|
||
|
|
|
||
|
|
FAIL_ZERO_RETURN(errctx, (obj != NULL), AKERR_NULLPOINTER, "NULL sprite state in init");
|
||
|
|
memset(obj, 0, sizeof(*obj));
|
||
|
|
for ( i = 0; i < AKBASIC_MAX_SPRITES; i++ ) {
|
||
|
|
obj->sprites[i].colorindex = SPRITE_COLOR_DEFAULT;
|
||
|
|
}
|
||
|
|
obj->sharedcolor1 = SHARED_COLOR_1_DEFAULT;
|
||
|
|
obj->sharedcolor2 = SHARED_COLOR_2_DEFAULT;
|
||
|
|
SUCCEED_RETURN(errctx);
|
||
|
|
}
|
||
|
|
|
||
|
|
akerr_ErrorContext *akbasic_sprite_unpack(const uint8_t *pattern, int bytes, uint8_t *dest)
|
||
|
|
{
|
||
|
|
PREPARE_ERROR(errctx);
|
||
|
|
int row = 0;
|
||
|
|
int col = 0;
|
||
|
|
|
||
|
|
FAIL_ZERO_RETURN(errctx, (pattern != NULL && dest != NULL), AKERR_NULLPOINTER,
|
||
|
|
"NULL argument in sprite unpack");
|
||
|
|
FAIL_ZERO_RETURN(errctx, (bytes == AKBASIC_SPRITE_PATTERN_BYTES), AKBASIC_ERR_BOUNDS,
|
||
|
|
"A sprite pattern is %d bytes, not %d",
|
||
|
|
AKBASIC_SPRITE_PATTERN_BYTES, bytes);
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Three bytes per row, most significant bit leftmost -- which is to say the
|
||
|
|
* first byte of a row is its left eight pixels, and bit 7 of that byte is
|
||
|
|
* the leftmost pixel of all. That is the order a C128 keeps a sprite block
|
||
|
|
* in and the order a type-in listing's DATA statements are written in, so
|
||
|
|
* getting it backwards would mirror every published sprite.
|
||
|
|
*/
|
||
|
|
for ( row = 0; row < AKBASIC_SPRITE_HEIGHT; row++ ) {
|
||
|
|
for ( col = 0; col < AKBASIC_SPRITE_WIDTH; col++ ) {
|
||
|
|
uint8_t byte = pattern[(row * 3) + (col / 8)];
|
||
|
|
dest[(row * AKBASIC_SPRITE_WIDTH) + col] = (uint8_t)((byte >> (7 - (col % 8))) & 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
SUCCEED_RETURN(errctx);
|
||
|
|
}
|