diff --git a/testbed.c b/testbed.c index 61cf5a5..1059b1a 100755 --- a/testbed.c +++ b/testbed.c @@ -391,7 +391,7 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int unsigned int *rp = gp + planeStride; unsigned int *ip = rp + planeStride; unsigned int *mp = ip + planeStride; - unsigned char bv, gv, rv, iv; + unsigned int bv, gv, rv, iv; if (meta.width > MAX_WIDTH || (meta.width % 16) != 0 || planes < 4 || planes > 5) { return 0; @@ -412,7 +412,7 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int int gpair = (pixelpair & 0x02) >> 1 | (pixelpair & 0x20) >> 4; int rpair = (pixelpair & 0x04) >> 2 | (pixelpair & 0x40) >> 5; int ipair = (pixelpair & 0x08) >> 3 | (pixelpair & 0x80) >> 6; - int shift = (3 - (ipixelpair % 4)) << 1; + int shift = (7 - (ipixelpair % 8)) << 1; bv |= bpair << shift; gv |= gpair << shift; @@ -425,7 +425,8 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int *rp++ = rv; *ip++ = iv; if (planes == 5) { - *mp++ = bv & gv & rv & iv; + iv = ~(bv & gv & rv & iv); + *mp++ = iv; } bv = gv = rv = iv = 0; } @@ -448,6 +449,18 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int /*** T I L E S ***/ +// Tiles are 16x16 bitmaps, stored as arrays of words. +// Each tile has 4 or 5 planes (depending on whether it is a tile or sprite) +// which are stored adjacant to each other; ie. a 16-word array of blue, +// followed by a 16-word array of green, etc. +// Tiles in RAM are stored byte-swapped to aid in fast bit-shifting, and must +// be byte-swapped before being written to video memory. + +// Because bit-shifting operations happen on little-endian words: +// 01234567 89ABCDEF << 3 => 34567XXX BCDEF012 +// which is wrong. So instead we do: +// 89ABCDEF 01234567 << 3 => BCDEFXXX 3456789A byteswap => 3456789A BCDEFXXX + #define PAGE_TILES_W 21 #define PAGE_TILES_H 13 #define PAGE_TILES_COUNT (PAGE_TILES_H * PAGE_TILES_W) @@ -503,6 +516,7 @@ void loadMap(unsigned char *map, unsigned int w, unsigned int h) { screen.map = map; screen.w = w; screen.h = h; + memset(screen.dirty, D_BGTILE, PAGE_TILES_COUNT * 2); } int prepareBuffer(int pageX, int pageY) { @@ -523,6 +537,7 @@ int prepareBuffer(int pageX, int pageY) { void drawSpriteToBuf(unsigned int *sprite, int pageX, int pageY, int shift, int yStart) { unsigned int *buf, *mask; + unsigned int maskval; int y, h, plane; if (pageX < 0 || pageY < 0 || pageX >= PAGE_TILES_W || pageY >= PAGE_TILES_H || @@ -532,19 +547,20 @@ void drawSpriteToBuf(unsigned int *sprite, int pageX, int pageY, int shift, int } buf = screen.buffer[prepareBuffer(pageX, pageY)]; -/* if (yStart < 0) { + if (yStart < 0) { sprite = &sprite[-yStart]; h = yStart + 16; } else { buf = &buf[yStart]; h = 16 - yStart; } - mask = &sprite[16 * 4]; + mask = &sprite[BUF_WSTRIDE * 4]; if (shift < 0) { shift = -shift; for (plane = 0; plane < 4; plane ++) { for (y = 0; y < h; y ++) { - buf[y] = (buf[y] & ~(mask[y] << shift)) | (sprite[y] << shift); + maskval = mask[y] << shift; + buf[y] = (buf[y] & ~maskval) | ((sprite[y] << shift) & maskval); } sprite += BUF_WSTRIDE; buf += BUF_WSTRIDE; @@ -552,12 +568,13 @@ void drawSpriteToBuf(unsigned int *sprite, int pageX, int pageY, int shift, int } else { for (plane = 0; plane < 4; plane ++) { for (y = 0; y < h; y ++) { - buf[y] = (buf[y] & ~(mask[y] >> shift)) | (sprite[y] >> shift); + maskval = mask[y] >> shift; + buf[y] = (buf[y] & ~maskval) | ((sprite[y] >> shift) & maskval); } sprite += BUF_WSTRIDE; buf += BUF_WSTRIDE; } - }*/ + } } void drawSprite(unsigned int *sprite, int x, int y) { @@ -572,15 +589,32 @@ void drawSprite(unsigned int *sprite, int x, int y) { drawSpriteToBuf(sprite, pageX + 1, pageY + 1, pageOffsetX - 16, pageOffsetY - 16); } -void scroll(int x, int y) { - x = min(max(x, 0), (screen.w << 4) - 320); - y = min(max(y, 0), (screen.h << 4) - 176); - if ((screen.scrollX & 0xfff0) != (x & 0xfff0) || - (screen.scrollY & 0xfff0) != (y & 0xfff0)) { - memset(screen.dirty, D_BGTILE, 2 * PAGE_TILES_COUNT); +void scroll(int newX, int newY) { + newX = min(max(newX, 0), (screen.w << 4) - 320); + newY = min(max(newY, 0), (screen.h << 4) - 176); + if ((screen.scrollX & 0xfff0) != (newX & 0xfff0) || + (screen.scrollY & 0xfff0) != (newY & 0xfff0)) { + int mapX, mapY; + unsigned char page; + for (page = 0; page < 2; page ++) { + int mapOffsetOld = (screen.scrollX >> 4) + ((screen.scrollY >> 4) * screen.w); + int mapOffsetNew = (newX >> 4) + ((newY >> 4) * screen.w); + unsigned char *dirty = screen.dirty[page]; + for (mapY = 0; mapY < PAGE_TILES_H; mapY ++) { + for (mapX = 0; mapX < PAGE_TILES_W; mapX ++) { + if (*dirty != D_NOTHING || + screen.map[mapOffsetOld + mapX] != screen.map[mapOffsetNew + mapX]) { + *dirty = D_BGTILE; + } + dirty ++; + } + mapOffsetNew += screen.w; + mapOffsetOld += screen.w; + } + } } - screen.scrollX = x; - screen.scrollY = y; + screen.scrollX = newX; + screen.scrollY = newY; } void drawScreen() { @@ -591,7 +625,7 @@ void drawScreen() { unsigned int drawOffset = screen.pageOffset[screen.currentPage]; unsigned int scrollOffset = drawOffset + (offsetX >> 3) + (offsetY * PAGE_STRIDE); unsigned char *dirty = screen.dirty[screen.currentPage]; - unsigned int x, y, di, plane; + unsigned int x, y, di, plane, bmp; setAllPlanes(); setWriteMode(1); @@ -600,7 +634,9 @@ void drawScreen() { for (y = startY; y < startY + PAGE_TILES_H; y ++) { for (x = startX; x < startX + PAGE_TILES_W; x ++) { if (dirty[di++] == D_BGTILE) { - blitTile(screen.tilesOffset + screen.map[x + (y * screen.w)], drawOffset); + blitTile( + screen.tilesOffset + (screen.map[x + (y * screen.w)] << 5), + drawOffset); } drawOffset += 2; } @@ -612,7 +648,8 @@ void drawScreen() { for (di = screen.firstBuffer; di != screen.nextBuffer; di = nextBufferIndex(di)) { drawOffset = screen.bufferOffset[di] >> 1; for (y = 0; y < 16; y ++) { - WVID[drawOffset] = screen.buffer[di][y + (BUF_WSTRIDE * plane)]; + bmp = screen.buffer[di][y + (BUF_WSTRIDE * plane)]; + WVID[drawOffset] = (bmp << 8) | (bmp >> 8); drawOffset += PAGE_STRIDE >> 1; } } @@ -630,9 +667,10 @@ void drawScreen() { #define NUM_TILES 128 #define NUM_SPRITES 64 #define OFF_TILES 0x4840 - -unsigned int tiles[NUM_TILES][4*16]; -unsigned int sprites[NUM_SPRITES][5*16]; +#define TILE_STRIDE 64 +#define SPRITE_STRIDE 80 +unsigned int tiles[NUM_TILES * TILE_STRIDE]; +unsigned int sprites[NUM_SPRITES * SPRITE_STRIDE]; unsigned char map[10000]; @@ -643,7 +681,7 @@ void fillMap() { for (y = 0; y < 100; y ++) { for (x = 0; x < 100; x ++) { - map[x + (y * 100)] = (((x + y + z) >> 2) % 4) << 5; + map[x + (y * 100)] = ((x + y + z) >> 2) % 4; } } } @@ -665,8 +703,8 @@ void game_init() { f = fopen("TILES.TIF", "rb"); meta = tifLoadMeta(f); - tifLoadEGA(f, meta, OFF_TILES, NUM_TILES * 16, 16); tifLoad(f, meta, tiles, NUM_TILES * 16, 16, 4); + tifLoadEGA(f, meta, OFF_TILES, NUM_TILES * 16, 16); fclose(f); f = fopen("SPRITE.TIF", "rb"); @@ -691,13 +729,13 @@ int main() { while (!keyPressed(K_ESC)) { - if (keyPressed(K_LEFT)) x -= 1; - if (keyPressed(K_RIGHT)) x += 1; - if (keyPressed(K_UP)) y -= 1; - if (keyPressed(K_DOWN)) y += 1; + if (keyPressed(K_LEFT)) x -= 3; + if (keyPressed(K_RIGHT)) x += 3; + if (keyPressed(K_UP)) y -= 3; + if (keyPressed(K_DOWN)) y += 3; scroll(x - 152, y - 90); - drawSprite(sprites[0], 50, 50); - drawSprite(sprites[1], x, y); + drawSprite(&sprites[0 * SPRITE_STRIDE], 50, 50); + drawSprite(&sprites[1 * SPRITE_STRIDE], x, y); drawScreen(); z++; diff --git a/testbed.exe b/testbed.exe index b39e2c7..78bdec1 100755 Binary files a/testbed.exe and b/testbed.exe differ