summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/ti85_ser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/ti85_ser.c')
-rw-r--r--src/mess/machine/ti85_ser.c1544
1 files changed, 1544 insertions, 0 deletions
diff --git a/src/mess/machine/ti85_ser.c b/src/mess/machine/ti85_ser.c
new file mode 100644
index 00000000000..6c7de85fc3f
--- /dev/null
+++ b/src/mess/machine/ti85_ser.c
@@ -0,0 +1,1544 @@
+
+#include "emu.h"
+#include "emuopts.h"
+#include "ti85_ser.h"
+
+enum
+{
+ TI85_SEND_STOP,
+ TI85_SEND_HEADER,
+ TI85_RECEIVE_OK_1,
+ TI85_RECEIVE_ANSWER_1,
+ TI85_RECEIVE_ANSWER_2,
+ TI85_RECEIVE_ANSWER_3,
+ TI85_SEND_OK,
+ TI85_SEND_DATA,
+ TI85_RECEIVE_OK_2,
+ TI85_SEND_END,
+ TI85_RECEIVE_OK_3,
+ TI85_RECEIVE_HEADER_1,
+ TI85_PREPARE_VARIABLE_DATA,
+ TI85_RECEIVE_HEADER_2,
+ TI85_SEND_OK_1,
+ TI85_SEND_CONTINUE,
+ TI85_RECEIVE_OK,
+ TI85_RECEIVE_DATA,
+ TI85_SEND_OK_2,
+ TI85_RECEIVE_END_OR_HEADER_1,
+ TI85_SEND_OK_3,
+ TI85_PREPARE_SCREEN_REQUEST,
+ TI85_SEND_SCREEN_REQUEST
+};
+
+//supported image formats
+enum
+{
+ TI_FILE_UNK,
+ TI_FILE_V1, //used for TI-85 and TI-86 image
+ TI_FILE_V2, //used for TI-82, TI-83 and TI-73 image
+ TI_FILE_V3 //used for TI-83+ and TI-84+ image
+};
+
+#define TI85_HEADER_SIZE 0x37
+
+#define TI85_SEND_VARIABLES 1
+#define TI85_SEND_BACKUP 2
+#define TI85_RECEIVE_BACKUP 3
+#define TI85_RECEIVE_VARIABLES 4
+#define TI85_RECEIVE_SCREEN 5
+
+#define TI85_PC_OK_PACKET_SIZE 4
+#define TI85_PC_END_PACKET_SIZE 4
+
+#define TI82_BACKUP_ID 0x0f //used by the TI-82
+#define TI85_BACKUP_ID 0x1d //used by the TI-85 and TI-86
+#define TI83_BACKUP_ID 0x13 //used by the TI-73, TI-83 and TI-83+
+
+//known tranfer ID
+#define TI_TRANFER_ID_TI73 0x07
+#define TI_TRANFER_ID_TI82 0x02
+#define TI_TRANFER_ID_TI83 0x03
+#define TI_TRANFER_ID_TI83P 0x23
+#define TI_TRANFER_ID_TI85 0x05
+#define TI_TRANFER_ID_TI86 0x06
+
+//packet type
+#define TI_OK_PACKET 0x56
+#define TI_CONTINUE_PACKET 0x09
+#define TI_SCREEN_REQUEST_PACKET 0x6d
+#define TI_END_PACKET 0x92
+
+static const UINT8 ti73_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x37, 0x33, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
+static const UINT8 ti85_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x35, 0x2a, 0x2a, 0x1a, 0x0c, 0x00};
+static const UINT8 ti82_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x32, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
+static const UINT8 ti83_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x33, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
+static const UINT8 ti83p_file_signature[]= {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x33, 0x46, 0x2a, 0x1a, 0x0a, 0x00};
+static const UINT8 ti86_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x36, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
+
+typedef struct {
+ UINT16 head_size;
+ UINT16 data_size;
+ unsigned char type;
+ unsigned char name_size;
+ unsigned int offset;
+} ti85_entry;
+
+
+typedef struct {
+ UINT8* header;
+ UINT16 header_size;
+ UINT8* ok;
+ UINT16 ok_size;
+ UINT8* data;
+ UINT32 data_size;
+} ti85_serial_variable;
+
+
+typedef struct {
+ ti85_serial_variable * variables;
+ UINT8* end;
+ UINT16 end_size;
+ UINT16 number_of_variables;
+} ti85_serial_data;
+
+
+typedef struct
+{
+ UINT8 status;
+ int transfer_type;
+ UINT8 image_type;
+ UINT8 send_id; /* ID used for PC to TI transfer */
+ UINT8 receive_id; /* ID used for TI to PC transfer */
+ UINT8 red_out; /* signal line from machine */
+ UINT8 white_out; /* signal line from machine */
+ UINT8 red_in; /* signal line to machine */
+ UINT8 white_in; /* signal line to machine */
+ UINT8 *receive_buffer;
+ UINT8 *receive_data;
+ ti85_serial_data stream;
+ /* receive_data_counter and send_data_counter can be combined? */
+ UINT32 receive_data_counter; /* from ti85_receive_serial */
+ UINT32 send_data_counter; /* from ti85_send_serial */
+ /* variables_variable_number, send_backup_variable_number, and backup_variable_number can be combined? */
+ UINT16 variables_variable_number; /* from ti85_send_variables */
+ UINT16 send_backup_variable_number; /* from ti85_send_backup */
+ int variable_number; /* from ti85_receive_variables */
+ UINT8 *var_data; /* from ti85_receive_variables */
+ UINT32 var_file_number; /* from ti85_receive_variables */
+ UINT8 *var_file_data; /* from ti85_receive_variables */
+ int var_file_size; /* from ti85_receive_variables */
+ int backup_variable_number; /* from ti85_receive_backup */
+ int backup_data_size[3]; /* from ti85_receive_backup */
+ UINT8 *backup_file_data; /* from ti85_receive_backup */
+ UINT32 backup_file_number; /* from ti85_receive_backup */
+ UINT32 image_file_number; /* from ti85_receive_screen */
+} ti85serial_state;
+
+
+INLINE ti85serial_state *get_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == TI82SERIAL) ||
+ (device->type() == TI73SERIAL) ||
+ (device->type() == TI83PSERIAL) ||
+ (device->type() == TI85SERIAL) ||
+ (device->type() == TI86SERIAL));
+ return (ti85serial_state *) downcast<legacy_device_base *>(device)->token();
+}
+
+
+static UINT16 ti85_calculate_checksum(const UINT8* data, unsigned int size)
+{
+ UINT16 checksum = 0;
+ unsigned int i;
+
+ for (i = 0; i<size; i++)
+ checksum += data[i];
+ return checksum;
+}
+
+
+static UINT16 ti85_variables_count (const UINT8 * ti85_data, unsigned int ti85_data_size)
+{
+ unsigned int pos, head_size, var_size;
+ UINT16 number_of_entries = 0;
+ pos = TI85_HEADER_SIZE;
+ while (pos < ti85_data_size-2)
+ {
+ head_size = ti85_data[pos+0x00] + ti85_data[pos+0x01]*256;
+ var_size = ti85_data[pos+0x02] + ti85_data[pos+0x03]*256;
+ pos += head_size+var_size+4;
+ number_of_entries++;
+ }
+ return number_of_entries;
+}
+
+
+static void ti85_free_serial_data_memory (device_t *device)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ if (ti85serial->receive_buffer)
+ {
+ free (ti85serial->receive_buffer);
+ ti85serial->receive_buffer = NULL;
+ }
+ if (ti85serial->receive_data)
+ {
+ free (ti85serial->receive_data);
+ ti85serial->receive_data = NULL;
+ }
+}
+
+
+static int ti85_alloc_serial_data_memory (device_t *device, UINT32 size)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ if (!ti85serial->receive_buffer)
+ {
+ ti85serial->receive_buffer = (UINT8*) malloc (8*size*sizeof(UINT8));
+ if (!ti85serial->receive_buffer)
+ return 0;
+ }
+
+ if (!ti85serial->receive_data)
+ {
+ ti85serial->receive_data = (UINT8*) malloc (size * sizeof(UINT8));
+ if (!ti85serial->receive_data)
+ {
+ free (ti85serial->receive_buffer);
+ ti85serial->receive_buffer = NULL;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+static void ti85_backup_read (const UINT8 * ti85_data, unsigned int ti85_data_size, ti85_entry * ti85_entries)
+{
+ unsigned int pos = 0x42+2;
+
+ ti85_entries[0].head_size = 0x09;
+ ti85_entries[0].data_size = ti85_data[0x39] + ti85_data[0x3a]*256;
+ ti85_entries[0].offset = pos;
+ pos += ti85_entries[0].data_size + 2;
+ ti85_entries[1].head_size = 0;
+ ti85_entries[1].data_size = ti85_data[0x3c] + ti85_data[0x3d]*256;
+ ti85_entries[1].offset = pos;
+ pos += ti85_entries[1].data_size + 2;
+ ti85_entries[2].head_size = 0;
+ ti85_entries[2].data_size = ti85_data[0x3e] + ti85_data[0x3f]*256;
+ ti85_entries[2].offset = pos;
+}
+
+
+static void ti85_variables_read (device_t *device, const UINT8 * ti85_data, unsigned int ti85_data_size, ti85_entry * ti85_entries)
+{
+ ti85serial_state *ti85serial = get_token( device );
+ unsigned int pos, i=0;
+
+ pos = TI85_HEADER_SIZE;
+ while (pos < ti85_data_size-2)
+ {
+ ti85_entries[i].head_size = ti85_data[pos+0x00] + ti85_data[pos+0x01]*256;
+ ti85_entries[i].data_size = ti85_data[pos+0x02] + ti85_data[pos+0x03]*256;
+ ti85_entries[i].type = ti85_data[pos+0x04];
+ ti85_entries[i].name_size = (ti85serial->image_type != TI_FILE_V1) ? 8 : ti85_data[pos+0x05];
+ ti85_entries[i].offset = pos;
+ pos += ti85_entries[i].head_size+ti85_entries[i].data_size+4;
+ i++;
+ }
+}
+
+
+static int ti85_receive_serial (device_t *device, UINT8* received_data, UINT32 received_data_size)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ if (ti85serial->receive_data_counter >= received_data_size)
+ {
+ if (!ti85serial->red_out && !ti85serial->white_out)
+ {
+ ti85serial->red_in = ti85serial->white_in = 1;
+ ti85serial->receive_data_counter = 0;
+ return 0;
+ }
+ return 1;
+ }
+
+ if (ti85serial->red_in && ti85serial->white_in && (ti85serial->red_out!=ti85serial->white_out))
+ {
+ ti85serial->white_in = ti85serial->white_out;
+ ti85serial->red_in = ti85serial->red_out;
+ received_data[ti85serial->receive_data_counter] = ti85serial->white_out;
+ return 1;
+ }
+
+ if (ti85serial->red_in!=ti85serial->white_in && !ti85serial->red_out && !ti85serial->white_out)
+ {
+ ti85serial->red_in = ti85serial->white_in = 1;
+ ti85serial->receive_data_counter ++;
+ return 1;
+ }
+ return 1;
+}
+
+
+static int ti85_send_serial(device_t *device, UINT8* serial_data, UINT32 serial_data_size)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ if (ti85serial->send_data_counter>=serial_data_size)
+ {
+ if (!ti85serial->red_out && !ti85serial->white_out)
+ {
+ ti85serial->red_in = ti85serial->white_in = 1;
+ ti85serial->send_data_counter = 0;
+ return 0;
+ }
+ ti85serial->red_in = ti85serial->white_in = 1;
+ return 1;
+ }
+
+ if (ti85serial->red_in && ti85serial->white_in && !ti85serial->red_out && !ti85serial->white_out)
+ {
+ ti85serial->red_in = serial_data[ti85serial->send_data_counter] ? 1 : 0;
+ ti85serial->white_in = serial_data[ti85serial->send_data_counter] ? 0 : 1;
+ return 1;
+ }
+
+ if ((ti85serial->red_in == ti85serial->red_out) && (ti85serial->white_in == ti85serial->white_out))
+ {
+ ti85serial->red_in = ti85serial->white_in = 1;
+ ti85serial->send_data_counter++;
+ return 1;
+ }
+ return 1;
+}
+
+
+static void ti85_convert_data_to_stream (const UINT8* file_data, unsigned int size, UINT8* serial_data)
+{
+ unsigned int i, bits;
+
+ for (i=0; i<size; i++)
+ for (bits = 0; bits < 8; bits++)
+ serial_data[i*8+bits] = (file_data[i]>>bits) & 0x01;
+}
+
+
+static void ti85_append_head_to_stream (UINT8 transfer_id, UINT8 tranfer_type, UINT8* serial_data)
+{
+ UINT8 tmp_data[4];
+
+ tmp_data[0] = transfer_id;
+ tmp_data[1] = tranfer_type;
+ tmp_data[2] = 0;
+ tmp_data[3] = 0;
+
+ ti85_convert_data_to_stream(tmp_data, sizeof(tmp_data), serial_data);
+}
+
+
+static void ti85_convert_stream_to_data (const UINT8* serial_data, UINT32 size, UINT8* data)
+{
+ UINT32 i;
+ UINT8 bits;
+
+ size = size/8;
+
+ for (i=0; i<size; i++)
+ {
+ data[i] = 0;
+ for (bits = 0; bits < 8; bits++)
+ data[i] |= serial_data[i*8+bits]<<bits;
+ }
+}
+
+
+static int ti85_convert_file_data_to_serial_stream (device_t *device, const UINT8* file_data, unsigned int file_size, ti85_serial_data* serial_data)
+{
+ ti85serial_state *ti85serial = get_token( device );
+ UINT16 i;
+ UINT16 number_of_entries;
+ UINT8 backup_id = (ti85serial->image_type == TI_FILE_V1) ? TI85_BACKUP_ID : ((device->type() == TI82SERIAL) ? TI82_BACKUP_ID : TI83_BACKUP_ID);
+
+ ti85_entry* ti85_entries = NULL;
+
+ UINT8* temp_data_to_convert = NULL;
+ UINT16 checksum;
+
+ //verify that the provided file is compatible with the model
+ if (device->type() == TI73SERIAL)
+ if (strncmp((char *) file_data, (char *) ti73_file_signature, 11))
+ return 0;
+ if (device->type() == TI85SERIAL)
+ if (strncmp((char *) file_data, (char *) ti85_file_signature, 11))
+ return 0;
+ if (device->type() == TI82SERIAL)
+ if (strncmp((char *) file_data, (char *) ti82_file_signature, 11))
+ return 0;
+ if (device->type() == TI83PSERIAL) //TI-83+ is compatible with TI-83 and TI-82 file
+ if (strncmp((char *) file_data, (char *) ti83p_file_signature, 10) && strncmp((char *) file_data, (char *) ti83_file_signature, 11)
+ && strncmp((char *) file_data, (char *) ti82_file_signature, 11))
+ return 0;
+ if (device->type() == TI86SERIAL) //TI-86 is compatible with TI-85 file
+ if (strncmp((char *) file_data, (char *) ti86_file_signature, 11) && strncmp((char *) file_data, (char *) ti85_file_signature, 11))
+ return 0;
+
+ //identify the image
+ if (!strncmp((char *) file_data, (char *) ti73_file_signature, 11))
+ {
+ ti85serial->send_id = TI_TRANFER_ID_TI73;
+ ti85serial->image_type = TI_FILE_V2;
+ }
+ else if (!strncmp((char *) file_data, (char *) ti85_file_signature, 11))
+ {
+ ti85serial->send_id = TI_TRANFER_ID_TI85;
+ ti85serial->image_type = TI_FILE_V1;
+ }
+ else if (!strncmp((char *) file_data, (char *) ti82_file_signature, 11))
+ {
+ ti85serial->send_id = TI_TRANFER_ID_TI82;
+ ti85serial->image_type = TI_FILE_V2;
+ }
+ else if (!strncmp((char *) file_data, (char *) ti83_file_signature, 11))
+ {
+ ti85serial->send_id = TI_TRANFER_ID_TI83;
+ ti85serial->image_type = TI_FILE_V2;
+ }
+ else if (!strncmp((char *) file_data, (char *) ti83p_file_signature, 11))
+ {
+ ti85serial->send_id = TI_TRANFER_ID_TI83P;
+ ti85serial->image_type = TI_FILE_V3;
+ }
+ else if (!strncmp((char *) file_data, (char *) ti86_file_signature, 11))
+ {
+ ti85serial->send_id = TI_TRANFER_ID_TI86;
+ ti85serial->image_type = TI_FILE_V1;
+ }
+
+ logerror("Image ID: 0x%02x, version: 0x%02x\n", ti85serial->send_id, ti85serial->image_type);
+
+ /*Serial stream preparing*/
+ serial_data->end = NULL;
+
+ number_of_entries = (file_data[0x3b]==backup_id) ? 3 : ti85_variables_count(file_data, file_size);
+ if (!number_of_entries) return 0;
+
+ serial_data->variables = (ti85_serial_variable*)malloc(sizeof(ti85_serial_variable)*number_of_entries);
+ if (!serial_data->variables) return 0;
+
+ for (i=0; i<number_of_entries; i++)
+ {
+ serial_data->variables[i].header = NULL;
+ serial_data->variables[i].ok = NULL;
+ serial_data->variables[i].data = NULL;
+ }
+
+ serial_data->number_of_variables = number_of_entries;
+
+ ti85_entries = (ti85_entry*) malloc (sizeof(ti85_entry)*number_of_entries);
+ if (!ti85_entries) return 0;
+
+ if (file_data[0x3b]==backup_id)
+ {
+ ti85serial->transfer_type = TI85_SEND_BACKUP;
+ ti85_backup_read (file_data, file_size, ti85_entries);
+ }
+ else
+ {
+ ti85serial->transfer_type = TI85_SEND_VARIABLES;
+ ti85_variables_read (device, file_data, file_size, ti85_entries);
+ }
+ for (i=0; i<number_of_entries; i++)
+ {
+ /*Header packet*/
+ if (file_data[0x3b]==backup_id)
+ {
+ if (!i)
+ {
+ temp_data_to_convert = (UINT8*) malloc (0x0f);
+ if (!temp_data_to_convert)
+ {
+ free (ti85_entries);
+ return 0;
+ }
+ serial_data->variables[i].header = (UINT8*) malloc (0x0f*8);
+
+ if (!serial_data->variables[i].header)
+ {
+ free (ti85_entries);
+ free (temp_data_to_convert);
+ return 0;
+ }
+ serial_data->variables[i].header_size = 0x0f*8;
+ temp_data_to_convert[0] = ti85serial->send_id; //PC sends
+ temp_data_to_convert[1] = 0x06; //header
+ memcpy( temp_data_to_convert+0x02, file_data+0x37, 0x0b);
+ checksum = ti85_calculate_checksum(temp_data_to_convert+4, 0x09);
+ temp_data_to_convert[13] = checksum&0x00ff;
+ temp_data_to_convert[14] = (checksum&0xff00)>>8;
+ ti85_convert_data_to_stream(temp_data_to_convert, 0x0f, serial_data->variables[i].header);
+ free(temp_data_to_convert);
+ }
+ else
+ {
+ serial_data->variables[i].header = NULL;
+ serial_data->variables[i].header_size = 0;
+ }
+ }
+ else
+ {
+ temp_data_to_convert = (UINT8*) malloc (10+ti85_entries[i].name_size);
+ if (!temp_data_to_convert)
+ {
+ free (ti85_entries);
+ return 0;
+ }
+ serial_data->variables[i].header = (UINT8*) malloc ((10+ti85_entries[i].name_size)*8);
+ if (!serial_data->variables[i].header)
+ {
+ free (temp_data_to_convert);
+ free (ti85_entries);
+ return 0;
+ }
+
+ if (ti85serial->image_type == TI_FILE_V1)
+ {
+ serial_data->variables[i].header_size = (10+ti85_entries[i].name_size)*8;
+
+ temp_data_to_convert[0] = ti85serial->send_id;
+ temp_data_to_convert[1] = 0x06; //header
+ temp_data_to_convert[2] = (4+ti85_entries[i].name_size)&0x00ff;
+ temp_data_to_convert[3] = ((4+ti85_entries[i].name_size)&0xff00)>>8;
+ temp_data_to_convert[4] = (ti85_entries[i].data_size)&0x00ff;
+ temp_data_to_convert[5] = ((ti85_entries[i].data_size)&0xff00)>>8;
+ temp_data_to_convert[6] = ti85_entries[i].type;
+ temp_data_to_convert[7] = ti85_entries[i].name_size;
+ memcpy(temp_data_to_convert+8, file_data+ti85_entries[i].offset+0x06, ti85_entries[i].name_size);
+ checksum = ti85_calculate_checksum(temp_data_to_convert+4,ti85_entries[i].name_size+4);
+ temp_data_to_convert[10+ti85_entries[i].name_size-2] = checksum&0x00ff;
+ temp_data_to_convert[10+ti85_entries[i].name_size-1] = (checksum&0xff00)>>8;
+ ti85_convert_data_to_stream(temp_data_to_convert, 10+ti85_entries[i].name_size, serial_data->variables[i].header);
+ }
+
+ if (ti85serial->image_type == TI_FILE_V2 || ti85serial->image_type == TI_FILE_V3)
+ {
+ serial_data->variables[i].header_size = (9+ti85_entries[i].name_size)*8;
+
+ temp_data_to_convert[0] = ti85serial->send_id;
+ temp_data_to_convert[1] = 0x06; //header
+ temp_data_to_convert[2] = (3+ti85_entries[i].name_size)&0x00ff;
+ temp_data_to_convert[3] = ((3+ti85_entries[i].name_size)&0xff00)>>8;
+ temp_data_to_convert[4] = (ti85_entries[i].data_size)&0x00ff;
+ temp_data_to_convert[5] = ((ti85_entries[i].data_size)&0xff00)>>8;
+ temp_data_to_convert[6] = ti85_entries[i].type;
+ memcpy(temp_data_to_convert+7, file_data+ti85_entries[i].offset+0x05, ti85_entries[i].name_size);
+ checksum = ti85_calculate_checksum(temp_data_to_convert+4,ti85_entries[i].name_size+3);
+ temp_data_to_convert[9+ti85_entries[i].name_size-2] = checksum&0x00ff;
+ temp_data_to_convert[9+ti85_entries[i].name_size-1] = (checksum&0xff00)>>8;
+ ti85_convert_data_to_stream(temp_data_to_convert, 9+ti85_entries[i].name_size, serial_data->variables[i].header);
+ }
+
+ free(temp_data_to_convert);
+ }
+
+ /*OK packet*/
+ serial_data->variables[i].ok = (UINT8*) malloc (TI85_PC_OK_PACKET_SIZE*8);
+ if (!serial_data->variables[i].ok)
+ {
+ free (ti85_entries);
+ return 0;
+ }
+ ti85_append_head_to_stream(ti85serial->send_id, TI_OK_PACKET, serial_data->variables[i].ok);
+ serial_data->variables[i].ok_size = TI85_PC_OK_PACKET_SIZE*8;
+
+ /*Data packet*/
+ temp_data_to_convert = (UINT8*) malloc (6+ti85_entries[i].data_size);
+ if (!temp_data_to_convert)
+ {
+ free (ti85_entries);
+ return 0;
+ }
+ serial_data->variables[i].data = (UINT8*) malloc ((6+ti85_entries[i].data_size)*8);
+ if (!serial_data->variables[i].data)
+ {
+ free (temp_data_to_convert);
+ free (ti85_entries);
+ return 0;
+ }
+ serial_data->variables[i].data_size = (6+ti85_entries[i].data_size)*8;
+
+ temp_data_to_convert[0] = ti85serial->send_id;
+ temp_data_to_convert[1] = 0x15; //data
+ temp_data_to_convert[2] = (ti85_entries[i].data_size)&0x00ff;
+ temp_data_to_convert[3] = ((ti85_entries[i].data_size)&0xff00)>>8;
+
+ UINT8 name_start = (ti85serial->image_type != TI_FILE_V1) ? 5 : 6;
+
+ //TI-83+ files have two additional byte used for the file's version and flag
+ if (ti85serial->image_type == TI_FILE_V3)
+ name_start += 2;
+
+ if (file_data[0x3b]==backup_id)
+ memcpy(temp_data_to_convert+4, file_data+ti85_entries[i].offset, ti85_entries[i].data_size);
+ else
+ memcpy(temp_data_to_convert+4, file_data+ti85_entries[i].offset+name_start+ti85_entries[i].name_size+0x02, ti85_entries[i].data_size);
+
+ checksum = ti85_calculate_checksum(temp_data_to_convert+4,ti85_entries[i].data_size);
+ temp_data_to_convert[6+ti85_entries[i].data_size-2] = checksum&0x00ff;
+ temp_data_to_convert[6+ti85_entries[i].data_size-1] = (checksum&0xff00)>>8;
+ ti85_convert_data_to_stream(temp_data_to_convert, 6+ti85_entries[i].data_size, serial_data->variables[i].data);
+ free(temp_data_to_convert);
+ }
+
+
+ /*END packet*/
+ serial_data->end = (UINT8*) malloc (TI85_PC_END_PACKET_SIZE*8);
+ if (!serial_data->end)
+ {
+ free (ti85_entries);
+ return 0;
+ }
+ ti85_append_head_to_stream(ti85serial->send_id, TI_END_PACKET, serial_data->end);
+ serial_data->end_size = TI85_PC_END_PACKET_SIZE*8;
+
+ free (ti85_entries);
+
+ return 1;
+}
+
+
+static void ti85_free_serial_stream (ti85_serial_data* serial_data)
+{
+ UINT16 i;
+ if (serial_data->variables)
+ {
+ for (i=0; i<serial_data->number_of_variables; i++)
+ {
+ if (serial_data->variables[i].header) free (serial_data->variables[i].header);
+ if (serial_data->variables[i].ok) free (serial_data->variables[i].ok);
+ if (serial_data->variables[i].data) free (serial_data->variables[i].data);
+ }
+ free (serial_data->variables);
+ serial_data->variables = NULL;
+ }
+ serial_data->number_of_variables = 0;
+ if (serial_data->end)
+ {
+ free (serial_data->end);
+ serial_data->end = NULL;
+ }
+}
+
+
+static void ti85_send_variables (device_t *device)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ if (!ti85_alloc_serial_data_memory(device, 7))
+ ti85serial->status = TI85_SEND_STOP;
+
+ switch (ti85serial->status)
+ {
+ case TI85_SEND_HEADER:
+ if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->variables_variable_number].header,ti85serial->stream.variables[ti85serial->variables_variable_number].header_size))
+ {
+ ti85serial->status = TI85_RECEIVE_OK_1;
+ memset (ti85serial->receive_data, 0, 7);
+ logerror ("Header sent\n");
+ }
+ break;
+ case TI85_RECEIVE_OK_1:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85serial->status = TI85_RECEIVE_ANSWER_1;
+ logerror ("OK received\n");
+ }
+ break;
+ case TI85_RECEIVE_ANSWER_1:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ switch (ti85serial->receive_data[1])
+ {
+ case 0x09: //continue
+ ti85serial->status = TI85_SEND_OK;
+ logerror ("Continue received\n");
+ break;
+ case 0x36: //out of memory, skip or exit
+ ti85serial->status = TI85_RECEIVE_ANSWER_2;
+ break;
+ }
+ }
+ break;
+ case TI85_RECEIVE_ANSWER_2:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer+4*8, 1*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 5*8, ti85serial->receive_data);
+ switch (ti85serial->receive_data[4])
+ {
+ case 0x01: //exit
+ case 0x02: //skip
+ ti85serial->status = TI85_RECEIVE_ANSWER_3;
+ break;
+ case 0x03: //out of memory
+ ti85serial->variables_variable_number = 0;
+ ti85_free_serial_data_memory(device);
+ ti85serial->status = TI85_SEND_STOP;
+ break;
+ }
+ }
+ break;
+ case TI85_RECEIVE_ANSWER_3:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer+5*8, 2*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 7*8, ti85serial->receive_data);
+ switch (ti85serial->receive_data[4])
+ {
+ case 0x01: //exit
+ ti85serial->variables_variable_number = 0;
+ ti85_free_serial_data_memory(device);
+ ti85serial->status = TI85_SEND_STOP;
+ break;
+ case 0x02: //skip
+ ti85serial->variables_variable_number++;
+ ti85serial->status = TI85_SEND_OK;
+ break;
+ }
+ }
+ break;
+ case TI85_SEND_OK:
+ if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->variables_variable_number].ok,ti85serial->stream.variables[ti85serial->variables_variable_number].ok_size))
+ {
+ ti85serial->status = (ti85serial->receive_data[4]==0x02) ? ((ti85serial->variables_variable_number < ti85serial->stream.number_of_variables) ? TI85_SEND_HEADER : TI85_SEND_END) : TI85_SEND_DATA;
+ memset(ti85serial->receive_data, 0, 7);
+ }
+ break;
+ case TI85_SEND_DATA:
+ if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->variables_variable_number].data,ti85serial->stream.variables[ti85serial->variables_variable_number].data_size))
+ ti85serial->status = TI85_RECEIVE_OK_2;
+ break;
+ case TI85_RECEIVE_OK_2:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85serial->variables_variable_number++;
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85serial->status = (ti85serial->variables_variable_number < ti85serial->stream.number_of_variables) ? TI85_SEND_HEADER : TI85_SEND_END;
+ }
+ break;
+ case TI85_SEND_END:
+ if(!ti85_send_serial(device, ti85serial->stream.end,ti85serial->stream.end_size))
+ {
+ logerror ("End sent\n");
+ ti85serial->variables_variable_number = 0;
+ ti85serial->status = TI85_RECEIVE_OK_3;
+ }
+ break;
+ case TI85_RECEIVE_OK_3:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ logerror ("OK received\n");
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85_free_serial_data_memory(device);
+ ti85serial->status = TI85_SEND_STOP;
+ }
+ break;
+ }
+}
+
+
+static void ti85_send_backup (device_t *device)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ if (!ti85_alloc_serial_data_memory(device, 7))
+ ti85serial->status = TI85_SEND_STOP;
+
+ switch (ti85serial->status)
+ {
+ case TI85_SEND_HEADER:
+ if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->send_backup_variable_number].header,ti85serial->stream.variables[ti85serial->send_backup_variable_number].header_size))
+ ti85serial->status = TI85_RECEIVE_OK_1;
+ break;
+ case TI85_RECEIVE_OK_1:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85serial->status = TI85_RECEIVE_ANSWER_1;
+ }
+ break;
+ case TI85_RECEIVE_ANSWER_1:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ switch (ti85serial->receive_data[1])
+ {
+ case 0x09: //continue
+ ti85serial->status = TI85_SEND_OK;
+ break;
+ case 0x36: //out of memory, skip or exit
+ ti85serial->status = TI85_RECEIVE_ANSWER_2;
+ break;
+ }
+ }
+ break;
+ case TI85_RECEIVE_ANSWER_2:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer+4*8, 3*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 5*8, ti85serial->receive_data);
+ ti85serial->send_backup_variable_number = 0;
+ ti85_free_serial_data_memory(device);
+ ti85serial->status = TI85_SEND_STOP;
+ }
+ break;
+ case TI85_SEND_OK:
+ if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->send_backup_variable_number].ok,ti85serial->stream.variables[ti85serial->send_backup_variable_number].ok_size))
+ ti85serial->status = TI85_SEND_DATA;
+ break;
+ case TI85_SEND_DATA:
+ if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->send_backup_variable_number].data,ti85serial->stream.variables[ti85serial->send_backup_variable_number].data_size))
+ ti85serial->status = TI85_RECEIVE_OK_2;
+ break;
+ case TI85_RECEIVE_OK_2:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85serial->send_backup_variable_number++;
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85serial->status = (ti85serial->send_backup_variable_number < ti85serial->stream.number_of_variables) ? TI85_SEND_DATA : TI85_SEND_END;
+ }
+ break;
+ case TI85_SEND_END:
+ if(!ti85_send_serial(device, ti85serial->stream.end,ti85serial->stream.end_size))
+ {
+ ti85serial->send_backup_variable_number = 0;
+ ti85_free_serial_data_memory(device);
+ ti85serial->status = TI85_SEND_STOP;
+ }
+ break;
+ }
+}
+
+
+static void ti85_receive_variables (device_t *device)
+{
+ ti85serial_state *ti85serial = get_token( device );
+ char var_file_name[16];
+ UINT8* temp;
+ file_error filerr;
+
+ switch (ti85serial->status)
+ {
+ case TI85_RECEIVE_HEADER_1:
+ if(!ti85_receive_serial(device, ti85serial->receive_buffer+4*8, 3*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer+4*8, 3*8, ti85serial->receive_data+4);
+ ti85serial->status = TI85_PREPARE_VARIABLE_DATA;
+ }
+ break;
+ case TI85_PREPARE_VARIABLE_DATA:
+ ti85serial->var_data = (UINT8*) malloc (ti85serial->receive_data[2]+2+ti85serial->receive_data[4]+ti85serial->receive_data[5]*256+2);
+ if(!ti85serial->var_data)
+ ti85serial->status = TI85_SEND_STOP;
+ memcpy (ti85serial->var_data, ti85serial->receive_data+2, 5);
+ ti85_free_serial_data_memory(device);
+ if (!ti85_alloc_serial_data_memory(device, ti85serial->var_data[0]-1))
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_HEADER_2;
+ case TI85_RECEIVE_HEADER_2:
+ if(!ti85_receive_serial(device, ti85serial->receive_buffer, (ti85serial->var_data[0]-1)*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, (ti85serial->var_data[0]-1)*8, ti85serial->receive_data);
+ memcpy (ti85serial->var_data+5, ti85serial->receive_data, ti85serial->var_data[0]-3);
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 8))
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_CONTINUE_PACKET, ti85serial->receive_buffer+4*8);
+ ti85serial->status = TI85_SEND_OK_1;
+ }
+ break;
+ case TI85_SEND_OK_1:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
+ ti85serial->status = TI85_SEND_CONTINUE;
+ break;
+ case TI85_SEND_CONTINUE:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer+4*8, 4*8))
+ {
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory(device, 4))
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_OK;
+ }
+ break;
+ case TI85_RECEIVE_OK:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory(device, ti85serial->var_data[2]+ti85serial->var_data[3]*256+6))
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_DATA;
+ }
+ break;
+ case TI85_RECEIVE_DATA:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, (ti85serial->var_data[2]+ti85serial->var_data[3]*256+6)*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, (ti85serial->var_data[2]+ti85serial->var_data[3]*256+6)*8, ti85serial->receive_data);
+ memcpy (ti85serial->var_data+ti85serial->var_data[0]+2, ti85serial->receive_data+2, ti85serial->var_data[2]+ti85serial->var_data[3]*256+2);
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 4))
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
+ ti85serial->status = TI85_SEND_OK_2;
+ }
+ break;
+ case TI85_SEND_OK_2:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory(device, 7))
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_END_OR_HEADER_1;
+ }
+ break;
+ case TI85_RECEIVE_END_OR_HEADER_1:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ if (ti85serial->variable_number == 0)
+ {
+ ti85serial->var_file_data = (UINT8*) malloc (0x39);
+ if (!ti85serial->var_file_data)
+ {
+ free (ti85serial->var_data); ti85serial->var_data = NULL;
+ free (ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ }
+ else
+ {
+ memcpy(ti85serial->var_file_data, ti85_file_signature, 0x0b);
+ memcpy(ti85serial->var_file_data+0x0b, "File created by MESS", 0x14);
+ memset(ti85serial->var_file_data+0x1f, 0, 0x1a);
+ ti85serial->var_file_size = 0x39;
+ }
+ }
+ temp = (UINT8*)malloc (ti85serial->var_file_size+ti85serial->var_data[0]+2+ti85serial->var_data[2]+ti85serial->var_data[3]*256+2);
+ if (temp)
+ {
+ memcpy (temp, ti85serial->var_file_data, ti85serial->var_file_size);
+ free (ti85serial->var_file_data);
+ ti85serial->var_file_data = temp;
+ memcpy (ti85serial->var_file_data + ti85serial->var_file_size -2, ti85serial->var_data, ti85serial->var_data[0]+2+ti85serial->var_data[2]+ti85serial->var_data[3]*256+2);
+ ti85serial->var_file_size += ti85serial->var_data[0]+2+ti85serial->var_data[2]+ti85serial->var_data[3]*256+2;
+ ti85serial->var_file_data[0x35] = (ti85serial->var_file_size-0x39)&0x00ff;
+ ti85serial->var_file_data[0x36] = ((ti85serial->var_file_size-0x39)&0xff00)>>8;
+ ti85serial->var_file_data[ti85serial->var_file_size-2] = ti85_calculate_checksum(ti85serial->var_file_data+0x37, ti85serial->var_file_size-0x39)&0x00ff;
+ ti85serial->var_file_data[ti85serial->var_file_size-1] = (ti85_calculate_checksum(ti85serial->var_file_data+0x37, ti85serial->var_file_size-0x39)&0xff00)>>8;
+ }
+ free (ti85serial->var_data);
+ ti85serial->var_data = NULL;
+ ti85serial->variable_number ++;
+
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ if (ti85serial->receive_data[1] == 0x06)
+ ti85serial->status = TI85_RECEIVE_HEADER_1;
+ else
+ {
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 4))
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
+ ti85serial->status = TI85_SEND_OK_3;
+ }
+ }
+ break;
+ case TI85_SEND_OK_3:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_free_serial_data_memory(device);
+ ti85serial->variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+ sprintf (var_file_name, "%08d.85g", ti85serial->var_file_number);
+ emu_file var_file(device->machine().options().memcard_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ filerr = var_file.open(var_file_name);
+
+ if (filerr == FILERR_NONE)
+ {
+ var_file.write(ti85serial->var_file_data, ti85serial->var_file_size);
+ free (ti85serial->var_file_data);
+ ti85serial->var_file_data = NULL;
+ ti85serial->var_file_size = 0;
+ ti85serial->var_file_number++;
+ }
+ }
+ break;
+ }
+}
+
+
+static void ti85_receive_backup (device_t *device)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ file_error filerr;
+ char backup_file_name[] = "00000000.85b";
+
+ switch (ti85serial->status)
+ {
+ case TI85_RECEIVE_HEADER_2:
+ if(!ti85_receive_serial(device, ti85serial->receive_buffer+7*8, 8*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer+7*8, 8*8, ti85serial->receive_data+7);
+ ti85serial->backup_data_size[0] = ti85serial->receive_data[4] + ti85serial->receive_data[5]*256;
+ ti85serial->backup_data_size[1] = ti85serial->receive_data[7] + ti85serial->receive_data[8]*256;
+ ti85serial->backup_data_size[2] = ti85serial->receive_data[9] + ti85serial->receive_data[10]*256;
+ ti85serial->backup_file_data = (UINT8*)malloc (0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x02);
+ if(!ti85serial->backup_file_data)
+ {
+ ti85serial->backup_variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ memcpy(ti85serial->backup_file_data, ti85_file_signature, 0x0b);
+ memcpy(ti85serial->backup_file_data+0x0b, "File created by MESS", 0x14);
+ memset(ti85serial->backup_file_data+0x1f, 0, 0x16);
+ ti85serial->backup_file_data[0x35] = (ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x11)&0x00ff;
+ ti85serial->backup_file_data[0x36] = ((ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x11)&0xff00)>>8;
+ memcpy(ti85serial->backup_file_data+0x37, ti85serial->receive_data+0x02, 0x0b);
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 8))
+ {
+ free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
+ ti85serial->backup_variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_CONTINUE_PACKET, ti85serial->receive_buffer+4*8);
+ ti85serial->status = TI85_SEND_OK_1;
+ }
+ break;
+ case TI85_SEND_OK_1:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
+ ti85serial->status = TI85_SEND_CONTINUE;
+ break;
+ case TI85_SEND_CONTINUE:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer+4*8, 4*8))
+ {
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory(device, 4))
+ {
+ free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
+ ti85serial->backup_variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_OK;
+ }
+ break;
+ case TI85_RECEIVE_OK:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory(device, ti85serial->backup_data_size[ti85serial->backup_variable_number]+6))
+ {
+ free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
+ ti85serial->backup_variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_DATA;
+ }
+ break;
+ case TI85_RECEIVE_DATA:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, (ti85serial->backup_data_size[ti85serial->backup_variable_number]+6)*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, (ti85serial->backup_data_size[ti85serial->backup_variable_number]+6)*8, ti85serial->receive_data);
+ switch (ti85serial->backup_variable_number)
+ {
+ case 0:
+ memcpy(ti85serial->backup_file_data+0x42, ti85serial->receive_data+0x02, ti85serial->backup_data_size[0]+0x02);
+ break;
+ case 1:
+ memcpy(ti85serial->backup_file_data+0x42+ti85serial->backup_data_size[0]+0x02, ti85serial->receive_data+0x02, ti85serial->backup_data_size[1]+0x02);
+ break;
+ case 2:
+ memcpy(ti85serial->backup_file_data+0x42+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+0x04, ti85serial->receive_data+0x02, ti85serial->backup_data_size[2]+0x02);
+ break;
+ }
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 4))
+ {
+ free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
+ ti85serial->backup_variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
+ ti85serial->status = TI85_SEND_OK_2;
+ }
+ break;
+ case TI85_SEND_OK_2:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_free_serial_data_memory(device);
+ ti85serial->backup_variable_number++;
+ if (ti85serial->backup_variable_number<3)
+ {
+ if(!ti85_alloc_serial_data_memory(device, ti85serial->backup_data_size[ti85serial->backup_variable_number]+6))
+ {
+ free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
+ ti85serial->backup_variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_DATA;
+ }
+ else
+ {
+ ti85serial->backup_variable_number = 0;
+ ti85serial->backup_file_data[0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]] = ti85_calculate_checksum(ti85serial->backup_file_data+0x37, 0x42+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x06-0x37)&0x00ff;
+ ti85serial->backup_file_data[0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x01] = (ti85_calculate_checksum(ti85serial->backup_file_data+0x37, 0x42+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x06-0x37)&0xff00)>>8;
+ sprintf (backup_file_name, "%08d.85b", ti85serial->backup_file_number);
+
+ emu_file backup_file(device->machine().options().memcard_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ filerr = backup_file.open(backup_file_name);
+
+ if (filerr == FILERR_NONE)
+ {
+ backup_file.write(ti85serial->backup_file_data, 0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x02);
+ ti85serial->backup_file_number++;
+ }
+ free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
+ ti85serial->status = TI85_SEND_STOP;
+ }
+ }
+ break;
+ }
+}
+
+static void ti85_receive_screen (device_t *device)
+{
+ ti85serial_state *ti85serial = get_token( device );
+ char image_file_name[] = "00000000.85i";
+ file_error filerr;
+ UINT8 * image_file_data;
+
+ switch (ti85serial->status)
+ {
+ case TI85_PREPARE_SCREEN_REQUEST:
+ if(!ti85_alloc_serial_data_memory (device, 4))
+ {
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_SCREEN_REQUEST_PACKET, ti85serial->receive_buffer);
+ ti85serial->status = TI85_SEND_SCREEN_REQUEST;
+ break;
+ case TI85_SEND_SCREEN_REQUEST:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 4))
+ {
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_OK;
+ }
+ break;
+ case TI85_RECEIVE_OK:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 1030))
+ {
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85serial->status = TI85_RECEIVE_DATA;
+ }
+ break;
+ case TI85_RECEIVE_DATA:
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 1030*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 1030*8, ti85serial->receive_data);
+ sprintf (image_file_name, "%08d.85i", ti85serial->image_file_number);
+
+ emu_file image_file(device->machine().options().memcard_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ filerr = image_file.open(image_file_name);
+
+ if (filerr == FILERR_NONE)
+ {
+ image_file_data = (UINT8*)malloc (0x49+1008);
+ if(!image_file_data)
+ {
+ ti85_free_serial_data_memory(device);
+ ti85serial->status = TI85_SEND_OK;
+ return;
+ }
+ memcpy(image_file_data, ti85_file_signature, 0x0b);
+ memcpy(image_file_data+0x0b, "File created by MESS", 0x14);
+ memset(image_file_data+0x1f, 0, 0x16);
+ image_file_data[0x35] = 0x00;
+ image_file_data[0x36] = 0x04;
+ image_file_data[0x37] = 0x0a; //header size
+ image_file_data[0x38] = 0x00;
+ image_file_data[0x39] = 0xf2; //data size
+ image_file_data[0x3a] = 0x03;
+ image_file_data[0x3b] = 0x11; //data type
+ image_file_data[0x3c] = 0x06; //name size
+ memcpy(image_file_data+0x3d, "Screen", 0x06);
+ image_file_data[0x43] = 0xf2;
+ image_file_data[0x44] = 0x03;
+ image_file_data[0x45] = 0xf0;
+ image_file_data[0x46] = 0x03;
+ memcpy(image_file_data+0x47, ti85serial->receive_data+4, 1008);
+ image_file_data[1008+0x49-2] = ti85_calculate_checksum(image_file_data+0x37, 1008+0x10)&0x00ff;
+ image_file_data[1008+0x49-1] = (ti85_calculate_checksum(image_file_data+0x37, 1008+0x10)&0xff00)>>8;
+ image_file.write(image_file_data, 1008+0x49);
+ free(image_file_data);
+ ti85serial->image_file_number++;
+ }
+ ti85_free_serial_data_memory(device);
+ if(!ti85_alloc_serial_data_memory (device, 4))
+ {
+ ti85serial->status = TI85_SEND_STOP;
+ return;
+ }
+ ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
+ ti85serial->status = TI85_SEND_OK;
+ }
+ break;
+ case TI85_SEND_OK:
+ if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
+ {
+ ti85_free_serial_data_memory(device);
+ ti85serial->status = TI85_SEND_STOP;
+ }
+ break;
+ }
+}
+
+
+void ti85_update_serial (device_t *device)
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ if (ti85serial->status == TI85_SEND_STOP)
+ {
+ if (input_port_read(*device, "SERIAL") & 0x01)
+ {
+ if(!ti85_alloc_serial_data_memory(device, 15)) return;
+ if(!ti85_receive_serial (device, ti85serial->receive_buffer, 7*8))
+ {
+ ti85_convert_stream_to_data (ti85serial->receive_buffer, 7*8, ti85serial->receive_data);
+ if (ti85serial->receive_data[0]!=0x85 || ti85serial->receive_data[1]!=0x06)
+ {
+ ti85_receive_serial (device, NULL, 0);
+ return;
+ }
+ ti85serial->transfer_type = (ti85serial->receive_data[6]==0x1d) ? TI85_RECEIVE_BACKUP : TI85_RECEIVE_VARIABLES;
+ ti85serial->status = (ti85serial->receive_data[6]==0x1d) ? TI85_RECEIVE_HEADER_2 : TI85_PREPARE_VARIABLE_DATA;
+ }
+ }
+ else
+ {
+ ti85_receive_serial(device, NULL, 0);
+ ti85_free_serial_data_memory(device);
+ if (input_port_read(*device, "DUMP") & 0x01)
+ {
+ ti85serial->status = TI85_PREPARE_SCREEN_REQUEST;
+ ti85serial->transfer_type = TI85_RECEIVE_SCREEN;
+ }
+ return;
+ }
+ }
+
+ switch (ti85serial->transfer_type)
+ {
+ case TI85_SEND_VARIABLES:
+ ti85_send_variables(device);
+ break;
+ case TI85_SEND_BACKUP:
+ ti85_send_backup(device);
+ break;
+ case TI85_RECEIVE_BACKUP:
+ ti85_receive_backup(device);
+ break;
+ case TI85_RECEIVE_VARIABLES:
+ ti85_receive_variables(device);
+ break;
+ case TI85_RECEIVE_SCREEN:
+ ti85_receive_screen(device);
+ break;
+ }
+}
+
+
+WRITE8_DEVICE_HANDLER( ti85serial_red_out )
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ ti85serial->red_out = data;
+}
+
+
+WRITE8_DEVICE_HANDLER( ti85serial_white_out )
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ ti85serial->white_out = data;
+}
+
+
+READ8_DEVICE_HANDLER( ti85serial_red_in )
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ return ti85serial->red_in;
+}
+
+
+READ8_DEVICE_HANDLER( ti85serial_white_in )
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ return ti85serial->white_in;
+}
+
+
+static DEVICE_START( ti85serial )
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ ti85serial->transfer_type = TI85_SEND_VARIABLES;
+ ti85serial->receive_buffer = NULL;
+ ti85serial->receive_data = NULL;
+ ti85serial->var_file_number = 0;
+ ti85serial->backup_file_number = 0;
+ ti85serial->image_file_number = 0;
+}
+
+
+static DEVICE_STOP( ti85serial )
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ ti85_free_serial_data_memory(device);
+ if (ti85serial->var_data)
+ {
+ free(ti85serial->var_data); ti85serial->var_data = NULL;
+ }
+ if (ti85serial->var_file_data)
+ {
+ free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
+ }
+ if (ti85serial->backup_file_data)
+ {
+ free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
+ }
+}
+
+
+static DEVICE_RESET( ti85serial )
+{
+ ti85serial_state *ti85serial = get_token( device );
+
+ ti85serial->receive_data_counter = 0;
+ ti85serial->send_data_counter = 0;
+ ti85_free_serial_data_memory(device);
+ ti85serial->red_in = 0;
+ ti85serial->white_in = 0;
+ ti85serial->red_out = 1;
+ ti85serial->white_out = 1;
+ ti85serial->variables_variable_number = 0;
+ ti85serial->send_backup_variable_number = 0;
+ ti85serial->var_data = NULL;
+ ti85serial->var_file_data = NULL;
+ ti85serial->var_file_size = 0;
+ ti85serial->variable_number = 0;
+ ti85serial->backup_file_data = NULL;
+ ti85serial->backup_variable_number = 0;
+ ti85serial->status = TI85_SEND_STOP;
+
+ //initialize the receive_id used for TI to PC transfer
+ if (device->type() == TI73SERIAL)
+ ti85serial->receive_id = TI_TRANFER_ID_TI73;
+ else if (device->type() == TI85SERIAL)
+ ti85serial->receive_id = TI_TRANFER_ID_TI85;
+ else if (device->type() == TI82SERIAL)
+ ti85serial->receive_id = TI_TRANFER_ID_TI82;
+ else if (device->type() == TI83PSERIAL)
+ ti85serial->receive_id = TI_TRANFER_ID_TI83P;
+ else if (device->type() == TI86SERIAL)
+ ti85serial->receive_id = TI_TRANFER_ID_TI86;
+
+ ti85serial->send_id = ti85serial->receive_id;
+}
+
+
+static DEVICE_IMAGE_LOAD( ti85serial )
+{
+ ti85serial_state *ti85serial = get_token( image );
+ UINT8* file_data;
+ UINT16 file_size;
+
+ if (ti85serial->status != TI85_SEND_STOP) return IMAGE_INIT_FAIL;
+
+ file_size = image.length();
+
+ if (file_size != 0)
+ {
+ file_data = auto_alloc_array(image.device().machine(), UINT8, file_size);
+ image.fread( file_data, file_size);
+
+ if(!ti85_convert_file_data_to_serial_stream(image, file_data, file_size, &ti85serial->stream))
+ {
+ ti85_free_serial_stream (&ti85serial->stream);
+ return IMAGE_INIT_FAIL;
+ }
+
+ ti85serial->status = TI85_SEND_HEADER;
+ }
+ else
+ {
+ return IMAGE_INIT_FAIL;
+ }
+ return IMAGE_INIT_PASS;
+}
+
+
+static DEVICE_IMAGE_UNLOAD( ti85serial )
+{
+ ti85serial_state *ti85serial = get_token( image );
+
+ ti85_free_serial_data_memory(image);
+ ti85serial->status = TI85_SEND_STOP;
+ ti85_free_serial_stream (&ti85serial->stream);
+}
+
+
+static INPUT_PORTS_START ( ti85serial )
+ PORT_START("SERIAL") /* receive data from calculator */
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Receive data") PORT_CODE(KEYCODE_R)
+ PORT_START("DUMP") /* screen dump requesting */
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Screen dump request") PORT_CODE(KEYCODE_S)
+INPUT_PORTS_END
+
+
+DEVICE_GET_INFO( ti85serial )
+{
+ switch ( state )
+ {
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof( ti85serial_state ); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_TYPE: info->i = IO_SERIAL; break;
+ case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ti85serial ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ti85serial ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ti85serial ); break;
+ case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( ti85serial ); break;
+ case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME( ti85serial ); break;
+ case DEVINFO_PTR_INPUT_PORTS: info->ipt = INPUT_PORTS_NAME( ti85serial ); break;
+ case DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME: strcpy(info->s, "ser"); break;
+ case DEVINFO_STR_IMAGE_INSTANCE_NAME: strcpy(info->s, "serial"); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "TI85 Serial"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "serial protocol"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "85p,85s,85i,85n,85c,85l,85k,85m,85v,85d,85e,85r,85g,85b"); break;
+ }
+}
+
+DEVICE_GET_INFO( ti73serial )
+{
+ switch ( state )
+ {
+ case DEVINFO_STR_NAME: strcpy(info->s, "TI73 Serial"); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "73p,73s,73i,73n,73c,73l,73k,73m,73v,73d,73e,73r,73g"); break;
+ default: DEVICE_GET_INFO_CALL( ti85serial );
+ }
+}
+
+DEVICE_GET_INFO( ti82serial )
+{
+ switch ( state )
+ {
+ case DEVINFO_STR_NAME: strcpy(info->s, "TI82 Serial"); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "82p,82s,82i,82n,82c,82l,82k,82m,82v,82d,82e,82r,82g"); break;
+ default: DEVICE_GET_INFO_CALL( ti85serial );
+ }
+}
+
+
+DEVICE_GET_INFO( ti83pserial )
+{
+ switch ( state )
+ {
+ case DEVINFO_STR_NAME: strcpy(info->s, "TI83 Plus Serial"); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "82p,82s,82i,82n,82c,82l,82k,82m,82v,82d,82e,82r,82g," //for TI-82 compatibility
+ "83p,83s,83i,83n,83c,83l,83k,83m,83v,83d,83e,83r,83g," //for TI-83 compatibility
+ "8xc,8xd,8xg,8xi,8xl,8xm,8xn,8xp,8xs,8xt,8xv,8xw,8xy,8xz"); break;
+ default: DEVICE_GET_INFO_CALL( ti85serial );
+ }
+}
+
+DEVICE_GET_INFO( ti86serial )
+{
+ switch ( state )
+ {
+ case DEVINFO_STR_NAME: strcpy(info->s, "TI86 Serial"); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "85p,85s,85i,85n,85c,85l,85k,85m,85v,85d,85e,85r,85g,85b" //for TI-85 compatibility
+ "86p,86s,86i,86n,86c,86l,86k,86m,86v,86d,86e,86r,86g"); break;
+ default: DEVICE_GET_INFO_CALL( ti85serial );
+ }
+}
+
+DEFINE_LEGACY_IMAGE_DEVICE(TI85SERIAL, ti85serial);
+DEFINE_LEGACY_IMAGE_DEVICE(TI73SERIAL, ti73serial);
+DEFINE_LEGACY_IMAGE_DEVICE(TI82SERIAL, ti82serial);
+DEFINE_LEGACY_IMAGE_DEVICE(TI83PSERIAL, ti83pserial);
+DEFINE_LEGACY_IMAGE_DEVICE(TI86SERIAL, ti86serial);