Skip to content

Commit efe1b98

Browse files
move allocated sprites into the context allocator
1 parent 175106b commit efe1b98

2 files changed

Lines changed: 56 additions & 44 deletions

File tree

src/basic/graphics.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#define STB_IMAGE_IMPLEMENTATION
88
#define STBI_NO_SIMD
99
#define STBI_NO_HDR
10-
#define STBI_NO_THREAD_LOCALS
10+
#define STBI_NO_THREAD_LOCALS
1111
#define STBI_MALLOC(sz) kmalloc(sz)
1212
#define STBI_REALLOC(p,newsz) krealloc(p,newsz)
1313
#define STBI_FREE(p) kfree(p)
@@ -41,7 +41,7 @@ void free_sprite(struct basic_ctx* ctx, int64_t sprite_handle)
4141
{
4242
if (sprite_handle >= 0 && sprite_handle < MAX_SPRITES && ctx->sprites[sprite_handle] != NULL) {
4343
if (ctx->sprites[sprite_handle]->pixels) {
44-
stbi_image_free(ctx->sprites[sprite_handle]->pixels);
44+
buddy_free(ctx->allocator, ctx->sprites[sprite_handle]->pixels);
4545
}
4646
buddy_free(ctx->allocator, ctx->sprites[sprite_handle]);
4747
}
@@ -117,28 +117,57 @@ void loadsprite_statement(struct basic_ctx* ctx)
117117
tokenizer_error_printf(ctx, "Unable to open sprite file '%s'", file);
118118
return;
119119
}
120-
char* buf = buddy_malloc(ctx->allocator, f->size);
120+
unsigned char* buf = buddy_malloc(ctx->allocator, f->size);
121121
if (!buf) {
122122
free_sprite(ctx, sprite_handle);
123123
tokenizer_error_printf(ctx, "Not enough memory to load sprite file '%s'", file);
124124
return;
125125
}
126-
fs_read_file(f, 0, f->size, (unsigned char*)buf);
127-
sprite_t* s = get_sprite(ctx, sprite_handle);
128-
int w, h, n;
129-
s->pixels = (uint32_t*)stbi_load_from_memory((unsigned char*)buf, f->size, &w, &h, &n, STBI_rgb_alpha);
130-
if (!s->pixels) {
126+
fs_read_file(f, 0, f->size, buf);
127+
128+
/* Query dimensions and components without full decode */
129+
int w = 0, h = 0, n = 0;
130+
if (!stbi_info_from_memory(buf, (int)f->size, &w, &h, &n)) {
131+
tokenizer_error_printf(ctx, "Error reading sprite info for '%s': %s", file, stbi_failure_reason());
132+
buddy_free(ctx->allocator, buf);
133+
free_sprite(ctx, sprite_handle);
134+
return;
135+
}
136+
137+
/* Allocate final pixel buffer from the BASIC context */
138+
size_t bytes = (size_t)w * (size_t)h * 4; /* STBI_rgb_alpha = 4 channels */
139+
uint32_t* pixels = buddy_malloc(ctx->allocator, bytes);
140+
if (!pixels) {
141+
tokenizer_error_printf(ctx, "Not enough memory for sprite pixels '%s'", file);
142+
buddy_free(ctx->allocator, buf);
143+
free_sprite(ctx, sprite_handle);
144+
return;
145+
}
146+
147+
/* Decode with stb_image into its own buffer, then copy */
148+
int dw = 0, dh = 0, dn = 0;
149+
unsigned char* tmp = stbi_load_from_memory(buf, (int)f->size, &dw, &dh, &dn, STBI_rgb_alpha);
150+
if (!tmp) {
131151
tokenizer_error_printf(ctx, "Error loading sprite file '%s': %s", file, stbi_failure_reason());
132152
buddy_free(ctx->allocator, buf);
133153
free_sprite(ctx, sprite_handle);
134154
return;
135155
}
136-
s->width = w;
156+
memcpy(pixels, tmp, bytes);
157+
stbi_image_free(tmp);
158+
159+
/* Store sprite metadata */
160+
sprite_t* s = get_sprite(ctx, sprite_handle);
161+
s->pixels = pixels;
162+
s->width = w;
137163
s->height = h;
164+
138165
dprintf("Width: %d Height: %d Comp: %d\n", w, h, n);
166+
139167
buddy_free(ctx->allocator, buf);
140168
}
141169

170+
142171
void freesprite_statement(struct basic_ctx* ctx)
143172
{
144173
accept_or_return(SPRITEFREE, ctx);

src/basic/main.c

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,38 +25,34 @@
2525
extern bool debug;
2626

2727
void *varmap_malloc(size_t size, void *udata) {
28-
struct buddy_allocator *a = (struct buddy_allocator *)udata;
28+
struct buddy_allocator *a = udata;
2929
return buddy_malloc(a, size);
3030
}
3131

3232
void *varmap_realloc(void *ptr, size_t size, void *udata) {
33-
struct buddy_allocator *a = (struct buddy_allocator *)udata;
33+
struct buddy_allocator *a = udata;
3434
return buddy_realloc(a, ptr, size);
3535
}
3636

3737
void varmap_free(const void *ptr, void *udata) {
38-
if (ptr != NULL) {
39-
struct buddy_allocator *a = (struct buddy_allocator *)udata;
40-
buddy_free(a, ptr);
41-
}
38+
struct buddy_allocator *a = udata;
39+
buddy_free(a, ptr);
4240
}
4341

4442
/* Assumes each ub_var_* has: char *varname; size_t name_length; */
4543
uint64_t varmap_hash(const void *item, uint64_t seed0, uint64_t seed1) {
46-
const ub_var_int *v = (const ub_var_int *)item; /* name fields layout-compatible */
44+
const ub_var_int *v = item; /* name fields layout-compatible */
4745
const char *s = v->varname ? v->varname : "";
4846
size_t len = v->name_length ? v->name_length : strlen(s);
4947
return hashmap_sip(s, len, seed0, seed1);
5048
}
5149

5250
int varmap_compare(const void *a, const void *b, void *udata) {
53-
(void)udata;
54-
const ub_var_int *va = (const ub_var_int *)a;
55-
const ub_var_int *vb = (const ub_var_int *)b;
51+
const ub_var_int *va = a;
52+
const ub_var_int *vb = b;
5653

5754
size_t la = va->name_length ? va->name_length : (va->varname ? strlen(va->varname) : 0);
5855
size_t lb = vb->name_length ? vb->name_length : (vb->varname ? strlen(vb->varname) : 0);
59-
6056
if (la != lb) {
6157
return (la < lb) ? -1 : 1;
6258
}
@@ -69,40 +65,32 @@ int varmap_compare(const void *a, const void *b, void *udata) {
6965
/* ===== Element free (udata = struct buddy_allocator*) ===== */
7066

7167
void varmap_elfree_int(const void *item, void *udata) {
72-
const ub_var_int *v = (const ub_var_int *)item;
73-
dprintf("elfree_int '%s'\n", v->varname);
68+
const ub_var_int *v = item;
7469
if (v && v->varname) {
75-
struct buddy_allocator *a = (struct buddy_allocator *)udata;
76-
buddy_free(a, (void *)v->varname);
70+
struct buddy_allocator *a = udata;
71+
buddy_free(a, v->varname);
7772
}
7873
}
7974

8075
void varmap_elfree_double(const void *item, void *udata) {
81-
const ub_var_double *v = (const ub_var_double *)item;
76+
const ub_var_double *v = item;
8277
if (v && v->varname) {
83-
dprintf("elfree_double '%s'\n", v->varname);
84-
struct buddy_allocator *a = (struct buddy_allocator *)udata;
85-
buddy_free(a, (void *)v->varname);
78+
struct buddy_allocator *a = udata;
79+
buddy_free(a, v->varname);
8680
}
8781
}
8882

8983
/* IMPORTANT: strings free both name AND value */
9084
void varmap_elfree_string(const void *item, void *udata) {
91-
const ub_var_string *v = (const ub_var_string *)item;
85+
const ub_var_string *v = item;
9286
if (!v) {
9387
return;
9488
}
95-
dprintf("elfree_string '%s'\n", v->varname);
96-
struct buddy_allocator *a = (struct buddy_allocator *)udata;
97-
if (v->varname) {
98-
buddy_free(a, (void *)v->varname);
99-
}
100-
if (v->value) {
101-
buddy_free(a, (void *)v->value);
102-
}
89+
struct buddy_allocator *a = udata;
90+
buddy_free(a, v->varname);
91+
buddy_free(a, v->value);
10392
}
10493

105-
10694
char *clean_basic(const char *program, char *output_buffer) {
10795
bool in_quotes = false;
10896
uint16_t bracket_depth = 0;
@@ -258,7 +246,7 @@ struct basic_ctx *basic_init(const char *program, uint32_t pid, const char *file
258246
*error = "Out of memory";
259247
return NULL;
260248
}
261-
buddy_init(ctx->allocator, 6, 20, 20);
249+
buddy_init(ctx->allocator, 6, 26, 26);
262250
ctx->debug_status = 0;
263251
ctx->debug_breakpoints = NULL;
264252
ctx->debug_breakpoint_count = 0;
@@ -525,11 +513,6 @@ struct basic_ctx *basic_clone(struct basic_ctx *old) {
525513

526514

527515
void basic_destroy(struct basic_ctx *ctx) {
528-
for (uint32_t sprite_handle = 0; sprite_handle < MAX_SPRITES; ++sprite_handle) {
529-
if (ctx->sprites[sprite_handle]) {
530-
free_sprite(ctx, sprite_handle);
531-
}
532-
}
533516
ctx->string_gc_storage_next = NULL;
534517
/* I'm not your pal, buddy... 😂 */
535518
buddy_destroy(ctx->allocator);

0 commit comments

Comments
 (0)