Search code examples
c++sdlsdl-2nullptr

SDL2.0 screen nullptr on render of Window


Hey so I'm relatively new to the SDL library and just trying to get to grips with it.

I found a C++ conversion for Minecraft4k but it was based on SDL1.x so I'm trying to convert it to SDL2.0

At present the build is successful, but when it gets to;

plot(x, y, rgbmul(col, fxmul(br, ddist)));

It throws a read access violation exception:

screen was nullptr

This is my code;

// C++ port of Minecraft 4k JS (http://jsdo.it/notch/dB1E)
// By The8BitPimp
// See: the8bitpimp.wordpress.com

#include <SDL.h>
#include <math.h>
#include <windows.h>
#include <tchar.h>
#include "plot.h"
#include "llist.h"

const int w = 320;
const int h = 240;

SDL_Surface *screen = nullptr;

const float math_pi = 3.14159265359f;

static inline float math_sin(float x) {
    return sinf(x);
}

static inline float math_cos(float x) {
    return cosf(x);
}

// the texture map
int texmap[16 * 16 * 16 * 3];

// the voxel map
char map[64 * 64 * 64];

static inline int random(int max) {
 return (rand() ^ (rand() << 16)) % max;
}

static inline void plot(int x, int y, int c) {
int *p = (int*)screen->pixels;
p[y * w + x] = c;
}

static void makeTextures(void) {

// each texture
for (int j = 0; j<16; j++) {

    int k = 255 - random(96);

    // each pixel in the texture
    for (int m = 0; m<16 * 3; m++)
        for (int n = 0; n<16; n++) {

            int i1 = 0x966C4A;
            int i2 = 0;
            int i3 = 0;

            if (j == 4)
                i1 = 0x7F7F7F;
            if ((j != 4) || (random(3) == 0))
                k = 255 - random(96);
            if (j == 1)
            {
                if (m < (((n * n * 3 + n * 81) >> 2) & 0x3) + 18)
                    i1 = 0x6AAA40;
                else if (m < (((n * n * 3 + n * 81) >> 2) & 0x3) + 19)
                    k = k * 2 / 3;
            }
            if (j == 7)
            {
                i1 = 0x675231;
                if ((n > 0) && (n < 15) && (((m > 0) && (m < 15)) || ((m > 32) && (m < 47))))
                {
                    i1 = 0xBC9862;
                    i2 = n - 7;
                    i3 = (m & 0xF) - 7;
                    if (i2 < 0)
                        i2 = 1 - i2;

                    if (i3 < 0)
                        i3 = 1 - i3;

                    if (i3 > i2)
                        i2 = i3;

                    k = 196 - random(32) + i2 % 3 * 32;
                }
                else if (random(2) == 0)
                    k = k * (150 - (n & 0x1) * 100) / 100;
            }
            if (j == 5)
            {
                i1 = 0xB53A15;
                if (((n + m / 4 * 4) % 8 == 0) || (m % 4 == 0))
                    i1 = 0xBCAFA5;
            }
            i2 = k;
            if (m >= 32)
                i2 /= 2;
            if (j == 8)
            {
                i1 = 5298487;
                if (random(2) == 0)
                {
                    i1 = 0;
                    i2 = 255;
                }
            }

            // fixed point colour multiply between i1 and i2
            i3 =
                ((((i1 >> 16) & 0xFF) * i2 / 255) << 16) |
                ((((i1 >> 8) & 0xFF) * i2 / 255) << 8) |
                ((i1 & 0xFF) * i2 / 255);
            // pack the colour away
            texmap[n + m * 16 + j * 256 * 3] = i3;
        }
}
}

static void makeMap(void) {
// add random blocks to the map
for (int x = 0; x < 64; x++) {
    for (int y = 0; y < 64; y++) {
        for (int z = 0; z < 64; z++) {
            int i = (z << 12) | (y << 6) | x;
            float yd = (y - 32.5) * 0.4;
            float zd = (z - 32.5) * 0.4;
            map[i] = random(16);

            float th = random(256) / 256.0f;

            if (th > sqrtf(sqrtf(yd * yd + zd * zd)) - 0.8f)
                map[i] = 0;
        }
    }
}
}

static void init(void) {
  makeTextures();
  makeMap();
}

// fixed point byte byte multiply
static inline int fxmul(int a, int b) {
return (a*b) >> 8;
}

// fixed point 8bit packed colour multiply
static inline int rgbmul(int a, int b) {
int _r = (((a >> 16) & 0xff) * b) >> 8;
int _g = (((a >> 8) & 0xff) * b) >> 8;
int _b = (((a)& 0xff) * b) >> 8;
return (_r << 16) | (_g << 8) | _b;
}

static void render(void) {

float now = (float)(SDL_GetTicks() % 10000) / 10000.f;

float xRot = math_sin(now * math_pi * 2) * 0.4 + math_pi / 2;
float yRot = math_cos(now * math_pi * 2) * 0.4;
float yCos = math_cos(yRot);
float ySin = math_sin(yRot);
float xCos = math_cos(xRot);
float xSin = math_sin(xRot);

float ox = 32.5 + now * 64.0;
float oy = 32.5;
float oz = 32.5;

// for each column
for (int x = 0; x < w; x++) {
    // get the x axis delta
    float ___xd = ((float)x - (float)w / 2.f) / (float)h;
    // for each row
    for (int y = 0; y < h; y++) {
        // get the y axis delta
        float  __yd = ((float)y - (float)h / 2.f) / (float)h;
        float  __zd = 1;
        float ___zd = __zd * yCos + __yd * ySin;
        float   _yd = __yd * yCos - __zd * ySin;
        float   _xd = ___xd * xCos + ___zd * xSin;
        float   _zd = ___zd * xCos - ___xd * xSin;

        int col = 0;
        int br = 255;
        float ddist = 0;

        float closest = 32.f;

        // for each principle axis  x,y,z
        for (int d = 0; d < 3; d++) {
            float dimLength = _xd;
            if (d == 1)
                dimLength = _yd;
            if (d == 2)
                dimLength = _zd;

            float ll = 1.0f / (dimLength < 0.f ? -dimLength : dimLength);
            float xd = (_xd)* ll;
            float yd = (_yd)* ll;
            float zd = (_zd)* ll;

            float       initial = ox - floor(ox);
            if (d == 1) initial = oy - floor(oy);
            if (d == 2) initial = oz - floor(oz);

            if (dimLength > 0) initial = 1 - initial;

            float dist = ll * initial;

            float xp = ox + xd * initial;
            float yp = oy + yd * initial;
            float zp = oz + zd * initial;

            if (dimLength < 0) {
                if (d == 0) xp--;
                if (d == 1) yp--;
                if (d == 2) zp--;
            }

            // while we are concidering a ray that is still closer then the best so far
            while (dist < closest) {

                // quantize to the map grid
                int tex = map[(((int)zp & 63) << 12) | (((int)yp & 63) << 6) | ((int)xp & 63)];

                // if this voxel has a texture applied
                if (tex > 0) {

                    // find the uv coordinates of the intersection point
                    int u = ((int)((xp + zp) * 16.f)) & 15;
                    int v = ((int)(yp       * 16.f) & 15) + 16;

                    // fix uvs for alternate directions?
                    if (d == 1) {
                        u = ((int)(xp * 16.f)) & 15;
                        v = (((int)(zp * 16.f)) & 15);
                        if (yd < 0)
                            v += 32;
                    }

                    // find the colour at the intersection point
                    int cc = texmap[u + v * 16 + tex * 256 * 3];

                    // if the colour is not transparent
                    if (cc > 0) {
                        col = cc;
                        ddist = 255 - ((dist / 32 * 255));
                        br = 255 * (255 - ((d + 2) % 3) * 50) / 255;

                        // we now have the closest hit point (also terminates this ray)
                        closest = dist;
                    }
                }

                // advance the ray
                xp += xd;
                yp += yd;
                zp += zd;
                dist += ll;
            }
        }

        plot(x, y, rgbmul(col, fxmul(br, ddist)));
    }
   }
}

int main(int argc, char *argv[]) {

SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *screen; 
screen = SDL_CreateWindow(
    "Minecraft4k",                  // window title
    SDL_WINDOWPOS_CENTERED,           // initial x position
    SDL_WINDOWPOS_CENTERED,           // initial y position
    320,                               // width, in pixels
    240,                               // height, in pixels
    SDL_WINDOW_OPENGL                  // flags - see below
    );

SDL_Renderer* renderer;
renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);

if (screen == nullptr) {
    return 1;
}

init();
bool running = true;
while (running) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        running &= (event.type != SDL_QUIT);
    }
    SDL_RenderPresent(renderer);
    render();
}

SDL_DestroyWindow(screen);
SDL_Quit();
return 0;

}

When I actually run the code I do get a black screen, but the debugger lands on the line

plot(x, y, rgbmul(col, fxmul(br, ddist)));

in ; static void render(void)

This is all just "for fun" so any information or guidance is appreciated.


Solution

  • You define screen twice (the first time as a global variable, the second time within your main), but you initialize it only once (within your main).
    Because of that, the global variable screen actually is set to nullptr and plot fails trying to use it, as the error message states.