Refactor into seperate modules & Turbo C++ project
This commit is contained in:
parent
e5d1ac5c79
commit
eeb1e86cba
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
*.obj
|
*.obj
|
||||||
*.bak
|
*.bak
|
||||||
|
*.dsk
|
||||||
|
*.swp
|
||||||
|
|
75
kbd.c
Executable file
75
kbd.c
Executable file
|
@ -0,0 +1,75 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include "kbd.h"
|
||||||
|
|
||||||
|
static void interrupt (*oldKbdISR)() = NULL;
|
||||||
|
|
||||||
|
void kbd_cleanup() {
|
||||||
|
if (oldKbdISR != NULL) {
|
||||||
|
setvect(KBD_INT, oldKbdISR);
|
||||||
|
oldKbdISR = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile unsigned char keybuf[128] = { 0 };
|
||||||
|
volatile char kbd_triggered = 0;
|
||||||
|
|
||||||
|
static void interrupt kbd_isr() {
|
||||||
|
unsigned char raw;
|
||||||
|
char ctl;
|
||||||
|
|
||||||
|
asm sti;
|
||||||
|
raw = inp(0x60);
|
||||||
|
ctl = inp(0x61) | 0x82;
|
||||||
|
outp(0x61, ctl);
|
||||||
|
outp(0x61, ctl & 0x7f);
|
||||||
|
outp(0x20, 0x20);
|
||||||
|
|
||||||
|
if (raw & 0x80) {
|
||||||
|
keybuf[raw & 0x7f] &= ~KEY_SIGNAL;
|
||||||
|
} else {
|
||||||
|
keybuf[raw] |= KEY_SIGNAL;
|
||||||
|
}
|
||||||
|
kbd_triggered = raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char kbd_wait() {
|
||||||
|
kbd_triggered = 0;
|
||||||
|
while (!kbd_triggered) {}
|
||||||
|
return kbd_triggered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kbd_init() {
|
||||||
|
if (oldKbdISR == NULL) {
|
||||||
|
memset(keybuf, 0, 128);
|
||||||
|
oldKbdISR = getvect(KBD_INT);
|
||||||
|
setvect(KBD_INT, kbd_isr);
|
||||||
|
atexit(kbd_cleanup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kbd_debounce() {
|
||||||
|
int i = 0;
|
||||||
|
asm cli;
|
||||||
|
for (i = 0; i < 128; i ++) {
|
||||||
|
unsigned char signal = keybuf[i] & KEY_SIGNAL;
|
||||||
|
unsigned char keystate = keybuf[i] & 0x0f;
|
||||||
|
|
||||||
|
if (!signal) {
|
||||||
|
if (keystate == KEY_RELEASED) {
|
||||||
|
keystate = KEY_OFF;
|
||||||
|
} else if (keystate != KEY_OFF) {
|
||||||
|
keystate = KEY_RELEASED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (keystate == KEY_OFF) {
|
||||||
|
keystate = KEY_PRESSED;
|
||||||
|
} else if (keystate == KEY_PRESSED) {
|
||||||
|
keystate = KEY_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keybuf[i] = signal | keystate;
|
||||||
|
}
|
||||||
|
asm sti;
|
||||||
|
}
|
106
kbd.h
Executable file
106
kbd.h
Executable file
|
@ -0,0 +1,106 @@
|
||||||
|
/*** K E Y B O A R D ***/
|
||||||
|
#define KBD_INT 0x09
|
||||||
|
|
||||||
|
extern volatile unsigned char keybuf[128];
|
||||||
|
extern volatile char kbd_triggered;
|
||||||
|
|
||||||
|
void kbd_init();
|
||||||
|
void kbd_debounce(); // call once per frame
|
||||||
|
unsigned char kbd_wait();
|
||||||
|
|
||||||
|
#define KEY_OFF 0
|
||||||
|
#define KEY_PRESSED 1
|
||||||
|
#define KEY_DOWN 2
|
||||||
|
#define KEY_RELEASED 3
|
||||||
|
#define KEY_SIGNAL 0x80
|
||||||
|
|
||||||
|
#define keyIsDown(k) (keybuf[k] & KEY_SIGNAL)
|
||||||
|
#define keyWasPressed(k) ((keybuf[k] & 0x0f) == KEY_PRESSED)
|
||||||
|
#define keyWasReleased(k) ((keybuf[k] & 0x0f) == KEY_RELEASED)
|
||||||
|
|
||||||
|
#define K_ESC 1
|
||||||
|
#define K_1 2
|
||||||
|
#define K_2 3
|
||||||
|
#define K_3 4
|
||||||
|
#define K_4 5
|
||||||
|
#define K_5 6
|
||||||
|
#define K_6 7
|
||||||
|
#define K_7 8
|
||||||
|
#define K_8 9
|
||||||
|
#define K_9 10
|
||||||
|
#define K_0 11
|
||||||
|
#define K_MINUS 12
|
||||||
|
#define K_EQUAL 13
|
||||||
|
#define K_BKSP 14
|
||||||
|
#define K_TAB 15
|
||||||
|
#define K_Q 16
|
||||||
|
#define K_W 17
|
||||||
|
#define K_E 18
|
||||||
|
#define K_R 19
|
||||||
|
#define K_T 20
|
||||||
|
#define K_Y 21
|
||||||
|
#define K_U 22
|
||||||
|
#define K_I 23
|
||||||
|
#define K_O 24
|
||||||
|
#define K_P 25
|
||||||
|
#define K_LBRK 26
|
||||||
|
#define K_RBRK 27
|
||||||
|
#define K_ENTER 28
|
||||||
|
#define K_CTRL 29
|
||||||
|
#define K_A 30
|
||||||
|
#define K_S 31
|
||||||
|
#define K_D 32
|
||||||
|
#define K_F 33
|
||||||
|
#define K_G 34
|
||||||
|
#define K_H 35
|
||||||
|
#define K_J 36
|
||||||
|
#define K_K 37
|
||||||
|
#define K_L 38
|
||||||
|
#define K_SEMI 39
|
||||||
|
#define K_APOS 40
|
||||||
|
#define K_TILDE 41
|
||||||
|
#define K_LSHFT 42
|
||||||
|
#define K_BSLSH 43
|
||||||
|
#define K_Z 44
|
||||||
|
#define K_X 45
|
||||||
|
#define K_C 46
|
||||||
|
#define K_V 47
|
||||||
|
#define K_B 48
|
||||||
|
#define K_N 49
|
||||||
|
#define K_M 50
|
||||||
|
#define K_COMMA 51
|
||||||
|
#define K_DOT 52
|
||||||
|
#define K_SLASH 53
|
||||||
|
#define K_RSHFT 54
|
||||||
|
#define K_PSCRN 55
|
||||||
|
#define K_ALT 56
|
||||||
|
#define K_SPACE 57
|
||||||
|
#define K_CAPS 58
|
||||||
|
#define K_F1 59
|
||||||
|
#define K_F2 60
|
||||||
|
#define K_F3 61
|
||||||
|
#define K_F4 62
|
||||||
|
#define K_F5 63
|
||||||
|
#define K_F6 64
|
||||||
|
#define K_F7 65
|
||||||
|
#define K_F8 66
|
||||||
|
#define K_F9 67
|
||||||
|
#define K_F10 68
|
||||||
|
#define K_NUMLK 69
|
||||||
|
#define K_SCRL 70
|
||||||
|
#define K_HOME 71
|
||||||
|
#define K_UP 72
|
||||||
|
#define K_PGUP 73
|
||||||
|
#define K_NDASH 74
|
||||||
|
#define K_LEFT 75
|
||||||
|
#define K_CENT 76
|
||||||
|
#define K_RIGHT 77
|
||||||
|
#define K_NPLUS 78
|
||||||
|
#define K_END 79
|
||||||
|
#define K_DOWN 80
|
||||||
|
#define K_PGDN 81
|
||||||
|
#define K_INS 82
|
||||||
|
#define K_DEL 83
|
||||||
|
#define K_F11 87
|
||||||
|
#define K_F12 88
|
||||||
|
|
55
mouse.c
Executable file
55
mouse.c
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#include <dos.h>
|
||||||
|
#include "mouse.h";
|
||||||
|
|
||||||
|
/*** M O U S E ***/
|
||||||
|
Mouse_t MOUSE;
|
||||||
|
|
||||||
|
void far mouse_callback() {
|
||||||
|
asm {
|
||||||
|
mov ax, DGROUP
|
||||||
|
mov ds, ax
|
||||||
|
shr cx, 1
|
||||||
|
mov MOUSE.x, cx
|
||||||
|
mov MOUSE.y, dx
|
||||||
|
mov MOUSE.buttons, bx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_cleanup() {
|
||||||
|
//uninstall handler
|
||||||
|
asm {
|
||||||
|
mov ax, 0ch
|
||||||
|
mov dx, 0
|
||||||
|
mov es, dx
|
||||||
|
mov cx, 0
|
||||||
|
int 33h
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
int 33h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_init() {
|
||||||
|
unsigned seg_mouse_callback = FP_SEG(mouse_callback);
|
||||||
|
unsigned off_mouse_callback = FP_OFF(mouse_callback);
|
||||||
|
unsigned int result;
|
||||||
|
asm {
|
||||||
|
xor ax, ax
|
||||||
|
int 33h
|
||||||
|
mov result, ax
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
printf("Mouse driver not installed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
atexit(mouse_cleanup);
|
||||||
|
|
||||||
|
asm {
|
||||||
|
mov ax, seg_mouse_callback
|
||||||
|
mov es, ax
|
||||||
|
mov dx, off_mouse_callback
|
||||||
|
mov ax, 0ch
|
||||||
|
mov cx, 1fh
|
||||||
|
int 33h
|
||||||
|
}
|
||||||
|
}
|
13
mouse.h
Executable file
13
mouse.h
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
/*** M O U S E ***/
|
||||||
|
typedef struct {
|
||||||
|
unsigned int x;
|
||||||
|
unsigned int y;
|
||||||
|
unsigned int buttons;
|
||||||
|
} Mouse_t;
|
||||||
|
|
||||||
|
extern Mouse_t MOUSE;
|
||||||
|
|
||||||
|
void mouse_init();
|
||||||
|
|
||||||
|
#define mouse_hide() asm { mov ax, 02h; int 33h }
|
||||||
|
#define mouse_show() asm { mov ax, 01h; int 33h }
|
701
testbed.c
701
testbed.c
|
@ -2,677 +2,14 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dos.h>
|
#include <dos.h>
|
||||||
|
|
||||||
/*** V I D E O ***/
|
#include "video.h"
|
||||||
#define setMode(hexval) asm { mov ax, hexval; int 10h }
|
#include "kbd.h"
|
||||||
|
#include "mouse.h"
|
||||||
#define setVGAMode() setMode(0013h)
|
#include "tiff.h"
|
||||||
#define setEGAMode() setMode(000Dh)
|
#include "tiles.h"
|
||||||
#define setTextMode() setMode(0003h)
|
|
||||||
|
|
||||||
#define REG_AC 0x03c0
|
|
||||||
#define REG_TS 0x03c4
|
|
||||||
#define REG_GDC 0x03ce
|
|
||||||
#define REG_CRTC 0x03d4
|
|
||||||
|
|
||||||
#define PLANE_B 0x00
|
|
||||||
#define PLANE_G 0x01
|
|
||||||
#define PLANE_R 0x02
|
|
||||||
#define PLANE_I 0x03
|
|
||||||
#define setPlane(p) outport(REG_TS, 2 | (0x100 << p))
|
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setWriteMode(m) outport(REG_GDC, 0x05 | m << 8)
|
|
||||||
void setSplitScreen(unsigned int y) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHorizontalPan(int offset) {
|
|
||||||
inp(0x3da); // INPUT_STATUS_1?
|
|
||||||
outp(REG_AC, 0x13 | 0x20);
|
|
||||||
outp(REG_AC, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
void kbd_cleanup() {
|
|
||||||
if (oldKbdISR != NULL) {
|
|
||||||
setvect(KBD_INT, oldKbdISR);
|
|
||||||
oldKbdISR = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volatile char keybuf[128];
|
|
||||||
volatile char kbd_triggered = 0;
|
|
||||||
|
|
||||||
void interrupt kbd_isr() {
|
|
||||||
unsigned char raw;
|
|
||||||
char ctl;
|
|
||||||
|
|
||||||
asm sti;
|
|
||||||
raw = inp(0x60);
|
|
||||||
ctl = inp(0x61) | 0x82;
|
|
||||||
outp(0x61, ctl);
|
|
||||||
outp(0x61, ctl & 0x7f);
|
|
||||||
outp(0x20, 0x20);
|
|
||||||
|
|
||||||
if (raw & 0x80) {
|
|
||||||
keybuf[raw & 0x7f] = 0;
|
|
||||||
} else {
|
|
||||||
keybuf[raw] = 1;
|
|
||||||
}
|
|
||||||
kbd_triggered = raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define K_ESC 1
|
|
||||||
#define K_1 2
|
|
||||||
#define K_2 3
|
|
||||||
#define K_3 4
|
|
||||||
#define K_4 5
|
|
||||||
#define K_5 6
|
|
||||||
#define K_6 7
|
|
||||||
#define K_7 8
|
|
||||||
#define K_8 9
|
|
||||||
#define K_9 10
|
|
||||||
#define K_0 11
|
|
||||||
#define K_MINUS 12
|
|
||||||
#define K_EQUAL 13
|
|
||||||
#define K_BKSP 14
|
|
||||||
#define K_TAB 15
|
|
||||||
#define K_Q 16
|
|
||||||
#define K_W 17
|
|
||||||
#define K_E 18
|
|
||||||
#define K_R 19
|
|
||||||
#define K_T 20
|
|
||||||
#define K_Y 21
|
|
||||||
#define K_U 22
|
|
||||||
#define K_I 23
|
|
||||||
#define K_O 24
|
|
||||||
#define K_P 25
|
|
||||||
#define K_LBRK 26
|
|
||||||
#define K_RBRK 27
|
|
||||||
#define K_ENTER 28
|
|
||||||
#define K_CTRL 29
|
|
||||||
#define K_A 30
|
|
||||||
#define K_S 31
|
|
||||||
#define K_D 32
|
|
||||||
#define K_F 33
|
|
||||||
#define K_G 34
|
|
||||||
#define K_H 35
|
|
||||||
#define K_J 36
|
|
||||||
#define K_K 37
|
|
||||||
#define K_L 38
|
|
||||||
#define K_SEMI 39
|
|
||||||
#define K_APOS 40
|
|
||||||
#define K_TILDE 41
|
|
||||||
#define K_LSHFT 42
|
|
||||||
#define K_BSLSH 43
|
|
||||||
#define K_Z 44
|
|
||||||
#define K_X 45
|
|
||||||
#define K_C 46
|
|
||||||
#define K_V 47
|
|
||||||
#define K_B 48
|
|
||||||
#define K_N 49
|
|
||||||
#define K_M 50
|
|
||||||
#define K_COMMA 51
|
|
||||||
#define K_DOT 52
|
|
||||||
#define K_SLASH 53
|
|
||||||
#define K_RSHFT 54
|
|
||||||
#define K_PSCRN 55
|
|
||||||
#define K_ALT 56
|
|
||||||
#define K_SPACE 57
|
|
||||||
#define K_CAPS 58
|
|
||||||
#define K_F1 59
|
|
||||||
#define K_F2 60
|
|
||||||
#define K_F3 61
|
|
||||||
#define K_F4 62
|
|
||||||
#define K_F5 63
|
|
||||||
#define K_F6 64
|
|
||||||
#define K_F7 65
|
|
||||||
#define K_F8 66
|
|
||||||
#define K_F9 67
|
|
||||||
#define K_F10 68
|
|
||||||
#define K_NUMLK 69
|
|
||||||
#define K_SCRL 70
|
|
||||||
#define K_HOME 71
|
|
||||||
#define K_UP 72
|
|
||||||
#define K_PGUP 73
|
|
||||||
#define K_NDASH 74
|
|
||||||
#define K_LEFT 75
|
|
||||||
#define K_CENT 76
|
|
||||||
#define K_RIGHT 77
|
|
||||||
#define K_NPLUS 78
|
|
||||||
#define K_END 79
|
|
||||||
#define K_DOWN 80
|
|
||||||
#define K_PGDN 81
|
|
||||||
#define K_INS 82
|
|
||||||
#define K_DEL 83
|
|
||||||
#define K_F11 87
|
|
||||||
#define K_F12 88
|
|
||||||
#define keyPressed(k) keybuf[k]
|
|
||||||
|
|
||||||
unsigned char kbd_wait() {
|
|
||||||
kbd_triggered = 0;
|
|
||||||
while (!kbd_triggered) {}
|
|
||||||
return kbd_triggered;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kbd_init() {
|
|
||||||
if (oldKbdISR == NULL) {
|
|
||||||
memset(keybuf, 0, 128);
|
|
||||||
oldKbdISR = getvect(KBD_INT);
|
|
||||||
setvect(KBD_INT, kbd_isr);
|
|
||||||
atexit(kbd_cleanup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** M O U S E ***/
|
|
||||||
struct {
|
|
||||||
unsigned int x;
|
|
||||||
unsigned int y;
|
|
||||||
unsigned int buttons;
|
|
||||||
} MOUSE;
|
|
||||||
|
|
||||||
void far mouse_callback() {
|
|
||||||
asm {
|
|
||||||
mov ax, DGROUP
|
|
||||||
mov ds, ax
|
|
||||||
shr cx, 1
|
|
||||||
mov MOUSE.x, cx
|
|
||||||
mov MOUSE.y, dx
|
|
||||||
mov MOUSE.buttons, bx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mouse_cleanup() {
|
|
||||||
//uninstall handler
|
|
||||||
asm {
|
|
||||||
mov ax, 0ch
|
|
||||||
mov dx, 0
|
|
||||||
mov es, dx
|
|
||||||
mov cx, 0
|
|
||||||
int 33h
|
|
||||||
|
|
||||||
xor ax, ax
|
|
||||||
int 33h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mouse_init() {
|
|
||||||
unsigned seg_mouse_callback = FP_SEG(mouse_callback);
|
|
||||||
unsigned off_mouse_callback = FP_OFF(mouse_callback);
|
|
||||||
unsigned int result;
|
|
||||||
asm {
|
|
||||||
xor ax, ax
|
|
||||||
int 33h
|
|
||||||
mov result, ax
|
|
||||||
}
|
|
||||||
if (result == 0) {
|
|
||||||
printf("Mouse driver not installed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
atexit(mouse_cleanup);
|
|
||||||
|
|
||||||
asm {
|
|
||||||
mov ax, seg_mouse_callback
|
|
||||||
mov es, ax
|
|
||||||
mov dx, off_mouse_callback
|
|
||||||
mov ax, 0ch
|
|
||||||
mov cx, 1fh
|
|
||||||
int 33h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define mouse_hide() asm { mov ax, 02h; int 33h }
|
|
||||||
#define mouse_show() asm { mov ax, 01h; int 33h }
|
|
||||||
|
|
||||||
/*** T I F F ***/
|
|
||||||
typedef struct {
|
|
||||||
unsigned int endian;
|
|
||||||
unsigned int version;
|
|
||||||
unsigned long ifdOffset;
|
|
||||||
} TifHeader_t;
|
|
||||||
|
|
||||||
#define TIF_WIDTH 256
|
|
||||||
#define TIF_HEIGHT 257
|
|
||||||
#define TIF_BITSPERSAMPLE 258
|
|
||||||
#define TIF_COMPRESSION 259
|
|
||||||
#define TIF_STRIPOFFSETS 273
|
|
||||||
#define TIF_ROWSPERSTRIP 278
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned int id;
|
|
||||||
unsigned int dataType;
|
|
||||||
unsigned long dataCount;
|
|
||||||
unsigned long dataOffset;
|
|
||||||
} TifTag_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned int width;
|
|
||||||
unsigned int height;
|
|
||||||
unsigned long rowsPerStrip;
|
|
||||||
unsigned long stripCount;
|
|
||||||
unsigned long stripOffsets;
|
|
||||||
} TifImageMeta_t;
|
|
||||||
|
|
||||||
TifImageMeta_t tifLoadMeta(FILE *f) {
|
|
||||||
TifImageMeta_t meta = {0, 0, 0, 0, 0};
|
|
||||||
TifHeader_t header;
|
|
||||||
TifTag_t tag;
|
|
||||||
unsigned int i, tagCount;
|
|
||||||
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
fread(&header, 8, 1, f);
|
|
||||||
|
|
||||||
if (header.endian != 0x4949 || header.version != 0x2a) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
fseek(f, header.ifdOffset, SEEK_SET);
|
|
||||||
fread(&tagCount, 2, 1, f);
|
|
||||||
for (i = 0; i < tagCount; i ++) {
|
|
||||||
fread(&tag, 12, 1, f);
|
|
||||||
if (tag.id == TIF_WIDTH) {
|
|
||||||
meta.width = tag.dataOffset;
|
|
||||||
} else if (tag.id == TIF_HEIGHT) {
|
|
||||||
meta.height = tag.dataOffset;
|
|
||||||
} else if (tag.id == TIF_BITSPERSAMPLE) {
|
|
||||||
if (tag.dataOffset != 4) goto fail;
|
|
||||||
} else if (tag.id == TIF_COMPRESSION) {
|
|
||||||
if (tag.dataOffset != 1) goto fail;
|
|
||||||
} else if (tag.id == TIF_STRIPOFFSETS) {
|
|
||||||
meta.stripCount = tag.dataCount;
|
|
||||||
meta.stripOffsets = tag.dataOffset;
|
|
||||||
} else if (tag.id == TIF_ROWSPERSTRIP) {
|
|
||||||
meta.rowsPerStrip = tag.dataOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return meta;
|
|
||||||
fail:
|
|
||||||
meta.stripCount = 0;
|
|
||||||
return meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_WIDTH 320
|
|
||||||
|
|
||||||
int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, unsigned int w) {
|
|
||||||
int istrip;
|
|
||||||
int irow;
|
|
||||||
int ipixelpair;
|
|
||||||
int y = 0;
|
|
||||||
unsigned long offset;
|
|
||||||
unsigned char rowData[MAX_WIDTH >> 1];
|
|
||||||
volatile unsigned char far *out = &VID[vidOffset];
|
|
||||||
unsigned char b, g, r, i;
|
|
||||||
|
|
||||||
if (meta.width > MAX_WIDTH || (meta.width % 16) != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
setWriteMode(0);
|
|
||||||
|
|
||||||
for (istrip = 0; istrip < meta.stripCount; istrip ++) {
|
|
||||||
fseek(f, meta.stripOffsets + (istrip << 2), SEEK_SET);
|
|
||||||
fread(&offset, 4, 1, f);
|
|
||||||
fseek(f, offset, SEEK_SET);
|
|
||||||
|
|
||||||
for (irow = 0; irow < meta.rowsPerStrip; irow ++) {
|
|
||||||
int ipixelpairLim = meta.width >> 1;
|
|
||||||
fread(rowData, 1, ipixelpairLim, f);
|
|
||||||
b = g = r = i = 0;
|
|
||||||
for (ipixelpair = 0; ipixelpair < ipixelpairLim; ipixelpair ++) {
|
|
||||||
unsigned char pixelpair = rowData[ipixelpair];
|
|
||||||
int bpair = (pixelpair & 0x01) | (pixelpair & 0x10) >> 3;
|
|
||||||
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;
|
|
||||||
|
|
||||||
b |= bpair << shift;
|
|
||||||
g |= gpair << shift;
|
|
||||||
r |= rpair << shift;
|
|
||||||
i |= ipair << shift;
|
|
||||||
|
|
||||||
if (shift == 0 || ipixelpair == ipixelpairLim - 1) {
|
|
||||||
// todo: use write mode 2, this is slooww
|
|
||||||
setPlane(PLANE_B); *out = b;
|
|
||||||
setPlane(PLANE_R); *out = r;
|
|
||||||
setPlane(PLANE_G); *out = g;
|
|
||||||
setPlane(PLANE_I); *out = i;
|
|
||||||
out ++;
|
|
||||||
b = g = r = i = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
y++;
|
|
||||||
if (y == maxY) {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
out += (w - meta.width) >> 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int yRepeat, int planes) {
|
|
||||||
int istrip;
|
|
||||||
int irow;
|
|
||||||
int ipixelpair;
|
|
||||||
int y = 0;
|
|
||||||
unsigned long offset;
|
|
||||||
unsigned char rowData[MAX_WIDTH >> 1];
|
|
||||||
unsigned int planeStride = (meta.width >> 4) * yRepeat;
|
|
||||||
unsigned int *bp = planeBuf;
|
|
||||||
unsigned int *gp = bp + planeStride;
|
|
||||||
unsigned int *rp = gp + planeStride;
|
|
||||||
unsigned int *ip = rp + planeStride;
|
|
||||||
unsigned int *mp = ip + planeStride;
|
|
||||||
unsigned int bv, gv, rv, iv;
|
|
||||||
|
|
||||||
if (meta.width > MAX_WIDTH || (meta.width % 16) != 0 || planes < 4 || planes > 5) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (istrip = 0; istrip < meta.stripCount; istrip ++) {
|
|
||||||
fseek(f, meta.stripOffsets + (istrip << 2), SEEK_SET);
|
|
||||||
fread(&offset, 4, 1, f);
|
|
||||||
fseek(f, offset, SEEK_SET);
|
|
||||||
|
|
||||||
for (irow = 0; irow < meta.rowsPerStrip; irow ++) {
|
|
||||||
int ipixelpairLim = meta.width >> 1;
|
|
||||||
fread(rowData, 1, ipixelpairLim, f);
|
|
||||||
bv = gv = rv = iv = 0;
|
|
||||||
for (ipixelpair = 0; ipixelpair < ipixelpairLim; ipixelpair ++) {
|
|
||||||
unsigned char pixelpair = rowData[ipixelpair];
|
|
||||||
int bpair = (pixelpair & 0x01) | (pixelpair & 0x10) >> 3;
|
|
||||||
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 = (7 - (ipixelpair % 8)) << 1;
|
|
||||||
|
|
||||||
bv |= bpair << shift;
|
|
||||||
gv |= gpair << shift;
|
|
||||||
rv |= rpair << shift;
|
|
||||||
iv |= ipair << shift;
|
|
||||||
|
|
||||||
if (shift == 0 || ipixelpair == ipixelpairLim - 1) {
|
|
||||||
*bp++ = bv;
|
|
||||||
*gp++ = gv;
|
|
||||||
*rp++ = rv;
|
|
||||||
*ip++ = iv;
|
|
||||||
if (planes == 5) {
|
|
||||||
iv = ~(bv & gv & rv & iv);
|
|
||||||
*mp++ = iv;
|
|
||||||
}
|
|
||||||
bv = gv = rv = iv = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
y++;
|
|
||||||
if (y == maxY) {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
if (y % yRepeat == 0) {
|
|
||||||
bp += planeStride * (planes - 1);
|
|
||||||
gp += planeStride * (planes - 1);
|
|
||||||
rp += planeStride * (planes - 1);
|
|
||||||
ip += planeStride * (planes - 1);
|
|
||||||
mp += planeStride * (planes - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** 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 14
|
|
||||||
#define PAGE_TILES_COUNT (PAGE_TILES_H * PAGE_TILES_W)
|
|
||||||
#define PAGE_STRIDE (PAGE_TILES_W << 1)
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#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 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, { 0x0600, 0x2B00 }, 0, 0, NULL, NULL,
|
|
||||||
0, 0, 0, 0, 0 };
|
|
||||||
|
|
||||||
void loadTiles(unsigned int tilesOffset, unsigned int *memTiles) {
|
|
||||||
screen.tilesOffset = tilesOffset;
|
|
||||||
screen.memTiles = memTiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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(ibuffer);
|
|
||||||
*dirty = ibuffer;
|
|
||||||
memcpy(screen.buffer[ibuffer], &screen.memTiles[tile * BUF_WSIZE], BUF_WSIZE << 1);
|
|
||||||
screen.bufferOffset[ibuffer] = screen.pageOffset[screen.currentPage]
|
|
||||||
+ (pageX << 1) + (pageY * PAGE_STRIDE * 16);
|
|
||||||
}
|
|
||||||
return *dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ||
|
|
||||||
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[BUF_WSTRIDE * 4];
|
|
||||||
if (shift < 0) {
|
|
||||||
shift = -shift;
|
|
||||||
for (plane = 0; plane < 4; plane ++) {
|
|
||||||
for (y = 0; y < h; y ++) {
|
|
||||||
maskval = mask[y] << shift;
|
|
||||||
buf[y] = (buf[y] & ~maskval) | ((sprite[y] << shift) & maskval);
|
|
||||||
}
|
|
||||||
sprite += BUF_WSTRIDE;
|
|
||||||
buf += BUF_WSTRIDE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (plane = 0; plane < 4; plane ++) {
|
|
||||||
for (y = 0; y < h; y ++) {
|
|
||||||
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) {
|
|
||||||
int pageX = (int)(x - (screen.scrollX & 0xfff0)) >> 4;
|
|
||||||
int pageY = (int)(y - (screen.scrollY & 0xfff0)) >> 4;
|
|
||||||
int pageOffsetX = x & 0x0f;
|
|
||||||
int pageOffsetY = y & 0x0f;
|
|
||||||
|
|
||||||
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 newX, int newY) {
|
|
||||||
newX = min(max(newX, 0), (screen.w << 4) - 320);
|
|
||||||
newY = min(max(newY, 0), (screen.h << 4) - 200);
|
|
||||||
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 = newX;
|
|
||||||
screen.scrollY = newY;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawScreen() {
|
|
||||||
unsigned int startX = screen.scrollX >> 4;
|
|
||||||
unsigned int startY = screen.scrollY >> 4;
|
|
||||||
unsigned int offsetX = screen.scrollX - (startX << 4);
|
|
||||||
unsigned int offsetY = screen.scrollY - (startY << 4);
|
|
||||||
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, bmp;
|
|
||||||
|
|
||||||
setAllPlanes();
|
|
||||||
setWriteMode(1);
|
|
||||||
|
|
||||||
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)] << 5),
|
|
||||||
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 ++) {
|
|
||||||
bmp = screen.buffer[di][y + (BUF_WSTRIDE * plane)];
|
|
||||||
WVID[drawOffset] = (bmp << 8) | (bmp >> 8);
|
|
||||||
drawOffset += PAGE_STRIDE >> 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setAllPlanes();
|
|
||||||
setDisplayOffset(scrollOffset);
|
|
||||||
setHorizontalPan(screen.scrollX & 0x07);
|
|
||||||
|
|
||||||
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
|
#define NUM_TILES 128
|
||||||
#define NUM_SPRITES 64
|
#define NUM_SPRITES 64
|
||||||
#define OFF_TILES 0x5000
|
#define OFF_TILES 0x5000
|
||||||
|
@ -681,7 +18,6 @@ void drawScreen() {
|
||||||
unsigned int tiles[NUM_TILES * TILE_STRIDE];
|
unsigned int tiles[NUM_TILES * TILE_STRIDE];
|
||||||
unsigned int sprites[NUM_SPRITES * SPRITE_STRIDE];
|
unsigned int sprites[NUM_SPRITES * SPRITE_STRIDE];
|
||||||
|
|
||||||
|
|
||||||
unsigned char map[10000];
|
unsigned char map[10000];
|
||||||
|
|
||||||
void fillMap() {
|
void fillMap() {
|
||||||
|
@ -719,16 +55,15 @@ void drawEntity(Entity_t *entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void playerThink(Entity_t *self) {
|
void playerThink(Entity_t *self) {
|
||||||
if (keyPressed(K_LEFT)) { self->x -= 3; self->dir = DIR_W; }
|
if (keyIsDown(K_LEFT)) { self->x -= 3; self->dir = DIR_W; }
|
||||||
if (keyPressed(K_RIGHT)) { self->x += 3; self->dir = DIR_E; }
|
if (keyIsDown(K_RIGHT)) { self->x += 3; self->dir = DIR_E; }
|
||||||
if (keyPressed(K_UP)) { self->y -= 3; self->dir = DIR_N; }
|
if (keyIsDown(K_UP)) { self->y -= 3; self->dir = DIR_N; }
|
||||||
if (keyPressed(K_DOWN)) { self->y += 3; self->dir = DIR_S; }
|
if (keyIsDown(K_DOWN)) { self->y += 3; self->dir = DIR_S; }
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int dy;
|
int dy;
|
||||||
int y;
|
int y;
|
||||||
int debounce;
|
|
||||||
} Footer_t;
|
} Footer_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -756,6 +91,8 @@ void game_init() {
|
||||||
setEGAMode();
|
setEGAMode();
|
||||||
atexit(vid_cleanup);
|
atexit(vid_cleanup);
|
||||||
|
|
||||||
|
kbd_init();
|
||||||
|
|
||||||
tile_init();
|
tile_init();
|
||||||
fillMap();
|
fillMap();
|
||||||
|
|
||||||
|
@ -775,8 +112,6 @@ void game_init() {
|
||||||
tifLoad(f, meta, sprites, NUM_SPRITES * 16, 16, 5);
|
tifLoad(f, meta, sprites, NUM_SPRITES * 16, 16, 5);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
// setSplitScreen(351);
|
|
||||||
|
|
||||||
loadTiles(OFF_TILES, tiles);
|
loadTiles(OFF_TILES, tiles);
|
||||||
loadMap(map, 100, 100);
|
loadMap(map, 100, 100);
|
||||||
scroll(0, 0);
|
scroll(0, 0);
|
||||||
|
@ -784,22 +119,18 @@ void game_init() {
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
game_init();
|
game_init();
|
||||||
kbd_init();
|
|
||||||
|
|
||||||
while (!keyPressed(K_ESC)) {
|
while (!keyIsDown(K_ESC)) {
|
||||||
|
kbd_debounce();
|
||||||
if (game.state == STATE_MAP) {
|
if (game.state == STATE_MAP) {
|
||||||
if (keyPressed(K_SPACE)) {
|
if (keyWasPressed(K_SPACE)) {
|
||||||
game.state = STATE_DIALOG;
|
game.state = STATE_DIALOG;
|
||||||
game.footer.debounce = 1;
|
|
||||||
game.footer.dy = 1;
|
game.footer.dy = 1;
|
||||||
}
|
}
|
||||||
playerThink(&game.player);
|
playerThink(&game.player);
|
||||||
scroll(game.player.x - 152, game.player.y - 92);
|
scroll(game.player.x - 152, game.player.y - 92);
|
||||||
} else if (game.state == STATE_DIALOG) {
|
} else if (game.state == STATE_DIALOG) {
|
||||||
if (game.footer.debounce && !keyPressed(K_SPACE)) {
|
if (keyWasPressed(K_SPACE)) {
|
||||||
game.footer.debounce = 0;
|
|
||||||
}
|
|
||||||
if (!game.footer.debounce && keyPressed(K_SPACE)) {
|
|
||||||
game.footer.dy = -1;
|
game.footer.dy = -1;
|
||||||
}
|
}
|
||||||
game.footer.y += game.footer.dy;
|
game.footer.y += game.footer.dy;
|
||||||
|
|
187
tiff.c
Executable file
187
tiff.c
Executable file
|
@ -0,0 +1,187 @@
|
||||||
|
#include <dos.h>
|
||||||
|
#include "tiff.h"
|
||||||
|
#include "video.h"
|
||||||
|
|
||||||
|
/*** T I F F ***/
|
||||||
|
typedef struct {
|
||||||
|
unsigned int endian;
|
||||||
|
unsigned int version;
|
||||||
|
unsigned long ifdOffset;
|
||||||
|
} TifHeader_t;
|
||||||
|
|
||||||
|
#define TIF_WIDTH 256
|
||||||
|
#define TIF_HEIGHT 257
|
||||||
|
#define TIF_BITSPERSAMPLE 258
|
||||||
|
#define TIF_COMPRESSION 259
|
||||||
|
#define TIF_STRIPOFFSETS 273
|
||||||
|
#define TIF_ROWSPERSTRIP 278
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int dataType;
|
||||||
|
unsigned long dataCount;
|
||||||
|
unsigned long dataOffset;
|
||||||
|
} TifTag_t;
|
||||||
|
|
||||||
|
TifImageMeta_t tifLoadMeta(FILE *f) {
|
||||||
|
TifImageMeta_t meta = {0, 0, 0, 0, 0};
|
||||||
|
TifHeader_t header;
|
||||||
|
TifTag_t tag;
|
||||||
|
unsigned int i, tagCount;
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
fread(&header, 8, 1, f);
|
||||||
|
|
||||||
|
if (header.endian != 0x4949 || header.version != 0x2a) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
fseek(f, header.ifdOffset, SEEK_SET);
|
||||||
|
fread(&tagCount, 2, 1, f);
|
||||||
|
for (i = 0; i < tagCount; i ++) {
|
||||||
|
fread(&tag, 12, 1, f);
|
||||||
|
if (tag.id == TIF_WIDTH) {
|
||||||
|
meta.width = tag.dataOffset;
|
||||||
|
} else if (tag.id == TIF_HEIGHT) {
|
||||||
|
meta.height = tag.dataOffset;
|
||||||
|
} else if (tag.id == TIF_BITSPERSAMPLE) {
|
||||||
|
if (tag.dataOffset != 4) goto fail;
|
||||||
|
} else if (tag.id == TIF_COMPRESSION) {
|
||||||
|
if (tag.dataOffset != 1) goto fail;
|
||||||
|
} else if (tag.id == TIF_STRIPOFFSETS) {
|
||||||
|
meta.stripCount = tag.dataCount;
|
||||||
|
meta.stripOffsets = tag.dataOffset;
|
||||||
|
} else if (tag.id == TIF_ROWSPERSTRIP) {
|
||||||
|
meta.rowsPerStrip = tag.dataOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return meta;
|
||||||
|
fail:
|
||||||
|
meta.stripCount = 0;
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, unsigned int w) {
|
||||||
|
int istrip;
|
||||||
|
int irow;
|
||||||
|
int ipixelpair;
|
||||||
|
int y = 0;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned char rowData[MAX_WIDTH >> 1];
|
||||||
|
volatile unsigned char far *out = &VID[vidOffset];
|
||||||
|
unsigned char b, g, r, i;
|
||||||
|
|
||||||
|
if (meta.width > MAX_WIDTH || (meta.width % 16) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
setWriteMode(0);
|
||||||
|
|
||||||
|
for (istrip = 0; istrip < meta.stripCount; istrip ++) {
|
||||||
|
fseek(f, meta.stripOffsets + (istrip << 2), SEEK_SET);
|
||||||
|
fread(&offset, 4, 1, f);
|
||||||
|
fseek(f, offset, SEEK_SET);
|
||||||
|
|
||||||
|
for (irow = 0; irow < meta.rowsPerStrip; irow ++) {
|
||||||
|
int ipixelpairLim = meta.width >> 1;
|
||||||
|
fread(rowData, 1, ipixelpairLim, f);
|
||||||
|
b = g = r = i = 0;
|
||||||
|
for (ipixelpair = 0; ipixelpair < ipixelpairLim; ipixelpair ++) {
|
||||||
|
unsigned char pixelpair = rowData[ipixelpair];
|
||||||
|
int bpair = (pixelpair & 0x01) | (pixelpair & 0x10) >> 3;
|
||||||
|
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;
|
||||||
|
|
||||||
|
b |= bpair << shift;
|
||||||
|
g |= gpair << shift;
|
||||||
|
r |= rpair << shift;
|
||||||
|
i |= ipair << shift;
|
||||||
|
|
||||||
|
if (shift == 0 || ipixelpair == ipixelpairLim - 1) {
|
||||||
|
// todo: use write mode 2, this is slooww
|
||||||
|
setPlane(PLANE_B); *out = b;
|
||||||
|
setPlane(PLANE_R); *out = r;
|
||||||
|
setPlane(PLANE_G); *out = g;
|
||||||
|
setPlane(PLANE_I); *out = i;
|
||||||
|
out ++;
|
||||||
|
b = g = r = i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y++;
|
||||||
|
if (y == maxY) {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
out += (w - meta.width) >> 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int yRepeat, int planes) {
|
||||||
|
int istrip;
|
||||||
|
int irow;
|
||||||
|
int ipixelpair;
|
||||||
|
int y = 0;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned char rowData[MAX_WIDTH >> 1];
|
||||||
|
unsigned int planeStride = (meta.width >> 4) * yRepeat;
|
||||||
|
unsigned int *bp = planeBuf;
|
||||||
|
unsigned int *gp = bp + planeStride;
|
||||||
|
unsigned int *rp = gp + planeStride;
|
||||||
|
unsigned int *ip = rp + planeStride;
|
||||||
|
unsigned int *mp = ip + planeStride;
|
||||||
|
unsigned int bv, gv, rv, iv;
|
||||||
|
|
||||||
|
if (meta.width > MAX_WIDTH || (meta.width % 16) != 0 || planes < 4 || planes > 5) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (istrip = 0; istrip < meta.stripCount; istrip ++) {
|
||||||
|
fseek(f, meta.stripOffsets + (istrip << 2), SEEK_SET);
|
||||||
|
fread(&offset, 4, 1, f);
|
||||||
|
fseek(f, offset, SEEK_SET);
|
||||||
|
|
||||||
|
for (irow = 0; irow < meta.rowsPerStrip; irow ++) {
|
||||||
|
int ipixelpairLim = meta.width >> 1;
|
||||||
|
fread(rowData, 1, ipixelpairLim, f);
|
||||||
|
bv = gv = rv = iv = 0;
|
||||||
|
for (ipixelpair = 0; ipixelpair < ipixelpairLim; ipixelpair ++) {
|
||||||
|
unsigned char pixelpair = rowData[ipixelpair];
|
||||||
|
int bpair = (pixelpair & 0x01) | (pixelpair & 0x10) >> 3;
|
||||||
|
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 = (7 - (ipixelpair % 8)) << 1;
|
||||||
|
|
||||||
|
bv |= bpair << shift;
|
||||||
|
gv |= gpair << shift;
|
||||||
|
rv |= rpair << shift;
|
||||||
|
iv |= ipair << shift;
|
||||||
|
|
||||||
|
if (shift == 0 || ipixelpair == ipixelpairLim - 1) {
|
||||||
|
*bp++ = bv;
|
||||||
|
*gp++ = gv;
|
||||||
|
*rp++ = rv;
|
||||||
|
*ip++ = iv;
|
||||||
|
if (planes == 5) {
|
||||||
|
iv = ~(bv & gv & rv & iv);
|
||||||
|
*mp++ = iv;
|
||||||
|
}
|
||||||
|
bv = gv = rv = iv = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y++;
|
||||||
|
if (y == maxY) {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
if (y % yRepeat == 0) {
|
||||||
|
bp += planeStride * (planes - 1);
|
||||||
|
gp += planeStride * (planes - 1);
|
||||||
|
rp += planeStride * (planes - 1);
|
||||||
|
ip += planeStride * (planes - 1);
|
||||||
|
mp += planeStride * (planes - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
17
tiff.h
Executable file
17
tiff.h
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*** T I F F ***/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned long rowsPerStrip;
|
||||||
|
unsigned long stripCount;
|
||||||
|
unsigned long stripOffsets;
|
||||||
|
} TifImageMeta_t;
|
||||||
|
|
||||||
|
#define MAX_WIDTH 320
|
||||||
|
|
||||||
|
TifImageMeta_t tifLoadMeta(FILE *f);
|
||||||
|
int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, unsigned int w);
|
||||||
|
int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int yRepeat, int planes);
|
222
tiles.c
Executable file
222
tiles.c
Executable file
|
@ -0,0 +1,222 @@
|
||||||
|
#include <dos.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "video.h"
|
||||||
|
|
||||||
|
/*** 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 14
|
||||||
|
#define PAGE_TILES_COUNT (PAGE_TILES_H * PAGE_TILES_W)
|
||||||
|
#define PAGE_STRIDE (PAGE_TILES_W << 1)
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 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, { 0x0600, 0x2B00 }, 0, 0, NULL, NULL,
|
||||||
|
0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
void loadTiles(unsigned int tilesOffset, unsigned int *memTiles) {
|
||||||
|
screen.tilesOffset = tilesOffset;
|
||||||
|
screen.memTiles = memTiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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(ibuffer);
|
||||||
|
*dirty = ibuffer;
|
||||||
|
memcpy(screen.buffer[ibuffer], &screen.memTiles[tile * BUF_WSIZE], BUF_WSIZE << 1);
|
||||||
|
screen.bufferOffset[ibuffer] = screen.pageOffset[screen.currentPage]
|
||||||
|
+ (pageX << 1) + (pageY * PAGE_STRIDE * 16);
|
||||||
|
}
|
||||||
|
return *dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ||
|
||||||
|
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[BUF_WSTRIDE * 4];
|
||||||
|
if (shift < 0) {
|
||||||
|
shift = -shift;
|
||||||
|
for (plane = 0; plane < 4; plane ++) {
|
||||||
|
for (y = 0; y < h; y ++) {
|
||||||
|
maskval = mask[y] << shift;
|
||||||
|
buf[y] = (buf[y] & ~maskval) | ((sprite[y] << shift) & maskval);
|
||||||
|
}
|
||||||
|
sprite += BUF_WSTRIDE;
|
||||||
|
buf += BUF_WSTRIDE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (plane = 0; plane < 4; plane ++) {
|
||||||
|
for (y = 0; y < h; y ++) {
|
||||||
|
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) {
|
||||||
|
int pageX = (int)(x - (screen.scrollX & 0xfff0)) >> 4;
|
||||||
|
int pageY = (int)(y - (screen.scrollY & 0xfff0)) >> 4;
|
||||||
|
int pageOffsetX = x & 0x0f;
|
||||||
|
int pageOffsetY = y & 0x0f;
|
||||||
|
|
||||||
|
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 newX, int newY) {
|
||||||
|
newX = min(max(newX, 0), (screen.w << 4) - 320);
|
||||||
|
newY = min(max(newY, 0), (screen.h << 4) - 200);
|
||||||
|
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 = newX;
|
||||||
|
screen.scrollY = newY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawScreen() {
|
||||||
|
unsigned int startX = screen.scrollX >> 4;
|
||||||
|
unsigned int startY = screen.scrollY >> 4;
|
||||||
|
unsigned int offsetX = screen.scrollX - (startX << 4);
|
||||||
|
unsigned int offsetY = screen.scrollY - (startY << 4);
|
||||||
|
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, bmp;
|
||||||
|
|
||||||
|
setAllPlanes();
|
||||||
|
setWriteMode(1);
|
||||||
|
|
||||||
|
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)] << 5),
|
||||||
|
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 ++) {
|
||||||
|
bmp = screen.buffer[di][y + (BUF_WSTRIDE * plane)];
|
||||||
|
WVID[drawOffset] = (bmp << 8) | (bmp >> 8);
|
||||||
|
drawOffset += PAGE_STRIDE >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setAllPlanes();
|
||||||
|
setDisplayOffset(scrollOffset);
|
||||||
|
setHorizontalPan(screen.scrollX & 0x07);
|
||||||
|
|
||||||
|
screen.currentPage ^= 1;
|
||||||
|
screen.firstBuffer = screen.nextBuffer;
|
||||||
|
for (di = 0; di < PAGE_TILES_COUNT; di ++) {
|
||||||
|
dirty[di] = isBufIndex(dirty[di]) ? D_BGTILE : D_NOTHING;
|
||||||
|
}
|
||||||
|
}
|
9
tiles.h
Executable file
9
tiles.h
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
/*** T I L E S ***/
|
||||||
|
|
||||||
|
void tile_init();
|
||||||
|
|
||||||
|
void loadTiles(unsigned int tilesOffset, unsigned int *memTiles);
|
||||||
|
void loadMap(unsigned char *map, unsigned int w, unsigned int h);
|
||||||
|
void drawSprite(unsigned int *sprite, int x, int y);
|
||||||
|
void scroll(int newX, int newY);
|
||||||
|
void drawScreen();
|
39
video.c
Executable file
39
video.c
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
#include <dos.h>
|
||||||
|
#include "video.h"
|
||||||
|
|
||||||
|
void vid_cleanup() {
|
||||||
|
setTextMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSplitScreen(unsigned int y) {
|
||||||
|
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 setDisplayOffset(unsigned int offset) {
|
||||||
|
outport(REG_CRTC, 0x0c | (offset & 0xff00));
|
||||||
|
outport(REG_CRTC, 0x0d | (offset << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHorizontalPan(int offset) {
|
||||||
|
inp(0x3da); // INPUT_STATUS_1?
|
||||||
|
outp(REG_AC, 0x13 | 0x20);
|
||||||
|
outp(REG_AC, offset);
|
||||||
|
}
|
||||||
|
|
34
video.h
Executable file
34
video.h
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
/*** V I D E O ***/
|
||||||
|
#define setMode(hexval) asm { mov ax, hexval; int 10h }
|
||||||
|
|
||||||
|
#define setVGAMode() setMode(0013h)
|
||||||
|
#define setEGAMode() setMode(000Dh)
|
||||||
|
#define setTextMode() setMode(0003h)
|
||||||
|
|
||||||
|
#define REG_AC 0x03c0
|
||||||
|
#define REG_TS 0x03c4
|
||||||
|
#define REG_GDC 0x03ce
|
||||||
|
#define REG_CRTC 0x03d4
|
||||||
|
|
||||||
|
#define PLANE_B 0x00
|
||||||
|
#define PLANE_G 0x01
|
||||||
|
#define PLANE_R 0x02
|
||||||
|
#define PLANE_I 0x03
|
||||||
|
#define setPlane(p) outport(REG_TS, 2 | (0x100 << p))
|
||||||
|
#define setAllPlanes() outport(REG_TS, 0x0f02)
|
||||||
|
|
||||||
|
#define setWriteMode(m) outport(REG_GDC, 0x05 | m << 8)
|
||||||
|
|
||||||
|
#define VID ((volatile char far *)MK_FP(0xa000, 0))
|
||||||
|
#define WVID ((volatile int far *)MK_FP(0xa000, 0))
|
||||||
|
|
||||||
|
#define flipPage(p) outport(REG_CRTC, 0x0c | (p << 8))
|
||||||
|
|
||||||
|
#define setLogicalWidth(w) outport(REG_CRTC, 0x13 | (w << 8))
|
||||||
|
|
||||||
|
void vid_cleanup();
|
||||||
|
void setSplitScreen(unsigned int y);
|
||||||
|
void unsetSplitScreen();
|
||||||
|
void setDisplayOffset(unsigned int offset);
|
||||||
|
void setHorizontalPan(int offset);
|
||||||
|
|
Loading…
Reference in a new issue