]> Shamusworld >> Repos - virtualjaguar/commitdiff
More enhancements to the file chooser.
authorShamus Hammons <jlhamm@acm.org>
Tue, 12 Jul 2011 18:12:41 +0000 (18:12 +0000)
committerShamus Hammons <jlhamm@acm.org>
Tue, 12 Jul 2011 18:12:41 +0000 (18:12 +0000)
res/homebrew-file.png
res/skunkboard-file.png [new file with mode: 0644]
src/filedb.cpp
src/gui/filepicker.cpp
src/gui/mainwin.cpp
src/gui/virtualjaguar.qrc
src/mmu.cpp [new file with mode: 0644]
src/mmu.h [new file with mode: 0644]

index 2702059637357f94fc165a8b3d263be62969de0b..92e8184d6e94327f054071447fb33bfc61e94752 100644 (file)
Binary files a/res/homebrew-file.png and b/res/homebrew-file.png differ
diff --git a/res/skunkboard-file.png b/res/skunkboard-file.png
new file mode 100644 (file)
index 0000000..5918033
Binary files /dev/null and b/res/skunkboard-file.png differ
index 47c31efe8ad9ef76c8af8a0aea26bcec14f73d71..0d835c99496f530552860b68646acab459a261cf 100644 (file)
@@ -37,7 +37,7 @@ enum FileFlags { FF_ROM=1, FF_ALPINE=2, FF_BIOS=4, FF_REQ_DSP=8, FF_REQ_BIOS=16,
 // that somebody slapped a universal header on.
 
 RomIdentifier romList[] = {
-       { 0x0509C85E, "Raiden (World) (alt)", FF_ROM },
+       { 0x0509C85E, "Raiden (World) (alt)", FF_ROM | FF_REQ_BIOS },
        { 0x08849D0F, "Hyper Force (World)", FF_ALPINE | FF_VERIFIED },
        { 0x08F15576, "Iron Soldier (World) (v1.04)", FF_ROM | FF_VERIFIED },
        { 0x0957A072, "Kasumi Ninja (World)", FF_ROM | FF_VERIFIED },
index 86fbe55b410d25cb62cc1776099a5aed63c06a78..e01f365bb2d7bb8da210dc4b81a6a1eedec7decd 100644 (file)
@@ -353,7 +353,7 @@ void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModel
 // should be valid.
 // The DB takes precedence over the fileType.
                if ((!haveUnknown && (romList[i].flags & FF_ROM))
-                       || (haveUnknown && (fileType == JST_ROM)))
+                       || (haveUnknown && (fileType == JST_ROM) && !haveUniversalHeader))
                {
                        cart = QImage(":/res/cart-blank.png");
                        QPainter painter(&cart);
@@ -361,11 +361,16 @@ void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModel
                        painter.end();
                }
                else if ((!haveUnknown && (romList[i].flags & FF_ALPINE))
-                       || (haveUnknown && (fileType == JST_ALPINE)))
+                       || (haveUnknown
+                               && ((fileType == JST_ALPINE) || ((fileType == JST_ROM) && haveUniversalHeader))))
                {
-                       cart = QImage(":/res/alpine-file.png");
+                       if (haveUniversalHeader)
+                               cart = QImage(":/res/skunkboard-file.png");
+                       else
+                               cart = QImage(":/res/alpine-file.png");
                }
-               else if (haveUnknown && (fileType == JST_ABS_TYPE1 || fileType == JST_ABS_TYPE2 || fileType == JST_JAGSERVER))
+               else if (haveUnknown && (fileType == JST_ABS_TYPE1 || fileType == JST_ABS_TYPE2
+                       || fileType == JST_JAGSERVER))
                {
                        cart = QImage(":/res/homebrew-file.png");
                }
@@ -403,10 +408,20 @@ void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModel
                        fileTypeString = QString(tr("*** UNKNOWN *** (%1 bytes)")).arg(fileSize);
        }
 #else
-       if ((!haveUnknown && (romList[i].flags & FF_ROM)) || (haveUnknown && (fileType == JST_ROM)))
+       if ((!haveUnknown && (romList[i].flags & FF_ROM))
+               || (haveUnknown && (fileType == JST_ROM) && !haveUniversalHeader))
                fileTypeString = QString(tr("%1MB Cartridge")).arg(fileSize / 1048576);
-       else if ((!haveUnknown && (romList[i].flags & FF_ALPINE)) || (haveUnknown && (fileType == JST_ALPINE)))
-               fileTypeString = QString(tr("%1MB Alpine ROM")).arg(fileSize / 1048576);
+       else if ((!haveUnknown && (romList[i].flags & FF_ALPINE))
+               || (haveUnknown
+                               && ((fileType == JST_ALPINE) || ((fileType == JST_ROM) && haveUniversalHeader))))
+       {
+               if (haveUniversalHeader)
+                       fileTypeString = QString(tr("%1MB Alpine ROM w/Universal Header"));
+               else
+                       fileTypeString = QString(tr("%1MB Alpine ROM"));
+
+               fileTypeString = fileTypeString.arg(fileSize / 1048576);
+       }
        else if (haveUnknown && (fileType == JST_ABS_TYPE1 || fileType == JST_ABS_TYPE2))
                fileTypeString = QString(tr("ABS/COF Executable (%1 bytes)")).arg(fileSize);
        else if (haveUnknown && (fileType == JST_JAGSERVER))
@@ -427,8 +442,11 @@ void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModel
        if (!haveUnknown && (romList[i].flags & FF_BAD_DUMP))
                notes = "<b>BAD DUMP</b>";
 
-       if (haveUniversalHeader)
-               notes += " Universal Header detected";
+//     if (haveUniversalHeader)
+//             notes += " Universal Header detected";
+
+       if (!haveUnknown && (romList[i].flags & FF_REQ_BIOS))
+               notes += " Requires BIOS";
 
        if (!haveUnknown && (romList[i].flags & FF_REQ_DSP))
                notes += " Requires DSP";
index e61b369d8002b59edea9b066f84fef3573c16372..3584fb9618fdee1ced7be1874d3696b3aea02a2c 100644 (file)
@@ -275,20 +275,20 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state)
                || (e->key() == vjs.p1KeyBindings[BUTTON_D] && joypad_0_buttons[BUTTON_U]))
                return;
 #else
-       if (e->key() == vjs.p1KeyBindings[BUTTON_L] && joypad_0_buttons[BUTTON_R])
+       if (e->key() == (int)vjs.p1KeyBindings[BUTTON_L] && joypad_0_buttons[BUTTON_R])
                joypad_0_buttons[BUTTON_R] = 0;
-       if (e->key() == vjs.p1KeyBindings[BUTTON_R] && joypad_0_buttons[BUTTON_L])
+       if (e->key() == (int)vjs.p1KeyBindings[BUTTON_R] && joypad_0_buttons[BUTTON_L])
                joypad_0_buttons[BUTTON_L] = 0;
-       if (e->key() == vjs.p1KeyBindings[BUTTON_U] && joypad_0_buttons[BUTTON_D])
+       if (e->key() == (int)vjs.p1KeyBindings[BUTTON_U] && joypad_0_buttons[BUTTON_D])
                joypad_0_buttons[BUTTON_D] = 0;
-       if (e->key() == vjs.p1KeyBindings[BUTTON_D] && joypad_0_buttons[BUTTON_U])
+       if (e->key() == (int)vjs.p1KeyBindings[BUTTON_D] && joypad_0_buttons[BUTTON_U])
                joypad_0_buttons[BUTTON_U] = 0;
 #endif
 
        // No bad combos exist, let's stuff the emulator key buffers...!
        for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
        {
-               if (e->key() == vjs.p1KeyBindings[i])
+               if (e->key() == (int)vjs.p1KeyBindings[i])
                        joypad_0_buttons[i] = (uint8)state;
        }
 }
@@ -528,25 +528,15 @@ void MainWin::ToggleRunState(void)
 
        if (!running)
        {
-#if 0
-               for(uint32_t x=0; x<videoWidget->rasterWidth; x++)
-                       for(uint32_t y=0; y<videoWidget->rasterHeight; y++)
-                               videoWidget->buffer[(y * videoWidget->textureWidth) + x] = 0x00000000;
-#else
-//             for(uint32_t i=0; i<TOMGetVideoModeWidth() * 256; i++)
-               for(uint32_t i=0; i<videoWidget->textureWidth * 256; i++)
+               for(uint32_t i=0; i<(uint32_t)(videoWidget->textureWidth * 256); i++)
                {
                        uint32_t pixel = backbuffer[i];
-//                     uint8_t b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
                        uint8_t r = (pixel >> 24) & 0xFF, g = (pixel >> 16) & 0xFF, b = (pixel >> 8) & 0xFF;
                        pixel = ((r + g + b) / 3) & 0x00FF;
-//                     backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
                        backbuffer[i] = 0x000000FF | (pixel << 16) | (pixel << 8);
                }
 
-//             memcpy(videoWidget->buffer, backbuffer, videoWidget->rasterHeight * videoWidget->rasterWidth);
                memcpy(videoWidget->buffer, backbuffer, videoWidget->rasterHeight * videoWidget->textureWidth * sizeof(uint32_t));
-#endif
 
                videoWidget->updateGL();
        }
index b669798e14b0e54fa6e3019ee05104ff13b14c2a..b5b7e08cad4cfe18d2cc226970c478b01d4169de 100644 (file)
@@ -19,6 +19,7 @@
        <file>../../res/upper-left.png</file>
        <file>../../res/upper-right.png</file>
        <file>../../res/alpine-file.png</file>
+       <file>../../res/skunkboard-file.png</file>
        <file>../../res/homebrew-file.png</file>
        <file>../../res/unknown-file.png</file>
 </qresource>
diff --git a/src/mmu.cpp b/src/mmu.cpp
new file mode 100644 (file)
index 0000000..65656b1
--- /dev/null
@@ -0,0 +1,604 @@
+//
+// mmu.cpp
+//
+// Jaguar Memory Manager Unit
+//
+// by James L. Hammons
+//
+// JLH = James L. Hammons
+//
+// WHO  WHEN        WHAT
+// ---  ----------  -----------------------------------------------------------
+// JLH  11/25/2009  Created this file. :-)
+//
+
+#include "mmu.h"
+
+#include <stdlib.h>                                                            // For NULL definition
+#include "dac.h"
+//#include "jaguar.h"
+//#include "memory.h"
+#include "wavetable.h"
+
+/*
+Addresses to be handled:
+
+SYSTEM SETUP REGISTERS
+
+*MEMCON1       Memory Control Register 1                       F00000          RW
+*MEMCON2       Memory Control Register 2                       F00002          RW
+HC                     Horizontal Count                                        F00004          RW
+VC                     Vertical Count                                          F00006          RW
+LPH                    Light Pen Horizontal                            F00008          RO
+LPV                    Light Pen Vertical                                      F0000A          RO
+OB[0-3]                Object Data Field                                       F00010-16       RO
+OLP                    Object List Pointer                                     F00020-23       WO
+OBF                    Object Flag                                                     F00026          WO
+VMODE          Video Mode                                                      F00028          WO
+BORD1          Border Colour (Red & Green)                     F0002A          WO
+BORD2          Border Colour (Blue)                            F0002C          WO
+*HP                    Horizontal Period                                       F0002E          WO
+*HBB           Horizontal Blank Begin                          F00030          WO
+*HBE           Horizontal Blank End                            F00032          WO
+*HS                    Horizontal Sync                                         F00034          WO
+*HVS           Horizontal Vertical Sync                        F00036          WO
+HDB1           Horizontal Display Begin 1                      F00038          WO
+HDB2           Horizontal Display Begin 2                      F0003A          WO
+HDE                    Horizontal Display End                          F0003C          WO
+*VP                    Vertical Period                                         F0003E          WO
+*VBB           Vertical Blank Begin                            F00040          WO
+*VBE           Vertical Blank End                                      F00042          WO
+*VS                    Vertical Sync                                           F00044          WO
+VDB                    Vertical Display Begin                          F00046          WO
+VDE                    Vertical Display End                            F00048          WO
+*VEB           Vertical Equalization Begin                     F0004A          WO
+*VEE           Vertical Equalization End                       F0004C          WO
+VI                     Vertical Interrupt                                      F0004E          WO
+PIT[0-1]       Programmable Interrupt Timer            F00050-52       WO
+*HEQ           Horizontal Equalization End                     F00054          WO
+BG                     Background Colour                                       F00058          WO
+INT1           CPU Interrupt Control Register          F000E0          RW
+INT2           CPU Interrupt Resume Register           F000E2          WO
+CLUT           Colour Look-Up Table                            F00400-7FE      RW
+LBUF           Line Buffer                                                     F00800-1D9E     RW
+
+GPU REGISTERS
+
+G_FLAGS                GPU Flags Register                                      F02100          RW
+G_MTXC         Matrix Control Register                         F02104          WO
+G_MTXA         Matrix Address Register                         F02108          WO
+G_END          Data Organization Register                      F0210C          WO
+G_PC           GPU Program Counter                                     F02110          RW
+G_CTRL         GPU Control/Status Register                     F02114          RW
+G_HIDATA       High Data Register                                      F02118          RW
+G_REMAIN       Divide Unit Remainder                           F0211C          RO
+G_DIVCTRL      Divide Unit Control                                     F0211C          WO
+
+BLITTER REGISTERS
+
+A1_BASE                A1 Base Register                                        F02200          WO
+A1_FLAGS       Flags Register                                          F02204          WO
+A1_CLIP                A1 Clipping Size                                        F02208          WO
+A1_PIXEL       A1 Pixel Pointer                                        F0220C          WO
+                                                                                               F02204          RO
+A1_STEP                A1 Step Value                                           F02210          WO
+A1_FSTEP       A1 Step Fraction Value                          F02214          WO
+A1_FPIXEL      A1 Pixel Pointer Fraction                       F02218          RW
+A1_INC         A1 Increment                                            F0221C          WO
+A1_FINC                A1 Increment Fraction                           F02220          WO
+A2_BASE                A2 Base Register                                        F02224          WO
+A2_FLAGS       A2 Flags Register                                       F02228          WO
+A2_MASK                A2 Window Mask                                          F0222C          WO
+A2_PIXEL       A2 Pixel Pointer                                        F02230          WO
+                                                                                               F0222C          RO
+A2_STEP                A2 Step Value                                           F02234          WO
+B_CMD          Command/Status Register                         F02238          RW
+B_COUNT                Counters Register                                       F0223C          WO
+B_SRCD         Source Data Register                            F02240          WO
+B_DSTD         Destination Data Register                       F02248          WO
+B_DSTZ         Destination Z Register                          F02250          WO
+B_SRCZ1                Source Z Register 1                                     F02258          WO
+B_SRCZ2                Source Z Register 2                                     F02260          WO
+B_PATD         Pattern Data Register                           F02268          WO
+B_IINC         Intensity Increment                                     F02270          WO
+B_ZINC         Z Increment                                                     F02274          WO
+B_STOP         Collision Control                                       F02278          WO
+B_I3           Intensity 3                                                     F0227C          WO
+B_I2           Intensity 2                                                     F02280          WO
+B_I1           Intensity 1                                                     F02284          WO
+B_I0           Intensity 0                                                     F02288          WO
+B_Z3           Z 3                                                                     F0228C          WO
+B_Z2           Z 2                                                                     F02290          WO
+B_Z1           Z 1                                                                     F02294          WO
+B_Z0           Z 0                                                                     F02298          WO
+
+JERRY REGISTERS
+
+*CLK1          Processor Clock Divider                         F10010          WO
+*CLK2          Video Clock Divider                                     F10012          WO
+*CLK3          Chroma Clock Divider                            F10014          WO
+JPIT1          Timer 1 Pre-scaler                                      F10000          WO
+JPIT3          Timer 2 Pre-scaler                                      F10004          WO
+JPIT2          Timer 1 Divider                                         F10002          WO
+JPIT4          Timer 2 Divider                                         F10006          WO
+J_INT          Interrup Control Register                       F10020          RW
+SCLK           Serial Clock Frequency                          F1A150          WO
+SMODE          Serial Mode                                                     F1A154          WO
+LTXD           Left Transmit Data                                      F1A148          WO
+RTXD           Right Transmit Data                                     F1A14C          WO
+LRXD           Left Receive Data                                       F1A148          RO
+RRXD           Right Receive Data                                      F1A14C          RO
+L_I2S          Left I2S Serial Interface                       F1A148          RW
+R_I2S          Right I2S Serial Interface                      F1A14C          RW
+SSTAT          Serial Status                                           F1A150          RO
+ASICLK         Asynchronous Serial Interface Clock     F10034          RW
+ASICTRL                Asynchronous Serial Control                     F10032          WO
+ASISTAT                Asynchronous Serial Status                      F10032          RO
+ASIDATA                Asynchronous Serial Data                        F10030          RW
+
+JOYSTICK REGISTERS
+
+JOYSTICK       Joystick Register                                       F14000          RW
+JOYBUTS                Button Register                                         F14002          RW
+
+DSP REGISTERS
+
+D_FLAGS                DSP Flags Register                                      F1A100          RW
+D_MTXC         DSP Matrix Control Register                     F1A104          WO
+D_MTXA         DSP Matrix Address Register                     F1A108          WO
+D_END          DSP Data Organization Register          F1A10C          WO
+D_PC           DSP Program Counter                                     F1A110          RW
+D_CTRL         DSP Control/Status Register                     F1A114          RW
+D_MOD          Modulo Instruction Mask                         F1A118          WO
+D_REMAIN       Divide Unit Remainder                           F1A11C          RO
+D_DIVCTRL      Divide Unit Control                                     F1A11C          WO
+D_MACHI                MAC High Result Bits                            F1A120          RO
+*/
+
+/*
+The approach here is to have a list of addresses and who handles them. Could be
+a one-to-one memory location up to a range for each function. Will look
+something like this:
+
+       { 0xF14000, 0xF14001, MM_IO, JoystickReadHandler, JoystickWriteHandler },
+
+Would be nice to have a way of either calling a handler function or reading/writing
+directly to/from a variable or array...
+*/
+
+enum MemType { MM_NOP = 0, MM_RAM = 1, MM_ROM = 2, MM_IO_R = 4, MM_IO_W = 8, MM_IO = 12 };
+
+/*
+Would be nice to have different structs tailored to different memory access types,
+but if we don't do that, we can encode things as follows:
+
+MM_NOP: readFunc = writeFunc = NULL
+MM_RAM: readFunc = byte array pointer, writeFunc = NULL
+MM_ROM: readFunc = byte array pointer, writeFunc = NULL
+MM_IO_R: readFunc = function pointer to read function, writeFunc = NULL
+MM_IO_W: readFunc = NULL, writeFunc = function pointer to write function
+MM_IO: readFunc = function pointer to read function, writeFunc = function pointer to write function
+
+There may be a need to have readFunc do both read & write functions (makes sense? perhaps)
+
+Should we have a read mask as well, for the purposes of reading?
+*/
+
+struct MemDesc {
+       uint32 startAddr;
+       uint32 endAddr;
+       MemType type;
+//     (void (* ioFunc)(uint32, uint32)); // <-- could also be a pointer to RAM...
+       void * readFunc;                                        // This is read & write with MM_IO
+       void * writeFunc;
+       uint32 mask;
+};
+
+
+MemDesc memoryMap[] = {
+       { 0x000000, 0x3FFFFF, MM_RAM,  jaguarMainRAM },
+       { 0x800000, 0xDFFEFF, MM_ROM,  jaguarMainROM },
+
+       { 0xDFFF00, 0xDFFF03, MM_IO,   &butch }, // base of Butch == interrupt control register, R/W
+       { 0xDFFF04, 0xDFFF07, MM_IO,   &dscntrl }, // DSA control register, R/W
+       { 0xDFFF0A, 0xDFFF0B, MM_IO,   &ds_data }, // DSA TX/RX data, R/W
+       { 0xDFFF10, 0xDFFF13, MM_IO,   &i2cntrl }, // i2s bus control register, R/W
+       { 0xDFFF14, 0xDFFF17, MM_IO,   &sbcntrl }, // CD subcode control register, R/W
+       { 0xDFFF18, 0xDFFF1B, MM_IO,   &subdata }, // Subcode data register A
+       { 0xDFFF1C, 0xDFFF1F, MM_IO,   &subdatb }, // Subcode data register B
+       { 0xDFFF20, 0xDFFF23, MM_IO,   &sb_time }, // Subcode time and compare enable (D24)
+       { 0xDFFF24, 0xDFFF27, MM_IO,   &fifo_data }, // i2s FIFO data
+       { 0xDFFF28, 0xDFFF2B, MM_IO,   &i2sdat2 }, // i2s FIFO data (old)
+       { 0xDFFF2C, 0xDFFF2F, MM_IO,   &unknown }, // Seems to be some sort of I2S interface
+
+       { 0xE00000, 0xE3FFFF, MM_ROM,  jaguarBootROM },
+
+       // TOM REGISTERS
+
+       { 0xF00000, 0xF00001, MM_IO,   &memcon1 }, // *MEMCON1  Memory Control Register 1                       F00000          RW
+       { 0xF00002, 0xF00003, MM_IO,   &memcon2 }, // *MEMCON2  Memory Control Register 2                       F00002          RW
+       { 0xF00004, 0xF00005, MM_IO,   &hc }, // HC                     Horizontal Count                                        F00004          RW
+       { 0xF00006, 0xF00007, MM_IO,   &vc }, // VC                     Vertical Count                                          F00006          RW
+       { 0xF00008, 0xF00009, MM_IO_R, &lph }, // LPH                   Light Pen Horizontal                            F00008          RO
+       { 0xF0000A, 0xF0000B, MM_IO_R, &lpv }, // LPV                   Light Pen Vertical                                      F0000A          RO
+       { 0xF00010, 0xF00017, MM_IO_R, &obData }, // OB[0-3]            Object Data Field                                       F00010-16       RO
+       { 0xF00020, 0xF00023, MM_IO_W, &olp }, // OLP                   Object List Pointer                                     F00020-23       WO
+       { 0xF00026, 0xF00027, MM_IO_W, &obf }, // OBF                   Object Flag                                                     F00026          WO
+       { 0xF00028, 0xF00029, MM_IO_W, &vmode }, // VMODE               Video Mode                                                      F00028          WO
+       { 0xF0002A, 0xF0002B, MM_IO_W, &bord1 }, // BORD1               Border Colour (Red & Green)                     F0002A          WO
+       { 0xF0002C, 0xF0002D, MM_IO_W, &bord2 }, // BORD2               Border Colour (Blue)                            F0002C          WO
+       { 0xF0002E, 0xF0002F, MM_IO_W, &hp }, // *HP                    Horizontal Period                                       F0002E          WO
+       { 0xF00030, 0xF00031, MM_IO_W, &hbb }, // *HBB          Horizontal Blank Begin                          F00030          WO
+       { 0xF00032, 0xF00033, MM_IO_W, &hbe }, // *HBE          Horizontal Blank End                            F00032          WO
+       { 0xF00034, 0xF00035, MM_IO_W, &hs }, // *HS                    Horizontal Sync                                         F00034          WO
+       { 0xF00036, 0xF00037, MM_IO_W, &hvs }, // *HVS          Horizontal Vertical Sync                        F00036          WO
+       { 0xF00038, 0xF00039, MM_IO_W, &hdb1 }, // HDB1         Horizontal Display Begin 1                      F00038          WO
+       { 0xF0003A, 0xF0003B, MM_IO_W, &hdb2 }, // HDB2         Horizontal Display Begin 2                      F0003A          WO
+       { 0xF0003C, 0xF0003D, MM_IO_W, &hde }, // HDE                   Horizontal Display End                          F0003C          WO
+       { 0xF0003E, 0xF0003F, MM_IO_W, &vp }, // *VP                    Vertical Period                                         F0003E          WO
+       { 0xF00040, 0xF00041, MM_IO_W, &vbb }, // *VBB          Vertical Blank Begin                            F00040          WO
+       { 0xF00042, 0xF00043, MM_IO_W, &vbe }, // *VBE          Vertical Blank End                                      F00042          WO
+       { 0xF00044, 0xF00045, MM_IO_W, &vs }, // *VS                    Vertical Sync                                           F00044          WO
+       { 0xF00046, 0xF00047, MM_IO_W, &vdb }, // VDB                   Vertical Display Begin                          F00046          WO
+       { 0xF00048, 0xF00049, MM_IO_W, &vde }, // VDE                   Vertical Display End                            F00048          WO
+       { 0xF0004A, 0xF0004B, MM_IO_W, &veb }, // *VEB          Vertical Equalization Begin                     F0004A          WO
+       { 0xF0004C, 0xF0004D, MM_IO_W, &vee }, // *VEE          Vertical Equalization End                       F0004C          WO
+       { 0xF0004E, 0xF0004F, MM_IO_W, &vi }, // VI                     Vertical Interrupt                                      F0004E          WO
+       { 0xF00050, 0xF00051, MM_IO_W, &pit0 }, // PIT[0-1]     Programmable Interrupt Timer            F00050-52       WO
+       { 0xF00052, 0xF00053, MM_IO_W, &pit1 },
+       { 0xF00054, 0xF00055, MM_IO_W, &heq }, // *HEQ          Horizontal Equalization End                     F00054          WO
+       { 0xF00058, 0xF0005B, MM_IO_W, &bg }, // BG                     Background Colour                                       F00058          WO
+       { 0xF000E0, 0xF000E1, MM_IO,   &int1 }, // INT1         CPU Interrupt Control Register          F000E0          RW
+       { 0xF000E2, 0xF000E3, MM_IO_W, &int2 }, // INT2         CPU Interrupt Resume Register           F000E2          WO
+//Some of these RAM spaces may be 16- or 32-bit only... in which case, we need
+//to cast appropriately (in memory.cpp, that is)...
+       { 0xF00400, 0xF005FF, MM_RAM,  clut }, // CLUT          Colour Look-Up Table                            F00400-7FE      RW
+       { 0xF00600, 0xF007FF, MM_RAM,  clut },
+       { 0xF00800, 0xF01D9F, MM_RAM,  lbuf }, // LBUF          Line Buffer                                                     F00800-1D9E     RW
+//Need high speed RAM interface for GPU & DSP (we have it now...)
+
+       // GPU REGISTERS
+
+       { 0xF02100, 0xF02103, MM_IO,   &g_flags }, // G_FLAGS           GPU Flags Register                                      F02100          RW
+       { 0xF02104, 0xF02107, MM_IO_W, &g_mtxc }, // G_MTXC             Matrix Control Register                         F02104          WO
+       { 0xF02108, 0xF0210B, MM_IO_W, &g_mtxa }, // G_MTXA             Matrix Address Register                         F02108          WO
+       { 0xF0210C, 0xF0210F, MM_IO_W, &g_end }, // G_END               Data Organization Register                      F0210C          WO
+       { 0xF02110, 0xF02113, MM_IO,   &g_pc }, // G_PC         GPU Program Counter                                     F02110          RW
+       { 0xF02114, 0xF02117, MM_IO,   &g_ctrl }, // G_CTRL             GPU Control/Status Register                     F02114          RW
+       { 0xF02118, 0xF0211B, MM_IO,   &g_hidata }, // G_HIDATA High Data Register                                      F02118          RW
+       { 0xF0211C, 0xF0211F, MM_IO,   &g_remain, &g_divctrl }, // G_REMAIN     Divide Unit Remainder                           F0211C          RO
+                                                                                       // G_DIVCTRL    Divide Unit Control                                     F0211C          WO
+       { 0xF03000, 0xF03FFF, MM_RAM,  gpuRAM },
+
+       // BLITTER REGISTERS
+
+       { 0xF02200, 0xF02203, MM_IO_W, &a1_base }, // A1_BASE           A1 Base Register                                        F02200          WO
+       { 0xF02204, 0xF02207, MM_IO,   &a1_pixel, &a1_flags }, // A1_FLAGS      Flags Register                                          F02204          WO
+       { 0xF02208, 0xF0220B, MM_IO_W, &a1_clip }, // A1_CLIP           A1 Clipping Size                                        F02208          WO
+       { 0xF0220C, 0xF0220F, MM_IO_W, &a1_pixel }, // A1_PIXEL A1 Pixel Pointer                                        F0220C          WO
+//                                                                                             F02204          RO
+       { 0xF02210, 0xF02213, MM_IO_W, &a1_step }, // A1_STEP           A1 Step Value                                           F02210          WO
+       { 0xF02214, 0xF02217, MM_IO_W, &a1_fstep }, // A1_FSTEP A1 Step Fraction Value                          F02214          WO
+       { 0xF02218, 0xF0221B, MM_IO,   &a1_fpixel }, // A1_FPIXEL       A1 Pixel Pointer Fraction                       F02218          RW
+       { 0xF0221C, 0xF0221F, MM_IO_W, &a1_inc }, // A1_INC             A1 Increment                                            F0221C          WO
+       { 0xF02220, 0xF02223, MM_IO_W, &a1_finc }, // A1_FINC           A1 Increment Fraction                           F02220          WO
+       { 0xF02224, 0xF02227, MM_IO_W, &a2_base }, // A2_BASE           A2 Base Register                                        F02224          WO
+       { 0xF02228, 0xF0222B, MM_IO_W, &a2_flags }, // A2_FLAGS A2 Flags Register                                       F02228          WO
+       { 0xF0222C, 0xF0222F, MM_IO,   &a2_pixel, &a2_mask }, // A2_MASK                A2 Window Mask                                          F0222C          WO
+       { 0xF02230, 0xF02233, MM_IO_W, &a2_pixel }, // A2_PIXEL A2 Pixel Pointer                                        F02230          WO
+//                                                                                             F0222C          RO
+       { 0xF02234, 0xF02237, MM_IO_W, &a2_step }, // A2_STEP           A2 Step Value                                           F02234          WO
+       { 0xF02238, 0xF0223B, MM_IO,   &b_cmd }, // B_CMD               Command/Status Register                         F02238          RW
+       { 0xF0223C, 0xF0223F, MM_IO_W, &b_count }, // B_COUNT           Counters Register                                       F0223C          WO
+       { 0xF02240, 0xF02247, MM_IO_W, &b_srcd }, // B_SRCD             Source Data Register                            F02240          WO
+       { 0xF02248, 0xF0224F, MM_IO_W, &b_dstd }, // B_DSTD             Destination Data Register                       F02248          WO
+       { 0xF02250, 0xF02258, MM_IO_W, &b_dstz }, // B_DSTZ             Destination Z Register                          F02250          WO
+       { 0xF02258, 0xF0225F, MM_IO_W, &b_srcz1 }, // B_SRCZ1           Source Z Register 1                                     F02258          WO
+       { 0xF02260, 0xF02267, MM_IO_W, &b_srcz2 }, // B_SRCZ2           Source Z Register 2                                     F02260          WO
+       { 0xF02268, 0xF0226F, MM_IO_W, &b_patd }, // B_PATD             Pattern Data Register                           F02268          WO
+       { 0xF02270, 0xF02273, MM_IO_W, &b_iinc }, // B_IINC             Intensity Increment                                     F02270          WO
+       { 0xF02274, 0xF02277, MM_IO_W, &b_zinc }, // B_ZINC             Z Increment                                                     F02274          WO
+       { 0xF02278, 0xF0227B, MM_IO_W, &b_stop }, // B_STOP             Collision Control                                       F02278          WO
+       { 0xF0227C, 0xF0227F, MM_IO_W, &b_i3 }, // B_I3         Intensity 3                                                     F0227C          WO
+       { 0xF02280, 0xF02283, MM_IO_W, &b_i2 }, // B_I2         Intensity 2                                                     F02280          WO
+       { 0xF02284, 0xF02287, MM_IO_W, &b_i1 }, // B_I1         Intensity 1                                                     F02284          WO
+       { 0xF02288, 0xF0228B, MM_IO_W, &b_i0 }, // B_I0         Intensity 0                                                     F02288          WO
+       { 0xF0228C, 0xF0228F, MM_IO_W, &b_z3 }, // B_Z3         Z 3                                                                     F0228C          WO
+       { 0xF02290, 0xF02293, MM_IO_W, &b_z2 }, // B_Z2         Z 2                                                                     F02290          WO
+       { 0xF02294, 0xF02297, MM_IO_W, &b_z1 }, // B_Z1         Z 1                                                                     F02294          WO
+       { 0xF02298, 0xF0229B, MM_IO_W, &b_z0 }, // B_Z0         Z 0                                                                     F02298          WO
+
+// JTRM sez ALL GPU address space is accessible from $8000 offset as "fast" 32-bit WO access
+// Dunno if anything actually USED it tho... :-P
+       { 0xF0A100, 0xF0A103, MM_IO_W, &g_flags }, // G_FLAGS           GPU Flags Register                                      F02100          RW
+       { 0xF0A104, 0xF0A107, MM_IO_W, &g_mtxc }, // G_MTXC             Matrix Control Register                         F02104          WO
+       { 0xF0A108, 0xF0A10B, MM_IO_W, &g_mtxa }, // G_MTXA             Matrix Address Register                         F02108          WO
+       { 0xF0A10C, 0xF0A10F, MM_IO_W, &g_end }, // G_END               Data Organization Register                      F0210C          WO
+       { 0xF0A110, 0xF0A113, MM_IO_W, &g_pc }, // G_PC         GPU Program Counter                                     F02110          RW
+       { 0xF0A114, 0xF0A117, MM_IO_W, &g_ctrl }, // G_CTRL             GPU Control/Status Register                     F02114          RW
+       { 0xF0A118, 0xF0A11B, MM_IO_W, &g_hidata }, // G_HIDATA High Data Register                                      F02118          RW
+       { 0xF0A11C, 0xF0A11F, MM_IO_W, &g_divctrl }, // G_REMAIN        Divide Unit Remainder                           F0211C          RO
+       { 0xF0B000, 0xF0BFFF, MM_IO_W, gpuRAM }, // "Fast" interface to GPU RAM
+
+       // JERRY REGISTERS
+
+       { 0xF10000, 0xF10001, MM_IO_W, &jpit1 }, // JPIT1               Timer 1 Pre-scaler                                      F10000          WO
+       { 0xF10002, 0xF10003, MM_IO_W, &jpit2 }, // JPIT2               Timer 1 Divider                                         F10002          WO
+       { 0xF10004, 0xF10005, MM_IO_W, &jpit3 }, // JPIT3               Timer 2 Pre-scaler                                      F10004          WO
+       { 0xF10006, 0xF10007, MM_IO_W, &jpit4 }, // JPIT4               Timer 2 Divider                                         F10006          WO
+       { 0xF10010, 0xF10011, MM_IO_W, &clk1 }, // *CLK1                Processor Clock Divider                         F10010          WO
+       { 0xF10012, 0xF10013, MM_IO_W, &clk2 }, // *CLK2                Video Clock Divider                                     F10012          WO
+       { 0xF10014, 0xF10015, MM_IO_W, &clk3 }, // *CLK3                Chroma Clock Divider                            F10014          WO
+       { 0xF10020, 0xF10021, MM_IO,   &j_int }, // J_INT               Interrup Control Register                       F10020          RW
+       { 0xF10030, 0xF10031, MM_IO,   &asidata }, // ASIDATA           Asynchronous Serial Data                        F10030          RW
+       { 0xF10032, 0xF10033, MM_IO,   &asistat, &asictrl }, // ASICTRL         Asynchronous Serial Control                     F10032          WO
+                                                                                       // ASISTAT              Asynchronous Serial Status                      F10032          RO
+       { 0xF10034, 0xF10035, MM_IO,   &asiclk }, // ASICLK             Asynchronous Serial Interface Clock     F10034          RW
+       { 0xF10036, 0xF10037, MM_IO_R, &jpit1 }, // JPIT1               Timer 1 Pre-scaler                                      F10036          RO
+       { 0xF10038, 0xF10039, MM_IO_R, &jpit2 }, // JPIT2               Timer 1 Divider                                         F10038          RO
+       { 0xF1003A, 0xF1003B, MM_IO_R, &jpit3 }, // JPIT3               Timer 2 Pre-scaler                                      F1003A          RO
+       { 0xF1003C, 0xF1003D, MM_IO_R, &jpit4 }, // JPIT4               Timer 2 Divider                                         F1003C          RO
+
+       { 0xF14000, 0xF14001, MM_IO,   &joystick }, // JOYSTICK Joystick Register                                       F14000          RW
+       { 0xF14002, 0xF14003, MM_IO,   &joybuts }, // JOYBUTS           Button Register                                         F14002          RW
+
+       // DSP REGISTERS
+
+       { 0xF1A100, 0xF1A103, MM_IO,   &d_flags }, // D_FLAGS           DSP Flags Register                                      F1A100          RW
+       { 0xF1A104, 0xF1A107, MM_IO_W, &d_mtxc }, // D_MTXC             DSP Matrix Control Register                     F1A104          WO
+       { 0xF1A108, 0xF1A10B, MM_IO_W, &d_mtxa }, // D_MTXA             DSP Matrix Address Register                     F1A108          WO
+       { 0xF1A10C, 0xF1A10F, MM_IO_W, &d_end }, // D_END               DSP Data Organization Register          F1A10C          WO
+       { 0xF1A110, 0xF1A113, MM_IO,   &d_pc }, // D_PC         DSP Program Counter                                     F1A110          RW
+       { 0xF1A114, 0xF1A117, MM_IO,   &d_ctrl }, // D_CTRL             DSP Control/Status Register                     F1A114          RW
+       { 0xF1A118, 0xF1A11B, MM_IO_W, &d_mod }, // D_MOD               Modulo Instruction Mask                         F1A118          WO
+       { 0xF1A11C, 0xF1A11F, MM_IO_W, &d_remain, &d_divctrl }, // D_REMAIN     Divide Unit Remainder                           F1A11C          RO
+                                                                                       // D_DIVCTRL    Divide Unit Control                                     F1A11C          WO
+       { 0xF1A120, 0xF1A123, MM_IO_R, &d_machi }, // D_MACHI           MAC High Result Bits                            F1A120          RO
+
+
+       { 0xF1A148, 0xF1A149, MM_IO,   &lrxd, &ltxd }, // LTXD          Left Transmit Data                                      F1A148          WO
+       // LRXD         Left Receive Data                                       F1A148          RO
+       // L_I2S                Left I2S Serial Interface                       F1A148          RW
+       { 0xF1A14C, 0xF1A14D, MM_IO,   &rrxd, &rtxd }, // RTXD          Right Transmit Data                                     F1A14C          WO
+       // RRXD         Right Receive Data                                      F1A14C          RO
+       // R_I2S                Right I2S Serial Interface                      F1A14C          RW
+       { 0xF1A150, 0xF1A150, MM_IO,   &sstat, &sclk }, // SCLK         Serial Clock Frequency                          F1A150          WO
+       // SSTAT                Serial Status                                           F1A150          RO
+       { 0xF1A154, 0xF1A157, MM_IO_W, &smode }, // SMODE               Serial Mode                                                     F1A154          WO
+
+       { 0xF1B000, 0xF1CFFF, MM_RAM,  dspRAM }, // F1B000-F1CFFF   R/W   xxxxxxxx xxxxxxxx   Local DSP RAM
+       { 0xF1D000, 0xF1DFFF, MM_ROM,  waveTableROM },
+// hi-speed interface for DSP??? Ain't no such thang...
+       { 0xFFFFFF, 0xFFFFFF, MM_NOP } // End of memory address sentinel
+};
+
+#if 0
+
+// Jaguar Memory map/handlers
+uint32 memoryMap[] = {
+       { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
+       { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
+// Note that this is really memory mapped I/O region...
+//     { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
+       { 0xDFFF00, 0xDFFF03, MM_IO,  cdBUTCH }, // base of Butch == interrupt control register, R/W
+       { 0xDFFF04, 0xDFFF07, MM_IO,  cdDSCNTRL }, // DSA control register, R/W
+       { 0xDFFF0A, 0xDFFF0B, MM_IO,  cdDS_DATA }, // DSA TX/RX data, R/W
+       { 0xDFFF10, 0xDFFF13, MM_IO,  cdI2CNTRL }, // i2s bus control register, R/W
+       { 0xDFFF14, 0xDFFF17, MM_IO,  cdSBCNTRL }, // CD subcode control register, R/W
+       { 0xDFFF18, 0xDFFF1B, MM_IO,  cdSUBDATA }, // Subcode data register A
+       { 0xDFFF1C, 0xDFFF1F, MM_IO,  cdSUBDATB }, // Subcode data register B
+       { 0xDFFF20, 0xDFFF23, MM_IO,  cdSB_TIME }, // Subcode time and compare enable (D24)
+       { 0xDFFF24, 0xDFFF27, MM_IO,  cdFIFO_DATA }, // i2s FIFO data
+       { 0xDFFF28, 0xDFFF2B, MM_IO,  cdI2SDAT2 }, // i2s FIFO data (old)
+       { 0xDFFF2C, 0xDFFF2F, MM_IO,  cdUNKNOWN }, // Seems to be some sort of I2S interface
+
+       { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
+
+//     { 0xF00000, 0xF0FFFF, MM_IO,  TOM_REGS_RW },
+       { 0xF00050, 0xF00051, MM_IO,  tomTimerPrescaler },
+       { 0xF00052, 0xF00053, MM_IO,  tomTimerDivider },
+       { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
+       { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
+       //What about LBUF writes???
+       { 0xF02100, 0xF0211F, MM_IO,  GPUWriteByte }, // GPU CONTROL
+       { 0xF02200, 0xF0229F, MM_IO,  BlitterWriteByte }, // BLITTER
+       { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
+
+       { 0xF10000, 0xF1FFFF, MM_IO,  JERRY_REGS_RW },
+
+/*
+       EEPROM:
+       { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
+       { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
+       { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
+
+       JOYSTICK:
+       { 0xF14000, 0xF14003, MM_IO,  joystickFoo }
+       0 = pad0/1 button values (4 bits each), RO(?)
+       1 = pad0/1 index value (4 bits each), WO
+       2 = unused, RO
+       3 = NTSC/PAL, certain button states, RO
+
+JOYSTICK    $F14000               Read/Write
+            15.....8  7......0
+Read        fedcba98  7654321q    f-1    Signals J15 to J1
+                                  q      Cartridge EEPROM  output data
+Write       exxxxxxm  76543210    e      1 = enable  J7-J0 outputs
+                                         0 = disable J7-J0 outputs
+                                  x      don't care
+                                  m      Audio mute
+                                         0 = Audio muted (reset state)
+                                         1 = Audio enabled
+                                  7-4    J7-J4 outputs (port 2)
+                                  3-0    J3-J0 outputs (port 1)
+JOYBUTS     $F14002               Read Only
+            15.....8  7......0
+Read        xxxxxxxx  rrdv3210    x      don't care
+                                  r      Reserved
+                                  d      Reserved
+                                  v      1 = NTSC Video hardware
+                                         0 = PAL  Video hardware
+                                  3-2    Button inputs B3 & B2 (port 2)
+                                  1-0    Button inputs B1 & B0 (port 1)
+
+J4 J5 J6 J7  Port 2    B2     B3    J12  J13   J14  J15
+J3 J2 J1 J0  Port 1    B0     B1    J8   J9    J10  J11
+ 0  0  0  0
+ 0  0  0  1
+ 0  0  1  0
+ 0  0  1  1
+ 0  1  0  0
+ 0  1  0  1
+ 0  1  1  0
+ 0  1  1  1  Row 3     C3   Option  #     9     6     3
+ 1  0  0  0
+ 1  0  0  1
+ 1  0  1  0
+ 1  0  1  1  Row 2     C2      C    0     8     5     2
+ 1  1  0  0
+ 1  1  0  1  Row 1     C1      B    *     7     4     1
+ 1  1  1  0  Row 0   Pause     A    Up  Down  Left  Right
+ 1  1  1  1
+
+0 bit read in any position means that button is pressed.
+C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
+*/
+};
+#endif
+
+void MMUWrite8(uint32 address, uint8 data, uint32 who/*= UNKNOWN*/)
+{
+}
+
+void MMUWrite16(uint32 address, uint16 data, uint32 who/*= UNKNOWN*/)
+{
+}
+
+void MMUWrite32(uint32 address, uint32 data, uint32 who/*= UNKNOWN*/)
+{
+}
+
+void MMUWrite64(uint32 address, uint64 data, uint32 who/*= UNKNOWN*/)
+{
+}
+
+uint8 MMURead8(uint32 address, uint32 who/*= UNKNOWN*/)
+{
+       // Search for address in the memory map
+       // NOTE: This assumes that all entries are linear and sorted in ascending order!
+
+       MemDesc memory;
+       uint8 byte = 0xFE;
+
+       uint32 i = 0;
+       while (true)
+       {
+               if (address <= memoryMap[i].endAddr)
+               {
+                       if (address >= memoryMap[i].startAddr)
+                       {
+                               memory = memoryMap[i];
+                               break;
+                       }
+                       else
+                               return 0xFF;    // Wasn't found...
+               }
+
+               i++;
+
+               if (memoryMap[i].startAddr == 0xFFFFFF)
+                       return 0xFF;            // Exhausted the list, so bail!
+       }
+
+       uint32 offset = address - memory.startAddr;
+       uint32 size = memory.endAddr - memory.startAddr + 1;
+       uint8 byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
+
+       if (memory.type == MM_RAM || memory.type == MM_ROM)
+       {
+               byte = ((uint8 *)memory.readFunc)[offset];
+       }
+       else if (memory.type == MM_IO_R || memory.type == MM_IO)
+       {
+               // Problem here: We don't know yet how wide the function is, so we don't know
+               // how to properly cast it. We COULD ignore the problem by passing in/receiving
+               // 64-bits of data and letting the function make heads or tails of it, but we
+               // still have the problem of, say, taking a byte from a 32-bit value.
+/*
+We can do like so:
+       uint8 byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
+       size = memory.endAddr - memory.startAddr + 1;
+       byte = (returnValFromFunc >> byteShift[offset]) & 0xFF;
+
+Let's see, will this work depending on the endianess?
+uint32 dword
+accessing it like so:
+((uint8 *)dword &)[0] --> should give us high byte
+but if we assign it directly...
+dword = 0x12345678 --> becomes 78 56 34 12 in memory, ptr[0] will be 78 in LE!
+dword = 0x12345678 --> becomes 12 34 56 78 in memory, ptr[0] will be 12 in BE!
+
+So we're in danger if we use the variables directly! We'd need something like
+#define ENDIAN_SAFE_16(x)  swap lo & hi bytes on LE systems
+#define ENDIAN_SAFE_16(x)  do nothing on BE systems
+
+Then, if we want to use a jaguar variable, we need to cast it like so:
+uint16 my_vbb = ENDIAN_SAFE_16(vbb);
+
+We have something like this already in jaguar.h, since we treat I/O spaces like
+contiguous memory anyway... For reference:
+
+// Some handy macros to help converting native endian to big endian (jaguar native)
+// & vice versa
+
+#define SET64(r, a, v)         r[(a)] = ((v) & 0xFF00000000000000) >> 56, r[(a)+1] = ((v) & 0x00FF000000000000) >> 48, \
+                                               r[(a)+2] = ((v) & 0x0000FF0000000000) >> 40, r[(a)+3] = ((v) & 0x000000FF00000000) >> 32, \
+                                               r[(a)+4] = ((v) & 0xFF000000) >> 24, r[(a)+5] = ((v) & 0x00FF0000) >> 16, \
+                                               r[(a)+6] = ((v) & 0x0000FF00) >> 8, r[(a)+7] = (v) & 0x000000FF
+#define GET64(r, a)            (((uint64)r[(a)] << 56) | ((uint64)r[(a)+1] << 48) | \
+                                               ((uint64)r[(a)+2] << 40) | ((uint64)r[(a)+3] << 32) | \
+                                               ((uint64)r[(a)+4] << 24) | ((uint64)r[(a)+5] << 16) | \
+                                               ((uint64)r[(a)+6] << 8) | (uint64)r[(a)+7])
+#define SET32(r, a, v) r[(a)] = ((v) & 0xFF000000) >> 24, r[(a)+1] = ((v) & 0x00FF0000) >> 16, \
+                                               r[(a)+2] = ((v) & 0x0000FF00) >> 8, r[(a)+3] = (v) & 0x000000FF
+#define GET32(r, a)            ((r[(a)] << 24) | (r[(a)+1] << 16) | (r[(a)+2] << 8) | r[(a)+3])
+#define SET16(r, a, v) r[(a)] = ((v) & 0xFF00) >> 8, r[(a)+1] = (v) & 0xFF
+#define GET16(r, a)            ((r[(a)] << 8) | r[(a)+1])
+*/
+               // Confused? Let me enlighten... What we're doing here is casting
+               // data1 as a pointer to a function which returns a Window pointer and
+               // which takes no parameters (the "(Window *(*)(void))" part), then
+               // derefencing it (the "*" in front of that) in order to call the
+               // function that it points to. Clear as mud? Yeah, I hate function
+               // pointers too, but what else are you gonna do?
+//             mainWindow = (*(Window *(*)(void))event.user.data1)();
+//             uint32 retVal = (*(uint32(*)(uint32))memory.readFunc)(offset);
+//#define FUNC_CAST(x) (*(uint32(*)(uint32))x)
+//             uint32 retVal = FUNC_CAST(memory.readFunc)(offset);
+#define FUNC_CAST(retVal, function, params) (*(retVal(*)(params))function)
+               uint64 retVal = FUNC_CAST(uint64, memory.readFunc, uint32)(offset);
+               byte = (retVal >> byteShift[offset]) & 0xFF;
+       }
+       else if (memory.type == MM_IO_W)
+       {
+               byte = 0xFF;            // Write only, what do we return? A fixed value?
+       }
+
+       return byte;
+}
+
+uint16 MMURead16(uint32 address, uint32 who/*= UNKNOWN*/)
+{
+       return 0;
+}
+
+uint32 MMURead32(uint32 address, uint32 who/*= UNKNOWN*/)
+{
+       return 0;
+}
+
+uint64 MMURead64(uint32 address, uint32 who/*= UNKNOWN*/)
+{
+       return 0;
+}
+
diff --git a/src/mmu.h b/src/mmu.h
new file mode 100644 (file)
index 0000000..9a04e9f
--- /dev/null
+++ b/src/mmu.h
@@ -0,0 +1,24 @@
+//
+// mmu.h
+//
+// Jaguar Memory Manager Unit
+//
+// by James L. Hammons
+//
+
+#ifndef __MMU_H__
+#define __MMU_H__
+
+//#include "types.h"
+#include "memory.h"
+
+void MMUWrite8(uint32 address, uint8 data, uint32 who = UNKNOWN);
+void MMUWrite16(uint32 address, uint16 data, uint32 who = UNKNOWN);
+void MMUWrite32(uint32 address, uint32 data, uint32 who = UNKNOWN);
+void MMUWrite64(uint32 address, uint64 data, uint32 who = UNKNOWN);
+uint8 MMURead8(uint32 address, uint32 who = UNKNOWN);
+uint16 MMURead16(uint32 address, uint32 who = UNKNOWN);
+uint32 MMURead32(uint32 address, uint32 who = UNKNOWN);
+uint64 MMURead64(uint32 address, uint32 who = UNKNOWN);
+
+#endif // __MMU_H__