Fix joystick support for real hardware
This commit is contained in:
parent
57970d78a3
commit
ec025d166f
13
Makefile
13
Makefile
|
@ -1,6 +1,6 @@
|
|||
BIN=curta.bin
|
||||
|
||||
GEN_ASM=a2e.stdjoy.s a2e.hi.s
|
||||
GEN_ASM=a2e.hi.s
|
||||
SRCS=$(wildcard *.c)
|
||||
ASM=$(filter-out $(GEN_ASM),$(wildcard *.s)) $(GEN_ASM)
|
||||
|
||||
|
@ -16,17 +16,6 @@ MAPFILE=curta.map
|
|||
|
||||
all: $(BIN)
|
||||
|
||||
# Big hack here. The joystick library from cc65 only considers a
|
||||
# jostick centered if it is within 20 of 127 which is very tight.
|
||||
# Thus the tests for $6B and $93. The good news is that the only
|
||||
# occurrences of these bytes in the binary image are for these
|
||||
# comparisons. So, I just do a global search and replace. The
|
||||
# new threshold I am using is +/- 60 from 127.
|
||||
a2e.stdjoy.s:
|
||||
co65 --code-label _a2e_stdjoy -o $@ $(CC65_HOME)/joy/a2e.stdjoy.joy
|
||||
sed -i .tmp 's/\$$6B/$$43/g' a2e.stdjoy.s
|
||||
sed -i .tmp 's/\$$93/$$BB/g' a2e.stdjoy.s
|
||||
|
||||
a2e.hi.s:
|
||||
co65 --code-label _a2e_hi -o $@ $(CC65_HOME)/tgi/a2e.hi.tgi
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "curtaModel.h"
|
||||
|
||||
|
|
|
@ -6,10 +6,6 @@
|
|||
//
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifndef _CURTAMODEL_H
|
||||
#define _CURTAMODEL_H
|
||||
|
||||
|
|
120
curtaUI.c
120
curtaUI.c
|
@ -7,6 +7,9 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <apple2.h>
|
||||
|
@ -15,11 +18,11 @@
|
|||
#include <tgi/tgi-mode.h>
|
||||
|
||||
#include "curtaModel.h"
|
||||
#include "joystick.h"
|
||||
#include "curtaUI.h"
|
||||
|
||||
|
||||
// Extern symbols for joystick and graphics drivers
|
||||
extern char a2e_stdjoy;
|
||||
// Extern symbols for graphics drivers
|
||||
extern char a2e_hi;
|
||||
|
||||
|
||||
|
@ -37,19 +40,6 @@ typedef int8_t tAction;
|
|||
#define ACTION_NULL 9
|
||||
|
||||
|
||||
typedef int8_t tJoyPos;
|
||||
|
||||
#define JOY_POS_CENTER 0
|
||||
#define JOY_POS_DOWN 1
|
||||
#define JOY_POS_DOWN_LEFT 2
|
||||
#define JOY_POS_LEFT 3
|
||||
#define JOY_POS_UP_LEFT 4
|
||||
#define JOY_POS_UP 5
|
||||
#define JOY_POS_UP_RIGHT 6
|
||||
#define JOY_POS_RIGHT 7
|
||||
#define JOY_POS_DOWN_RIGHT 8
|
||||
|
||||
|
||||
#define OPERAND_COLOR COLOR_WHITE
|
||||
#define OPERAND_OFFSET 4
|
||||
#define SLIDER_BAR_COLOR COLOR_BLUE
|
||||
|
@ -87,7 +77,7 @@ static char displayBuffer[] =
|
|||
#define BASE_OFFSET 103
|
||||
|
||||
|
||||
static void playSound(int freq, int duration)
|
||||
static void playSound(int8_t freq, int8_t duration)
|
||||
{
|
||||
while (duration > 0) {
|
||||
asm ("STA %w", 0xc030);
|
||||
|
@ -235,59 +225,25 @@ static void drawOperand(tDigitPos pos)
|
|||
}
|
||||
|
||||
|
||||
static tJoyPos getJoyPos(char joyState)
|
||||
{
|
||||
if (JOY_BTN_UP(joyState)) {
|
||||
if (JOY_BTN_LEFT(joyState)) {
|
||||
return JOY_POS_UP_LEFT;
|
||||
} else if (JOY_BTN_RIGHT(joyState)) {
|
||||
return JOY_POS_UP_RIGHT;
|
||||
} else {
|
||||
return JOY_POS_UP;
|
||||
}
|
||||
} else if (JOY_BTN_DOWN(joyState)) {
|
||||
if (JOY_BTN_LEFT(joyState)) {
|
||||
return JOY_POS_DOWN_LEFT;
|
||||
} else if (JOY_BTN_RIGHT(joyState)) {
|
||||
return JOY_POS_DOWN_RIGHT;
|
||||
} else {
|
||||
return JOY_POS_DOWN;
|
||||
}
|
||||
} else {
|
||||
if (JOY_BTN_LEFT(joyState)) {
|
||||
return JOY_POS_LEFT;
|
||||
} else if (JOY_BTN_RIGHT(joyState)) {
|
||||
return JOY_POS_RIGHT;
|
||||
} else {
|
||||
return JOY_POS_CENTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static tAction getNextAction(void)
|
||||
{
|
||||
static bool firstCall = true;
|
||||
static char oldJoyState;
|
||||
static tJoyPos oldJoyPos;
|
||||
static unsigned int possibleActions = 0xffff;
|
||||
|
||||
char joyState;
|
||||
tJoyPos joyPos;
|
||||
tJoyState joyState;
|
||||
tAction result = ACTION_NULL;
|
||||
|
||||
if (firstCall) {
|
||||
oldJoyState = joy_read(JOY_1);
|
||||
oldJoyPos = getJoyPos(oldJoyState);
|
||||
oldJoyPos = JOY_POS_CENTER;
|
||||
firstCall = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
joyState = joy_read(JOY_1);
|
||||
joyPos = getJoyPos(joyState);
|
||||
getJoystickState(&joyState);
|
||||
|
||||
if ((joyPos != JOY_POS_CENTER) &&
|
||||
(joyPos != JOY_POS_DOWN)) {
|
||||
if ((joyState.position != JOY_POS_CENTER) &&
|
||||
(joyState.position != JOY_POS_DOWN)) {
|
||||
if (possibleActions == (1 << ACTION_ADD)) {
|
||||
playSound(400, 10);
|
||||
}
|
||||
|
@ -296,29 +252,28 @@ static tAction getNextAction(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (joyPos == oldJoyPos) {
|
||||
oldJoyState = joyState;
|
||||
if (joyState.position == oldJoyPos) {
|
||||
return result;
|
||||
} else if (oldJoyPos == JOY_POS_CENTER) {
|
||||
if (joyPos == JOY_POS_LEFT) {
|
||||
if (JOY_BTN_FIRE(joyState)) {
|
||||
if (joyState.position == JOY_POS_LEFT) {
|
||||
if (joyState.button0) {
|
||||
possibleActions = (1 << ACTION_RESULT_SHIFT_LEFT);
|
||||
} else {
|
||||
possibleActions = (1 << ACTION_OPERAND_SHIFT_LEFT);
|
||||
}
|
||||
} else if (joyPos == JOY_POS_RIGHT) {
|
||||
if (JOY_BTN_FIRE(joyState)) {
|
||||
} else if (joyState.position == JOY_POS_RIGHT) {
|
||||
if (joyState.button0) {
|
||||
possibleActions = (1 << ACTION_RESULT_SHIFT_RIGHT);
|
||||
} else {
|
||||
possibleActions = (1 << ACTION_OPERAND_SHIFT_RIGHT);
|
||||
}
|
||||
} else if (joyPos == JOY_POS_UP) {
|
||||
} else if (joyState.position == JOY_POS_UP) {
|
||||
possibleActions = (1 << ACTION_OPERAND_DEC);
|
||||
} else if (joyPos == JOY_POS_DOWN) {
|
||||
} else if (joyState.position == JOY_POS_DOWN) {
|
||||
possibleActions = (1 << ACTION_OPERAND_INC);
|
||||
if (JOY_BTN_FIRE(joyState)) {
|
||||
if (joyState.button0) {
|
||||
possibleActions |= (1 << ACTION_SUBTRACT);
|
||||
} else if (JOY_BTN_FIRE2(joyState)) {
|
||||
} else if (joyState.button1) {
|
||||
possibleActions |= (1 << ACTION_CLEAR);
|
||||
} else {
|
||||
possibleActions |= (1 << ACTION_ADD);
|
||||
|
@ -326,7 +281,7 @@ static tAction getNextAction(void)
|
|||
}
|
||||
} else {
|
||||
if (possibleActions & (1 << ACTION_OPERAND_SHIFT_LEFT)) {
|
||||
if (joyPos == JOY_POS_CENTER) {
|
||||
if (joyState.position == JOY_POS_CENTER) {
|
||||
result = ACTION_OPERAND_SHIFT_LEFT;
|
||||
} else {
|
||||
possibleActions &= (~(1 << ACTION_OPERAND_SHIFT_LEFT));
|
||||
|
@ -334,7 +289,7 @@ static tAction getNextAction(void)
|
|||
}
|
||||
|
||||
if (possibleActions & (1 << ACTION_OPERAND_SHIFT_RIGHT)) {
|
||||
if (joyPos == JOY_POS_CENTER) {
|
||||
if (joyState.position == JOY_POS_CENTER) {
|
||||
result = ACTION_OPERAND_SHIFT_RIGHT;
|
||||
} else {
|
||||
possibleActions &= (~(1 << ACTION_OPERAND_SHIFT_RIGHT));
|
||||
|
@ -342,7 +297,7 @@ static tAction getNextAction(void)
|
|||
}
|
||||
|
||||
if (possibleActions & (1 << ACTION_OPERAND_INC)) {
|
||||
if (joyPos == JOY_POS_CENTER) {
|
||||
if (joyState.position == JOY_POS_CENTER) {
|
||||
result = ACTION_OPERAND_INC;
|
||||
} else {
|
||||
possibleActions &= (~(1 << ACTION_OPERAND_INC));
|
||||
|
@ -350,7 +305,7 @@ static tAction getNextAction(void)
|
|||
}
|
||||
|
||||
if (possibleActions & (1 << ACTION_OPERAND_DEC)) {
|
||||
if (joyPos == JOY_POS_CENTER) {
|
||||
if (joyState.position == JOY_POS_CENTER) {
|
||||
result = ACTION_OPERAND_DEC;
|
||||
} else {
|
||||
possibleActions &= (~(1 << ACTION_OPERAND_DEC));
|
||||
|
@ -358,7 +313,7 @@ static tAction getNextAction(void)
|
|||
}
|
||||
|
||||
if (possibleActions & (1 << ACTION_RESULT_SHIFT_LEFT)) {
|
||||
if (joyPos == JOY_POS_CENTER) {
|
||||
if (joyState.position == JOY_POS_CENTER) {
|
||||
result = ACTION_RESULT_SHIFT_LEFT;
|
||||
} else {
|
||||
possibleActions &= (~(1 << ACTION_RESULT_SHIFT_LEFT));
|
||||
|
@ -366,7 +321,7 @@ static tAction getNextAction(void)
|
|||
}
|
||||
|
||||
if (possibleActions & (1 << ACTION_RESULT_SHIFT_RIGHT)) {
|
||||
if (joyPos == JOY_POS_CENTER) {
|
||||
if (joyState.position == JOY_POS_CENTER) {
|
||||
result = ACTION_RESULT_SHIFT_RIGHT;
|
||||
} else {
|
||||
possibleActions &= (~(1 << ACTION_RESULT_SHIFT_RIGHT));
|
||||
|
@ -374,41 +329,40 @@ static tAction getNextAction(void)
|
|||
}
|
||||
|
||||
if (possibleActions & (1 << ACTION_ADD)) {
|
||||
if ((joyPos == JOY_POS_DOWN) &&
|
||||
if ((joyState.position == JOY_POS_DOWN) &&
|
||||
(oldJoyPos == JOY_POS_DOWN_RIGHT)) {
|
||||
result = ACTION_ADD;
|
||||
possibleActions = 0;
|
||||
} else if (joyPos != oldJoyPos + 1) {
|
||||
} else if (joyState.position != oldJoyPos + 1) {
|
||||
possibleActions &= (~(1 << ACTION_ADD));
|
||||
}
|
||||
} else if (possibleActions & (1 << ACTION_SUBTRACT)) {
|
||||
if ((joyPos == JOY_POS_DOWN) &&
|
||||
if ((joyState.position == JOY_POS_DOWN) &&
|
||||
(oldJoyPos == JOY_POS_DOWN_RIGHT)) {
|
||||
result = ACTION_SUBTRACT;
|
||||
possibleActions = 0;
|
||||
} else if (joyPos != oldJoyPos + 1) {
|
||||
} else if (joyState.position != oldJoyPos + 1) {
|
||||
possibleActions &= (~(1 << ACTION_SUBTRACT));
|
||||
}
|
||||
} else if (possibleActions & (1 << ACTION_CLEAR)) {
|
||||
if ((joyPos == JOY_POS_DOWN) &&
|
||||
if ((joyState.position == JOY_POS_DOWN) &&
|
||||
(oldJoyPos == JOY_POS_DOWN_RIGHT)) {
|
||||
result = ACTION_CLEAR;
|
||||
possibleActions = 0;
|
||||
} else if (joyPos != oldJoyPos + 1) {
|
||||
} else if (joyState.position != oldJoyPos + 1) {
|
||||
possibleActions &= (~(1 << ACTION_CLEAR));
|
||||
} else if ((joyPos == JOY_POS_UP_LEFT) ||
|
||||
(joyPos == JOY_POS_DOWN_RIGHT)) {
|
||||
} else if ((joyState.position == JOY_POS_UP_LEFT) ||
|
||||
(joyState.position == JOY_POS_DOWN_RIGHT)) {
|
||||
playSound(100, 50);
|
||||
}
|
||||
}
|
||||
|
||||
if (joyPos == JOY_POS_CENTER) {
|
||||
if (joyState.position == JOY_POS_CENTER) {
|
||||
possibleActions = -1;
|
||||
}
|
||||
}
|
||||
|
||||
oldJoyPos = joyPos;
|
||||
oldJoyState = joyState;
|
||||
oldJoyPos = joyState.position;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -421,7 +375,6 @@ void initUI(void)
|
|||
|
||||
initDevice(changeOperand, changeSelectedOperand);
|
||||
|
||||
joy_install(&a2e_stdjoy);
|
||||
tgi_install(&a2e_hi);
|
||||
|
||||
tgi_init();
|
||||
|
@ -502,5 +455,4 @@ void shutdownUI(void)
|
|||
{
|
||||
// Uninstall drivers
|
||||
tgi_uninstall();
|
||||
joy_uninstall();
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
// This is the interface for the Curta emulator UI.
|
||||
//
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifndef _CURTAUI_H
|
||||
#define _CURTAUI_H
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// Author: Jeremy Rand
|
||||
// Date: July 20, 2012
|
||||
//
|
||||
// This is the implementation for the Curta emulator UI.
|
||||
//
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "joystick.h"
|
||||
|
||||
|
||||
#define PREAD 0xFB1E
|
||||
#define ROM_SWITCH 0xC082
|
||||
#define RAM_SWITCH 0xC080
|
||||
#define BTN0 0xC061
|
||||
#define BTN1 0xC062
|
||||
|
||||
|
||||
#define JOYSTICK_CENTER 127
|
||||
#define JOYSTICK_THRESHOLD 60
|
||||
#define LOWER_THRESHOLD (JOYSTICK_CENTER - JOYSTICK_THRESHOLD)
|
||||
#define UPPER_THRESHOLD (JOYSTICK_CENTER + JOYSTICK_THRESHOLD)
|
||||
|
||||
|
||||
static uint8_t joystickTemp;
|
||||
|
||||
|
||||
static bool isButtonPressed(int8_t buttonNum)
|
||||
{
|
||||
if (buttonNum) {
|
||||
__asm__("LDA %w", BTN1);
|
||||
__asm__("STA %v", joystickTemp);
|
||||
} else {
|
||||
__asm__("LDA %w", BTN0);
|
||||
__asm__("STA %v", joystickTemp);
|
||||
}
|
||||
return ((joystickTemp > 127) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t joystickLeftRight(void)
|
||||
{
|
||||
__asm__("BIT %w", ROM_SWITCH);
|
||||
__asm__("LDX #0");
|
||||
__asm__("JSR %w", PREAD);
|
||||
__asm__("STY %v", joystickTemp);
|
||||
__asm__("BIT %w", RAM_SWITCH);
|
||||
return joystickTemp;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t joystickUpDown(void)
|
||||
{
|
||||
__asm__("BIT %w", ROM_SWITCH);
|
||||
__asm__("LDX #1");
|
||||
__asm__("JSR %w", PREAD);
|
||||
__asm__("STY %v", joystickTemp);
|
||||
__asm__("BIT %w", RAM_SWITCH);
|
||||
return joystickTemp;
|
||||
}
|
||||
|
||||
|
||||
void getJoystickState(tJoyState *state)
|
||||
{
|
||||
static bool readLeftRight = true;
|
||||
static uint8_t axisLeftRight = 127;
|
||||
static uint8_t axisUpDown = 127;
|
||||
|
||||
tJoyPos pos = JOY_POS_CENTER;
|
||||
|
||||
if (readLeftRight) {
|
||||
int temp = joystickLeftRight(); // Get left/right position
|
||||
temp *= 3;
|
||||
temp /= 4;
|
||||
axisLeftRight /= 4;
|
||||
axisLeftRight += temp;
|
||||
readLeftRight = false;
|
||||
} else {
|
||||
int temp = joystickUpDown();
|
||||
temp *= 3;
|
||||
temp /= 4;
|
||||
axisUpDown /= 4;
|
||||
axisUpDown += temp;
|
||||
readLeftRight = true;
|
||||
}
|
||||
|
||||
if (axisLeftRight < LOWER_THRESHOLD) {
|
||||
pos = JOY_POS_LEFT;
|
||||
} else if (axisLeftRight > UPPER_THRESHOLD) {
|
||||
pos = JOY_POS_RIGHT;
|
||||
}
|
||||
|
||||
state->button0 = isButtonPressed(0);
|
||||
state->button1 = isButtonPressed(1);
|
||||
|
||||
if (axisUpDown < LOWER_THRESHOLD) {
|
||||
switch (pos) {
|
||||
case JOY_POS_LEFT:
|
||||
pos = JOY_POS_UP_LEFT;
|
||||
break;
|
||||
case JOY_POS_RIGHT:
|
||||
pos = JOY_POS_UP_RIGHT;
|
||||
break;
|
||||
default:
|
||||
pos = JOY_POS_UP;
|
||||
break;
|
||||
}
|
||||
} else if (axisUpDown > UPPER_THRESHOLD) {
|
||||
switch (pos) {
|
||||
case JOY_POS_LEFT:
|
||||
pos = JOY_POS_DOWN_LEFT;
|
||||
break;
|
||||
case JOY_POS_RIGHT:
|
||||
pos = JOY_POS_DOWN_RIGHT;
|
||||
break;
|
||||
default:
|
||||
pos = JOY_POS_DOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state->position = pos;
|
||||
// Add in a bit of extra delay also
|
||||
for (pos = 0; pos < 100; pos++)
|
||||
;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// Author: Jeremy Rand
|
||||
// Date: July 29, 2012
|
||||
//
|
||||
// This is an interface for the Apple // joystick. Note that I used to use
|
||||
// the cc65 joystck interface but found it lacking on real hardware. It
|
||||
// worked fine on an emulator but I think it was testing the second axis of
|
||||
// the joystick too quickly leading to inaccuracies.
|
||||
//
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
typedef int8_t tJoyPos;
|
||||
typedef struct tJoyState {
|
||||
tJoyPos position;
|
||||
bool button0;
|
||||
bool button1;
|
||||
} tJoyState;
|
||||
|
||||
|
||||
#define JOY_POS_CENTER 0
|
||||
#define JOY_POS_DOWN 1
|
||||
#define JOY_POS_DOWN_LEFT 2
|
||||
#define JOY_POS_LEFT 3
|
||||
#define JOY_POS_UP_LEFT 4
|
||||
#define JOY_POS_UP 5
|
||||
#define JOY_POS_UP_RIGHT 6
|
||||
#define JOY_POS_RIGHT 7
|
||||
#define JOY_POS_DOWN_RIGHT 8
|
||||
|
||||
|
||||
void getJoystickState(tJoyState *state);
|
Loading…
Reference in New Issue