Add strided memory pushing and improved spritebatching
This commit is contained in:
@@ -7,29 +7,30 @@ function MoveCubeCutscene(params) {
|
|||||||
|
|
||||||
var startX = this.cube.position.position.x;
|
var startX = this.cube.position.position.x;
|
||||||
|
|
||||||
this.animLeft = new Animation([
|
// this.animLeft = new Animation([
|
||||||
{ time: 0.0, value: startX, easing: Easing.outQuad },
|
// { time: 0.0, value: startX, easing: Easing.outQuad },
|
||||||
{ time: DURATION, value: startX - SPEED * DURATION }
|
// { time: DURATION, value: startX - SPEED * DURATION }
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
this.animRight = new Animation([
|
// this.animRight = new Animation([
|
||||||
{ time: 0.0, value: startX - SPEED * DURATION, easing: Easing.inOutQuad },
|
// { time: 0.0, value: startX - SPEED * DURATION, easing: Easing.inOutQuad },
|
||||||
{ time: DURATION, value: startX }
|
// { time: DURATION, value: startX }
|
||||||
]);
|
// ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveCubeCutscene.prototype = Object.create(Cutscene.prototype);
|
MoveCubeCutscene.prototype = Object.create(Cutscene.prototype);
|
||||||
MoveCubeCutscene.prototype.constructor = MoveCubeCutscene;
|
MoveCubeCutscene.prototype.constructor = MoveCubeCutscene;
|
||||||
|
|
||||||
MoveCubeCutscene.prototype.update = function() {
|
MoveCubeCutscene.prototype.update = function() {
|
||||||
if(!this.animLeft.complete) {
|
Cutscene.finish();
|
||||||
this.cube.position.position.x = this.animLeft.update(TIME.delta);
|
// if(!this.animLeft.complete) {
|
||||||
} else {
|
// this.cube.position.position.x = this.animLeft.update(TIME.delta);
|
||||||
this.cube.position.position.x = this.animRight.update(TIME.delta);
|
// } else {
|
||||||
if(this.animRight.complete) {
|
// this.cube.position.position.x = this.animRight.update(TIME.delta);
|
||||||
Cutscene.finish();
|
// if(this.animRight.complete) {
|
||||||
}
|
// Cutscene.finish();
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
module = MoveCubeCutscene;
|
module = MoveCubeCutscene;
|
||||||
|
|||||||
@@ -129,11 +129,10 @@ errorret_t consoleDraw(void) {
|
|||||||
|
|
||||||
for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) {
|
for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) {
|
||||||
errorChain(textDraw(
|
errorChain(textDraw(
|
||||||
0, FONT_TILESET_DEFAULT.tileHeight * i,
|
0, FONT_DEFAULT.tileset.tileHeight * i,
|
||||||
CONSOLE.line[i],
|
CONSOLE.line[i],
|
||||||
COLOR_WHITE,
|
COLOR_WHITE,
|
||||||
&FONT_TILESET_DEFAULT,
|
&FONT_DEFAULT
|
||||||
&FONT_TEXTURE_DEFAULT
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return spriteBatchFlush();
|
return spriteBatchFlush();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "spritebatch.h"
|
#include "spritebatch.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "util/math.h"
|
||||||
|
|
||||||
meshvertex_t SPRITEBATCH_VERTICES[SPRITEBATCH_VERTEX_COUNT];
|
meshvertex_t SPRITEBATCH_VERTICES[SPRITEBATCH_VERTEX_COUNT];
|
||||||
spritebatch_t SPRITEBATCH;
|
spritebatch_t SPRITEBATCH;
|
||||||
@@ -24,6 +25,97 @@ errorret_t spriteBatchInit() {
|
|||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorret_t spriteBatchPushv(
|
||||||
|
const float_t *minX,
|
||||||
|
const float_t *minY,
|
||||||
|
const float_t *maxX,
|
||||||
|
const float_t *maxY,
|
||||||
|
const float_t *z,
|
||||||
|
#if MESH_ENABLE_COLOR
|
||||||
|
const color_t *color,
|
||||||
|
#endif
|
||||||
|
const float_t *u0,
|
||||||
|
const float_t *v0,
|
||||||
|
const float_t *u1,
|
||||||
|
const float_t *v1,
|
||||||
|
const size_t count
|
||||||
|
) {
|
||||||
|
size_t offset = 0;
|
||||||
|
while(offset < count) {
|
||||||
|
if(SPRITEBATCH.spriteCount >= SPRITEBATCH_SPRITES_MAX_PER_FLUSH) {
|
||||||
|
errorChain(spriteBatchFlush());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t available = (size_t)(
|
||||||
|
SPRITEBATCH_SPRITES_MAX_PER_FLUSH - SPRITEBATCH.spriteCount
|
||||||
|
);
|
||||||
|
size_t toPush = mathMin(count - offset, available);
|
||||||
|
|
||||||
|
meshvertex_t *start = &SPRITEBATCH_VERTICES[
|
||||||
|
(SPRITEBATCH.spriteCount + (SPRITEBATCH.spriteFlush *
|
||||||
|
SPRITEBATCH_SPRITES_MAX_PER_FLUSH)) * QUAD_VERTEX_COUNT
|
||||||
|
];
|
||||||
|
|
||||||
|
// Fill all toPush sprites field-by-field, one memoryCopyInterleaved per
|
||||||
|
// vertex-slot per field. Vertex layout matches quadBuffer3D:
|
||||||
|
// v0=(minX,minY,z,u0,v0) v1=(maxX,minY,z,u1,v0) v2=(maxX,maxY,z,u1,v1)
|
||||||
|
// v3=(minX,minY,z,u0,v0) v4=(maxX,maxY,z,u1,v1) v5=(minX,maxY,z,u0,v1)
|
||||||
|
const size_t dstStride = sizeof(meshvertex_t) * QUAD_VERTEX_COUNT;
|
||||||
|
const size_t fSz = sizeof(float_t);
|
||||||
|
const float_t *sMinX = minX + offset;
|
||||||
|
const float_t *sMaxX = maxX + offset;
|
||||||
|
const float_t *sMinY = minY + offset;
|
||||||
|
const float_t *sMaxY = maxY + offset;
|
||||||
|
const float_t *sZ = z + offset;
|
||||||
|
const float_t *sU0 = u0 + offset;
|
||||||
|
const float_t *sU1 = u1 + offset;
|
||||||
|
const float_t *sV0 = v0 + offset;
|
||||||
|
const float_t *sV1 = v1 + offset;
|
||||||
|
|
||||||
|
#define COPY_FIELD(vi, field, srcArr) \
|
||||||
|
memoryCopyInterleaved(&start[vi].field, dstStride, srcArr, fSz, fSz, toPush)
|
||||||
|
|
||||||
|
COPY_FIELD(0, pos[0], sMinX); COPY_FIELD(0, pos[1], sMinY);
|
||||||
|
COPY_FIELD(0, pos[2], sZ); COPY_FIELD(0, uv[0], sU0);
|
||||||
|
COPY_FIELD(0, uv[1], sV0);
|
||||||
|
|
||||||
|
COPY_FIELD(1, pos[0], sMaxX); COPY_FIELD(1, pos[1], sMinY);
|
||||||
|
COPY_FIELD(1, pos[2], sZ); COPY_FIELD(1, uv[0], sU1);
|
||||||
|
COPY_FIELD(1, uv[1], sV0);
|
||||||
|
|
||||||
|
COPY_FIELD(2, pos[0], sMaxX); COPY_FIELD(2, pos[1], sMaxY);
|
||||||
|
COPY_FIELD(2, pos[2], sZ); COPY_FIELD(2, uv[0], sU1);
|
||||||
|
COPY_FIELD(2, uv[1], sV1);
|
||||||
|
|
||||||
|
COPY_FIELD(3, pos[0], sMinX); COPY_FIELD(3, pos[1], sMinY);
|
||||||
|
COPY_FIELD(3, pos[2], sZ); COPY_FIELD(3, uv[0], sU0);
|
||||||
|
COPY_FIELD(3, uv[1], sV0);
|
||||||
|
|
||||||
|
COPY_FIELD(4, pos[0], sMaxX); COPY_FIELD(4, pos[1], sMaxY);
|
||||||
|
COPY_FIELD(4, pos[2], sZ); COPY_FIELD(4, uv[0], sU1);
|
||||||
|
COPY_FIELD(4, uv[1], sV1);
|
||||||
|
|
||||||
|
COPY_FIELD(5, pos[0], sMinX); COPY_FIELD(5, pos[1], sMaxY);
|
||||||
|
COPY_FIELD(5, pos[2], sZ); COPY_FIELD(5, uv[0], sU0);
|
||||||
|
COPY_FIELD(5, uv[1], sV1);
|
||||||
|
|
||||||
|
#undef COPY_FIELD
|
||||||
|
|
||||||
|
#if MESH_ENABLE_COLOR
|
||||||
|
for(uint8_t vi = 0; vi < QUAD_VERTEX_COUNT; vi++) {
|
||||||
|
memoryCopyInterleaved(
|
||||||
|
&start[vi].color, dstStride,
|
||||||
|
color + offset, sizeof(color_t), sizeof(color_t), toPush
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPRITEBATCH.spriteCount += (int32_t)toPush;
|
||||||
|
offset += toPush;
|
||||||
|
}
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t spriteBatchPush(
|
errorret_t spriteBatchPush(
|
||||||
const float_t minX,
|
const float_t minX,
|
||||||
const float_t minY,
|
const float_t minY,
|
||||||
@@ -37,14 +129,13 @@ errorret_t spriteBatchPush(
|
|||||||
const float_t u1,
|
const float_t u1,
|
||||||
const float_t v1
|
const float_t v1
|
||||||
) {
|
) {
|
||||||
return spriteBatchPush3D(
|
return spriteBatchPushv(
|
||||||
(vec3){ minX, minY, 0 },
|
&minX, &minY, &maxX, &maxY, &(float_t){0},
|
||||||
(vec3){ maxX, maxY, 0 },
|
|
||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
color,
|
&color,
|
||||||
#endif
|
#endif
|
||||||
(vec2){ u0, v0 },
|
&u0, &v0, &u1, &v1,
|
||||||
(vec2){ u1, v1 }
|
1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,25 +148,17 @@ errorret_t spriteBatchPush3D(
|
|||||||
const vec2 uv0,
|
const vec2 uv0,
|
||||||
const vec2 uv1
|
const vec2 uv1
|
||||||
) {
|
) {
|
||||||
// Need to flush?
|
return spriteBatchPushv(
|
||||||
if(SPRITEBATCH.spriteCount >= SPRITEBATCH_SPRITES_MAX_PER_FLUSH) {
|
&min[0], &min[1],
|
||||||
errorChain(spriteBatchFlush());
|
&max[0], &max[1],
|
||||||
}
|
&min[2],
|
||||||
|
|
||||||
size_t vertexOffset = (
|
|
||||||
SPRITEBATCH.spriteCount +
|
|
||||||
(SPRITEBATCH.spriteFlush * SPRITEBATCH_SPRITES_MAX_PER_FLUSH)
|
|
||||||
) * QUAD_VERTEX_COUNT;
|
|
||||||
quadBuffer3D(
|
|
||||||
&SPRITEBATCH_VERTICES[vertexOffset],
|
|
||||||
min, max,
|
|
||||||
uv0, uv1
|
|
||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
, color
|
&color,
|
||||||
#endif
|
#endif
|
||||||
|
&uv0[0], &uv0[1],
|
||||||
|
&uv1[0], &uv1[1],
|
||||||
|
1
|
||||||
);
|
);
|
||||||
SPRITEBATCH.spriteCount++;
|
|
||||||
errorOk();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spriteBatchClear() {
|
void spriteBatchClear() {
|
||||||
|
|||||||
@@ -33,6 +33,38 @@ extern spritebatch_t SPRITEBATCH;
|
|||||||
*/
|
*/
|
||||||
errorret_t spriteBatchInit();
|
errorret_t spriteBatchInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes multiple sprites to the batch using arrays of values.
|
||||||
|
*
|
||||||
|
* @param minX Array of minimum x coordinates.
|
||||||
|
* @param minY Array of minimum y coordinates.
|
||||||
|
* @param maxX Array of maximum x coordinates.
|
||||||
|
* @param maxY Array of maximum y coordinates.
|
||||||
|
* @param z Array of z coordinates.
|
||||||
|
* @param color Array of colors (if enabled).
|
||||||
|
* @param u0 Array of u0 texture coordinates.
|
||||||
|
* @param v0 Array of v0 texture coordinates.
|
||||||
|
* @param u1 Array of u1 texture coordinates.
|
||||||
|
* @param v1 Array of v1 texture coordinates.
|
||||||
|
* @param count Number of sprites to push.
|
||||||
|
* @return An error code indicating success or failure.
|
||||||
|
*/
|
||||||
|
errorret_t spriteBatchPushv(
|
||||||
|
const float_t *minX,
|
||||||
|
const float_t *minY,
|
||||||
|
const float_t *maxX,
|
||||||
|
const float_t *maxY,
|
||||||
|
const float_t *z,
|
||||||
|
#if MESH_ENABLE_COLOR
|
||||||
|
const color_t *color,
|
||||||
|
#endif
|
||||||
|
const float_t *u0,
|
||||||
|
const float_t *v0,
|
||||||
|
const float_t *u1,
|
||||||
|
const float_t *v1,
|
||||||
|
const size_t count
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes a sprite to the batch. This basically "queues" it to render (well
|
* Pushes a sprite to the batch. This basically "queues" it to render (well
|
||||||
* technically it is buffering the vertices to the mesh at the moment, but
|
* technically it is buffering the vertices to the mesh at the moment, but
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "display/texture/texture.h"
|
||||||
|
#include "display/texture/tileset.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
texture_t texture;
|
||||||
|
tileset_t tileset;
|
||||||
|
} font_t;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2026 Dominic Masters
|
* Copyright (c) 2026 Dominic Masters
|
||||||
*
|
*
|
||||||
* This software is released under the MIT License.
|
* This software is released under the MIT License.
|
||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
*/
|
*/
|
||||||
@@ -13,19 +13,18 @@
|
|||||||
#include "asset/loader/display/assettilesetloader.h"
|
#include "asset/loader/display/assettilesetloader.h"
|
||||||
#include "display/shader/shaderunlit.h"
|
#include "display/shader/shaderunlit.h"
|
||||||
|
|
||||||
texture_t FONT_TEXTURE_DEFAULT;
|
font_t FONT_DEFAULT;
|
||||||
tileset_t FONT_TILESET_DEFAULT;
|
|
||||||
|
|
||||||
errorret_t textInit(void) {
|
errorret_t textInit(void) {
|
||||||
errorChain(assetTextureLoad(
|
errorChain(assetTextureLoad(
|
||||||
"ui/minogram.png", &FONT_TEXTURE_DEFAULT, TEXTURE_FORMAT_RGBA
|
"ui/minogram.png", &FONT_DEFAULT.texture, TEXTURE_FORMAT_RGBA
|
||||||
));
|
));
|
||||||
errorChain(assetTilesetLoad("ui/minogram.dtf", &FONT_TILESET_DEFAULT));
|
errorChain(assetTilesetLoad("ui/minogram.dtf", &FONT_DEFAULT.tileset));
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t textDispose(void) {
|
errorret_t textDispose(void) {
|
||||||
errorChain(textureDispose(&FONT_TEXTURE_DEFAULT));
|
errorChain(textureDispose(&FONT_DEFAULT.texture));
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,27 +35,24 @@ errorret_t textDrawChar(
|
|||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
const color_t color,
|
const color_t color,
|
||||||
#endif
|
#endif
|
||||||
const tileset_t *tileset,
|
font_t *font
|
||||||
texture_t *texture
|
|
||||||
) {
|
) {
|
||||||
int32_t tileIndex = (int32_t)(c) - TEXT_CHAR_START;
|
int32_t tileIndex = (int32_t)(c) - TEXT_CHAR_START;
|
||||||
if(tileIndex < 0 || tileIndex >= tileset->tileCount) {
|
if(tileIndex < 0 || tileIndex >= font->tileset.tileCount) {
|
||||||
tileIndex = ((int32_t)'@') - TEXT_CHAR_START;
|
tileIndex = ((int32_t)'@') - TEXT_CHAR_START;
|
||||||
}
|
}
|
||||||
assertTrue(
|
assertTrue(
|
||||||
tileIndex >= 0 && tileIndex <= tileset->tileCount,
|
tileIndex >= 0 && tileIndex <= font->tileset.tileCount,
|
||||||
"Character is out of bounds for font tiles"
|
"Character is out of bounds for font tiles"
|
||||||
);
|
);
|
||||||
|
|
||||||
vec4 uv;
|
vec4 uv;
|
||||||
tilesetTileGetUV(tileset, tileIndex, uv);
|
tilesetTileGetUV(&font->tileset, tileIndex, uv);
|
||||||
|
|
||||||
|
|
||||||
errorChain(spriteBatchPush(
|
errorChain(spriteBatchPush(
|
||||||
// texture,
|
|
||||||
x, y,
|
x, y,
|
||||||
x + tileset->tileWidth,
|
x + font->tileset.tileWidth,
|
||||||
y + tileset->tileHeight,
|
y + font->tileset.tileHeight,
|
||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
color,
|
color,
|
||||||
#endif
|
#endif
|
||||||
@@ -65,47 +61,36 @@ errorret_t textDrawChar(
|
|||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
errorret_t textDraw(
|
errorret_t textDraw(
|
||||||
const float_t x,
|
const float_t x,
|
||||||
const float_t y,
|
const float_t y,
|
||||||
const char_t *text,
|
const char_t *text,
|
||||||
const color_t color,
|
const color_t color,
|
||||||
const tileset_t *tileset,
|
font_t *font
|
||||||
texture_t *texture
|
|
||||||
) {
|
) {
|
||||||
assertNotNull(text, "Text cannot be NULL");
|
assertNotNull(text, "Text cannot be NULL");
|
||||||
|
|
||||||
float_t posX = x;
|
float_t posX = x;
|
||||||
float_t posY = y;
|
float_t posY = y;
|
||||||
|
|
||||||
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, texture));
|
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, &font->texture));
|
||||||
|
|
||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
#else
|
#else
|
||||||
errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, color));
|
errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, color));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// errorChain(spriteBatchPush(
|
|
||||||
// // texture,
|
|
||||||
// posX, posY,
|
|
||||||
// posX + texture->width * 1, posY + texture->height * 1,
|
|
||||||
// color,
|
|
||||||
// 0.0f, 0.0f, 1.0f, 1.0f
|
|
||||||
// ));
|
|
||||||
// errorOk();
|
|
||||||
|
|
||||||
char_t c;
|
char_t c;
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
while((c = text[i++]) != '\0') {
|
while((c = text[i++]) != '\0') {
|
||||||
if(c == '\n') {
|
if(c == '\n') {
|
||||||
posX = x;
|
posX = x;
|
||||||
posY += tileset->tileHeight;
|
posY += font->tileset.tileHeight;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c == ' ') {
|
if(c == ' ') {
|
||||||
posX += tileset->tileWidth;
|
posX += font->tileset.tileWidth;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,16 +99,16 @@ errorret_t textDraw(
|
|||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
color,
|
color,
|
||||||
#endif
|
#endif
|
||||||
tileset, texture
|
font
|
||||||
));
|
));
|
||||||
posX += tileset->tileWidth;
|
posX += font->tileset.tileWidth;
|
||||||
}
|
}
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
void textMeasure(
|
void textMeasure(
|
||||||
const char_t *text,
|
const char_t *text,
|
||||||
const tileset_t *tileset,
|
const font_t *font,
|
||||||
int32_t *outWidth,
|
int32_t *outWidth,
|
||||||
int32_t *outHeight
|
int32_t *outHeight
|
||||||
) {
|
) {
|
||||||
@@ -132,28 +117,24 @@ void textMeasure(
|
|||||||
assertNotNull(outHeight, "Output height pointer cannot be NULL");
|
assertNotNull(outHeight, "Output height pointer cannot be NULL");
|
||||||
|
|
||||||
int32_t width = 0;
|
int32_t width = 0;
|
||||||
int32_t height = tileset->tileHeight;
|
int32_t height = font->tileset.tileHeight;
|
||||||
int32_t lineWidth = 0;
|
int32_t lineWidth = 0;
|
||||||
|
|
||||||
char_t c;
|
char_t c;
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
while((c = text[i++]) != '\0') {
|
while((c = text[i++]) != '\0') {
|
||||||
if(c == '\n') {
|
if(c == '\n') {
|
||||||
if(lineWidth > width) {
|
if(lineWidth > width) width = lineWidth;
|
||||||
width = lineWidth;
|
|
||||||
}
|
|
||||||
lineWidth = 0;
|
lineWidth = 0;
|
||||||
height += tileset->tileHeight;
|
height += font->tileset.tileHeight;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lineWidth += tileset->tileWidth;
|
lineWidth += font->tileset.tileWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lineWidth > width) {
|
if(lineWidth > width) width = lineWidth;
|
||||||
width = lineWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
*outWidth = width;
|
*outWidth = width;
|
||||||
*outHeight = height;
|
*outHeight = height;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,40 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2026 Dominic Masters
|
* Copyright (c) 2026 Dominic Masters
|
||||||
*
|
*
|
||||||
* This software is released under the MIT License.
|
* This software is released under the MIT License.
|
||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
#include "display/texture/texture.h"
|
#include "display/text/font.h"
|
||||||
#include "display/texture/tileset.h"
|
|
||||||
|
|
||||||
#define TEXT_CHAR_START '!'
|
#define TEXT_CHAR_START '!'
|
||||||
|
|
||||||
extern texture_t FONT_TEXTURE_DEFAULT;
|
extern font_t FONT_DEFAULT;
|
||||||
extern tileset_t FONT_TILESET_DEFAULT;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the text system.
|
* Initializes the text system.
|
||||||
*
|
*
|
||||||
* @return Either an error or success result.
|
* @return Either an error or success result.
|
||||||
*/
|
*/
|
||||||
errorret_t textInit(void);
|
errorret_t textInit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes of the text system.
|
* Disposes of the text system.
|
||||||
*
|
*
|
||||||
* @return Either an error or success result.
|
* @return Either an error or success result.
|
||||||
*/
|
*/
|
||||||
errorret_t textDispose(void);
|
errorret_t textDispose(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a single character at the specified position.
|
* Draws a single character at the specified position.
|
||||||
*
|
*
|
||||||
* @param x The x-coordinate to draw the character at.
|
* @param x The x-coordinate to draw the character at.
|
||||||
* @param y The y-coordinate to draw the character at.
|
* @param y The y-coordinate to draw the character at.
|
||||||
* @param c The character to draw.
|
* @param c The character to draw.
|
||||||
* @param color The color to draw the character in.
|
* @param color The color to draw the character in.
|
||||||
* @param tileset Font tileset to use for rendering.
|
* @param font Font to use for rendering.
|
||||||
* @param texture Texture containing the font tileset image.
|
|
||||||
* @return Either an error or success result.
|
* @return Either an error or success result.
|
||||||
*/
|
*/
|
||||||
errorret_t textDrawChar(
|
errorret_t textDrawChar(
|
||||||
@@ -47,19 +44,17 @@ errorret_t textDrawChar(
|
|||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
const color_t color,
|
const color_t color,
|
||||||
#endif
|
#endif
|
||||||
const tileset_t *tileset,
|
font_t *font
|
||||||
texture_t *texture
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a string of text at the specified position.
|
* Draws a string of text at the specified position.
|
||||||
*
|
*
|
||||||
* @param x The x-coordinate to draw the text at.
|
* @param x The x-coordinate to draw the text at.
|
||||||
* @param y The y-coordinate to draw the text at.
|
* @param y The y-coordinate to draw the text at.
|
||||||
* @param text The null-terminated string of text to draw.
|
* @param text The null-terminated string of text to draw.
|
||||||
* @param color The color to draw the text in.
|
* @param color The color to draw the text in.
|
||||||
* @param tileset Font tileset to use for rendering.
|
* @param font Font to use for rendering.
|
||||||
* @param texture Texture containing the font tileset image.
|
|
||||||
* @return Either an error or success result.
|
* @return Either an error or success result.
|
||||||
*/
|
*/
|
||||||
errorret_t textDraw(
|
errorret_t textDraw(
|
||||||
@@ -67,21 +62,20 @@ errorret_t textDraw(
|
|||||||
const float_t y,
|
const float_t y,
|
||||||
const char_t *text,
|
const char_t *text,
|
||||||
const color_t color,
|
const color_t color,
|
||||||
const tileset_t *tileset,
|
font_t *font
|
||||||
texture_t *texture
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Measures the width and height of the given text string when rendered.
|
* Measures the width and height of the given text string when rendered.
|
||||||
*
|
*
|
||||||
* @param text The null-terminated string of text to measure.
|
* @param text The null-terminated string of text to measure.
|
||||||
* @param tileset Font tileset to use for measurement.
|
* @param font Font to use for measurement.
|
||||||
* @param outWidth Pointer to store the measured width in pixels.
|
* @param outWidth Pointer to store the measured width in pixels.
|
||||||
* @param outHeight Pointer to store the measured height in pixels.
|
* @param outHeight Pointer to store the measured height in pixels.
|
||||||
*/
|
*/
|
||||||
void textMeasure(
|
void textMeasure(
|
||||||
const char_t *text,
|
const char_t *text,
|
||||||
const tileset_t *tileset,
|
const font_t *font,
|
||||||
int32_t *outWidth,
|
int32_t *outWidth,
|
||||||
int32_t *outHeight
|
int32_t *outHeight
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ moduleBaseFunction(moduleTextDraw) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t err = textDraw(
|
errorret_t err = textDraw(
|
||||||
x, y, text, col, &FONT_TILESET_DEFAULT, &FONT_TEXTURE_DEFAULT
|
x, y, text, col, &FONT_DEFAULT
|
||||||
);
|
);
|
||||||
if(err.code != ERROR_OK) {
|
if(err.code != ERROR_OK) {
|
||||||
errorCatch(errorPrint(err));
|
errorCatch(errorPrint(err));
|
||||||
@@ -54,7 +54,7 @@ moduleBaseFunction(moduleTextMeasure) {
|
|||||||
moduleBaseToString(args[0], text, sizeof(text));
|
moduleBaseToString(args[0], text, sizeof(text));
|
||||||
|
|
||||||
int32_t w, h;
|
int32_t w, h;
|
||||||
textMeasure(text, &FONT_TILESET_DEFAULT, &w, &h);
|
textMeasure(text, &FONT_DEFAULT, &w, &h);
|
||||||
|
|
||||||
jerry_value_t obj = jerry_object();
|
jerry_value_t obj = jerry_object();
|
||||||
jerry_value_t wKey = jerry_string_sz("width");
|
jerry_value_t wKey = jerry_string_sz("width");
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ errorret_t uiFPSDraw() {
|
|||||||
errorChain(textDraw(
|
errorChain(textDraw(
|
||||||
0, 0,
|
0, 0,
|
||||||
fpsText, textColor,
|
fpsText, textColor,
|
||||||
&FONT_TILESET_DEFAULT, &FONT_TEXTURE_DEFAULT
|
&FONT_DEFAULT
|
||||||
));
|
));
|
||||||
|
|
||||||
return spriteBatchFlush();
|
return spriteBatchFlush();
|
||||||
|
|||||||
+13
-14
@@ -21,8 +21,10 @@ errorret_t uiTextboxInit(void) {
|
|||||||
UI_TEXTBOX.textColor = COLOR_WHITE;
|
UI_TEXTBOX.textColor = COLOR_WHITE;
|
||||||
UI_TEXTBOX.advanceAction = INPUT_ACTION_ACCEPT;
|
UI_TEXTBOX.advanceAction = INPUT_ACTION_ACCEPT;
|
||||||
|
|
||||||
float_t fontW = (float_t)FONT_TILESET_DEFAULT.tileWidth;
|
UI_TEXTBOX.font = &FONT_DEFAULT;
|
||||||
float_t fontH = (float_t)FONT_TILESET_DEFAULT.tileHeight;
|
|
||||||
|
float_t fontW = (float_t)FONT_DEFAULT.tileset.tileWidth;
|
||||||
|
float_t fontH = (float_t)FONT_DEFAULT.tileset.tileHeight;
|
||||||
float_t tbHeight = (
|
float_t tbHeight = (
|
||||||
(float_t)UI_TEXTBOX_LINES_PER_PAGE_MAX * fontH +
|
(float_t)UI_TEXTBOX_LINES_PER_PAGE_MAX * fontH +
|
||||||
(float_t)(UI_TEXTBOX_LINES_PER_PAGE_MAX - 1) * UI_TEXTBOX_LINE_SPACING +
|
(float_t)(UI_TEXTBOX_LINES_PER_PAGE_MAX - 1) * UI_TEXTBOX_LINE_SPACING +
|
||||||
@@ -36,13 +38,11 @@ errorret_t uiTextboxInit(void) {
|
|||||||
UI_TEXTBOX.frame.tileset.columns = 3;
|
UI_TEXTBOX.frame.tileset.columns = 3;
|
||||||
UI_TEXTBOX.frame.tileset.rows = 3;
|
UI_TEXTBOX.frame.tileset.rows = 3;
|
||||||
UI_TEXTBOX.frame.tileset.tileCount = 9;
|
UI_TEXTBOX.frame.tileset.tileCount = 9;
|
||||||
UI_TEXTBOX.frame.tileset.tileWidth = FONT_TILESET_DEFAULT.tileWidth;
|
UI_TEXTBOX.frame.tileset.tileWidth = FONT_DEFAULT.tileset.tileWidth;
|
||||||
UI_TEXTBOX.frame.tileset.tileHeight = FONT_TILESET_DEFAULT.tileHeight;
|
UI_TEXTBOX.frame.tileset.tileHeight = FONT_DEFAULT.tileset.tileHeight;
|
||||||
UI_TEXTBOX.frame.tileset.uv[0] = 1.0f / 3.0f;
|
UI_TEXTBOX.frame.tileset.uv[0] = 1.0f / 3.0f;
|
||||||
UI_TEXTBOX.frame.tileset.uv[1] = 1.0f / 3.0f;
|
UI_TEXTBOX.frame.tileset.uv[1] = 1.0f / 3.0f;
|
||||||
UI_TEXTBOX.frame.texture = &TEXTURE_WHITE;
|
UI_TEXTBOX.frame.texture = &TEXTURE_WHITE;
|
||||||
UI_TEXTBOX.textTileset = FONT_TILESET_DEFAULT;
|
|
||||||
UI_TEXTBOX.textTexture = &FONT_TEXTURE_DEFAULT;
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -53,8 +53,8 @@ void uiTextboxBuildLayout(void) {
|
|||||||
|
|
||||||
float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
||||||
float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
||||||
float_t fontW = (float_t)UI_TEXTBOX.textTileset.tileWidth;
|
float_t fontW = (float_t)UI_TEXTBOX.font->tileset.tileWidth;
|
||||||
float_t fontH = (float_t)UI_TEXTBOX.textTileset.tileHeight;
|
float_t fontH = (float_t)UI_TEXTBOX.font->tileset.tileHeight;
|
||||||
|
|
||||||
if(fontW <= 0.0f || fontH <= 0.0f) return;
|
if(fontW <= 0.0f || fontH <= 0.0f) return;
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ errorret_t uiTextboxDraw(void) {
|
|||||||
if(UI_TEXTBOX.lineCount == 0 || UI_TEXTBOX.text[0] == '\0') errorOk();
|
if(UI_TEXTBOX.lineCount == 0 || UI_TEXTBOX.text[0] == '\0') errorOk();
|
||||||
|
|
||||||
errorChain(shaderSetTexture(
|
errorChain(shaderSetTexture(
|
||||||
&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, UI_TEXTBOX.textTexture
|
&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, &UI_TEXTBOX.font->texture
|
||||||
));
|
));
|
||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
#else
|
#else
|
||||||
@@ -215,8 +215,8 @@ errorret_t uiTextboxDraw(void) {
|
|||||||
|
|
||||||
float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
||||||
float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
||||||
float_t fontW = (float_t)UI_TEXTBOX.textTileset.tileWidth;
|
float_t fontW = (float_t)UI_TEXTBOX.font->tileset.tileWidth;
|
||||||
float_t fontH = (float_t)UI_TEXTBOX.textTileset.tileHeight;
|
float_t fontH = (float_t)UI_TEXTBOX.font->tileset.tileHeight;
|
||||||
float_t contentX = UI_TEXTBOX.x + frameTileW;
|
float_t contentX = UI_TEXTBOX.x + frameTileW;
|
||||||
float_t contentY = UI_TEXTBOX.y + frameTileH;
|
float_t contentY = UI_TEXTBOX.y + frameTileH;
|
||||||
|
|
||||||
@@ -242,8 +242,7 @@ errorret_t uiTextboxDraw(void) {
|
|||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
UI_TEXTBOX.textColor,
|
UI_TEXTBOX.textColor,
|
||||||
#endif
|
#endif
|
||||||
&UI_TEXTBOX.textTileset,
|
UI_TEXTBOX.font
|
||||||
UI_TEXTBOX.textTexture
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,5 +255,5 @@ errorret_t uiTextboxDraw(void) {
|
|||||||
|
|
||||||
void uiTextboxDispose(void) {
|
void uiTextboxDispose(void) {
|
||||||
uiFrameDispose(&UI_TEXTBOX.frame);
|
uiFrameDispose(&UI_TEXTBOX.frame);
|
||||||
UI_TEXTBOX.textTexture = NULL;
|
UI_TEXTBOX.font = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uiframe_t frame;
|
uiframe_t frame;
|
||||||
|
|
||||||
tileset_t textTileset;
|
font_t *font;
|
||||||
texture_t *textTexture;
|
|
||||||
color_t textColor;
|
color_t textColor;
|
||||||
|
|
||||||
float_t x, y, width, height;
|
float_t x, y, width, height;
|
||||||
|
|||||||
@@ -107,6 +107,29 @@ void memoryReallocate(void **ptr, const size_t size) {
|
|||||||
*ptr = newPointer;
|
*ptr = newPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memoryCopyInterleaved(
|
||||||
|
void *dest,
|
||||||
|
const size_t destStride,
|
||||||
|
const void *src,
|
||||||
|
const size_t srcStride,
|
||||||
|
const size_t elementSize,
|
||||||
|
const size_t count
|
||||||
|
) {
|
||||||
|
assertNotNull(dest, "Cannot copy to NULL memory.");
|
||||||
|
assertNotNull(src, "Cannot copy from NULL memory.");
|
||||||
|
assertTrue(elementSize > 0, "Element size must be > 0.");
|
||||||
|
assertTrue(destStride >= elementSize, "Dest stride must be >= element size.");
|
||||||
|
assertTrue(srcStride >= elementSize, "Src stride must be >= element size.");
|
||||||
|
|
||||||
|
uint8_t *d = (uint8_t *)dest;
|
||||||
|
const uint8_t *s = (const uint8_t *)src;
|
||||||
|
for(size_t i = 0; i < count; i++) {
|
||||||
|
memcpy(d, s, elementSize);
|
||||||
|
d += destStride;
|
||||||
|
s += srcStride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void memoryResize(void **ptr, const size_t oldSize, const size_t newSize) {
|
void memoryResize(void **ptr, const size_t oldSize, const size_t newSize) {
|
||||||
assertNotNull(ptr, "Cannot resize NULL pointer.");
|
assertNotNull(ptr, "Cannot resize NULL pointer.");
|
||||||
assertTrue(newSize > 0, "Cannot resize to 0 bytes of memory.");
|
assertTrue(newSize > 0, "Cannot resize to 0 bytes of memory.");
|
||||||
|
|||||||
+23
-2
@@ -117,9 +117,30 @@ void memoryReallocate(void **ptr, const size_t size);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reallocates memory, but copies existing data to the new memory.
|
* Reallocates memory, but copies existing data to the new memory.
|
||||||
*
|
*
|
||||||
* @param ptr The pointer to the memory to resize.
|
* @param ptr The pointer to the memory to resize.
|
||||||
* @param oldSize The old size of the memory.
|
* @param oldSize The old size of the memory.
|
||||||
* @param newSize The new size of the memory.
|
* @param newSize The new size of the memory.
|
||||||
*/
|
*/
|
||||||
void memoryResize(void **ptr, const size_t oldSize, const size_t newSize);
|
void memoryResize(void **ptr, const size_t oldSize, const size_t newSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scatter-copies elements from a contiguous source array into a strided
|
||||||
|
* destination. For each of count elements, copies elementSize bytes from
|
||||||
|
* src[i * srcStride] into dest[i * destStride].
|
||||||
|
*
|
||||||
|
* @param dest Base destination pointer.
|
||||||
|
* @param destStride Byte stride between destination slots.
|
||||||
|
* @param src Base source pointer.
|
||||||
|
* @param srcStride Byte stride between source elements.
|
||||||
|
* @param elementSize Bytes to copy per element.
|
||||||
|
* @param count Number of elements to copy.
|
||||||
|
*/
|
||||||
|
void memoryCopyInterleaved(
|
||||||
|
void *dest,
|
||||||
|
const size_t destStride,
|
||||||
|
const void *src,
|
||||||
|
const size_t srcStride,
|
||||||
|
const size_t elementSize,
|
||||||
|
const size_t count
|
||||||
|
);
|
||||||
@@ -423,6 +423,87 @@ static void test_memoryResize(void **state) {
|
|||||||
assert_int_equal(memoryGetAllocatedCount(), 0);
|
assert_int_equal(memoryGetAllocatedCount(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_memoryCopyInterleaved(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
// Basic: copy 4 uint32_t values from contiguous source into every-other dest
|
||||||
|
// slot (stride = 2*sizeof(uint32_t)).
|
||||||
|
uint32_t src[4] = { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
|
||||||
|
uint32_t dest[8];
|
||||||
|
memoryZero(dest, sizeof(dest));
|
||||||
|
|
||||||
|
memoryCopyInterleaved(
|
||||||
|
dest, sizeof(uint32_t) * 2,
|
||||||
|
src, sizeof(uint32_t),
|
||||||
|
sizeof(uint32_t), 4
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_int_equal(dest[0], 0x11111111);
|
||||||
|
assert_int_equal(dest[2], 0x22222222);
|
||||||
|
assert_int_equal(dest[4], 0x33333333);
|
||||||
|
assert_int_equal(dest[6], 0x44444444);
|
||||||
|
// Skipped slots should be untouched.
|
||||||
|
assert_int_equal(dest[1], 0);
|
||||||
|
assert_int_equal(dest[3], 0);
|
||||||
|
assert_int_equal(dest[5], 0);
|
||||||
|
assert_int_equal(dest[7], 0);
|
||||||
|
|
||||||
|
// Strided source: pick every second element into a contiguous destination.
|
||||||
|
uint32_t src2[8] = { 0xA, 0xFF, 0xB, 0xFF, 0xC, 0xFF, 0xD, 0xFF };
|
||||||
|
uint32_t dest2[4];
|
||||||
|
memoryZero(dest2, sizeof(dest2));
|
||||||
|
|
||||||
|
memoryCopyInterleaved(
|
||||||
|
dest2, sizeof(uint32_t),
|
||||||
|
src2, sizeof(uint32_t) * 2,
|
||||||
|
sizeof(uint32_t), 4
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_int_equal(dest2[0], 0xA);
|
||||||
|
assert_int_equal(dest2[1], 0xB);
|
||||||
|
assert_int_equal(dest2[2], 0xC);
|
||||||
|
assert_int_equal(dest2[3], 0xD);
|
||||||
|
|
||||||
|
// Multi-byte element: copy structs field-by-field pattern.
|
||||||
|
typedef struct { uint32_t x; uint32_t y; } pair_t;
|
||||||
|
uint32_t yVals[3] = { 10, 20, 30 };
|
||||||
|
pair_t pairs[3];
|
||||||
|
memoryZero(pairs, sizeof(pairs));
|
||||||
|
|
||||||
|
memoryCopyInterleaved(
|
||||||
|
&pairs[0].y, sizeof(pair_t),
|
||||||
|
yVals, sizeof(uint32_t),
|
||||||
|
sizeof(uint32_t), 3
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_int_equal(pairs[0].y, 10);
|
||||||
|
assert_int_equal(pairs[1].y, 20);
|
||||||
|
assert_int_equal(pairs[2].y, 30);
|
||||||
|
assert_int_equal(pairs[0].x, 0);
|
||||||
|
assert_int_equal(pairs[1].x, 0);
|
||||||
|
assert_int_equal(pairs[2].x, 0);
|
||||||
|
|
||||||
|
// Count of 0 is a no-op.
|
||||||
|
uint32_t untouched[2] = { 0xDEAD, 0xBEEF };
|
||||||
|
memoryCopyInterleaved(untouched, 4, src, 4, 4, 0);
|
||||||
|
assert_int_equal(untouched[0], 0xDEAD);
|
||||||
|
|
||||||
|
// NULL dest
|
||||||
|
expect_assert_failure(memoryCopyInterleaved(NULL, 8, src, 4, 4, 2));
|
||||||
|
|
||||||
|
// NULL src
|
||||||
|
expect_assert_failure(memoryCopyInterleaved(dest, 8, NULL, 4, 4, 2));
|
||||||
|
|
||||||
|
// elementSize 0
|
||||||
|
expect_assert_failure(memoryCopyInterleaved(dest, 8, src, 4, 0, 2));
|
||||||
|
|
||||||
|
// destStride smaller than elementSize
|
||||||
|
expect_assert_failure(memoryCopyInterleaved(dest, 2, src, 4, 4, 2));
|
||||||
|
|
||||||
|
// srcStride smaller than elementSize
|
||||||
|
expect_assert_failure(memoryCopyInterleaved(dest, 8, src, 2, 4, 2));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
const struct CMUnitTest tests[] = {
|
const struct CMUnitTest tests[] = {
|
||||||
cmocka_unit_test(test_memoryAllocate),
|
cmocka_unit_test(test_memoryAllocate),
|
||||||
@@ -435,6 +516,7 @@ int main(int argc, char **argv) {
|
|||||||
cmocka_unit_test(test_memoryCompare),
|
cmocka_unit_test(test_memoryCompare),
|
||||||
cmocka_unit_test(test_memoryReallocate),
|
cmocka_unit_test(test_memoryReallocate),
|
||||||
cmocka_unit_test(test_memoryResize),
|
cmocka_unit_test(test_memoryResize),
|
||||||
|
cmocka_unit_test(test_memoryCopyInterleaved),
|
||||||
};
|
};
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user