Author Topic: [Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine  (Read 4883 times)

0 Members and 1 Guest are viewing this topic.

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
[Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine
« on: March 25, 2013, 01:01:56 pm »
Hey guys,

I'm currently adapting F-Zero to use with the hoffa and t_k' mode7 engine, but I can't make it display a simple rotoscaled map. I didn't ask them because there's been a while they didn't even log in <_<

So, I adapted a little bit the engine to make it work with non-square maps, but it keep not working.

Original m7.c :
Code: [Select]
#include <os.h>
#include <SDL.h>

#include "m7.h"

void m7BuildLut(m7Vec_t lut[M7_SCREEN_HEIGHT]) {
    int screenRow;
    for (screenRow = 0; screenRow < M7_SCREEN_HEIGHT; ++screenRow) {
        float cameraV = (((float)screenRow / (float)M7_SCREEN_HEIGHT) * 2.0F - 1.0F);

        float rayX = M7_VIEW_PLANE_H;
        float rayY = 1.0F;
        float rayZ = M7_VIEW_PLANE_V * cameraV;

        float intersectY = (M7_VIEW_HEIGHT / rayZ) * rayY;
        float intersectX = (M7_VIEW_HEIGHT / rayZ) * rayX;

        lut[screenRow].x = M7_FLOAT_TO_FIX(intersectX);
        lut[screenRow].y = M7_FLOAT_TO_FIX(intersectY);
    }
}

void m7LoadTex(Uint8 tex[M7_NUM_TEX][M7_TEX_SIZE][M7_TEX_SIZE], ...) {
    va_list ap;
    int i, j, k;

    va_start(ap, tex);
    for (i = 0; i < M7_NUM_TEX; ++i) {
        SDL_Surface* surf = va_arg(ap, SDL_Surface*);
        for (j = 0; j < M7_TEX_SIZE; j++)
            for (k = 0; k < M7_TEX_SIZE; k++)
                tex[i][j][k] = nSDL_GetPixel(surf, k, j);
    }
    va_end(ap);
}

void m7Render(SDL_Surface *screen,
              m7Vec_t lut[M7_SCREEN_HEIGHT],
              Uint8 tilemap[M7_MAP_SIZE][M7_MAP_SIZE],
              Uint8 tex[M7_NUM_TEX][M7_TEX_SIZE][M7_TEX_SIZE],
              m7Vec_t pos,
              Sint32 heading) {
    int screenX, screenY;
    for (screenY = (M7_SCREEN_HEIGHT / 2) + 1; screenY < M7_SCREEN_HEIGHT; ++screenY) {
        m7Vec_t map = lut[screenY];
        m7Vec_t mapXStep = {-map.x / (M7_SCREEN_WIDTH / 2), 0};
       
        Sint32 sinHeading = m7SinLut(heading);
        Sint32 cosHeading = m7CosLut(heading);
       
        m7RotateVec(&map, sinHeading, cosHeading);
        m7RotateVec(&mapXStep, sinHeading, cosHeading);
       
        map.x += pos.x;
        map.y += pos.y;
       
        for (screenX = 0; screenX < M7_SCREEN_WIDTH; ++screenX) {
            Uint8 color = 0;

            if (map.x >= 0 && map.x < M7_INT_TO_FIX(M7_MAP_SIZE)
             && map.y >= 0 && map.y < M7_INT_TO_FIX(M7_MAP_SIZE))
                color = tex[(int)tilemap[map.y >> M7_TEX_SIZE]
                                        [map.x >> M7_TEX_SIZE]]
                           [(map.y & 0xFFFF) >> 12]
                           [(map.x & 0xFFFF) >> 12];

            map.x += mapXStep.x;
            map.y += mapXStep.y;

            M7_SET_PIXEL8(screenX, screenY, color);
        }
    }
    SDL_UpdateRect(screen, 0, M7_SCREEN_HEIGHT / 2, M7_SCREEN_WIDTH, M7_SCREEN_HEIGHT / 2);
}
(m7.h only contains some very basic defines)

Modified m7.c :
Code: [Select]
#include <os.h>
#include <SDL.h>

#include "m7.h"

void m7BuildLut(m7Vec_t lut[M7_SCREEN_HEIGHT]) {
    int screenRow;
    for (screenRow = 0; screenRow < M7_SCREEN_HEIGHT; ++screenRow) {
        float cameraV = (((float)screenRow / (float)M7_SCREEN_HEIGHT) * 2.0F - 1.0F);

        float rayX = M7_VIEW_PLANE_H;
        float rayY = 1.0F;
        float rayZ = M7_VIEW_PLANE_V * cameraV;

        float intersectY = (M7_VIEW_HEIGHT / rayZ) * rayY;
        float intersectX = (M7_VIEW_HEIGHT / rayZ) * rayX;

        lut[screenRow].x = M7_FLOAT_TO_FIX(intersectX);
        lut[screenRow].y = M7_FLOAT_TO_FIX(intersectY);
    }
}

void m7LoadTex(Uint8 tex[M7_NUM_TEX][M7_TEX_SIZE][M7_TEX_SIZE], ...) {
    va_list ap;
    int i, j, k;

    va_start(ap, tex);
    for (i = 0; i < M7_NUM_TEX; ++i) {
        SDL_Surface* surf = va_arg(ap, SDL_Surface*);
        for (j = 0; j < M7_TEX_SIZE; j++)
            for (k = 0; k < M7_TEX_SIZE; k++)
                tex[i][j][k] = nSDL_GetPixel(surf, k, j);
    }
    va_end(ap);
}

void m7LoadTexArray(Uint8 tex[M7_NUM_TEX][M7_TEX_SIZE][M7_TEX_SIZE], SDL_Surface *src)
{
int i,j,k;
for(i = 0; i < M7_NUM_TEX; i++)
for(k = 0; k < M7_TEX_SIZE; k++)
for(j = 0; j < M7_TEX_SIZE; j++)
tex[i][k][j] = nSDL_GetPixel(src, j, i * M7_TEX_SIZE + k);
}

void m7Render(SDL_Surface *screen,
              m7Vec_t lut[M7_SCREEN_HEIGHT],
              Uint8 **tilemap,
              Uint8 tex[M7_NUM_TEX][M7_TEX_SIZE][M7_TEX_SIZE],
              m7Vec_t pos,
              Sint32 heading,
  Uint8 mapWidth,
  Uint8 mapHeight) {
    int screenX, screenY;
    for (screenY = (M7_SCREEN_HEIGHT / 2) + 1; screenY < M7_SCREEN_HEIGHT; ++screenY) {
        m7Vec_t map = lut[screenY];
        m7Vec_t mapXStep = {-map.x / (M7_SCREEN_WIDTH / 2), 0};
       
        Sint32 sinHeading = m7SinLut(heading);
        Sint32 cosHeading = m7CosLut(heading);
       
        m7RotateVec(&map, sinHeading, cosHeading);
        m7RotateVec(&mapXStep, sinHeading, cosHeading);
       
        map.x += pos.x;
        map.y += pos.y;
       
        for (screenX = 0; screenX < M7_SCREEN_WIDTH; ++screenX) {
            Uint8 color = 0;

            if (map.x >= 0 && map.x < M7_INT_TO_FIX(mapWidth)
             && map.y >= 0 && map.y < M7_INT_TO_FIX(mapHeight))
                color = tex[(int)tilemap[map.y >> M7_TEX_SIZE]
                                        [map.x >> M7_TEX_SIZE]]
                           [(map.y & 0xFFFF) >> 12]
                           [(map.x & 0xFFFF) >> 12];

            map.x += mapXStep.x;
            map.y += mapXStep.y;

            M7_SET_PIXEL8(screenX, screenY, color);
        }
    }
    SDL_UpdateRect(screen, 0, M7_SCREEN_HEIGHT / 2, M7_SCREEN_WIDTH, M7_SCREEN_HEIGHT / 2);
}

demo.c (from the engine's zip, works) :
Code: [Select]
#include <os.h>
#include <SDL/SDL.h>

#include "m7.h"
#include "gfx.h"

SDL_Surface *screen;

SDL_Surface *loadTex(unsigned short *data) {
    SDL_Surface *tex, *tmp;
    tmp = nSDL_LoadImage(data);
    tex = SDL_DisplayFormat(tmp);
    SDL_FreeSurface(tmp);
    return tex;
}

int main(void) {
    m7Vec_t lut[M7_SCREEN_HEIGHT];
    Uint8 tilemap[M7_MAP_SIZE][M7_MAP_SIZE];
    Uint8 tex[M7_NUM_TEX][M7_TEX_SIZE][M7_TEX_SIZE];
    m7Vec_t pos = {M7_INT_TO_FIX(2), M7_INT_TO_FIX(4)};
    Sint32 heading = 0;

    SDL_Surface *texMushroom, *texFB, *texCartman, *texYoshi;
    nSDL_Font *font;
    const SDL_VideoInfo *info;
    Uint32 curTime = 0;
    Uint32 oldTime = 0;
    int fps = 0;
    int num_frames = 0;
    int done = 0;
    int i, j;

    SDL_Init(SDL_INIT_VIDEO);
    screen = SDL_SetVideoMode(M7_SCREEN_WIDTH, M7_SCREEN_HEIGHT, M7_BPP, SDL_SWSURFACE);
    font = nSDL_LoadFont(NSDL_FONT_TINYTYPE, 255, 255, 255);
    texMushroom = loadTex(ntiMushroom);
    texFB = loadTex(ntiFB);
    texCartman = loadTex(ntiCartman);
    texYoshi = loadTex(ntiYoshi);
    SDL_FillRect(screen, NULL, 0);
    info = SDL_GetVideoInfo();
    nSDL_DrawString(screen, font, 0, 0, "M7 engine test\nnSDL %s\n%dx%d\n%d-bit/%d-bit",
                    NSDL_VERSION, info->current_w, info->current_h, info->vfmt->BitsPerPixel, is_cx ? 16 : 4);
    SDL_Flip(screen);

    srand(42);
    for (i = 0; i < M7_MAP_SIZE; ++i)
        for (j = 0; j < M7_MAP_SIZE; ++j)
            tilemap[i][j] = rand() % 4;

    m7BuildLut(lut);
    m7LoadTex(tex, texMushroom, texFB, texCartman, texYoshi);

    while(!done) {
        m7Vec_t moveDist = {M7_INT_TO_FIX(0), M7_FLOAT_TO_FIX(0.25)};
        SDL_Rect fpsRect = {M7_SCREEN_WIDTH - 40, 0, 40, 8};

        m7RotateVec(&moveDist, m7SinLut(heading), m7CosLut(heading));

        if (isKeyPressed(KEY_NSPIRE_8)) m7AddVec(&pos, &moveDist);
        if (isKeyPressed(KEY_NSPIRE_2)) m7SubVec(&pos, &moveDist);
        if (isKeyPressed(KEY_NSPIRE_6)) m7AddVec(&pos, m7RotateVec(&moveDist, M7_INT_TO_FIX(1), 0));
        if (isKeyPressed(KEY_NSPIRE_4)) m7SubVec(&pos, m7RotateVec(&moveDist, M7_INT_TO_FIX(1), 0));
        if (isKeyPressed(KEY_NSPIRE_9)) heading -= 0x400;
        if (isKeyPressed(KEY_NSPIRE_7)) heading += 0x400;
        if (isKeyPressed(KEY_NSPIRE_ESC)) done = 1;

        m7Render(screen, lut, tilemap, tex, pos, heading);

        SDL_FillRect(screen, &fpsRect, 0);
        nSDL_DrawString(screen, font, fpsRect.x, fpsRect.y, "%d FPS", fps);
        SDL_UpdateRect(screen, fpsRect.x, fpsRect.y, fpsRect.w, fpsRect.h);
        curTime = SDL_GetTicks();
        if(curTime - oldTime <= 993) /* Clock set to 993 Hz by nSDL */
            ++num_frames;
        else {
            fps = num_frames;
            num_frames = 0;
            oldTime = curTime;
        }
    }

    SDL_FreeSurface(texYoshi);
    SDL_FreeSurface(texCartman);
    SDL_FreeSurface(texFB);
    SDL_FreeSurface(texMushroom);
    nSDL_FreeFont(font);
    SDL_Quit();

    return 0;
}

main.c (mine, doesn't work) :
Code: [Select]
#include <os.h>
#include <SDL.h>
#include "m7.h"

SDL_Surface *loadTex(unsigned short *data)
{
SDL_Surface *tex, *temp;
temp = nSDL_LoadImage(data);
tex = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);
return tex;
}

int main(int argc, char *argv[])
{
// Mode7-relative variables
m7Vec_t lut[M7_SCREEN_HEIGHT];
#include "muteCityTilemap.h"
#include "muteCityTileset.h"
#include "blueFalcon.h"
Uint8 finalTex[M7_NUM_TEX][M7_TEX_SIZE][M7_TEX_SIZE];
m7Vec_t pos = {M7_INT_TO_FIX(1), M7_INT_TO_FIX(1)};
Sint32 heading = 0;

SDL_Surface *screen, *shipSurface, *tiles;
SDL_Rect shipRect, shipSrcRect;

shipRect.x = 136;
shipRect.y = 190;

shipSrcRect.x = (shipSrcRect.y = 0);
shipSrcRect.w = 48;
shipSrcRect.h = 31;

SDL_Init(SDL_INIT_VIDEO);

int speed = 0, rotationSpeed = 0;

screen = SDL_SetVideoMode(M7_SCREEN_WIDTH, M7_SCREEN_HEIGHT, M7_BPP, SDL_SWSURFACE);

shipSurface = nSDL_LoadImage(blueFalconSprite);
SDL_SetColorKey(shipSurface, SDL_SRCCOLORKEY, SDL_MapRGB(shipSurface->format, 0xff, 0, 0xff));

tiles = loadTex(muteCityTileset);

m7BuildLut(lut);
m7LoadTexArray(finalTex, tiles);

while(1)
{
m7Vec_t moveDist = {M7_INT_TO_FIX(0), M7_FLOAT_TO_FIX(0.25)};

m7RotateVec(&moveDist, m7SinLut(heading), m7CosLut(heading));

if(isKeyPressed(KEY_NSPIRE_ESC)) break;
if(isKeyPressed(KEY_NSPIRE_DOWN)) m7SubVec(&pos, &moveDist);
if(isKeyPressed(KEY_NSPIRE_LEFT))
{
heading -= 0x400;
shipSrcRect.y = 62;
}
if(isKeyPressed(KEY_NSPIRE_RIGHT))
{
heading += 0x400;
shipSrcRect.y = 31;
}
if(!isKeyPressed(KEY_NSPIRE_LEFT) && !isKeyPressed(KEY_NSPIRE_RIGHT)) shipSrcRect.y = 0;
if(isKeyPressed(KEY_NSPIRE_UP)) m7AddVec(&pos, &moveDist);

m7Render(screen, lut, muteCityTilemap, finalTex, pos, heading, 792, 366);

}

SDL_FreeSurface(tiles);
SDL_FreeSurface(shipSurface);
SDL_Quit();

return 0;
}

The *.h I use are always image datas.

You can download the engine here : http://ourl.ca/18123/337001

If you can help me, I'd be glad :(
« Last Edit: March 25, 2013, 01:03:52 pm by Matrefeytontias »

Offline Juju

  • Incredibly sexy mare
  • Coder Of Tomorrow
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 5730
  • Rating: +500/-19
  • Weird programmer
    • View Profile
    • juju2143's shed
Re: [Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine
« Reply #1 on: March 25, 2013, 01:23:22 pm »
What's the error exactly?

Remember the day the walrus started to fly...

I finally cleared my sig after 4 years you're happy now?
THEGAME
This signature is ridiculously large you've been warned.

The cute mare that used to be in my avatar is Yuki Kagayaki, you can follow her on Facebook and Tumblr.

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: [Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine
« Reply #2 on: March 25, 2013, 01:24:08 pm »
I really don't know. It compiles fine, but when I launch it on whatever Nspire, it crashes immediately.

Offline tr1p1ea

  • LV7 Elite (Next: 700)
  • *******
  • Posts: 647
  • Rating: +110/-0
    • View Profile
Re: [Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine
« Reply #3 on: March 25, 2013, 01:28:04 pm »
Did you successfully launch the unmodified version at any stage?
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."


Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: [Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine
« Reply #4 on: March 25, 2013, 01:28:56 pm »
Yep I did, it works perfectly.

Offline hoffa

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 322
  • Rating: +131/-13
    • View Profile
Re: [Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine
« Reply #5 on: March 26, 2013, 09:09:11 pm »
First of all in the engine there are a few hardcoded values that you have to live with, that's what allows good optimization. Look at the macros in the header and see if you have to change them (you should only need to change M7_NUM_TEX IIRC). A texture in the engine is a 16x16 bitmap, aka a tile. m7_LoadTex() adds M7_NUM_TEX 16x16 SDL_Surfaces to the main texture array that contains all of the tiles. Look at the demo I wrote, start from there and modify it bit by bit so you understand what you and the code are doing.

Also this line's wrong: tex[k][j] = nSDL_GetPixel(src, j, i * M7_TEX_SIZE + k); nSDL_GetPixel() takes x- and y-coordinates as input. But you shouldn't even have to write such a function, as m7_LoadTex() does just that (look at how it was done in the demo).

Greetings from a public library in Canberra.
« Last Edit: March 26, 2013, 09:11:03 pm by hoffa »

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: [Ndless] Problems with hoffa and t0xic_kitt3n' mode7 engine
« Reply #6 on: March 26, 2013, 09:32:41 pm »
I know what m7_LoadTex() does, but it needs one argument for each tile, I won't put 256 SDL_Surfaces in my program .__.


Also, the getPixel line is that way because the tilset is 8*2048.
« Last Edit: March 26, 2013, 09:33:48 pm by Matrefeytontias »