diff --git a/CMakeLists.txt b/CMakeLists.txt index caec2e2..d962ed5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,8 +158,6 @@ set(SOURCES_CG # R61524 driver src/r61524/r61524.c # Rendering - src/render-cg/bopti-asm.s - src/render-cg/bopti.c src/render-cg/dclear.c src/render-cg/dpixel.c src/render-cg/drect.c diff --git a/TODO b/TODO index 02a27cf..446b151 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,6 @@ gint 2.8 image things: -* Margins around the VRAM, and around XYRAM fragments * Design the new image formats, inspired from libimg * Replace the [profile] attribute with [format] -* Single VRAM Extensions on existing code: * usb: add PC->calc reading, and interrupt pipes diff --git a/src/render-cg/bopti-asm.h b/src/render-cg/bopti-asm.h deleted file mode 100644 index 57afb27..0000000 --- a/src/render-cg/bopti-asm.h +++ /dev/null @@ -1,55 +0,0 @@ -//--- -// gint:render-cg:bopti-asm - Assembler drawing routines for bopti -//--- - -#ifndef GINT_RENDERCG_BOPTIASM -#define GINT_RENDERCG_BOPTIASM - -/* bopti_r5g6b5(): Full opaque 16-bit rendering - @data Input data (2-aligned) - @target Target in VRAM (2-aligned) - @width Width of rendered image - @height Height of rendered image - @in_stride Bytes to ignore between two rows of @data - @out_stride Bytes to ignore between two rows of @target */ -void bopti_r5g6b5(uint16_t const *data, uint16_t *target, int width, - int height, int in_stride, int out_stride); - -/* bopti_r5g6b5a(): 16-bit rendering with alpha - @data @target @width @height @in_stride @out_stride - As in bopti_r5g6b5(). - @alpha Color code that encodes transparency */ -void bopti_r5g6b5a(uint16_t const *data, uint16_t *target, int width, - int height, int in_stride, int out_stride, uint16_t alpha); - -/* bopti_p8(): 8-bit palette rendering with alpha - @data @target @width @height @in_stride @out_stride - As in bopti_r5g6b5(). - @palette Pointer to image palette (256 colors) - @alpha Palette index for transparency, if >= 256 no alpha is used */ -void bopti_p8(uint8_t const *data, uint16_t *target, int width, int height, - int in_stride, int out_stride, uint16_t const *palette, int alpha); - -/* bopti_p4(): 4-bit palette rendering with alpha - @data @target @width @height @in_stride @out_stride - As in bopti_r5g6b5(). - @palette Pointer to image palette (16 colors) - @alpha Palette index for transparency, if >= 16 no alpha is used - @offset Initial offset within [data], in number of pixels */ -void bopti_p4(uint8_t const *data, uint16_t *target, int width, int height, - int in_stride, int out_stride, uint16_t const *palette, int alpha, - int offset); - -/* bopti_render_clip(): Render with clipping - Same parameters as dsubimage(), except for flags. */ -void bopti_render_clip(int x, int y, bopti_image_t const *img, int left, - int top, int width, int height); - -/* bopti_render_clip(): Render without clipping - Behaviour is not defined if (left,top)+(width,height) is not included in the - source image or (x,y)+(width,height) is not included in the VRAM area. - Same parameters as dsubimage(), except for flags. */ -void bopti_render_noclip(int x, int y, bopti_image_t const *img, int left, - int top, int width, int height); - -#endif /* GINT_RENDERCG_BOPTIASM */ diff --git a/src/render-cg/bopti-asm.s b/src/render-cg/bopti-asm.s deleted file mode 100644 index dd63124..0000000 --- a/src/render-cg/bopti-asm.s +++ /dev/null @@ -1,315 +0,0 @@ - -.global _bopti_r5g6b5 -.global _bopti_r5g6b5a -.global _bopti_p8 -.global _bopti_p4 - -# REGISTER ALLOCATION: -# r0: (tmp) -# r1: (tmp) -# r2: width - 1 -# r3: target & 2 -# --- -# r4: data -# r5: target -# r6: width; then, the number of longword operations -# r7: height -# --- -# r8: in_stride -# r9: out_stride -# r10: x counter -# --- -# @12: in_stride -# @16: out_stride - -.align 4 - -_bopti_r5g6b5: - # Target alignment, either 0 (4-aligned) or 2 (2-aligned) - mov.l r8, @-r15 - mov r5, r3 - mov.l r9, @-r15 - mov #2, r0 - mov.l r10, @-r15 - and r0, r3 - - # width-1, used to copy the last longword - mov r6, r2 - add #-1, r2 - shll r2 - - # Input and output strides. Add ending alignment because there is no - # corresponding increment in the y-loop. - mov.l @(12, r15), r8 - mov.l @(16, r15), r9 - mov r5, r0 - shll r6 - add r6 ,r0 - and #2, r0 - add r0, r8 - add r0, r9 - - # Number of longword operations per row - sub r3, r6 - shlr2 r6 - -.r5g6b5_y: - # First longword - mov.w @r4, r1 - mov r2, r0 - mov.w r1, @r5 - - # Last longword; align to 4-byte boundaries for target - mov.w @(r0, r4), r1 - add r3, r4 - mov.w r1, @(r0, r5) - add r3, r5 - - mov r6, r10 - tst r6, r6 - bt .r5g6b5_y_end - -.r5g6b5_x: - # Copy longwords - movua.l @r4+, r0 - mov.l r0, @r5 - - dt r10 - bf.s .r5g6b5_x - add #4, r5 - -.r5g6b5_y_end: - - add r8, r4 - dt r7 - bf.s .r5g6b5_y - add r9, r5 - -# - - - mov.l @r15+, r10 - mov.l @r15+, r9 - rts - mov.l @r15+, r8 - -# REGISTER ALLOCATION: -# r0: (tmp) -# r1: in_stride -# r2: out_stride -# r3: x counter -# --- -# r4: data -# r5: target -# r6: width -# r7: height -# --- -# r8: alpha -# --- -# @4: in_stride -# @8: out_stride -# @12: alpha - -.align 4 - -_bopti_r5g6b5a: - # Load alpha value - mov.l r8, @-r15 - mov.l @(12, r15), r8 - - # Load input and output strides - mov.l @(4, r15), r1 - mov.l @(8, r15), r2 - -.r5g6b5a_y: - mov r6, r3 - -.r5g6b5a_x: - mov.w @r4+, r0 - cmp/eq r0, r8 - bt .r5g6b5a_alpha - - mov.w r0, @r5 - -.r5g6b5a_alpha: - dt r3 - bf.s .r5g6b5a_x - add #2, r5 - -# - - - add r1, r4 - dt r7 - bf.s .r5g6b5a_y - add r2, r5 - -# - - - rts - mov.l @r15+, r8 - -# REGISTER ALLOCATION: -# r0: (tmp) -# r1: in_stride -# r2: out_stride -# r3: x counter -# --- -# r4: data -# r5: target -# r6: width -# r7: height -# --- -# r8: palette -# r9: alpha -# --- -# @8: in_stride -# @12: out_stride -# @16: palette -# @20: alpha - -.align 4 - -_bopti_p8: - # Load palette and in/out strides - mov.l r8, @-r15 - mov.l r9, @-r15 - mov.l @(16, r15), r8 - mov.l @(8, r15), r1 - mov.l @(12, r15), r2 - - # Load alpha value - mov.l @(20, r15), r9 - -.p8_y: - mov r6, r3 - -.p8_x: - mov.b @r4+, r0 - extu.b r0, r0 - cmp/eq r0, r9 - bt .p8_alpha - - # Pass pixel through palette - shll r0 - mov.w @(r0, r8), r0 - mov.w r0, @r5 - -.p8_alpha: - dt r3 - bf.s .p8_x - add #2, r5 - -# - - - add r1, r4 - dt r7 - bf.s .p8_y - add r2, r5 - -# - - - mov.l @r15+, r9 - rts - mov.l @r15+, r8 - -# REGISTER ALLOCATION: -# r0: (tmp) -# r1: in_stride (in pixels) -# r2: out_stride -# r3: x counter -# --- -# r4: data -# r5: target -# r6: width -# r7: height -# --- -# r8: palette -# r9: number of pixels of offset into data (r4) -# r10: alpha -# --- -# @12: in_stride -# @16: out_stride -# @20: palette -# @24: alpha -# @28: initial offset (in pixels) - -.align 4 - -_bopti_p4: - mov.l r8, @-r15 - mov.l r9, @-r15 - mov.l r10, @-r15 - - # Load palette and in/out strides - mov.l @(20, r15), r8 - mov.l @(12, r15), r1 - mov.l @(16, r15), r2 - - # Load initial offset - mov.l @(28, r15), r9 - - # Load alpha value - mov.l @(24, r15), r10 - shll r10 - -.p4_y: - mov r6, r3 - -.p4_x: - - # Load 4 bits from offset r9 (in pixels) within image data (r4). Note - # that [shlr] puts bit 0 of the shifted register in T. - mov r9, r0 - add #1, r9 - shlr r0 - bt.s .p4_x_unaligned - mov.b @(r0, r4), r0 - -.p4_x_aligned: - - # Load 4 bits from the higher half of @r4 and use them to index the - # palette. Since the palette has two-byte entries, we need the color - # bits to be in position 000xxxx0. - shlr2 r0 - shlr r0 - and #0x1e, r0 - - cmp/eq r0, r10 - bt .p4_alpha - - # Pass pixel through palette - mov.w @(r0, r8), r0 - bra .p4_alpha - mov.w r0, @r5 - -.p4_x_unaligned: - - # Load 4 bits from the lower half of @r4 into position 000xxxx0. - shll r0 - and #0x1e, r0 - - cmp/eq r0, r10 - bt .p4_alpha - - # Pass pixel through palette - mov.w @(r0, r8), r0 - mov.w r0, @r5 - -.p4_alpha: - - dt r3 - bf.s .p4_x - add #2, r5 - -.p4_y_end: - - add r1, r9 - dt r7 - bf.s .p4_y - add r2, r5 - -# - - - mov.l @r15+, r10 - mov.l @r15+, r9 - rts - mov.l @r15+, r8 diff --git a/src/render-cg/bopti.c b/src/render-cg/bopti.c deleted file mode 100644 index 1e13c9b..0000000 --- a/src/render-cg/bopti.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include "bopti-asm.h" - -struct box { - /* Target location of top-left corner */ - int x, y; - /* Width and height of rendered sub-image */ - int w, h; - /* Source bounding box (low included, high excluded) */ - int left, top; -}; - -enum { - PX_R5G6B5 = 0, - PX_R5G6B5A = 1, - PX_P8 = 2, - PX_P4 = 3, -}; - -void bopti_render(bopti_image_t const *img, struct box *box) -{ - /* Offset in video RAM and output stride */ - uint16_t *target = gint_vram + (396 * box->y + box->x); - int out = 2 * (396 - box->w); - - int profile = img->profile; - void const *data = img->data; - - int w = box->w; - int h = box->h; - - if(profile == PX_R5G6B5 || profile == PX_R5G6B5A) - { - /* Input stride */ - int true_width = img->width + (img->width & 1); - int in = 2 * (true_width - w); - - data += 2 * (true_width * box->top + box->left); - - if(profile == PX_R5G6B5) - bopti_r5g6b5(data, target, w, h, in, out); - else - bopti_r5g6b5a(data, target, w, h, in, out, img->alpha); - } - else if(profile == PX_P8) - { - /* Palette has 0x100 entries of 2 bytes each */ - uint16_t const *palette = data; - data += 512; - - int in = img->width - w; - data += img->width * box->top + box->left; - - bopti_p8(data, target, w, h, in, out, palette, img->alpha); - } - else if(profile == PX_P4) - { - /* Palette has 0x10 entries of 2 bytes each */ - uint16_t const *palette = data; - data += 32; - - int true_width = img->width + (img->width & 1); - - /* Due to nibble alignment being a hassle, in this function the - input stride is expressed in pixels. */ - int in = true_width - w; - /* Also we don't move pointers, we just use pixel offsets. */ - int offset = true_width * box->top + box->left; - - bopti_p4(data, target, w, h, in, out, palette, img->alpha, - offset); - } -} - -void bopti_render_clip(int x, int y, bopti_image_t const *img, int left, - int top, int width, int height) -{ - /* Adjust the bounding box of the input image */ - if(left < 0) width += left, x -= left, left = 0; - if(top < 0) height += top, y -= top, top = 0; - if(left + width > img->width) width = img->width - left; - if(top + height > img->height) height = img->height - top; - - /* Check whether the box intersects the screen */ - if(width <= 0 || height <= 0) return; - if(x + width <= 0 || x >= 396 || y + height <= 0 || y >= 224) return; - - /* Intersect with the bounding box on-screen */ - if(y < 0) top -= y, height += y, y = 0; - if(y + height > 224) height = (224 - y); - if(x < 0) left -= x, width += x, x = 0; - if(x + width > 396) width = (396 - x); - - /* Finish with the renderer */ - struct box box = { x, y, width, height, left, top }; - bopti_render(img, &box); -} - -void bopti_render_noclip(int x, int y, bopti_image_t const *img, int left, - int top, int width, int height) -{ - struct box box = { x, y, width, height, left, top }; - bopti_render(img, &box); -} diff --git a/src/render-cg/dsubimage.c b/src/render-cg/dsubimage.c index e3cf3f1..59a9493 100644 --- a/src/render-cg/dsubimage.c +++ b/src/render-cg/dsubimage.c @@ -1,16 +1,14 @@ #include -#include "bopti-asm.h" /* dsubimage(): Render a section of an image */ -void dsubimage(int x, int y, bopti_image_t const *img, int left, int top, - int width, int height, int flags) +void dsubimage(int x, int y, image_t const *img, int left, int top, + int w, int h, int flags) { - if(flags & DIMAGE_NOCLIP) - { - bopti_render_noclip(x, y, img, left, top, width, height); - } - else - { - bopti_render_clip(x, y, img, left, top, width, height); - } + int p = img->profile; + if(p == IMAGE_RGB565 || p == IMAGE_RGB565A) + return dsubimage_rgb16(x, y, img, left, top, w, h, flags); + if(p == IMAGE_P8_RGB565 || p == IMAGE_P8_RGB565A) + return dsubimage_p8(x, y, img, left, top, w, h, flags); + if(p == IMAGE_P4_RGB565 || p == IMAGE_P4_RGB565A) + return dsubimage_p4(x, y, img, left, top, w, h, flags); } diff --git a/src/render-cg/image/image.c b/src/render-cg/image/image.c index 66b678d..794f249 100644 --- a/src/render-cg/image/image.c +++ b/src/render-cg/image/image.c @@ -15,7 +15,7 @@ bool gint_image_clip_input(image_t const *img, struct gint_image_box *b, return false; if(b->x + b->w <= 0 || b->x >= out_w) return false; - if(b->y + b->w <= 0 || b->y >= out_h) + if(b->y + b->h <= 0 || b->y >= out_h) return false; return true;