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

173
testbed.c
View file

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

Binary file not shown.