dostunnel
changeset 3:a8024271c662
added timer
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 16 Mar 2013 03:35:08 +0200 |
parents | a52d0b786ce1 |
children | ba868d348de8 |
files | src/pit8254.h src/timer.c src/timer.h src/tunnel.c src/wvga.c |
diffstat | 5 files changed, 241 insertions(+), 8 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/pit8254.h Sat Mar 16 03:35:08 2013 +0200 1.3 @@ -0,0 +1,34 @@ 1.4 +#ifndef PIT8254_H_ 1.5 +#define PIT8254_H_ 1.6 + 1.7 +/* frequency of the oscillator driving the 8254 timer */ 1.8 +#define OSC_FREQ_HZ 1193182 1.9 + 1.10 +/* I/O ports connected to the 8254 */ 1.11 +#define PORT_DATA0 0x40 1.12 +#define PORT_DATA1 0x41 1.13 +#define PORT_DATA2 0x42 1.14 +#define PORT_CMD 0x43 1.15 + 1.16 +/* command bits */ 1.17 +#define CMD_CHAN0 0 1.18 +#define CMD_CHAN1 (1 << 6) 1.19 +#define CMD_CHAN2 (2 << 6) 1.20 +#define CMD_RDBACK (3 << 6) 1.21 + 1.22 +#define CMD_LATCH 0 1.23 +#define CMD_ACCESS_LOW (1 << 4) 1.24 +#define CMD_ACCESS_HIGH (2 << 4) 1.25 +#define CMD_ACCESS_BOTH (3 << 4) 1.26 + 1.27 +#define CMD_OP_INT_TERM 0 1.28 +#define CMD_OP_ONESHOT (1 << 1) 1.29 +#define CMD_OP_RATE (2 << 1) 1.30 +#define CMD_OP_SQWAVE (3 << 1) 1.31 +#define CMD_OP_SW_STROBE (4 << 1) 1.32 +#define CMD_OP_HW_STROBE (5 << 1) 1.33 + 1.34 +#define CMD_MODE_BIN 0 1.35 +#define CMD_MODE_BCD 1 1.36 + 1.37 +#endif /* PIT8254_H_ */
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/timer.c Sat Mar 16 03:35:08 2013 +0200 2.3 @@ -0,0 +1,130 @@ 2.4 +/* 2.5 +256-color 3D graphics hack for real-mode DOS. 2.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 2.7 + 2.8 +This program is free software: you can redistribute it and/or modify 2.9 +it under the terms of the GNU General Public License as published by 2.10 +the Free Software Foundation, either version 3 of the License, or 2.11 +(at your option) any later version. 2.12 + 2.13 +This program is distributed in the hope that it will be useful, 2.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 2.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2.16 +GNU General Public License for more details. 2.17 + 2.18 +You should have received a copy of the GNU General Public License 2.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 2.20 +*/ 2.21 +#include <stdio.h> 2.22 +#include <stdlib.h> 2.23 +#include <conio.h> 2.24 +#include <dos.h> 2.25 +#include <i86.h> 2.26 +#include "pit8254.h" 2.27 + 2.28 +#define PIT_TIMER_INTR 8 2.29 +#define DOS_TIMER_INTR 0x1c 2.30 + 2.31 +/* macro to divide and round to the nearest integer */ 2.32 +#define DIV_ROUND(a, b) \ 2.33 + ((a) / (b) + ((a) % (b)) / ((b) / 2)) 2.34 + 2.35 +static void set_timer_reload(int reload_val); 2.36 +static void cleanup(void); 2.37 +static void __interrupt __far timer_irq(); 2.38 +static void __interrupt __far dos_timer_intr(); 2.39 + 2.40 +static void (__interrupt __far *prev_timer_intr)(); 2.41 + 2.42 +static unsigned long ticks; 2.43 +static unsigned long tick_interval, ticks_per_dos_intr; 2.44 +static int inum; 2.45 + 2.46 +void init_timer(int res_hz) 2.47 +{ 2.48 + _disable(); 2.49 + 2.50 + if(res_hz > 0) { 2.51 + int reload_val = DIV_ROUND(OSC_FREQ_HZ, res_hz); 2.52 + set_timer_reload(reload_val); 2.53 + 2.54 + tick_interval = DIV_ROUND(1000, res_hz); 2.55 + ticks_per_dos_intr = DIV_ROUND(65535L, reload_val); 2.56 + 2.57 + inum = PIT_TIMER_INTR; 2.58 + prev_timer_intr = _dos_getvect(inum); 2.59 + _dos_setvect(inum, timer_irq); 2.60 + } else { 2.61 + tick_interval = 55; 2.62 + 2.63 + inum = DOS_TIMER_INTR; 2.64 + prev_timer_intr = _dos_getvect(inum); 2.65 + _dos_setvect(inum, dos_timer_intr); 2.66 + } 2.67 + _enable(); 2.68 + 2.69 + atexit(cleanup); 2.70 +} 2.71 + 2.72 +static void cleanup(void) 2.73 +{ 2.74 + if(!prev_timer_intr) { 2.75 + return; /* init hasn't ran, there's nothing to cleanup */ 2.76 + } 2.77 + 2.78 + _disable(); 2.79 + if(inum == PIT_TIMER_INTR) { 2.80 + /* restore the original timer frequency */ 2.81 + set_timer_reload(65535); 2.82 + } 2.83 + 2.84 + /* restore the original interrupt handler */ 2.85 + _dos_setvect(inum, prev_timer_intr); 2.86 + _enable(); 2.87 +} 2.88 + 2.89 +void reset_timer(void) 2.90 +{ 2.91 + ticks = 0; 2.92 +} 2.93 + 2.94 +unsigned long get_msec(void) 2.95 +{ 2.96 + return ticks * tick_interval; 2.97 +} 2.98 + 2.99 +static void set_timer_reload(int reload_val) 2.100 +{ 2.101 + outp(PORT_CMD, CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE); 2.102 + outp(PORT_DATA0, reload_val & 0xff); 2.103 + outp(PORT_DATA0, (reload_val >> 8) & 0xff); 2.104 +} 2.105 + 2.106 +static void __interrupt __far dos_timer_intr() 2.107 +{ 2.108 + ticks++; 2.109 + _chain_intr(prev_timer_intr); /* DOES NOT RETURN */ 2.110 +} 2.111 + 2.112 +/* first PIC command port */ 2.113 +#define PIC1_CMD 0x20 2.114 +/* end of interrupt control word */ 2.115 +#define OCW2_EOI (1 << 5) 2.116 + 2.117 +static void __interrupt __far timer_irq() 2.118 +{ 2.119 + static unsigned long dos_ticks; 2.120 + 2.121 + ticks++; 2.122 + 2.123 + if(++dos_ticks >= ticks_per_dos_intr) { 2.124 + /* I suppose the dos irq handler does the EOI so I shouldn't 2.125 + * do it if I am to call the previous function 2.126 + */ 2.127 + dos_ticks = 0; 2.128 + _chain_intr(prev_timer_intr); /* DOES NOT RETURN */ 2.129 + } else { 2.130 + /* send EOI to the PIC */ 2.131 + outp(PIC1_CMD, OCW2_EOI); 2.132 + } 2.133 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/timer.h Sat Mar 16 03:35:08 2013 +0200 3.3 @@ -0,0 +1,29 @@ 3.4 +/* 3.5 +256-color 3D graphics hack for real-mode DOS. 3.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 3.7 + 3.8 +This program is free software: you can redistribute it and/or modify 3.9 +it under the terms of the GNU General Public License as published by 3.10 +the Free Software Foundation, either version 3 of the License, or 3.11 +(at your option) any later version. 3.12 + 3.13 +This program is distributed in the hope that it will be useful, 3.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 3.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3.16 +GNU General Public License for more details. 3.17 + 3.18 +You should have received a copy of the GNU General Public License 3.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 3.20 +*/ 3.21 +#ifndef TIMER_H_ 3.22 +#define TIMER_H_ 3.23 + 3.24 +/* expects the required timer resolution in hertz 3.25 + * if res_hz is 0, the current resolution is retained 3.26 + */ 3.27 +void init_timer(int res_hz); 3.28 + 3.29 +void reset_timer(void); 3.30 +unsigned long get_msec(void); 3.31 + 3.32 +#endif /* TIMER_H_ */
4.1 --- a/src/tunnel.c Fri Mar 15 19:55:29 2013 +0200 4.2 +++ b/src/tunnel.c Sat Mar 16 03:35:08 2013 +0200 4.3 @@ -6,6 +6,7 @@ 4.4 #include "wvga.h" 4.5 #include "texture.h" 4.6 #include "palman.h" 4.7 +#include "timer.h" 4.8 4.9 #ifndef M_PI 4.10 #define M_PI 3.14159265 4.11 @@ -18,22 +19,26 @@ 4.12 void cleanup(void); 4.13 void display(void); 4.14 int calc_tunnel_mapping(void); 4.15 +int parse_args(int argc, char **argv); 4.16 4.17 static unsigned char *fbuf; 4.18 static struct texture *tex; 4.19 static int colrange; 4.20 4.21 -static char *tex_fname = "data/wall2.ppm"; 4.22 +static char *tex_fname; 4.23 4.24 static unsigned long *umap, *vmap; 4.25 4.26 static unsigned long frames; 4.27 static unsigned long start_time; 4.28 4.29 +static int under_windows; 4.30 + 4.31 + 4.32 int main(int argc, char **argv) 4.33 { 4.34 - if(argc > 1) { 4.35 - tex_fname = argv[1]; 4.36 + if(parse_args(argc, argv) == -1) { 4.37 + return 1; 4.38 } 4.39 4.40 if(init() == -1) { 4.41 @@ -68,9 +73,8 @@ 4.42 free(fbuf); 4.43 return -1; 4.44 } 4.45 - 4.46 } else { 4.47 - fprintf(stderr, "FOO\n"); 4.48 + fprintf(stderr, "you must specify a texture to use\n"); 4.49 return -1; 4.50 } 4.51 4.52 @@ -85,19 +89,28 @@ 4.53 } 4.54 colrange = palm_color_range(); 4.55 4.56 + init_timer(120); 4.57 + start_time = get_msec(); 4.58 + 4.59 return 0; 4.60 } 4.61 4.62 void cleanup(void) 4.63 { 4.64 + unsigned long sec = (get_msec() - start_time) / 1000ul; 4.65 + 4.66 free_texture(tex); 4.67 free(fbuf); 4.68 set_video_mode(0x3); 4.69 + 4.70 + if(sec) { 4.71 + printf("avg fps: %lu\n", frames / sec); 4.72 + } 4.73 } 4.74 4.75 void display(void) 4.76 { 4.77 - static unsigned long msec; 4.78 + unsigned long msec = get_msec() - start_time; 4.79 4.80 unsigned int i; 4.81 unsigned char voffs = msec >> 3; 4.82 @@ -122,7 +135,7 @@ 4.83 } 4.84 4.85 copy_frame(fbuf); 4.86 - msec += 33; 4.87 + frames++; 4.88 } 4.89 4.90 int calc_tunnel_mapping(void) 4.91 @@ -162,3 +175,30 @@ 4.92 } 4.93 return 0; 4.94 } 4.95 + 4.96 +int parse_args(int argc, char **argv) 4.97 +{ 4.98 + int i; 4.99 + 4.100 + for(i=1; i<argc; i++) { 4.101 + if(argv[i][0] == '-') { 4.102 + if(strcmp(argv[i], "-win") == 0) { 4.103 + under_windows = 1; 4.104 + } else { 4.105 + fprintf(stderr, "invalid option: %s\n", argv[i]); 4.106 + return -1; 4.107 + } 4.108 + } else { 4.109 + if(tex_fname) { 4.110 + fprintf(stderr, "unexpected argument: %s\n", argv[i]); 4.111 + return -1; 4.112 + } 4.113 + tex_fname = argv[i]; 4.114 + } 4.115 + } 4.116 + 4.117 + if(!tex_fname) { 4.118 + tex_fname = "data/wall2.ppm"; 4.119 + } 4.120 + return 0; 4.121 +}
5.1 --- a/src/wvga.c Fri Mar 15 19:55:29 2013 +0200 5.2 +++ b/src/wvga.c Sat Mar 16 03:35:08 2013 +0200 5.3 @@ -25,7 +25,7 @@ 5.4 } 5.5 5.6 if(mode != 3) { 5.7 - framebuffer = (void*)dpmi_mmap((void*)0xa0000, 64000); 5.8 + framebuffer = dpmi_mmap(0xa0000, 64000); 5.9 } else { 5.10 dpmi_munmap((void*)0xa0000); 5.11 }