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  	}