]> Shamusworld >> Repos - virtualjaguar/commitdiff
Various fixes for GPU/DSP DIV instruction, fixes for joypad handling.
authorShamus Hammons <jlhamm@acm.org>
Sun, 24 Mar 2013 03:06:31 +0000 (22:06 -0500)
committerShamus Hammons <jlhamm@acm.org>
Sun, 24 Mar 2013 03:06:31 +0000 (22:06 -0500)
docs/TODO
docs/WHATSNEW
src/dsp.cpp
src/gpu.cpp
src/gui/app.cpp
src/gui/controllertab.cpp
src/gui/controllertab.h
src/gui/mainwin.cpp
src/jerry.cpp
src/joystick.cpp
src/joystick.h

index 6a95a605e36793887e9e66c4ed42e0640bba210d..c86f39d6254664d790bde5160a734248d0310d99 100644 (file)
--- a/docs/TODO
+++ b/docs/TODO
@@ -21,6 +21,10 @@ Stuff to add/fix for the next release of Virtual Jaguar
   how much it's capable of. [Shamus]
 - Fix coming out of fullscreen on Win32. As of now, it doesn't restore the
   window position correctly [CJ]
+- Fix the Tripper Getem ROM so that it works. It has some tight coupling
+  between the M68K and the DSP that causes the DSP to starve itself; fixing
+  this will probably fix a bunch of other timing related issues as well.
+  [Shamus]
 
 
 Stuff that was added/fixed
index b6ff9289506690f8770bd2a1565d51a35b726bcc..f7dbf46e4e7a37ae8cba40ccae1660a0bedad8f3 100644 (file)
@@ -1,6 +1,15 @@
 Virtual Jaguar v2.1.1 GCC/Qt
 ----------------------------
 
+* Added controller profiles. What this means is that if you left your gamepad
+  behind and/or have a different one, VJ will let you create a controller
+  config for the new controller without destroying the old one. This also means
+  that if you have *no* controllers, you can still play VJ with the keyboard.
+  [Shamus]
+* Fixed a few problems with the DSP a timing; as a result, the sound in Rayman
+  and the FACTS demo is correct now. [Shamus]
+* Removed toolbar from full screen mode. [Shamus]
+* Added analog inputs to gamepad support. [Shamus]
 * Fixed 6MB cartridge space access limitation. 6MB carts should work now.
   [Shamus]
 * Fixed problem with JERRY interrupts corrupting the M68K core. [Shamus]
index 748c4ab01750a4f1c4a2bf509fe1a957fc701a1a..2dab23c2e6f90cf5cfd9f9df30555f47a1a578a9 100644 (file)
@@ -2403,6 +2403,7 @@ static void dsp_opcode_abs(void)
 
 static void dsp_opcode_div(void)
 {
+#if 0
        uint32_t _Rm=RM;
        uint32_t _Rn=RN;
 
@@ -2425,6 +2426,32 @@ static void dsp_opcode_div(void)
        }
        else
                RN=0xffffffff;
+#else
+       if (RM)
+       {
+               if (dsp_div_control & 0x01)             // 16.16 division
+               {
+                       dsp_remain = ((uint64_t)RN << 16) % RM;
+                       RN = ((uint64_t)RN << 16) / RM;
+               }
+               else
+               {
+                       // We calculate the remainder first because we destroy RN after
+                       // this by assigning it to itself.
+                       dsp_remain = RN % RM;
+                       RN = RN / RM;
+               }
+
+// What we really should do here is figure out why this condition
+// happens in the real divide unit and emulate *that* behavior.
+#if 0
+               if ((gpu_remain - RM) & 0x80000000)     // If the result would have been negative...
+                       gpu_remain -= RM;                       // Then make it negative!
+#endif
+       }
+       else
+               RN = 0xFFFFFFFF;
+#endif
 }
 
 static void dsp_opcode_imultn(void)
index 1f1bef9351cbe14eb6ab5ba18a1c94d00d5fa7e8..49a862a1fe945efff93633bd3a1b5810436b357c 100644 (file)
@@ -99,8 +99,8 @@
 #define GPU_DIS_SUBQT
 #define GPU_DIS_XOR
 
-//bool doGPUDis = false;
-bool doGPUDis = true;
+bool doGPUDis = false;
+//bool doGPUDis = true;
 #endif
 
 /*
@@ -1192,6 +1192,10 @@ if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] ==
 /*             gpu_flag_c = (gpu_flag_c ? 1 : 0);
                gpu_flag_z = (gpu_flag_z ? 1 : 0);
                gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
+#if 0
+if (gpu_pc == 0xF03200)
+       doGPUDis = true;
+#endif
 
                uint16_t opcode = GPUReadWord(gpu_pc, GPU);
                uint32_t index = opcode >> 10;
@@ -2188,6 +2192,7 @@ static void gpu_opcode_mult(void)
                WriteLog("%06X: MULT   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
 #endif
        RN = (uint16_t)RM * (uint16_t)RN;
+//     RN = (RM & 0xFFFF) * (RN & 0xFFFF);
        SET_ZN(RN);
 #ifdef GPU_DIS_MULT
        if (doGPUDis)
@@ -2347,48 +2352,34 @@ static void gpu_opcode_div(void)        // RN / RM
 //       The original tried to get it right by checking to see if the
 //       remainder was negative, but that's too late...
 // The code there should do it now, but I'm not 100% sure...
+// [Now it should be correct, but not displaying correct behavior of the actual
+//  hardware. A step in the right direction.]
 
        if (RM)
        {
                if (gpu_div_control & 0x01)             // 16.16 division
                {
-                       RN = ((uint64_t)RN << 16) / RM;
                        gpu_remain = ((uint64_t)RN << 16) % RM;
+                       RN = ((uint64_t)RN << 16) / RM;
                }
                else
                {
-                       RN = RN / RM;
+                       // We calculate the remainder first because we destroy RN after
+                       // this by assigning it to itself.
                        gpu_remain = RN % RM;
+                       RN = RN / RM;
                }
 
+// What we really should do here is figure out why this condition
+// happens in the real divide unit and emulate *that* behavior.
+#if 0
                if ((gpu_remain - RM) & 0x80000000)     // If the result would have been negative...
                        gpu_remain -= RM;                       // Then make it negative!
+#endif
        }
        else
                RN = 0xFFFFFFFF;
 
-/*     uint32_t _RM=RM;
-       uint32_t _RN=RN;
-
-       if (_RM)
-       {
-               if (gpu_div_control & 1)
-               {
-                       gpu_remain = (((uint64_t)_RN) << 16) % _RM;
-                       if (gpu_remain&0x80000000)
-                               gpu_remain-=_RM;
-                       RN = (((uint64_t)_RN) << 16) / _RM;
-               }
-               else
-               {
-                       gpu_remain = _RN % _RM;
-                       if (gpu_remain&0x80000000)
-                               gpu_remain-=_RM;
-                       RN/=_RM;
-               }
-       }
-       else
-               RN=0xffffffff;*/
 #ifdef GPU_DIS_DIV
        if (doGPUDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] Remainder: %08X\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN, gpu_remain);
index c1093fff4e7e4f35aaf3dc0766d740744396573c..a951e644c8921c60698ad93d0f87879ed96336ea 100644 (file)
@@ -48,8 +48,9 @@ QString filename;
 // Here's the main application loop--short and simple...
 int main(int argc, char * argv[])
 {
-       // Win32 console redirection, because MS and their band of super geniuses decided
-       // that nobody would ever launch an app from the command line. :-P
+       // Win32 console redirection, because MS and their band of super geniuses
+       // decided that nobody would ever launch an app from the command line. :-P
+       // [Unfortunately, this doesn't seem to work on Vista/7. :-(]
 #ifdef __GCCWIN32__
        BOOL (WINAPI * AttachConsole)(DWORD dwProcessId);
 
index 6050dd733a7125ed4bd34b969771b57d3cfcf59c..a5b5328de18c4813909a2bbecbd0f55ddd993744 100644 (file)
@@ -23,7 +23,7 @@
 
 ControllerTab::ControllerTab(QWidget * parent/*= 0*/): QWidget(parent),
        label(new QLabel(tr("Controller:"))),
-       profile(new QComboBox(this)),
+       profileList(new QComboBox(this)),
        redefineAll(new QPushButton(tr("Define All Inputs"))),
        controllerWidget(new ControllerWidget(this))
 {
@@ -31,27 +31,23 @@ ControllerTab::ControllerTab(QWidget * parent/*= 0*/): QWidget(parent),
        QHBoxLayout * top = new QHBoxLayout;
        layout->addLayout(top);
        top->addWidget(label);
-       top->addWidget(profile, 0, Qt::AlignLeft);
+       top->addWidget(profileList, 0, Qt::AlignLeft);
        layout->addWidget(controllerWidget);
        layout->addWidget(redefineAll, 0, Qt::AlignHCenter);
-//     layout->setFixedWidth(label->width());
-//     layout->setSizeConstraint(QLayout::SetFixedSize);
-//     top->setSizeConstraint(QLayout::SetFixedSize);
-//printf("cw width = %i, label width = %i (min=%i, sizehint=%i)\n", controllerWidget->width(), label->width(), label->minimumWidth(), label->sizeHint().width());
-       // This is ugly, ugly, ugly. But it works. :-P It's a shame that Qt's
-       // layout system doesn't seem to allow for a nicer way to handle this.
-//     profile->setFixedWidth(controllerWidget->sizeHint().width() - label->sizeHint().width());
        setLayout(layout);
+       // At least by doing this, it keeps the QComboBox from resizing itself too
+       // large and breaking the layout. :-P
        setFixedWidth(sizeHint().width());
 
        connect(redefineAll, SIGNAL(clicked()), this, SLOT(DefineAllKeys()));
+       connect(profileList, SIGNAL(currentIndexChanged(int)), this, SLOT(ChangeProfile(int)));
 
-//this is the default. :-/ need to set it somewhere else i guess...
-//     profile->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
-       profile->addItem(tr("Keyboard"));
+       // Set up the profile combobox (Keyboard is the default, and always
+       // present)
+       profileList->addItem(tr("Keyboard"));
 
        for(int i=0; i<Gamepad::numJoysticks; i++)
-               profile->addItem(Gamepad::GetJoystickName(i));
+               profileList->addItem(Gamepad::GetJoystickName(i));
 }
 
 
@@ -60,12 +56,6 @@ ControllerTab::~ControllerTab()
 }
 
 
-//QSize ControllerTab::sizeHint(void) const
-//{
-//     return 
-//}
-
-
 void ControllerTab::DefineAllKeys(void)
 {
 //     char jagButtonName[21][10] = { "Up", "Down", "Left", "Right",
@@ -90,3 +80,54 @@ void ControllerTab::DefineAllKeys(void)
        }
 }
 
+
+void ControllerTab::ChangeProfile(int profile)
+{
+printf("You selected profile: %s\n", (profile == 0 ? "Keyboard" : Gamepad::GetJoystickName(profile - 1)));
+}
+
+#if 0
+The profiles need the following:
+
+ - The name of the controller
+ - A unique human readable ID
+ - The key definitions for that controller (keyboard keys can be mixed in)
+
+So there can be more than one profile for each unique controller; the
+relationship is many-to-one. So basically, how it works it like this: SDL
+reports all connected controllers. If there are none connected, the default
+controller is the keyboard (which can have multiple profiles). The UI only
+presents those profiles which are usuable with the controllers that are plugged
+in, all else is ignored. The user can pick the profile for the controller and
+configure the keys for it; the UI automagically saves everything.
+
+How to handle the case of identical controllers being plugged in? How does the
+UI know which is which? Each controller will have a mapping to a default
+Jaguar controller (#1 or #2). Still doesn't prevent confusion though. Actually,
+it can: The profile can have a field that maps it to a preferred Jaguar
+controller, which can also be both (#1 AND #2--in this case we can set it to
+zero which means no preference). If the UI detects two of the same controller
+and each can be mapped to the same profile, it assigns them in order since it
+doesn't matter, the profiles are identical.
+
+The default profile is always available and is the keyboard (hey, we're PC
+centric here). The default profile is usually #0.
+
+Can there be more than one keyboard profile? Why not? You will need separate
+ones for controller #1 and controller #2.
+
+A profile might look like this:
+
+Field 1: Nostomo N45 Analog
+Field 2: Dad's #1
+Field 3: Jaguar controller #1
+Field 4: The button/stick mapping
+
+Profile # would be implicit in the order that they are stored in the internal
+data structure.
+
+When a new controller is plugged in with no profiles attached, it defaults to
+a set keyboard layout which the user can change. So every new controller will
+always have at least one profile.
+#endif
+
index 9b4c5259e9cee51de69650f5defc9688488474a2..998d193333ac79341500bee89c99231ba669e928 100644 (file)
@@ -13,18 +13,20 @@ class ControllerTab: public QWidget
        public:
                ControllerTab(QWidget * parent = 0);
                ~ControllerTab();
-//             QSize sizeHint(void) const;
 
        protected slots:
                void DefineAllKeys(void);
+               void ChangeProfile(int);
 
        private:
                QLabel * label;
-               QComboBox * profile;
+               QComboBox * controllerList;
+               QComboBox * profileList;
                QPushButton * redefineAll;
 
        public:
                ControllerWidget * controllerWidget;
+               int profile;
 };
 
 #endif // __CONTROLLERTAB_H__
index 6becf8eb13816b1b7eae77d4ec568ce2155a36a0..02da8c7ba3c8adf289fa29f201fe985474f7a8e6 100644 (file)
@@ -539,13 +539,13 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state)
        {
                if (e->key() == (int)vjs.p1KeyBindings[i])
 //                     joypad_0_buttons[i] = (uint8)state;
-                       joypad_0_buttons[i] = (state ? 0x01 : 0x00);
+                       joypad0Buttons[i] = (state ? 0x01 : 0x00);
 
 // Pad #2 is screwing up pad #1. Prolly a problem in joystick.cpp...
 // So let's try to fix it there. :-P [DONE]
                if (e->key() == (int)vjs.p2KeyBindings[i])
 //                     joypad_1_buttons[i] = (uint8)state;
-                       joypad_1_buttons[i] = (state ? 0x01 : 0x00);
+                       joypad1Buttons[i] = (state ? 0x01 : 0x00);
        }
 }
 
@@ -557,10 +557,10 @@ void MainWin::HandleGamepads(void)
        for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
        {
                if (vjs.p1KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS))
-                       joypad_0_buttons[i] = (Gamepad::GetState(0, vjs.p1KeyBindings[i]) ? 0x01 : 0x00);
+                       joypad0Buttons[i] = (Gamepad::GetState(0, vjs.p1KeyBindings[i]) ? 0x01 : 0x00);
 
                if (vjs.p2KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS))
-                       joypad_1_buttons[i] = (Gamepad::GetState(1, vjs.p2KeyBindings[i]) ? 0x01 : 0x00);
+                       joypad1Buttons[i] = (Gamepad::GetState(1, vjs.p2KeyBindings[i]) ? 0x01 : 0x00);
        }
 }
 
index 9ff7ac6af141faeb92409025c5193051aa9ec8ee..3237d7bd16ca461492a090788725cf89b789dcc4 100644 (file)
@@ -435,7 +435,8 @@ WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset);
 //     else if (offset >= 0xF17C00 && offset <= 0xF17C01)
 //             return anajoy_byte_read(offset);
        else if (offset >= 0xF14000 && offset <= 0xF14003)
-               return JoystickReadByte(offset) | EepromReadByte(offset);
+//             return JoystickReadByte(offset) | EepromReadByte(offset);
+               return JoystickReadWord(offset & 0xFE) | EepromReadByte(offset);
        else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
                return EepromReadByte(offset);
 
@@ -568,7 +569,8 @@ WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", offset);
        }*/
        else if ((offset >= 0xF14000) && (offset <= 0xF14003))
        {
-               JoystickWriteByte(offset, data);
+//             JoystickWriteByte(offset, data);
+               JoystickWriteWord(offset & 0xFE, (uint16_t)data);
                EepromWriteByte(offset, data);
                return;
        }
index 86940fc80dc1ae2d13f933784565fa9cfe6f8a79..e662bf1308526a475013527da707480c1c1eccf5 100644 (file)
@@ -3,8 +3,8 @@
 //
 // by cal2
 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
-// Cleanups/fixes by James Hammons
-// (C) 2010 Underground Software
+// Extensive rewrite by James Hammons
+// (C) 2013 Underground Software
 //
 // JLH = James Hammons <jlhamm@acm.org>
 //
@@ -14,9 +14,6 @@
 //
 
 #include "joystick.h"
-
-//#include <SDL.h>
-//#include <time.h>
 #include <string.h>                    // For memset()
 #include "gpu.h"
 #include "jaguar.h"
 // Global vars
 
 static uint8_t joystick_ram[4];
-uint8_t joypad_0_buttons[21];
-uint8_t joypad_1_buttons[21];
-
-bool keyBuffer[21];
+uint8_t joypad0Buttons[21];
+uint8_t joypad1Buttons[21];
+bool audioEnabled = false;
+bool joysticksEnabled = false;
 
-//SDL_Joystick * joystick1;
 
 bool GUIKeyHeld = false;
 extern int start_logging;
@@ -71,8 +67,8 @@ void JoystickExec(void)
 void JoystickReset(void)
 {
        memset(joystick_ram, 0x00, 4);
-       memset(joypad_0_buttons, 0, 21);
-       memset(joypad_1_buttons, 0, 21);
+       memset(joypad0Buttons, 0, 21);
+       memset(joypad1Buttons, 0, 21);
 }
 
 
@@ -81,17 +77,23 @@ void JoystickDone(void)
 }
 
 
-uint8_t JoystickReadByte(uint32_t offset)
+//uint8_t JoystickReadByte(uint32_t offset)
+uint16_t JoystickReadWord(uint32_t offset)
 {
-// For now, until we can fix the 2nd controller... :-P
-//memset(joypad_1_buttons, 0, 21);
+       // E, D, B, 7
+       uint8_t joypad0Offset[16] = {
+               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xFF, 0xFF, 0xFF, 0x08, 0xFF, 0x04, 0x00, 0xFF
+       };
+       uint8_t joypad1Offset[16] = {
+               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x0C, 0xFF
+       };
 
 #warning "No bounds checking done in JoystickReadByte!"
-//     extern bool hardwareTypeNTSC;
        offset &= 0x03;
 
        if (offset == 0)
        {
+#if 0
                uint8_t data = 0x00;
                int pad0Index = joystick_ram[1] & 0x0F;
                int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
@@ -122,21 +124,54 @@ uint8_t JoystickReadByte(uint32_t offset)
                else if (!(pad1Index & 0x08))
                        pad1Index = 0;
 
-               if (joypad_0_buttons[(pad0Index << 2) + 0])     data |= 0x01;
-               if (joypad_0_buttons[(pad0Index << 2) + 1]) data |= 0x02;
-               if (joypad_0_buttons[(pad0Index << 2) + 2]) data |= 0x04;
-               if (joypad_0_buttons[(pad0Index << 2) + 3]) data |= 0x08;
-               if (joypad_1_buttons[(pad1Index << 2) + 0]) data |= 0x10;
-               if (joypad_1_buttons[(pad1Index << 2) + 1]) data |= 0x20;
-               if (joypad_1_buttons[(pad1Index << 2) + 2]) data |= 0x40;
-               if (joypad_1_buttons[(pad1Index << 2) + 3]) data |= 0x80;
+               if (joypad0Buttons[(pad0Index << 2) + 0]) data |= 0x01;
+               if (joypad0Buttons[(pad0Index << 2) + 1]) data |= 0x02;
+               if (joypad0Buttons[(pad0Index << 2) + 2]) data |= 0x04;
+               if (joypad0Buttons[(pad0Index << 2) + 3]) data |= 0x08;
+               if (joypad1Buttons[(pad1Index << 2) + 0]) data |= 0x10;
+               if (joypad1Buttons[(pad1Index << 2) + 1]) data |= 0x20;
+               if (joypad1Buttons[(pad1Index << 2) + 2]) data |= 0x40;
+               if (joypad1Buttons[(pad1Index << 2) + 3]) data |= 0x80;
 
                return ~data;
+#else
+               if (!joysticksEnabled)
+                       return 0xFF;
+
+               // Joystick data returns active low for buttons pressed, high for non-
+               // pressed.
+               uint16_t data = 0xFFFF;
+               uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
+               uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
+
+               if (offset0 != 0xFF)
+               {
+                       uint16_t mask[4] = { 0xFEFF, 0xFDFF, 0xFBFF, 0xF7FF };
+
+                       for(uint8_t i=0; i<4; i++)
+                               data &= (joypad0Buttons[offset0 + i] ? mask[i] : 0xFFFF);
+               }
+
+               if (offset1 != 0xFF)
+               {
+                       uint16_t mask[4] = { 0xEFFF, 0xDFFF, 0xBFFF, 0x7FFF };
+
+                       for(uint8_t i=0; i<4; i++)
+                               data &= (joypad1Buttons[offset1 + i] ? mask[i] : 0xFFFF);
+               }
+
+               return data;
+#endif
        }
-       else if (offset == 3)
+//     else if (offset == 3)
+       else if (offset == 2)
        {
                // Hardware ID returns NTSC/PAL identification bit here
-               uint8_t data = 0x2F | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
+               uint16_t data = 0xFFEF | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
+
+               if (!joysticksEnabled)
+                       return data;
+#if 0
                int pad0Index = joystick_ram[1] & 0x0F;
                int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
 
@@ -145,67 +180,96 @@ uint8_t JoystickReadByte(uint32_t offset)
 #warning "!!! This reports TeamTap incorrectly when PAUSE pressed on controller #1 or #2 !!!"
                if (!(pad0Index & 0x01))
                {
-                       if (joypad_0_buttons[BUTTON_PAUSE])
+                       if (joypad0Buttons[BUTTON_PAUSE])
                                data ^= 0x01;
-                       if (joypad_0_buttons[BUTTON_A])
+                       if (joypad0Buttons[BUTTON_A])
                                data ^= 0x02;
                }
                else if (!(pad0Index & 0x02))
                {
-                       if (joypad_0_buttons[BUTTON_B])
+                       if (joypad0Buttons[BUTTON_B])
                                data ^= 0x02;
                }
                else if (!(pad0Index & 0x04))
                {
-                       if (joypad_0_buttons[BUTTON_C])
+                       if (joypad0Buttons[BUTTON_C])
                                data ^= 0x02;
                }
                else if (!(pad0Index & 0x08))
                {
-                       if (joypad_0_buttons[BUTTON_OPTION])
+                       if (joypad0Buttons[BUTTON_OPTION])
                                data ^= 0x02;
                }
 
                if (!(pad1Index & 0x08))
                {
-                       if (joypad_1_buttons[BUTTON_PAUSE])
+                       if (joypad1Buttons[BUTTON_PAUSE])
                                data ^= 0x04;
-                       if (joypad_1_buttons[BUTTON_A])
+                       if (joypad1Buttons[BUTTON_A])
                                data ^= 0x08;
                }
                else if (!(pad1Index & 0x04))
                {
-                       if (joypad_1_buttons[BUTTON_B])
+                       if (joypad1Buttons[BUTTON_B])
                                data ^= 0x08;
                }
                else if (!(pad1Index & 0x02))
                {
-                       if (joypad_1_buttons[BUTTON_C])
+                       if (joypad1Buttons[BUTTON_C])
                                data ^= 0x08;
                }
                else if (!(pad1Index & 0x01))
                {
-                       if (joypad_1_buttons[BUTTON_OPTION])
+                       if (joypad1Buttons[BUTTON_OPTION])
                                data ^= 0x08;
                }
+#else
+               // Joystick data returns active low for buttons pressed, high for non-
+               // pressed.
+               uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F] / 4;
+               uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F] / 4;
+
+               if (offset0 != 0xFF)
+               {
+                       uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, -1 }, { BUTTON_C, -1 }, { BUTTON_OPTION, -1 } };
+                       data &= (joypad0Buttons[mask[offset0][0]] ? 0xFFFD : 0xFFFF);
+
+                       if (mask[offset0][1] != -1)
+                               data &= (joypad0Buttons[mask[offset0][1]] ? 0xFFFE : 0xFFFF);
+               }
+
+               if (offset1 != 0xFF)
+               {
+                       uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, -1 }, { BUTTON_C, -1 }, { BUTTON_OPTION, -1 } };
+                       data &= (joypad1Buttons[mask[offset1][0]] ? 0xFFF7 : 0xFFFF);
+
+                       if (mask[offset1][1] != -1)
+                               data &= (joypad1Buttons[mask[offset1][1]] ? 0xFFFB : 0xFFFF);
+               }
+#endif
 
                return data;
        }
 
-       return joystick_ram[offset];
+//     return joystick_ram[offset];
+       return 0xFF;
 }
 
 
+#if 0
 uint16_t JoystickReadWord(uint32_t offset)
 {
        return ((uint16_t)JoystickReadByte((offset + 0) & 0x03) << 8) | JoystickReadByte((offset + 1) & 0x03);
 }
+#endif
 
 
+#if 0
 void JoystickWriteByte(uint32_t offset, uint8_t data)
 {
        joystick_ram[offset & 0x03] = data;
 }
+#endif
 
 
 void JoystickWriteWord(uint32_t offset, uint16_t data)
@@ -214,5 +278,11 @@ void JoystickWriteWord(uint32_t offset, uint16_t data)
        offset &= 0x03;
        joystick_ram[offset + 0] = (data >> 8) & 0xFF;
        joystick_ram[offset + 1] = data & 0xFF;
+
+       if (offset == 0)
+       {
+               audioEnabled = (data & 0x0100 ? true : false);
+               joysticksEnabled = (data & 0x8000 ? true : false);
+       }
 }
 
index 891f1360d5ec4b40c6ab02c1cec371ea54cd9de4..09e2378ce55c040bf2143f58bd7ec5f8bf747ddf 100644 (file)
@@ -34,13 +34,16 @@ BUTTON_PAUSE = 20, BUTTON_LAST = 20 };
 void JoystickInit(void);
 void JoystickReset(void);
 void JoystickDone(void);
-void JoystickWriteByte(uint32_t, uint8_t);
+//void JoystickWriteByte(uint32_t, uint8_t);
 void JoystickWriteWord(uint32_t, uint16_t);
-uint8_t JoystickReadByte(uint32_t);
+//uint8_t JoystickReadByte(uint32_t);
 uint16_t JoystickReadWord(uint32_t);
 void JoystickExec(void);
 
-extern bool keyBuffer[];
-extern uint8_t joypad_0_buttons[];
-extern uint8_t joypad_1_buttons[];
-#endif
+extern uint8_t joypad0Buttons[];
+extern uint8_t joypad1Buttons[];
+extern bool audioEnabled;
+extern bool joysticksEnabled;
+
+#endif // __JOYSTICK_H__
+