I've got quite a few routines that I've been moving from file to file. Most of them are pretty self-explanatory, and some may only make sense if Kerm releases his floating point library. All the angles are in degrees (as that's what the FP library uses). Some are out-right taken straight from Wikipedia, but I did my best to cite where I got everything from. I can take parts of it out if anyone wants me to.
Also, I'll be the first to say that some of these are terrible, and that I don't know how to structure a *.h and *.c set of files, so... Yeah.
library.h:
Code: #define LCD_WIDTH_PX 384
#define LCD_HEIGHT_PX 216
#define LCD_MIDDLE_X (LCD_WIDTH_PX / 2)
#define LCD_MIDDLE_Y (LCD_HEIGHT_PX / 2)
#define Flip Bdisp_PutDisp_DD
#define memcpy(dest, src, size) int abcd; for(abcd=0;abcd<size;abcd++) dest[abcd] = src[abcd];
#define abs(x) ((x) < 0 ? -(x) : (x))
#define swap(x, y) { x = x + y; y = x - y; x = x - y; }
#define square(x) ((x) * (x))
//
void CopySprite(char* data, int x, int y, int width, int height);
void XORSprite(char* data, int x, int y, int width, int height);
void Line(int x0, int y0, int x1, int y1, color_t color);
void Plot(int x, int y, color_t color);
color_t Get(int x, int y);
void Arc(int startangle, int endangle, int dist, int width, color_t color);
void Bucket(int x, int y, color_t targetcolor, color_t replacecolor);
void ClearScreen();
void FillScreen(color_t color);
void FilledCircle(int centerx, int centery, int radius, color_t color);
void FilledArc(int centerx, int centery, int radius, int startangle, int endangle, color_t color);
void FilledCheckLine(int x0, int y0, int x1, int y1, fp slopeleft, fp sloperight, color_t color);
int PRGM_GetKey();
int tandeg(int angle);
unsigned int rand(void);
unsigned int srandom(int seed);
int GetX(int centerx, int angle, int dist);
int GetY(int centery, int angle, int dist);
void FilledCircleAngle(int centerx, int centery, int angle, int dist, int radius, color_t color);
library.c:Code: // KermMartian
void XORSprite(char* data, int x, int y, int width, int height) {
int j, i;
char* VRAM = (char*)0xA8000000;
VRAM += 2*(LCD_WIDTH_PX*y + x);
for(j=y; j<y+height; j++) {
for(i=x; i<x+width; i++) {
*(VRAM++) ^= *(data++);
*(VRAM++) ^= *(data++);
}
VRAM += 2*(LCD_WIDTH_PX-width);
}
}
// KermMartian
void CopySprite(char* data, int x, int y, int width, int height) {
int j;
char* VRAM = (char*)0xA8000000;
VRAM += 2*(LCD_WIDTH_PX*y + x);
for(j=y; j<y+height; j++) {
memcpy(VRAM,data,2*width);
VRAM += 2*LCD_WIDTH_PX;
data += 2*width;
}
}
// Catherine
void Line(int x0, int y0, int x1, int y1, color_t color) {
Plot(x0, y0, color);
Plot(x1, y1, color);
int steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int deltax = x1 - x0;
int deltay = abs(y1 - y0);
int error = deltax / 2;
int ystep;
int y = y0;
int x;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for(x=x0;x<x1;x++) {
if (steep)
Plot(y, x, color);
else
Plot(x, y, color);
error -= deltay;
if (error < 0) {
y += ystep;
error += deltax;
}
}
}
// Catherine
void Plot(int x, int y, color_t color) {
short* VRAM = (short*)0xA8000000;
VRAM[LCD_WIDTH_PX*y + x] = color;
}
// Catherine
color_t Get(int x, int y) {
short* VRAM = (short*)0xA8000000;
return VRAM[LCD_WIDTH_PX*y + x];
}
// Catherine
void Arc(int startangle, int endangle, int dist, int width, color_t color) {
while (startangle > endangle)
endangle += 360;
int angle;
int cos;
int sin;
int halfwidth = fp_convert(0, 14, width / 2);
width = fp_convert(0, 14, width);
dist = fp_convert(0, 14, dist);
int lastcos = cosdeg(startangle % 360);
int lastsin = sindeg(startangle % 360);
Line(LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist, lastcos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist, lastsin, 14)),
LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, lastcos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, lastsin, 14)),
color);
for(angle=startangle; angle<endangle; angle++) {
cos = cosdeg((angle + 360) % 360);
sin = sindeg((angle + 360) % 360);
Line(LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist, cos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist, sin, 14)),
LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist, lastcos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist, lastsin, 14)),
color);
Line(LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, cos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, sin, 14)),
LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, lastcos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, lastsin, 14)),
color);
lastcos = cos;
lastsin = sin;
}
Line(LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist, lastcos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist, lastsin, 14)),
LCD_WIDTH_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, lastcos, 14)),
LCD_HEIGHT_PX / 2 + fp_convert(14, 0, fp_mul(dist + width, lastsin, 14)),
color);
if (startangle != endangle) {
lastcos = LCD_WIDTH_PX / 2 + fp_convert(14, 0,
fp_mul(dist + halfwidth,
cosdeg(((startangle + endangle) / 2) % 360),
14));
lastsin = LCD_HEIGHT_PX / 2 + fp_convert(14, 0,
fp_mul(dist + halfwidth,
sindeg(((startangle + endangle) / 2) % 360),
14));
Bucket(lastcos, lastsin, Get(lastcos, lastsin), color);
}
}
// Catherine
void Bucket(int x, int y, color_t targetcolor, color_t replacecolor) {
if (x < 0 || x >= LCD_WIDTH_PX || y < 0 || y >= LCD_HEIGHT_PX)
return;
if (Get(x, y) == targetcolor) {
Plot(x, y, replacecolor);
Bucket(x - 1, y, targetcolor, replacecolor);
Bucket(x, y - 1, targetcolor, replacecolor);
Bucket(x + 1, y, targetcolor, replacecolor);
Bucket(x, y + 1, targetcolor, replacecolor);
}
}
// Catherine
void ClearScreen() {
FillScreen(COLOR_WHITE);
}
// Catherine
void FillScreen(color_t color) {
int j;
short* VRAM = (short*)0xA8000000;
for(j=0;j<LCD_WIDTH_PX * LCD_HEIGHT_PX;j++)
VRAM[j] = color;
}
// Wikipedia/Bresenham
void FilledCircle(int centerx, int centery, int radius, color_t color) {
int f = 1 - radius;
int ddF_x = 1;
int ddF_y = -2 * radius;
int x = 0;
int y = radius;
Line(centerx, centery + radius, centerx, centery - radius, color);
Line(centerx + radius, centery, centerx - radius, centery, color);
while(x < y)
{
// ddF_x == 2 * x + 1;
// ddF_y == -2 * y;
// f == x*x + y*y - radius*radius + 2*x - y + 1;
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
Line(centerx + x, centery + y, centerx - x, centery + y, color);
Line(centerx + x, centery - y, centerx - x, centery - y, color);
Line(centerx + y, centery + x, centerx - y, centery + x, color);
Line(centerx + y, centery - x, centerx - y, centery - x, color);
}
}
// Wikipedia/Bresenham
void FilledArc(int centerx, int centery, int radius, int startangle, int endangle, color_t color) {
int f = 1 - radius;
int ddF_x = 1;
int ddF_y = -2 * radius;
int x = 0;
int y = radius;
int slopeleft = fp_div(fp_mul(fp_convert(0, 14, radius),
sindeg(startangle),
14),
fp_mul(fp_convert(0, 14, radius),
cosdeg(startangle),
14),
14);
int sloperight = fp_div(fp_mul(fp_convert(0, 14, radius),
sindeg(endangle),
14),
fp_mul(fp_convert(0, 14, radius),
cosdeg(endangle),
14),
14);
FilledCheckLine(centerx, centery + radius, centerx, centery - radius, slopeleft, sloperight, color);
FilledCheckLine(centerx + radius, centery, centerx - radius, centery, slopeleft, sloperight, color);
while(x < y)
{
// ddF_x == 2 * x + 1;
// ddF_y == -2 * y;
// f == x*x + y*y - radius*radius + 2*x - y + 1;
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
FilledCheckLine(centerx + x, centery + y, centerx - x, centery + y, slopeleft, sloperight, color);
FilledCheckLine(centerx + x, centery - y, centerx - x, centery - y, slopeleft, sloperight, color);
FilledCheckLine(centerx + y, centery + x, centerx - y, centery + x, slopeleft, sloperight, color);
FilledCheckLine(centerx + y, centery - x, centerx - y, centery - x, slopeleft, sloperight, color);
}
}
// Wikipedia
void FilledCheckLine(int x0, int y0, int x1, int y1, fp slopeleft, fp sloperight, color_t color) {
int slope = fp_div(fp_convert(0, 14, y0),
fp_convert(0, 14, x0),
14);
int slope2 = fp_div(fp_convert(0, 14, y1),
fp_convert(0, 14, x1),
14);
if (slope >= slopeleft && slope <= sloperight && slope2 >= slopeleft && slope2 <= sloperight)
Line(x0, y0, x1, y1, color);
}
// MiniSDK
int PRGM_GetKey() {
unsigned char buffer[12];
PRGM_GetKey_OS( buffer );
return ( buffer[1] & 0x0F ) * 10 + ( ( buffer[2] & 0xF0 ) >> 4 );
}
// Catherine
int tandeg(int angle) {
return sindeg(angle) / cosdeg(angle);
}
// KermMartian
static unsigned int lastrandom=0x12345678;
unsigned int rand(void) {
return srandom(0);
}
// KermMartian
unsigned int srandom(int seed){
if (seed) lastrandom=seed;
lastrandom = ( 0x41C64E6D*lastrandom ) + 0x3039;
return ( lastrandom >> 16 );
}
// Catherine
int GetX(int centerx, int angle, int dist) {
return centerx + fp_convert(14, 0, fp_mul(fp_convert(0, 14, dist),
cosdeg(angle),
14));
}
// Catherine
int GetY(int centery, int angle, int dist) {
return centery + fp_convert(14, 0, fp_mul(fp_convert(0, 14, dist),
sindeg(angle),
14));
}
// Catherine
void FilledCircleAngle(int centerx, int centery, int angle, int dist, int radius, color_t color) {
FilledCircle(GetX(centerx, angle, dist),
GetY(centery, angle, dist),
radius,
color);
}