diff --git a/testbed.c b/testbed.c index 00c53d0..5d37102 100755 --- a/testbed.c +++ b/testbed.c @@ -21,6 +21,7 @@ #define setAllPlanes() outport(REG_TS, 0x0f02) #define VID ((volatile char far *)MK_FP(0xa000, 0)) +#define WVID ((volatile int far *)MK_FP(0xa000, 0)) void vid_cleanup() { setTextMode(); @@ -377,7 +378,7 @@ int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, u return y; } -int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int yRepeat) { +int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int yRepeat, int planes) { int istrip; int irow; int ipixelpair; @@ -389,8 +390,9 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int unsigned int *g = b + planeStride; unsigned int *r = g + planeStride; unsigned int *i = r + planeStride; + unsigned int *m = i + planeStride; - if (meta.width > MAX_WIDTH || (meta.width % 16) != 0) { + if (meta.width > MAX_WIDTH || (meta.width % 16) != 0 || planes < 4 || planes > 5) { return 0; } @@ -413,11 +415,17 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int *++g = gpair; *++r = rpair; *++i = ipair; + if (planes == 5) { + *++m = bpair & gpair & rpair & ipair; + } } else { *b |= bpair << shift; *g |= gpair << shift; *r |= rpair << shift; *i |= ipair << shift; + if (planes == 5) { + *m |= (bpair & gpair & rpair & ipair) << shift; + } } } y++; @@ -425,10 +433,10 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int return y; } if (y % yRepeat == 0) { - b += planeStride * 3; - g += planeStride * 3; - r += planeStride * 3; - i += planeStride * 3; + b += planeStride * (planes - 1); + g += planeStride * (planes - 1); + r += planeStride * (planes - 1); + i += planeStride * (planes - 1); } } } @@ -436,12 +444,11 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int } /*** T I L E S ***/ -void prepareEgaMemCopy() { - setAllPlanes(); - setWriteMode(1); -} -#define PAGE_STRIDE 42 +#define PAGE_TILES_W 21 +#define PAGE_TILES_H 13 +#define PAGE_TILES_COUNT (PAGE_TILES_H * PAGE_TILES_W) +#define PAGE_STRIDE (PAGE_TILES_W << 1) void tile_init() { setLogicalWidth(PAGE_STRIDE >> 1); @@ -456,19 +463,33 @@ void blitTile(unsigned int offsetFrom, unsigned int offsetTo) { } } +#define D_NOTHING 0x80 +#define D_BGTILE 0x81 +#define isBufIndex(d) (!((d) & 0x80)) + +#define NUM_BUFFERS 32 +#define nextBufferIndex(i) ((i + 1) % 32) +#define BUF_WSTRIDE 16 +#define BUF_WSIZE (BUF_WSTRIDE * 4) typedef struct { unsigned int w; unsigned int h; int scrollX; int scrollY; unsigned int pageOffset[2]; - unsigned char currentPage; + unsigned char dirty[2][PAGE_TILES_COUNT]; unsigned int tilesOffset; unsigned int *memTiles; unsigned char *map; + unsigned int buffer[NUM_BUFFERS][BUF_WSIZE]; + unsigned int bufferOffset[NUM_BUFFERS]; + unsigned char currentPage; + unsigned char nextBuffer; + unsigned char firstBuffer; } TiledScreen_t; -TiledScreen_t screen = { 0, 0, 0, 0, { 0x0400, 0x2620 }, 0, 0, NULL, NULL }; +TiledScreen_t screen = { 0, 0, 0, 0, { 0x0400, 0x2620 }, 0, 0, NULL, NULL, + 0, 0, 0, 0, 0 }; void loadTiles(unsigned int tilesOffset, unsigned int *memTiles) { screen.tilesOffset = tilesOffset; @@ -481,11 +502,85 @@ void loadMap(unsigned char *map, unsigned int w, unsigned int h) { screen.h = h; } +int prepareBuffer(int pageX, int pageY) { + unsigned char *dirty = &screen.dirty[screen.currentPage][pageX + (pageY * PAGE_TILES_W)]; + if (!isBufIndex(*dirty)) { + unsigned int startX = screen.scrollX >> 4; + unsigned int startY = screen.scrollY >> 4; + unsigned char tile = screen.map[startX + pageX + ((startY + pageY) * screen.w)]; + unsigned char ibuffer = screen.nextBuffer; + screen.nextBuffer = nextBufferIndex(screen.nextBuffer); + *dirty = ibuffer; + memcpy(screen.buffer[ibuffer], &screen.memTiles[tile * BUF_WSIZE], BUF_WSIZE); + screen.bufferOffset[ibuffer] = screen.pageOffset[screen.currentPage] + + (pageX << 1) + (pageY * PAGE_STRIDE); + } + return *dirty; +} + +void drawSpriteToBuf(unsigned int *sprite, int pageX, int pageY, int shift, int yStart) { + unsigned int *buf, *mask; + int y, h, plane; + if (pageX < 0 || pageY < 0 || + pageX >= PAGE_TILES_W || pageY >= PAGE_TILES_H || + shift >= 16 || shift <= -16 || + yStart <= -16 || yStart >= 16) { + return; + } + + buf = screen.buffer[prepareBuffer(pageX, pageY)]; +/* if (yStart < 0) { + sprite = &sprite[-yStart]; + h = yStart + 16; + } else { + buf = &buf[yStart]; + h = 16 - yStart; + } + mask = &sprite[16 * 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); + } + sprite += BUF_WSTRIDE; + buf += BUF_WSTRIDE; + } + } else { + for (plane = 0; plane < 4; plane ++) { + for (y = 0; y < h; y ++) { + buf[y] = (buf[y] & ~(mask[y] >> shift)) | (sprite[y] >> shift); + } + sprite += BUF_WSTRIDE; + buf += BUF_WSTRIDE; + } + }*/ +} + +void drawSprite(unsigned int *sprite, int x, int y) { + unsigned int startX = screen.scrollX >> 4; + unsigned int startY = screen.scrollY >> 4; + int pageX = (x - startX) >> 4; + int pageY = (y - startY) >> 4; + int pageOffsetX = x - (pageX << 4); + int pageOffsetY = y - (pageY << 4); + + drawSpriteToBuf(sprite, pageX, pageY, pageOffsetX, pageOffsetY); + drawSpriteToBuf(sprite, pageX + 1, pageY, pageOffsetX - 16, pageOffsetY); + drawSpriteToBuf(sprite, pageX, pageY + 1, pageOffsetX, pageOffsetY - 16); + drawSpriteToBuf(sprite, pageX + 1, pageY + 1, pageOffsetX - 16, pageOffsetY - 16); +} + void scroll(int x, int y) { + unsigned int startX = screen.scrollX >> 4; + unsigned int startY = screen.scrollY >> 4; x = min(max(x, 0), (screen.w << 4) - 320); y = min(max(y, 0), (screen.h << 4) - 176); screen.scrollX = x; screen.scrollY = y; + if (startX != (x >> 4) || startY != (y >> 4)) { + memset(screen.dirty, D_BGTILE, 2 * PAGE_TILES_COUNT); + } } void drawScreen() { @@ -495,27 +590,51 @@ void drawScreen() { unsigned int offsetY = screen.scrollY - (startY << 4); unsigned int drawOffset = screen.pageOffset[screen.currentPage]; unsigned int scrollOffset = drawOffset + (offsetX >> 3) + (offsetY * PAGE_STRIDE); - unsigned int x, y; + unsigned char *dirty = screen.dirty[screen.currentPage]; + unsigned int x, y, di, plane; - prepareEgaMemCopy(); + setAllPlanes(); + setWriteMode(1); - for (y = startY; y < startY + 13; y ++) { - for (x = startX; x < startX + 21; x ++) { - blitTile(screen.tilesOffset + screen.map[x + (y * screen.w)], drawOffset); + di = 0; + 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); + } drawOffset += 2; } drawOffset += PAGE_STRIDE * 15; } - + setWriteMode(0); + for(plane = 0; plane < 4; plane ++) { + setPlane(plane); + 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)]; + drawOffset += PAGE_STRIDE >> 1; + } + } + } + setAllPlanes(); setDisplayOffset(scrollOffset); screen.currentPage ^= 1; + screen.firstBuffer = screen.nextBuffer; + for (di = 0; di < PAGE_TILES_COUNT; di ++) { + dirty[di] = isBufIndex(dirty[di]) ? D_BGTILE : D_NOTHING; + } } /*** S C R A T C H ***/ - -unsigned int tiles[2*16 * 128]; +#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]; + + unsigned char map[10000]; void fillMap() { @@ -546,8 +665,13 @@ void game_init() { f = fopen("TILES.TIF", "rb"); meta = tifLoadMeta(f); - tifLoadEGA(f, meta, OFF_TILES, 256, 16); - tifLoad(f, meta, tiles, 128 * 16, 16); + tifLoadEGA(f, meta, OFF_TILES, NUM_TILES * 16, 16); + tifLoad(f, meta, tiles, NUM_TILES * 16, 16, 4); + fclose(f); + + f = fopen("SPRITE.TIF", "rb"); + meta = tifLoadMeta(f); + tifLoad(f, meta, sprites, NUM_SPRITES * 16, 16, 5); fclose(f); setSplitScreen(351); @@ -558,8 +682,8 @@ void game_init() { } int main() { - int x; - int y; + int x = 100; + int y = 100; int z = 0; game_init(); @@ -567,13 +691,13 @@ int main() { while (!keyPressed(K_ESC)) { - x = screen.scrollX; - y = screen.scrollY; - if (keyPressed(K_LEFT)) x -= 8; - if (keyPressed(K_RIGHT)) x += 8; - if (keyPressed(K_UP)) y -= 8; - if (keyPressed(K_DOWN)) y += 8; - scroll(x, y); + if (keyPressed(K_LEFT)) x -= 1; + if (keyPressed(K_RIGHT)) x += 1; + if (keyPressed(K_UP)) y -= 1; + if (keyPressed(K_DOWN)) y += 1; + scroll(x + 152, y + 90); + drawSprite(sprites[0], 50, 50); + drawSprite(sprites[1], x, y); drawScreen(); z++; diff --git a/testbed.exe b/testbed.exe index ad63d16..ffcb4e3 100755 Binary files a/testbed.exe and b/testbed.exe differ