forked from Lephenixnoir/Azur
Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Sylvain PILLOT | 3ff6008b9a |
|
@ -5,5 +5,3 @@
|
|||
|
||||
# Editor files
|
||||
*.sublime-*
|
||||
.vscode
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"editor.fontSize": 12
|
||||
}
|
8
TODO.txt
8
TODO.txt
|
@ -1,8 +0,0 @@
|
|||
Polygon shader
|
||||
Filled polygon shader
|
||||
|
||||
Ellipse shader
|
||||
Filled ellipse shader
|
||||
|
||||
Better font shader
|
||||
|
|
@ -35,11 +35,6 @@ if(AZUR_TOOLKIT_SDL AND AZUR_GRAPHICS_OPENGL)
|
|||
DEPENDS gen_glsl.py ${ASSETS})
|
||||
endif()
|
||||
|
||||
if(AZUR_TOOLKIT_GINT)
|
||||
list(APPEND SOURCES
|
||||
src/gint/init.cpp)
|
||||
endif()
|
||||
|
||||
# gint rendering
|
||||
if(AZUR_GRAPHICS_GINT_CG)
|
||||
list(APPEND SOURCES
|
||||
|
@ -72,15 +67,7 @@ if(AZUR_GRAPHICS_GINT_CG)
|
|||
src/gint/shaders/image_p4_dye.c
|
||||
# Triangle shader
|
||||
src/gint/shaders/triangle.c
|
||||
src/gint/shaders/triangle.S
|
||||
# Line shader
|
||||
src/gint/shaders/line.c
|
||||
# Circle shader
|
||||
src/gint/shaders/circle.c
|
||||
src/gint/shaders/filledcircle.c
|
||||
src/gint/shaders/poly.c
|
||||
src/gint/shaders/filledpoly.c
|
||||
)
|
||||
src/gint/shaders/triangle.S)
|
||||
endif()
|
||||
|
||||
add_library(azur STATIC ${SOURCES})
|
||||
|
|
|
@ -44,14 +44,6 @@
|
|||
#cmakedefine AZUR_GRAPHICS_GINT_CG
|
||||
|
||||
|
||||
/* CPU architecture (mostly useful for optimized SuperH stuff). */
|
||||
|
||||
/* Generic/unknown CPU architecture; only C code is used. */
|
||||
#cmakedefine AZUR_ARCH_GENERIC
|
||||
/* SH4AL-DSP for the fx-CG. */
|
||||
#cmakedefine AZUR_ARCH_SH4ALDSP
|
||||
|
||||
|
||||
/* Input/output settings on terminal. */
|
||||
|
||||
/* No terminal output entirely. */
|
||||
|
|
|
@ -205,21 +205,6 @@ void azrp_subimage(int x, int y, bopti_image_t const *image,
|
|||
|
||||
void azrp_triangle(int x1, int y1, int x2, int y2, int x3, int y3, int color);
|
||||
|
||||
/* azrp_line(): Draw a line with clipping to the screen resolution between point (x1,y1) and (x2,y2) */
|
||||
void azrp_line( int x1, int y1, int x2, int y2, uint16_t color );
|
||||
|
||||
/* azrp_circle() : Draw a circle with clipping to the screen resolution with a center (xc,yc) and a radius rad */
|
||||
void azrp_circle( int xc, int yx, uint16_t rad, uint16_t color );
|
||||
|
||||
/* azrp_filledcircle() : Draw a filled circle with clipping to the screen resolution with a center (xc,yc) and a radius rad */
|
||||
void azrp_filledcircle( int xc, int yx, uint16_t rad, uint16_t color );
|
||||
|
||||
/* azrp_poly() : Draw a polygon with clipping*/
|
||||
void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color);
|
||||
|
||||
/* azrp_filledpoly() : Draw a filled polygon with clipping*/
|
||||
void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color);
|
||||
|
||||
/* See below for more detailed image functions. Dynamic effects are provided
|
||||
with the same naming convention as gint. */
|
||||
|
||||
|
@ -232,12 +217,6 @@ void azrp_shader_image_p8_configure(void);
|
|||
void azrp_shader_image_p4_configure(void);
|
||||
void azrp_shader_triangle_configure(void);
|
||||
|
||||
void azrp_shader_line_configure(void);
|
||||
|
||||
void azrp_shader_circle_configure(void);
|
||||
void azrp_shader_filledcircle_configure(void);
|
||||
void azrp_shader_filledpoly_configure(void);
|
||||
|
||||
//---
|
||||
// Performance indicators
|
||||
//
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
#include <azur/azur.h>
|
||||
#include <azur/log.h>
|
||||
#include <gint/timer.h>
|
||||
#include <gint/cpu.h>
|
||||
|
||||
int azur_init(char const *title, int window_width, int window_height)
|
||||
{
|
||||
(void)title;
|
||||
(void)window_width;
|
||||
(void)window_height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((destructor))
|
||||
void azur_quit(void)
|
||||
{
|
||||
}
|
||||
|
||||
//---
|
||||
// Main loop setup
|
||||
//---
|
||||
|
||||
/* Time spent in the main loop (seconds)
|
||||
TODO: Handle ml_time (also in the SDL backend) */
|
||||
static double ml_time = 0.0;
|
||||
/* Timers for render and updates */
|
||||
static int ml_timer_render = -1;
|
||||
static int ml_timer_update = -1;
|
||||
|
||||
static int set_flag(volatile int *flag)
|
||||
{
|
||||
*flag = 1;
|
||||
return TIMER_CONTINUE;
|
||||
}
|
||||
|
||||
int azur_main_loop(
|
||||
void (*render)(void), int render_fps,
|
||||
int (*update)(void), int update_ups,
|
||||
int flags)
|
||||
{
|
||||
volatile int render_tick = 1;
|
||||
volatile int update_tick = 0;
|
||||
bool started = false;
|
||||
|
||||
ml_timer_render = timer_configure(TIMER_ANY, 1000000 / render_fps,
|
||||
GINT_CALL(set_flag, &render_tick));
|
||||
if(ml_timer_render < 0) {
|
||||
azlog(ERROR, "failed to create render timer\n");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
timer_start(ml_timer_render);
|
||||
}
|
||||
|
||||
if(!(flags & AZUR_MAIN_LOOP_TIED)) {
|
||||
ml_timer_update = timer_configure(TIMER_ANY, 1000000 / update_ups,
|
||||
GINT_CALL(set_flag, &update_tick));
|
||||
if(ml_timer_update < 0) {
|
||||
timer_stop(ml_timer_render);
|
||||
azlog(ERROR, "failed to create render timer\n");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
timer_start(ml_timer_update);
|
||||
}
|
||||
}
|
||||
|
||||
while(1) {
|
||||
if(update_tick && !(flags & AZUR_MAIN_LOOP_TIED)) {
|
||||
update_tick = 0;
|
||||
if(update && update()) break;
|
||||
}
|
||||
|
||||
if(render_tick) {
|
||||
render_tick = 0;
|
||||
|
||||
/* Tied renders and updates */
|
||||
if(started && (flags & AZUR_MAIN_LOOP_TIED)) {
|
||||
if(update && update()) break;
|
||||
}
|
||||
if(render) render();
|
||||
started = true;
|
||||
}
|
||||
|
||||
sleep();
|
||||
}
|
||||
|
||||
if(ml_timer_render >= 0) {
|
||||
timer_stop(ml_timer_render);
|
||||
ml_timer_render = 0;
|
||||
}
|
||||
if(ml_timer_update >= 0) {
|
||||
timer_stop(ml_timer_update);
|
||||
ml_timer_update = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -30,7 +30,7 @@ static int commands_count=0, commands_length=0;
|
|||
Rendering order is integer order. */
|
||||
static uint32_t commands_array[AZRP_MAX_COMMANDS];
|
||||
|
||||
static GALIGNED(4) uint8_t commands_data[4*16384];
|
||||
static GALIGNED(4) uint8_t commands_data[16384*2];
|
||||
|
||||
/* Array of shader programs and uniforms. */
|
||||
static azrp_shader_t *shaders[AZRP_MAX_SHADERS] = { NULL };
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
#include <azur/gint/render.h>
|
||||
|
||||
uint8_t AZRP_SHADER_CIRCLE = -1;
|
||||
|
||||
__attribute__((constructor))
|
||||
static void register_shader(void)
|
||||
{
|
||||
extern azrp_shader_t azrp_shader_circle;
|
||||
AZRP_SHADER_CIRCLE = azrp_register_shader(azrp_shader_circle);
|
||||
}
|
||||
|
||||
void azrp_shader_circle_configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_CIRCLE, (void *)azrp_width);
|
||||
}
|
||||
|
||||
|
||||
static int min(int x, int y)
|
||||
{
|
||||
return (x < y) ? x : y;
|
||||
}
|
||||
static int max(int x, int y)
|
||||
{
|
||||
return (x > y) ? x : y;
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
#define TABLE_WIDTH 256
|
||||
|
||||
struct command {
|
||||
uint8_t shader_id;
|
||||
uint16_t color;
|
||||
uint8_t curr_frag;
|
||||
uint16_t NbPixels[14]; // Nunmber of pixels in each fragment
|
||||
uint16_t DataPixelsX[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width
|
||||
uint16_t DataPixelsY[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width
|
||||
};
|
||||
|
||||
void AddPixelCircle( int16_t xp, int16_t yp, struct command *cmd )
|
||||
{
|
||||
if (xp >= 0 && xp < azrp_width && yp >= 0 && yp < azrp_height)
|
||||
{
|
||||
uint8_t cfrag = yp / azrp_frag_height;
|
||||
uint16_t nbpixinfrag = cmd->NbPixels[ cfrag ];
|
||||
|
||||
uint16_t index = cfrag * TABLE_WIDTH + nbpixinfrag;
|
||||
|
||||
cmd->DataPixelsX[ index ] = xp;
|
||||
cmd->DataPixelsY[ index ] = yp & 15;
|
||||
cmd->NbPixels[ cfrag ]++;
|
||||
}
|
||||
}
|
||||
|
||||
void azrp_circle(int xc, int yc, uint16_t rad, uint16_t color)
|
||||
{
|
||||
prof_enter(azrp_perf_cmdgen);
|
||||
|
||||
|
||||
int xmin = xc - rad;
|
||||
int xmax = xc + rad;
|
||||
int ymin = yc - rad;
|
||||
int ymax = yc + rad;
|
||||
|
||||
// The circle is fully outside the screen
|
||||
if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) || (ymin >= azrp_height))
|
||||
{
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ytop = max( ymin, 0 );
|
||||
int ybot = min( ymax, azrp_height-1 );
|
||||
|
||||
int frag_first = ytop / azrp_frag_height;
|
||||
int frag_last = ybot / azrp_frag_height;
|
||||
int frag_count = frag_last - frag_first + 1;
|
||||
|
||||
|
||||
struct command cmd;
|
||||
cmd.shader_id = AZRP_SHADER_CIRCLE;
|
||||
cmd.color = color;
|
||||
cmd.curr_frag = frag_first;
|
||||
|
||||
// reset the point counters in each cell of the table
|
||||
for( int i = 0; i < 14; i++ )
|
||||
cmd.NbPixels[i]=0;
|
||||
|
||||
int x = 0;
|
||||
int y = rad;
|
||||
int m = 5 - 4*rad;
|
||||
|
||||
while (x <= y)
|
||||
{
|
||||
AddPixelCircle( xc+x, yc+y, &cmd );
|
||||
AddPixelCircle( xc+y, yc+x, &cmd );
|
||||
AddPixelCircle( xc-x, yc+y, &cmd );
|
||||
AddPixelCircle( xc-y, yc+x, &cmd );
|
||||
AddPixelCircle( xc+x, yc-y, &cmd );
|
||||
AddPixelCircle( xc+y, yc-x, &cmd );
|
||||
AddPixelCircle( xc-x, yc-y, &cmd );
|
||||
AddPixelCircle( xc-y, yc-x, &cmd );
|
||||
|
||||
if (m > 0)
|
||||
{
|
||||
y--;
|
||||
m -= 8*y;
|
||||
}
|
||||
x++;
|
||||
m += 8*x + 4;
|
||||
}
|
||||
|
||||
azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count);
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
}
|
||||
|
||||
void azrp_shader_circle( void *uniforms, void *comnd, void *fragment )
|
||||
{
|
||||
struct command *cmd = (struct command *) comnd;
|
||||
uint16_t *frag = (uint16_t *) fragment;
|
||||
|
||||
uint16_t *taille = (uint16_t *) cmd->NbPixels;
|
||||
uint16_t *DX = (uint16_t *) cmd->DataPixelsX;
|
||||
uint16_t *DY = (uint16_t *) cmd->DataPixelsY;
|
||||
|
||||
uint16_t nbpix = taille[ cmd->curr_frag ];
|
||||
int BaseAdress = cmd->curr_frag * TABLE_WIDTH;
|
||||
|
||||
for( int i = 0; i < nbpix; i++ )
|
||||
{
|
||||
uint16_t X = DX[ BaseAdress + i ];
|
||||
uint16_t Y = DY[ BaseAdress + i ];
|
||||
|
||||
frag[ azrp_width * Y + X ] = cmd->color;
|
||||
}
|
||||
|
||||
cmd->curr_frag++;
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
#include <azur/gint/render.h>
|
||||
|
||||
uint8_t AZRP_SHADER_FILLEDCIRCLE = -1;
|
||||
|
||||
__attribute__((constructor)) static void register_shader(void) {
|
||||
extern azrp_shader_t azrp_shader_filledcircle;
|
||||
AZRP_SHADER_FILLEDCIRCLE = azrp_register_shader(azrp_shader_filledcircle);
|
||||
}
|
||||
|
||||
void azrp_shader_filledcircle_configure(void) {
|
||||
azrp_set_uniforms(AZRP_SHADER_FILLEDCIRCLE, (void *)azrp_width);
|
||||
}
|
||||
|
||||
static int min(int x, int y) { return (x < y) ? x : y; }
|
||||
static int max(int x, int y) { return (x > y) ? x : y; }
|
||||
|
||||
//---
|
||||
|
||||
#define TABLE_WIDTH
|
||||
|
||||
struct command {
|
||||
uint8_t shader_id;
|
||||
uint16_t color;
|
||||
uint8_t curr_frag;
|
||||
int16_t DataFilling[2 * 224]; // Each line of the screen can have a xmin and
|
||||
// a xmax value
|
||||
};
|
||||
|
||||
void AddPixelFilledCircle(int16_t xpmin, int16_t xpmax, int16_t yp,
|
||||
struct command *cmd) {
|
||||
if (yp >= 0 && yp < azrp_height) {
|
||||
if (xpmin >= 0)
|
||||
cmd->DataFilling[2 * yp] = xpmin;
|
||||
else
|
||||
cmd->DataFilling[2 * yp] = 0;
|
||||
|
||||
if (xpmax < azrp_width)
|
||||
cmd->DataFilling[2 * yp + 1] = xpmax;
|
||||
else
|
||||
cmd->DataFilling[2 * yp + 1] = azrp_width - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void azrp_filledcircle(int xc, int yc, uint16_t rad, uint16_t color) {
|
||||
prof_enter(azrp_perf_cmdgen);
|
||||
|
||||
int xmin = xc - rad;
|
||||
int xmax = xc + rad;
|
||||
int ymin = yc - rad;
|
||||
int ymax = yc + rad;
|
||||
|
||||
// The circle is fully outside the screen
|
||||
if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) ||
|
||||
(ymin >= azrp_height)) {
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
return;
|
||||
}
|
||||
|
||||
int ytop = max(ymin, 0);
|
||||
int ybot = min(ymax, azrp_height - 1);
|
||||
|
||||
int frag_first = ytop / azrp_frag_height;
|
||||
int frag_last = ybot / azrp_frag_height;
|
||||
int frag_count = frag_last - frag_first + 1;
|
||||
|
||||
struct command cmd;
|
||||
cmd.shader_id = AZRP_SHADER_FILLEDCIRCLE;
|
||||
cmd.color = color;
|
||||
cmd.curr_frag = frag_first;
|
||||
|
||||
// reset the point counters in each cell of the table
|
||||
for (int i = 0; i < 224; i++) {
|
||||
cmd.DataFilling[2 * i] = -1; // reset with value equels -1
|
||||
cmd.DataFilling[2 * i + 1] = -1; // reset with value equals -1
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int y = rad;
|
||||
int m = 5 - 4 * rad;
|
||||
|
||||
while (x <= y) {
|
||||
AddPixelFilledCircle(xc - x, xc + x, yc - y, &cmd);
|
||||
AddPixelFilledCircle(xc - y, xc + y, yc - x, &cmd);
|
||||
AddPixelFilledCircle(xc - x, xc + x, yc + y, &cmd);
|
||||
AddPixelFilledCircle(xc - y, xc + y, yc + x, &cmd);
|
||||
|
||||
if (m > 0) {
|
||||
y--;
|
||||
m -= 8 * y;
|
||||
}
|
||||
x++;
|
||||
m += 8 * x + 4;
|
||||
}
|
||||
|
||||
azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count);
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
}
|
||||
|
||||
void azrp_shader_filledcircle(void *uniforms, void *comnd, void *fragment) {
|
||||
struct command *cmd = (struct command *)comnd;
|
||||
uint16_t *frag = (uint16_t *)fragment;
|
||||
|
||||
int16_t *data = (int16_t *)cmd->DataFilling;
|
||||
int BaseAdress = cmd->curr_frag * azrp_frag_height * 2;
|
||||
|
||||
for (int i = 0; i < azrp_frag_height; i++) {
|
||||
int16_t Xmin = data[BaseAdress + 2 * i];
|
||||
int16_t Xmax = data[BaseAdress + 2 * i + 1];
|
||||
|
||||
if (Xmin != -1 && Xmax != -1)
|
||||
for (int j = Xmin; j <= Xmax; j++)
|
||||
frag[azrp_width * i + j] = cmd->color;
|
||||
}
|
||||
|
||||
cmd->curr_frag++;
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
#include <azur/gint/render.h>
|
||||
|
||||
uint8_t AZRP_SHADER_FILLEDPOLY = -1;
|
||||
|
||||
__attribute__((constructor)) static void register_shader(void) {
|
||||
extern azrp_shader_t azrp_shader_filledpoly;
|
||||
AZRP_SHADER_FILLEDPOLY = azrp_register_shader(azrp_shader_filledpoly);
|
||||
}
|
||||
|
||||
void azrp_shader_filledpoly_configure(void) {
|
||||
azrp_set_uniforms(AZRP_SHADER_FILLEDPOLY, (void *)azrp_width);
|
||||
}
|
||||
|
||||
static int min(int x, int y) { return (x < y) ? x : y; }
|
||||
static int max(int x, int y) { return (x > y) ? x : y; }
|
||||
|
||||
//---
|
||||
|
||||
#define TABLE_WIDTH
|
||||
|
||||
struct command {
|
||||
uint8_t shader_id;
|
||||
uint16_t color;
|
||||
uint8_t curr_frag;
|
||||
int16_t xmin[224];
|
||||
int16_t xmax[224];
|
||||
uint8_t empty[224];
|
||||
};
|
||||
|
||||
|
||||
void AddPixelFilledPoly(int16_t xpmin, int16_t xpmax, int16_t yp,
|
||||
struct command *cmd) {
|
||||
if (yp >= 0 && yp < azrp_height) {
|
||||
if (xpmin >= 0)
|
||||
cmd->xmin[yp] = xpmin;
|
||||
else
|
||||
cmd->xmin[yp] = 0;
|
||||
|
||||
if (xpmax < azrp_width)
|
||||
cmd->xmax[yp] = xpmax;
|
||||
else
|
||||
cmd->xmax[yp] = azrp_width - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color) {
|
||||
prof_enter(azrp_perf_cmdgen);
|
||||
|
||||
int i, ymin, ymax, xmin2, xmax2, *xmin, *xmax;
|
||||
char *empty;
|
||||
|
||||
if(nb_vertices < 3) {
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
return;
|
||||
}
|
||||
|
||||
ymin = ymax = y[0];
|
||||
xmin2 = xmax2 = x[0];
|
||||
|
||||
for(i=0 ; i<nb_vertices ; i++) {
|
||||
if(y[i] < ymin) ymin = y[i];
|
||||
if(y[i] > ymax) ymax = y[i];
|
||||
if(x[i] < xmin2) xmin2 = x[i];
|
||||
if(x[i] > xmax2) xmax2 = x[i];
|
||||
}
|
||||
|
||||
// The polygon is fully outside the screen
|
||||
if ((xmax2 < 0) || (xmin2 >= azrp_width) || (ymax < 0) ||
|
||||
(ymin >= azrp_height)) {
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
return;
|
||||
}
|
||||
|
||||
xmin = malloc((ymax-ymin+1)*sizeof(int));
|
||||
xmax = malloc((ymax-ymin+1)*sizeof(int));
|
||||
empty = malloc(ymax-ymin+1);
|
||||
|
||||
|
||||
int ytop = max(ymin, 0);
|
||||
int ybot = min(ymax, azrp_height - 1);
|
||||
|
||||
int frag_first = ytop / azrp_frag_height;
|
||||
int frag_last = ybot / azrp_frag_height;
|
||||
int frag_count = frag_last - frag_first + 1;
|
||||
|
||||
struct command cmd;
|
||||
cmd.shader_id = AZRP_SHADER_FILLEDPOLY;
|
||||
cmd.color = color;
|
||||
cmd.curr_frag = frag_first;
|
||||
|
||||
// reset the point counters in each cell of the table
|
||||
for (int i = 0; i < 224; i++) {
|
||||
cmd.xmin[i] = -1; // reset with value equels -1
|
||||
cmd.xmax[i] = -1; // reset with value equals -1
|
||||
}
|
||||
|
||||
if(xmin && xmax && empty) {
|
||||
for(i=0 ; i<ymax-ymin+1 ; i++) empty[i] = 1;
|
||||
for(i=0 ; i<nb_vertices ; i++) {
|
||||
int j, px, py, dx, dy, sx, sy, cumul;
|
||||
px = x[i];
|
||||
py = y[i];
|
||||
dx = x[(i+1)%nb_vertices]-px;
|
||||
dy = y[(i+1)%nb_vertices]-py;
|
||||
sx = (dx > 0) ? 1 : -1;
|
||||
sy = (dy > 0) ? 1 : -1;
|
||||
dx = (dx > 0) ? dx : -dx;
|
||||
dy = (dy > 0) ? dy : -dy;
|
||||
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
|
||||
if(dx > dy) {
|
||||
cumul = dx >> 1;
|
||||
for(j=1 ; j<dx ; j++) {
|
||||
px += sx;
|
||||
cumul += dy;
|
||||
if(cumul > dx) cumul -= dx, py += sy;
|
||||
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
|
||||
}
|
||||
} else {
|
||||
cumul = dy >> 1;
|
||||
for(j=1 ; j<dy ; j++) {
|
||||
py += sy;
|
||||
cumul += dx;
|
||||
if(cumul > dy) cumul -= dy, px += sx;
|
||||
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0 ; i<ymax-ymin+1 ; i++)
|
||||
AddPixelFilledPoly(xmin[i], xmax[i], ymin+i, &cmd);
|
||||
}
|
||||
free(xmin);
|
||||
free(xmax);
|
||||
free(empty);
|
||||
|
||||
azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count);
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
}
|
||||
|
||||
void azrp_shader_filledpoly(void *uniforms, void *comnd, void *fragment) {
|
||||
struct command *cmd = (struct command *)comnd;
|
||||
uint16_t *frag = (uint16_t *)fragment;
|
||||
|
||||
int16_t *Xmindata = (int16_t *)cmd->xmin;
|
||||
int16_t *Xmaxdata = (int16_t *)cmd->xmax;
|
||||
|
||||
int BaseAdress = cmd->curr_frag * azrp_frag_height;
|
||||
|
||||
for (int i = 0; i < azrp_frag_height; i++)
|
||||
{
|
||||
int16_t Xmin = Xmindata[BaseAdress + i];
|
||||
int16_t Xmax = Xmaxdata[BaseAdress + i];
|
||||
|
||||
if (Xmin != -1 && Xmax != -1)
|
||||
if (Xmin<=Xmax)
|
||||
for (int j = Xmin; j <= Xmax; j++) frag[azrp_width * i + j] = cmd->color;
|
||||
else
|
||||
for (int j = Xmax; j <= Xmin; j++) frag[azrp_width * i + j] = cmd->color;
|
||||
}
|
||||
|
||||
cmd->curr_frag++;
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
#include <azur/gint/render.h>
|
||||
|
||||
uint8_t AZRP_SHADER_LINE = -1;
|
||||
|
||||
__attribute__((constructor))
|
||||
static void register_shader(void)
|
||||
{
|
||||
extern azrp_shader_t azrp_shader_line;
|
||||
AZRP_SHADER_LINE = azrp_register_shader(azrp_shader_line);
|
||||
}
|
||||
|
||||
void azrp_shader_line_configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_LINE, (void *)azrp_width);
|
||||
}
|
||||
|
||||
|
||||
//---
|
||||
|
||||
struct command {
|
||||
uint8_t shader_id;
|
||||
uint16_t color;
|
||||
uint16_t curr_y;
|
||||
uint16_t curr_x;
|
||||
int16_t dx, dy, sx, sy;
|
||||
int16_t cumul;
|
||||
int16_t i;
|
||||
};
|
||||
|
||||
int ABS( int x1 )
|
||||
{
|
||||
if (x1 >= 0) return x1;
|
||||
else return (-1 * x1);
|
||||
}
|
||||
|
||||
int SGN( int x1 )
|
||||
{
|
||||
if (x1 > 0) return 1;
|
||||
else if (x1 == 0) return 0;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
void azrp_line(int xA, int yA, int xB, int yB, uint16_t color)
|
||||
{
|
||||
prof_enter(azrp_perf_cmdgen);
|
||||
|
||||
//clipping algorithm as per "Another Simple but Faster Method for 2D Line Clipping"
|
||||
//from Dimitrios Matthes and Vasileios Drakopoulos
|
||||
//International Journal of Computer Graphics & Animation (IJCGA) Vol.9, No.1/2/3, July 2019
|
||||
|
||||
int xmin = 0;
|
||||
int xmax = azrp_width-1;
|
||||
int ymin = 0;
|
||||
int ymax = azrp_height-1;
|
||||
|
||||
//step 1 line are fully out of the screen
|
||||
if ((xA<xmin && xB<xmin) || (xA>xmax && xB>xmax) || (yA<ymin && yB<ymin) || (yA>ymax && yB>ymax)) {
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
return;
|
||||
}
|
||||
|
||||
int x1, x2, y1, y2;
|
||||
|
||||
// step 1.5 - specific to Azur fragment approach
|
||||
// we swap to always start with the point on top as the fragment are updated from top to bottom
|
||||
// (x1,y1) is the most top point and (x2,y2) is the most bottom point (rankig as per y values only
|
||||
if (yA <= yB) {
|
||||
x1 = xA; y1 = yA;
|
||||
x2 = xB; y2 = yB;
|
||||
}
|
||||
else {
|
||||
x1 = xB; y1 = yB;
|
||||
x2 = xA; y2 = yA;
|
||||
}
|
||||
|
||||
//step 2 line clipping within the box (xmin,ymin) --> (xmax,ymax)
|
||||
int x[2];
|
||||
int y[2];
|
||||
|
||||
x[0] = x1; x[1] = x2;
|
||||
y[0] = y1; y[1] = y2;
|
||||
|
||||
|
||||
for(int i=0; i<2; i++) {
|
||||
if (x[i] < xmin) {
|
||||
x[i] = xmin; y[i] = ((y2-y1) * (xmin-x1)) / (x2-x1) + y1;
|
||||
}
|
||||
else if (x[i] > xmax) {
|
||||
x[i] = xmax; y[i] = ((y2-y1) * (xmax-x1)) / (x2-x1) + y1;
|
||||
}
|
||||
|
||||
if (y[i] < ymin) {
|
||||
x[i] = ((x2-x1) * (ymin-y1)) / (y2-y1) + x1; y[i] = ymin;
|
||||
}
|
||||
else if (y[i] > ymax) {
|
||||
x[i] = ((x2-x1) * (ymax-y1)) / (y2-y1) + x1; y[i] = ymax;
|
||||
}
|
||||
}
|
||||
|
||||
if((x[0] < xmin && x[1] < xmin) || (x[0] > xmax && x[1] > xmax)) {
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
return;
|
||||
}
|
||||
|
||||
x1 = x[0];
|
||||
y1 = y[0];
|
||||
x2 = x[1];
|
||||
y2 = y[1];
|
||||
|
||||
int frag_first = y1 / azrp_frag_height;
|
||||
int frag_last = y2 / azrp_frag_height;
|
||||
int frag_count = frag_last - frag_first + 1;
|
||||
|
||||
struct command cmd;
|
||||
cmd.shader_id = AZRP_SHADER_LINE;
|
||||
cmd.color = color;
|
||||
|
||||
cmd.curr_x = x1;
|
||||
cmd.curr_y = y1 & 15;
|
||||
|
||||
cmd.dx = ABS(x2-x1);
|
||||
cmd.sx = SGN(x2-x1);
|
||||
|
||||
cmd.dy = ABS(y2-y1);
|
||||
cmd.sy = SGN(y2-y1);
|
||||
|
||||
cmd.i = 0;
|
||||
cmd.cumul = (cmd.dx >= cmd.dy) ? cmd.dx/2 : cmd.dy/2;
|
||||
|
||||
azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count);
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
}
|
||||
|
||||
void azrp_shader_line( void *uniforms, void *comnd, void *fragment )
|
||||
{
|
||||
struct command *cmd = (struct command *) comnd;
|
||||
uint16_t *frag = (uint16_t *) fragment;
|
||||
|
||||
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
|
||||
|
||||
int i;
|
||||
|
||||
if (cmd->dy == 0)
|
||||
{
|
||||
for( i = cmd->i; i < cmd->dx ; i++ )
|
||||
{
|
||||
cmd->curr_x += cmd->sx;
|
||||
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
|
||||
}
|
||||
}
|
||||
else if (cmd->dx == 0)
|
||||
{
|
||||
for( i = cmd->i; i < cmd->dy ; i++ )
|
||||
{
|
||||
cmd->curr_y += cmd->sy;
|
||||
|
||||
// if curr_y=16, this means we are changing to next fragment
|
||||
if (cmd->curr_y == azrp_frag_height) break;
|
||||
|
||||
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
|
||||
}
|
||||
}
|
||||
else if (cmd->dx >= cmd->dy)
|
||||
{
|
||||
for( i = cmd->i; i < cmd->dx; i++ )
|
||||
{
|
||||
cmd->curr_x += cmd->sx;
|
||||
cmd->cumul += cmd->dy;
|
||||
if (cmd->cumul > cmd->dx)
|
||||
{
|
||||
cmd->cumul -= cmd->dx;
|
||||
cmd->curr_y += cmd->sy;
|
||||
}
|
||||
// if curr_y=16, this means we are changing to next fragment
|
||||
if (cmd->curr_y == azrp_frag_height ) break;
|
||||
|
||||
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = cmd->i; i < cmd->dy; i++ )
|
||||
{
|
||||
cmd->curr_y += cmd->sy;
|
||||
cmd->cumul += cmd->dx;
|
||||
if (cmd->cumul > cmd->dy)
|
||||
{
|
||||
cmd->cumul -= cmd->dy;
|
||||
cmd->curr_x += cmd->sx;
|
||||
}
|
||||
|
||||
// if curr_y=16, this means we are changing to next fragment
|
||||
if (cmd->curr_y == azrp_frag_height) break;
|
||||
|
||||
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
|
||||
}
|
||||
}
|
||||
|
||||
cmd->curr_y = cmd->curr_y & 15;
|
||||
|
||||
cmd->i = i+1;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <azur/gint/render.h>
|
||||
|
||||
void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color) {
|
||||
prof_enter(azrp_perf_cmdgen);
|
||||
|
||||
for( int i=0 ; i<nb_vertices ; i++) {
|
||||
int px = x[i];
|
||||
int py = y[i];
|
||||
int px2 = x[(i+1)%nb_vertices];
|
||||
int py2 = y[(i+1)%nb_vertices];
|
||||
azrp_line( px, py, px2, py2, color );
|
||||
}
|
||||
|
||||
prof_leave(azrp_perf_cmdgen);
|
||||
}
|
|
@ -134,8 +134,7 @@ SDL_Window *azur_sdl_window(void)
|
|||
// Main loop setup
|
||||
//---
|
||||
|
||||
/* Time spent in the main loop (seconds)
|
||||
TODO: Handle ml_time (also in the gint backend) */
|
||||
/* Time spent in the main loop (seconds) */
|
||||
static double ml_time = 0.0;
|
||||
|
||||
/* In emscripten, callbacks are void/void, vsync is always ON, and the
|
||||
|
|
|
@ -7,31 +7,15 @@
|
|||
|
||||
include(CTest)
|
||||
|
||||
set(SOURCES
|
||||
src/num.cpp
|
||||
add_library(num STATIC
|
||||
src/str.cpp)
|
||||
|
||||
if(DEFINED AZUR_ARCH_GENERIC)
|
||||
set(LIBNUM_ARCH_GENERIC TRUE)
|
||||
elseif(DEFINED AZUR_ARCH_SH4ALDSP)
|
||||
set(LIBNUM_ARCH_SH4ALDSP TRUE)
|
||||
list(APPEND SOURCES
|
||||
src/sh4aldsp/div_i32_i16_i16.s)
|
||||
endif()
|
||||
|
||||
configure_file(include/num/config.h.in num/config.h)
|
||||
|
||||
add_library(num STATIC ${SOURCES})
|
||||
target_include_directories(num PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
target_include_directories(num PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
|
||||
# Library file: libnum.a
|
||||
install(TARGETS num DESTINATION ${LIBDIR})
|
||||
# Headers: num/config.h and num/*.h
|
||||
# Headers: azur/*.h
|
||||
install(DIRECTORY include/ DESTINATION ${INCDIR})
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/num/config.h"
|
||||
DESTINATION ${INCDIR}/num)
|
||||
|
||||
#---
|
||||
# Unit tests
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// ," /\ ", Azur: A game engine for CASIO fx-CG and PC //
|
||||
// | _/__\_ | Designed by Lephe' and the Planète Casio community. //
|
||||
// "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> //
|
||||
//---------------------------------------------------------------------------//
|
||||
// num.config: Compile-time configuration options
|
||||
|
||||
#pragma once
|
||||
|
||||
/* CPU architecture. */
|
||||
|
||||
/* Generic/unknown CPU architecture; only C code is used. */
|
||||
#cmakedefine LIBNUM_ARCH_GENERIC
|
||||
/* SH4AL-DSP for the fx-CG. */
|
||||
#cmakedefine LIBNUM_ARCH_SH4ALDSP
|
|
@ -48,8 +48,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <num/primitives.h>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
|
||||
|
@ -116,15 +117,9 @@ struct num8
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr num8 ifloor() {
|
||||
return 0;
|
||||
}
|
||||
inline constexpr num8 floor() {
|
||||
return num8(0);
|
||||
}
|
||||
inline constexpr num8 iceil() {
|
||||
return v != 0;
|
||||
}
|
||||
/* Warning: num8::ceil() always overflows! */
|
||||
inline constexpr num8 ceil() {
|
||||
return num8(0);
|
||||
|
@ -137,19 +132,19 @@ struct num8
|
|||
|
||||
/* Comparisons with int */
|
||||
|
||||
inline constexpr bool operator==(int const &i) const {
|
||||
inline constexpr bool operator==(int const &i) {
|
||||
return (v | i) == 0;
|
||||
}
|
||||
inline constexpr bool operator<(int const &i) const {
|
||||
inline constexpr bool operator<(int const &i) {
|
||||
return i >= 1;
|
||||
}
|
||||
inline constexpr bool operator>=(int const &i) const {
|
||||
inline constexpr bool operator>=(int const &i) {
|
||||
return i <= 0;
|
||||
}
|
||||
inline constexpr bool operator<=(int const &i) const {
|
||||
inline constexpr bool operator<=(int const &i) {
|
||||
return i + !v > 0;
|
||||
}
|
||||
inline constexpr bool operator>(int const &i) const {
|
||||
inline constexpr bool operator>(int const &i) {
|
||||
return i + !v <= 0;
|
||||
}
|
||||
|
||||
|
@ -200,9 +195,6 @@ struct num16
|
|||
/* num16 x num16 -> num32 multiplication
|
||||
This is efficiently implemented with a muls.w instruction. */
|
||||
static constexpr num32 dmul(num16 const &x, num16 const &y);
|
||||
/* num16 / num16 -> num16 division for positive numbers
|
||||
This bypasses some sign tests, which saves a bit of time. */
|
||||
static constexpr num16 div_positive(num16 const &x, num16 const &y);
|
||||
|
||||
/* Basic arithmetic */
|
||||
|
||||
|
@ -218,25 +210,19 @@ struct num16
|
|||
v = (v * other.v) / 256;
|
||||
return *this;
|
||||
}
|
||||
inline num16 &operator/=(num16 const &other) {
|
||||
v = prim::div_i32_i16_i16(v * 256, other.v);
|
||||
inline constexpr num16 &operator/=(num16 const &other) {
|
||||
v = (v * 256) / other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr num16 &operator%=(num16 const &other) {
|
||||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr int ifloor() {
|
||||
return v >> 8;
|
||||
}
|
||||
inline constexpr num16 floor() {
|
||||
num16 x;
|
||||
x.v = v & 0xff00;
|
||||
return x;
|
||||
}
|
||||
inline constexpr int iceil() {
|
||||
return (v + 0xff) >> 8;
|
||||
}
|
||||
inline constexpr num16 ceil() {
|
||||
num16 x;
|
||||
x.v = ((v - 1) | 0xff) + 1;
|
||||
|
@ -250,22 +236,22 @@ struct num16
|
|||
|
||||
/* Comparisons with int */
|
||||
|
||||
inline constexpr bool operator==(int const &i) const {
|
||||
inline constexpr bool operator==(int const &i) {
|
||||
return (int16_t)i == i && (i << 8) == v;
|
||||
}
|
||||
inline constexpr bool operator<(int const &i) const {
|
||||
inline constexpr bool operator<(int const &i) {
|
||||
return (v >> 8) < i;
|
||||
}
|
||||
inline constexpr bool operator>=(int const &i) const {
|
||||
inline constexpr bool operator>=(int const &i) {
|
||||
return (v >> 8) >= i;
|
||||
}
|
||||
/* Unfortunately the branchless version for this test is expressed in terms
|
||||
of `v`, not `i`, so it does not simplify well when `i` is known. In that
|
||||
case, writing eg. `x > num16(0)` is faster than `x > 0`. */
|
||||
inline constexpr bool operator<=(int const &i) const {
|
||||
inline constexpr bool operator<=(int const &i) {
|
||||
return (v >> 8) + ((v & 0xff) != 0) <= i;
|
||||
}
|
||||
inline constexpr bool operator>(int const &i) const {
|
||||
inline constexpr bool operator>(int const &i) {
|
||||
return (v >> 8) + ((v & 0xff) != 0) > i;
|
||||
}
|
||||
|
||||
|
@ -344,17 +330,11 @@ struct num32
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr int ifloor() {
|
||||
return v >> 16;
|
||||
}
|
||||
inline constexpr num32 floor() {
|
||||
num32 x;
|
||||
x.v = v & 0xffff0000;
|
||||
return x;
|
||||
}
|
||||
inline constexpr int iceil() {
|
||||
return (v + 0xffff) >> 16;
|
||||
}
|
||||
inline constexpr num32 ceil() {
|
||||
num32 x;
|
||||
x.v = ((v - 1) | 0xffff) + 1;
|
||||
|
@ -365,23 +345,22 @@ struct num32
|
|||
x.v = v & 0xffff;
|
||||
return x;
|
||||
}
|
||||
num32 sqrt() const;
|
||||
|
||||
/* Comparisons with int */
|
||||
|
||||
inline constexpr bool operator==(int const &i) const {
|
||||
inline constexpr bool operator==(int const &i) {
|
||||
return (int16_t)i == i && (i << 16) == v;
|
||||
}
|
||||
inline constexpr bool operator<(int const &i) const {
|
||||
inline constexpr bool operator<(int const &i) {
|
||||
return (v >> 16) < i;
|
||||
}
|
||||
inline constexpr bool operator>=(int const &i) const {
|
||||
inline constexpr bool operator>=(int const &i) {
|
||||
return (v >> 16) >= i;
|
||||
}
|
||||
inline constexpr bool operator<=(int const &i) const {
|
||||
inline constexpr bool operator<=(int const &i) {
|
||||
return (v >> 16) + ((v & 0xffff) != 0) <= i;
|
||||
}
|
||||
inline constexpr bool operator>(int const &i) const {
|
||||
inline constexpr bool operator>(int const &i) {
|
||||
return (v >> 16) + ((v & 0xffff) != 0) > i;
|
||||
}
|
||||
|
||||
|
@ -468,17 +447,11 @@ struct num64
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr int ifloor() {
|
||||
return v >> 32;
|
||||
}
|
||||
inline constexpr num64 floor() {
|
||||
num64 x;
|
||||
x.v = v & 0xffffffff00000000ull;
|
||||
return x;
|
||||
}
|
||||
inline constexpr int iceil() {
|
||||
return (v >> 32) + ((uint32_t)v != 0);
|
||||
}
|
||||
inline constexpr num64 ceil() {
|
||||
num64 x;
|
||||
x.v = ((v - 1) | 0xffffffffull) + 1;
|
||||
|
@ -596,26 +569,6 @@ inline constexpr T operator-(T const &op) {
|
|||
return T(0) - op;
|
||||
}
|
||||
|
||||
/* Internal minima, maxima and clamp */
|
||||
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T min(T const &left, T const &right)
|
||||
{
|
||||
return (left < right) ? left : right;
|
||||
}
|
||||
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T max(T const &left, T const &right)
|
||||
{
|
||||
return (left > right) ? left : right;
|
||||
}
|
||||
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T clamp(T const &val, T const &lower, T const &upper)
|
||||
{
|
||||
return max(lower, min(val, upper));
|
||||
}
|
||||
|
||||
/* Other specific operations */
|
||||
|
||||
inline constexpr num32 num16::dmul(num16 const &x, num16 const &y)
|
||||
|
@ -625,13 +578,6 @@ inline constexpr num32 num16::dmul(num16 const &x, num16 const &y)
|
|||
return n;
|
||||
}
|
||||
|
||||
inline constexpr num16 num16::div_positive(num16 const &x, num16 const &y)
|
||||
{
|
||||
num16 r;
|
||||
r.v = ((uint32_t)(uint16_t)x.v << 8) / (uint16_t)y.v;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline constexpr num64 num32::dmul(num32 const &x, num32 const &y)
|
||||
{
|
||||
num64 n;
|
||||
|
@ -639,12 +585,4 @@ inline constexpr num64 num32::dmul(num32 const &x, num32 const &y)
|
|||
return n;
|
||||
}
|
||||
|
||||
/* Floor modulo. We provide an optimized version for constants, which optimizes
|
||||
away the main condition. */
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T modf(T const &x, T const &y) {
|
||||
T r = x % y;
|
||||
return (r.v && (r.v ^ y.v) < 0) ? r + y : r;
|
||||
}
|
||||
|
||||
} /* namespace libnum */
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// ," /\ ", Azur: A game engine for CASIO fx-CG and PC //
|
||||
// | _/__\_ | Designed by Lephe' and the Planète Casio community. //
|
||||
// "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> //
|
||||
//---------------------------------------------------------------------------//
|
||||
// num.primitives: Platform-specific optimized primitives
|
||||
//
|
||||
// This header provides a generic interface to optimized primitives such as
|
||||
// unusual-size divisions. These are used in libnum functions for a performance
|
||||
// boost.
|
||||
//
|
||||
// The following functions are defined:
|
||||
// - div_X_Y_Z: Division of an X by a Y with a result of type Z (where X,Y,Z is
|
||||
// a signed integer type iN or an unsigned integer type uN)
|
||||
//---
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <num/config.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace libnum::prim {
|
||||
|
||||
#ifdef LIBNUM_ARCH_SH4ALDSP
|
||||
|
||||
extern int div_i32_i16_i16(int32_t num, int16_t denum);
|
||||
|
||||
#else
|
||||
|
||||
static inline constexpr int div_i32_i16_i16(int32_t num, int16_t denum)
|
||||
{
|
||||
return num / denum;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} /* namespace libnum::prim */
|
|
@ -189,10 +189,6 @@ inline constexpr vec<T,N> operator*(T const &lhs, vec<T,N> rhs) {
|
|||
rhs[i] *= lhs;
|
||||
return rhs;
|
||||
}
|
||||
template<typename T, int N>
|
||||
inline constexpr vec<T,N> operator/(vec<T,N> lhs, T const &rhs) {
|
||||
return lhs /= rhs;
|
||||
}
|
||||
|
||||
/* Comparisons */
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
#include <num/num.h>
|
||||
using namespace libnum;
|
||||
|
||||
/* Integer square root (rather slow) */
|
||||
static int64_t sqrtll(int64_t n)
|
||||
{
|
||||
if(n < 4)
|
||||
return (n > 0);
|
||||
|
||||
int64_t low_bound = sqrtll(n / 4) * 2;
|
||||
int64_t high_bound = low_bound + 1;
|
||||
|
||||
return (high_bound * high_bound <= n) ? high_bound : low_bound;
|
||||
}
|
||||
|
||||
num32 num32::sqrt() const
|
||||
{
|
||||
num32 r;
|
||||
r.v = sqrtll((int64_t)v << 16);
|
||||
return r;
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
# --------------------------------------------------------------------------- #
|
||||
# ," /\ ", Azur: A game engine for CASIO fx-CG and PC #
|
||||
# | _/__\_ | Designed by Lephe' and the Planète Casio community. #
|
||||
# "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# SH4AL-DSP optimized i32 / i16 -> i16 division.
|
||||
#
|
||||
# This simply uses the CPU's ability to divide without rotation for 16 bit
|
||||
# divisors without all the boilerplate than libgcc's __sdivisi3 requires since
|
||||
# it assumes 32-bit inputs. Used for num16 division.
|
||||
# ---
|
||||
|
||||
.global __ZN6libnum4prim15div_i32_i16_i16Els
|
||||
|
||||
# libnum::prim::div_i32_i16_i16(long, short)
|
||||
__ZN6libnum4prim15div_i32_i16_i16Els:
|
||||
shll16 r5
|
||||
mov #0, r2
|
||||
|
||||
mov r4, r3
|
||||
rotcl r3
|
||||
|
||||
subc r2, r4
|
||||
|
||||
div0s r5, r4
|
||||
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
div1 r5, r4
|
||||
|
||||
exts.w r4, r4
|
||||
|
||||
rotcl r4
|
||||
|
||||
addc r2, r4
|
||||
|
||||
rts
|
||||
exts.w r4, r0
|
|
@ -306,7 +306,7 @@ class ExprParser:
|
|||
return decorate
|
||||
|
||||
def binaryOpsRight(ctor, ops):
|
||||
return binaryOps(ctor, ops, rassoc=True)
|
||||
return binaryOpsRight(ctor, ops, rassoc=True)
|
||||
|
||||
def unaryOps(ctor, ops, assoc=True):
|
||||
def decorate(f):
|
||||
|
|
Loading…
Reference in New Issue