]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/event.cpp
Removed some cruft and nonstandard int/uint types, added M series BIOS.
[virtualjaguar] / src / event.cpp
index 734ad87bdad92709038988cd0d3cb461a64e6c19..6951d16fc32fc679db7278dd6b13b668baa8f567 100644 (file)
@@ -1,7 +1,16 @@
 //
 // System time handlers
 //
-// by James L. Hammons
+// by James Hammons
+// (C) 2010 Underground Software
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  01/16/2010  Created this log ;-)
+//
+
 //
 // STILL TO DO:
 //
 
 #include "event.h"
 
+#include <stdint.h>
 #include "log.h"
 
-#define EVENT_LIST_SIZE       512
 
-/*
-// Current execution path:
-
-do
-{
-       HandleJoystick
-
-       // Execute one frame
-
-    for(int i=0; i<numLines; i++)
-    {
-               ExecuteM68K
-               ExecutePITs
-               ExecuteGPU
-               ExecuteDSP
-               // Render Scanline
-               CallObjectProcessor
-               MoveLineBufToBackBuf
-    }
-
-       RenderBackbuffer
-}
-while (true)
-
-// What we need to do:
-
-Set up timers (frame [for native render--on vblank interval?], OP line, PITs)
-
-do
-{
-       double timeToNextEvent = GetTimeToNextEvent();
-
-       m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
-       GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
-       DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
-
-       HandleNextEvent();
-}
-while (true)
+//#define EVENT_LIST_SIZE       512
+#define EVENT_LIST_SIZE       32
 
 
-*/
-
 // Now, a bit of weirdness: It seems that the number of lines displayed on the screen
 // makes the effective refresh rate either 30 or 25 Hz!
 
@@ -71,136 +41,255 @@ while (true)
 
 struct Event
 {
-    bool valid;
-    double eventTime;
-    void (* timerCallback)(void);
+       bool valid;
+       int eventType;
+       double eventTime;
+       void (* timerCallback)(void);
 };
 
-Event eventList[EVENT_LIST_SIZE];
-uint32 nextEvent;
+
+static Event eventList[EVENT_LIST_SIZE];
+static Event eventListJERRY[EVENT_LIST_SIZE];
+static uint32_t nextEvent;
+static uint32_t nextEventJERRY;
+static uint32_t numberOfEvents;
+
 
 void InitializeEventList(void)
 {
-    for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
-        eventList[i].valid = false;
+       for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
+       {
+               eventList[i].valid = false;
+               eventListJERRY[i].valid = false;
+       }
+
+       numberOfEvents = 0;
+       WriteLog("EVENT: Cleared event list.\n");
 }
 
-//We just slap the next event into the list, no checking, no nada...
-void SetCallbackTime(void (* callback)(void), double time)
+
+// Set callback time in µs. This is fairly arbitrary, but works well enough for our purposes.
+//We just slap the next event into the list in the first available slot, no checking, no nada...
+void SetCallbackTime(void (* callback)(void), double time, int type/*= EVENT_MAIN*/)
 {
-    for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
-    {
-        if (!eventList[i].valid)
-        {
-//WriteLog("SCT: Found callback slot #%u...\n", i);
-            eventList[i].timerCallback = callback;
-            eventList[i].eventTime = time;
-            eventList[i].valid = true;
-
-            return;
-        }
-    }
-
-    WriteLog("SetCallbackTime() failed to find an empty slot in the list!\n");
+       if (type == EVENT_MAIN)
+       {
+               for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
+               {
+                       if (!eventList[i].valid)
+                       {
+//WriteLog("EVENT: Found callback slot #%u...\n", i);
+                               eventList[i].timerCallback = callback;
+                               eventList[i].eventTime = time;
+                               eventList[i].eventType = type;
+                               eventList[i].valid = true;
+                               numberOfEvents++;
+
+                               return;
+                       }
+               }
+
+               WriteLog("EVENT: SetCallbackTime() failed to find an empty slot in the main list (%u events)!\n", numberOfEvents);
+       }
+       else
+       {
+               for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
+               {
+                       if (!eventListJERRY[i].valid)
+                       {
+//WriteLog("EVENT: Found callback slot #%u...\n", i);
+                               eventListJERRY[i].timerCallback = callback;
+                               eventListJERRY[i].eventTime = time;
+                               eventListJERRY[i].eventType = type;
+                               eventListJERRY[i].valid = true;
+                               numberOfEvents++;
+
+                               return;
+                       }
+               }
+
+               WriteLog("EVENT: SetCallbackTime() failed to find an empty slot in the main list (%u events)!\n", numberOfEvents);
+       }
 }
 
+
 void RemoveCallback(void (* callback)(void))
 {
-    for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
-    {
-        if (eventList[i].valid && eventList[i].timerCallback == callback)
-        {
-            eventList[i].valid = false;
-
-            return;
-        }
-    }
+       for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
+       {
+               if (eventList[i].valid && eventList[i].timerCallback == callback)
+               {
+                       eventList[i].valid = false;
+                       numberOfEvents--;
+
+                       return;
+               }
+               else if (eventListJERRY[i].valid && eventListJERRY[i].timerCallback == callback)
+               {
+                       eventListJERRY[i].valid = false;
+                       numberOfEvents--;
+
+                       return;
+               }
+       }
 }
 
+
 void AdjustCallbackTime(void (* callback)(void), double time)
 {
-    for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
-    {
-        if (eventList[i].valid && eventList[i].timerCallback == callback)
-        {
-            eventList[i].eventTime = time;
-
-            return;
-        }
-    }
+       for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
+       {
+               if (eventList[i].valid && eventList[i].timerCallback == callback)
+               {
+                       eventList[i].eventTime = time;
+
+                       return;
+               }
+               else if (eventListJERRY[i].valid && eventListJERRY[i].timerCallback == callback)
+               {
+                       eventListJERRY[i].eventTime = time;
+
+                       return;
+               }
+       }
 }
 
-double GetTimeToNextEvent(void)
-{
-    double time = 0;
-    bool firstTime = true;
-
-    for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
-    {
-        if (eventList[i].valid)
-        {
-            if (firstTime)
-                time = eventList[i].eventTime, nextEvent = i, firstTime = false;
-            else
-            {
-                if (eventList[i].eventTime < time)
-                    time = eventList[i].eventTime, nextEvent = i;
-            }
-        }
-    }
-
-    return time;
-}
 
-void HandleNextEvent(void)
+//
+// Since our list is unordered WRT time, we have to search it to find the next event
+// Returns time to next event & sets nextEvent to that event
+//
+double GetTimeToNextEvent(int type/*= EVENT_MAIN*/)
 {
-    double elapsedTime = eventList[nextEvent].eventTime;
-    void (* event)(void) = eventList[nextEvent].timerCallback;
-
-    for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
-        if (eventList[i].valid)
-            eventList[i].eventTime -= elapsedTime;
+#if 0
+       double time = 0;
+       bool firstTime = true;
+
+       for(uint32 i=0; i<EVENT_LIST_SIZE; i++)
+       {
+               if (eventList[i].valid)
+               {
+                       if (firstTime)
+                               time = eventList[i].eventTime, nextEvent = i, firstTime = false;
+                       else
+                       {
+                               if (eventList[i].eventTime < time)
+                                       time = eventList[i].eventTime, nextEvent = i;
+                       }
+               }
+       }
+#else
+       if (type == EVENT_MAIN)
+       {
+               double time = eventList[0].eventTime;
+               nextEvent = 0;
+
+               for(uint32_t i=1; i<EVENT_LIST_SIZE; i++)
+               {
+                       if (eventList[i].valid && (eventList[i].eventTime < time))
+                       {
+                               time = eventList[i].eventTime;
+                               nextEvent = i;
+                       }
+               }
+
+               return time;
+       }
+       else
+       {
+               double time = eventListJERRY[0].eventTime;
+               nextEventJERRY = 0;
+
+               for(uint32_t i=1; i<EVENT_LIST_SIZE; i++)
+               {
+                       if (eventListJERRY[i].valid && (eventListJERRY[i].eventTime < time))
+                       {
+                               time = eventListJERRY[i].eventTime;
+                               nextEventJERRY = i;
+                       }
+               }
+
+               return time;
+       }
+#endif
+}
 
-    eventList[nextEvent].valid = false;      // Remove event from list...
 
-    (*event)();
+void HandleNextEvent(int type/*= EVENT_MAIN*/)
+{
+       if (type == EVENT_MAIN)
+       {
+               double elapsedTime = eventList[nextEvent].eventTime;
+               void (* event)(void) = eventList[nextEvent].timerCallback;
+
+               for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
+               {
+       //We can skip the check & just subtract from everything, since the check is probably
+       //just as heavy as the code after and we won't use the elapsed time from an invalid event anyway.
+       //              if (eventList[i].valid)
+                               eventList[i].eventTime -= elapsedTime;
+               }
+
+               eventList[nextEvent].valid = false;                     // Remove event from list...
+               numberOfEvents--;
+
+               (*event)();
+       }
+       else
+       {
+               double elapsedTime = eventListJERRY[nextEventJERRY].eventTime;
+               void (* event)(void) = eventListJERRY[nextEventJERRY].timerCallback;
+
+               for(uint32_t i=0; i<EVENT_LIST_SIZE; i++)
+               {
+       //We can skip the check & just subtract from everything, since the check is probably
+       //just as heavy as the code after and we won't use the elapsed time from an invalid event anyway.
+       //              if (eventList[i].valid)
+                               eventListJERRY[i].eventTime -= elapsedTime;
+               }
+
+               eventListJERRY[nextEventJERRY].valid = false;   // Remove event from list...
+               numberOfEvents--;
+
+               (*event)();
+       }
 }
 
 
 /*
 void OPCallback(void)
 {
-    DoFunkyOPStuffHere();
+       DoFunkyOPStuffHere();
 
-    SetCallbackTime(OPCallback, HORIZ_PERIOD_IN_USEC);
+       SetCallbackTime(OPCallback, HORIZ_PERIOD_IN_USEC);
 }
 
 void VICallback(void)
 {
-    double oneFrameInUsec = 16666.66666666;
-    SetCallbackTime(VICallback, oneFrameInUsec / numberOfLines);
+       double oneFrameInUsec = 16666.66666666;
+       SetCallbackTime(VICallback, oneFrameInUsec / numberOfLines);
 }
 
 void JaguarInit(void)
 {
-    double oneFrameInUsec = 16666.66666666;
-    SetCallbackTime(VICallback, oneFrameInUsec / numberOfLines);
-    SetCallbackTime(OPCallback, );
+       double oneFrameInUsec = 16666.66666666;
+       SetCallbackTime(VICallback, oneFrameInUsec / numberOfLines);
+       SetCallbackTime(OPCallback, );
 }
 
 void JaguarExec(void)
 {
-    while (true)
-    {
-        double timeToNextEvent = GetTimeToNextEvent();
+       while (true)
+       {
+               double timeToNextEvent = GetTimeToNextEvent();
 
-        m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
-        GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
-        DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
+               m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
+               GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
+               DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
 
-        if (!HandleNextEvent())
-            break;
-    }
+               if (!HandleNextEvent())
+                       break;
+       }
 }
 
 // NOTES: The timers count RISC cycles, and when the dividers count down to zero they can interrupt either the DSP and/or CPU.
@@ -212,25 +301,25 @@ void JaguarExec(void)
 
 void TOMResetPIT()
 {
-    // Need to remove previous timer from the queue, if it exists...
-    RemoveCallback(TOMPITCallback);
-
-    if (TOMPITPrescaler)
-    {
-        double usecs = (TOMPITPrescaler + 1) * (TOMPITDivider + 1) * RISC_CYCLE_IN_USEC;
-        SetCallbackTime(TOMPITCallback, usecs);
-    }
+       // Need to remove previous timer from the queue, if it exists...
+       RemoveCallback(TOMPITCallback);
+
+       if (TOMPITPrescaler)
+       {
+               double usecs = (TOMPITPrescaler + 1) * (TOMPITDivider + 1) * RISC_CYCLE_IN_USEC;
+               SetCallbackTime(TOMPITCallback, usecs);
+       }
 }
 
 void TOMPITCallback(void)
 {
-    INT1_RREG |= 0x08;                         // Set TOM PIT interrupt pending
-    GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);  // It does the 'IRQ enabled' checking
+       INT1_RREG |= 0x08;                         // Set TOM PIT interrupt pending
+       GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);  // It does the 'IRQ enabled' checking
 
-    if (INT1_WREG & 0x08)
-        m68k_set_irq(7);                       // Generate 68K NMI
+       if (INT1_WREG & 0x08)
+               m68k_set_irq(2);                       // Generate 68K NMI
 
-    TOMResetPIT();
+       TOMResetPIT();
 }
 
 // Small problem with this approach: If a timer interrupt is already pending,
@@ -238,16 +327,16 @@ void TOMPITCallback(void)
 
 TOMWriteWord(uint32 address, uint16 data)
 {
-    if (address == PIT0)
-    {
-        TOMPITPrescaler = data;
-        TOMResetPIT();
-    }
-    else if (address == PIT1)
-    {
-        TOMPITDivider = data;
-        TOMResetPIT();
-    }
+       if (address == PIT0)
+       {
+               TOMPITPrescaler = data;
+               TOMResetPIT();
+       }
+       else if (address == PIT1)
+       {
+               TOMPITDivider = data;
+               TOMResetPIT();
+       }
 }
 
 */