Source:
#include <os.h>
#include "utils.h"
#include "raymath.h"
#include "sort.h"
#include "sprites.h"
#include "config.h"
asm(".string \"PRG\"\n");
int main(void)
{
*(volatile unsigned*) 0x900B0000 = 0x00000002;
*(volatile unsigned*) 0x900B000C = 4;
struct Sprite sprite[numSprites] =
{
{12, 12},
{13, 12},
{14, 12},
{15, 12},
};
int map[mapWidth][mapHeight]=
{
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,2,2,2,2,2,0,0,0,1,0},
{0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,2,0,0,0,2,0,0,0,1,0},
{0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,2,0,0,0,2,0,0,0,1,0},
{0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,2,2,2,2,2,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
float height[mapWidth][mapHeight]=
{
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,2,1,2,1,2,0,0,0,1,0},
{0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0},
{0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,2,1,2,1,2,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,1,0.8,0.6,0.4,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
char* scrbuf = (char*) malloc(SCREEN_BYTES_SIZE);
int tex[texW][texH];
int u, v;
for (u = 0; u < texW; u++) {
for (v = 0; v < texH; v++) {
tex[u][v] = 6;
}
}
for (u = 0; u < texW; u++) {
for (v = 0; v < texH; v++) {
if (u % 4 == 3 || (v % 8 == 2 && ((u / 4) % 2) == 0) ||
(v % 8 == 6 && ((u / 4) % 2) == 1)) {
tex[u][v] = 15;
}
}
}
int tex2[texW][texH];
for (u = 0; u < texW; u++) {
for (v = 0; v < texH; v++) {
tex2[u][v] = (u ^ v) / 2;
}
}
int texSpr[texW][texH];
for (u = 0; u < texW; u++) {
for (v = 0; v < texH; v++) {
int dsq = (u - 16) * (u - 16) + (v - 16) * (v - 16);
if (dsq > 196 && dsq < 256) {
texSpr[u][v] = 0;
} else if (dsq < 196 && dsq > 64) {
texSpr[u][v] = 8;
} else if (dsq < 64 && dsq > 49) {
texSpr[u][v] = 0;
} else {
texSpr[u][v] = -1;
}
}
}
float posX = 12, posY = 12;
float dirX = -1, dirY = 0;
float planeX = 0, planeY = 0.66;
int w = 320, h = 240;
int res = 1;
int x, y;
float zbuf[w][h];
int spriteOrder[numSprites];
float spriteDistance[numSprites];
int redraw;
float heye = 0.5;
while (!isKeyPressed(KEY_NSPIRE_ESC)) {
redraw = 0;
if (isKeyPressed(KEY_NSPIRE_LEFT)) {
float oldDirX = dirX;
dirX = dirX * cos1 - dirY * sin1;
dirY = oldDirX * sin1 + dirY * cos1;
float oldPlaneX = planeX;
planeX = planeX * cos1 - planeY * sin1;
planeY = oldPlaneX * sin1 + planeY * cos1;
redraw = 1;
}
if (isKeyPressed(KEY_NSPIRE_RIGHT)) {
float oldDirX = dirX;
dirX = dirX * cos1 + dirY * sin1;
dirY = -oldDirX * sin1 + dirY * cos1;
float oldPlaneX = planeX;
planeX = planeX * cos1 + planeY * sin1;
planeY = -oldPlaneX * sin1 + planeY * cos1;
redraw = 1;
}
if (isKeyPressed(KEY_NSPIRE_UP)) {
if (map[(int) (posX + stpsize * dirX)][(int) (posY)] == 0)
posX += stpsize * dirX;
if (map[(int) (posX)][(int) (posY + stpsize * dirY)] == 0)
posY += stpsize * dirY;
if (posX < 0) posX = 0;
if (posX > 24) posX = 24;
if (posY < 0) posY = 0;
if (posY > 24) posY = 24;
redraw = true;
}
if (isKeyPressed(KEY_NSPIRE_DOWN)) {
if (map[(int) (posX - stpsize * dirX)][(int) (posY)] == 0)
posX -= stpsize * dirX;
if (map[(int) (posX)][(int) (posY - stpsize * dirY)] == 0)
posY -= stpsize * dirY;
if (posX < 0) posX = 0;
if (posX > 24) posX = 24;
if (posY < 0) posY = 0;
if (posY > 24) posY = 24;
redraw = true;
}
if (isKeyPressed(KEY_NSPIRE_MINUS)) {
heye -= 0.1;
redraw = true;
}
if (isKeyPressed(KEY_NSPIRE_PLUS)) {
heye += 0.1;
redraw = true;
}
if (isKeyPressed(KEY_NSPIRE_DIVIDE)) {
w = (int) (w * 1.1);
if (w > 320) w = 320;
h = (int) (h * 1.1);
if (h > 240) h = 240;
redraw = true;
}
if (isKeyPressed(KEY_NSPIRE_MULTIPLY)) {
w = (int) (w * 0.9);
h = (int) (h * 0.9);
redraw = true;
}
if (isKeyPressed(KEY_NSPIRE_H)) {
res = 1;
redraw = true;
}
if (isKeyPressed(KEY_NSPIRE_L)) {
res = 2;
redraw = true;
}
if (redraw) {
memset(scrbuf, 0x00, SCREEN_BYTES_SIZE);
for(x = 0; x < w; x += res) {
float rayPosX = posX;
float rayPosY = posY;
int mapX = (int) rayPosX;
int mapY = (int) rayPosY;
float cameraX = 2 * x / (float) (w) - 1;
float raydx = dirX + planeX * cameraX;
float raydy = dirY + planeY * cameraX;
float sideDistX;
float sideDistY;
float raydx2 = raydx * raydx, raydy2 = raydy * raydy;
float deltaDistX = sqrt(1 + raydy2 / raydx2);
float deltaDistY = sqrt(1 + raydx2 / raydy2);
float perpWallDist;
int stepX;
int stepY;
int side;
float curH = 0;
int scrtop = h - 1;
if (raydx < 0) {
stepX = -1;
sideDistX = (rayPosX - mapX) * deltaDistX;
} else {
stepX = 1;
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
}
if (raydy < 0) {
stepY = -1;
sideDistY = (rayPosY - mapY) * deltaDistY;
} else {
stepY = 1;
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
}
int first = true;
while (mapX > 0 && mapX < mapWidth && mapY > 0 && mapY < mapHeight ) {
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
} else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
if (!map[mapX][mapY]) continue;
if (scrtop < 0) break;
float hwall = height[mapX][mapY];
if (side == 0) {
perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / raydx);
} else {
perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / raydy);
}
int nextX;
int nextY;
int nextSide;
if (sideDistX < sideDistY) {
nextX = mapX + stepX;
nextSide = 0;
} else {
nextY = mapY + stepY;
nextSide = 1;
}
float nextD;
if (nextSide == 0) {
nextD = fabs((nextX - rayPosX + (1 - stepX) / 2) / raydx);
} else {
nextD = fabs((nextY - rayPosY + (1 - stepY) / 2) / raydy);
}
int lo = (int) (h * (0.5 - heye / perpWallDist));
int lw = (int) (h * hwall / perpWallDist);
int nlo = (int) (h * (0.5 - heye / nextD));
int nlw = (int) (h * hwall / nextD);
int fstart = h - nlo - nlw;
int fend = h - lo - lw - 1;
int wstart = h - lo - lw;
int wend = h - lo - 1;
float wallX;
if (side == 1) {
wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / raydy) * raydx;
} else {
wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / raydx) * raydy;
}
wallX -= (int) wallX;
int texX = (int) (wallX * (float) (texW));
if(side == 0 && raydx > 0) texX = texW - texX - 1;
if(side == 1 && raydy < 0) texX = texW - texX - 1;
//floor loop
int y;
int sfstart = max(fstart, 0);
int sfend = min(fend, scrtop);
for (y = sfstart; y <= sfend; y++) {
setPixelBuf(scrbuf, x, y, 8);
//very large value since sprites always cover floors
zbuf[x][y] = 1000;
if (res == 2 && x < w - 1) {
setPixelBuf(scrbuf, x + 1, y, 8);
zbuf[x + 1][y] = 1000;
}
}
//wall loop
float texY = 0;
float texD = ((float)texH) / ((float)lw);
int swstart = max(wstart, 0);
if (swstart == 0) texY += (-wstart) * texD;
int swend = min(wend, scrtop);
for (y = swstart; y <= swend; y++) {
int color = tex[(int) texY][texX];
if (side == 1) color = color / 2;
setPixelBuf(scrbuf, x, y, color);
//set the zbuffer
zbuf[x][y] = perpWallDist;
if (res == 2 && x < w - 1) {
setPixelBuf(scrbuf, x + 1, y, color);
zbuf[x + 1][y] = perpWallDist;
}
texY += texD;
}
int oldtop = scrtop;
scrtop = fstart - 1;
if (scrtop > wstart - 1) scrtop = wstart;
if (scrtop > oldtop) scrtop = oldtop;
curH = hwall;
}
}
int i;
for(i = 0; i < numSprites; i++)
{
spriteOrder[i] = i;
spriteDistance[i] = ((posX - sprite[i].x) * (posX - sprite[i].x)
+ (posY - sprite[i].y) * (posY - sprite[i].y));
}
combSort(spriteOrder, spriteDistance, numSprites);
for(i = 0; i < numSprites; i++)
{
float spriteX = sprite[spriteOrder[i]].x - posX;
float spriteY = sprite[spriteOrder[i]].y - posY;
float invDet = 1.0 / (planeX * dirY - dirX * planeY);
float transformX = invDet * (dirY * spriteX - dirX * spriteY);
float transformY = invDet * (-planeY * spriteX + planeX * spriteY);
int spriteScreenX = (int) ((w / 2) * (1 + transformX / transformY));
#define uDiv 1
#define vDiv 1
#define vMove 0.0
int vMoveScreen = (int) (vMove / transformY);
int spriteHeight = abs((int) (h / transformY)) / vDiv;
int lo = (int) (h * (0.5 - heye / transformY));
int drawStartY = h - lo - spriteHeight;
int drawEndY = h - lo;
if (drawEndY > h - 1) drawEndY = h - 1;
int texOff = 0;
if (drawStartY < 0) {
texOff = -drawStartY;
drawStartY = 0;
}
int spriteWidth = abs((int) (h / (transformY))) / uDiv;
int drawStartX = -spriteWidth / 2 + spriteScreenX;
if(drawStartX < 0) drawStartX = 0;
int drawEndX = spriteWidth / 2 + spriteScreenX;
if(drawEndX >= w) drawEndX = w - 1;
int stripe;
float texD = ((float)texH) / ((float)spriteHeight);
texOff *= texD;
for(stripe = drawStartX; stripe < drawEndX; stripe += res)
{
int texX = (int) (256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * texW / spriteWidth) / 256;
float texY = texOff;
if(transformY > 0 && stripe > 0 && stripe < w) {
for(y = drawStartY; y < drawEndY; y++)
{
if (y >= 0 && y <= h - 1) {
if (transformY >= zbuf[stripe][y]) continue;
int color = texSpr[(int)texY][texX];
if (color != -1) {
setPixelBuf(scrbuf, stripe, y, color);
if (res == 2 && stripe < w - 1) {
setPixelBuf(scrbuf, stripe + 1, y, color);
}
}
}
texY += texD;
}
}
}
}
refresh(scrbuf);
}
}
*(volatile unsigned*) 0x900B0000 = 0x00141002;
*(volatile unsigned*) 0x900B000C = 4;
return 0;
}