5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Extensive rewrite by James Hammons
7 // (C) 2013 Underground Software
9 // JLH = James Hammons <jlhamm@acm.org>
12 // --- ---------- -------------------------------------------------------------
13 // JLH 01/16/2010 Created this log ;-)
17 #include <string.h> // For memset()
25 static uint8_t joystick_ram[4];
26 uint8_t joypad0Buttons[21];
27 uint8_t joypad1Buttons[21];
28 bool audioEnabled = false;
29 bool joysticksEnabled = false;
32 bool GUIKeyHeld = false;
33 extern int start_logging;
34 int gpu_start_log = 0;
36 int blit_start_log = 0;
38 int effect_start2 = 0, effect_start3 = 0, effect_start4 = 0, effect_start5 = 0, effect_start6 = 0;
39 bool interactiveMode = false;
40 bool iLeft, iRight, iToggle = false;
41 bool keyHeld1 = false, keyHeld2 = false, keyHeld3 = false;
43 bool startMemLog = false;
44 extern bool doDSPDis, doGPUDis;
46 bool blitterSingleStep = false;
51 void JoystickInit(void)
57 void JoystickExec(void)
59 gpu_start_log = 0; // Only log while key down!
61 effect_start2 = effect_start3 = effect_start4 = effect_start5 = effect_start6 = 0;
63 iLeft = iRight = false;
67 void JoystickReset(void)
69 memset(joystick_ram, 0x00, 4);
70 memset(joypad0Buttons, 0, 21);
71 memset(joypad1Buttons, 0, 21);
75 void JoystickDone(void)
80 //uint8_t JoystickReadByte(uint32_t offset)
81 uint16_t JoystickReadWord(uint32_t offset)
84 uint8_t joypad0Offset[16] = {
85 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xFF, 0xFF, 0xFF, 0x08, 0xFF, 0x04, 0x00, 0xFF
87 uint8_t joypad1Offset[16] = {
88 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x0C, 0xFF
91 #warning "No bounds checking done in JoystickReadByte!"
98 int pad0Index = joystick_ram[1] & 0x0F;
99 int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
101 // This is bad--we're assuming that a bit is set in the last case. Might not be so!
102 // NOTE: values $7, B, D, & E are only legal ones for pad 0, (rows 3 to 0, in both cases)
103 // $E, D, B, & 7 are only legal ones for pad 1
104 // So the following code is WRONG! (now fixed! ;-)
105 // Also: we should explicitly check for those bit patterns, as other patterns
106 // are legal and yield other controllers... !!! FIX !!!
107 #warning "!!! Need to explicitly check for the proper bit combinations! !!!"
109 if (!(pad0Index & 0x01))
111 else if (!(pad0Index & 0x02))
113 else if (!(pad0Index & 0x04))
115 else if (!(pad0Index & 0x08))
118 if (!(pad1Index & 0x01))
120 else if (!(pad1Index & 0x02))
122 else if (!(pad1Index & 0x04))
124 else if (!(pad1Index & 0x08))
127 if (joypad0Buttons[(pad0Index << 2) + 0]) data |= 0x01;
128 if (joypad0Buttons[(pad0Index << 2) + 1]) data |= 0x02;
129 if (joypad0Buttons[(pad0Index << 2) + 2]) data |= 0x04;
130 if (joypad0Buttons[(pad0Index << 2) + 3]) data |= 0x08;
131 if (joypad1Buttons[(pad1Index << 2) + 0]) data |= 0x10;
132 if (joypad1Buttons[(pad1Index << 2) + 1]) data |= 0x20;
133 if (joypad1Buttons[(pad1Index << 2) + 2]) data |= 0x40;
134 if (joypad1Buttons[(pad1Index << 2) + 3]) data |= 0x80;
138 if (!joysticksEnabled)
141 // Joystick data returns active low for buttons pressed, high for non-
143 uint16_t data = 0xFFFF;
144 uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F];
145 uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F];
149 uint16_t mask[4] = { 0xFEFF, 0xFDFF, 0xFBFF, 0xF7FF };
151 for(uint8_t i=0; i<4; i++)
152 data &= (joypad0Buttons[offset0 + i] ? mask[i] : 0xFFFF);
157 uint16_t mask[4] = { 0xEFFF, 0xDFFF, 0xBFFF, 0x7FFF };
159 for(uint8_t i=0; i<4; i++)
160 data &= (joypad1Buttons[offset1 + i] ? mask[i] : 0xFFFF);
166 // else if (offset == 3)
167 else if (offset == 2)
169 // Hardware ID returns NTSC/PAL identification bit here
170 uint16_t data = 0xFFEF | (vjs.hardwareTypeNTSC ? 0x10 : 0x00);
172 if (!joysticksEnabled)
175 int pad0Index = joystick_ram[1] & 0x0F;
176 int pad1Index = (joystick_ram[1] >> 4) & 0x0F;
178 //This is more stuff to add to the button reading, as the preceeding only
179 //yields 16 buttons...
180 #warning "!!! This reports TeamTap incorrectly when PAUSE pressed on controller #1 or #2 !!!"
181 if (!(pad0Index & 0x01))
183 if (joypad0Buttons[BUTTON_PAUSE])
185 if (joypad0Buttons[BUTTON_A])
188 else if (!(pad0Index & 0x02))
190 if (joypad0Buttons[BUTTON_B])
193 else if (!(pad0Index & 0x04))
195 if (joypad0Buttons[BUTTON_C])
198 else if (!(pad0Index & 0x08))
200 if (joypad0Buttons[BUTTON_OPTION])
204 if (!(pad1Index & 0x08))
206 if (joypad1Buttons[BUTTON_PAUSE])
208 if (joypad1Buttons[BUTTON_A])
211 else if (!(pad1Index & 0x04))
213 if (joypad1Buttons[BUTTON_B])
216 else if (!(pad1Index & 0x02))
218 if (joypad1Buttons[BUTTON_C])
221 else if (!(pad1Index & 0x01))
223 if (joypad1Buttons[BUTTON_OPTION])
227 // Joystick data returns active low for buttons pressed, high for non-
229 uint8_t offset0 = joypad0Offset[joystick_ram[1] & 0x0F] / 4;
230 uint8_t offset1 = joypad1Offset[(joystick_ram[1] >> 4) & 0x0F] / 4;
234 uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, -1 }, { BUTTON_C, -1 }, { BUTTON_OPTION, -1 } };
235 data &= (joypad0Buttons[mask[offset0][0]] ? 0xFFFD : 0xFFFF);
237 if (mask[offset0][1] != -1)
238 data &= (joypad0Buttons[mask[offset0][1]] ? 0xFFFE : 0xFFFF);
243 uint8_t mask[4][2] = { { BUTTON_A, BUTTON_PAUSE }, { BUTTON_B, -1 }, { BUTTON_C, -1 }, { BUTTON_OPTION, -1 } };
244 data &= (joypad1Buttons[mask[offset1][0]] ? 0xFFF7 : 0xFFFF);
246 if (mask[offset1][1] != -1)
247 data &= (joypad1Buttons[mask[offset1][1]] ? 0xFFFB : 0xFFFF);
254 // return joystick_ram[offset];
260 uint16_t JoystickReadWord(uint32_t offset)
262 return ((uint16_t)JoystickReadByte((offset + 0) & 0x03) << 8) | JoystickReadByte((offset + 1) & 0x03);
268 void JoystickWriteByte(uint32_t offset, uint8_t data)
270 joystick_ram[offset & 0x03] = data;
275 void JoystickWriteWord(uint32_t offset, uint16_t data)
277 #warning "No bounds checking done for JoystickWriteWord!"
279 joystick_ram[offset + 0] = (data >> 8) & 0xFF;
280 joystick_ram[offset + 1] = data & 0xFF;
284 audioEnabled = (data & 0x0100 ? true : false);
285 joysticksEnabled = (data & 0x8000 ? true : false);