Implement map scrolling

This commit is contained in:
Jeremy Penner 2019-01-18 23:02:50 -05:00
parent 7abb774dfb
commit 4688bdccb0
2 changed files with 112 additions and 61 deletions

171
testbed.c
View file

@ -26,42 +26,37 @@ void vid_cleanup() {
setTextMode();
}
typedef struct {
unsigned int b[16];
unsigned int g[16];
unsigned int r[16];
unsigned int i[16];
} Tile_t;
unsigned int PAGE[] = { 0x04, 0x24 };
#define setWriteMode(m) outport(REG_GDC, 0x05 | m << 8)
void setSplitScreen(unsigned int y) {
// TODO: VGA registers??
outport(REG_CRTC, 0x1018);// | y << 8);
outport(REG_CRTC, 0x0107);
int val;
outport(REG_CRTC, 0x18 | (y << 8));
outp(REG_CRTC, 7);
val = inp(REG_CRTC + 1);
val &= ~0x10;
val |= (y & 0x100) >> 4;
outp(REG_CRTC + 1, val);
outp(REG_CRTC, 9);
val = inp(REG_CRTC + 1);
val &= ~0x40;
outp(REG_CRTC + 1, val);
}
void unsetSplitScreen() {
outport(REG_CRTC, 0xff18);
outport(REG_CRTC, 0x1107);
outport(REG_CRTC, 0x0f09);
}
void prepareEgaMemCopy() {
setAllPlanes();
setWriteMode(1);
}
#define PAGE_STRIDE 40
void blitTile(unsigned int offsetFrom, unsigned int offsetTo) {
int y;
for (y = 0; y < 16; y ++) {
VID[offsetTo] = VID[offsetFrom ++];
VID[offsetTo + 1] = VID[offsetFrom ++];
offsetTo += PAGE_STRIDE;
}
}
#define flipPage(p) outport(REG_CRTC, 0x0c | (p << 8))
void setDisplayOffset(unsigned int offset) {
outport(REG_CRTC, 0x0c | (offset & 0xff00));
outport(REG_CRTC, 0x0d | (offset << 8));
}
#define setLogicalWidth(w) outport(REG_CRTC, 0x13 | (w << 8))
/*** K E Y B O A R D ***/
#define KBD_INT 0x09
void interrupt (*oldKbdISR)() = NULL;
@ -325,7 +320,7 @@ fail:
#define MAX_WIDTH 320
int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY) {
int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, unsigned int w) {
int istrip;
int irow;
int ipixelpair;
@ -376,6 +371,7 @@ int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY) {
if (y == maxY) {
return y;
}
out += (w - meta.width) >> 3;
}
}
return y;
@ -439,30 +435,87 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int
return y;
}
/*** S C R A T C H ***/
void paintPattern(int r, int g, int b, int t) {
int i;
/*** T I L E S ***/
void prepareEgaMemCopy() {
setAllPlanes();
setWriteMode(1);
}
setPlane(PLANE_R);
for (i = 0; i < 8000; i ++) {
VID[i] = r;
#define PAGE_STRIDE 42
void tile_init() {
setLogicalWidth(PAGE_STRIDE >> 1);
}
setPlane(PLANE_G);
for (i = 0; i < 8000; i ++) {
VID[i] = g;
void blitTile(unsigned int offsetFrom, unsigned int offsetTo) {
int y;
for (y = 0; y < 16; y ++) {
VID[offsetTo] = VID[offsetFrom ++];
VID[offsetTo + 1] = VID[offsetFrom ++];
offsetTo += PAGE_STRIDE;
}
setPlane(PLANE_B);
for (i = 0; i < 8000; i ++) {
VID[i] = b;
}
setPlane(PLANE_I);
for (i = 0; i < 8000; i ++) {
VID[i] = t;
typedef struct {
unsigned int w;
unsigned int h;
int scrollX;
int scrollY;
unsigned int pageOffset;
unsigned char *tiles;
} TilePage_t;
#define OFF_TILES 0x4840
void scrollPage(TilePage_t *page, int x, int y) {
x = min(max(x, 0), (page->w << 4) - 320);
y = min(max(y, 0), (page->h << 4) - 176);
page->scrollX = x;
page->scrollY = y;
}
void drawPage(TilePage_t *page) {
unsigned int startX = page->scrollX >> 4;
unsigned int startY = page->scrollY >> 4;
unsigned int offsetX = page->scrollX - (startX << 4);
unsigned int offsetY = page->scrollY - (startY << 4);
unsigned int drawOffset = page->pageOffset;
unsigned int scrollOffset = drawOffset + (offsetX >> 3) + (offsetY * PAGE_STRIDE);
unsigned int x, y;
prepareEgaMemCopy();
for (y = startY; y < startY + 13; y ++) {
for (x = startX; x < startX + 21; x ++) {
blitTile(OFF_TILES + page->tiles[x + (y * page->w)], drawOffset);
drawOffset += 2;
}
drawOffset += PAGE_STRIDE * 15;
}
setDisplayOffset(scrollOffset);
}
/*** S C R A T C H ***/
unsigned char tiles[10000];
TilePage_t pages[2] = {
{ 100, 100, 0, 0, 0x0400, tiles },
{ 100, 100, 0, 0, 0x2620, tiles }
};
void fillTiles() {
unsigned int x, y, z;
z = 0;
for (y = 0; y < 100; y ++) {
for (x = 0; x < 100; x ++) {
tiles[x + (y * 100)] = (((x + y + z) >> 2) % 3) << 5;
}
}
}
int main() {
Tile_t tiles[16];
FILE *f;
TifImageMeta_t meta;
int plane;
@ -472,41 +525,39 @@ int main() {
unsigned int drawOffset;
unsigned int page = 0;
#define OFF_TILES 0x4200
setEGAMode();
atexit(vid_cleanup);
f = fopen("FOOTER.TIF", "rb");
meta = tifLoadMeta(f);
tifLoadEGA(f, meta, 0, 24);
tifLoadEGA(f, meta, 0, 24, 336);
fclose(f);
f = fopen("TILES.TIF", "rb");
meta = tifLoadMeta(f);
tifLoadEGA(f, meta, OFF_TILES, 256);
tifLoadEGA(f, meta, OFF_TILES, 256, 16);
fclose(f);
mouse_init();
kbd_init();
tile_init();
setSplitScreen(351);
fillTiles();
while (!keyPressed(K_ESC)) {
page ^= 1;
prepareEgaMemCopy();
drawOffset = PAGE[page] << 8;
for (y = 0; y < 11; y ++) {
for (x = 0; x < 20; x ++) {
blitTile(OFF_TILES + ((((x + y + z) >> 2) % 3) << 5), drawOffset);
drawOffset += 2;
}
drawOffset += 600; // 40 bytes per line * 15 more lines
}
x = pages[page].scrollX;
y = pages[page].scrollY;
if (keyPressed(K_LEFT)) x -= 4;
if (keyPressed(K_RIGHT)) x += 4;
if (keyPressed(K_UP)) y -= 4;
if (keyPressed(K_DOWN)) y += 4;
scrollPage(&pages[0], x, y);
scrollPage(&pages[1], x, y);
drawPage(&pages[page]);
flipPage(PAGE[page]);
setSplitScreen(16);
kbd_wait();
// kbd_wait();
z++;
}

Binary file not shown.