# HG changeset patch # User John Tsiombikas # Date 1363397708 -7200 # Node ID a8024271c662ea33cc7fd5964f81d89ebeed0a70 # Parent a52d0b786ce13346432bd29bbce67c52fcc5f2f1 added timer diff -r a52d0b786ce1 -r a8024271c662 src/pit8254.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pit8254.h Sat Mar 16 03:35:08 2013 +0200 @@ -0,0 +1,34 @@ +#ifndef PIT8254_H_ +#define PIT8254_H_ + +/* frequency of the oscillator driving the 8254 timer */ +#define OSC_FREQ_HZ 1193182 + +/* I/O ports connected to the 8254 */ +#define PORT_DATA0 0x40 +#define PORT_DATA1 0x41 +#define PORT_DATA2 0x42 +#define PORT_CMD 0x43 + +/* command bits */ +#define CMD_CHAN0 0 +#define CMD_CHAN1 (1 << 6) +#define CMD_CHAN2 (2 << 6) +#define CMD_RDBACK (3 << 6) + +#define CMD_LATCH 0 +#define CMD_ACCESS_LOW (1 << 4) +#define CMD_ACCESS_HIGH (2 << 4) +#define CMD_ACCESS_BOTH (3 << 4) + +#define CMD_OP_INT_TERM 0 +#define CMD_OP_ONESHOT (1 << 1) +#define CMD_OP_RATE (2 << 1) +#define CMD_OP_SQWAVE (3 << 1) +#define CMD_OP_SW_STROBE (4 << 1) +#define CMD_OP_HW_STROBE (5 << 1) + +#define CMD_MODE_BIN 0 +#define CMD_MODE_BCD 1 + +#endif /* PIT8254_H_ */ diff -r a52d0b786ce1 -r a8024271c662 src/timer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timer.c Sat Mar 16 03:35:08 2013 +0200 @@ -0,0 +1,130 @@ +/* +256-color 3D graphics hack for real-mode DOS. +Copyright (C) 2011 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include +#include +#include +#include +#include "pit8254.h" + +#define PIT_TIMER_INTR 8 +#define DOS_TIMER_INTR 0x1c + +/* macro to divide and round to the nearest integer */ +#define DIV_ROUND(a, b) \ + ((a) / (b) + ((a) % (b)) / ((b) / 2)) + +static void set_timer_reload(int reload_val); +static void cleanup(void); +static void __interrupt __far timer_irq(); +static void __interrupt __far dos_timer_intr(); + +static void (__interrupt __far *prev_timer_intr)(); + +static unsigned long ticks; +static unsigned long tick_interval, ticks_per_dos_intr; +static int inum; + +void init_timer(int res_hz) +{ + _disable(); + + if(res_hz > 0) { + int reload_val = DIV_ROUND(OSC_FREQ_HZ, res_hz); + set_timer_reload(reload_val); + + tick_interval = DIV_ROUND(1000, res_hz); + ticks_per_dos_intr = DIV_ROUND(65535L, reload_val); + + inum = PIT_TIMER_INTR; + prev_timer_intr = _dos_getvect(inum); + _dos_setvect(inum, timer_irq); + } else { + tick_interval = 55; + + inum = DOS_TIMER_INTR; + prev_timer_intr = _dos_getvect(inum); + _dos_setvect(inum, dos_timer_intr); + } + _enable(); + + atexit(cleanup); +} + +static void cleanup(void) +{ + if(!prev_timer_intr) { + return; /* init hasn't ran, there's nothing to cleanup */ + } + + _disable(); + if(inum == PIT_TIMER_INTR) { + /* restore the original timer frequency */ + set_timer_reload(65535); + } + + /* restore the original interrupt handler */ + _dos_setvect(inum, prev_timer_intr); + _enable(); +} + +void reset_timer(void) +{ + ticks = 0; +} + +unsigned long get_msec(void) +{ + return ticks * tick_interval; +} + +static void set_timer_reload(int reload_val) +{ + outp(PORT_CMD, CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE); + outp(PORT_DATA0, reload_val & 0xff); + outp(PORT_DATA0, (reload_val >> 8) & 0xff); +} + +static void __interrupt __far dos_timer_intr() +{ + ticks++; + _chain_intr(prev_timer_intr); /* DOES NOT RETURN */ +} + +/* first PIC command port */ +#define PIC1_CMD 0x20 +/* end of interrupt control word */ +#define OCW2_EOI (1 << 5) + +static void __interrupt __far timer_irq() +{ + static unsigned long dos_ticks; + + ticks++; + + if(++dos_ticks >= ticks_per_dos_intr) { + /* I suppose the dos irq handler does the EOI so I shouldn't + * do it if I am to call the previous function + */ + dos_ticks = 0; + _chain_intr(prev_timer_intr); /* DOES NOT RETURN */ + } else { + /* send EOI to the PIC */ + outp(PIC1_CMD, OCW2_EOI); + } +} diff -r a52d0b786ce1 -r a8024271c662 src/timer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timer.h Sat Mar 16 03:35:08 2013 +0200 @@ -0,0 +1,29 @@ +/* +256-color 3D graphics hack for real-mode DOS. +Copyright (C) 2011 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef TIMER_H_ +#define TIMER_H_ + +/* expects the required timer resolution in hertz + * if res_hz is 0, the current resolution is retained + */ +void init_timer(int res_hz); + +void reset_timer(void); +unsigned long get_msec(void); + +#endif /* TIMER_H_ */ diff -r a52d0b786ce1 -r a8024271c662 src/tunnel.c --- a/src/tunnel.c Fri Mar 15 19:55:29 2013 +0200 +++ b/src/tunnel.c Sat Mar 16 03:35:08 2013 +0200 @@ -6,6 +6,7 @@ #include "wvga.h" #include "texture.h" #include "palman.h" +#include "timer.h" #ifndef M_PI #define M_PI 3.14159265 @@ -18,22 +19,26 @@ void cleanup(void); void display(void); int calc_tunnel_mapping(void); +int parse_args(int argc, char **argv); static unsigned char *fbuf; static struct texture *tex; static int colrange; -static char *tex_fname = "data/wall2.ppm"; +static char *tex_fname; static unsigned long *umap, *vmap; static unsigned long frames; static unsigned long start_time; +static int under_windows; + + int main(int argc, char **argv) { - if(argc > 1) { - tex_fname = argv[1]; + if(parse_args(argc, argv) == -1) { + return 1; } if(init() == -1) { @@ -68,9 +73,8 @@ free(fbuf); return -1; } - } else { - fprintf(stderr, "FOO\n"); + fprintf(stderr, "you must specify a texture to use\n"); return -1; } @@ -85,19 +89,28 @@ } colrange = palm_color_range(); + init_timer(120); + start_time = get_msec(); + return 0; } void cleanup(void) { + unsigned long sec = (get_msec() - start_time) / 1000ul; + free_texture(tex); free(fbuf); set_video_mode(0x3); + + if(sec) { + printf("avg fps: %lu\n", frames / sec); + } } void display(void) { - static unsigned long msec; + unsigned long msec = get_msec() - start_time; unsigned int i; unsigned char voffs = msec >> 3; @@ -122,7 +135,7 @@ } copy_frame(fbuf); - msec += 33; + frames++; } int calc_tunnel_mapping(void) @@ -162,3 +175,30 @@ } return 0; } + +int parse_args(int argc, char **argv) +{ + int i; + + for(i=1; i