2023-11-16 18:19:54 -05:00

800 lines
16 KiB
C

/*------------------------------------------------------*/
/* AMIGA GENERIC INTERFACE (TFTP) */
/*------------------------------------------------------*/
#include "exec\types.h"
#include "exec\exec.h"
#include "libraries\dos.h"
#include "libraries\dosextens.h"
#include "intuition\intuition.h" /* for AllocRemember */
#include "intuition\intuibase.h"
#include "devices\serial.h" /* for serial port I/O */
#define CHAR unsigned char
#define INT short /* 16 bits for 68K compatibility */
#define LONG long
#define VOID int
#define GLOBAL /**/
#define FOREVER for(;;)
/************************************************************************/
/* Global Variables */
/************************************************************************/
struct IOExtSer XIOExtSer; /* for serial device, IOStdReq+ */
struct MsgPort XMsgPort;
LONG con_file; /* console file refnum */
/* LONG ser_file; */ /* serial file refnum */
/* This slot returns file refnums to caller (function returns an error code).
Better solution -- return refnum through a VAR type parameter */
LONG temp_channel;
INT columns, cur_column; /* cursor info */
INT rows, cur_row; /* cur_row in 0 .. rows-1 */
INT split_row; /* first row in scrolling area */
CHAR savename[64]; /* buffer for file_select dialog */
CHAR saveback[64]; /* buffer for default name */
/* These vars increase the speed of disk reads */
LONG old_channel = -1;
LONG old_offset = -1;
struct IntuitionBase *IntuitionBase;
struct Remember *RememberKey;
/************************************************************************/
/* Low Level Console Device I/O */
/************************************************************************/
/*------------------------------*/
/* write_console */
/*------------------------------*/
VOID
write_console (string, len) /* send raw string to console device */
CHAR *string;
INT len;
{
Write (con_file, string, len); /* AmigaDOS write */
}
/*------------------------------*/
/* read_console */
/*------------------------------*/
CHAR
read_console () /* get a char from console device */
{
CHAR the_char;
/* RAW read always completes after a single character */
Read (con_file, &the_char, 1);
return (the_char);
}
/*------------------------------*/
/* send_control_seq */
/*------------------------------*/
#define begin_mark '\233' /* 0x9B (one byte only) */
VOID
send_control_seq (string) /* write it, prefixed with control char */
CHAR *string;
{
CHAR temp;
temp = begin_mark;
write_console (&temp, 1);
write_console (string, strlen (string));
}
/*------------------------------*/
/* get_control_seq */ /* read chars into buffer */
/*------------------------------*/
VOID
get_control_seq (buffer, end_mark)
CHAR *buffer;
CHAR end_mark;
{
CHAR the_char;
INT i;
while ((the_char = read_console ()) != begin_mark)
{
/* ignore any prior chars, also starting mark */
}
i = 0;
while ((the_char = read_console ()) != end_mark)
{
buffer[i] = the_char;
i++;
}
buffer[i] = end_mark; /* end with the ending mark */
buffer[i+1] = 0; /* make it ASCIZ */
}
/************************************************************************/
/* Low Level Functions */
/************************************************************************/
/************************************************************************/
/* Cursor Positioning */
/************************************************************************/
/* ALL absolute cursor positioning should go through these two routines */
/*------------------------------*/
/* read_cursor_pos */
/*------------------------------*/
VOID
read_cursor_pos () /* read, unparse, and digitize cursor position,
store in globals */
{
CHAR cursor_info[64];
CHAR *startx,*endx; /* string limits */
CHAR *starty,*endy;
int x_value,y_value; /* careful of type here */
/* read in string representing cursor position -- format is <row>;<col>R */
send_control_seq ("6n");
get_control_seq (&cursor_info, 'R');
/* setup pointers to x and y strings, and make them asciz */
endy = (CHAR *) strchr (&cursor_info, ';');
endx = (CHAR *) strchr (&cursor_info, 'R');
starty = (CHAR *) &cursor_info; endy[0] = 0;
startx = endy + 1; endx[0] = 0;
/* convert decimal strings to integers,
normalize (cur_row in 0 .. rows - 1),
leave results in globals (global type may be different) */
stcd_i (starty, &y_value); cur_row = y_value - 1;
stcd_i (startx, &x_value); cur_column = x_value - 1;
}
/*------------------------------*/
/* write_cursor_pos */
/*------------------------------*/
VOID
write_cursor_pos (x_new, y_new) /* reset the cursor position */
INT x_new,y_new;
{
CHAR cursor_info[64];
CHAR x_str[32];
CHAR y_str[32];
/* normalize co-ords (y_new in 0 .. rows - 1), convert integers to strings */
stcu_d (&x_str, x_new + 1, 32);
stcu_d (&y_str, y_new + 1, 32);
/* combine and transmit the strings */
cursor_info[0] = 0; /* asciz */
strcat (&cursor_info, &y_str);
strcat (&cursor_info, ";");
strcat (&cursor_info, &x_str);
strcat (&cursor_info, "H");
send_control_seq (&cursor_info);
}
/*------------------------------*/
/* amiga_scroll */
/*------------------------------*/
VOID
amiga_scroll () /* method depends on cursor position */
{
CHAR char_seq[2];
read_cursor_pos (); /* get cursor pos into globals */
if (cur_row < rows) /* not at bottom of screen? */
{
char_seq[0] = 13;
char_seq[1] = 10; /* CR, tack on a LF */
write_console (&char_seq, 2);
}
else /* at bottom, delete top line to scroll */
{
write_cursor_pos (0, split_row);
send_control_seq ("M");
write_cursor_pos (0, cur_row);
}
}
/************************************************************************/
/* Screen Handling */
/************************************************************************/
/*------------------------------*/
/* clear_eol */
/*------------------------------*/
VOID
clear_eol ()
{
send_control_seq ("K"); /* clear to EOL */
}
/*------------------------------*/
/* clear_screen */
/*------------------------------*/
VOID
clear_screen ()
{
write_cursor_pos (0,0);
send_control_seq ("J");
write_cursor_pos (0,1); /* move cursor to second row */
}
/*------------------------------*/
/* line_out */
/*------------------------------*/
VOID
line_out (string, len) /* draw a string at current position, */
CHAR *string;
INT len;
{
write_console (string, len);
}
/*------------------------------*/
/* char_out */
/*------------------------------*/
VOID
char_out (the_char) /* if CR or BS, special case, else draw the char */
CHAR the_char;
{
CHAR char_seq[4];
if (the_char == 13)
{
amiga_scroll ();
}
else if (the_char == 8)
{
char_seq[0] = 8;
char_seq[1] = 32; /* erase the current char */
char_seq[2] = 8;
write_console (&char_seq, 3);
}
else write_console (&the_char, 1);
}
/*------------------------------*/
/* char_in */
/*------------------------------*/
CHAR
char_in () /* wait for keyboard input */
{
CHAR the_char;
the_char = read_console ();
if (the_char == begin_mark)
{
the_char = 'X'; /* don't echo begin_mark! */
}
return (the_char);
}
/************************************************************************/
/* File Selection */
/************************************************************************/
/*------------------------------*/
/* file_select */
/*------------------------------*/
INT
file_select (opsave, drive) /* get file and pathspec from user, */
/* combine and leave in SAVENAME */
INT opsave; /* zero if restore, otherwise save */
CHAR drive; /* drive to use, zero for default */
{
}
/*------------------------------*/
/* new_default */
/*------------------------------*/
VOID
new_default (okay) /* called at end of each SAVE/RESTORE */
INT okay;
{
if (okay) /* dest <- source */
{
strcpy (saveback, savename); /* update old defaults */
}
else
{
strcpy (savename, saveback); /* retrieve old defaults */
}
}
/************************************************************************/
/* Serial Port I/O */
/************************************************************************/
/*------------------------------*/
/* init_serial */
/*------------------------------*/
VOID
init_serial (open) /* initialize/uninitialize the serial port */
INT open;
{
if (open)
{
if (OpenDevice ("serial.device", 0, &XIOExtSer, 0) != 0)
{
/* error */
}
/* set up the message port in the I/O request */
XMsgPort.mp_Node.ln_Type = NT_MSGPORT;
XMsgPort.mp_Flags = 0;
XMsgPort.mp_SigBit = AllocSignal (-1);
XMsgPort.mp_SigTask = (struct Task *) FindTask (NULL);
AddPort (&XMsgPort);
XIOExtSer.IOSer.io_Message.mn_ReplyPort = &XMsgPort;
/* configure the port to read 8 data bits */
XIOExtSer.io_ReadLen = 8;
/* disable xON-xOFF (causes loss of valid data) */
XIOExtSer.io_SerFlags |= SERF_XDISABLED;
/* XIOExtSer.io_WBufLen = 2; (was zero) */
XIOExtSer.io_BrkTime = (30 * 1000 * 1000);
XIOExtSer.IOSer.io_Command = SDCMD_SETPARAMS;
DoIO (&XIOExtSer);
}
else /* clean up the various structures we created */
{
RemPort (&XMsgPort);
FreeSignal (XMsgPort.mp_SigBit);
CloseDevice (&XIOExtSer);
}
}
/*------------------------------*/
/* read_serial */
/*------------------------------*/
LONG
read_serial (buffer, length)
CHAR *buffer;
LONG length;
{
/* LONG result;
result = Read (ser_file, buffer, length);
if (result < 0)
return (result);
else return (0);
*/
XIOExtSer.IOSer.io_Data = (APTR) buffer;
XIOExtSer.IOSer.io_Length = length;
XIOExtSer.IOSer.io_Command = CMD_READ;
DoIO (&XIOExtSer);
/* SendIO (&XIOExtSer); */ /* due to bug in DoIO */
}
/*------------------------------*/
/* write_serial */
/*------------------------------*/
LONG
write_serial (buffer, length)
CHAR *buffer;
LONG length;
{
/* if (Write (ser_file, buffer, length) == -1)
return IoErr ();
else return (0);
*/
XIOExtSer.IOSer.io_Data = (APTR) buffer;
XIOExtSer.IOSer.io_Length = length;
XIOExtSer.IOSer.io_Command = CMD_WRITE;
DoIO (&XIOExtSer);
}
/************************************************************************/
/* Disk I/O */
/************************************************************************/
/*------------------------------*/
/* read_file */
/*------------------------------*/
LONG
read_file (channel, offset, length, buffer)
LONG channel;
LONG offset, length;
CHAR *buffer;
{
/* disk access speed is increased, if unnecessary seeks are eliminated */
if (! ((channel == old_channel) & (offset == old_offset)))
{
if (Seek (channel, offset, -1) == -1) /* AmigaDOS */
{
old_offset = -1; /* force seek next time */
return IoErr ();
}
}
old_channel = channel;
old_offset = offset + length;
if (Read (channel, buffer, length) == -1)
return IoErr ();
else return (0); /* zero means no error */
}
/*------------------------------*/
/* write_file */
/*------------------------------*/
LONG
write_file (channel, offset, length, buffer)
LONG channel;
LONG offset, length;
CHAR *buffer;
{
if (Seek (channel, offset, -1) == -1) /* AmigaDOS */
return IoErr ();
if (Write (channel, buffer, length) == -1)
return IoErr ();
else return (0); /* zero means no error */
}
/*------------------------------*/
/* create_file */
/*------------------------------*/
LONG
create_file () /* create AND OPEN a new file, */
/* leave channel in temporary var */
{
temp_channel = Open (savename, MODE_NEWFILE);
if (temp_channel == 0)
return (IoErr ());
else return (0); /* zero means OK */
}
/*------------------------------*/
/* open_file */
/*------------------------------*/
LONG
open_file () /* open an existing file, return channel */
{
temp_channel = Open (savename, MODE_OLDFILE);
if (temp_channel == 0)
return (IoErr ());
else return (0); /* zero means OK */
}
/*------------------------------*/
/* close_file */
/*------------------------------*/
LONG
close_file (channel)
LONG channel;
{
Close (channel);
return (0); /* no error codes? */
}
/*------------------------------*/
/* delete_file */
/*------------------------------*/
LONG
delete_file ()
{
LONG success; /* actually BOOLEAN */
success = DeleteFile (savename);
if (success)
return (0);
else return (1);
}
/*------------------------------*/
/* exist_file */
/*------------------------------*/
LONG
exist_file ()
{
LONG filelock;
filelock = Lock (savename, ACCESS_WRITE);
if (filelock == 0) /* file does not exist */
return (0);
UnLock (filelock); /* exists, undo lock */
return (1); /* and indicate duplicate file */
}
/*------------------------------*/
/* open_game */
/*------------------------------*/
LONG
open_game (gamename, channel)
CHAR *gamename;
LONG *channel; /* return file refnum through this ptr */
{
*channel = Open (gamename, MODE_NEWFILE);
if (*channel == 0)
return (IoErr ());
else return (0); /* zero means OK */
}
/*------------------------------*/
/* close_game */
/*------------------------------*/
LONG
close_game (channel)
LONG channel;
{
Close (channel);
return (0); /* no errors in AmigaDOS ? */
}
/*------------------------------*/
/* write_game */
/*------------------------------*/
LONG
write_game (channel, length, buffer) /* no Seeking for TFTP */
LONG channel;
LONG length;
CHAR *buffer;
{
/* if (Seek (channel, offset, -1) == -1)
return IoErr ();
*/
if (Write (channel, buffer, length) != length)
return IoErr ();
else return (0); /* zero means no error */
}
/************************************************************************/
/* Memory Management */
/************************************************************************/
/*------------------------------*/
/* c_maxmem */
/*------------------------------*/
LONG
c_maxmem () /* return size of available memory pool */
{
return (AvailMem (MEMF_PUBLIC));
}
/*------------------------------*/
/* c_getmem */
/*------------------------------*/
LONG
c_getmem (nbytes)
LONG nbytes;
{
/* return (AllocMem (nbytes, MEMF_PUBLIC)); */ /* zero if failed */
/* This routine calls the AllocMem function, but also allocates a LINK NODE
and saves the data needed for automatic de-allocation when the program ends.
*/
return (AllocRemember (&RememberKey, nbytes, MEMF_PUBLIC));
}
/************************************************************************/
/* Initializations */
/************************************************************************/
/*------------------------------*/
/* z_init */
/*------------------------------*/
INT
z_init ()
{
CHAR *name;
/* open the console device */
name = "raw:0/0/640/200/"; /* untitled */
if ((con_file = Open (name, MODE_NEWFILE )) == 0)
{
return (101);
}
/* and the serial device */
/* ser_file = Open ("SER:", MODE_OLDFILE); */
/* and the Intuition Library */
IntuitionBase = (struct IntuitionBase *)
OpenLibrary ("intuition.library", 0);
if (IntuitionBase == 0)
return (103);
RememberKey = 0; /* set up for memory allocation */
strcpy (saveback, "Story.Save"); /* initial default */
rows = 100; /* force normal scrolling always */
return (0);
}
/*------------------------------*/
/* z_exit */
/*------------------------------*/
VOID
z_exit ()
{
/* De-allocate the various pieces of memory we allocated */
FreeRemember (&RememberKey, TRUE);
CloseLibrary (IntuitionBase);
/* Close (ser_file); */
Close (con_file);
}
/************************************************************************/
/* Diagnostics (Temporary) */
/************************************************************************/
/*------------------------------*/
/* z_test */
/*------------------------------*/
z_test()
{
CHAR mychr;
c_maxmem (); c_getmem (16); /* test memory functions */
c_getmem (16); c_maxmem ();
FOREVER /* do input, output, scroll, until 'quit' */
{
mychr = char_in ();
if (mychr == 'q') break; /* leave the loop */
else if (mychr == 'z') /* print a string */
{
line_out ("xyz", 3);
char_out (13);
}
else char_out (mychr); /* echo the char */
}
}
/************************************************************************/
/* Top Level */
/************************************************************************/
/*------------------------------*/
/* dummy_main */
/*------------------------------*/
INT
dummy_main ()
{
INT error;
error = z_init (); /* zero if OK */
/* if (!error) */
/* z_test (); */
/* START (); */
z_exit (); /* clean up */
return (error);
}