//
// 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>
//
//
#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;
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);
}
}
-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)
{
- uint8_t data = 0x00;
- int pad0Index = joystick_ram[1] & 0x0F;
- int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
-
-// This is bad--we're assuming that a bit is set in the last case. Might not be so!
-// NOTE: values $7, B, D, & E are only legal ones for pad 0, (rows 3 to 0, in both cases)
-// $E, D, B, & 7 are only legal ones for pad 1
-// So the following code is WRONG! (now fixed! ;-)
-// Also: we should explicitly check for those bit patterns, as other patterns
-// are legal and yield other controllers... !!! FIX !!!
-#warning "!!! Need to explicitly check for the proper bit combinations! !!!"
-
- if (!(pad0Index & 0x01))
- pad0Index = 0;
- else if (!(pad0Index & 0x02))
- pad0Index = 1;
- else if (!(pad0Index & 0x04))
- pad0Index = 2;
- else if (!(pad0Index & 0x08))
- pad0Index = 3;
-
- if (!(pad1Index & 0x01))
- pad1Index = 3;
- else if (!(pad1Index & 0x02))
- pad1Index = 2;
- else if (!(pad1Index & 0x04))
- pad1Index = 1;
- 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;
-
- return ~data;
- }
- else if (offset == 3)
- {
- // Hardware ID returns NTSC/PAL identification bit here
- uint8_t data = 0x2F | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
- int pad0Index = joystick_ram[1] & 0x0F;
- int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
-
-//This is more stuff to add to the button reading, as the preceeding only
-//yields 16 buttons...
-#warning "!!! This reports TeamTap incorrectly when PAUSE pressed on controller #1 or #2 !!!"
- if (!(pad0Index & 0x01))
- {
- if (joypad_0_buttons[BUTTON_PAUSE])
- data ^= 0x01;
- if (joypad_0_buttons[BUTTON_A])
- data ^= 0x02;
- }
- else if (!(pad0Index & 0x02))
- {
- if (joypad_0_buttons[BUTTON_B])
- data ^= 0x02;
- }
- else if (!(pad0Index & 0x04))
- {
- if (joypad_0_buttons[BUTTON_C])
- data ^= 0x02;
- }
- else if (!(pad0Index & 0x08))
- {
- if (joypad_0_buttons[BUTTON_OPTION])
- data ^= 0x02;
- }
+ if (!joysticksEnabled)
+ return 0xFFFF;
- if (!(pad1Index & 0x08))
- {
- if (joypad_1_buttons[BUTTON_PAUSE])
- data ^= 0x04;
- if (joypad_1_buttons[BUTTON_A])
- data ^= 0x08;
- }
- else if (!(pad1Index & 0x04))
- {
- if (joypad_1_buttons[BUTTON_B])
- data ^= 0x08;
- }
- else if (!(pad1Index & 0x02))
+ // 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)
{
- if (joypad_1_buttons[BUTTON_C])
- data ^= 0x08;
+ uint16_t mask[4] = { 0xFEFF, 0xFDFF, 0xFBFF, 0xF7FF };
+//No! uint16_t mask[4] = { 0xFFFE, 0xFFFD, 0xFFFB, 0xFFF7 };
+
+ for(uint8_t i=0; i<4; i++)
+ data &= (joypad0Buttons[offset0 + i] ? mask[i] : 0xFFFF);
}
- else if (!(pad1Index & 0x01))
+
+ if (offset1 != 0xFF)
{
- if (joypad_1_buttons[BUTTON_OPTION])
- data ^= 0x08;
+ uint16_t mask[4] = { 0xEFFF, 0xDFFF, 0xBFFF, 0x7FFF };
+//No! uint16_t mask[4] = { 0xFFEF, 0xFFDF, 0xFFBF, 0xFF7F };
+
+ for(uint8_t i=0; i<4; i++)
+ data &= (joypad1Buttons[offset1 + i] ? mask[i] : 0xFFFF);
}
return data;
}
+ else if (offset == 2)
+ {
+ // Hardware ID returns NTSC/PAL identification bit here
+ uint16_t data = 0xFFEF | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
- return joystick_ram[offset];
-}
+ if (!joysticksEnabled)
+ return data;
+ // Joystick data returns active low for buttons pressed, high for non-
+ // pressed.
+ uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
+ uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
-uint16_t JoystickReadWord(uint32_t offset)
-{
- return ((uint16_t)JoystickReadByte((offset + 0) & 0x03) << 8) | JoystickReadByte((offset + 1) & 0x03);
-}
+ if (offset0 != 0xFF)
+ {
+ offset0 /= 4; // Make index 0, 1, 2, 3 instead of 0, 4, 8, 12
+ uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, 0xFF }, { BUTTON_C, 0xFF }, { BUTTON_OPTION, 0xFF } };
+ data &= (joypad0Buttons[mask[offset0][0]] ? 0xFFFD : 0xFFFF);
+ if (mask[offset0][1] != -1)
+ data &= (joypad0Buttons[mask[offset0][1]] ? 0xFFFE : 0xFFFF);
+ }
-void JoystickWriteByte(uint32_t offset, uint8_t data)
-{
- joystick_ram[offset & 0x03] = data;
+ if (offset1 != 0xFF)
+ {
+ offset1 /= 4; // Make index 0, 1, 2, 3 instead of 0, 4, 8, 12
+ uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, 0xFF }, { BUTTON_C, 0xFF }, { BUTTON_OPTION, 0xFF } };
+ data &= (joypad1Buttons[mask[offset1][0]] ? 0xFFF7 : 0xFFFF);
+
+ if (mask[offset1][1] != -1)
+ data &= (joypad1Buttons[mask[offset1][1]] ? 0xFFFB : 0xFFFF);
+ }
+
+ return data;
+ }
+
+ return 0xFFFF;
}
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);
+ }
}