summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/formats/m65_snqk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/formats/m65_snqk.c')
-rw-r--r--src/mess/formats/m65_snqk.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/src/mess/formats/m65_snqk.c b/src/mess/formats/m65_snqk.c
new file mode 100644
index 00000000000..4a48588802e
--- /dev/null
+++ b/src/mess/formats/m65_snqk.c
@@ -0,0 +1,374 @@
+/******************************************************************************
+ * Microtan 65
+ *
+ * Snapshot and quickload formats
+ *
+ * Juergen Buchmueller <pullmoll@t-online.de>, Jul 2000
+ *
+ * Thanks go to Geoff Macdonald <mail@geoff.org.uk>
+ * for his site http:://www.geo255.redhotant.com
+ * and to Fabrice Frances <frances@ensica.fr>
+ * for his site http://www.ifrance.com/oric/microtan.html
+ *
+ *****************************************************************************/
+#include "emu.h"
+#include "cpu/m6502/m6502.h"
+#include "includes/microtan.h"
+#include "machine/6522via.h"
+#include "machine/6551acia.h"
+#include "sound/ay8910.h"
+#include "formats/m65_snqk.h"
+
+static int microtan_verify_snapshot(UINT8 *data, int size)
+{
+ if (size == 8263)
+ {
+ logerror("microtan_snapshot_id: magic size %d found\n", size);
+ return IMAGE_VERIFY_PASS;
+ }
+ else
+ {
+ if (4 + data[2] + 256 * data[3] + 1 + 16 + 16 + 16 + 1 + 1 + 16 + 16 + 64 + 7 == size)
+ {
+ logerror("microtan_snapshot_id: header RAM size + structures matches filesize %d\n", size);
+ return IMAGE_VERIFY_PASS;
+ }
+ }
+
+ return IMAGE_VERIFY_FAIL;
+}
+
+static int parse_intel_hex(UINT8 *snapshot_buff, char *src)
+{
+ char line[128];
+ int /*row = 0,*/ column = 0, last_addr = 0, last_size = 0;
+
+ while (*src)
+ {
+ if (*src == '\r' || *src == '\n')
+ {
+ if (column)
+ {
+ unsigned int size, addr, null, b[32], cs, n;
+
+ line[column] = '\0';
+ /*row++;*/
+ n = sscanf(line, ":%02x%04x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ &size, &addr, &null,
+ &b[ 0], &b[ 1], &b[ 2], &b[ 3], &b[ 4], &b[ 5], &b[ 6], &b[ 7],
+ &b[ 8], &b[ 9], &b[10], &b[11], &b[12], &b[13], &b[14], &b[15],
+ &b[16], &b[17], &b[18], &b[19], &b[20], &b[21], &b[22], &b[23],
+ &b[24], &b[25], &b[26], &b[27], &b[28], &b[29], &b[30], &b[31],
+ &cs);
+ if (n == 0)
+ {
+ logerror("parse_intel_hex: malformed line [%s]\n", line);
+ }
+ else if (n == 1)
+ {
+ logerror("parse_intel_hex: only size found [%s]\n", line);
+ }
+ else if (n == 2)
+ {
+ logerror("parse_intel_hex: only size and addr found [%s]\n", line);
+ }
+ else if (n == 3)
+ {
+ logerror("parse_intel_hex: only size, addr and null found [%s]\n", line);
+ }
+ else
+ if (null != 0)
+ {
+ logerror("parse_intel_hex: warning null byte is != 0 [%s]\n", line);
+ }
+ else
+ {
+ int i, sum;
+
+ n -= 3;
+
+ sum = size + (addr & 0xff) + ((addr >> 8) & 0xff);
+ if (n != 32 + 1)
+ cs = b[n-1];
+
+ last_addr = addr;
+ last_size = n-1;
+ logerror("parse_intel_hex: %04X", addr);
+ for (i = 0; i < n-1; i++)
+ {
+ sum += b[i];
+ snapshot_buff[addr++] = b[i];
+ }
+ logerror("-%04X checksum %02X+%02X = %02X\n", addr-1, cs, sum & 0xff, (cs + sum) & 0xff);
+ }
+ }
+ column = 0;
+ }
+ else
+ {
+ line[column++] = *src;
+ }
+ src++;
+ }
+ /* register preset? */
+ if (last_size == 7)
+ {
+ logerror("parse_intel_hex: registers (?) at %04X\n", last_addr);
+ memcpy(&snapshot_buff[8192+64], &snapshot_buff[last_addr], last_size);
+ }
+ return IMAGE_INIT_PASS;
+}
+
+static int parse_zillion_hex(UINT8 *snapshot_buff, char *src)
+{
+ char line[128];
+ int parsing = 0, /*row = 0,*/ column = 0;
+
+ while (*src)
+ {
+ if (parsing)
+ {
+ if (*src == '}')
+ parsing = 0;
+ else
+ {
+ if (*src == '\r' || *src == '\n')
+ {
+ if (column)
+ {
+ unsigned int addr, b[8], n;
+
+ line[column] = '\0';
+ /*row++;*/
+ n = sscanf(line, "%x %x %x %x %x %x %x %x %x", &addr, &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], &b[6], &b[7]);
+ if (n == 0)
+ {
+ logerror("parse_zillion_hex: malformed line [%s]\n", line);
+ }
+ else if (n == 1)
+ {
+ logerror("parse_zillion_hex: only addr found [%s]\n", line);
+ }
+ else
+ {
+ int i;
+
+ logerror("parse_zillion_hex: %04X", addr);
+ for (i = 0; i < n-1; i++)
+ snapshot_buff[addr++] = b[i];
+ logerror("-%04X\n", addr-1);
+ }
+ }
+ column = 0;
+ }
+ else
+ {
+ line[column++] = *src;
+ }
+ }
+ }
+ else
+ {
+ if (*src == '\r' || *src == '\n')
+ {
+ if (column)
+ {
+ int addr, n;
+
+ /*row++;*/
+ line[column] = '\0';
+ n = sscanf(line, "G%x", (unsigned int *) &addr);
+ if (n == 1 && !snapshot_buff[8192+64+0] && !snapshot_buff[8192+64+1])
+ {
+ logerror("microtan_hexfile_init: go addr %04X\n", addr);
+ snapshot_buff[8192+64+0] = addr & 0xff;
+ snapshot_buff[8192+64+1] = (addr >> 8) & 0xff;
+ }
+ }
+ column = 0;
+ }
+ else
+ {
+ line[column++] = *src;
+ }
+ if (*src == '{')
+ {
+ parsing = 1;
+ column = 0;
+ }
+ }
+ src++;
+ }
+ return IMAGE_INIT_PASS;
+}
+
+static void microtan_set_cpu_regs(running_machine &machine,const UINT8 *snapshot_buff, int base)
+{
+ logerror("microtan_snapshot_copy: PC:%02X%02X P:%02X A:%02X X:%02X Y:%02X SP:1%02X",
+ snapshot_buff[base+1], snapshot_buff[base+0], snapshot_buff[base+2], snapshot_buff[base+3],
+ snapshot_buff[base+4], snapshot_buff[base+5], snapshot_buff[base+6]);
+ cpu_set_reg(machine.device("maincpu"), M6502_PC, snapshot_buff[base+0] + 256 * snapshot_buff[base+1]);
+ cpu_set_reg(machine.device("maincpu"), M6502_P, snapshot_buff[base+2]);
+ cpu_set_reg(machine.device("maincpu"), M6502_A, snapshot_buff[base+3]);
+ cpu_set_reg(machine.device("maincpu"), M6502_X, snapshot_buff[base+4]);
+ cpu_set_reg(machine.device("maincpu"), M6502_Y, snapshot_buff[base+5]);
+ cpu_set_reg(machine.device("maincpu"), M6502_S, snapshot_buff[base+6]);
+}
+
+static void microtan_snapshot_copy(running_machine &machine, UINT8 *snapshot_buff, int snapshot_size)
+{
+ microtan_state *state = machine.driver_data<microtan_state>();
+ UINT8 *RAM = state->memregion("maincpu")->base();
+ address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
+ via6522_device *via_0 = machine.device<via6522_device>("via6522_0");
+ via6522_device *via_1 = machine.device<via6522_device>("via6522_1");
+ device_t *ay8910 = machine.device("ay8910.1");
+
+ /* check for .DMP file format */
+ if (snapshot_size == 8263)
+ {
+ int i, base;
+ /********** DMP format
+ * Lower 8k of RAM (0000 to 1fff)
+ * 64 bytes of chunky graphics bits (first byte bit is for character at 0200, bit 1=0201, etc)
+ * 7 bytes of CPU registers (PCL, PCH, PSW, A, IX, IY, SP)
+ */
+ logerror("microtan_snapshot_copy: magic size %d found, assuming *.DMP format\n", snapshot_size);
+
+ base = 0;
+ /* 8K of RAM from 0000 to 1fff */
+ memcpy(RAM, &snapshot_buff[base], 8192);
+ base += 8192;
+ /* 64 bytes of chunky graphics info */
+ for (i = 0; i < 32*16; i++)
+ {
+ state->m_chunky_buffer[i] = (snapshot_buff[base+i/8] >> (i&7)) & 1;
+ }
+ base += 64;
+ microtan_set_cpu_regs(machine, snapshot_buff, base);
+ }
+ else
+ {
+ int i, ramend, base;
+ /********** M65 format ************************************
+ * 2 bytes: File version
+ * 2 bytes: RAM size
+ * n bytes: RAM (0000 to RAM Size)
+ * 16 bytes: 1st 6522 (0xbfc0 to 0xbfcf)
+ * 16 bytes: 2ns 6522 (0xbfe0 to 0xbfef)
+ * 16 bytes: Microtan IO (0xbff0 to 0xbfff)
+ * 1 byte : Invaders sound (0xbc04)
+ * 1 byte : Chunky graphics state (0=off, 1=on)
+ * 16 bytes: 1st AY8910 registers
+ * 16 bytes: 2nd AY8910 registers
+ * 64 bytes: Chunky graphics bits (first byte bit 0 is for character at 0200, bit 1=0201, etc)
+ * 7 bytes: CPU registers (PCL, PCH, PSW, A, IX, IY, SP)
+ */
+ ramend = snapshot_buff[2] + 256 * snapshot_buff[3];
+ if (2 + 2 + ramend + 1 + 16 + 16 + 16 + 1 + 1 + 16 + 16 + 64 + 7 != snapshot_size)
+ {
+ logerror("microtan_snapshot_copy: size %d doesn't match RAM size %d + structure size\n", snapshot_size, ramend+1);
+ return;
+ }
+
+ logerror("microtan_snapshot_copy: size %d found, assuming *.M65 format\n", snapshot_size);
+ base = 4;
+ memcpy(RAM, &snapshot_buff[base], snapshot_buff[2] + 256 * snapshot_buff[3] + 1);
+ base += ramend + 1;
+
+ /* first set of VIA6522 registers */
+ for (i = 0; i < 16; i++ )
+ via_0->write(*space, i, snapshot_buff[base++]);
+
+ /* second set of VIA6522 registers */
+ for (i = 0; i < 16; i++ )
+ via_1->write(*space, i, snapshot_buff[base++]);
+
+ /* microtan IO bff0-bfff */
+ for (i = 0; i < 16; i++ )
+ {
+ RAM[0xbff0+i] = snapshot_buff[base++];
+ if (i < 4)
+ state->microtan_bffx_w(*space, i, RAM[0xbff0+i]);
+ }
+
+ state->microtan_sound_w(*space, 0, snapshot_buff[base++]);
+ state->m_chunky_graphics = snapshot_buff[base++];
+
+ /* first set of AY8910 registers */
+ for (i = 0; i < 16; i++ )
+ {
+ ay8910_address_w(ay8910, 0, i);
+ ay8910_data_w(ay8910, 0, snapshot_buff[base++]);
+ }
+
+ /* second set of AY8910 registers */
+ for (i = 0; i < 16; i++ )
+ {
+ ay8910_address_w(ay8910, 0, i);
+ ay8910_data_w(ay8910, 0, snapshot_buff[base++]);
+ }
+
+ for (i = 0; i < 32*16; i++)
+ {
+ state->m_chunky_buffer[i] = (snapshot_buff[base+i/8] >> (i&7)) & 1;
+ }
+ base += 64;
+
+ microtan_set_cpu_regs(machine, snapshot_buff, base);
+ }
+}
+
+SNAPSHOT_LOAD( microtan )
+{
+ UINT8 *snapshot_buff;
+
+ snapshot_buff = (UINT8*)image.ptr();
+ if (!snapshot_buff)
+ return IMAGE_INIT_FAIL;
+
+ if (microtan_verify_snapshot(snapshot_buff, snapshot_size)==IMAGE_VERIFY_FAIL)
+ return IMAGE_INIT_FAIL;
+
+ microtan_snapshot_copy(image.device().machine(), snapshot_buff, snapshot_size);
+ return IMAGE_INIT_PASS;
+}
+
+QUICKLOAD_LOAD( microtan )
+{
+ int snapshot_size;
+ UINT8 *snapshot_buff;
+ char *buff;
+ int rc;
+
+ snapshot_size = 8263; /* magic size */
+ snapshot_buff = (UINT8*)malloc(snapshot_size);
+ if (!snapshot_buff)
+ {
+ logerror("microtan_hexfile_load: could not allocate %d bytes of buffer\n", snapshot_size);
+ return IMAGE_INIT_FAIL;
+ }
+ memset(snapshot_buff, 0, snapshot_size);
+
+ buff = (char*)malloc(quickload_size + 1);
+ if (!buff)
+ {
+ free(snapshot_buff);
+ logerror("microtan_hexfile_load: could not allocate %d bytes of buffer\n", quickload_size);
+ return IMAGE_INIT_FAIL;
+ }
+ image.fread( buff, quickload_size);
+
+ buff[quickload_size] = '\0';
+
+ if (buff[0] == ':')
+ rc = parse_intel_hex(snapshot_buff, buff);
+ else
+ rc = parse_zillion_hex(snapshot_buff, buff);
+ if (rc == IMAGE_INIT_PASS)
+ microtan_snapshot_copy(image.device().machine(), snapshot_buff, snapshot_size);
+ free(snapshot_buff);
+ return rc;
+}
+
+