implementing sprites drawn overtop of tilemap

This commit is contained in:
Jeremy Penner 2019-01-18 23:03:02 -05:00
parent 28f98c20b2
commit aeb1f47f51
2 changed files with 156 additions and 32 deletions

188
testbed.c
View file

@ -21,6 +21,7 @@
#define setAllPlanes() outport(REG_TS, 0x0f02) #define setAllPlanes() outport(REG_TS, 0x0f02)
#define VID ((volatile char far *)MK_FP(0xa000, 0)) #define VID ((volatile char far *)MK_FP(0xa000, 0))
#define WVID ((volatile int far *)MK_FP(0xa000, 0))
void vid_cleanup() { void vid_cleanup() {
setTextMode(); setTextMode();
@ -377,7 +378,7 @@ int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, u
return y; 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 istrip;
int irow; int irow;
int ipixelpair; 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 *g = b + planeStride;
unsigned int *r = g + planeStride; unsigned int *r = g + planeStride;
unsigned int *i = r + 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; return 0;
} }
@ -413,11 +415,17 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int
*++g = gpair; *++g = gpair;
*++r = rpair; *++r = rpair;
*++i = ipair; *++i = ipair;
if (planes == 5) {
*++m = bpair & gpair & rpair & ipair;
}
} else { } else {
*b |= bpair << shift; *b |= bpair << shift;
*g |= gpair << shift; *g |= gpair << shift;
*r |= rpair << shift; *r |= rpair << shift;
*i |= ipair << shift; *i |= ipair << shift;
if (planes == 5) {
*m |= (bpair & gpair & rpair & ipair) << shift;
}
} }
} }
y++; y++;
@ -425,10 +433,10 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int
return y; return y;
} }
if (y % yRepeat == 0) { if (y % yRepeat == 0) {
b += planeStride * 3; b += planeStride * (planes - 1);
g += planeStride * 3; g += planeStride * (planes - 1);
r += planeStride * 3; r += planeStride * (planes - 1);
i += planeStride * 3; 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 ***/ /*** 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() { void tile_init() {
setLogicalWidth(PAGE_STRIDE >> 1); 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 { typedef struct {
unsigned int w; unsigned int w;
unsigned int h; unsigned int h;
int scrollX; int scrollX;
int scrollY; int scrollY;
unsigned int pageOffset[2]; unsigned int pageOffset[2];
unsigned char currentPage; unsigned char dirty[2][PAGE_TILES_COUNT];
unsigned int tilesOffset; unsigned int tilesOffset;
unsigned int *memTiles; unsigned int *memTiles;
unsigned char *map; 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;
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) { void loadTiles(unsigned int tilesOffset, unsigned int *memTiles) {
screen.tilesOffset = tilesOffset; screen.tilesOffset = tilesOffset;
@ -481,11 +502,85 @@ void loadMap(unsigned char *map, unsigned int w, unsigned int h) {
screen.h = 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) { 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); x = min(max(x, 0), (screen.w << 4) - 320);
y = min(max(y, 0), (screen.h << 4) - 176); y = min(max(y, 0), (screen.h << 4) - 176);
screen.scrollX = x; screen.scrollX = x;
screen.scrollY = y; screen.scrollY = y;
if (startX != (x >> 4) || startY != (y >> 4)) {
memset(screen.dirty, D_BGTILE, 2 * PAGE_TILES_COUNT);
}
} }
void drawScreen() { void drawScreen() {
@ -495,27 +590,51 @@ void drawScreen() {
unsigned int offsetY = screen.scrollY - (startY << 4); unsigned int offsetY = screen.scrollY - (startY << 4);
unsigned int drawOffset = screen.pageOffset[screen.currentPage]; unsigned int drawOffset = screen.pageOffset[screen.currentPage];
unsigned int scrollOffset = drawOffset + (offsetX >> 3) + (offsetY * PAGE_STRIDE); 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 ++) { di = 0;
for (x = startX; x < startX + 21; x ++) { for (y = startY; y < startY + PAGE_TILES_H; y ++) {
blitTile(screen.tilesOffset + screen.map[x + (y * screen.w)], drawOffset); 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 += 2;
} }
drawOffset += PAGE_STRIDE * 15; 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); setDisplayOffset(scrollOffset);
screen.currentPage ^= 1; 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 ***/ /*** S C R A T C H ***/
#define NUM_TILES 128
unsigned int tiles[2*16 * 128]; #define NUM_SPRITES 64
#define OFF_TILES 0x4840 #define OFF_TILES 0x4840
unsigned int tiles[NUM_TILES][4*16];
unsigned int sprites[NUM_SPRITES][5*16];
unsigned char map[10000]; unsigned char map[10000];
void fillMap() { void fillMap() {
@ -546,8 +665,13 @@ void game_init() {
f = fopen("TILES.TIF", "rb"); f = fopen("TILES.TIF", "rb");
meta = tifLoadMeta(f); meta = tifLoadMeta(f);
tifLoadEGA(f, meta, OFF_TILES, 256, 16); tifLoadEGA(f, meta, OFF_TILES, NUM_TILES * 16, 16);
tifLoad(f, meta, tiles, 128 * 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); fclose(f);
setSplitScreen(351); setSplitScreen(351);
@ -558,8 +682,8 @@ void game_init() {
} }
int main() { int main() {
int x; int x = 100;
int y; int y = 100;
int z = 0; int z = 0;
game_init(); game_init();
@ -567,13 +691,13 @@ int main() {
while (!keyPressed(K_ESC)) { while (!keyPressed(K_ESC)) {
x = screen.scrollX; if (keyPressed(K_LEFT)) x -= 1;
y = screen.scrollY; if (keyPressed(K_RIGHT)) x += 1;
if (keyPressed(K_LEFT)) x -= 8; if (keyPressed(K_UP)) y -= 1;
if (keyPressed(K_RIGHT)) x += 8; if (keyPressed(K_DOWN)) y += 1;
if (keyPressed(K_UP)) y -= 8; scroll(x + 152, y + 90);
if (keyPressed(K_DOWN)) y += 8; drawSprite(sprites[0], 50, 50);
scroll(x, y); drawSprite(sprites[1], x, y);
drawScreen(); drawScreen();
z++; z++;

Binary file not shown.