Refactor and clean up
This commit is contained in:
parent
de2dc16c6a
commit
eecba58070
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Author: Jeremy Rand
|
||||
// Date: July 20, 2012
|
||||
//
|
||||
// This is the main entry point for the Curta emulator.
|
||||
//
|
||||
|
||||
|
||||
#include "curtaUI.h"
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bool timeToQuit = false;
|
||||
initUI();
|
||||
|
||||
while (!timeToQuit) {
|
||||
timeToQuit= processNextEvent();
|
||||
}
|
||||
|
||||
shutdownUI();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
//
|
||||
// Author: Jeremy Rand
|
||||
// Date: July 20, 2012
|
||||
//
|
||||
// This is the implementation for the Curta emulator model.
|
||||
//
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "curtaModel.h"
|
||||
|
||||
|
||||
tDigit operand[NUM_OPERAND_DIGITS];
|
||||
tDigit result[NUM_RESULT_DIGITS];
|
||||
tDigit counter[NUM_COUNTER_DIGITS];
|
||||
|
||||
tDigitPos basePos;
|
||||
|
||||
tDigitPos selectedOperand;
|
||||
|
||||
|
||||
static operandChangeNotif operandCallback = NULL;
|
||||
|
||||
|
||||
void clearDevice(void)
|
||||
{
|
||||
tDigitPos pos;
|
||||
|
||||
for (pos = 0; pos < NUM_RESULT_DIGITS; pos++) {
|
||||
result[pos] = 0;
|
||||
}
|
||||
for (pos = 0; pos < NUM_COUNTER_DIGITS; pos++) {
|
||||
counter[pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void initDevice(operandChangeNotif callback)
|
||||
{
|
||||
tDigitPos pos;
|
||||
|
||||
operandCallback = callback;
|
||||
|
||||
clearDevice();
|
||||
basePos = 0;
|
||||
selectedOperand = 0;
|
||||
|
||||
for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) {
|
||||
result[pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void incOperandPos(tDigitPos pos)
|
||||
{
|
||||
if (!IS_VALID_OPERAND_POS(pos))
|
||||
return;
|
||||
|
||||
if (operand[pos] == 9)
|
||||
return;
|
||||
|
||||
operand[pos]++;
|
||||
if (operandCallback != NULL)
|
||||
operandCallback(pos);
|
||||
}
|
||||
|
||||
|
||||
void decOperandPos(tDigitPos pos)
|
||||
{
|
||||
if (!IS_VALID_OPERAND_POS(pos))
|
||||
return;
|
||||
|
||||
if (operand[pos] == 0)
|
||||
return;
|
||||
|
||||
operand[pos]--;
|
||||
if (operandCallback != NULL)
|
||||
operandCallback(pos);
|
||||
}
|
||||
|
||||
|
||||
void shiftOperandPos(bool left)
|
||||
{
|
||||
tDigitPos newPos = selectedOperand;
|
||||
tDigitPos oldPos = selectedOperand;
|
||||
|
||||
if (left) {
|
||||
newPos++;
|
||||
if (!IS_VALID_OPERAND_POS(newPos)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
newPos--;
|
||||
if (!IS_VALID_OPERAND_POS(newPos)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
selectedOperand = newPos;
|
||||
if (operandCallback != NULL) {
|
||||
operandCallback(oldPos);
|
||||
operandCallback(newPos);
|
||||
}
|
||||
}
|
||||
|
||||
void shiftResultPos(bool left)
|
||||
{
|
||||
tDigitPos newPos = basePos;
|
||||
if (left) {
|
||||
newPos++;
|
||||
if (!IS_VALID_BASE_POS(newPos))
|
||||
return;
|
||||
} else {
|
||||
newPos--;
|
||||
if (!IS_VALID_BASE_POS(newPos))
|
||||
return;
|
||||
}
|
||||
basePos = newPos;
|
||||
}
|
||||
|
||||
|
||||
static void subOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toSub)
|
||||
{
|
||||
if (toSub == 0)
|
||||
return;
|
||||
|
||||
if (pos >= maxPos)
|
||||
return;
|
||||
|
||||
digits[pos]-=toSub;
|
||||
while (digits[pos] < 0) {
|
||||
digits[pos]+=10;
|
||||
subOperation(digits, pos+1, maxPos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void addOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toAdd)
|
||||
{
|
||||
if (toAdd == 0)
|
||||
return;
|
||||
|
||||
if (pos >= maxPos)
|
||||
return;
|
||||
|
||||
digits[pos]+=toAdd;
|
||||
while (digits[pos] > 9) {
|
||||
digits[pos]-=10;
|
||||
addOperation(digits, pos+1, maxPos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void crank(bool isSubtract)
|
||||
{
|
||||
tDigitPos pos;
|
||||
if (isSubtract) {
|
||||
subOperation(counter, basePos, NUM_COUNTER_DIGITS, 1);
|
||||
for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) {
|
||||
subOperation(result, basePos+pos, NUM_RESULT_DIGITS, operand[pos]);
|
||||
}
|
||||
} else {
|
||||
addOperation(counter, basePos, NUM_COUNTER_DIGITS, 1);
|
||||
for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) {
|
||||
addOperation(result, basePos+pos, NUM_RESULT_DIGITS, operand[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// Author: Jeremy Rand
|
||||
// Date: July 20, 2012
|
||||
//
|
||||
// This is the interface for the Curta emulator model.
|
||||
//
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifndef _CURTAMODEL_H
|
||||
#define _CURTAMODEL_H
|
||||
|
||||
#define NUM_OPERAND_DIGITS 11
|
||||
#define NUM_RESULT_DIGITS 15
|
||||
#define NUM_COUNTER_DIGITS 8
|
||||
|
||||
typedef int8_t tDigit;
|
||||
typedef int8_t tDigitPos;
|
||||
|
||||
extern tDigit operand[NUM_OPERAND_DIGITS];
|
||||
extern tDigit result[NUM_RESULT_DIGITS];
|
||||
extern tDigit counter[NUM_COUNTER_DIGITS];
|
||||
|
||||
#define IS_VALID_OPERAND_POS(pos) (((pos) >= 0) && ((pos) < NUM_OPERAND_DIGITS))
|
||||
#define IS_VALID_RESULT_POS(pos) (((pos) >= 0) && ((pos) < NUM_RESULT_DIGITS))
|
||||
#define IS_VALID_COUNTER_POS(pos) (((pos) >= 0) && ((pos) < NUM_COUNTER_DIGITS))
|
||||
|
||||
#define GET_OPERAND_DIGIT(pos) (operand[(pos)])
|
||||
#define GET_RESULT_DIGIT(pos) (result[(pos)])
|
||||
#define GET_COUNTER_DIGIT(pos) (counter[(pos)])
|
||||
|
||||
// Ranges from 0 to 8
|
||||
#define BASE_POS_MIN 0
|
||||
#define BASE_POS_MAX 8
|
||||
extern tDigitPos basePos;
|
||||
|
||||
#define IS_VALID_BASE_POS(pos) (((pos) >= BASE_POS_MIN) && ((pos) < BASE_POS_MAX))
|
||||
|
||||
extern tDigitPos selectedOperand;
|
||||
#define IS_SELECTED_OPERAND(pos) ((pos) == selectedOperand);
|
||||
|
||||
|
||||
typedef void (*operandChangeNotif)(tDigitPos pos);
|
||||
|
||||
extern void clearDevice(void);
|
||||
extern void initDevice(operandChangeNotif callback);
|
||||
|
||||
extern void incOperandPos(tDigitPos pos);
|
||||
extern void decOperandPos(tDigitPos pos);
|
||||
|
||||
extern void shiftOperandPos(bool left);
|
||||
|
||||
extern void shiftResultPos(bool left);
|
||||
|
||||
extern void crank(bool isSubtract);
|
||||
|
||||
#endif
|
|
@ -1,29 +1,30 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
//
|
||||
// Author: Jeremy Rand
|
||||
// Date: July 20, 2012
|
||||
//
|
||||
// This is the implementation for the Curta emulator UI.
|
||||
//
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <conio.h>
|
||||
#include <apple2.h>
|
||||
#include <apple2enh.h>
|
||||
#include <conio.h>
|
||||
#include <joystick.h>
|
||||
#include <tgi.h>
|
||||
#include <tgi/tgi-mode.h>
|
||||
|
||||
#include "curtaModel.h"
|
||||
#include "curtaUI.h"
|
||||
|
||||
|
||||
// Extern symbols for joystick and graphics drivers
|
||||
extern char a2e_stdjoy;
|
||||
extern char a2e_hi;
|
||||
|
||||
#define NUM_OPERAND_DIGITS 11
|
||||
#define NUM_RESULT_DIGITS 15
|
||||
#define NUM_COUNTER_DIGITS 8
|
||||
|
||||
typedef int8_t tDigit;
|
||||
typedef int8_t tDigitPos;
|
||||
typedef int8_t tAction;
|
||||
typedef int8_t tJoyPos;
|
||||
|
||||
#define ACTION_OPERAND_SHIFT_LEFT 0
|
||||
#define ACTION_OPERAND_SHIFT_RIGHT 1
|
||||
|
@ -36,6 +37,9 @@ typedef int8_t tJoyPos;
|
|||
#define ACTION_CLEAR 8
|
||||
#define ACTION_NULL 9
|
||||
|
||||
|
||||
typedef int8_t tJoyPos;
|
||||
|
||||
#define JOY_POS_CENTER 0
|
||||
#define JOY_POS_DOWN 1
|
||||
#define JOY_POS_DOWN_LEFT 2
|
||||
|
@ -46,16 +50,6 @@ typedef int8_t tJoyPos;
|
|||
#define JOY_POS_RIGHT 7
|
||||
#define JOY_POS_DOWN_RIGHT 8
|
||||
|
||||
tDigit operand[NUM_OPERAND_DIGITS];
|
||||
tDigit result[NUM_RESULT_DIGITS];
|
||||
tDigit counter[NUM_COUNTER_DIGITS];
|
||||
|
||||
// Ranges from 0 to 8
|
||||
#define RESULT_POS_MIN 0
|
||||
#define RESULT_POS_MAX 8
|
||||
tDigitPos resultPos;
|
||||
tDigitPos selectedOperand;
|
||||
|
||||
|
||||
#define OPERAND_COLOR COLOR_WHITE
|
||||
#define OPERAND_OFFSET 4
|
||||
|
@ -76,148 +70,7 @@ tDigitPos selectedOperand;
|
|||
#define SLIDER_Y_SPACING (SLIDER_HEIGHT + (2 * SLIDER_Y_OFFSET))
|
||||
|
||||
|
||||
void drawOperand(tDigitPos pos);
|
||||
|
||||
|
||||
void clearDevice(void)
|
||||
{
|
||||
tDigitPos pos;
|
||||
|
||||
for (pos = 0; pos < NUM_RESULT_DIGITS; pos++) {
|
||||
result[pos] = 0;
|
||||
}
|
||||
for (pos = 0; pos < NUM_COUNTER_DIGITS; pos++) {
|
||||
counter[pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void resetDevice(void)
|
||||
{
|
||||
tDigitPos pos;
|
||||
|
||||
clearDevice();
|
||||
resultPos = 0;
|
||||
selectedOperand = 0;
|
||||
|
||||
for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) {
|
||||
result[pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void incOperandPos(tDigitPos pos)
|
||||
{
|
||||
if (pos >= NUM_OPERAND_DIGITS)
|
||||
return;
|
||||
|
||||
if (operand[pos] == 9)
|
||||
return;
|
||||
|
||||
operand[pos]++;
|
||||
drawOperand(pos);
|
||||
}
|
||||
|
||||
|
||||
void decOperandPos(tDigitPos pos)
|
||||
{
|
||||
if (pos >= NUM_OPERAND_DIGITS)
|
||||
return;
|
||||
|
||||
if (operand[pos] == 0)
|
||||
return;
|
||||
|
||||
operand[pos]--;
|
||||
drawOperand(pos);
|
||||
}
|
||||
|
||||
|
||||
void shiftOperandPos(bool left)
|
||||
{
|
||||
tDigitPos newPos = selectedOperand;
|
||||
tDigitPos oldPos = selectedOperand;
|
||||
|
||||
if (left) {
|
||||
newPos++;
|
||||
if (newPos >= NUM_OPERAND_DIGITS) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
newPos--;
|
||||
if (newPos < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
selectedOperand = newPos;
|
||||
drawOperand(oldPos);
|
||||
drawOperand(newPos);
|
||||
}
|
||||
|
||||
void shiftResultPos(bool left)
|
||||
{
|
||||
if (left) {
|
||||
if (resultPos + 1 >= RESULT_POS_MAX)
|
||||
return;
|
||||
resultPos++;
|
||||
} else {
|
||||
if (resultPos <= RESULT_POS_MIN)
|
||||
return;
|
||||
resultPos--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void subOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toSub)
|
||||
{
|
||||
if (toSub == 0)
|
||||
return;
|
||||
|
||||
if (pos >= maxPos)
|
||||
return;
|
||||
|
||||
digits[pos]-=toSub;
|
||||
while (digits[pos] < 0) {
|
||||
digits[pos]+=10;
|
||||
subOperation(digits, pos+1, maxPos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void addOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toAdd)
|
||||
{
|
||||
if (toAdd == 0)
|
||||
return;
|
||||
|
||||
if (pos >= maxPos)
|
||||
return;
|
||||
|
||||
digits[pos]+=toAdd;
|
||||
while (digits[pos] > 9) {
|
||||
digits[pos]-=10;
|
||||
addOperation(digits, pos+1, maxPos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void crank(bool isSubtract)
|
||||
{
|
||||
tDigitPos pos;
|
||||
if (isSubtract) {
|
||||
subOperation(counter, resultPos, NUM_COUNTER_DIGITS, 1);
|
||||
for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) {
|
||||
subOperation(result, resultPos+pos, NUM_RESULT_DIGITS, operand[pos]);
|
||||
}
|
||||
} else {
|
||||
addOperation(counter, resultPos, NUM_COUNTER_DIGITS, 1);
|
||||
for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) {
|
||||
addOperation(result, resultPos+pos, NUM_RESULT_DIGITS, operand[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printDigits(char *label, tDigit *digits, tDigitPos maxPos)
|
||||
static void printDigits(char *label, tDigit *digits, tDigitPos maxPos)
|
||||
{
|
||||
tDigitPos pos;
|
||||
|
||||
|
@ -229,33 +82,31 @@ void printDigits(char *label, tDigit *digits, tDigitPos maxPos)
|
|||
}
|
||||
|
||||
|
||||
void printState(void)
|
||||
static void printState(void)
|
||||
{
|
||||
tDigitPos pos;
|
||||
printDigits("Counter", counter, NUM_COUNTER_DIGITS);
|
||||
printDigits("Result", result, NUM_RESULT_DIGITS);
|
||||
|
||||
printf(" ");
|
||||
for(pos = 0; pos < NUM_RESULT_DIGITS - resultPos; pos++) {
|
||||
for(pos = 0; pos < NUM_RESULT_DIGITS - basePos; pos++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf(" ^\n");
|
||||
}
|
||||
|
||||
|
||||
void drawOperand(tDigitPos pos)
|
||||
static void drawOperand(tDigitPos pos)
|
||||
{
|
||||
char xPos;
|
||||
char buffer[2];
|
||||
tDigit digit;
|
||||
|
||||
if (pos < 0)
|
||||
return;
|
||||
if (pos >= NUM_OPERAND_DIGITS)
|
||||
if (!IS_VALID_OPERAND_POS(pos))
|
||||
return;
|
||||
|
||||
xPos = SLIDER_X_BORDER + (SLIDER_BAR_SPACING * (NUM_OPERAND_DIGITS - pos - 1));
|
||||
digit = operand[pos];
|
||||
digit = GET_OPERAND_DIGIT(pos);
|
||||
|
||||
// Clear old bar
|
||||
tgi_setcolor(COLOR_BLACK);
|
||||
|
@ -288,7 +139,7 @@ void drawOperand(tDigitPos pos)
|
|||
}
|
||||
|
||||
|
||||
tJoyPos getJoyPos(char joyState)
|
||||
static tJoyPos getJoyPos(char joyState)
|
||||
{
|
||||
if (JOY_BTN_UP(joyState)) {
|
||||
if (JOY_BTN_LEFT(joyState)) {
|
||||
|
@ -318,7 +169,7 @@ tJoyPos getJoyPos(char joyState)
|
|||
}
|
||||
|
||||
|
||||
tAction getNextAction(void)
|
||||
static tAction getNextAction(void)
|
||||
{
|
||||
static bool firstCall = true;
|
||||
static char oldJoyState;
|
||||
|
@ -448,11 +299,13 @@ tAction getNextAction(void)
|
|||
}
|
||||
|
||||
|
||||
void graphicalInterface(void)
|
||||
void initUI(void)
|
||||
{
|
||||
// Install drivers
|
||||
tDigitPos pos;
|
||||
|
||||
initDevice(drawOperand);
|
||||
|
||||
joy_install(&a2e_stdjoy);
|
||||
tgi_install(&a2e_hi);
|
||||
|
||||
|
@ -466,66 +319,69 @@ void graphicalInterface(void)
|
|||
asm ("STA %w", 0xc053);
|
||||
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
||||
printState();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if ((kbhit()) &&
|
||||
(cgetc() == ' ')) {
|
||||
break;
|
||||
}
|
||||
switch (getNextAction()) {
|
||||
case ACTION_NULL:
|
||||
break;
|
||||
case ACTION_OPERAND_SHIFT_LEFT:
|
||||
shiftOperandPos(true);
|
||||
break;
|
||||
|
||||
case ACTION_OPERAND_SHIFT_RIGHT:
|
||||
shiftOperandPos(false);
|
||||
break;
|
||||
bool processNextEvent(void)
|
||||
{
|
||||
bool timeToQuit = false;
|
||||
|
||||
case ACTION_OPERAND_INC:
|
||||
incOperandPos(selectedOperand);
|
||||
break;
|
||||
|
||||
case ACTION_OPERAND_DEC:
|
||||
decOperandPos(selectedOperand);
|
||||
break;
|
||||
|
||||
case ACTION_RESULT_SHIFT_LEFT:
|
||||
shiftResultPos(true);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_RESULT_SHIFT_RIGHT:
|
||||
shiftResultPos(false);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_ADD:
|
||||
crank(false);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_SUBTRACT:
|
||||
crank(true);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_CLEAR:
|
||||
clearDevice();
|
||||
printState();
|
||||
break;
|
||||
}
|
||||
// Exit on ESC
|
||||
if ((kbhit()) &&
|
||||
(cgetc() == 27)) {
|
||||
timeToQuit = true;
|
||||
}
|
||||
|
||||
switch (getNextAction()) {
|
||||
case ACTION_NULL:
|
||||
break;
|
||||
case ACTION_OPERAND_SHIFT_LEFT:
|
||||
shiftOperandPos(true);
|
||||
break;
|
||||
|
||||
case ACTION_OPERAND_SHIFT_RIGHT:
|
||||
shiftOperandPos(false);
|
||||
break;
|
||||
|
||||
case ACTION_OPERAND_INC:
|
||||
incOperandPos(selectedOperand);
|
||||
break;
|
||||
|
||||
case ACTION_OPERAND_DEC:
|
||||
decOperandPos(selectedOperand);
|
||||
break;
|
||||
|
||||
case ACTION_RESULT_SHIFT_LEFT:
|
||||
shiftResultPos(true);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_RESULT_SHIFT_RIGHT:
|
||||
shiftResultPos(false);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_ADD:
|
||||
crank(false);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_SUBTRACT:
|
||||
crank(true);
|
||||
printState();
|
||||
break;
|
||||
|
||||
case ACTION_CLEAR:
|
||||
clearDevice();
|
||||
printState();
|
||||
break;
|
||||
}
|
||||
return timeToQuit;
|
||||
}
|
||||
|
||||
|
||||
void shutdownUI(void)
|
||||
{
|
||||
// Uninstall drivers
|
||||
tgi_uninstall();
|
||||
joy_uninstall();
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
graphicalInterface();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Author: Jeremy Rand
|
||||
// Date: July 20, 2012
|
||||
//
|
||||
// This is the interface for the Curta emulator UI.
|
||||
//
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifndef _CURTAUI_H
|
||||
#define _CURTAUI_H
|
||||
|
||||
extern void initUI(void);
|
||||
extern void shutdownUI(void);
|
||||
extern bool processNextEvent(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue