From e17bfec530d9d476c61c9bb2a156788c742db43b Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 3 Jul 2023 13:44:40 +0300 Subject: [PATCH] added dos timer and double-esc to quit --- Makefile | 10 +-- src/app.c | 14 ++++- src/app.h | 1 - src/dos/main.c | 7 +-- src/dos/pit8254.h | 17 ------ src/dos/timer.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/modern/main.c | 4 +- src/scr_mod.c | 29 ++++++--- src/timer.h | 22 +++++++ 9 files changed, 239 insertions(+), 40 deletions(-) create mode 100644 src/dos/timer.c create mode 100644 src/timer.h diff --git a/Makefile b/Makefile index ada31b2..634f40a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ !ifdef __UNIX__ -dosobj = src/dos/main.obj src/dos/keyb.obj src/dos/mouse.obj src/dos/cdpmi.obj & - src/dos/vidsys.obj src/dos/drv_vga.obj src/dos/drv_vbe.obj src/dos/drv_s3.obj +dosobj = src/dos/main.obj src/dos/keyb.obj src/dos/mouse.obj src/dos/timer.obj & + src/dos/cdpmi.obj src/dos/vidsys.obj src/dos/drv_vga.obj src/dos/drv_vbe.obj & + src/dos/drv_s3.obj appobj = src/app.obj src/cmesh.obj src/darray.obj src/font.obj src/logger.obj & src/meshgen.obj src/meshload.obj src/options.obj src/rbtree.obj src/geom.obj & src/rend.obj src/rtk.obj src/scene.obj src/scr_mod.obj src/scr_rend.obj & @@ -11,8 +12,9 @@ gawobj = src/gaw/gaw_sw.obj src/gaw/gawswtnl.obj src/gaw/polyclip.obj src/gaw/po incpath = -Isrc -Isrc/dos -Ilibs -Ilibs/imago/src -Ilibs/treestor/include -Ilibs/drawtext libpath = libpath libs/dos !else -dosobj = src\dos\main.obj src\dos\keyb.obj src\dos\mouse.obj src\dos\cdpmi.obj & - src\dos\vidsys.obj src\dos\drv_vga.obj src\dos\drv_vbe.obj src\dos\drv_s3.obj +dosobj = src\dos\main.obj src\dos\keyb.obj src\dos\mouse.obj src\dos\timer.obj & + src\dos\cdpmi.obj src\dos\vidsys.obj src\dos\drv_vga.obj src\dos\drv_vbe.obj & + src\dos\drv_s3.obj appobj = src\app.obj src\cmesh.obj src\darray.obj src\font.obj src\logger.obj & src\meshgen.obj src\meshload.obj src\options.obj src\rbtree.obj src\geom.obj & src\rend.obj src\rtk.obj src\scene.obj src\scr_mod.obj src\scr_rend.obj & diff --git a/src/app.c b/src/app.c index 25baebb..b0fc2e8 100644 --- a/src/app.c +++ b/src/app.c @@ -23,6 +23,7 @@ along with this program. If not, see . #include #include "gaw/gaw.h" #include "app.h" +#include "timer.h" #include "rend.h" #include "options.h" #include "font.h" @@ -111,7 +112,7 @@ int app_init(void) } } - time_msec = app_getmsec(); + time_msec = get_msec(); for(i=0; iname && start_scr_name && strcmp(screens[i]->name, start_scr_name) == 0) { @@ -154,7 +155,7 @@ void app_shutdown(void) void app_display(void) { - time_msec = app_getmsec(); + time_msec = get_msec(); cur_scr->display(); } @@ -191,11 +192,18 @@ void app_reshape(int x, int y) void app_keyboard(int key, int press) { + long msec; + static long prev_esc; + if(press) { switch(key) { #ifdef DBG_ESCQUIT case 27: - app_quit(); + msec = get_msec(); + if(msec - prev_esc < 1000) { + app_quit(); + } + prev_esc = msec; return; #endif diff --git a/src/app.h b/src/app.h index b2a3b82..6073261 100644 --- a/src/app.h +++ b/src/app.h @@ -105,7 +105,6 @@ void app_sball_button(int bn, int st); void app_chscr(struct app_screen *scr); /* defined in main.c */ -long app_getmsec(void); void app_redisplay(int x, int y, int w, int h); void app_swap_buffers(void); void app_quit(void); diff --git a/src/dos/main.c b/src/dos/main.c index e7aae2c..e26d2b6 100644 --- a/src/dos/main.c +++ b/src/dos/main.c @@ -21,6 +21,7 @@ along with this program. If not, see . #include #include #include "app.h" +#include "timer.h" #include "keyb.h" #include "vidsys.h" #include "cdpmi.h" @@ -66,6 +67,7 @@ int main(int argc, char **argv) print_cpuid(&cpuid); } + init_timer(0); kb_init(); if(!have_mouse()) { @@ -159,11 +161,6 @@ break_evloop: return 0; } -long app_getmsec(void) -{ - return time(0) * 1000; /* TODO */ -} - void app_redisplay(int x, int y, int w, int h) { rtk_rect r; diff --git a/src/dos/pit8254.h b/src/dos/pit8254.h index 4389883..5d45f55 100644 --- a/src/dos/pit8254.h +++ b/src/dos/pit8254.h @@ -1,20 +1,3 @@ -/* -colcycle - color cycling image viewer -Copyright (C) 2016 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 PIT8254_H_ #define PIT8254_H_ diff --git a/src/dos/timer.c b/src/dos/timer.c new file mode 100644 index 0000000..b7cd6a2 --- /dev/null +++ b/src/dos/timer.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include + +#ifdef __WATCOMC__ +#include +#endif + +#ifdef __DJGPP__ +#include +#include +#include +#endif + +#include "pit8254.h" +#include "inttypes.h" +#include "util.h" +#include "dosutil.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); + +#ifdef __WATCOMC__ +#define INTERRUPT __interrupt __far + +static void INTERRUPT dos_timer_intr(); + +static void (INTERRUPT *prev_timer_intr)(); +#endif + +#ifdef __DJGPP__ +#define INTERRUPT + +static _go32_dpmi_seginfo intr, prev_intr; +#endif + +static void INTERRUPT timer_irq(); + +static volatile 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; +#ifdef __WATCOMC__ + prev_timer_intr = _dos_getvect(inum); + _dos_setvect(inum, timer_irq); +#endif +#ifdef __DJGPP__ + _go32_dpmi_get_protected_mode_interrupt_vector(inum, &prev_intr); + intr.pm_offset = (intptr_t)timer_irq; + intr.pm_selector = _go32_my_cs(); + _go32_dpmi_allocate_iret_wrapper(&intr); + _go32_dpmi_set_protected_mode_interrupt_vector(inum, &intr); +#endif + } else { + tick_interval = 55; + + inum = DOS_TIMER_INTR; +#ifdef __WATCOMC__ + prev_timer_intr = _dos_getvect(inum); + _dos_setvect(inum, dos_timer_intr); +#endif +#ifdef __DJGPP__ + assert(0); +#endif + } + _enable(); + + atexit(cleanup); +} + +static void cleanup(void) +{ + if(!inum) { + 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 */ +#ifdef __WATCOMC__ + _dos_setvect(inum, prev_timer_intr); +#endif +#ifdef __DJGPP__ + _go32_dpmi_set_protected_mode_interrupt_vector(inum, &prev_intr); + _go32_dpmi_free_iret_wrapper(&intr); +#endif + + _enable(); +} + +void reset_timer(void) +{ + ticks = 0; +} + +unsigned long get_msec(void) +{ + return ticks * tick_interval; +} + +void sleep_msec(unsigned long msec) +{ + unsigned long wakeup_time = ticks + msec / tick_interval; + while(ticks < wakeup_time) { +#ifdef USE_HLT + halt(); +#endif + } +} + +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); +} + +#ifdef __WATCOMC__ +static void INTERRUPT dos_timer_intr() +{ + ticks++; + _chain_intr(prev_timer_intr); /* DOES NOT RETURN */ +} +#endif + +/* first PIC command port */ +#define PIC1_CMD 0x20 +/* end of interrupt control word */ +#define OCW2_EOI (1 << 5) + +static void INTERRUPT timer_irq() +{ + static unsigned long dos_ticks; + + ticks++; + +#ifdef __WATCOMC__ + 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); /* XXX DOES NOT RETURN */ + return; /* just for clarity */ + } +#endif + + /* send EOI to the PIC */ + outp(PIC1_CMD, OCW2_EOI); +} diff --git a/src/modern/main.c b/src/modern/main.c index 5c90787..601b2ef 100644 --- a/src/modern/main.c +++ b/src/modern/main.c @@ -96,9 +96,9 @@ int main(int argc, char **argv) return 0; } -long app_getmsec(void) +unsigned long get_msec(void) { - return glutGet(GLUT_ELAPSED_TIME); + return (unsigned long)glutGet(GLUT_ELAPSED_TIME); } void app_redisplay(int x, int y, int w, int h) diff --git a/src/scr_mod.c b/src/scr_mod.c index efa4cb0..b1cbc1d 100644 --- a/src/scr_mod.c +++ b/src/scr_mod.c @@ -69,6 +69,7 @@ enum { static rtk_widget *tools[NUM_TOOLS]; static int vpdirty; +static rtk_rect totalrend; static int mdl_init(void); @@ -388,15 +389,20 @@ static void mdl_mouse(int bn, int press, int x, int y) app_rband(0, 0, 0, 0); if(cur_tool == TOOL_REND_AREA) { - if(prev_tool >= 0) { - act_settool(prev_tool); + if(rband.width && rband.height) { + rendering = 1; + rend_size(win_width, win_height); + rtk_fix_rect(&rband); + rendrect = rband; + rend_begin(rband.x, rband.y, rband.width, rband.height); + app_redisplay(rband.x, rband.y, rband.width, rband.height); + + if(totalrend.width) { + rtk_rect_union(&totalrend, &rband); + } else { + totalrend = rband; + } } - rendering = 1; - rend_size(win_width, win_height); - rtk_fix_rect(&rband); - rendrect = rband; - rend_begin(rband.x, rband.y, rband.width, rband.height); - app_redisplay(rband.x, rband.y, rband.width, rband.height); } } else if(bn == 0 && x == rband.x && y == rband.y) { @@ -518,6 +524,13 @@ static void act_settool(int tidx) int i; rtk_rect r; + if(tidx == prev_tool) return; + + if(prev_tool == TOOL_REND_AREA) { + app_redisplay(totalrend.x, totalrend.y, totalrend.width, totalrend.height); + totalrend.width = 0; + } + prev_tool = cur_tool; cur_tool = tidx; for(i=0; i