home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
141.lha
/
C64_Emulator
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-21
|
7KB
|
373 lines
/*
* Commodore 64 Spoof Emulator (C) Eddy Carroll, 1st April 1988
*
* Module: MAIN.C
*
* This module is the mainline - it handles the input loop and command
* interpretation logic.
*
* Note: Compile with Lattice V3.10 or later. Manx may work, but hasn't
* been tested.
*
*/
#include <exec/types.h>
#include <exec/io.h>
#include <intuition/intuition.h>
#include "screen.h"
#include "commands.h"
extern struct Menu mymenus;
extern struct IntuiText mytext[];
extern struct commandlist command[]; /* Commands & Responses */
extern char *errormsg[]; /* List of error msgs */
extern int MAXCOMMANDS; /* Number of commands */
extern int MAXERRORS; /* Number of messages */
extern char *STARTUP; /* Startup message */
extern char *ABOUT; /* "About..." message */
extern char *READY; /* Ready prompt */
/*
* Executes one of the menu commands
*
*/
void domenu(opt)
int opt;
{
CURSOROFF;
switch (opt) {
case M_ABOUT:
clearscreen();
if (titlebar) printchar('\r'); /* Skip past title bar if on */
printmess(ABOUT);
printmess(READY);
break;
case M_TITLE:
titlebar = !titlebar;
ClearMenuStrip(mywin);
mytext[1].IText = titlebar ? " Hide Title" : " Show Title";
SetMenuStrip(mywin,&mymenus);
ShowTitle(myscreen, titlebar);
break;
case M_QUIT:
cleanup(0);
break;
}
}
/*
* Returns a random number in range 0..range-1.
*
*/
int random(range)
int range;
{
LONG seconds,micros;
CurrentTime(&seconds,µs);
return (micros % range);
}
/*
* Reads current line from screen into string, stripping off any extra
* leading or trailing spaces.
*
*/
void getcommand(s)
char *s;
{
int i = 0, j = 39;
char *p;
p = screen[cursory];
while (p[i] == ' ' && i < 40)
i++;
if (i == 40) {
*s = '\0';
return;
}
while (p[j] == ' ')
j--;
while (i <= j) {
*s++ = toupper(p[i]);
i++;
}
*s = '\0';
}
/*
* Returns TRUE if the first n chars of the two strings are equal, else
* returns FALSE
*
*/
int match(s1,s2,n)
char *s1,*s2;
int n;
{
while (*s1++ == *s2++ && n)
n--;
return (!n);
}
/*
* Initialises error messages to be in random order.
*
*/
void initerror()
{
int i, x, y;
char *p;
for (i = 0; i < MAXERRORS; i++) {
x = random(MAXERRORS);
y = MAXERRORS - 1 - random(MAXERRORS);
p = errormsg[x];
errormsg[x] = errormsg[y];
errormsg[y] = p;
}
}
/*
* Prints a suitable response for command in string s. If a match is found
* in the command list, then a reponse appropriate to that command is
* printed, else one of the standard error messages is printed.
*
*/
void docommand(s)
char *s;
{
static int curerr = 0;
int i = 1, k = -1, x, y;
char *p;
struct commandlist *com;
if (*s >= '0' && *s <= '9')
k = 0;
else {
while (i < MAXCOMMANDS && k < 0) {
if (match(command[i].asc,s,command[i].len))
k = i;
i++;
}
}
printchar('\r');
if (k >= 0) {
com = &command[k];
do {
com->num++;
/* If we have printed all three messages once each, re-arrange */
/* the order of them before we print them again to make it */
/* seem random. */
if (com->num >= MAXRESPONSE) {
com->num = 0;
x = random(MAXRESPONSE); y = random(MAXRESPONSE);
p = com->response[x];
com->response[x] = com->response[y];
com->response[y] = p;
}
} while ((p = com->response[com->num]) == NULL);
printmess(p);
} else {
printmess(errormsg[curerr]);
curerr++;
if (curerr >= MAXERRORS) {
curerr = 0;
initerror();
}
}
printmess(READY);
}
/*
* Initialises the message headers to point to random messages
*
*/
void initmess()
{
int i;
for (i = 0; i < MAXCOMMANDS; i++)
command[i].num = random(3);
}
/*
* Returns code for function key n, where n = 0..20
* Returns 0 if no char equivalent.
*
*/
char fkey(n)
int n;
{
register char ch;
switch (n) {
case 0: ch = C_HOME; break;
case 1: ch = C_CLEAR; break;
case 9: ch = C_INSERT; break;
case 20: printmess("HELP");
default: ch = 0; break;
}
return (ch);
}
/*
* Converts code (an escape character) into one of the internal codes
* (or 0 if no corresponding code)
*
*/
char convert(ch)
char ch;
{
switch (ch) {
case 'A': ch = C_UP; break;
case 'B': ch = C_DOWN; break;
case 'C': ch = C_RIGHT; break;
case 'D': ch = C_LEFT; break;
default: ch = 0;
}
return(ch);
}
/*
* Mainline
*
*/
void main()
{
LONG MenuNumber;
struct MenuItem *item;
register struct IntuiMessage *message;
register struct Message *conmessage;
int escape = 0;
LONG class;
USHORT code;
int time = 3, curstate = 0, fkeynum;
char s[50], ch;
titlebar = 0; /* Initially hidden */
initscreen();
initmess();
initerror();
printmess(STARTUP);
printmess(READY);
CURSORON;
/* Main loop */
#define INTUIBITS (1 << mywin->UserPort->mp_SigBit)
#define CONSOLEBITS (1 << ConReadPort->mp_SigBit)
while (1) {
/* Reset message pointers, just in case 2nd part of conditional */
/* && isn't executed. */
message = NULL;
conmessage = NULL;
while ((message = (struct IntuiMessage *)
GetMsg(mywin->UserPort)) == NULL &&
(conmessage = (struct Message *)
GetMsg(ConReadPort)) == NULL)
Wait ( INTUIBITS | CONSOLEBITS);
if (message) { /* Got an IntuiMessage */
class = message->Class;
code = message->Code;
ReplyMsg((struct Message *)message);
switch (class) {
case MENUPICK:
MenuNumber = code;
while (MenuNumber != MENUNULL) {
item = (struct MenuItem *)ItemAddress(&mymenus,MenuNumber);
code = item->Command;
MenuNumber = item->NextSelect;
}
domenu(code);
break;
case INTUITICKS:
if (time == 0) {
curstate = 1 - curstate;
if (curstate)
CURSORON;
else
CURSOROFF;
time = 3;
} else --time;
break;
}
}
if (conmessage) { /* Character from console */
ch = *constring;
/* Retrieve char, then line up request for next char */
QueueRead(ConReadReq,constring);
if (ch == CSI)
escape = 1, fkeynum = 0;
else {
if (escape) {
if (isdigit(ch))
fkeynum = fkeynum * 10 + ch - '0', ch = 0;
else if (ch == '?')
fkeynum = 20, ch = 0;
else if (ch == ' ')
escape = 2, ch = 0;
else {
escape = 0;
if (ch == '~')
ch = fkey(fkeynum);
else if (escape != 2)
ch = convert(ch);
}
}
CURSOROFF;
if (ch == '\r') {
getcommand(s); /* Read command from screen */
printchar(ch);
if (*s)
docommand(s);
} else
printchar(ch);
CURSORON;
time = 3;
curstate = 1;
}
}
}
}