689 lines
21 KiB
C++
689 lines
21 KiB
C++
#include "graphics.h"
|
|
#include "test.h"
|
|
|
|
|
|
uint8_t getPixelGiga(uint8_t x, uint8_t y)
|
|
{
|
|
x = x % GIGA_WIDTH;
|
|
y = y % GIGA_HEIGHT;
|
|
uint16_t address = GIGA_VRAM + x + (y <<8);
|
|
return Cpu::getRAM(address);
|
|
}
|
|
|
|
void drawPixelGiga(uint8_t x, uint8_t y, uint8_t colour)
|
|
{
|
|
x = x % GIGA_WIDTH;
|
|
y = y % GIGA_HEIGHT;
|
|
uint16_t address = GIGA_VRAM + x + (y <<8);
|
|
Cpu::setRAM(address, colour);
|
|
}
|
|
|
|
|
|
namespace TestTetris
|
|
{
|
|
#define TETRIS_XPOS 60
|
|
#define TETRIS_YPOS 20
|
|
#define TETRIS_XEXT 10
|
|
#define TETRIS_YEXT 20
|
|
#define NUM_TETROMINOES 7
|
|
#define NUM_ROTATIONS 4
|
|
#define TETROMINOE_SIZE 4
|
|
#define MAX_LINES 4
|
|
#define MAX_LEVEL 8
|
|
|
|
|
|
enum BoardState {Clear=0, Blocked, GameOver};
|
|
|
|
struct Tetromino
|
|
{
|
|
uint8_t _colour;
|
|
uint8_t _pattern[NUM_ROTATIONS][4 + TETROMINOE_SIZE*2];
|
|
};
|
|
|
|
Tetromino I =
|
|
{
|
|
0x3C,
|
|
4, 1, 0, 1, 0, 1, 1, 1, 2, 1, 3, 1,
|
|
1, 4, 2, 0, 2, 0, 2, 1, 2, 2, 2, 3,
|
|
4, 1, 0, 2, 0, 2, 1, 2, 2, 2, 3, 2,
|
|
1, 4, 1, 0, 1, 0, 1, 1, 1, 2, 1, 3,
|
|
};
|
|
Tetromino J =
|
|
{
|
|
0x30,
|
|
3, 2, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1,
|
|
2, 3, 1, 0, 1, 0, 2, 0, 1, 1, 1, 2,
|
|
3, 2, 0, 1, 0, 1, 1, 1, 2, 1, 2, 2,
|
|
2, 3, 0, 0, 1, 0, 1, 1, 0, 2, 1, 2
|
|
};
|
|
Tetromino L =
|
|
{
|
|
0x0B,
|
|
3, 2, 0, 0, 2, 0, 0, 1, 1, 1, 2, 1,
|
|
2, 3, 1, 0, 1, 0, 1, 1, 1, 2, 2, 2,
|
|
3, 2, 0, 1, 0, 1, 1, 1, 2, 1, 0, 2,
|
|
2, 3, 0, 0, 0, 0, 1, 0, 1, 1, 1, 2
|
|
};
|
|
Tetromino O =
|
|
{
|
|
0x0F,
|
|
2, 2, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1,
|
|
2, 2, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1,
|
|
2, 2, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1,
|
|
2, 2, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1
|
|
};
|
|
Tetromino S =
|
|
{
|
|
0x0C,
|
|
3, 2, 0, 0, 1, 0, 2, 0, 0, 1, 1, 1,
|
|
2, 3, 1, 0, 1, 0, 1, 1, 2, 1, 2, 2,
|
|
3, 2, 0, 1, 1, 1, 2, 1, 0, 2, 1, 2,
|
|
2, 3, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2
|
|
};
|
|
Tetromino T =
|
|
{
|
|
0x33,
|
|
3, 2, 0, 0, 1, 0, 0, 1, 1, 1, 2, 1,
|
|
2, 3, 1, 0, 1, 0, 1, 1, 2, 1, 1, 2,
|
|
3, 2, 0, 1, 0, 1, 1, 1, 2, 1, 1, 2,
|
|
2, 3, 0, 0, 1, 0, 0, 1, 1, 1, 1, 2
|
|
};
|
|
Tetromino Z =
|
|
{
|
|
0x03,
|
|
3, 2, 0, 0, 0, 0, 1, 0, 1, 1, 2, 1,
|
|
2, 3, 1, 0, 2, 0, 1, 1, 2, 1, 1, 2,
|
|
3, 2, 0, 1, 0, 1, 1, 1, 1, 2, 2, 2,
|
|
2, 3, 0, 0, 1, 0, 0, 1, 1, 1, 0, 2
|
|
};
|
|
Tetromino tetrominoes[NUM_TETROMINOES] = {I, J, L, O, S, T, Z};
|
|
int tetrisScore = 0, tetrisLevel = 0, scoreDelta = 0;
|
|
int frameTickLevel = 60;
|
|
int frameTick = frameTickLevel;
|
|
int frameCount = 0;
|
|
int x=TETRIS_XEXT/2, y = -1;
|
|
int index = 0, rotation = 0;
|
|
int w, h, u, v;
|
|
int ox, oy, ov;
|
|
int oindex, orotation;
|
|
|
|
uint8_t getTetrisPixel(int tx, int ty)
|
|
{
|
|
tx *= 4;
|
|
ty *= 4;
|
|
return getPixelGiga(uint8_t(TETRIS_XPOS + tx), uint8_t(TETRIS_YPOS + ty));
|
|
}
|
|
|
|
void setTetrisPixel(int tx, int ty, uint8_t colour)
|
|
{
|
|
tx *= 4;
|
|
ty *= 4;
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 0), uint8_t(TETRIS_YPOS + ty + 0), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 0), uint8_t(TETRIS_YPOS + ty + 1), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 0), uint8_t(TETRIS_YPOS + ty + 2), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 0), uint8_t(TETRIS_YPOS + ty + 3), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 1), uint8_t(TETRIS_YPOS + ty + 0), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 1), uint8_t(TETRIS_YPOS + ty + 1), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 1), uint8_t(TETRIS_YPOS + ty + 2), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 1), uint8_t(TETRIS_YPOS + ty + 3), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 2), uint8_t(TETRIS_YPOS + ty + 0), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 2), uint8_t(TETRIS_YPOS + ty + 1), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 2), uint8_t(TETRIS_YPOS + ty + 2), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 2), uint8_t(TETRIS_YPOS + ty + 3), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 3), uint8_t(TETRIS_YPOS + ty + 0), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 3), uint8_t(TETRIS_YPOS + ty + 1), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 3), uint8_t(TETRIS_YPOS + ty + 2), colour);
|
|
drawPixelGiga(uint8_t(TETRIS_XPOS + tx + 3), uint8_t(TETRIS_YPOS + ty + 3), colour);
|
|
}
|
|
|
|
void drawTetromino(int idx, int rot, int tx, int ty, uint8_t colour)
|
|
{
|
|
for(int i=0; i<TETROMINOE_SIZE; i++)
|
|
{
|
|
int xx = tx + tetrominoes[idx]._pattern[rot][4 + i*2];
|
|
int yy = ty + tetrominoes[idx]._pattern[rot][5 + i*2];
|
|
if(xx < 0 || xx >= TETRIS_XEXT) continue;
|
|
if(yy < 0 || yy >= TETRIS_YEXT) continue;
|
|
|
|
setTetrisPixel(uint8_t(xx), uint8_t(yy), colour);
|
|
}
|
|
}
|
|
|
|
BoardState checkTetromino(int idx, int rot, int tx, int ty)
|
|
{
|
|
for(int i=0; i<TETROMINOE_SIZE; i++)
|
|
{
|
|
int xx = tx + tetrominoes[idx]._pattern[rot][4 + i*2];
|
|
int yy = ty + tetrominoes[idx]._pattern[rot][5 + i*2];
|
|
if(xx < 0 || xx >= TETRIS_XEXT) continue;
|
|
if(yy < 0 || yy >= TETRIS_YEXT) continue;
|
|
|
|
if(getTetrisPixel(uint8_t(xx), uint8_t(yy)))
|
|
{
|
|
if(y == 0) return GameOver;
|
|
return Blocked;
|
|
}
|
|
}
|
|
|
|
return Clear;
|
|
}
|
|
|
|
void updateScore(int lines)
|
|
{
|
|
static int scoring[MAX_LINES] = {10, 25, 50, 100};
|
|
static int levelling[MAX_LEVEL] = {500, 500, 1000, 2000, 4000, 8000, 16000, 32000};
|
|
|
|
scoreDelta += scoring[(lines - 1) & (MAX_LINES - 1)] * (tetrisLevel + 1);
|
|
|
|
// Level up
|
|
if(scoreDelta >= levelling[tetrisLevel & (MAX_LEVEL - 1)])
|
|
{
|
|
tetrisScore += scoreDelta;
|
|
tetrisLevel++;
|
|
frameTickLevel = std::max(60 - 5*tetrisLevel, 15);
|
|
frameTick = frameTickLevel;
|
|
scoreDelta = 0;
|
|
}
|
|
|
|
fprintf(stderr, "Tetris: score : %06d level : %d frameTickLevel : %d lines : %d\n", tetrisScore + scoreDelta, tetrisLevel, frameTickLevel, lines);
|
|
}
|
|
|
|
int checkLines(void)
|
|
{
|
|
int lines = 0;
|
|
|
|
for(int ii=0; ii<MAX_LINES; ii++)
|
|
{
|
|
for(int ll=TETRIS_YEXT-1; ll>=0; ll--)
|
|
{
|
|
bool line = true;
|
|
for(int kk=0; kk<TETRIS_XEXT; kk++) line &= getTetrisPixel(kk, ll) > 0;
|
|
if(line)
|
|
{
|
|
lines++;
|
|
|
|
for(int nn=ll; nn>0; nn--)
|
|
{
|
|
for(int mm=0; mm<TETRIS_XEXT; mm++) setTetrisPixel(mm, nn, getTetrisPixel(mm, nn-1));
|
|
}
|
|
for(int kk=0; kk<TETRIS_XEXT; kk++) setTetrisPixel(kk, 0, 0x00);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(lines) updateScore(lines);
|
|
|
|
return lines;
|
|
}
|
|
|
|
void saveTetrominoState(void)
|
|
{
|
|
ox = x;
|
|
oy = y;
|
|
ov = tetrominoes[index]._pattern[rotation][3];
|
|
oindex = index;
|
|
orotation = rotation;
|
|
}
|
|
|
|
void updateTetromino(void)
|
|
{
|
|
w = tetrominoes[index]._pattern[rotation][0];
|
|
h = tetrominoes[index]._pattern[rotation][1];
|
|
u = tetrominoes[index]._pattern[rotation][2];
|
|
v = tetrominoes[index]._pattern[rotation][3];
|
|
}
|
|
|
|
int spawnTetromino(void)
|
|
{
|
|
index = rand() % NUM_TETROMINOES;
|
|
rotation = rand() & (NUM_ROTATIONS-1);
|
|
x = rand() % (TETRIS_XEXT - (w - 1)) - u;
|
|
|
|
updateTetromino();
|
|
saveTetrominoState();
|
|
return checkLines();
|
|
}
|
|
|
|
void shakeScreen(int lines)
|
|
{
|
|
static int frameCnt = 0;
|
|
static int strength = 0;
|
|
|
|
if(lines)
|
|
{
|
|
frameCnt = 1;
|
|
strength = lines;
|
|
}
|
|
|
|
if(frameCnt)
|
|
{
|
|
int screenShake = rand() % 4;
|
|
switch(screenShake)
|
|
{
|
|
case 0: Cpu::setRAM(0x0101, uint8_t(strength)); break;
|
|
case 1: Cpu::setRAM(0x0101, uint8_t(0 - strength)); break;
|
|
case 2: for(int i=0x0100; i<0x01EE; i+=2) Cpu::setRAM(uint16_t(i), uint8_t(0x08 + (i-0x0100)/2 + strength)); break;
|
|
case 3: for(int i=0x0100; i<0x01EE; i+=2) Cpu::setRAM(uint16_t(i), uint8_t(0x08 + (i-0x0100)/2 + uint8_t(0 - strength))); break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
if(++frameCnt >= 20) //strength * 10)
|
|
{
|
|
frameCnt = 0;
|
|
Cpu::setRAM(0x0101, 0x00);
|
|
for(int i=0x0100; i<0x01EF; i+=2) Cpu::setRAM(uint16_t(i), uint8_t(0x08 + (i-0x0101)/2));
|
|
}
|
|
}
|
|
}
|
|
|
|
void tetris(void)
|
|
{
|
|
static bool firstTime = true;
|
|
if(firstTime && Cpu::getClock() > 10000000)
|
|
{
|
|
firstTime = false;
|
|
for(int l=0; l<TETRIS_YEXT; l++)
|
|
for(int k=0; k<TETRIS_XEXT; k++) setTetrisPixel(k, l, 0x00);
|
|
}
|
|
|
|
bool refresh = false;
|
|
|
|
saveTetrominoState();
|
|
|
|
SDL_Event event;
|
|
SDL_PollEvent(&event);
|
|
|
|
switch(event.type)
|
|
{
|
|
case SDL_KEYDOWN:
|
|
{
|
|
if(y == -1) break;
|
|
|
|
switch(event.key.keysym.sym)
|
|
{
|
|
case SDLK_LEFT: x--; refresh = true; break;
|
|
case SDLK_RIGHT: x++; refresh = true; break;
|
|
case SDLK_DOWN: frameTick = 2; break;
|
|
|
|
case SDLK_UP:
|
|
{
|
|
static int rotation_old = rotation;
|
|
rotation = (rotation + 1) & (NUM_ROTATIONS-1);
|
|
updateTetromino();
|
|
if(y > TETRIS_YEXT - h - v)
|
|
{
|
|
rotation = rotation_old;
|
|
updateTetromino();
|
|
}
|
|
else
|
|
{
|
|
refresh = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SDLK_ESCAPE:
|
|
{
|
|
Cpu::shutdown();
|
|
exit(0);
|
|
}
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SDL_KEYUP:
|
|
{
|
|
switch(event.key.keysym.sym)
|
|
{
|
|
case SDLK_DOWN: frameTick = frameTickLevel; break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
int lines = 0;
|
|
if(refresh || ++frameCount >= frameTick)
|
|
{
|
|
// Erase old tetromino
|
|
drawTetromino(oindex, orotation, ox, oy-ov, 0x00);
|
|
|
|
updateTetromino();
|
|
|
|
if(x < 0 - u) x = 0 - u;
|
|
if(x > TETRIS_XEXT - w - u) x = TETRIS_XEXT - w - u;
|
|
|
|
// Update tetromino
|
|
if(frameCount >= frameTick)
|
|
{
|
|
frameCount = 0;
|
|
|
|
// Gravity
|
|
if(++y > TETRIS_YEXT - h)
|
|
{
|
|
// Hit ground
|
|
drawTetromino(index, rotation, x, y-v-1, tetrominoes[index]._colour);
|
|
y = -1;
|
|
lines = spawnTetromino();
|
|
}
|
|
}
|
|
|
|
BoardState boardState = checkTetromino(index, rotation, x, y-v);
|
|
switch(boardState)
|
|
{
|
|
case Clear: drawTetromino(index, rotation, x, y-v, tetrominoes[index]._colour); break;
|
|
|
|
case Blocked:
|
|
{
|
|
if(!refresh)
|
|
{
|
|
drawTetromino(index, rotation, x, y-v-1, tetrominoes[index]._colour);
|
|
y = -1;
|
|
lines = spawnTetromino();
|
|
}
|
|
else
|
|
{
|
|
drawTetromino(oindex, orotation, ox, oy-ov, tetrominoes[oindex]._colour);
|
|
x = ox, y = oy, v = ov, rotation = orotation, index = oindex;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GameOver:
|
|
{
|
|
// Game over
|
|
scoreDelta = 0;
|
|
tetrisScore = 0;
|
|
tetrisLevel = 0;
|
|
frameTickLevel = 60;
|
|
frameTick = frameTickLevel;
|
|
for(int l=0; l<TETRIS_YEXT; l++)
|
|
for(int k=0; k<TETRIS_XEXT; k++) setTetrisPixel(k, l, 0x00);
|
|
fprintf(stderr, "Tetris GAME OVER...\n");
|
|
}
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
shakeScreen(lines);
|
|
}
|
|
}
|
|
|
|
|
|
namespace TestLife
|
|
{
|
|
void lifePixel(uint8_t x, uint8_t y, uint32_t colour)
|
|
{
|
|
uint32_t screen = x + y*SCREEN_WIDTH;
|
|
Graphics::getPixels()[screen] = colour*0xFFFFFFFF;
|
|
}
|
|
|
|
#define LIFE_WIDTH 2000
|
|
#define LIFE_HEIGHT 2000
|
|
void life(bool initialise)
|
|
{
|
|
static uint8_t buffers[2][LIFE_HEIGHT][LIFE_WIDTH];
|
|
static uint8_t lut[9] = {0, 0, 0, 1, 0, 0, 0, 0, 0};
|
|
static int index = 0;
|
|
static bool initialised = false;
|
|
|
|
if(initialise)
|
|
{
|
|
initialised = true;
|
|
|
|
for(int j=0; j<LIFE_HEIGHT; j++)
|
|
for(int i=0; i<LIFE_WIDTH; i++)
|
|
lifePixel(uint8_t(i), uint8_t(j), 0);
|
|
|
|
for(int k=0; k<2; k++)
|
|
for(int j=0; j<LIFE_HEIGHT; j++)
|
|
for(int i=0; i<LIFE_WIDTH; i++)
|
|
buffers[k][j][i] = 0;
|
|
|
|
// Gliders
|
|
for(int i=0; i<8; i+=4)
|
|
{
|
|
buffers[0][100][100+i] = 1; buffers[0][101][100+i] = 1; buffers[0][102][100+i] = 1; buffers[0][102][99+i] = 1; buffers[0][101][98+i] = 1;
|
|
lifePixel(uint8_t(100+i), 100, 1); lifePixel(uint8_t(100+i), 101, 1); lifePixel(uint8_t(100+i), 102, 1); lifePixel(uint8_t(99+i), 102, 1); lifePixel(uint8_t(98+i), 101, 1);
|
|
}
|
|
|
|
index = 0;
|
|
}
|
|
|
|
if(initialised)
|
|
{
|
|
for(int j=1; j<LIFE_HEIGHT-1; j++)
|
|
{
|
|
for(int i=1; i<LIFE_WIDTH-1; i++)
|
|
{
|
|
lut[2] = buffers[index][j][i];
|
|
int count = buffers[index][j-1][i-1] + buffers[index][j-1][i] + buffers[index][j-1][i+1] + buffers[index][j][i+1] + buffers[index][j+1][i+1] + buffers[index][j+1][i] + buffers[index][j+1][i-1] + buffers[index][j][i-1];
|
|
buffers[index ^ 1][j][i] = lut[count];
|
|
if(i < 256 && j < 256) lifePixel(uint8_t(i), uint8_t(j), lut[count]);
|
|
}
|
|
}
|
|
|
|
index ^= 1;
|
|
}
|
|
}
|
|
|
|
void life1(bool initialise)
|
|
{
|
|
static uint8_t buffers[2][LIFE_HEIGHT][LIFE_WIDTH];
|
|
static uint8_t lut[9] = {0, 0, 0, 1, 0, 0, 0, 0, 0};
|
|
static bool initialised = false;
|
|
|
|
if(initialise)
|
|
{
|
|
initialised = true;
|
|
|
|
for(int j=0; j<LIFE_HEIGHT; j++)
|
|
for(int i=0; i<LIFE_WIDTH; i++)
|
|
lifePixel(uint8_t(i), uint8_t(j), 0);
|
|
|
|
for(int k=0; k<2; k++)
|
|
for(int j=0; j<LIFE_HEIGHT; j++)
|
|
for(int i=0; i<LIFE_WIDTH; i++)
|
|
buffers[k][j][i] = 0;
|
|
|
|
// Gliders
|
|
for(int i=0; i<8; i+=4)
|
|
{
|
|
buffers[0][100][100+i] = 1; buffers[0][101][100+i] = 1; buffers[0][102][100+i] = 1; buffers[0][102][99+i] = 1; buffers[0][101][98+i] = 1;
|
|
lifePixel(uint8_t(100+i), 100, 1); lifePixel(uint8_t(100+i), 101, 1); lifePixel(uint8_t(100+i), 102, 1); lifePixel(uint8_t(99+i), 102, 1); lifePixel(uint8_t(98+i), 101, 1);
|
|
}
|
|
}
|
|
|
|
if(initialised)
|
|
{
|
|
for(int j=1; j<LIFE_HEIGHT-1; j++)
|
|
{
|
|
for(int i=1; i<LIFE_WIDTH-1; i++)
|
|
{
|
|
// Increment neighbour counts
|
|
if(buffers[0][j][i] == 1)
|
|
{
|
|
buffers[1][j-1][i-1]++; buffers[1][j-1][i]++; buffers[1][j-1][i+1]++; buffers[1][j][i+1]++; buffers[1][j+1][i+1]++; buffers[1][j+1][i]++; buffers[1][j+1][i-1]++; buffers[1][j][i-1]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(int j=1; j<LIFE_HEIGHT-1; j++)
|
|
{
|
|
for(int i=1; i<LIFE_WIDTH-1; i++)
|
|
{
|
|
lut[2] = buffers[0][j][i];
|
|
int cell = lut[buffers[1][j][i]];
|
|
buffers[1][j][i] = 0;
|
|
buffers[0][j][i] = uint8_t(cell);
|
|
if(i < 256 && j < 256) lifePixel(uint8_t(i), uint8_t(j), cell);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
namespace TestMandelbrot
|
|
{
|
|
void mandelbrot(void)
|
|
{
|
|
const uint8_t colours[16] = {0x01, 0x02, 0x03, 0x07, 0x0b, 0x0f, 0x0e, 0x0d, 0x0c, 0x3c, 0x38, 0x34, 0x30, 0x20, 0x10, 0x00};
|
|
const int16_t xmin = -100;
|
|
const int16_t xmax = 60;
|
|
const int16_t ymin = -60;
|
|
const int16_t ymax = 60;
|
|
const int16_t dx = (xmax-xmin)/160;
|
|
const int16_t dy = (ymax-ymin)/120;
|
|
|
|
int16_t cy = ymin;
|
|
for(int16_t py=8; py<128; py++)
|
|
{
|
|
int16_t cx = xmin;
|
|
for(int16_t px=0; px<160; px++)
|
|
{
|
|
int16_t x=0, y=x, x2=y, y2=x2;
|
|
|
|
int colour = 0;
|
|
for(int16_t c=0; c<=15; c++)
|
|
{
|
|
colour = c;
|
|
|
|
x2 = int16_t(x*x) >> 5;
|
|
y2 = int16_t(y*y) >> 5;
|
|
if(int16_t(x2+y2) > 128) break;
|
|
|
|
y = (int16_t(x*y) >> 4) + cy;
|
|
x = int16_t(x2 - y2 + cx);
|
|
}
|
|
|
|
Cpu::setRAM((py <<8) + px, colours[colour]);
|
|
cx = cx + dx;
|
|
}
|
|
|
|
cy = cy + dy;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
namespace TestDrawLine
|
|
{
|
|
void drawLineGiga(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t colour)
|
|
{
|
|
int16_t dx = int16_t(abs(x2 - x1));
|
|
int16_t sx = (x1 < x2) ? 1 : -1;
|
|
int16_t dy = int16_t(abs(y2 - y1));
|
|
int16_t sy = (y1 < y2) ? 1 : -1;
|
|
int16_t err = ((dx > dy) ? dx : -dy) >>1;
|
|
int16_t e2;
|
|
|
|
for(;;)
|
|
{
|
|
drawPixelGiga(uint8_t(x1), uint8_t(y1), colour);
|
|
if(x1 == x2 && y1 == y2) break;
|
|
e2 = err;
|
|
if(e2 >-dx)
|
|
{
|
|
err -= dy;
|
|
x1 += sx;
|
|
}
|
|
if(e2 < dy)
|
|
{
|
|
err += dx;
|
|
y1 += sy;
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawLineGiga1(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t colour)
|
|
{
|
|
int16_t sx = x2 - x1;
|
|
int16_t sy = y2 - y1;
|
|
int h = sy;
|
|
int16_t dx1 = 1, dx2 = 1, dy1 = 1, dy2 = 0;
|
|
|
|
if(sx & 0x8000)
|
|
{
|
|
dx1 = -1;
|
|
dx2 = -1;
|
|
sx = 0 - sx;
|
|
}
|
|
|
|
if(sy & 0x8000)
|
|
{
|
|
dy1 = -1;
|
|
sy = 0 - sy;
|
|
if(sx < sy) dy2 = -1;
|
|
}
|
|
|
|
if(sx < sy)
|
|
{
|
|
dx2 = 0;
|
|
std::swap(sx, sy);
|
|
if(h > 0) dy2 = 1;
|
|
}
|
|
|
|
int16_t numerator = sx >> 1;
|
|
int16_t xy1 = x1 | (y1<<8);
|
|
int16_t xy2 = x2 | (y2<<8);
|
|
int16_t dxy1 = dx1 + (dy1<<8);
|
|
int16_t dxy2 = dx2 + (dy2<<8);
|
|
|
|
for(uint16_t i=0; i<=sx/2; i++)
|
|
{
|
|
drawPixelGiga(uint8_t(xy1), uint8_t(xy1>>8), colour);
|
|
drawPixelGiga(uint8_t(xy2), uint8_t(xy2>>8), colour);
|
|
numerator += sy;
|
|
if(numerator > sx)
|
|
{
|
|
numerator -= sx;
|
|
xy1 += dxy1;
|
|
xy2 -= dxy1;
|
|
}
|
|
else
|
|
{
|
|
xy1 += dxy2;
|
|
xy2 -= dxy2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
namespace TestMath
|
|
{
|
|
void fastMath(void)
|
|
{
|
|
for(int i=0; i<32768; i++)
|
|
{
|
|
#if 1
|
|
// Mod5
|
|
int16_t j = int16_t(i); //int16_t(rand() % 32767);
|
|
int16_t a = (j >> 8) + (j & 0xFF); /* sum base 2**8 digits */
|
|
a = (a >> 4) + (a & 0xF); /* sum base 2**4 digits */
|
|
if (a > 14) a = a - 15;
|
|
if (a > 9) a = a - 10;
|
|
if (a > 4) a = a - 5;
|
|
//(a == j%5) ? fprintf(stderr, "%d : %d %d\n", j, a, j%5) : fprintf(stderr, "%d : %d %d ***\n", j, a, j%5);
|
|
if(a != j%5) fprintf(stderr, "%d : %d %d ***\n", j, a, j%5);
|
|
#else
|
|
// Div5
|
|
int16_t j = int16_t(i); //int16_t(rand() % 255);
|
|
int16_t a = j - j/64; // error term
|
|
a = (a<<5) + (a<<4) + (a<<2); // * 52
|
|
a = (a>>8); // / 256
|
|
(a == j/5) ? fprintf(stderr, "%d : %d %d\n", j, a, j/5) : fprintf(stderr, "%d : %d %d ***\n", j, a, j/5);
|
|
#endif
|
|
}
|
|
}
|
|
}
|