!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 &
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 &
#include <time.h>
#include "gaw/gaw.h"
#include "app.h"
+#include "timer.h"
#include "rend.h"
#include "options.h"
#include "font.h"
}
}
- time_msec = app_getmsec();
+ time_msec = get_msec();
for(i=0; i<num_screens; i++) {
if(screens[i]->name && start_scr_name && strcmp(screens[i]->name, start_scr_name) == 0) {
void app_display(void)
{
- time_msec = app_getmsec();
+ time_msec = get_msec();
cur_scr->display();
}
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
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);
#include <ctype.h>
#include <time.h>
#include "app.h"
+#include "timer.h"
#include "keyb.h"
#include "vidsys.h"
#include "cdpmi.h"
print_cpuid(&cpuid);
}
+ init_timer(0);
kb_init();
if(!have_mouse()) {
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;
-/*
-colcycle - color cycling image viewer
-Copyright (C) 2016 John Tsiombikas <nuclear@member.fsf.org>
-
-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 <http://www.gnu.org/licenses/>.
-*/
#ifndef PIT8254_H_
#define PIT8254_H_
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <conio.h>
+#include <dos.h>
+
+#ifdef __WATCOMC__
+#include <i86.h>
+#endif
+
+#ifdef __DJGPP__
+#include <dpmi.h>
+#include <go32.h>
+#include <pc.h>
+#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);
+}
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)
static rtk_widget *tools[NUM_TOOLS];
static int vpdirty;
+static rtk_rect totalrend;
static int mdl_init(void);
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) {
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<NUM_TOOLS; i++) {
--- /dev/null
+#ifndef TIMER_H_
+#define TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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);
+
+void sleep_msec(unsigned long msec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TIMER_H_ */