started backporting the eradicate code
[dosdemo] / src / dos / timer.c
index dfadd25..2440bd5 100644 (file)
@@ -1,26 +1,27 @@
-/*
-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/>.
-*/
+/* for sound we use MIDAS, which takes over the PIT and we can't use it
+ * therefore only compile this file for NO_SOUND builds.
+ */
+#ifdef NO_SOUND
+
 #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"
 
 #define PIT_TIMER_INTR 8
 #define DOS_TIMER_INTR 0x1c
@@ -31,12 +32,26 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 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)();
+#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;
 
-static unsigned long ticks;
+#define outp(p, v)     outportb(p, v)
+#endif
+
+static void INTERRUPT timer_irq();
+
+static volatile unsigned long ticks;
 static unsigned long tick_interval, ticks_per_dos_intr;
 static int inum;
 
@@ -52,14 +67,28 @@ void init_timer(int 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();
 
@@ -68,7 +97,7 @@ void init_timer(int res_hz)
 
 static void cleanup(void)
 {
-       if(!prev_timer_intr) {
+       if(!inum) {
                return; /* init hasn't ran, there's nothing to cleanup */
        }
 
@@ -79,7 +108,14 @@ static void cleanup(void)
        }
 
        /* 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();
 }
 
@@ -93,6 +129,16 @@ 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);
@@ -100,23 +146,26 @@ static void set_timer_reload(int reload_val)
        outp(PORT_DATA0, (reload_val >> 8) & 0xff);
 }
 
-static void __interrupt __far dos_timer_intr()
+#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 __far timer_irq()
+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
@@ -125,7 +174,10 @@ static void __interrupt __far timer_irq()
                _chain_intr(prev_timer_intr);   /* XXX DOES NOT RETURN */
                return; /* just for clarity */
        }
+#endif
 
        /* send EOI to the PIC */
        outp(PIC1_CMD, OCW2_EOI);
 }
+
+#endif /* NO_SOUND */