Cleanup, background graphics etc.

This commit is contained in:
Heath Mitchell 2022-06-28 22:40:19 +01:00
parent 0b25f98e82
commit 94a1f49df4
21 changed files with 220 additions and 616 deletions

View File

@ -5,6 +5,8 @@
"generated_lut.cpp": "c",
"track.cpp": "c",
"kartsprites.h": "c",
"track.h": "c"
"track.h": "c",
"3d.h": "c",
"display.h": "c"
}
}

View File

@ -104,7 +104,7 @@ export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: all clean
#---------------------------------------------------------------------------------
all: $(BUILD)
all: $(BUILD) data-headers/*.h
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
# Don't know what I'm doing here
@ -112,7 +112,7 @@ generated_lut.cpp: /home/heath/ti-mario-kart-py/compress.py lookup_gen_config.ya
/usr/bin/env /bin/python3.10 /home/heath/ti-mario-kart-py/compress.py > generated_lut.cpp
# Still not really sure what I'm doing here
html/index.html: src/*.c
html/index.html: src/*.c data-headers/*.h
emcc -D FXCG_MOCK -D EMSCRIPTEN -Ifxcg-mock/include -g src/*.c ./fxcg-mock/include/fxcg/*.c -o html/index.html
browser: html/index.html

BIN
assets/img/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -5,13 +5,17 @@ main.o: /home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/main.c \
/home/heath/PrizmSDK-win-0.5.2/include/stddef.h \
/home/heath/PrizmSDK-win-0.5.2/include/fxcg/rtc.h \
/home/heath/PrizmSDK-win-0.5.2/include/fxcg/system.h \
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/./graphics.h \
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/../kartsprites.cpp
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/./3d.h \
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/./sprites.h \
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/../data-headers/images.h \
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/../data-headers/kartsprites.h
/home/heath/PrizmSDK-win-0.5.2/include/fxcg/display.h:
/home/heath/PrizmSDK-win-0.5.2/include/fxcg/keyboard.h:
/home/heath/PrizmSDK-win-0.5.2/include/fxcg/misc.h:
/home/heath/PrizmSDK-win-0.5.2/include/stddef.h:
/home/heath/PrizmSDK-win-0.5.2/include/fxcg/rtc.h:
/home/heath/PrizmSDK-win-0.5.2/include/fxcg/system.h:
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/./graphics.h:
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/../kartsprites.cpp:
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/./3d.h:
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/./sprites.h:
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/../data-headers/images.h:
/home/heath/PrizmSDK-win-0.5.2/projects/mario-kart/src/../data-headers/kartsprites.h:

Binary file not shown.

File diff suppressed because one or more lines are too long

1
data-headers/images.h Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,9 @@ int setKeyState(unsigned char key, unsigned char state) {
case 88: // x
keysPressed[78] = state;
break;
case 68: // d
keysPressed[31] = state;
break;
}
return 0;
}

46
scripts/img2header.py Normal file
View File

@ -0,0 +1,46 @@
# Reads images, converts the colour data to RGB565, and writes it to a header file.
# 0x4fe0 is used as the transparent colour.
from PIL import Image
import sys
import os
def toHeader(path):
img = Image.open(path)
img = img.convert("RGBA")
outData = []
# Add the height and width to the header.
outData.append(img.size[0])
outData.append(img.size[1])
# Iterate through the pixels.
for y in range(img.size[1]):
for x in range(img.size[0]):
# Get the colour data.
r, g, b, a = img.getpixel((x, y))
# print(r, g, b, a)
# Convert to RGB565.
rgb = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3);
if (rgb == 0x4fe0):
rgb = 0x4fe1
if a < 128:
rgb = 0x4fe0
outData.append(rgb)
out = f"const unsigned short img_{os.path.basename(path).split('.')[0]}[{len(outData)}] = {{"
for i in outData:
out += f"0x{i:04x}, "
out = out[:-2] + "};"
return out
all = ""
# Loop over the PNG files in ../assets/img/ (relative to the script)
os.chdir(os.path.dirname(os.path.realpath(__file__)))
for file in os.listdir("../assets/img/"):
if file.endswith(".png"):
result = toHeader("../assets/img/" + file)
print("Converted " + file)
all += result + "\n"
else:
print("Skipping " + file)
# Write the header to a file.
with open("../data-headers/images.h", "w") as f:
f.write(all)

68
src/3d.c Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,158 +0,0 @@
#include "./main.h"
#include "./tilemap.h"
#include "../data/generated_lut.h"
// const short lut[91] = {
// 0, 572, 1144, 1715, 2286, 2856, 3425, 3993, 4560, 5126, 5690, 6252, 6813, 7371, 7927, 8481, 9032, 9580, 10126, 10668, 11207, 11743, 12275, 12803, 13328, 13848, 14364, 14876, 15383, 15886, 16383, 16876, 17364, 17846, 18323, 18794, 19260, 19720, 20173, 20621, 21062, 21497, 21925, 22347, 22762, 23170, 23571, 23964, 24351, 24730, 25101, 25465, 25821, 26169, 26509, 26841, 27165, 27481, 27788, 28087, 28377, 28659, 28932, 29196, 29451, 29697, 29934, 30162, 30381, 30591, 30791, 30982, 31163, 31335, 31498, 31650, 31794, 31927, 32051, 32165, 32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762, 32767
// };
const short lut[angleWidth] = {
0, 269, 539, 808, 1078, 1347, 1616, 1885, 2154, 2423, 2692, 2960, 3228, 3497, 3764, 4032, 4299, 4566, 4833, 5099, 5365, 5631, 5896, 6161, 6426, 6690, 6953, 7216, 7479, 7741, 8003, 8264, 8524, 8784, 9043, 9302, 9560, 9818, 10074, 10330, 10586, 10840, 11094, 11348, 11600, 11852, 12102, 12352, 12602, 12850, 13097, 13344, 13590, 13834, 14078, 14321, 14563, 14804, 15044, 15283, 15520, 15757, 15993, 16228, 16461, 16694, 16925, 17155, 17384, 17612, 17839, 18064, 18288, 18511, 18733, 18953, 19173, 19391, 19607, 19822, 20036, 20249, 20460, 20670, 20878, 21085, 21291, 21495, 21697, 21899, 22098, 22297, 22493, 22689, 22882, 23074, 23265, 23454, 23641, 23827, 24011, 24194, 24375, 24554, 24732, 24907, 25082, 25254, 25425, 25594, 25762, 25927, 26091, 26253, 26414, 26572, 26729, 26884, 27037, 27188, 27338, 27486, 27631, 27775, 27917, 28057, 28196, 28332, 28466, 28599, 28730, 28858, 28985, 29109, 29232, 29353, 29472, 29589, 29703, 29816, 29927, 30036, 30142, 30247, 30350, 30450, 30549, 30645, 30739, 30832, 30922, 31010, 31096, 31180, 31262, 31341, 31419, 31494, 31568, 31639, 31708, 31775, 31839, 31902, 31963, 32021, 32077, 32131, 32183, 32232, 32280, 32325, 32368, 32409, 32447, 32484, 32518, 32550, 32580, 32608, 32633, 32656, 32677, 32696, 32713, 32727, 32739, 32749, 32757, 32763, 32766, 32767
};
short fpsin(short x) {
x = x % ((angleWidth - 1) * 4);
if (x < 0) {
x += ((angleWidth - 1) * 4);
}
short sign = 1;
if (x < ((angleWidth - 1) * 2)) {
sign = 1;
} else {
sign = -1;
}
x = x % ((angleWidth - 1) * 2);
if (x > (angleWidth - 1)) {
x = ((angleWidth - 1) * 2) - x;
}
return lut[x] * sign;
}
short fpcos(short x) {
return fpsin(x + angleWidth);
}
unsigned short getScreenPixel(unsigned short x, unsigned short y) {
// Use trigonometry to get the position of the track (mode 7 style)
/* short xPos = (short)(cos(index) * x - sin(index) * y);
short yPos = (short)(sin(index) * x + cos(index) * y);
// Get the colour of the pixel in the track
return samplePixel(xPos, yPos); */
// Used to indicate framerate
/* if (x == 0 && y == 0) {
return angle == 0;
} */
// x /= WIDTH_DIVIDER;
// Temporary for small screen sizes
/* if (y >= LUT_HEIGHT) return false;
if (x >= LUT_WIDTH) return false; */
// If both samples are 0 in the Python, the horizon colour is set but that doesn't seem to be needed
// return x % 2 == y % 2 ? 0 : 0xFFFF;
// unsigned short newY;
// __builtin_expect(x == (int)(LUT_WIDTH / 2), 0);
// if (x < (int)(LUT_WIDTH / 2)) {
// y = distortion_correction[x][y - horizon];
// } else if (x == (int)(LUT_WIDTH / 2)) {
// y = y - 1;
// } else {
// y = distortion_correction[(int)(LUT_WIDTH / 2) + ((int)(LUT_WIDTH / 2) - x)][y - horizon];
// }
int thingX;
int thingY;
if ((y - horizon) < sixteenBitHeight) {
thingX = angles16[0][y - horizon][0];
thingY = angles16[0][y - horizon][1];
} else {
thingX = angles8[0][y - horizon][0];
thingY = angles8[0][y - horizon][1];
}
// Rotate thingX and thingY by x
// short xPos = (short)(cos(x) * thingX - sin(x) * thingY);
// short yPos = (short)(sin(x) * thingX + cos(x) * thingY);
// Fixed point multiplication
x += angle;
short xPos = ((thingX * fpcos(x)) >> 16) + ((thingY * fpsin(x)) >> 16);
short yPos = ((thingY * fpcos(x)) >> 16) - ((thingX * fpsin(x)) >> 16);
return samplePixel(xPos, yPos);
// x = 0;
// index2 = 0;
// element = 0;
// unsigned short newY;
// // __builtin_expect(x == (int)(LUT_WIDTH / 2), 0);
// if (x < (int)(LUT_WIDTH / 2)) {
// newY = distortion_correction[x][y - horizon];
// } else if (x == (int)(LUT_WIDTH / 2)) {
// newY = y - 1;
// } else {
// newY = distortion_correction[(int)(LUT_WIDTH / 2) + ((int)(LUT_WIDTH / 2) - x)][y - horizon];
// }
// if ((y - horizon) < sixteenBitHeight) {
// // TODO: Remove again? Or remove the similar code in the loop
// /* short index = x + angle;
// index = mod(index, (angleWidth * 4));
// unsigned short element = mod(index, angleWidth); */
// if (index2 < angleWidth) {
// return samplePixel(
// angles16[element % 16][newY - horizon][0],
// angles16[element % 16][newY - horizon][1]);
// } else if (index2 < angleWidth * 2) {
// // Return 90 degree rotated position
// return samplePixel(
// angles16[element % 16][newY - horizon][1],
// -angles16[element % 16][newY - horizon][0]);
// } else if (index2 < angleWidth * 3) {
// // Return 180 degree rotated position
// return samplePixel(
// -angles16[element % 16][newY - horizon][0],
// -angles16[element % 16][newY - horizon][1]);
// } else /*if (index < angleWidth * 4)*/ {
// // Return 270 degree rotated position
// return samplePixel(
// -angles16[element % 16][newY - horizon][1],
// angles16[element % 16][newY - horizon][0]);
// }
// } else {
// // TODO: no duplicated code?
// // TODO: Remove again? Or remove the similar code in the loop
// /* short index = x + angle;
// index = mod(index, (angleWidth * 4));
// unsigned short element = mod(index, angleWidth); */
// if (index2 < angleWidth) {
// return samplePixel(
// angles8[element][newY - horizon - sixteenBitHeight][0],
// angles8[element][newY - horizon - sixteenBitHeight][1]);
// } else if (index2 < angleWidth * 2) {
// // Return 90 degree rotated position
// return samplePixel(
// angles8[element][newY - horizon - sixteenBitHeight][1],
// -angles8[element][newY - horizon - sixteenBitHeight][0]);
// } else if (index2 < angleWidth * 3) {
// // Return 180 degree rotated position
// return samplePixel(
// -angles8[element][newY - horizon - sixteenBitHeight][0],
// -angles8[element][newY - horizon - sixteenBitHeight][1]);
// } else /*if (index < angleWidth * 4)*/ {
// // Return 270 degree rotated position
// return samplePixel(
// -angles8[element][newY - horizon - sixteenBitHeight][1],
// angles8[element][newY - horizon - sixteenBitHeight][0]);
// }
// }
}

View File

@ -11,7 +11,9 @@
#endif
#endif
#include "./graphics.h"
#include "./3d.h"
#include "./sprites.h"
#include "../data-headers/images.h"
#define bool unsigned char
#define true 1
@ -45,7 +47,7 @@ float fmod(float a, float b) {
return r < 0 ? r + b : r;
}
#include "../data/kartsprites.h"
#include "../data-headers/kartsprites.h"
// https://stackoverflow.com/a/3689059/4012708
// TODO: use the symmetry of the sine graph to make this smaller
@ -74,45 +76,6 @@ void setPixel(int x, int y, color_t color) {
VRAM[y * LCD_WIDTH_PX + x] = color;
}
// From https://www.cemetech.net/forum/viewtopic.php?t=6114&postdays=0&postorder=asc&start=100
void CopySpriteMasked(const void* datar, int x, int y, int width, int height, int maskcolor) {
color_t* data = (color_t*)datar;
color_t* VRAM2 = (color_t*)VRAM;
VRAM2 += LCD_WIDTH_PX * y + x;
for (int j = y; j < y + height; j++) {
for (int i = x; i < x + width; i++) {
if (*(data) != maskcolor) {
*(VRAM2++) = *(data++);
} else {
VRAM2++;
data++;
}
}
VRAM2 += LCD_WIDTH_PX - width;
}
}
// Version of the function above that draws the sprite flipped horizontally
void CopySpriteMaskedFlipped(const void* datar, int x, int y, int width, int height, int maskcolor) {
color_t* data = (color_t*)datar;
color_t* VRAM2 = (color_t*)VRAM;
VRAM2 += LCD_WIDTH_PX * y + x;
for (int j = y; j < y + height; j++) {
// Start at the end of the line and work backwards
data += width - 1;
for (int i = x; i < x + width; i++) {
if (*(data) != maskcolor) {
*(VRAM2++) = *(data--);
} else {
VRAM2++;
data--;
}
}
data += width + 1;
VRAM2 += LCD_WIDTH_PX - width;
}
}
// https://prizm.cemetech.net/index.php?title=PRGM_GetKey
int PRGM_GetKey(void) {
unsigned char buffer[12];
@ -142,11 +105,12 @@ void cameraBehind(short x, short y, short objectAngle, short distance) {
}
void fillSky(unsigned short yMin, unsigned short yMax) {
for (unsigned short x = 0; x < LCD_WIDTH_PX; x++) {
/* for (unsigned short x = 0; x < LCD_WIDTH_PX; x++) {
for (unsigned short y = yMin; y < yMax; y++) {
setPixel(x, y, 0x867D);
}
}
} */
draw(img_bg, 0, 0);
Bdisp_PutDisp_DD();
}
@ -196,7 +160,7 @@ float kartVel = 0;
float kartAngle = 90;
#define kartSpeed 2
int labelType = 0;
int debugType = 0;
bool exeWasPressed = false;
// For framerate counter
@ -213,7 +177,7 @@ void main_loop() {
if (currentTime - lastTime >= 128) {
lastTime = currentTime;
if (labelType == 1) {
if (debugType == 1) {
int x = 8;
int y = 0;
@ -222,7 +186,7 @@ void main_loop() {
PrintMiniMini(&x, &y, buffer, 0, COLOR_BLACK, 0);
Bdisp_PutDisp_DD_stripe(24, 34);
} else if (labelType == 2) {
} else if (debugType == 2) {
int x = 8;
int y = 0;
@ -306,9 +270,9 @@ void main_loop() {
bool exePressed = keydown(31);
if (exePressed && !exeWasPressed) {
labelType++;
labelType = labelType % 3;
if (!labelType) {
debugType++;
debugType = debugType % 3;
if (!debugType) {
// Put the sky back
fillSky(24, 34);
Bdisp_PutDisp_DD_stripe(24, 34);

View File

@ -5,6 +5,10 @@ extern short yOffset;
extern short index2;
extern unsigned short element;
extern int debugType;
extern unsigned short* VRAM;
int mod(int a, int b);
float sin(int angle);
float cos(int angle);

52
src/sprites.c Normal file
View File

@ -0,0 +1,52 @@
#include <fxcg/display.h>
#include "./main.h"
// From https://www.cemetech.net/forum/viewtopic.php?t=6114&postdays=0&postorder=asc&start=100
void CopySpriteMasked(const void* datar, int x, int y, int width, int height, int maskcolor) {
color_t* data = (color_t*)datar;
color_t* VRAM2 = (color_t*)VRAM;
VRAM2 += LCD_WIDTH_PX * y + x;
for (int j = y; j < y + height; j++) {
for (int i = x; i < x + width; i++) {
if (*(data) != maskcolor) {
*(VRAM2++) = *(data++);
} else {
VRAM2++;
data++;
}
}
VRAM2 += LCD_WIDTH_PX - width;
}
}
// Version of the function above that draws the sprite flipped horizontally
void CopySpriteMaskedFlipped(const void* datar, int x, int y, int width, int height, int maskcolor) {
color_t* data = (color_t*)datar;
color_t* VRAM2 = (color_t*)VRAM;
VRAM2 += LCD_WIDTH_PX * y + x;
for (int j = y; j < y + height; j++) {
// Start at the end of the line and work backwards
data += width - 1;
for (int i = x; i < x + width; i++) {
if (*(data) != maskcolor) {
*(VRAM2++) = *(data--);
} else {
VRAM2++;
data--;
}
}
data += width + 1;
VRAM2 += LCD_WIDTH_PX - width;
}
}
void draw(const unsigned short* data, int x, int y) {
// The height and width of the sprite are the first two elements in the data array
int width = data[0];
int height = data[1];
// The data array starts at index 2
const unsigned short* data2 = data + 2;
// Now draw the sprite
CopySpriteMasked(data2, x, y, width, height, 0x4fe0);
}

3
src/sprites.h Normal file
View File

@ -0,0 +1,3 @@
void CopySpriteMasked(const void* datar, int x, int y, int width, int height, int maskcolor);
void CopySpriteMaskedFlipped(const void* datar, int x, int y, int width, int height, int maskcolor);
void draw(const unsigned short* data, int x, int y);

View File

@ -1,11 +1,11 @@
#include "./main.h"
#include "../data/track.h"
#include "../data-headers/track.h"
#define precision 8
unsigned char getTileType(short xPos, short yPos) {
__builtin_expect(xPos < 0 || xPos >= trackImageWidth || yPos < 0 || yPos >= trackImageHeight, 0);
// __builtin_expect(xPos < 0 || xPos >= trackImageWidth || yPos < 0 || yPos >= trackImageHeight, 0);
if (xPos < 0 || xPos >= trackImageWidth || yPos < 0 || yPos >= trackImageHeight) {
return 0; // Grass
} else {
@ -13,7 +13,7 @@ unsigned char getTileType(short xPos, short yPos) {
int xPixel = xPos >> 3;
int yPixel = yPos >> 3;
return trackData[((yPixel * (trackImageWidth / precision)) + xPixel) /*% 8192*/];//
return trackData[((yPixel * (trackImageWidth / precision)) + xPixel)];
}
}
@ -30,5 +30,5 @@ unsigned short samplePixel(short xPos, short yPos) {
int yPixelInTile = yPos & (precision - 1);
// Get the colour of the pixel in the tile
return tileData[getTileType(xPos, yPos) /*% 64*/][(yPixelInTile * precision) + xPixelInTile /*% 64*/];
return tileData[getTileType(xPos, yPos)][(yPixelInTile * precision) + xPixelInTile];
}

BIN
unselected.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB