(unsigned int)(distanceTable[x][y] + shiftX)
already, but I made it (unsigned int)((unsigned int)distanceTable[x][y] + shiftX)
and there's no change. Any other ideas?
for(x = 0; x < w; x++)
for(y = 0; y < h; y++){
color=texture[blah][blah];
buffer[x][y]=color;
}
texture[((unsigned int)(distanceTable[x][y] + shiftX) % texWidth)][((unsigned int)(angleTable[x][y] + shiftY) % texHeight)];
And that doesn't work ? Weird .__.
Try replacing the cast with abs(), just to be sure.
Oh you're using it. So I know why there are those vertical lines on the texture : you're trying to use 3-bytes bitmaps but my function only loads correctly 16-bits non-paletted bitmaps.
EDIT : error spotted. You must not cast to unsigned when calculating distance and angle, because pixels at the left of te center have negative angles.
The screenshot looks cool, but the CX one isn't working. It only shows four black squares at the top of the screen.
Edit: Oh, and you should probably clear the screen at the start of your program, the garbage it displays before starting is a bit ugly :P
Now I don't see it anymore, either.
If you have lcd_ingray() at the start of your program, it should work without any changes (unless you directly use the timers or other hardware).
Nice indeed. I am really curious about how this would look like with color support in game.
You normally don't need lcd_incolor() if you don't have a lcd_ingray() earlier in your program.
It still doesn't work, it only shows a black screen. Or do I need something else than texture.bmp.tns and Tunnel.tns in the same directory?
Could you post the code?
#include <os.h>
#include "math.h"
#include "nCOMMON.h"
#include "touchpad.c"
#define R5G6B5(r,g,b) (is_cx ? (((r) << 11) | ((g) << 5) | (b)) : ((int)( 0.229 * (r) + 0.587 * ((g) / 2) + 0.114 * (b)) / 2))
int nRC_enableRelativePaths(char **argv)
{
char buf[256], *p;
strcpy(buf, argv[0]);
p = strrchr(buf, '/');
if (!p)
return -1;
*p = '\0';
return NU_Set_Current_Dir(buf) ? -1 : 0;
}
uint16_t* nRC_loadBMP(char *path)
{
int size, offset, i, x, bpp, r, g, b;
uint16_t *returnValue, color;
FILE *temp = fopen(path, "rb");
if(!temp)
{
printf("Could not open %s\n", path);
return NULL;
}
// Check if the file's 2 first char are BM (indicates bitmap)
if(!(fgetc(temp) == 0x42 && fgetc(temp) == 0x4d))
{
printf("Image is not a bitmap\n");
fclose(temp);
return NULL;
}
// Check the bits-per-pixel format of the bitmap and converts color accordingly
fseek(temp, 0x1c, SEEK_SET);
bpp = fgetc(temp);
// Gets the 4-bytes numbers of bytes representing pixels, situated at 0x22
// Note that a same size can represent a different number of pixels, depending on bpp
fseek(temp, 0x22, SEEK_SET);
size = fgetc(temp) | (fgetc(temp) << 8) | (fgetc(temp) << 16) | (fgetc(temp) << 24);
// Gets the 4-bytes offset to the start of the pixel table, situated at 0x0a
fseek(temp, 0x0a, SEEK_SET);
offset = fgetc(temp) | (fgetc(temp) << 8) | (fgetc(temp) << 16) | (fgetc(temp) << 24);
fseek(temp, offset, SEEK_SET);
switch(bpp)
{ // Monochrome bitmaps have 1 bit per pixel : 0 is full black, 1 is full white
case 1:
returnValue = malloc(size * 8 * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
color = fgetc(temp);
for(x = 0; x < 8; x++)
{
returnValue[i * 8 + x] = (color & (1 << x)) ? (is_cx ? 65535 : 15) : 0;
}
}
break;
// 16-colours bitmaps have 4 bits per pixel, corresponding to a grayscale.
// Fortunately, the non-CX screen uses the same pixel format.
case 4:
returnValue = malloc(size * 2 * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
x = fgetc(temp);
color = x & 0x0f;
returnValue[i * 2] = is_cx ? ((color * 2) << 11) | ((color * 4) << 5) | (color * 2) : color;
color = (x >> 4) & 0x0f;
returnValue[i * 2 + 1] = is_cx ? ((color * 2) << 11) | ((color * 4) << 5) | (color * 2) : color;
}
break;
// 256-colours bitmaps have 8 bits per pixel, corresponding to an index in a palette.
// So we must add the 8-bit value to the start of the palette to get the 32-bits colour of the pixel.
case 8:
printf("Paletted bitmaps not supported\n");
fclose(temp);
return NULL;
break;
// 65536-colours bitmaps have 16 bits per pixel, corresponding to the R5G6B5 colour format.
// Fortunately, the CX screen uses the same pixel format.
case 16:
size >>= 1;
returnValue = malloc(size * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory\n");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
color = (uint16_t)(fgetc(temp) | (fgetc(temp) << 8));
returnValue[i] = (is_cx ? color : ((int)( 0.229 * (color >> 11) + 0.587 * ((color >> 6) & 0x1f) + 0.114 * (color & 0x1f)) >> 1));
}
break;
// 16777216-colours bitmaps have 24 bits per pixel, being 8 bits for red, 8 for green and 8 for blue.
// Unfortunately, no TI-Nspire screen supports this format for now, so we have to scale it down to R5G6B5
// even if this means that we loose some quality.
case 24:
size /= 3;
returnValue = malloc(size * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
b = fgetc(temp); g = fgetc(temp); r = fgetc(temp);
returnValue[i] = R5G6B5((int)(r / 8), (int)(g / 4), (int)(b / 8));
}
break;
// This format is the same than the previous one, except that it includes an alpha byte to determine the transparence
// degree of the pixel. I never planned to support transparency anyway.
case 32:
printf("32-bits bitmaps not supported\n");
fclose(temp);
return NULL;
break;
default:
printf("Format not supported\n");
fclose(temp);
return NULL;
break;
}
fclose(temp);
return returnValue;
}
#define texWidth 64
#define texHeight 64
#define screenWidth 240
#define screenHeight 240
int w = 240, h = 240, x, y;
uint16_t *texture;
int distanceTable[screenWidth][screenHeight];
int angleTable[screenWidth][screenHeight];
int buffer[screenWidth][screenHeight];
void sprite1(void *buffer, int *data, int x, int y, int width, int height){
int i, j;
for(i = 0; i < height; i++){
for(j = 0; j < width; j++){
if(x+j < 320 && x+j > 0 && y+i < 240 && y+i > 0){
setPixel(x+j, y+i, data[i*width+j], buffer);
}
}
}
}
uint16_t RGBColor(uint8_t r, uint8_t g, uint8_t b)
{
return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8);
}
uint16_t HSLtoRGB(int h, float s, float l) {
float r = 0.0f; float g = 0.0f; float b = 0.0f;
float c = (1-fabs(2*l-1))*s;
float tc = c*(1-abs(h%2-1));
switch(h/60) {
case 0: r = c; g = tc; break;
case 1: g = c; r = tc; break;
case 2: g = c; b = tc; break;
case 3: b = c; g = tc; break;
case 4: b = c; r = tc; break;
case 5: r = c; b = tc; break;
default: break;
}
float m = l-c/2;
r += m; g += m; b += m;
return (uint16_t)(((int)(r*32)<<11)|((int)(g*64)<<5)|((int)(b*32)));
}
int main(int argc, char *argv[]) {
char *screen;
screen = (char*)malloc(SCREEN_BYTES_SIZE * sizeof(char)); // just a buffer
if(!screen)
{
exit(0);
}
clearScreen(RGBColor(0,0,0), screen);
if(nRC_enableRelativePaths(argv))
{
printf("Couldn't change directory\n");
exit(0);
}
texture = nRC_loadBMP("texture.bmp.tns");
if(!texture){
free(screen);
exit(0);
}
initTP();
for(x = 0; x < w; x++)
for(y = 0; y < h; y++)
{
int angle, distance;
float ratio = 32.0;
distance = (int)(ratio * texHeight / sqrt((x - w / 2.0) * (x - w / 2.0) + (y - h / 2.0) * (y - h / 2.0))) % texHeight;
angle = (0.5 * texWidth * atan2(y - h / 2.0, x - w / 2.0) / M_PI);
distanceTable[x][y] = distance;
angleTable[x][y] = angle;
}
float animation = 0;
int shiftY = (unsigned int)(texHeight * 0.25);
//begin the loop
while(!isKeyPressed(KEY_NSPIRE_ESC))
{
animation = animation+0.04;
readTP();
int TZ = getTouchedZone4();
//calculate the shift values out of the animation value
int shiftX = (unsigned int)(texWidth * 1.0 * animation);
if(isKeyPressed(KEY_NSPIRE_RIGHT) || TZ==6)
shiftY++;
if(isKeyPressed(KEY_NSPIRE_LEFT) || TZ==4)
shiftY--;
for(x = 0; x < w; x++)
for(y = 0; y < h; y++)
{
//get the texel from the texture by using the tables, shifted with the animation values
int color = texture[((unsigned int)(angleTable[x][y] + shiftY) % texHeight)*texWidth+((unsigned int)(distanceTable[x][y] + shiftX) % texWidth)];
buffer[x][y] = color;
}
sprite1(screen, buffer[0], 40, 0, 240, 240);
display(screen);
clearScreen(RGBColor(255,255,255), screen);
}
free(screen);
endTP();
return 0;
}
Either one of the functions you didn't post is the problem, or something with your SDK or makefile is wrong. It works without a problem after I built it. I'm pretty sure it's a problem with your makefile or Ndless, since my (working) build is 13kb whereas your broken build is almost 700kb big.
Maybe all you have to do is replace "nspire-ld" by "nspire-ld-bflt" in the makefile. If it still doesn't work, could you post the makefile?
GCC = nspire-gcc
LD = nspire-ld
GCCFLAGS = -O2 -Wall -W -marm
LDFLAGS =
OBJCOPY := "$(shell which arm-elf-objcopy 2>/dev/null)"
ifeq (${OBJCOPY},"")
OBJCOPY := arm-none-eabi-objcopy
endif
EXE = Tunnel.tns
OBJS = Tunnel.o
DISTDIR = ../
vpath %.tns $(DISTDIR)
all: $(EXE)
%.o: %.c
$(GCC) $(GCCFLAGS) -c $<
$(EXE): $(OBJS)
$(LD) $(LDFLAGS) $^ -o $(@:.tns=.elf) -lRGB
mkdir -p $(DISTDIR)
$(OBJCOPY) -O binary $(@:.tns=.elf) $(DISTDIR)/$@
clean:
rm -f *.o *.elf
rm -f $(DISTDIR)/$(EXE)
c:\Users\Kids\Downloads\ndless-v3.1-beta-r825-sdk\ndless-v3.1-beta-r825-sdk\yagarto\bin\arm-none-eabi-objcopy.exe:Tunnel.elf: File format not recognized
make: *** [Tunnel.tns] Error 1
Glad to see you're still working on this and especially that you added colors! :) By the way you should really add stuff on each sides of the screen or move the tunnel on one side then add stuff on the other side, such as an HUD with score and credits.
I probably won't try this now, though, unless this runs on any Ndless version released within the last 6 months (installing Ndless takes 5 hours because my battery is always depleted due to not using my calc often, and Ndless requires to charge it completely before being sent)
There are two files attached to this post. One in CX, and one is non-CX(though the gray should work just fine on CX).Why are you giving separate builds ? You should checkout has_color (or similar others) (http://hackspire.unsads.com/wiki/index.php/Libndls#Hardware) in order to make only one build compatible with all models.
Compiled with ndless-v3.1-beta-r825-sdk. I think that's a newer version. WinkIf your using specific functionalities, you should always use assert_ndless_rev(rev) (http://hackspire.unsads.com/wiki/index.php/Libndls#Platform) according to the revision the feature you're using appeared in.
(installing Ndless takes 5 hours because my battery is always depleted due to not using my calc often, and Ndless requires to charge it completely before being sent)Completely charged ? No.
*BUMP*This one finally works (the one a post before this one didn't, though) :)
It definitely hasn't been 24 hours, but I felt I should update.
There are two files attached to this post. One in CX, and one is non-CX(though the gray should work just fine on CX). I'd like for tests and screenshots please(I hope it works). Also, if you test it, can you tell me how fast the CX one goes(if it works)?
Yeah, now it works. It's much slower than before, though.
Have you made a conditional branch/jump or something smarter ?
Remember that using an if inside a setPixel is most likely time cretical. You may want to use faster designs like function pointers.
if(has_colors)
setPixel(x,y,color,buffer);
*BUMP*Without the last source updated source code ? Does anything has changed since the last one ?
Could one of you help make this faster? What exactly should I do instead of my if statement?
*BUMP*Without the last source updated source code ? Does anything has changed since the last one ?
Could one of you help make this faster? What exactly should I do instead of my if statement?
#include <os.h>
#include "utils.c"
#include "graphics3.c"
#include "math.h"
#include "nCOMMON.h"
#include "touchpad.c"
#define R5G6B5(r,g,b) (is_cx ? (((r) << 11) | ((g) << 5) | (b)) : ((int)( 0.229 * (r) + 0.587 * ((g) / 2) + 0.114 * (b)) / 2))
int nRC_enableRelativePaths(char **argv)
{
char buf[256], *p;
strcpy(buf, argv[0]);
p = strrchr(buf, '/');
if (!p)
return -1;
*p = '\0';
return NU_Set_Current_Dir(buf) ? -1 : 0;
}
uint16_t* nRC_loadBMP(char *path)
{
int size, offset, i, x, bpp, r, g, b;
uint16_t *returnValue, color;
FILE *temp = fopen(path, "rb");
if(!temp)
{
printf("Could not open %s\n", path);
return NULL;
}
// Check if the file's 2 first char are BM (indicates bitmap)
if(!(fgetc(temp) == 0x42 && fgetc(temp) == 0x4d))
{
printf("Image is not a bitmap\n");
fclose(temp);
return NULL;
}
// Check the bits-per-pixel format of the bitmap and converts color accordingly
fseek(temp, 0x1c, SEEK_SET);
bpp = fgetc(temp);
// Gets the 4-bytes numbers of bytes representing pixels, situated at 0x22
// Note that a same size can represent a different number of pixels, depending on bpp
fseek(temp, 0x22, SEEK_SET);
size = fgetc(temp) | (fgetc(temp) << 8) | (fgetc(temp) << 16) | (fgetc(temp) << 24);
// Gets the 4-bytes offset to the start of the pixel table, situated at 0x0a
fseek(temp, 0x0a, SEEK_SET);
offset = fgetc(temp) | (fgetc(temp) << 8) | (fgetc(temp) << 16) | (fgetc(temp) << 24);
fseek(temp, offset, SEEK_SET);
switch(bpp)
{ // Monochrome bitmaps have 1 bit per pixel : 0 is full black, 1 is full white
case 1:
returnValue = malloc(size * 8 * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
color = fgetc(temp);
for(x = 0; x < 8; x++)
{
returnValue[i * 8 + x] = (color & (1 << x)) ? (is_cx ? 65535 : 15) : 0;
}
}
break;
// 16-colours bitmaps have 4 bits per pixel, corresponding to a grayscale.
// Fortunately, the non-CX screen uses the same pixel format.
case 4:
returnValue = malloc(size * 2 * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
x = fgetc(temp);
color = x & 0x0f;
returnValue[i * 2] = is_cx ? ((color * 2) << 11) | ((color * 4) << 5) | (color * 2) : color;
color = (x >> 4) & 0x0f;
returnValue[i * 2 + 1] = is_cx ? ((color * 2) << 11) | ((color * 4) << 5) | (color * 2) : color;
}
break;
// 256-colours bitmaps have 8 bits per pixel, corresponding to an index in a palette.
// So we must add the 8-bit value to the start of the palette to get the 32-bits colour of the pixel.
case 8:
printf("Paletted bitmaps not supported\n");
fclose(temp);
return NULL;
break;
// 65536-colours bitmaps have 16 bits per pixel, corresponding to the R5G6B5 colour format.
// Fortunately, the CX screen uses the same pixel format.
case 16:
size >>= 1;
returnValue = malloc(size * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory\n");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
color = (uint16_t)(fgetc(temp) | (fgetc(temp) << 8));
returnValue[i] = (is_cx ? color : ((int)( 0.229 * (color >> 11) + 0.587 * ((color >> 6) & 0x1f) + 0.114 * (color & 0x1f)) >> 1));
}
break;
// 16777216-colours bitmaps have 24 bits per pixel, being 8 bits for red, 8 for green and 8 for blue.
// Unfortunately, no TI-Nspire screen supports this format for now, so we have to scale it down to R5G6B5
// even if this means that we loose some quality.
case 24:
size /= 3;
returnValue = malloc(size * sizeof(int));
if(!returnValue)
{
printf("Could not allocate memory");
fclose(temp);
return NULL;
}
for(i = size - 1; i >= 0; i--)
{
b = fgetc(temp); g = fgetc(temp); r = fgetc(temp);
returnValue[i] = R5G6B5((int)(r / 8), (int)(g / 4), (int)(b / 8));
}
break;
// This format is the same than the previous one, except that it includes an alpha byte to determine the transparence
// degree of the pixel. I never planned to support transparency anyway.
case 32:
printf("32-bits bitmaps not supported\n");
fclose(temp);
return NULL;
break;
default:
printf("Format not supported\n");
fclose(temp);
return NULL;
break;
}
fclose(temp);
return returnValue;
}
#define texWidth 64
#define texHeight 64
#define screenWidth 240
#define screenHeight 240
int w = 240, h = 240, x, y;
uint16_t *texture;
int distanceTable[screenWidth][screenHeight];
int angleTable[screenWidth][screenHeight];
int buffer[screenWidth][screenHeight];
void sprite1(void *buffer, int *data, int x, int y, int width, int height){
int i, j;
for(i = 0; i < height; i++){
for(j = 0; j < width; j++){
if(x+j < 320 && x+j > 0 && y+i < 240 && y+i > 0){
if(has_colors)
setPixel(x+j, y+i, data[i*width+j], buffer);
else
setPixelBuf(buffer, x+j, y+i, data[i*width+j]);
}
}
}
}
uint16_t RGBColor(uint8_t r, uint8_t g, uint8_t b)
{
return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8);
}
uint16_t HSLtoRGB(int h, float s, float l) {
float r = 0.0f; float g = 0.0f; float b = 0.0f;
float c = (1-fabs(2*l-1))*s;
float tc = c*(1-abs(h%2-1));
switch(h/60) {
case 0: r = c; g = tc; break;
case 1: g = c; r = tc; break;
case 2: g = c; b = tc; break;
case 3: b = c; g = tc; break;
case 4: b = c; r = tc; break;
case 5: r = c; b = tc; break;
default: break;
}
float m = l-c/2;
r += m; g += m; b += m;
return (uint16_t)(((int)(r*32)<<11)|((int)(g*64)<<5)|((int)(b*32)));
}
int main(int argc, char *argv[]) {
char *screen;
screen = (char*)malloc(SCREEN_BYTES_SIZE * sizeof(char)); // just a buffer
if(!screen)
{
exit(0);
}
if(nRC_enableRelativePaths(argv))
{
printf("Couldn't change directory\n");
exit(0);
}
texture = nRC_loadBMP("texture.bmp.tns");
if(!texture){
free(screen);
exit(0);
}
initTP();
if(!has_colors)
lcd_ingray();
for(x = 0; x < w; x++)
for(y = 0; y < h; y++)
{
int angle, distance;
float ratio = 32.0;
distance = (int)(ratio * texHeight / sqrt((x - w / 2.0) * (x - w / 2.0) + (y - h / 2.0) * (y - h / 2.0))) % texHeight;
angle = (0.5 * texWidth * atan2(y - h / 2.0, x - w / 2.0) / M_PI);
distanceTable[x][y] = distance;
angleTable[x][y] = angle;
}
float animation = 0;
int shiftY = (unsigned int)(texHeight * 0.25);
if(has_colors)
clearScreen(RGBColor(255,255,255), screen);
else
clearBuf(screen);
//begin the loop
while(!isKeyPressed(KEY_NSPIRE_ESC))
{
animation = animation+0.04;
readTP();
int TZ = getTouchedZone4();
//calculate the shift values out of the animation value
int shiftX = (unsigned int)(texWidth * 1.0 * animation);
if(isKeyPressed(KEY_NSPIRE_RIGHT) || TZ==6)
shiftY++;
if(isKeyPressed(KEY_NSPIRE_LEFT) || TZ==4)
shiftY--;
for(x = 0; x < w; x++)
for(y = 0; y < h; y++)
{
//get the texel from the texture by using the tables, shifted with the animation values
int color = texture[((unsigned int)(angleTable[x][y] + shiftY) % texHeight)*texWidth+((unsigned int)(distanceTable[x][y] + shiftX) % texWidth)];
buffer[x][y] = color;
}
sprite1(screen, buffer[0], 40, 0, 240, 240);
switch(has_colors){
case 1:
display(screen);
//clearScreen(RGBColor(255,255,255), screen);
break;
case 0:
refresh(screen);
clearBuf(screen);
break;
default:
refresh(screen);
clearBuf(screen);
break;
}
}
free(screen);
endTP();
return 0;
}
#include "utils.c"
#include "graphics3.c"
#include "math.h"
#include "nCOMMON.h"
#include "touchpad.c"
void sprite1(void *buffer, int *data, int x, int y, int width, int height){
int i, j;
for(i = 0; i < height; i++){
for(j = 0; j < width; j++){
if(x+j < 320 && x+j > 0 && y+i < 240 && y+i > 0){
if(has_colors)
setPixel(x+j, y+i, data[i*width+j], buffer);
else
setPixelBuf(buffer, x+j, y+i, data[i*width+j]);
}
}
}
}
void sprite1(void *buffer, int *data, int x, int y, int width, int height){
int i, j;
switch (has_colors)
{
case 1:
for(i = 0; i < height; i++){
for(j = 0; j < width; j++){
if(x+j < 320 && x+j > 0 && y+i < 240 && y+i > 0)
setPixel(x+j, y+i, data[i*width+j], buffer);
}
}
break;
default:
for(i = 0; i < height; i++){
for(j = 0; j < width; j++){
if(x+j < 320 && x+j > 0 && y+i < 240 && y+i > 0)
setPixelBuf(buffer, x+j, y+i, data[i*width+j]);
}
}
}
}
void sprite1(void *buffer, int *data, int x, int y, int width, int height){
if(x > SCREEN_WIDTH || y > SCREEN_HEIGHT || x+w < 0 || y+h < 0)
return;
if(x < 0)
{
w += x;
x = 0;
}
if(y < 0)
{
h += y;
y = 0;
}
if(x + w > SCREEN_WIDTH)
w = SCREEN_WIDTH - x;
if(y + h > SCREEN_HEIGHT)
h = SCREEN_HEIGHT - y;
if(w <= 0 || h <= 0)
return;
int i, j;
switch (has_colors)
{
case 1:
for(i = 0; i < height; i++){
for(j = 0; j < width; j++)
setPixel(x+j, y+i, data[i*width+j], buffer);
}
break;
default:
for(i = 0; i < height; i++){
for(j = 0; j < width; j++)
setPixelBuf(buffer, x+j, y+i, data[i*width+j]);
}
}
}
Does anyone have an idea for how to add another texture(so there's two)?