eobish
changeset 7:6a350c554e46
started DOS port
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 19 Jan 2015 15:49:14 +0200 |
parents | 0baf4e98315e |
children | c0e8bbf96849 |
files | Makefile.wat dos4gw.exe src/dos/dpmi.c src/dos/dpmi.h src/dos/inttypes.h src/dos/keyb.c src/dos/keyb.h src/dos/mouse.c src/dos/mouse.h src/dos/pit8254.h src/dos/scancode.h src/dos/timer.c src/dos/timer.h src/dos/vbe.c src/dos/vbe.h src/dos/vbegfx.c src/dos/vbegfx.h src/fblib.c src/fblibdos.c src/fblibsdl.c src/level.c src/tileset.c |
diffstat | 22 files changed, 1243 insertions(+), 15 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile.wat Mon Jan 19 15:49:14 2015 +0200 1.3 @@ -0,0 +1,39 @@ 1.4 +gameobj = main.obj player.obj level.obj rend.obj tileset.obj image.obj 1.5 +fblibobj = fblib.obj 1.6 +sysobj = vbe.obj dpmi.obj timer.obj mouse.obj keyb.obj 1.7 +obj = $(gameobj) $(fblibobj) $(sysobj) 1.8 +bin = eobish.exe 1.9 + 1.10 +def = -dFBLIB_VBE=1 1.11 +opt = -5 -fp5 -otexan 1.12 +dbg = -d1 1.13 + 1.14 +AS = nasm 1.15 +CC = wcc386 1.16 +CXX = wpp386 1.17 +ASFLAGS = -fobj 1.18 +CFLAGS = $(dbg) $(opt) $(def) -zq -bt=dos -Isrc\dos 1.19 +CXXFLAGS = $(CFLAGS) 1.20 +LD = wlink 1.21 + 1.22 +$(bin): $(obj) 1.23 + %write objects.lnk file { $(obj) } 1.24 + $(LD) debug all name $@ @objects $(LDFLAGS) 1.25 + 1.26 +.c: src 1.27 +.c: src\dos 1.28 +.cc: src 1.29 +.asm: src 1.30 + 1.31 +.c.obj: .autodepend 1.32 + $(CC) $(CFLAGS) $[* 1.33 + 1.34 +.cc.obj: .autodepend 1.35 + $(CXX) $(CXXFLAGS) $[* 1.36 + 1.37 +.asm.obj: 1.38 + $(AS) $(ASFLAGS) -o $@ $[*.asm 1.39 + 1.40 +clean: .symbolic 1.41 + del *.obj 1.42 + del $(bin)
2.1 Binary file dos4gw.exe has changed
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/dos/dpmi.c Mon Jan 19 15:49:14 2015 +0200 3.3 @@ -0,0 +1,55 @@ 3.4 +#include "dpmi.h" 3.5 + 3.6 +void dpmi_real_int(int inum, struct dpmi_real_regs *regs) 3.7 +{ 3.8 + unsigned char int_num = (unsigned char)inum; 3.9 + __asm { 3.10 + mov eax, 0x300 3.11 + mov edi, regs 3.12 + mov bl, int_num 3.13 + mov bh, 0 3.14 + xor ecx, ecx 3.15 + int 0x31 3.16 + } 3.17 +} 3.18 + 3.19 +void *dpmi_mmap(uint32_t phys_addr, unsigned int size) 3.20 +{ 3.21 + uint16_t mem_high, mem_low; 3.22 + uint16_t phys_high = phys_addr >> 16; 3.23 + uint16_t phys_low = phys_addr & 0xffff; 3.24 + uint16_t size_high = size >> 16; 3.25 + uint16_t size_low = size & 0xffff; 3.26 + unsigned int err, res = 0; 3.27 + 3.28 + __asm { 3.29 + mov eax, 0x800 3.30 + mov bx, phys_high 3.31 + mov cx, phys_low 3.32 + mov si, size_high 3.33 + mov di, size_low 3.34 + int 0x31 3.35 + add res, 1 3.36 + mov err, eax 3.37 + mov mem_high, bx 3.38 + mov mem_low, cx 3.39 + } 3.40 + 3.41 + if(res == 2) { 3.42 + return 0; 3.43 + } 3.44 + return (void*)(((uint32_t)mem_high << 16) | ((uint32_t)mem_low)); 3.45 +} 3.46 + 3.47 +void dpmi_munmap(void *addr) 3.48 +{ 3.49 + uint16_t mem_high = (uint32_t)addr >> 16; 3.50 + uint16_t mem_low = (uint16_t)addr; 3.51 + 3.52 + __asm { 3.53 + mov eax, 0x801 3.54 + mov bx, mem_high 3.55 + mov cx, mem_low 3.56 + int 0x31 3.57 + } 3.58 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/dos/dpmi.h Mon Jan 19 15:49:14 2015 +0200 4.3 @@ -0,0 +1,26 @@ 4.4 +#ifndef DPMI_H_ 4.5 +#define DPMI_H_ 4.6 + 4.7 +#include "inttypes.h" 4.8 + 4.9 +struct dpmi_real_regs { 4.10 + uint32_t edi, esi, ebp; 4.11 + uint32_t reserved; 4.12 + uint32_t ebx, edx, ecx, eax; 4.13 + uint16_t flags; 4.14 + uint16_t es, ds, fs, gs; 4.15 + uint16_t ip, cs, sp, ss; 4.16 +}; 4.17 + 4.18 +unsigned short dpmi_alloc(unsigned int par); 4.19 +#pragma aux dpmi_alloc = \ 4.20 + "mov eax, 0x100" \ 4.21 + "int 0x31" \ 4.22 + value[ax] parm[ebx]; 4.23 + 4.24 +void dpmi_real_int(int inum, struct dpmi_real_regs *regs); 4.25 + 4.26 +void *dpmi_mmap(uint32_t phys_addr, unsigned int size); 4.27 +void dpmi_munmap(void *addr); 4.28 + 4.29 +#endif /* DPMI_H_ */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/dos/inttypes.h Mon Jan 19 15:49:14 2015 +0200 5.3 @@ -0,0 +1,18 @@ 5.4 +#ifndef INT_TYPES_H_ 5.5 +#define INT_TYPES_H_ 5.6 + 5.7 +#if defined(__DOS__) || defined(WIN32) 5.8 +typedef char int8_t; 5.9 +typedef short int16_t; 5.10 +typedef long int32_t; 5.11 + 5.12 +typedef unsigned char uint8_t; 5.13 +typedef unsigned short uint16_t; 5.14 +typedef unsigned long uint32_t; 5.15 + 5.16 +typedef unsigned long intptr_t; 5.17 +#else 5.18 +#include <stdint.h> 5.19 +#endif 5.20 + 5.21 +#endif /* INT_TYPES_H_ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/dos/keyb.c Mon Jan 19 15:49:14 2015 +0200 6.3 @@ -0,0 +1,201 @@ 6.4 +/* 6.5 +DOS interrupt-based keyboard driver. 6.6 +Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org> 6.7 + 6.8 +This program is free software: you can redistribute it and/or modify 6.9 +it under the terms of the GNU General Public License as published by 6.10 +the Free Software Foundation, either version 3 of the License, or 6.11 +(at your option) any later version. 6.12 + 6.13 +This program is distributed in the hope that it will be useful, 6.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 6.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 6.16 +GNU General Public License for more details. 6.17 + 6.18 +You should have received a copy of the GNU General Public License 6.19 +along with the program. If not, see <http://www.gnu.org/licenses/> 6.20 +*/ 6.21 +#define KEYB_C_ 6.22 + 6.23 +#include <stdio.h> 6.24 +#include <stdlib.h> 6.25 +#include <string.h> 6.26 +#include <conio.h> 6.27 +#include <dos.h> 6.28 +#include <i86.h> 6.29 +#include "keyb.h" 6.30 +#include "scancode.h" 6.31 + 6.32 +#define KB_INTR 0x9 6.33 +#define KB_PORT 0x60 6.34 + 6.35 +#define PIC1_CMD_PORT 0x20 6.36 +#define OCW2_EOI (1 << 5) 6.37 + 6.38 +#define DONE_INIT (prev_handler) 6.39 + 6.40 +static void __interrupt __far kbintr(); 6.41 + 6.42 +static void (__interrupt __far *prev_handler)(); 6.43 + 6.44 +static int *buffer; 6.45 +static int buffer_size, buf_ridx, buf_widx; 6.46 +static int last_key; 6.47 + 6.48 +static unsigned int num_pressed; 6.49 +static unsigned char keystate[256]; 6.50 + 6.51 +#define ADVANCE(x) ((x) = ((x) + 1) % buffer_size) 6.52 + 6.53 +int kb_init(int bufsz) 6.54 +{ 6.55 + if(DONE_INIT) { 6.56 + fprintf(stderr, "keyboard driver already initialized!\n"); 6.57 + return 0; 6.58 + } 6.59 + 6.60 + buffer_size = bufsz; 6.61 + if(buffer_size && !(buffer = malloc(buffer_size * sizeof *buffer))) { 6.62 + fprintf(stderr, "failed to allocate input buffer, continuing without\n"); 6.63 + buffer_size = 0; 6.64 + } 6.65 + buf_ridx = buf_widx = 0; 6.66 + last_key = -1; 6.67 + 6.68 + memset(keystate, 0, sizeof keystate); 6.69 + num_pressed = 0; 6.70 + 6.71 + /* set our interrupt handler */ 6.72 + _disable(); 6.73 + prev_handler = _dos_getvect(KB_INTR); 6.74 + _dos_setvect(KB_INTR, kbintr); 6.75 + _enable(); 6.76 + 6.77 + return 0; 6.78 +} 6.79 + 6.80 +void kb_shutdown(void) 6.81 +{ 6.82 + if(!DONE_INIT) { 6.83 + return; 6.84 + } 6.85 + 6.86 + /* restore the original interrupt handler */ 6.87 + _disable(); 6.88 + _dos_setvect(KB_INTR, prev_handler); 6.89 + _enable(); 6.90 + 6.91 + free(buffer); 6.92 +} 6.93 + 6.94 +int kb_isdown(int key) 6.95 +{ 6.96 + switch(key) { 6.97 + case KB_ANY: 6.98 + return num_pressed; 6.99 + 6.100 + case KB_ALT: 6.101 + return keystate[KB_LALT] + keystate[KB_RALT]; 6.102 + 6.103 + case KB_CTRL: 6.104 + return keystate[KB_LCTRL] + keystate[KB_RCTRL]; 6.105 + } 6.106 + return keystate[key]; 6.107 +} 6.108 + 6.109 +void kb_wait(void) 6.110 +{ 6.111 + int key; 6.112 + while((key = kb_getkey()) == -1) { 6.113 + /* put the processor to sleep while waiting for keypresses, but first 6.114 + * make sure interrupts are enabled, or we'll sleep forever 6.115 + */ 6.116 + __asm { 6.117 + sti 6.118 + hlt 6.119 + } 6.120 + } 6.121 + kb_putback(key); 6.122 +} 6.123 + 6.124 +int kb_getkey(void) 6.125 +{ 6.126 + int res; 6.127 + 6.128 + if(buffer) { 6.129 + if(buf_ridx == buf_widx) { 6.130 + return -1; 6.131 + } 6.132 + res = buffer[buf_ridx]; 6.133 + ADVANCE(buf_ridx); 6.134 + } else { 6.135 + res = last_key; 6.136 + last_key = -1; 6.137 + } 6.138 + return res; 6.139 +} 6.140 + 6.141 +void kb_putback(int key) 6.142 +{ 6.143 + if(buffer) { 6.144 + /* go back a place */ 6.145 + if(--buf_ridx < 0) { 6.146 + buf_ridx += buffer_size; 6.147 + } 6.148 + 6.149 + /* if the write end hasn't caught up with us, go back one place 6.150 + * and put it there, otherwise just overwrite the oldest key which 6.151 + * is right where we were. 6.152 + */ 6.153 + if(buf_ridx == buf_widx) { 6.154 + ADVANCE(buf_ridx); 6.155 + } 6.156 + 6.157 + buffer[buf_ridx] = key; 6.158 + } else { 6.159 + last_key = key; 6.160 + } 6.161 +} 6.162 + 6.163 +static void __interrupt __far kbintr() 6.164 +{ 6.165 + unsigned char code; 6.166 + int key, press; 6.167 + 6.168 + code = inp(KB_PORT); 6.169 + 6.170 + if(code >= 128) { 6.171 + press = 0; 6.172 + code -= 128; 6.173 + 6.174 + if(num_pressed > 0) { 6.175 + num_pressed--; 6.176 + } 6.177 + } else { 6.178 + press = 1; 6.179 + 6.180 + num_pressed++; 6.181 + } 6.182 + 6.183 + key = scantbl[code]; 6.184 + 6.185 + if(press) { 6.186 + /* append to buffer */ 6.187 + last_key = key; 6.188 + if(buffer_size > 0) { 6.189 + buffer[buf_widx] = key; 6.190 + ADVANCE(buf_widx); 6.191 + /* if the write end overtook the read end, advance the read end 6.192 + * too, to discard the oldest keypress from the buffer 6.193 + */ 6.194 + if(buf_widx == buf_ridx) { 6.195 + ADVANCE(buf_ridx); 6.196 + } 6.197 + } 6.198 + } 6.199 + 6.200 + /* and update keystate table */ 6.201 + keystate[key] = press; 6.202 + 6.203 + outp(PIC1_CMD_PORT, OCW2_EOI); /* send end-of-interrupt */ 6.204 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/dos/keyb.h Mon Jan 19 15:49:14 2015 +0200 7.3 @@ -0,0 +1,69 @@ 7.4 +/* 7.5 +DOS interrupt-based keyboard driver. 7.6 +Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org> 7.7 + 7.8 +This program is free software: you can redistribute it and/or modify 7.9 +it under the terms of the GNU General Public License as published by 7.10 +the Free Software Foundation, either version 3 of the License, or 7.11 +(at your option) any later version. 7.12 + 7.13 +This program is distributed in the hope that it will be useful, 7.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 7.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 7.16 +GNU General Public License for more details. 7.17 + 7.18 +You should have received a copy of the GNU General Public License 7.19 +along with the program. If not, see <http://www.gnu.org/licenses/> 7.20 +*/ 7.21 +#ifndef KEYB_H_ 7.22 +#define KEYB_H_ 7.23 + 7.24 +#define KB_ANY (-1) 7.25 +#define KB_ALT (-2) 7.26 +#define KB_CTRL (-3) 7.27 +#define KB_SHIFT (-4) 7.28 + 7.29 +/* special keys */ 7.30 +enum { 7.31 + KB_LALT, KB_RALT, 7.32 + KB_LCTRL, KB_RCTRL, 7.33 + KB_LSHIFT, KB_RSHIFT, 7.34 + KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, 7.35 + KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, 7.36 + KB_CAPSLK, KB_NUMLK, KB_SCRLK, KB_SYSRQ, 7.37 + KB_ESC = 27, 7.38 + KB_INSERT, KB_DEL, KB_HOME, KB_END, KB_PGUP, KB_PGDN, 7.39 + KB_LEFT, KB_RIGHT, KB_UP, KB_DOWN, 7.40 + KB_NUM_DOT, KB_NUM_ENTER, KB_NUM_PLUS, KB_NUM_MINUS, KB_NUM_MUL, KB_NUM_DIV, 7.41 + KB_NUM_0, KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_4, 7.42 + KB_NUM_5, KB_NUM_6, KB_NUM_7, KB_NUM_8, KB_NUM_9, 7.43 + KB_BACKSP = 127 7.44 +}; 7.45 + 7.46 + 7.47 +#ifdef __cplusplus 7.48 +extern "C" { 7.49 +#endif 7.50 + 7.51 +int kb_init(int bufsz); /* bufsz can be 0 for no buffered keys */ 7.52 +void kb_shutdown(void); /* don't forget to call this at the end! */ 7.53 + 7.54 +/* Boolean predicate for testing the current state of a particular key. 7.55 + * You may also pass KB_ANY to test if any key is held down. 7.56 + */ 7.57 +int kb_isdown(int key); 7.58 + 7.59 +/* waits for any keypress */ 7.60 +void kb_wait(void); 7.61 + 7.62 +/* removes and returns a single key from the input buffer. 7.63 + * If buffering is disabled (initialized with kb_init(0)), then it always 7.64 + * returns the last key pressed. 7.65 + */ 7.66 +int kb_getkey(void); 7.67 + 7.68 +#ifdef __cplusplus 7.69 +} 7.70 +#endif 7.71 + 7.72 +#endif /* KEYB_H_ */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/dos/mouse.c Mon Jan 19 15:49:14 2015 +0200 8.3 @@ -0,0 +1,93 @@ 8.4 +#include "mouse.h" 8.5 +#include "inttypes.h" 8.6 + 8.7 +#define INTR 0x33 8.8 + 8.9 +#define QUERY 0 8.10 +#define SHOW 1 8.11 +#define HIDE 2 8.12 +#define READ 3 8.13 +#define WRITE 4 8.14 +#define PIXRATE 0xf 8.15 + 8.16 +#define XLIM 7 8.17 +#define YLIM 8 8.18 + 8.19 +int have_mouse(void) 8.20 +{ 8.21 + uint16_t res = 0; 8.22 + _asm { 8.23 + mov eax, QUERY 8.24 + int INTR 8.25 + mov res, ax 8.26 + } 8.27 + return res; 8.28 +} 8.29 + 8.30 +void show_mouse(int show) 8.31 +{ 8.32 + uint16_t cmd = show ? SHOW : HIDE; 8.33 + _asm { 8.34 + mov ax, cmd 8.35 + int INTR 8.36 + } 8.37 +} 8.38 + 8.39 +int read_mouse(int *xp, int *yp) 8.40 +{ 8.41 + uint16_t x, y, state; 8.42 + _asm { 8.43 + mov eax, READ 8.44 + int INTR 8.45 + mov state, bx 8.46 + mov x, cx 8.47 + mov y, dx 8.48 + } 8.49 + 8.50 + if(xp) *xp = x; 8.51 + if(yp) *yp = y; 8.52 + return state; 8.53 +} 8.54 + 8.55 +void set_mouse(int x, int y) 8.56 +{ 8.57 + _asm { 8.58 + mov eax, WRITE 8.59 + mov ecx, x 8.60 + mov edx, y 8.61 + int INTR 8.62 + } 8.63 +} 8.64 + 8.65 +void set_mouse_limits(int xmin, int ymin, int xmax, int ymax) 8.66 +{ 8.67 + _asm { 8.68 + mov eax, XLIM 8.69 + mov ecx, xmin 8.70 + mov edx, xmax 8.71 + int INTR 8.72 + mov eax, YLIM 8.73 + mov ecx, ymin 8.74 + mov edx, ymax 8.75 + int INTR 8.76 + } 8.77 +} 8.78 + 8.79 +void set_mouse_rate(int xrate, int yrate) 8.80 +{ 8.81 + _asm { 8.82 + mov ax, PIXRATE 8.83 + mov ecx, xrate 8.84 + mov edx, yrate 8.85 + int INTR 8.86 + } 8.87 +} 8.88 + 8.89 +void set_mouse_mode(enum mouse_mode mode) 8.90 +{ 8.91 + if(mode == MOUSE_GFX) { 8.92 + set_mouse_rate(1, 1); 8.93 + } else { 8.94 + set_mouse_rate(8, 16); 8.95 + } 8.96 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/dos/mouse.h Mon Jan 19 15:49:14 2015 +0200 9.3 @@ -0,0 +1,31 @@ 9.4 +#ifndef MOUSE_H_ 9.5 +#define MOUSE_H_ 9.6 + 9.7 +enum { 9.8 + MOUSE_LEFT = 1, 9.9 + MOUSE_RIGHT = 2, 9.10 + MOUSE_MIDDLE = 4 9.11 +}; 9.12 + 9.13 +enum mouse_mode { 9.14 + MOUSE_GFX, 9.15 + MOUSE_TEXT 9.16 +}; 9.17 + 9.18 +#ifdef __cplusplus 9.19 +extern "C" { 9.20 +#endif 9.21 + 9.22 +int have_mouse(void); 9.23 +void show_mouse(int show); 9.24 +int read_mouse(int *xp, int *yp); 9.25 +void set_mouse(int x, int y); 9.26 +void set_mouse_limits(int xmin, int ymin, int xmax, int ymax); 9.27 +void set_mouse_rate(int xrate, int yrate); 9.28 +void set_mouse_mode(enum mouse_mode mode); 9.29 + 9.30 +#ifdef __cplusplus 9.31 +} 9.32 +#endif 9.33 + 9.34 +#endif /* MOUSE_H_ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/dos/pit8254.h Mon Jan 19 15:49:14 2015 +0200 10.3 @@ -0,0 +1,34 @@ 10.4 +#ifndef PIT8254_H_ 10.5 +#define PIT8254_H_ 10.6 + 10.7 +/* frequency of the oscillator driving the 8254 timer */ 10.8 +#define OSC_FREQ_HZ 1193182 10.9 + 10.10 +/* I/O ports connected to the 8254 */ 10.11 +#define PORT_DATA0 0x40 10.12 +#define PORT_DATA1 0x41 10.13 +#define PORT_DATA2 0x42 10.14 +#define PORT_CMD 0x43 10.15 + 10.16 +/* command bits */ 10.17 +#define CMD_CHAN0 0 10.18 +#define CMD_CHAN1 (1 << 6) 10.19 +#define CMD_CHAN2 (2 << 6) 10.20 +#define CMD_RDBACK (3 << 6) 10.21 + 10.22 +#define CMD_LATCH 0 10.23 +#define CMD_ACCESS_LOW (1 << 4) 10.24 +#define CMD_ACCESS_HIGH (2 << 4) 10.25 +#define CMD_ACCESS_BOTH (3 << 4) 10.26 + 10.27 +#define CMD_OP_INT_TERM 0 10.28 +#define CMD_OP_ONESHOT (1 << 1) 10.29 +#define CMD_OP_RATE (2 << 1) 10.30 +#define CMD_OP_SQWAVE (3 << 1) 10.31 +#define CMD_OP_SW_STROBE (4 << 1) 10.32 +#define CMD_OP_HW_STROBE (5 << 1) 10.33 + 10.34 +#define CMD_MODE_BIN 0 10.35 +#define CMD_MODE_BCD 1 10.36 + 10.37 +#endif /* PIT8254_H_ */
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/dos/scancode.h Mon Jan 19 15:49:14 2015 +0200 11.3 @@ -0,0 +1,17 @@ 11.4 +#ifndef KEYB_C_ 11.5 +#error "do not include scancode.h anywhere..." 11.6 +#endif 11.7 + 11.8 +/* table with rough translations from set 1 scancodes to ASCII-ish */ 11.9 +static int scantbl[] = { 11.10 + 0, KB_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', /* 0 - e */ 11.11 + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* f - 1c */ 11.12 + KB_LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', /* 1d - 29 */ 11.13 + KB_LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', KB_RSHIFT, /* 2a - 36 */ 11.14 + KB_NUM_MUL, KB_LALT, ' ', KB_CAPSLK, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, /* 37 - 44 */ 11.15 + KB_NUMLK, KB_SCRLK, KB_NUM_7, KB_NUM_8, KB_NUM_9, KB_NUM_MINUS, KB_NUM_4, KB_NUM_5, KB_NUM_6, KB_NUM_PLUS, /* 45 - 4e */ 11.16 + KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_0, KB_NUM_DOT, KB_SYSRQ, 0, 0, KB_F11, KB_F12, /* 4d - 58 */ 11.17 + 0, 0, 0, 0, 0, 0, 0, /* 59 - 5f */ 11.18 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ 11.19 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */ 11.20 +};
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/dos/timer.c Mon Jan 19 15:49:14 2015 +0200 12.3 @@ -0,0 +1,131 @@ 12.4 +/* 12.5 +256-color 3D graphics hack for real-mode DOS. 12.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 12.7 + 12.8 +This program is free software: you can redistribute it and/or modify 12.9 +it under the terms of the GNU General Public License as published by 12.10 +the Free Software Foundation, either version 3 of the License, or 12.11 +(at your option) any later version. 12.12 + 12.13 +This program is distributed in the hope that it will be useful, 12.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 12.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12.16 +GNU General Public License for more details. 12.17 + 12.18 +You should have received a copy of the GNU General Public License 12.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 12.20 +*/ 12.21 +#include <stdio.h> 12.22 +#include <stdlib.h> 12.23 +#include <conio.h> 12.24 +#include <dos.h> 12.25 +#include <i86.h> 12.26 +#include "pit8254.h" 12.27 + 12.28 +#define PIT_TIMER_INTR 8 12.29 +#define DOS_TIMER_INTR 0x1c 12.30 + 12.31 +/* macro to divide and round to the nearest integer */ 12.32 +#define DIV_ROUND(a, b) \ 12.33 + ((a) / (b) + ((a) % (b)) / ((b) / 2)) 12.34 + 12.35 +static void set_timer_reload(int reload_val); 12.36 +static void cleanup(void); 12.37 +static void __interrupt __far timer_irq(); 12.38 +static void __interrupt __far dos_timer_intr(); 12.39 + 12.40 +static void (__interrupt __far *prev_timer_intr)(); 12.41 + 12.42 +static unsigned long ticks; 12.43 +static unsigned long tick_interval, ticks_per_dos_intr; 12.44 +static int inum; 12.45 + 12.46 +void init_timer(int res_hz) 12.47 +{ 12.48 + _disable(); 12.49 + 12.50 + if(res_hz > 0) { 12.51 + int reload_val = DIV_ROUND(OSC_FREQ_HZ, res_hz); 12.52 + set_timer_reload(reload_val); 12.53 + 12.54 + tick_interval = DIV_ROUND(1000, res_hz); 12.55 + ticks_per_dos_intr = DIV_ROUND(65535L, reload_val); 12.56 + 12.57 + inum = PIT_TIMER_INTR; 12.58 + prev_timer_intr = _dos_getvect(inum); 12.59 + _dos_setvect(inum, timer_irq); 12.60 + } else { 12.61 + tick_interval = 55; 12.62 + 12.63 + inum = DOS_TIMER_INTR; 12.64 + prev_timer_intr = _dos_getvect(inum); 12.65 + _dos_setvect(inum, dos_timer_intr); 12.66 + } 12.67 + _enable(); 12.68 + 12.69 + atexit(cleanup); 12.70 +} 12.71 + 12.72 +static void cleanup(void) 12.73 +{ 12.74 + if(!prev_timer_intr) { 12.75 + return; /* init hasn't ran, there's nothing to cleanup */ 12.76 + } 12.77 + 12.78 + _disable(); 12.79 + if(inum == PIT_TIMER_INTR) { 12.80 + /* restore the original timer frequency */ 12.81 + set_timer_reload(65535); 12.82 + } 12.83 + 12.84 + /* restore the original interrupt handler */ 12.85 + _dos_setvect(inum, prev_timer_intr); 12.86 + _enable(); 12.87 +} 12.88 + 12.89 +void reset_timer(void) 12.90 +{ 12.91 + ticks = 0; 12.92 +} 12.93 + 12.94 +unsigned long get_msec(void) 12.95 +{ 12.96 + return ticks * tick_interval; 12.97 +} 12.98 + 12.99 +static void set_timer_reload(int reload_val) 12.100 +{ 12.101 + outp(PORT_CMD, CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE); 12.102 + outp(PORT_DATA0, reload_val & 0xff); 12.103 + outp(PORT_DATA0, (reload_val >> 8) & 0xff); 12.104 +} 12.105 + 12.106 +static void __interrupt __far dos_timer_intr() 12.107 +{ 12.108 + ticks++; 12.109 + _chain_intr(prev_timer_intr); /* DOES NOT RETURN */ 12.110 +} 12.111 + 12.112 +/* first PIC command port */ 12.113 +#define PIC1_CMD 0x20 12.114 +/* end of interrupt control word */ 12.115 +#define OCW2_EOI (1 << 5) 12.116 + 12.117 +static void __interrupt __far timer_irq() 12.118 +{ 12.119 + static unsigned long dos_ticks; 12.120 + 12.121 + ticks++; 12.122 + 12.123 + if(++dos_ticks >= ticks_per_dos_intr) { 12.124 + /* I suppose the dos irq handler does the EOI so I shouldn't 12.125 + * do it if I am to call the previous function 12.126 + */ 12.127 + dos_ticks = 0; 12.128 + _chain_intr(prev_timer_intr); /* XXX DOES NOT RETURN */ 12.129 + return; /* just for clarity */ 12.130 + } 12.131 + 12.132 + /* send EOI to the PIC */ 12.133 + outp(PIC1_CMD, OCW2_EOI); 12.134 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/dos/timer.h Mon Jan 19 15:49:14 2015 +0200 13.3 @@ -0,0 +1,37 @@ 13.4 +/* 13.5 +256-color 3D graphics hack for real-mode DOS. 13.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 13.7 + 13.8 +This program is free software: you can redistribute it and/or modify 13.9 +it under the terms of the GNU General Public License as published by 13.10 +the Free Software Foundation, either version 3 of the License, or 13.11 +(at your option) any later version. 13.12 + 13.13 +This program is distributed in the hope that it will be useful, 13.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 13.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13.16 +GNU General Public License for more details. 13.17 + 13.18 +You should have received a copy of the GNU General Public License 13.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 13.20 +*/ 13.21 +#ifndef TIMER_H_ 13.22 +#define TIMER_H_ 13.23 + 13.24 +#ifdef __cplusplus 13.25 +extern "C" { 13.26 +#endif 13.27 + 13.28 +/* expects the required timer resolution in hertz 13.29 + * if res_hz is 0, the current resolution is retained 13.30 + */ 13.31 +void init_timer(int res_hz); 13.32 + 13.33 +void reset_timer(void); 13.34 +unsigned long get_msec(void); 13.35 + 13.36 +#ifdef __cplusplus 13.37 +} 13.38 +#endif 13.39 + 13.40 +#endif /* TIMER_H_ */
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/dos/vbe.c Mon Jan 19 15:49:14 2015 +0200 14.3 @@ -0,0 +1,153 @@ 14.4 +#include <stdio.h> 14.5 +#include <string.h> 14.6 +#include "vbe.h" 14.7 +#include "dpmi.h" 14.8 + 14.9 +/* VGA DAC registers used for palette setting in 8bpp modes */ 14.10 +#define VGA_DAC_STATE 0x3c7 14.11 +#define VGA_DAC_ADDR_RD 0x3c7 14.12 +#define VGA_DAC_ADDR_WR 0x3c8 14.13 +#define VGA_DAC_DATA 0x3c9 14.14 + 14.15 +#define MODE_LFB (1 << 14) 14.16 + 14.17 + 14.18 +struct vbe_info *vbe_get_info(void) 14.19 +{ 14.20 + static unsigned short info_block_seg; 14.21 + static struct vbe_info *info; 14.22 + struct dpmi_real_regs regs; 14.23 + 14.24 + if(!info) { 14.25 + /* allocate 32 paragraphs (512 bytes) */ 14.26 + info_block_seg = dpmi_alloc(32); 14.27 + info = (struct vbe_info*)(info_block_seg << 4); 14.28 + } 14.29 + 14.30 + memcpy(info->sig, "VBE2", 4); 14.31 + 14.32 + memset(®s, 0, sizeof regs); 14.33 + regs.es = info_block_seg; 14.34 + regs.eax = 0x4f00; 14.35 + 14.36 + dpmi_real_int(0x10, ®s); 14.37 + 14.38 + return info; 14.39 +} 14.40 + 14.41 +struct vbe_mode_info *vbe_get_mode_info(int mode) 14.42 +{ 14.43 + static unsigned short mode_info_seg; 14.44 + static struct vbe_mode_info *mi; 14.45 + struct dpmi_real_regs regs; 14.46 + 14.47 + if(!mi) { 14.48 + /* allocate 16 paragraphs (256 bytes) */ 14.49 + mode_info_seg = dpmi_alloc(16); 14.50 + mi = (struct vbe_mode_info*)(mode_info_seg << 4); 14.51 + } 14.52 + 14.53 + memset(®s, 0, sizeof regs); 14.54 + regs.es = mode_info_seg; 14.55 + regs.eax = 0x4f01; 14.56 + regs.ecx = mode; 14.57 + regs.es = mode_info_seg; 14.58 + 14.59 + dpmi_real_int(0x10, ®s); 14.60 + if(regs.eax & 0xff00) { 14.61 + return 0; 14.62 + } 14.63 + 14.64 + return mi; 14.65 +} 14.66 + 14.67 +int vbe_set_mode(int mode) 14.68 +{ 14.69 + struct dpmi_real_regs regs; 14.70 + 14.71 + memset(®s, 0, sizeof regs); 14.72 + regs.eax = 0x4f02; 14.73 + regs.ebx = mode; 14.74 + dpmi_real_int(0x10, ®s); 14.75 + 14.76 + if(regs.eax == 0x100) { 14.77 + return -1; 14.78 + } 14.79 + return 0; 14.80 +} 14.81 + 14.82 +int vbe_set_palette_bits(int bits) 14.83 +{ 14.84 + struct dpmi_real_regs regs; 14.85 + 14.86 + memset(®s, 0, sizeof regs); 14.87 + regs.eax = 0x4f08; 14.88 + regs.ebx = bits << 8; /* bits in bh */ 14.89 + dpmi_real_int(0x10, ®s); 14.90 + 14.91 + if((regs.eax >> 8) & 0xff == 3) { 14.92 + return -1; 14.93 + } 14.94 + return regs.ebx >> 8 & 0xff; /* new color bits in bh */ 14.95 +} 14.96 + 14.97 +/* TODO: implement palette setting through the VBE2 interface for 14.98 + * non-VGA displays (actually don't). 14.99 + */ 14.100 +void vbe_set_palette(int idx, int *col, int count, int bits) 14.101 +{ 14.102 + int i, shift = 8 - bits; 14.103 + 14.104 + __asm { 14.105 + mov dx, VGA_DAC_ADDR_WR 14.106 + mov eax, idx 14.107 + out dx, al 14.108 + } 14.109 + 14.110 + for(i=0; i<count; i++) { 14.111 + unsigned char r = *col++; 14.112 + unsigned char g = *col++; 14.113 + unsigned char b = *col++; 14.114 + 14.115 + if(shift) { 14.116 + r >>= shift; 14.117 + g >>= shift; 14.118 + b >>= shift; 14.119 + } 14.120 + 14.121 + __asm { 14.122 + mov dx, VGA_DAC_DATA 14.123 + mov al, r 14.124 + out dx, al 14.125 + mov al, g 14.126 + out dx, al 14.127 + mov al, b 14.128 + out dx, al 14.129 + } 14.130 + } 14.131 +} 14.132 + 14.133 +static unsigned int get_mask(int sz, int pos) 14.134 +{ 14.135 + unsigned int i, mask = 0; 14.136 + 14.137 + for(i=0; i<sz; i++) { 14.138 + mask |= 1 << i; 14.139 + } 14.140 + return mask << pos; 14.141 +} 14.142 + 14.143 +void print_mode_info(FILE *fp, struct vbe_mode_info *mi) 14.144 +{ 14.145 + fprintf(fp, "resolution: %dx%d\n", mi->xres, mi->yres); 14.146 + fprintf(fp, "color depth: %d\n", mi->bpp); 14.147 + fprintf(fp, "mode attributes: %x\n", mi->mode_attr); 14.148 + fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes); 14.149 + fprintf(fp, "number of planes: %d\n", (int)mi->num_planes); 14.150 + fprintf(fp, "number of banks: %d\n", (int)mi->num_banks); 14.151 + fprintf(fp, "mem model: %d\n", (int)mi->mem_model); 14.152 + fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos)); 14.153 + fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos)); 14.154 + fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos)); 14.155 + fprintf(fp, "framebuffer address: %x\n", mi->fb_addr); 14.156 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/dos/vbe.h Mon Jan 19 15:49:14 2015 +0200 15.3 @@ -0,0 +1,70 @@ 15.4 +#ifndef VBE_H_ 15.5 +#define VBE_H_ 15.6 + 15.7 +#include "inttypes.h" 15.8 + 15.9 +#define VBE_ATTR_LFB (1 << 7) 15.10 +#define VBE_MODE_LFB (1 << 14) 15.11 + 15.12 +#pragma pack (push, 0) 15.13 +struct vbe_info { 15.14 + uint8_t sig[4]; 15.15 + uint16_t version; 15.16 + uint32_t oem_str_ptr; 15.17 + uint8_t caps[4]; /* capabilities */ 15.18 + uint32_t vid_mode_ptr; /* vbefarptr to video mode list */ 15.19 + uint16_t total_mem; /* num of 64k mem blocks */ 15.20 + uint16_t oem_sw_rev; /* VBE implementation software revision */ 15.21 + uint32_t oem_vendor_name_ptr; 15.22 + uint32_t oem_product_name_ptr; 15.23 + uint32_t oem_product_rev_ptr; 15.24 + uint8_t reserved[222]; 15.25 + uint8_t oem_data[256]; 15.26 +}; 15.27 + 15.28 +struct vbe_mode_info { 15.29 + uint16_t mode_attr; 15.30 + uint8_t wina_attr, winb_attr; 15.31 + uint16_t win_gran, win_size; 15.32 + uint16_t wina_seg, winb_seg; 15.33 + uint32_t win_func; 15.34 + uint16_t scanline_bytes; 15.35 + 15.36 + /* VBE 1.2 and above */ 15.37 + uint16_t xres, yres; 15.38 + uint8_t xcharsz, ycharsz; 15.39 + uint8_t num_planes; 15.40 + uint8_t bpp; 15.41 + uint8_t num_banks; 15.42 + uint8_t mem_model; 15.43 + uint8_t bank_size; /* bank size in KB */ 15.44 + uint8_t num_img_pages; 15.45 + uint8_t reserved1; 15.46 + 15.47 + /* direct color fields */ 15.48 + uint8_t rmask_size, rpos; 15.49 + uint8_t gmask_size, gpos; 15.50 + uint8_t bmask_size, bpos; 15.51 + uint8_t xmask_size, xpos; 15.52 + uint8_t cmode_info; /* direct color mode attributes */ 15.53 + 15.54 + /* VBE 2.0 and above */ 15.55 + uint32_t fb_addr; /* physical address of the linear framebuffer */ 15.56 + uint32_t reserved2; 15.57 + uint16_t reserved3; 15.58 + 15.59 + uint8_t reserved4[206]; 15.60 +}; 15.61 +#pragma pack (pop) 15.62 + 15.63 +struct vbe_info *vbe_get_info(void); 15.64 +struct vbe_mode_info *vbe_get_mode_info(unsigned int mode); 15.65 + 15.66 +int vbe_set_mode(unsigned int mode); 15.67 + 15.68 +int vbe_set_palette_bits(int bits); 15.69 +void vbe_set_palette(int idx, int *col, int count, int bits); 15.70 + 15.71 +void print_mode_info(FILE *fp, struct vbe_mode_info *modei); 15.72 + 15.73 +#endif /* VBE_H_ */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/dos/vbegfx.c Mon Jan 19 15:49:14 2015 +0200 16.3 @@ -0,0 +1,158 @@ 16.4 +#ifndef GFX_H_ 16.5 +#define GFX_H_ 16.6 + 16.7 +#include <stdio.h> 16.8 +#include <stdlib.h> 16.9 +#include <string.h> 16.10 +#include "vbe.h" 16.11 +#include "logger.h" 16.12 + 16.13 +#define REALPTR(s, o) (void*)(((uint32_t)(s) << 4) + (uint32_t)(o)) 16.14 +#define VBEPTR(x) REALPTR(((x) & 0xffff0000) >> 16, (x) & 0xffff) 16.15 +#define VBEPTR_SEG(x) (((x) & 0xffff0000) >> 16) 16.16 +#define VBEPTR_OFF(x) ((x) & 0xffff) 16.17 + 16.18 +#define SAME_BPP(a, b) \ 16.19 + ((a) == (b) || (a) == 16 && (b) == 15 || (a) == 15 && (b) == 16 || (a) == 32 && (b) == 24 || (a) == 24 && (b) == 32) 16.20 + 16.21 +static unsigned int make_mask(int sz, int pos); 16.22 + 16.23 +static struct vbe_info *vbe_info; 16.24 +static struct vbe_mode_info *mode_info; 16.25 +static int pal_bits = 6; 16.26 + 16.27 +void *set_video_mode(int xsz, int ysz, int bpp) 16.28 +{ 16.29 + int i; 16.30 + uint16_t *modes, best = 0; 16.31 + unsigned int fbsize; 16.32 + 16.33 + /* check for VBE2 support and output some info */ 16.34 + if(!vbe_info) { 16.35 + if(!(vbe_info = vbe_get_info())) { 16.36 + fprintf(stderr, "VESA BIOS Extensions not available\n"); 16.37 + return 0; 16.38 + } 16.39 + 16.40 + printlog("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff); 16.41 + if(vbe_info->version < 0x200) { 16.42 + fprintf(stderr, "This program requires VBE 2.0 or greater. Try running UniVBE\n"); 16.43 + return 0; 16.44 + } 16.45 + 16.46 + printlog("Graphics adapter: %s, %s (%s)\n", VBEPTR(vbe_info->oem_vendor_name_ptr), 16.47 + VBEPTR(vbe_info->oem_product_name_ptr), VBEPTR(vbe_info->oem_product_rev_ptr)); 16.48 + printlog("Video memory: %dmb\n", vbe_info->total_mem << 6); 16.49 + 16.50 + modes = VBEPTR(vbe_info->vid_mode_ptr); 16.51 + } 16.52 + 16.53 + for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */ 16.54 + if(modes[i] == 0xffff) { 16.55 + break; /* reached the end */ 16.56 + } 16.57 + 16.58 + mode_info = vbe_get_mode_info(modes[i] | VBE_MODE_LFB); 16.59 + if(!mode_info || mode_info->xres != xsz || mode_info->yres != ysz) { 16.60 + continue; 16.61 + } 16.62 + if(SAME_BPP(mode_info->bpp, bpp)) { 16.63 + best = modes[i]; 16.64 + } 16.65 + } 16.66 + 16.67 + if(best) { 16.68 + mode_info = vbe_get_mode_info(best); 16.69 + } else { 16.70 + fprintf(stderr, "Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp); 16.71 + return 0; 16.72 + } 16.73 + 16.74 + if(vbe_set_mode(best | VBE_MODE_LFB) == -1) { 16.75 + fprintf(stderr, "Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp); 16.76 + return 0; 16.77 + } 16.78 + 16.79 + /* attempt to set 8 bits of color per component in palettized modes */ 16.80 + if(bpp <= 8) { 16.81 + pal_bits = vbe_set_palette_bits(8); 16.82 + printlog("palette bits per color primary: %d\n", pal_bits); 16.83 + } 16.84 + 16.85 + fbsize = xsz * ysz * mode_info->num_img_pages * (bpp / CHAR_BIT); 16.86 + return (void*)dpmi_mmap(mode_info->fb_addr, fbsize); 16.87 +} 16.88 + 16.89 +int set_text_mode(void) 16.90 +{ 16.91 + vbe_set_mode(0x3); 16.92 + return 0; 16.93 +} 16.94 + 16.95 +int get_color_depth(void) 16.96 +{ 16.97 + if(!mode_info) { 16.98 + return -1; 16.99 + } 16.100 + return mode_info->bpp; 16.101 +} 16.102 + 16.103 +int get_color_bits(int *rbits, int *gbits, int *bbits) 16.104 +{ 16.105 + if(!mode_info) { 16.106 + return -1; 16.107 + } 16.108 + *rbits = mode_info->rmask_size; 16.109 + *gbits = mode_info->gmask_size; 16.110 + *bbits = mode_info->bmask_size; 16.111 + return 0; 16.112 +} 16.113 + 16.114 +int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask) 16.115 +{ 16.116 + if(!mode_info) { 16.117 + return -1; 16.118 + } 16.119 + *rmask = make_mask(mode_info->rmask_size, mode_info->rpos); 16.120 + *gmask = make_mask(mode_info->gmask_size, mode_info->gpos); 16.121 + *bmask = make_mask(mode_info->bmask_size, mode_info->bpos); 16.122 + return 0; 16.123 +} 16.124 + 16.125 +int get_color_shift(int *rshift, int *gshift, int *bshift) 16.126 +{ 16.127 + if(!mode_info) { 16.128 + return -1; 16.129 + } 16.130 + *rshift = mode_info->rpos; 16.131 + *gshift = mode_info->gpos; 16.132 + *bshift = mode_info->bpos; 16.133 + return 0; 16.134 +} 16.135 + 16.136 +void set_palette(int idx, int r, int g, int b) 16.137 +{ 16.138 + int col[3]; 16.139 + col[0] = r; 16.140 + col[1] = g; 16.141 + col[2] = b; 16.142 + vbe_set_palette(idx, col, 1, pal_bits); 16.143 +} 16.144 + 16.145 +void wait_vsync(void) 16.146 +{ 16.147 + /* TODO */ 16.148 +} 16.149 + 16.150 +static unsigned int make_mask(int sz, int pos) 16.151 +{ 16.152 + unsigned int i, mask = 0; 16.153 + 16.154 + for(i=0; i<sz; i++) { 16.155 + mask |= 1 << i; 16.156 + } 16.157 + return mask << pos; 16.158 +} 16.159 + 16.160 + 16.161 +#endif /* GFX_H_ */
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/dos/vbegfx.h Mon Jan 19 15:49:14 2015 +0200 17.3 @@ -0,0 +1,24 @@ 17.4 +#ifndef VBEGFX_H_ 17.5 +#define VBEGFX_H_ 17.6 + 17.7 +#ifdef __cplusplus 17.8 +extern "C" { 17.9 +#endif 17.10 + 17.11 +void *set_video_mode(int xsz, int ysz, int bpp); 17.12 +int set_text_mode(void); 17.13 + 17.14 +int get_color_depth(void); 17.15 +int get_color_bits(int *rbits, int *gbits, int *bbits); 17.16 +int get_color_shift(int *rshift, int *gshift, int *bshift); 17.17 +int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask); 17.18 + 17.19 +void set_palette(int idx, int r, int g, int b); 17.20 + 17.21 +void wait_vsync(void); 17.22 + 17.23 +#ifdef __cplusplus 17.24 +} 17.25 +#endif 17.26 + 17.27 +#endif /* VBEGFX_H_ */
18.1 --- a/src/fblib.c Mon Jan 19 02:32:01 2015 +0200 18.2 +++ b/src/fblib.c Mon Jan 19 15:49:14 2015 +0200 18.3 @@ -1,6 +1,21 @@ 18.4 #include "fblib.h" 18.5 #include "fblibimp.h" 18.6 18.7 +int fb_get_width(void) 18.8 +{ 18.9 + return fb_width; 18.10 +} 18.11 + 18.12 +int fb_get_height(void) 18.13 +{ 18.14 + return fb_height; 18.15 +} 18.16 + 18.17 +int fb_get_bpp(void) 18.18 +{ 18.19 + return fb_bpp; 18.20 +} 18.21 + 18.22 void fb_set_palette(int *colors) 18.23 { 18.24 fb_set_palette_range(0, 256, colors);
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/src/fblibdos.c Mon Jan 19 15:49:14 2015 +0200 19.3 @@ -0,0 +1,62 @@ 19.4 +#ifdef FBLIB_DOS 19.5 +#include "vbegfx.h" 19.6 + 19.7 +static unsigned char *framebuf; 19.8 + 19.9 +int fb_init(int width, int height, int bpp) 19.10 +{ 19.11 + init_timer(128); 19.12 + if(kb_init(32) == -1) { 19.13 + fprintf(stderr, "failed to initialize keyboard driver\n"); 19.14 + return false; 19.15 + } 19.16 + 19.17 + if(!(framebuf = set_video_mode(width, height, bpp))) { 19.18 + return -1; 19.19 + } 19.20 + fb_width = width; 19.21 + fb_height = height; 19.22 + fb_bpp = get_color_depth(); 19.23 + 19.24 + 19.25 + return 0; 19.26 +} 19.27 + 19.28 +void fb_shutdown(void) 19.29 +{ 19.30 + framebuf = 0; 19.31 + set_text_mode(); 19.32 +} 19.33 + 19.34 +void *fb_begin_frame(void) 19.35 +{ 19.36 + return framebuf; 19.37 +} 19.38 + 19.39 +void fb_end_frame(void) 19.40 +{ 19.41 + wait_vsync(void); 19.42 +} 19.43 + 19.44 +void fb_set_palette_range(int start, int count, int *colors) 19.45 +{ 19.46 + /* TODO: add a range-palette setter in vbegfx.c */ 19.47 + int i; 19.48 + for(i=0; i<count; i++) { 19.49 + set_palette(start + i, colors[0], colors[1], colors[2]); 19.50 + colors += 3; 19.51 + } 19.52 +} 19.53 + 19.54 +int fb_process_events(void) 19.55 +{ 19.56 + if(handle_keyboard() == -1) { 19.57 + return -1; 19.58 + } 19.59 + if(handle_mouse() == -1) { 19.60 + return -1; 19.61 + } 19.62 + return 0; 19.63 +} 19.64 + 19.65 +#endif /* FBLIB_DOS */
20.1 --- a/src/fblibsdl.c Mon Jan 19 02:32:01 2015 +0200 20.2 +++ b/src/fblibsdl.c Mon Jan 19 15:49:14 2015 +0200 20.3 @@ -61,21 +61,6 @@ 20.4 SDL_Quit(); 20.5 } 20.6 20.7 -int fb_get_width(void) 20.8 -{ 20.9 - return fb_width; 20.10 -} 20.11 - 20.12 -int fb_get_height(void) 20.13 -{ 20.14 - return fb_height; 20.15 -} 20.16 - 20.17 -int fb_get_bpp(void) 20.18 -{ 20.19 - return fb_bpp; 20.20 -} 20.21 - 20.22 void *fb_begin_frame(void) 20.23 { 20.24 if(!surf) return 0;
21.1 --- a/src/level.c Mon Jan 19 02:32:01 2015 +0200 21.2 +++ b/src/level.c Mon Jan 19 15:49:14 2015 +0200 21.3 @@ -3,6 +3,11 @@ 21.4 #include <string.h> 21.5 #include <ctype.h> 21.6 #include <math.h> 21.7 +#if defined(_MSC_VER) || defined(__WATCOMC__) 21.8 +#include <malloc.h> 21.9 +#else 21.10 +#include <alloca.h> 21.11 +#endif 21.12 #include "level.h" 21.13 21.14 #define C_WALL '#'
22.1 --- a/src/tileset.c Mon Jan 19 02:32:01 2015 +0200 22.2 +++ b/src/tileset.c Mon Jan 19 15:49:14 2015 +0200 22.3 @@ -5,6 +5,11 @@ 22.4 #include <errno.h> 22.5 #include <ctype.h> 22.6 #include <assert.h> 22.7 +#if defined(_MSC_VER) || defined(__WATCOMC__) 22.8 +#include <malloc.h> 22.9 +#else 22.10 +#include <alloca.h> 22.11 +#endif 22.12 #include "tileset.h" 22.13 #include "image.h" 22.14