#include "unigi.ext/main.h" 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; } } unigi_ext_type_texture * unigi_ext_texture_create(unigi_type_resolution_2d_coord width, unigi_type_resolution_2d_coord height) { 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 #include unigi_ext_type_texture * unigi_ext_texture_open(char * path) { int fd = open(path,O_RDONLY); if (fd == -1) { goto fail; } uint16_t width; uint16_t height; 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; } 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); } 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); if (fd == -1) { goto fail_sample; } size_t size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); uint8_t * data = malloc(size); if (data == NULL) { goto fail_file; } if (read(fd,data,size) != size) { goto fail_data; } close(fd); sample->size = size; sample->data = data; return sample; fail_data:; free(data); fail_file:; close(fd); 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); }