2024-09-10 23:53:56 +00:00
|
|
|
#include "unigi.ext/main.h"
|
|
|
|
|
2024-09-25 19:12:28 +00:00
|
|
|
void unigi_ext_texture_draw(unigi_ext_type_texture *sprite, unigi_ext_type_texture *fb, unigi_ext_type_rect texrect, unigi_ext_type_rect outrect) {
|
|
|
|
// Precalc the step, as it's always the same even if we clip the rect
|
|
|
|
unigi_ext_type_2d_coord tex_width, tex_height, out_width, out_height;
|
|
|
|
unigi_ext_rect_dimensions(texrect,&tex_width,&tex_height);
|
|
|
|
unigi_ext_rect_dimensions(outrect,&out_width,&out_height);
|
|
|
|
int32_t stepx = (1 << unigi_ext_texture_fixedpointdepth) * (float)tex_width / out_width;
|
|
|
|
int32_t stepy = (1 << unigi_ext_texture_fixedpointdepth) * (float)tex_height / out_height;
|
|
|
|
int32_t texx_init = (1 << unigi_ext_texture_fixedpointdepth) * texrect.x1;
|
|
|
|
int32_t texy = (1 << unigi_ext_texture_fixedpointdepth) * texrect.y1;
|
|
|
|
// Clip the rect
|
|
|
|
if (outrect.x1 < 0) {
|
|
|
|
texx_init += stepx * -outrect.x1;
|
|
|
|
outrect.x1 = 0;
|
|
|
|
}
|
|
|
|
if (outrect.y1 < 0) {
|
|
|
|
texy += stepy * -outrect.y1;
|
|
|
|
outrect.y1 = 0;
|
|
|
|
}
|
|
|
|
if (outrect.x2 >= fb->width) {
|
|
|
|
outrect.x2 = fb->width - 1;
|
|
|
|
}
|
|
|
|
if (outrect.y2 >= fb->height) {
|
|
|
|
outrect.y2 = fb->height - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int y = outrect.y1; y < outrect.y2; y++) {
|
|
|
|
int32_t texx = texx_init;
|
|
|
|
int yiter = y * fb->width;
|
|
|
|
for (int x = outrect.x1; x < outrect.x2; x++) {
|
|
|
|
uint16_t pix = sprite->pixels[((texy >> unigi_ext_texture_fixedpointdepth) * sprite->width) + (texx >> unigi_ext_texture_fixedpointdepth)];
|
|
|
|
|
|
|
|
if (pix & 0xF000) {
|
|
|
|
fb->pixels[yiter + x] = pix;
|
|
|
|
}
|
|
|
|
texx += stepx;
|
|
|
|
}
|
|
|
|
texy += stepy;
|
|
|
|
}
|
2024-09-10 23:53:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-25 19:17:32 +00:00
|
|
|
unigi_ext_type_texture * unigi_ext_texture_create(unigi_type_resolution_2d_coord width, unigi_type_resolution_2d_coord height) {
|
2024-09-13 21:25:10 +00:00
|
|
|
unigi_ext_type_texture * texture = malloc(sizeof(unigi_ext_type_texture));
|
|
|
|
if (texture == NULL) { return NULL; }
|
|
|
|
texture->width = width;
|
|
|
|
texture->height = height;
|
|
|
|
texture->pixels = malloc(sizeof(unigi_type_color) * width * height);
|
|
|
|
if (texture->pixels == NULL) {
|
|
|
|
free(texture);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
void unigi_ext_texture_destroy(unigi_ext_type_texture * texture) {
|
|
|
|
free(texture->pixels);
|
|
|
|
free(texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
unigi_ext_type_texture * unigi_ext_texture_open(char * path) {
|
|
|
|
int fd = open(path,O_RDONLY);
|
|
|
|
if (fd == -1) { goto fail; }
|
2024-09-25 19:12:42 +00:00
|
|
|
uint16_t width;
|
|
|
|
uint16_t height;
|
2024-09-13 21:25:10 +00:00
|
|
|
if (read(fd,&width,sizeof(uint16_t)) != sizeof(uint16_t)) { goto fail_file; }
|
|
|
|
if (read(fd,&height,sizeof(uint16_t)) != sizeof(uint16_t)) { goto fail_file; }
|
|
|
|
unigi_ext_type_texture * texture = unigi_ext_texture_create(width,height);
|
|
|
|
if (texture == NULL) { goto fail_file; }
|
|
|
|
|
|
|
|
if (read(fd,texture->pixels,sizeof(uint16_t) * width * height) != sizeof(uint16_t) * width * height) {
|
|
|
|
goto fail_texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
return texture;
|
|
|
|
|
|
|
|
fail_texture:;
|
|
|
|
unigi_ext_texture_destroy(texture);
|
|
|
|
fail_file:;
|
|
|
|
close(fd);
|
|
|
|
fail:;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-09-10 23:53:56 +00:00
|
|
|
void unigi_ext_rect_dimensions(
|
|
|
|
unigi_ext_type_rect bounds,
|
|
|
|
unigi_ext_type_2d_coord * width,
|
|
|
|
unigi_ext_type_2d_coord * height
|
|
|
|
) {
|
|
|
|
*width = abs(bounds.x2 - bounds.x1);
|
|
|
|
*height = abs(bounds.y2 - bounds.y1);
|
|
|
|
}
|
|
|
|
|
2024-10-16 00:56:36 +00:00
|
|
|
unigi_ext_type_sound_sample * unigi_ext_sound_open(char * path) {
|
|
|
|
unigi_ext_type_sound_sample * sample = malloc(sizeof(unigi_ext_type_sound_sample));
|
|
|
|
if (sample == NULL) { goto fail; }
|
|
|
|
int fd = open(path,O_RDONLY);
|
2024-10-22 07:26:03 +00:00
|
|
|
if (fd == -1) { goto fail_sample; }
|
2024-10-16 00:56:36 +00:00
|
|
|
size_t size = lseek(fd, 0, SEEK_END);
|
|
|
|
lseek(fd, 0, SEEK_SET);
|
|
|
|
uint8_t * data = malloc(size);
|
2024-10-22 07:26:03 +00:00
|
|
|
if (data == NULL) { goto fail_file; }
|
2024-10-16 00:56:36 +00:00
|
|
|
if (read(fd,data,size) != size) { goto fail_data; }
|
|
|
|
close(fd);
|
|
|
|
sample->size = size;
|
|
|
|
sample->data = data;
|
|
|
|
return sample;
|
|
|
|
|
|
|
|
fail_data:;
|
|
|
|
free(data);
|
2024-10-22 07:26:03 +00:00
|
|
|
fail_file:;
|
|
|
|
close(fd);
|
2024-10-16 00:56:36 +00:00
|
|
|
fail_sample:;
|
|
|
|
free(sample);
|
|
|
|
fail:;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: add channel cap (+ static stack allocation, instead of dynamic malloc?)
|
|
|
|
unigi_ext_type_sound_channel * unigi_ext_sound_channel_create(unigi_ext_type_sound_sample * sample) {
|
|
|
|
size_t i = 0;
|
|
|
|
unigi_ext_type_sound_channel * channel = NULL;
|
|
|
|
while (i < unigi_ext_sound_channels_size) {
|
|
|
|
if (unigi_ext_sound_channels[i].sound == NULL) {
|
|
|
|
channel = &unigi_ext_sound_channels[i];
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channel == NULL) {
|
|
|
|
unigi_ext_type_sound_channel * newchannels = realloc(unigi_ext_sound_channels,(unigi_ext_sound_channels_size + 1) * sizeof(unigi_ext_type_sound_channel));
|
|
|
|
if (newchannels == NULL) { goto fail; }
|
|
|
|
unigi_ext_sound_channels = newchannels;
|
|
|
|
channel = &unigi_ext_sound_channels[unigi_ext_sound_channels_size];
|
|
|
|
++unigi_ext_sound_channels_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
channel->sound = sample;
|
|
|
|
channel->volume = 1.0;
|
|
|
|
channel->start = 0;
|
|
|
|
channel->stop = sample->size;
|
|
|
|
channel->progress = 0;
|
|
|
|
channel->loop = 1;
|
|
|
|
return channel;
|
|
|
|
fail:;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void unigi_ext_sound_channel_play(unigi_ext_type_sound_channel * channel, uint8_t * buffer, size_t size) {
|
|
|
|
size_t i = 0;
|
|
|
|
while (i < size) { // TODO: make proper for loop
|
|
|
|
buffer[i] += (channel->sound->data[channel->progress] * (channel->volume / 2)); // TODO: cap volume (?) + remove the "/ 2" (SDL specific)
|
|
|
|
channel->progress += 1;
|
|
|
|
if (channel->progress >= channel->stop) {
|
|
|
|
if (channel->loop == 0) {
|
|
|
|
channel->sound = NULL;
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
channel->progress = channel->start;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void unigi_ext_sound_handle(uint8_t * buffer, size_t size) {
|
|
|
|
memset(buffer, 0, size);
|
|
|
|
size_t i = 0;
|
|
|
|
while (i < unigi_ext_sound_channels_size) { // TODO: make proper for loop
|
|
|
|
if (unigi_ext_sound_channels[i].sound != NULL) {
|
|
|
|
unigi_ext_sound_channel_play(&unigi_ext_sound_channels[i],buffer,size);
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void unigi_ext_sound_init() {
|
|
|
|
unigi_sound_init(unigi_ext_sound_handle);
|
|
|
|
}
|