OSDN Git Service

client 0.5.3 release
authornaruko <naruko@24ea1065-a21e-4ca1-99c9-f5125deb0858>
Sat, 10 Jan 2009 19:23:30 +0000 (19:23 +0000)
committernaruko <naruko@24ea1065-a21e-4ca1-99c9-f5125deb0858>
Sat, 10 Jan 2009 19:23:30 +0000 (19:23 +0000)
git-svn-id: svn+ssh://svn.osdn.net/svnroot/unagi@250 24ea1065-a21e-4ca1-99c9-f5125deb0858

39 files changed:
client/tag/0.5.3/Makefile [new file with mode: 0644]
client/tag/0.5.3/client_test.h [new file with mode: 0644]
client/tag/0.5.3/config.h [new file with mode: 0644]
client/tag/0.5.3/crc32.c [new file with mode: 0644]
client/tag/0.5.3/crc32.h [new file with mode: 0644]
client/tag/0.5.3/crctable.h [new file with mode: 0644]
client/tag/0.5.3/file.c [new file with mode: 0644]
client/tag/0.5.3/file.h [new file with mode: 0644]
client/tag/0.5.3/file.mak [new file with mode: 0644]
client/tag/0.5.3/flashmemory.c [new file with mode: 0644]
client/tag/0.5.3/flashmemory.h [new file with mode: 0644]
client/tag/0.5.3/giveio.c [new file with mode: 0644]
client/tag/0.5.3/giveio.h [new file with mode: 0644]
client/tag/0.5.3/hard_hongkongfc.h [new file with mode: 0644]
client/tag/0.5.3/hard_onajimi.h [new file with mode: 0644]
client/tag/0.5.3/header.c [new file with mode: 0644]
client/tag/0.5.3/header.h [new file with mode: 0644]
client/tag/0.5.3/meg.ico [new file with mode: 0644]
client/tag/0.5.3/paralellport.h [new file with mode: 0644]
client/tag/0.5.3/profile/profile.mak [new file with mode: 0644]
client/tag/0.5.3/reader_hongkongfc.c [new file with mode: 0644]
client/tag/0.5.3/reader_hongkongfc.h [new file with mode: 0644]
client/tag/0.5.3/reader_master.c [new file with mode: 0644]
client/tag/0.5.3/reader_master.h [new file with mode: 0644]
client/tag/0.5.3/reader_onajimi.c [new file with mode: 0644]
client/tag/0.5.3/reader_onajimi.h [new file with mode: 0644]
client/tag/0.5.3/release/release.mak [new file with mode: 0644]
client/tag/0.5.3/rule.mak [new file with mode: 0644]
client/tag/0.5.3/script.c [new file with mode: 0644]
client/tag/0.5.3/script.h [new file with mode: 0644]
client/tag/0.5.3/syntax.h [new file with mode: 0644]
client/tag/0.5.3/textutil.c [new file with mode: 0644]
client/tag/0.5.3/textutil.h [new file with mode: 0644]
client/tag/0.5.3/type.h [new file with mode: 0644]
client/tag/0.5.3/unagi.c [new file with mode: 0644]
client/tag/0.5.3/unagi.ico [new file with mode: 0644]
client/tag/0.5.3/unagi.rc [new file with mode: 0644]
client/tag/0.5.3/unagi.txt [new file with mode: 0644]
client/tag/0.5.3/version.h [new file with mode: 0644]

diff --git a/client/tag/0.5.3/Makefile b/client/tag/0.5.3/Makefile
new file mode 100644 (file)
index 0000000..9472097
--- /dev/null
@@ -0,0 +1,45 @@
+OBJ_HK = giveio.o reader_hongkongfc.o
+OBJ_HD = head/nesheader.o head/header.o file.o
+ARCHIVE_FILE = \
+       *.c *.h *.mak Makefile COPYING \
+       debug/debug.mak profile/profile.mak release/release.mak \
+       unagi.rc unagi.ico
+ARCHIVE_GZ = unagi_client.0.5.3.tar.gz
+ARCHIVE_ZIP = unagi_053.zip
+TARGET_DIR = debug
+TARGET_MAK = debug.mak
+ifeq ($(PROFILE),1)
+       TARGET_DIR = profile
+       TARGET_MAK = profile.mak
+endif
+ifeq ($(RELEASE),1)
+       TARGET_DIR = release
+       TARGET_MAK = release.mak
+endif
+
+all:
+       cd $(TARGET_DIR); make -f $(TARGET_MAK)
+       cp $(TARGET_DIR)/unagi.exe .
+clean:
+       rm -f unagi.exe \
+               debug/*.o debug/*.exe debug/*.d \
+               profile/*.o profile/*.exe profile/*.d \
+               release/*.o release/*.exe release/*.d
+
+head/nesheader.o: nesheader.c
+       $(CC) $(CFLAGS) -DHEADEROUT -I. -c -o $@ $<
+head/header.o: header.c
+       $(CC) $(CFLAGS) -DHEADEROUT -I. -c -o $@ $<
+hk.exe: $(OBJ_HK)
+       $(CC) -o $@ $(OBJ_HK)
+iodel.exe: iodel.o giveio.o
+       $(CC) -o $@ iodel.o giveio.o
+nesheader.exe: $(OBJ_HD)
+       $(CC) -o $@ $(OBJ_HD)
+gz:
+       cd ..; \
+       tar cfz $(ARCHIVE_GZ) $(patsubst %,client/%,$(ARCHIVE_FILE))
+zip:
+       7za a $(ARCHIVE_ZIP) unagi.exe unagi.txt iodel.exe iodel.txt COPYING
+       cd release; 7za a ../$(ARCHIVE_ZIP) unagi.cfg
+       mv $(ARCHIVE_ZIP) ..
diff --git a/client/tag/0.5.3/client_test.h b/client/tag/0.5.3/client_test.h
new file mode 100644 (file)
index 0000000..9cee63e
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _CLIENT_TEST_H_
+#define _CLIENT_TEST_H_
+void client_test(const struct reader_driver *const d, const char *option, const char *file, const char *devicename, const char *mappername);
+#endif
diff --git a/client/tag/0.5.3/config.h b/client/tag/0.5.3/config.h
new file mode 100644 (file)
index 0000000..a987f91
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+#include "reader_master.h"
+enum{
+       CONFIG_OVERRIDE_UNDEF = 4649,
+       CONFIG_OVERRIDE_TRUE = 1,
+       CONFIG_STR_LENGTH = 20
+};
+struct st_config{
+       //override config
+       long mapper;
+       int mirror, backupram;
+       //target filename
+       const char *ramimage, *romimage;
+       const char *script;
+       //device driver function pointer struct
+       const struct reader_driver *reader;
+       const struct flash_driver *cpu_flash_driver, *ppu_flash_driver;
+       //data mode
+       int mode, syntaxtest;
+       //debug member
+       long write_wait;
+       char flash_test_device[CONFIG_STR_LENGTH];
+       char flash_test_mapper[CONFIG_STR_LENGTH];
+};
+
+enum{
+       MODE_TEST,
+       MODE_ROM_DUMP,
+       MODE_RAM_READ,
+       MODE_RAM_WRITE,
+       MODE_ROM_PROGRAM
+};
+
+#endif
diff --git a/client/tag/0.5.3/crc32.c b/client/tag/0.5.3/crc32.c
new file mode 100644 (file)
index 0000000..fa981c4
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+GZIP file format specification version 4.3
+*/
+#include "type.h"
+#include "crc32.h"
+#include "crctable.h"
+/*
+   Update a running crc with the bytes buf[0..len-1] and return
+ the updated crc. The crc should be initialized to zero. Pre- and
+ post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the caller. Usage example:
+
+   unsigned long crc = 0L;
+
+   while (read_buffer(buffer, length) != EOF) {
+     crc = update_crc(crc, buffer, length);
+   }
+   if (crc != original_crc) error();
+*/
+static uint32_t update_crc(uint32_t crc, const uint8_t *buf, int len)
+{
+       uint32_t c = crc ^ 0xffffffffUL;
+       int n;
+
+       for (n = 0; n < len; n++) {
+               c = CRCTABLE[(c ^ buf[n]) & 0xff] ^ (c >> 8);
+       }
+       return c ^ 0xffffffffUL;
+}
+
+/* Return the CRC of the bytes buf[0..len-1]. */
+//uint32_t crc(uint8_t *buf, int len) //ÊÑ¿ô̾¤È¤«¤Ö¤ë¤Î¤Ç¤«¤¨¤ë
+uint32_t crc32_get(const uint8_t *buf, int len)
+{
+       return update_crc(0UL, buf, len);
+}
diff --git a/client/tag/0.5.3/crc32.h b/client/tag/0.5.3/crc32.h
new file mode 100644 (file)
index 0000000..629857b
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _CRC32_H_
+#define _CRC32_H_
+uint32_t crc32_get(const uint8_t *buf, int len);
+#endif
diff --git a/client/tag/0.5.3/crctable.h b/client/tag/0.5.3/crctable.h
new file mode 100644 (file)
index 0000000..dd70e97
--- /dev/null
@@ -0,0 +1,96 @@
+enum{
+       CRC_TABLE_NUM = 256
+};
+#if 0
+/* Table of CRCs of all 8-bit messages. */
+static unsigned long crc_table[CRC_TABLE_NUM];
+
+/* Flag: has the table been computed? Initially false. */
+static int crc_table_computed = 0;
+
+/* Make the table for a fast CRC. */
+void make_crc_table(void)
+{
+       unsigned long c;
+       int n, k;
+       for (n = 0; n < CRC_TABLE_NUM; n++) {
+               c = (unsigned long) n;
+               for (k = 0; k < 8; k++) {
+                       if (c & 1) {
+                               c = 0xedb88320L ^ (c >> 1);
+                       } else {
+                               c = c >> 1;
+                       }
+               }
+               crc_table[n] = c;
+       }
+       crc_table_computed = 1;
+}
+#endif
+
+static const uint32_t CRCTABLE[CRC_TABLE_NUM] = {
+       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+       0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+       0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+       0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+       0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+       0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+       0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+       0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+       0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+       0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+       0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+       0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+       0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+       0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+       0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+       0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+       0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+       0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+       0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+       0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+       0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+       0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+       0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+       0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+       0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+       0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+       0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+       0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+       0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+       0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+       0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+       0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+       0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+       0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+       0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
diff --git a/client/tag/0.5.3/file.c b/client/tag/0.5.3/file.c
new file mode 100644 (file)
index 0000000..9a7bcc4
--- /dev/null
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "file.h"
+
+int buf_load(u8 *buf, const char *file, int size)
+{
+       FILE *fp;
+
+       fp = fopen(file, "rb");
+       if(fp == NULL){
+               return NG;
+       }
+       fseek(fp, 0, SEEK_SET);
+       fread(buf, sizeof(u8), size, fp);
+       fclose(fp);
+       return OK;
+}
+
+void* buf_load_full(const char *file, int *size)
+{
+       FILE *fp;
+       u8 *buf;
+
+       *size = 0;
+       fp = fopen(file, "rb");
+       if(fp == NULL){
+               return NULL;
+       }
+       fseek(fp, 0, SEEK_END);
+       *size = ftell(fp);
+       if(*size == 0){
+               fclose(fp);
+               return NULL;
+       }
+       fseek(fp, 0, SEEK_SET);
+       buf = malloc(*size);
+       fread(buf, sizeof(u8), *size, fp);
+       fclose(fp);
+       return buf;
+}
+
+void buf_save(const void *buf, const char *file, int size)
+{
+       FILE *fp;
+
+       fp = fopen(file, "wb");
+       fseek(fp, 0, SEEK_SET);
+       fwrite(buf, sizeof(u8), size, fp);
+       fclose(fp);
+}
+
diff --git a/client/tag/0.5.3/file.h b/client/tag/0.5.3/file.h
new file mode 100644 (file)
index 0000000..f2384cf
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _FILE_H_
+#define _FILE_H_
+#include "type.h"
+int buf_load(u8 *buf, const char *file, int size);
+void* buf_load_full(const char *file, int *size);
+void buf_save(const void *buf, const char *file, int size);
+#endif
diff --git a/client/tag/0.5.3/file.mak b/client/tag/0.5.3/file.mak
new file mode 100644 (file)
index 0000000..47af38e
--- /dev/null
@@ -0,0 +1,8 @@
+OBJ = \
+       unagi.o script.o header.o crc32.o \
+       reader_master.o reader_onajimi.o reader_hongkongfc.o \
+       flashmemory.o \
+       file.o textutil.o giveio.o unagi.res.o
+TARGET = unagi.exe
+CC = gcc
+CFLAGS = -Wall -Werror -Wmissing-declarations -I..#-Wcast-qual
diff --git a/client/tag/0.5.3/flashmemory.c b/client/tag/0.5.3/flashmemory.c
new file mode 100644 (file)
index 0000000..ae0163b
--- /dev/null
@@ -0,0 +1,584 @@
+/*
+famicom ROM cartridge utility - unagi
+flash memory driver
+
+Copyright (C) 2008-2009 ±·³«È¯¶¨Æ±Áȹç
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+flashmemory.c ¤À¤±¤Î·Ù¹ð
+¤³¤Î¥½¡¼¥¹¥³¡¼¥É¤ò»²¹Í¡¢Å¾ÍѤ·¤Æ¥·¥§¥¢¥¦¥§¥¢¤Ê¤É¤ÇÍø±×¤òÆÀ¤Ê¤¤¤³¤È¡£
+ȽÌÀ¤·¤¿¾ì¹ç¤Ï LGPL ¤¬Å¬ÍѤµ¤ì¡¢³ºÅö²Õ½ê¤Î¥½¡¼¥¹¤ò¸ø³«¤¹¤ëɬÍפ¬¤¢¤ë¡£
+*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include "type.h"
+#include "header.h"
+#include "flashmemory.h"
+/*
+driver for Winbond W29C020, W49F002
+*/
+/*
+JEDEC flash memory command
+http://www.sst.com/downloads/software_driver/SST49LF002A.txt
+*/
+struct flash_task{
+       long address, data;
+};
+enum{
+       ADDRESS_0000 = 0,
+       ADDRESS_2AAA = 0x2aaa,
+       ADDRESS_5555 = 0x5555,
+       FLASH_COMMAND_END
+};
+static const struct flash_task PRODUCTID_ENTRY[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x90},
+       {FLASH_COMMAND_END, 0}
+};
+static const struct flash_task PRODUCTID_EXIT[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0xf0},
+       {FLASH_COMMAND_END, 0}
+};
+static const struct flash_task PROTECT_DISABLE[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0xa0},
+       {FLASH_COMMAND_END, 0}
+};
+static const struct flash_task PROTECT_ENABLE[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x80},
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x20},
+       {FLASH_COMMAND_END, 0}
+};
+static const struct flash_task ERASE_CHIP[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x80},
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x10},
+       {FLASH_COMMAND_END, 0}
+};
+
+static const struct flash_task ERASE_SECTOR[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x80},
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       //¤³¤Î¤¢¤È sectoraddress ¤Ë 0x30 ¤ò write
+       {FLASH_COMMAND_END, 0}
+};
+
+static const struct flash_task PP[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x80},
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x60},
+       {FLASH_COMMAND_END, 0}
+};
+
+static void command_set(const struct flash_order *d, const struct flash_task *t)
+{
+       while(t->address != FLASH_COMMAND_END){
+               long logical_address = 0;
+               switch(t->address){
+               case ADDRESS_0000: //bank ¤Ë¤è¤Ã¤Æ¤ÏÀßÄê¤Ç¤­¤Ê¤¤¤«¤â?
+                       logical_address = d->command_0000;
+                       break;
+               case ADDRESS_2AAA:
+                       logical_address = d->command_2aaa;
+                       break;
+               case ADDRESS_5555:
+                       logical_address = d->command_5555;
+                       break;
+               default:
+                       assert(0); //unknown task address
+               }
+               d->flash_write(logical_address, t->data);
+               t++;
+       }
+}
+
+/*
+---- product ID check ----
+*/
+#define dprintf if(DEBUG==1) printf
+static int productid_check(const struct flash_order *d, const struct flash_driver *f)
+{
+       u8 data[3];
+       command_set(d, PRODUCTID_ENTRY);
+       d->read(d->command_0000, 3, data);
+       command_set(d, PRODUCTID_EXIT);
+       if(f->id_manufacurer != data[0]){
+               return NG;
+       }
+       if(f->id_device != data[1]){
+               return NG;
+       }
+       return OK;
+}
+
+static int productid_sram(const struct flash_order *d, const struct flash_driver *f)
+{
+       return OK;
+}
+/*
+---- toggle check ----
+databit6
+*/
+const int CHECK_RETRY_MAX = 0x10000;
+static int toggle_check_d6(const struct flash_order *d, long address)
+{
+       u8 predata;
+       int retry = 0;
+       d->read(address, 1, &predata); //read DQ6
+       predata &= 0x40;
+       while(retry < CHECK_RETRY_MAX){
+               u8 data;
+               d->read(address, 1, &data); //read DQ6 again
+               data &= 0x40;
+               if(predata == data){
+                       return OK;
+               }
+               predata = data;
+               retry++;
+       }
+       return NG;
+}
+
+static int toggle_check_d2d5d6(const struct flash_order *d, long address)
+{
+       u8 predata;
+       int retry = 0;
+       d->read(address, 1, &predata);
+       predata &= 0x40;
+       do{
+               u8 data;
+               d->read(address, 1, &data);
+               //DQ6 toggle check
+               if(predata == (data & 0x40)){
+                       return OK;
+               }
+               //DQ5 == 0 ¤Ê¤é¤ä¤ê¤Ê¤ª¤·
+               if(data & 0x20){
+                       //recheck toggle bit, read twice
+                       u8 t[2];
+                       d->read(address, 1, &t[0]);
+                       d->read(address, 1, &t[1]);
+                       if((t[0] & 0x40) == (t[1] & 0x40)){
+                               return OK;
+                       }
+                       //Program/Erase operation not complete, write reset command.
+                       return NG;
+               }
+               if((retry & 0x0f) == 0){
+                       dprintf("toggle out %06x \n", (int) address);
+               }
+               retry++;
+       }while(retry < CHECK_RETRY_MAX);
+       return NG;
+}
+
+/*
+---- polling check ----
+databit7
+*/
+static int polling_check_d7(const struct flash_order *d, long address, u8 truedata)
+{
+       int retry = 0;
+       
+       truedata &= 0x80;
+       while(retry < CHECK_RETRY_MAX){
+               u8 data;
+               d->read(address, 1, &data);
+               data &= 0x80;
+               if(truedata == data){
+                       return OK;
+               }
+               retry++;
+       }
+       return NG;
+}
+
+static int polling_check_d5d7(const struct flash_order *d, long address, u8 truedata)
+{
+       int retry = 0;
+       
+       truedata &= 0x80;
+       do{
+               u8 data;
+               d->read(address, 1, &data);
+               if(truedata == (data & 0x80)){
+                       return OK;
+               }
+               if(data & 0x20){
+                       d->read(address, 1, &data);
+                       if(truedata == (data & 0x80)){
+                               return OK;
+                       }
+                       dprintf("%s error", __FUNCTION__);
+                       return NG;
+               }
+               retry++;
+       }while(retry < CHECK_RETRY_MAX);
+       return NG;
+}
+/*
+---- erase ----
+*/
+static void flash_erase_chip_2aaa(const struct flash_order *d)
+{
+       command_set(d, ERASE_CHIP);
+       toggle_check_d6(d, d->command_2aaa);
+       Sleep(d->erase_wait);
+}
+
+static void flash_erase_chip_02aa(const struct flash_order *d)
+{
+       u8 data;
+       d->read(d->command_2aaa, 1, &data);
+       command_set(d, ERASE_CHIP);
+       if(0){
+               toggle_check_d2d5d6(d, d->command_2aaa);
+               
+       }else{
+               polling_check_d5d7(d, d->command_2aaa, data);
+       }
+       Sleep(d->erase_wait);
+}
+
+#if DEBUG==1
+static void sram_erase(const struct flash_order *d)
+{
+       //bank ÀÚ¤êÂؤ¨¤¬È¼¤¦¤Î¤Ç¼ÂÁõ¤Ç¤­¤Ê¤¤
+}
+#endif
+
+/*
+---- program ----
+*/
+static int program_byte(const struct flash_order *d, long address, const u8 *data, long length)
+{
+       while(length != 0){
+               if(*data != 0xff){
+                       fflush(stdout);
+                       command_set(d, PROTECT_DISABLE);
+                       d->flash_write(address, *data);
+                       if(toggle_check_d6(d, address) == NG){
+                               dprintf("%s NG\n", __FUNCTION__);
+                               return NG;
+                       }
+                       /*if(polling_check_d7(d, address, *data) == NG){
+                               dprintf("%s NG\n", __FUNCTION__);
+                               return NG;
+                       }*/
+               }
+               address++;
+               data++;
+               length--;
+       }
+       return OK;
+}
+
+static int program_pagewrite(const struct flash_order *d, long address, const u8 *data, long length)
+{
+       const long toggle_address = address ;
+       command_set(d, PROTECT_DISABLE);
+       while(length != 0){
+               d->flash_write(address, *data);
+               address++;
+               data++;
+               length--;
+       }
+       int ret = toggle_check_d6(d, toggle_address);
+       if(0){
+               data--;
+               polling_check_d7(d, address - 1, *data);
+       }
+
+       return ret;
+}
+
+/*
+¸ÇÍ­¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð
+*/
+static void w49f002_init(const struct flash_order *d)
+{
+/*
+byte program mode ¤Ç¤Ï 1->0 ¤Ë¤¹¤ë¤À¤±¡£ 0->1 ¤Ï erase ¤Î¤ß¡£
+¤è¤Ã¤Æ½é´ü²½»þ¤Ë¤Ï erase ¤ò¼Â¹Ô¤¹¤ë
+*/
+       flash_erase_chip_2aaa(d);
+}
+
+static void w49f002_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+       program_byte(d, address, m->data, length);
+//     dprintf("write %s 0x%06x done\n", m->name, (int) m->offset);
+}
+
+static void am29f040_init(const struct flash_order *d)
+{
+       flash_erase_chip_02aa(d);
+}
+
+static void am29f040_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+       const u8 *data;
+       data = m->data;
+       while(length != 0){
+               if(*data != 0xff){
+                       command_set(d, PROTECT_DISABLE);
+                       d->flash_write(address, *data);
+                       if(toggle_check_d2d5d6(d, address) == NG){
+                               dprintf("%s NG\n", __FUNCTION__);
+                               return;
+                       }
+               }
+               address++;
+               data++;
+               length--;
+       }
+}
+
+static void init_nop(const struct flash_order *d)
+{
+/*
+page write mode ¤Ç¤Ï¤È¤¯¤Ë¤Ê¤·
+*/
+}
+
+static void w29c040_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+       u8 *cmp;
+       int ngblock = 0;
+       int retry = 0;
+       assert(d->pagesize != 0);
+       cmp = malloc(d->pagesize);
+       do{
+               long a = address;
+               long i = length;
+               long offset = m->offset;
+               const u8 *dd;
+
+               dd = m->data;
+               ngblock = 0;
+               while(i != 0){
+                       d->read(a, d->pagesize, cmp);
+                       if(memcmp(cmp, dd, d->pagesize) != 0){
+                               ngblock++;
+                               dprintf("write %s 0x%06x\n", m->name, (int) offset);
+                               int result = program_pagewrite(d, a, dd, d->pagesize);
+                               if(result == NG){
+                                       printf("%s: write error\n", __FUNCTION__);
+                                       free(cmp);
+                                       return;
+                               }
+                       }
+                       a += d->pagesize;
+                       dd += d->pagesize;
+                       offset += d->pagesize;
+                       i -= d->pagesize;
+               }
+               dprintf("%s 0x%06x, ngblock %d\n", m->name, (int) m->offset, ngblock);
+               /* mmc5 test
+               if(retry >= 3 && ngblock >= 16){
+                       dprintf("skip\n");
+                       break;
+               }*/
+               if(retry > 80){
+                       dprintf("skip\n");
+                       break;
+               }
+               retry++;
+               fflush(stdout);
+       }while(ngblock != 0);
+
+       free(cmp);
+}
+
+static void sram_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+       const u8 *data;
+       data = m->data;
+       while(length != 0){
+               d->flash_write(address, *data);
+               address++;
+               data++;
+               length--;
+       }
+}
+
+static void dummy_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+}
+
+/*
+¥Ç¥Ð¥¤¥¹¥ê¥¹¥È
+*/
+//0x80 °Ê¹ß¤ÏËÜÅö¤Î¥Ç¥Ð¥¤¥¹½ÅÊ£¤·¤Ê¤¤¤È»×¤¦. Ã¯¤« JEDEC ¤Î¤È¤³¤ò¤·¤é¤Ù¤Æ.
+static const struct flash_driver DRIVER_SRAM256K = {
+       .name = "SRAM256K",
+       .capacity = 0x8000,
+       .pagesize = 0,
+       .erase_wait = 0,
+       .command_mask = 0,
+       .id_manufacurer = FLASH_ID_DEVICE_SRAM,
+       .id_device = FLASH_ID_DEVICE_SRAM,
+       .productid_check = productid_sram,
+#if DEBUG==1
+       .erase = sram_erase,
+#endif
+       .init = init_nop,
+       .write = sram_write
+};
+
+static const struct flash_driver DRIVER_DUMMY = {
+       .name = "dummy",
+       .capacity = 0x40000,
+       .pagesize = 0,
+       .erase_wait = 0,
+       .command_mask = 0,
+       .id_manufacurer = FLASH_ID_DEVICE_DUMMY,
+       .id_device = FLASH_ID_DEVICE_DUMMY,
+       .productid_check = productid_sram,
+#if DEBUG==1
+       .erase = init_nop,
+#endif
+       .init = init_nop,
+       .write = dummy_write
+};
+
+static const struct flash_driver DRIVER_W29C020 = {
+       .name = "W29C020",
+       .capacity = 0x40000,
+       .pagesize = 0x80,
+       .erase_wait = 50,
+       .command_mask = 0x7fff,
+       .id_manufacurer = 0xda,
+       .id_device = 0x45,
+       .productid_check = productid_check,
+#if DEBUG==1
+       .erase = flash_erase_chip_2aaa,
+#endif
+       .init = init_nop,
+       .write = w29c040_write
+};
+
+static const struct flash_driver DRIVER_W29C040 = {
+       .name = "W29C040",
+       .capacity = 0x80000,
+       .pagesize = 0x100,
+       .erase_wait = 50,
+       .command_mask = 0x7fff,
+       .id_manufacurer = 0xda,
+       .id_device = 0x46,
+       .productid_check = productid_check,
+#if DEBUG==1
+       .erase = flash_erase_chip_2aaa,
+#endif
+       .init = init_nop,
+       .write = w29c040_write
+};
+
+static const struct flash_driver DRIVER_W49F002 = {
+       .name = "W49F002",
+       .capacity = 0x40000,
+       .pagesize = 0,
+       .erase_wait = 100, //typ 0.1, max 0.2 sec
+       .command_mask = 0x7fff,
+       .id_manufacurer = 0xda,
+       .id_device = 0xae,
+       .productid_check = productid_check,
+#if DEBUG==1
+       .erase = flash_erase_chip_2aaa,
+#endif
+       .init = w49f002_init,
+       .write = w49f002_write
+};
+
+/*
+MANUFATUTER ID 0x7f1c
+EN29F002T DEVICE ID 0x7f92
+EN29F002B DEVICE ID 0x7f97
+
+command address ¤¬ 0x00555, 0x00aaa ¤Ë¤Ê¤Ã¤Æ¤ë
+*/
+static const struct flash_driver DRIVER_EN29F002T = {
+       .name = "EN29F002T",
+       .capacity = 0x40000,
+       .pagesize = 0,
+       .erase_wait = 3000, //typ 2, max 5 sec
+       .command_mask = 0x07ff,
+       .id_manufacurer = 0x1c,
+       .id_device = 0x92,
+       .productid_check = productid_check,
+#if DEBUG==1
+       .erase = flash_erase_chip_02aa,
+#endif
+       .init = am29f040_init,
+       .write = am29f040_write
+};
+
+static const struct flash_driver DRIVER_AM29F040B = {
+       .name = "AM29F040B",
+       .capacity = 0x80000,
+       .pagesize = 0,
+       .erase_wait = 8000, //typ 8, max 64 sec
+       .command_mask = 0x07ff,
+       .id_manufacurer = 0x01,
+       .id_device = 0xa4,
+       .productid_check = productid_check,
+#if DEBUG==1
+       .erase = flash_erase_chip_02aa,
+#endif
+       .init = am29f040_init,
+       .write = am29f040_write
+};
+
+static const struct flash_driver *DRIVER_LIST[] = {
+       &DRIVER_W29C020, &DRIVER_W29C040, 
+       &DRIVER_W49F002, &DRIVER_EN29F002T, &DRIVER_AM29F040B,
+       &DRIVER_SRAM256K, 
+       &DRIVER_DUMMY,
+       NULL
+};
+
+const struct flash_driver *flash_driver_get(const char *name)
+{
+       const struct flash_driver **d;
+       d = DRIVER_LIST;
+       while(*d != NULL){
+               if(strcmp(name, (*d)->name) == 0){
+                       return *d;
+               }
+               d++;
+       }
+       return NULL;
+}
diff --git a/client/tag/0.5.3/flashmemory.h b/client/tag/0.5.3/flashmemory.h
new file mode 100644 (file)
index 0000000..417890a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+famicom ROM cartridge utility - unagi
+flash memory driver
+
+Copyright (C) 2008-2009 ±·³«È¯¶¨Æ±Áȹç
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+flashmemory.c ¤À¤±¤Î·Ù¹ð
+¤³¤Î¥½¡¼¥¹¥³¡¼¥É¤ò»²¹Í¡¢Å¾ÍѤ·¤Æ¥·¥§¥¢¥¦¥§¥¢¤Ê¤É¤ÇÍø±×¤òÆÀ¤Ê¤¤¤³¤È¡£
+ȽÌÀ¤·¤¿¾ì¹ç¤Ï LGPL ¤¬Å¬ÍѤµ¤ì¡¢³ºÅö²Õ½ê¤Î¥½¡¼¥¹¤ò¸ø³«¤¹¤ëɬÍפ¬¤¢¤ë¡£
+*/
+#ifndef _FLASHMEMORY_H_
+#define _FLASHMEMORY_H_
+
+struct flash_order{
+       //JEDEC command ¤ò½¼¤Æ¤ë CPU/PPU ÏÀÍý¥¢¥É¥ì¥¹
+       long command_0000, command_2aaa, command_5555;
+       long command_mask;
+       long pagesize;
+       long erase_wait;
+       //struct reader_driver ¤Î´Ø¿ô¥Ý¥¤¥ó¥¿¤òÅϤ¹¾ì½ê
+       void (*flash_write)(long address, long data);
+       void (*read)(long address, long length, u8 *data);
+};
+
+struct memory;
+struct flash_driver{
+       const char *name;
+       long capacity, pagesize;
+       long command_mask;
+       long erase_wait; //ñ°Ì msec
+       u8 id_manufacurer, id_device;
+       int (*productid_check)(const struct flash_order *d, const struct flash_driver *f);
+#if DEBUG==1
+       void (*erase)(const struct flash_order *d);
+#endif
+       void (*init)(const struct flash_order *d);
+       void (*write)(const struct flash_order *d, long address, long length, const struct memory *m);
+};
+
+const struct flash_driver *flash_driver_get(const char *name);
+enum{
+       FLASH_ID_DEVICE_SRAM = 0xf0, 
+       FLASH_ID_DEVICE_DUMMY
+};
+#endif
diff --git a/client/tag/0.5.3/giveio.c b/client/tag/0.5.3/giveio.c
new file mode 100644 (file)
index 0000000..4df6a4c
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+       Win32 GIVEIO(DirectI/O Access) Service Controll Module
+*/
+
+#include "giveio.h"
+#include <windows.h>
+#include <stdio.h>
+
+/**-----------------------------------------------------**/
+
+/*
++--------------------+---------+----+----+----+----+--------------------+
+|Products            |Version  |PFID|MJRV|MNRV|BNUM| note
++--------------------+---------+----+----+----+----+--------------------+
+|Windows 95          |4.00.950 |  1 |  4 |  0 | 950|(Windows 95 + SP1)  |
+|Windows 95 OSR 2    |4.00.950B|  1 |  4 |  0 |1111|(Windows 95 OSR 2.1)|
+|Windows 95 OSR 2.5  |4.00.950C|  1 |  4 |  0 |1212|                    |
+|Windows 98          |4.10.1998|  1 |  4 | 10 |1998|                    |
+|Windows 98 SE       |4.10.2222|  1 |  4 | 10 |2222|                    |
+|Windows Me          |4.90.3000|  1 |  4 | 90 |3000|                    |
+|Windows NT 4.0      |4.00.1381|  2 |  4 |  0 |1381|                    |
+|Windows 2000        |5.00.2195|  2 |  5 |  0 |2195|                    |
+|Windows XP          |5.01.2600|  2 |  5 |  1 |2600|                    |
++--------------------+---------+----+----+----+----+--------------------+
+
+PFID = dwPlatformId
+MJRV = dwMajorVersion
+MNRV = dwMinorVersion
+BNUM = dwBuildNumber
+*/
+
+/* check the OS which GIVEIO should be necessary */
+static int is_winnt(void)
+{
+       OSVERSIONINFO osvi;
+
+       osvi.dwOSVersionInfoSize = sizeof(osvi);
+       if( !GetVersionEx(&osvi) )
+               return 0;
+
+       switch (osvi.dwPlatformId)
+       {
+       case VER_PLATFORM_WIN32_NT:
+               return 1;
+       case VER_PLATFORM_WIN32_WINDOWS:
+               return 0;
+       case VER_PLATFORM_WIN32s:
+               return 0;
+       }
+
+       /* unknown */
+       return 0;
+}
+
+/**-----------------------------------------------------**/
+
+/*  connect to local service control manager */
+static SC_HANDLE hSCMan = NULL;
+static int OpenServiceControlManager(void)
+{
+       if(hSCMan==NULL)
+       {
+               /*  connect to local service control manager */
+               if ((hSCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL) 
+                       return GetLastError();
+       }
+       return 0;
+}
+
+static void ClseServiceControlManager(void)
+{
+       if(hSCMan==NULL)
+               CloseServiceHandle(hSCMan);
+       hSCMan = NULL;
+}
+
+/**-----------------------------------------------------**/
+/* #define MAX_PATH 256 */
+static DWORD DriverInstall(LPCTSTR lpFname,LPCTSTR lpDriver)
+{
+       BOOL dwStatus = 0;
+       SC_HANDLE hService = NULL;
+       char *address;
+       char fullpath[MAX_PATH];
+
+       /*  connect to local service control manager */
+       if(OpenServiceControlManager())
+               return 1;
+
+       /* get full path of driver file in current directry */
+       GetFullPathName(lpFname,MAX_PATH,fullpath,&address);
+
+       /* add to service control manager's database */
+       if ((hService = CreateService(hSCMan, lpDriver, 
+               lpDriver, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER,
+               SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, fullpath, 
+               NULL, NULL, NULL, NULL, NULL)) == NULL)
+               dwStatus = GetLastError();
+       else CloseServiceHandle(hService);
+
+       return dwStatus;
+}
+
+static DWORD DriverStart(LPCTSTR lpDriver)
+{
+       BOOL dwStatus = 0;
+       SC_HANDLE hService = NULL;
+
+       /*  connect to local service control manager */
+       if(OpenServiceControlManager())
+               return 1;
+
+       // get a handle to the service
+       if ((hService = OpenService(hSCMan, lpDriver, SERVICE_ALL_ACCESS)) != NULL) 
+       {
+               // start the driver
+               if (!StartService(hService, 0, NULL))
+                       dwStatus = GetLastError();
+       } else dwStatus = GetLastError();
+
+       if (hService != NULL) CloseServiceHandle(hService);
+
+       return dwStatus;
+} // DriverStart
+
+/**-----------------------------------------------------**/
+static DWORD DriverStop(LPCTSTR lpDriver)
+{
+   BOOL dwStatus = 0;
+   SC_HANDLE hService = NULL;
+   SERVICE_STATUS serviceStatus;
+
+       /*  connect to local service control manager */
+       if(OpenServiceControlManager())
+               return 1;
+
+
+   // get a handle to the service
+   if ((hService = OpenService(hSCMan, lpDriver, 
+      SERVICE_ALL_ACCESS)) != NULL) 
+   {
+      // stop the driver
+      if (!ControlService(hService, SERVICE_CONTROL_STOP,
+         &serviceStatus))
+            dwStatus = GetLastError();
+   } else dwStatus = GetLastError();
+
+   if (hService != NULL) CloseServiceHandle(hService);
+   return dwStatus;
+} // DriverStop
+
+/**-----------------------------------------------------**/
+static DWORD DriverRemove(LPCTSTR lpDriver)
+{
+   BOOL dwStatus = 0;
+   SC_HANDLE hService = NULL;
+
+       /*  connect to local service control manager */
+       if(OpenServiceControlManager())
+               return 1;
+
+   // get a handle to the service
+   if ((hService = OpenService(hSCMan, lpDriver, 
+      SERVICE_ALL_ACCESS)) != NULL) 
+   {
+      // remove the driver
+      if (!DeleteService(hService))
+         dwStatus = GetLastError();
+   } else dwStatus = GetLastError();
+
+   if (hService != NULL) CloseServiceHandle(hService);
+   return dwStatus;
+} // DriverRemove
+
+/*****************************************************************************/
+
+const char giveio_dname[] = "\\\\.\\giveio"; /* device name      */
+const char giveio_fname[] = "giveio.sys";    /* driver-file name */
+const char giveio_sname[] = "giveio";        /* service name     */
+
+/*
+open & close "giveio" device for Direct I/O Access
+
+1st try : open giveio 
+2nd try : start service & open
+3rd try : install current "giveio.sys" file & start & open
+*/
+
+int giveio_start(void)
+{
+       HANDLE h;
+       int res;
+
+       /* escape when Win95/98/Me */
+       if(!is_winnt())
+               return GIVEIO_WIN95;
+
+
+       /* WinNT , try GIVEIO */
+       res = GIVEIO_OPEN;
+       while(1)
+       {
+               if(res>=GIVEIO_INSTALL)
+               {
+/* printf("Install\n"); */
+                       /* Install "GIVEIO.SYS" file in currect directry */
+                       if( DriverInstall(giveio_fname,giveio_sname) )
+                       {
+                               /* if install error , no retry */
+                               break;
+                       }
+               }
+               if(res>=GIVEIO_START)
+               {
+/* printf("Start\n"); */
+                       /* Start GIVEIO Service */
+                       if( DriverStart(giveio_sname) )
+                       {
+                               /* error , retry with install */
+                               res ++;
+                               continue;
+                       }
+               }
+/* printf("Open\n"); */
+               /* open driver */
+               h = CreateFile(giveio_dname, GENERIC_READ, 0, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+               if(h != INVALID_HANDLE_VALUE)
+               {
+                       /* OK */
+                       CloseHandle(h);
+                       return res;
+               }
+               /* error , retry with Start,Install */
+               res++;
+       }
+
+       /* error */
+       return GIVEIO_ERROR;
+}
+
+int giveio_stop(int param)
+{
+       /* escape when Win95/98/Me */
+       if(!is_winnt())
+               return 0;
+
+       if(param>=GIVEIO_STOP)
+       {
+/* printf("Stop\n"); */
+               if( DriverStop(giveio_sname) )
+                       return param;
+               if(param>=GIVEIO_REMOVE)
+               {
+/* printf("Remove\n"); */
+                       if(DriverRemove(giveio_sname) )
+                               return param;
+               }
+       }
+
+       ClseServiceControlManager();
+
+       /* Okay */
+       return 0;
+}
+
diff --git a/client/tag/0.5.3/giveio.h b/client/tag/0.5.3/giveio.h
new file mode 100644 (file)
index 0000000..d37ced3
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __GIVEIO_H__
+#define __GIVEIO_H__
+
+/* result of giveio_start() */
+#define GIVEIO_ERROR   0
+#define GIVEIO_WIN95   1  /* windows 95/98/Me, unnecessary */
+#define GIVEIO_OPEN    2  /* giveio opened                 */
+#define GIVEIO_START   3  /* giveio service start & opened */
+#define GIVEIO_INSTALL 4  /* giveio install,start & opened */
+int giveio_start(void);
+
+/* parameter of giveio_stop() */
+#define GIVEIO_STOP   3   /* giveio stop service         */
+#define GIVEIO_REMOVE 4   /* giveio stop & remove driver */
+int giveio_stop(int param);
+
+#endif
diff --git a/client/tag/0.5.3/hard_hongkongfc.h b/client/tag/0.5.3/hard_hongkongfc.h
new file mode 100644 (file)
index 0000000..64a8f98
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _HONGKONGFC_HARD_H_
+#define _HONGKONGFC_HARD_H_
+/*
+DATA PORT
+BIT0-BIT7: DATA IN/OUT, ADDRESS, BUS CONTROL
+STATUS PORT:
+BIT7: DATA ½ÐÎϳÎǧ?
+CONTROL PORT:
+BIT~0: DATA PORT LATCH CLOCK
+  H->L ¤Ç LATCH
+BIT~1 2 3: DATA PORT SELECT
+BIT4: ³ä¤ê¹þ¤ßµö²Ä MUST BE 0
+BIT5: PORT DIRECTION
+  L PC->BUS
+  H BUS->PC
+*/
+enum{
+       BITNUM_CONTROL_DATA_LATCH = 0,
+       BITNUM_CONTROL_DATA_SELECT,
+       BITNUM_CONTROL_INTERRUPT = 4,
+       BITNUM_CONTROL_DIRECTION
+};
+/*
+DATA PORT SELECT
+0: DATA BUS DIRECTION PC->BUS
+1: DATA BUS DIRECTION BUS->PC
+2: WRITE->READ ¤ËÀڤ괹¤¨¤ë¤È DATA_SELECT_A23toA16 ¤¬ÇË»¤¹¤ë
+3: WRITE->READ ¤ËÀڤ괹¤¨¤ë¤È DATA_SELECT_CONTROL ¤¬ÇË»¤¹¤ë
+4: LATCH cartridge control
+5: LATCH A23-A16, fc ¤Ç¤Ï write data
+6: LATCH A15-A8
+7: LATCH A7-A0
+*/
+enum{
+       DATA_SELECT_WRITE = 0,
+       DATA_SELECT_READ,
+       DATA_SELECT_BREAK_DATA,
+       DATA_SELECT_BREAK_CONTROL,
+       DATA_SELECT_A7toA0 = 4,
+       DATA_SELECT_A15toA8,
+       DATA_SELECT_A23toA16,
+       DATA_SELECT_CONTROL,
+       DATA_SELECT_WRITEDATA = DATA_SELECT_A23toA16
+};
+enum{
+       BITNUM_PPU_OUTPUT = 0,
+       BITNUM_PPU_SELECT,
+       BITNUM_PPU_RW,
+       //bit3̤»ÈÍÑ
+       BITNUM_WRITEDATA_OUTPUT = 4, //b0 L ¤Ç½ÐÎÏ
+       BITNUM_WRITEDATA_LATCH, //b1 L->H
+       BITNUM_CPU_RW, //b2
+       BITNUM_CPU_M2 //b3
+};
+#endif
diff --git a/client/tag/0.5.3/hard_onajimi.h b/client/tag/0.5.3/hard_onajimi.h
new file mode 100644 (file)
index 0000000..0ac8186
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef _HARD_ONAJIMI_H_
+#define _HARD_ONAJIMI_H_
+/*
+STROB: CPU/PPU ADDRESS BUS control
+L Address reset, address = 0
+H Address Enable
+*/
+enum{
+       ADDRESS_RESET = 1,
+       ADDRESS_ENABLE = 0
+};
+/*
+D0: CPU/PPU ADDRESS BUS increment
+D1: CPU/PPU DATA SHIFT
+D2: CPU/PPU DATA WRITE DATA
+D3: CPU/PPU DATA DIRECTION
+D4: PPU /WR + CPU ¦Õ2
+D5: PPU /CS
+D6: CPU ROM area /CS
+D7: CPU /WR
+*/
+enum BITNUM{
+       BITNUM_ADDRESS_INCREMENT = 0,
+       BITNUM_DATA_SHIFT_RIGHT,
+       BITNUM_DATA_WRITE_DATA,
+       BITNUM_DATA_DIRECTION,
+       BITNUM_CPU_M2,
+       BITNUM_PPU_SELECT,
+       BITNUM_CPU_RAMROM_SELECT,
+       BITNUM_CPU_RW,
+       BITNUM_PPU_RW = BITNUM_CPU_M2
+};
+/*
+D0: CPU/PPU ADDRESS BUS increment
+H->L address += 1
+
+D1: CPU/PPU DATA SHIFT (¥Ð¥¹¤ÎÀܳ¤¬È¿Å¾¤·¤Æ¤¤¤ë)
+L->H D01234567
+
+D2: CPU/PPU DATA WRITE DATA
+LSB->MSB ºÇ²¼°Ìbit¤«¤é½ç¤Ë¡£
+*/
+enum{
+       ADDRESS_NOP = 1 << BITNUM_ADDRESS_INCREMENT,
+       DATA_SHIFT_NOP = 0 << BITNUM_DATA_SHIFT_RIGHT
+};
+/*
+D3: CPU/PPU DATA DIRECTION
+H FC read
+L FC write
+*/
+enum{
+       DATA_DIRECTION_WRITE = 0,
+       DATA_DIRECTION_READ = 1
+};
+/*
+D4: PPU /WE + CPU M2
+H PPU read + CPU bus enable (for MMC5)
+L PPU write + CPU bus disable
+*/
+enum{
+       PPU_WRITE__CPU_DISABLE = 0,
+       PPU_READ__CPU_ENABLE
+};
+/*
+D5: PPU /RD + PPU A13
+H disable
+L enable
+*/
+enum{
+       PPU_ENABLE = 0,
+       PPU_DISABLE
+};
+/*
+D6: CPU ROM select (~A15)
+H RAM IO select, use $0000-$7fff
+L ROM select, use $8000-$ffff
+*/
+enum{
+       CPU_ROM_SELECT = 0,
+       CPU_RAM_SELECT
+};
+/*
+D7: CPU W/~R
+L write
+H read
+*/
+enum{
+       CPU_WRITE = 0,
+       CPU_READ
+};
+/*
+BUSY: CPU/PPU DATA READ DATA
+LSB->MSB ºÇ²¼°Ìbit¤«¤é½ç¤Ë¡£
+*/
+#endif
diff --git a/client/tag/0.5.3/header.c b/client/tag/0.5.3/header.c
new file mode 100644 (file)
index 0000000..135efd6
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+famicom ROM cartridge utility - unagi
+iNES header/buffer control
+*/
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "type.h"
+#include "file.h"
+#include "crc32.h"
+#include "config.h"
+#include "header.h"
+
+enum{
+       NES_HEADER_SIZE = 0x10,
+       PROGRAM_ROM_MIN = 0x4000,
+       CHARCTER_ROM_MIN = 0x2000
+};
+static const u8 NES_HEADER_INIT[NES_HEADER_SIZE] = {
+       'N', 'E', 'S', 0x1a, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#ifndef HEADEROUT
+static 
+#endif
+void nesheader_set(const struct romimage *r, u8 *header)
+{
+       memcpy(header, NES_HEADER_INIT, NES_HEADER_SIZE);
+       header[4] = r->cpu_rom.size / PROGRAM_ROM_MIN;
+       header[5] = r->ppu_rom.size / CHARCTER_ROM_MIN;
+       if(r->mirror == MIRROR_VERTICAL){
+               header[6] |= 0x01;
+       }
+       if((r->cpu_ram.size != 0) || (r->backupram != 0)){
+               header[6] |= 0x02;
+       }
+       //4 screen ¤Ï̵»ë
+       header[6] |= (r->mappernum & 0x0f) << 4;
+       header[7] |= r->mappernum & 0xf0;
+}
+
+#ifndef HEADEROUT
+/*
+returnÃÍ: error count
+*/
+static int mirroring_fix(struct memory *m, long min)
+{
+       long mirror_size = m->size / 2;
+       while(mirror_size >= min){
+               const u8 *halfbuf;
+               halfbuf = m->data;
+               halfbuf += mirror_size;
+               if(memcmp(m->data, halfbuf, mirror_size) != 0){
+                       const long ret = mirror_size * 2;
+                       if(m->size != ret){
+                               printf("mirroring %s rom fixed\n", m->name);
+                               m->size = ret;
+                       }
+                       return 0;
+               }
+               mirror_size /= 2;
+       }
+       
+       u8 *ffdata;
+       int ret = 0;
+       ffdata = malloc(min);
+       memset(ffdata, 0xff, min);
+       if(memcmp(ffdata, m->data, min) == 0){
+               printf("error: data is all 0xff\n");
+               ret = 1;
+       }else if(m->size != min){
+               printf("mirroring %s rom fixed\n", m->name);
+               m->size = min;
+       }
+       free(ffdata);
+       
+       return ret;
+}
+
+//hash ¤Ï sha1 ¤Ë¤·¤¿¤¤¤¬Â¾¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤¢¤ï¤»¤Æ crc32 ¤Ë¤·¤È¤¯
+static void rominfo_print(const struct memory *m)
+{
+       if(m->size != 0){
+               const uint32_t crc = crc32_get(m->data, m->size);
+               printf("%s ROM: size 0x%06x, crc32 0x%08x\n", m->name, m->size, (const int) crc);
+       }else{
+               printf("%s RAM\n", m->name);
+       }
+}
+
+void nesfile_create(struct romimage *r, const char *romfilename)
+{
+       int error = 0;
+       //RAM adapter bios size 0x2000 ¤ÏÊѹ¹¤·¤Ê¤¤
+       if(r->cpu_rom.size >= PROGRAM_ROM_MIN){
+               error += mirroring_fix(&(r->cpu_rom), PROGRAM_ROM_MIN);
+       }
+       if(r->ppu_rom.size != 0){
+               error += mirroring_fix(&(r->ppu_rom), CHARCTER_ROM_MIN);
+       }
+       if((DEBUG == 0) && (error != 0)){
+               return;
+       }
+       //½¤ÀµºÑ¤ß ROM ¾ðÊóɽ¼¨
+       printf("mapper %d\n", (int) r->mappernum);
+       rominfo_print(&(r->cpu_rom));
+       rominfo_print(&(r->ppu_rom));
+
+       FILE *f;
+       u8 header[NES_HEADER_SIZE];
+       nesheader_set(r, header);
+       f = fopen(romfilename, "wb");
+       fseek(f, 0, SEEK_SET);
+       //RAM adapter bios ¤Ë¤Ï NES ¥Ø¥Ã¥À¤òºî¤é¤Ê¤¤
+       if(r->cpu_rom.size >= PROGRAM_ROM_MIN){ 
+               fwrite(header, sizeof(u8), NES_HEADER_SIZE, f);
+       }
+       fwrite(r->cpu_rom.data, sizeof(u8), r->cpu_rom.size, f);
+       if(r->ppu_rom.size != 0){
+               fwrite(r->ppu_rom.data, sizeof(u8), r->ppu_rom.size, f);
+       }
+       fclose(f);
+}
+
+static inline void memory_malloc(struct memory *m)
+{
+       m->data = NULL;
+       if(m->size != 0){
+               m->data = malloc(m->size);
+       }
+}
+
+int nesbuffer_malloc(struct romimage *r, int mode)
+{
+       switch(mode){
+       case MODE_ROM_DUMP:
+               memory_malloc(&(r->cpu_rom));
+               memory_malloc(&(r->ppu_rom));
+               break;
+       case MODE_RAM_READ:
+               memory_malloc(&(r->cpu_ram));
+               break;
+       }
+       return OK;
+}
+
+static inline void memory_free(struct memory *m)
+{
+       if(m->size != 0){
+               free(m->data);
+               m->data = NULL;
+       }
+}
+void nesbuffer_free(struct romimage *r, int mode)
+{
+       memory_free(&(r->cpu_rom));
+       memory_free(&(r->ppu_rom));
+       if(mode == MODE_RAM_READ){
+               memory_free(&(r->cpu_ram));
+       }
+}
+
+void backupram_create(const struct memory *r, const char *ramfilename)
+{
+       buf_save(r->data, ramfilename, r->size);
+}
+
+static int nesfile_size_check(const char *errorprefix, const struct memory *m, long size)
+{
+       if(size < m->size){
+               while(size == m->size){
+                       if(size < 0){
+                               printf("%s NES header %s romsize alignment error\n", errorprefix, m->name);
+                               return NG;
+                       }
+                       size -= m->size;
+               }
+               return NG;
+       }
+       //
+       else if(size > m->size){
+               printf("%s NES header cpuromsize too large\n", errorprefix);
+               return NG;
+       }
+       return OK;
+}
+
+/*
+memory size ¤Ï 2¾è¤µ¤ì¤Æ¤¤¤¯Ãͤ¬Àµ¾ïÃÍ.
+¤¿¤À¤·¡¢region ¤ÎºÇ¾®Ãͤè¤ê¾®¤µ¤¤¾ì¹ç¤Ï test ÍѤȤ·¤ÆÀµ¾ï¤Ë¤¹¤ë
+*/
+int memorysize_check(const long size, int region)
+{
+       long min = 0;
+       switch(region){
+       case MEMORY_AREA_CPU_ROM:
+               min = PROGRAM_ROM_MIN;
+               break;
+       case MEMORY_AREA_CPU_RAM:
+               min = 0x800; //¤¤¤Þ¤Î¤È¤³¤í. taito ·Ï¤Ï¤â¤Ã¤È¾®¤µ¤¤¤è¤¦¤Êµ¤¤¬¤¹¤ë
+               break;
+       case MEMORY_AREA_PPU:
+               min = CHARCTER_ROM_MIN;
+               break;
+       default:
+               assert(0);
+       }
+       if(size <= min){
+               return OK;
+       }
+       switch(size){
+       case 0x004000: //128K bit
+       case 0x008000: //256K
+       case 0x010000: //512K
+       case 0x020000: //1M
+       case 0x040000: //2M
+       case 0x080000: //4M
+       case 0x100000: //8M
+               return OK;
+       }
+       return NG;
+}
+
+/*
+romimage ¤¬ bank ¤ÎÄêµÁÃͤè¤ê¾®¤µ¤¤¾ì¹ç¤Ï romarea ¤ÎËöÈø¤ËÄ¥¤ë¡£ 
+Ʊ¤¸¥Ç¡¼¥¿¤ò memcpy ¤·¤¿¤Û¤¦¤¬°ÂÁ´¤À¤¬¡¢¤È¤ê¤¢¤¨¤º¤Ç¡£
+*/
+static void nesfile_datapointer_set(const u8 *buf, struct memory *m, long size)
+{
+       u8 *data;
+       assert((size % CHARCTER_ROM_MIN) == 0);
+       assert((m->size % CHARCTER_ROM_MIN) == 0);
+       data = malloc(size);
+       m->data = data;
+       if(size < m->size){
+               long fillsize = m->size - size;
+               assert(fillsize >= 0); //fillsize is minus
+               memset(data, 0xff, fillsize); //ROM ¤Î̤»ÈÍÑÎΰè¤Ï 0xff ¤¬´ðËÜ
+               data += fillsize;
+               size -= fillsize;
+       }
+       memcpy(data, buf, size);
+}
+
+//flashmemory device capacity check ¤¬È´¤±¤Æ¤ë¤±¤É¤É¤³¤Ç¤ä¤ë¤«Ì¤Äê
+int nesfile_load(const char *errorprefix, const char *file, struct romimage *r)
+{
+       int imagesize;
+       u8 *buf;
+       
+       buf = buf_load_full(file, &imagesize);
+       if(buf == NULL || imagesize < (NES_HEADER_SIZE + PROGRAM_ROM_MIN)){
+               printf("%s ROM image open error\n", errorprefix);
+               return NG;
+       }
+       //nes header check
+       if(memcmp(buf, NES_HEADER_INIT, 4) != 0){
+               printf("%s NES header identify error\n", errorprefix);
+               free(buf);
+               return NG;
+       }
+       //mapper number check
+       {
+               long mapper = (buf[6] >> 4) & 0x0f;
+               mapper |= buf[7] & 0xf0;
+               if(r->mappernum != mapper){
+                       printf("%s NES header mapper error\n", errorprefix);
+                       free(buf);
+                       return NG;
+               }
+       }
+       //NES/CPU/PPU imagesize check
+       long cpusize, ppusize;
+       {
+               long offset = NES_HEADER_SIZE;
+               //CPU
+               cpusize = ((long) buf[4]) * PROGRAM_ROM_MIN;
+               offset += cpusize;
+               if(nesfile_size_check(errorprefix, &r->cpu_rom, cpusize) == NG){
+                       free(buf);
+                       return NG;
+               }
+               //PPU
+               ppusize = ((long) buf[5]) * CHARCTER_ROM_MIN;
+               offset += ppusize;
+               if(ppusize != 0){
+                       if(nesfile_size_check(errorprefix, &r->ppu_rom, ppusize) == NG){
+                               free(buf);
+                               return NG;
+                       }
+               }
+               //NESfilesize
+               if(offset != imagesize){
+                       printf("%s NES header filesize error\n", errorprefix);
+                       free(buf);
+                       return NG;
+               }
+       }
+       /*
+       image pointer set/ memcpy
+       */
+       {
+               u8 *d;
+               d = buf;
+               d += NES_HEADER_SIZE;
+               nesfile_datapointer_set(d, &r->cpu_rom, cpusize);
+               d += cpusize;
+               if(ppusize != 0){
+                       nesfile_datapointer_set(d, &r->ppu_rom, ppusize);
+               }
+       }
+
+       free(buf);
+       return OK;
+}
+#endif
diff --git a/client/tag/0.5.3/header.h b/client/tag/0.5.3/header.h
new file mode 100644 (file)
index 0000000..f2c198f
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _HEADER_H_
+#define _HEADER_H_
+#include "flashmemory.h"
+struct memory{
+       const char *name;
+       int size, offset, attribute;
+       u8 *data;
+};
+/*
+ROM image Æâ struct memory ¤Î¥â¡¼¥ÉÊ̤λȤ¤Êý
+MODE_ROM_DUMP
+       cpu_rom ROM Æɤ߹þ¤ß¥Ð¥Ã¥Õ¥¡, file out
+       ppu_rom ROM Æɤ߹þ¤ß¥Ð¥Ã¥Õ¥¡, file out
+       cpu_ram Ì¤»ÈÍÑ
+MODE_RAM_READ
+       cpu_rom Ì¤»ÈÍÑ
+       ppu_rom Ì¤»ÈÍÑ
+       cpu_ram RAM Æɤ߹þ¤ß¥Ð¥Ã¥Õ¥¡. file out
+MODE_RAM_WRITE
+       cpu_rom Ì¤»ÈÍÑ
+       ppu_rom Ì¤»ÈÍÑ
+       cpu_ram RAM ½ñ¤­¹þ¤ß¥Ð¥Ã¥Õ¥¡. . file in
+MODE_ROM_PROGRAM
+       cpu_rom ROM ½ñ¤­¹þ¤ß¥Ð¥Ã¥Õ¥¡, file in
+       ppu_rom ROM ½ñ¤­¹þ¤ß¥Ð¥Ã¥Õ¥¡, file in
+       cpu_ram Ì¤»ÈÍÑ
+*/
+struct romimage{
+       struct memory cpu_rom, ppu_rom, cpu_ram;
+       struct flash_order cpu_flash, ppu_flash;
+       long mappernum;
+       int mirror, backupram;
+};
+
+enum{
+       MIRROR_HORIZONAL = 0,
+       MIRROR_VERTICAL,
+       MIRROR_PROGRAMABLE = MIRROR_HORIZONAL
+};
+enum{
+       MEMORY_AREA_CPU_RAM, MEMORY_AREA_CPU_ROM, MEMORY_AREA_PPU,
+       MEMORY_ATTR_READ, MEMORY_ATTR_WRITE, MEMORY_ATTR_NOTUSE
+};
+
+#ifdef HEADEROUT
+void nesheader_set(const struct romimage *r, u8 *header);
+#endif
+int nesbuffer_malloc(struct romimage *r, int mode);
+void nesfile_create(struct romimage *r, const char *romfilename);
+void nesbuffer_free(struct romimage *r, int mode);
+void backupram_create(const struct memory *r, const char *ramfilename);
+int memorysize_check(const long size, int region);
+int nesfile_load(const char *errorprefix, const char *file, struct romimage *r);
+#endif
diff --git a/client/tag/0.5.3/meg.ico b/client/tag/0.5.3/meg.ico
new file mode 100644 (file)
index 0000000..d2d452b
Binary files /dev/null and b/client/tag/0.5.3/meg.ico differ
diff --git a/client/tag/0.5.3/paralellport.h b/client/tag/0.5.3/paralellport.h
new file mode 100644 (file)
index 0000000..a33ad58
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+famicom ROM cartridge utility - unagi
+¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¶¦Í­ÄêµÁ
+*/
+#ifndef _PARALELL_PORT_INLINE_H_
+#define _PARALELL_PORT_INLINE_H_
+#include "giveio.h"
+#include <windows.h>
+#define ASM_ENABLE (0)
+enum{
+       PORT_DATA = 0x0378,
+       PORT_BUSY,
+       PORT_CONTROL
+};
+enum{
+       ADDRESS_MASK_A0toA12 = 0x1fff,
+       ADDRESS_MASK_A0toA14 = 0x7fff,
+       ADDRESS_MASK_A15 = 0x8000
+};
+enum{ 
+       M2_CONTROL_TRUE, M2_CONTROL_FALSE
+};
+
+int _inp(int);
+#if ASM_ENABLE==0
+void _outp(int, int);
+#else
+static inline void _outp(int address, int data){
+       asm(
+               " movl %0,%%edx\n"
+               " movl %1,%%eax\n"
+               " out %%al,%%dx\n"
+               :: "q"(address), "q"(data): "%edx", "%eax"
+       );
+}
+#endif
+
+/*
+static inline ¤Ï¶¦Í­¥Þ¥¯¥í°·¤¤
+*/
+static inline int bit_set(int data, const int bit)
+{
+       data |= 1 << bit;
+       return data;
+}
+
+static inline int bit_clear(int data, const int bit)
+{
+       data &= ~(1 << bit);
+       return data;
+}
+
+static inline void wait(long msec)
+{
+       if(msec == 0){
+               return;
+       }
+       //const long waittime = 100000;
+       Sleep(msec);
+}
+
+#endif
diff --git a/client/tag/0.5.3/profile/profile.mak b/client/tag/0.5.3/profile/profile.mak
new file mode 100644 (file)
index 0000000..3a9fb7f
--- /dev/null
@@ -0,0 +1,9 @@
+include ../file.mak
+CFLAGS += -O2 -pg -DDEBUG=0
+VPATH = ..
+$(TARGET): $(OBJ)
+       $(CC) -pg -o $@ $(OBJ)
+
+include ../rule.mak
+#---- depend file ----
+-include unagi.d
diff --git a/client/tag/0.5.3/reader_hongkongfc.c b/client/tag/0.5.3/reader_hongkongfc.c
new file mode 100644 (file)
index 0000000..09f37ac
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+famicom ROM cartridge utility - unagi
+hongkong FC driver
+
+Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+»ÅÍÍÉÔÌÀÍ×ÁÇ:
+  * 74138 ¤Î channel select ¤À¤¬¡¢¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤Î¥Ç¡¼¥¿¤ÎÊý¸þ¤òÊѹ¹¤¹¤ë¤È¡¢ÆÃÄê¤Î¥Á¥ã¥ó¥Í¥ë¤Î¥Ç¡¼¥¿¤¬Ç˲õ¤µ¤ì¤ë
+    * Ç˲õ¤µ¤ì¤ë¤¬¡¢Ç˲õÀ褬ÀßÄê¤Ç¤­¤ë¤é¤·¤¯¤½¤ì¤Ë¤·¤¿
+*/
+#include "type.h"
+#include "paralellport.h"
+#include "reader_master.h"
+#include "reader_hongkongfc.h"
+#include "hard_hongkongfc.h"
+
+enum{
+       PORT_CONTROL_MASK_XOR = 0x03, //bit01 invert
+       PORT_CONTROL_READ = 0,
+       PORT_CONTROL_WRITE
+};
+
+static inline int busy_get(void)
+{
+       int d = _inp(PORT_BUSY);
+       d >>= 7;
+       return d ^ 1;
+}
+
+static inline void port_control_write(int s, int rw)
+{
+       if(rw == PORT_CONTROL_READ){ 
+               //H:BUS->PC
+               s = bit_set(s, BITNUM_CONTROL_DIRECTION);
+       }else{
+               //L:PC->BUS
+               s = bit_clear(s, BITNUM_CONTROL_DIRECTION);
+       }
+       s = bit_clear(s, BITNUM_CONTROL_INTERRUPT);
+       s ^= PORT_CONTROL_MASK_XOR;
+       _outp(PORT_CONTROL, s);
+}
+
+static inline void data_port_latch(int select, long data)
+{
+       select <<= BITNUM_CONTROL_DATA_SELECT;
+       select = bit_set(select, BITNUM_CONTROL_DATA_LATCH);
+       port_control_write(select, PORT_CONTROL_WRITE);
+       _outp(PORT_DATA, data);
+       select = bit_clear(select, BITNUM_CONTROL_DATA_LATCH);
+       port_control_write(select, PORT_CONTROL_WRITE);
+}
+
+enum{ADDRESS_CPU_OPEN, ADDRESS_CPU_CLOSE};
+static inline void address_set(long address)
+{
+       long address_h = address >> 8;
+       long address_l = address & 0xff;
+       data_port_latch(DATA_SELECT_A15toA8, address_h);
+       data_port_latch(DATA_SELECT_A7toA0, address_l);
+}
+
+static inline u8 data_port_get(long address, int bus)
+{
+       address_set(address);
+       port_control_write(DATA_SELECT_BREAK_DATA << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
+       int s = DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT;
+       s = bit_set(s, BITNUM_CONTROL_DATA_LATCH);
+       port_control_write(s, PORT_CONTROL_READ);
+       return (u8) _inp(PORT_DATA);
+}
+
+/*
+ËÜÂΠA23-A16 port ¤Ë latch ¤µ¤»¤¿¤¢¤È¤Ë¡¢
+fc adapater ÆâÉô¤Ë¤µ¤é¤Ë latch ¤µ¤»¤ë¡£
+*/
+static void data_port_set(int c, long data)
+{
+       data_port_latch(DATA_SELECT_WRITEDATA, data);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       c = bit_set(c, BITNUM_WRITEDATA_LATCH);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+}
+
+// /A15 ¤À¤±¤ò»ÈÍѤ¹¤ë
+static const int BUS_CONTROL_CPU_READ = (
+       (1 << BITNUM_PPU_OUTPUT) |
+       (1 << BITNUM_PPU_RW) |
+       (1 << BITNUM_PPU_SELECT) |
+       (1 << BITNUM_WRITEDATA_OUTPUT) |
+       (0 << BITNUM_WRITEDATA_LATCH) |
+       (1 << BITNUM_CPU_M2) |
+       (1 << BITNUM_CPU_RW)
+);
+static const int BUS_CONTROL_PPU_READ = (
+       (0 << BITNUM_PPU_OUTPUT) |
+       (1 << BITNUM_PPU_RW) |
+       (0 << BITNUM_PPU_SELECT) |
+       (1 << BITNUM_WRITEDATA_OUTPUT) |
+       (0 << BITNUM_WRITEDATA_LATCH) |
+       (1 << BITNUM_CPU_M2) |
+       (1 << BITNUM_CPU_RW)
+);
+//static const int BUS_CONTROL_BUS_STANDBY = BUS_CONTROL_CPU_READ; //¥¨¥é¡¼¤Ë¤Ê¤ë
+#define BUS_CONTROL_BUS_STANDBY BUS_CONTROL_CPU_READ
+/*
+namcot ¤Î SRAM ÉÕ¥«¡¼¥È¥ê¥Ã¥¸¤Ï¦Õ2¤ò0x80²ó¾å¤²¤ë¤È½ÐÎϤ¬°ÂÄꤹ¤ë
+RAM ¥¢¥À¥×¥¿¤âƱÍÍ??
+ÉÔ°ÂÄê»þ¤Ï CPU ¤È PPU ¤Î data ¤¬º®¹ç¤µ¤ì¤Æ¤¤¤ëʪ¤¬¤Ç¤Æ¤¤¤ëµ¤¤¬¤¹¤ë
+*/
+static void hk_init(void)
+{
+       int c = BUS_CONTROL_CPU_READ;
+       int i = 0x80;
+       while(i != 0){
+               c = bit_set(c, BITNUM_CPU_M2);
+               data_port_latch(DATA_SELECT_CONTROL, c);
+               c = bit_clear(c, BITNUM_CPU_M2);
+               data_port_latch(DATA_SELECT_CONTROL, c);
+               i--;
+       }
+}
+
+static void hk_cpu_read(long address, long length, u8 *data)
+{
+       //fc bus ½é´ü²½
+       data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_CPU_READ);
+               //A15 ¤òȿž¤·¡¢ /ROMCS ¤Ë¤·¤¿¤â¤Î¤òÅϤ¹
+       address ^= ADDRESS_MASK_A15;
+       while(length != 0){
+               *data = data_port_get(address, BUS_CONTROL_CPU_READ);
+               address++;
+               data++;
+               length--;
+       }
+}
+
+static void hk_ppu_read(long address, long length, u8 *data)
+{
+       data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_PPU_READ);
+       address &= ADDRESS_MASK_A0toA12; //PPU charcter data area mask
+       address |= ADDRESS_MASK_A15; //CPU area disk
+       while(length != 0){
+               *data = data_port_get(address, BUS_CONTROL_PPU_READ);
+               address++;
+               data++;
+               length--;
+       }
+}
+
+static inline void cpu_romcs_set(long address)
+{
+       data_port_latch(DATA_SELECT_A15toA8, address >> 8);
+}
+
+static void hk_cpu_6502_write(long address, long data, long wait_msec)
+{
+       int c = BUS_CONTROL_BUS_STANDBY;
+       //Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       // /rom ¤ò H ¤Ë¤·¤Æ¥Ð¥¹¤ò»ß¤á¤ë
+       address_set(address | ADDRESS_MASK_A15);
+       
+       //¦Õ2 = L, R/W=L, address set, data set
+       c = bit_clear(c, BITNUM_CPU_M2);
+       data_port_set(c, data); //latch¤Ï¤³¤Î´Ø¿ôÆâÉô¤Ç¹Ô¤¦
+       if(address & ADDRESS_MASK_A15){
+               cpu_romcs_set(address & ADDRESS_MASK_A0toA14);
+       }
+       c = bit_clear(c, BITNUM_CPU_RW);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       wait(wait_msec);
+       //¦Õ2 = H, data out
+       c = bit_set(c, BITNUM_CPU_M2);
+       c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       wait(wait_msec);
+       //¦Õ2 = L, H ¤Ë¤¹¤ë¤Þ¤Ç R/W, address, Data ¤òÍ­¸ú¾õÂ֤ˤ¹¤ë
+       c = bit_clear(c, BITNUM_CPU_M2);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       wait(wait_msec);
+       //¦Õ2 = H, R/W = H, address disable, data out disable
+       if(address & ADDRESS_MASK_A15){
+               //address & ADDRESS_MASK_A15 ¤ÇÆ°¤¤¤Æ¤¿..?
+               cpu_romcs_set(address | ADDRESS_MASK_A15);
+       }
+       data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
+}
+
+//onajimi ¤À¤È /CS ¤È /OE ¤¬Æ±¤¸¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¬¡¢hongkong¤À¤È»ß¤á¤é¤ì¤ë¡£½ñ¤­¹þ¤ß»þ¤Ë output enable ¤Ï H ¤Ç¤¢¤ë¤Ù¤­¡£
+#include <stdio.h>
+static void hk_ppu_write(long address, long data)
+{
+       int c = BUS_CONTROL_BUS_STANDBY;
+       c = bit_clear(c, BITNUM_CPU_M2); //¤¿¤Ö¤ó¤¤¤ë
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       //cpu rom ¤ò»ß¤á¤¿¥¢¥É¥ì¥¹¤òÅϤ¹
+       address_set((address & ADDRESS_MASK_A0toA12) | ADDRESS_MASK_A15);
+       data_port_set(c, data); 
+       c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
+       //CS down
+       c = bit_clear(c, BITNUM_PPU_SELECT);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       //WE down
+       c = bit_clear(c, BITNUM_PPU_RW);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       //WE up
+       c = bit_set(c, BITNUM_PPU_RW);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       //CS up
+       data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
+}
+
+static const int FLASH_CPU_WRITE = (
+       (1 << BITNUM_PPU_OUTPUT) |
+       (1 << BITNUM_PPU_RW) |
+       (1 << BITNUM_PPU_SELECT) |
+       (1 << BITNUM_WRITEDATA_OUTPUT) |
+       (0 << BITNUM_WRITEDATA_LATCH) |
+       (0 << BITNUM_CPU_M2) |
+       (1 << BITNUM_CPU_RW)
+);
+
+static void hk_cpu_flash_write(long address, long data)
+{
+       int c = FLASH_CPU_WRITE;
+       //Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       address_set(address | ADDRESS_MASK_A15);
+       data_port_set(c, data);
+/*
+W29C020
+During the byte-load cycle, the addresses are latched by the falling 
+edge of either CE or WE,whichever occurs last. The data are latched 
+by the rising edge of either CE or WE, whicheveroccurs first.
+W49F002
+#CS or #WE ¤¬¹ß¤ê¤¿¤È¤­¤Ë address latch
+#CS or #WE ¤¬¾å¤¬¤Ã¤¿¤È¤­¤Ë data latch
+
+hongkong ·Ï¤Ï address ¤È /ROMCS ¤¬Æ±¤¸¥Ð¥¤¥È¤Ç¡¢ /CS À©¸æ¤Ë¤¹¤ë¤È
+hongkong ¥Ç¡¼¥¿Ç˲õ+¥¢¥É¥ì¥¹ÉÔ°ÂÄê¤Ë¤Ê¤ë¤Î¤Ç¡¢/WE À©¸æ¤Ë¤·¤Ê¤¤¤ÈÆ°¤«¤Ê¤¤¡£
+*/
+       c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
+       //CS down
+       cpu_romcs_set(address & ADDRESS_MASK_A0toA14);
+       //WE down
+       c = bit_clear(c, BITNUM_CPU_RW);
+//     c = bit_clear(c, BITNUM_CPU_M2);
+       data_port_latch(DATA_SELECT_CONTROL, c);
+       //WE up
+       data_port_latch(DATA_SELECT_CONTROL, FLASH_CPU_WRITE);
+       //CS up
+       cpu_romcs_set(address | ADDRESS_MASK_A15);
+}
+
+const struct reader_driver DRIVER_HONGKONGFC = {
+       .name = "hongkongfc",
+       .open_or_close = paralellport_open_or_close,
+       .init = hk_init,
+       .cpu_read = hk_cpu_read,
+       .ppu_read = hk_ppu_read,
+       .cpu_6502_write = hk_cpu_6502_write,
+       .ppu_write = hk_ppu_write,
+       .cpu_flash_write = hk_cpu_flash_write
+};
+
+#ifdef TEST
+#include "giveio.h"
+#include <stdio.h>
+#include <stdlib.h>
+static void data_show(u8 *d, int length)
+{
+       int sum = 0;
+       int offset = 0;
+       while(length != 0){
+               char safix;
+               switch(offset & 0xf){
+               default:
+                       safix = ' ';
+                       break;
+               case 7:
+                       safix = '-';
+                       break;
+               case 0xf:
+                       safix = '\n';
+                       break;
+               }
+               printf("%02x%c", *d, safix);
+               sum += *d;
+               d++;
+               offset++;
+               length--;
+       }
+       printf("sum 0x%06x", sum);
+}
+
+int main(int c, char **v)
+{
+       const int gg = giveio_start();
+       switch(gg){
+       case GIVEIO_OPEN:
+       case GIVEIO_START:
+       case GIVEIO_WIN95:
+               break;
+       default:
+       case GIVEIO_ERROR:
+               printf("Can't Access Direct IO %d\n", gg);
+               return 0;
+       }
+
+       long d = strtol(v[2], NULL, 0x10);
+
+       switch(v[1][0]){
+       case 'w':
+               data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
+               port_control_write(DATA_SELECT_WRITE << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
+               _outp(PORT_DATA, d);
+               break;
+       case 'c':
+               data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_CPU_READ);
+               address_set(d ^ ADDRESS_MASK_A15);
+               port_control_write(DATA_SELECT_BREAK_DATA << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
+               port_control_write(DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_READ);
+               printf("%02x\n", _inp(PORT_DATA));
+               break;
+       case 'C':{
+               const long length = 0x1000;
+               u8 data[length];
+               hk_cpu_read(d, length, data);
+               data_show(data, length);
+               }
+               break;
+       case 'p':
+               data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_PPU_READ);
+               address_set(d | ADDRESS_MASK_A15, ADDRESS_RESET);
+               port_control_write(DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_READ);
+               printf("%02x\n", _inp(PORT_DATA));
+               break;
+       case 'P':{
+               const long length = 0x200;
+               u8 data[length];
+               hk_ppu_read(d, length, data);
+               data_show(data, length);
+               }
+               break;
+       }
+       
+       if(gg != GIVEIO_WIN95){
+               giveio_stop(GIVEIO_STOP);
+       }
+       return 0;
+}
+#endif
diff --git a/client/tag/0.5.3/reader_hongkongfc.h b/client/tag/0.5.3/reader_hongkongfc.h
new file mode 100644 (file)
index 0000000..c568bce
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _READER_HONGKONGFC_H_
+#define _READER_HONGKONGFC_H_
+const struct reader_driver DRIVER_HONGKONGFC;
+#endif
diff --git a/client/tag/0.5.3/reader_master.c b/client/tag/0.5.3/reader_master.c
new file mode 100644 (file)
index 0000000..1a8e4c8
--- /dev/null
@@ -0,0 +1,50 @@
+#include <assert.h>
+#include <string.h>
+#include "giveio.h"
+#include "reader_master.h"
+#include "reader_onajimi.h"
+#include "reader_hongkongfc.h"
+
+//¤³¤ì¤ò rodata ¤Ë¤·¤¿¤¤¤±¤É const ¤ÎÉÕ¤±Êý¤¬Ê¬¤«¤é¤ó
+static const struct reader_driver *DRIVER_LIST[] = {
+       &DRIVER_ONAJIMI, &DRIVER_HONGKONGFC,
+       NULL
+};
+
+int paralellport_open_or_close(int oc)
+{
+       static int giveio_status;
+       if(oc == READER_OPEN){
+               giveio_status = giveio_start();
+               switch(giveio_status){
+               case GIVEIO_OPEN:
+               case GIVEIO_START:
+               case GIVEIO_WIN95:
+                       break;
+               default:
+               case GIVEIO_ERROR:
+                       //printf("%s Can't Access Direct IO %d\n", __FILE__, giveio_status);
+                       return NG;
+               }
+       }else if(oc == READER_CLOSE){
+               if(giveio_status != GIVEIO_WIN95){
+                       giveio_stop(GIVEIO_STOP);
+               }
+       }else{
+               assert(0);
+       }
+       return OK;
+}
+
+const struct reader_driver *reader_driver_get(const char *name)
+{
+       const struct reader_driver **d;
+       d = DRIVER_LIST;
+       while(*d != NULL){
+               if(strcmp(name, (*d)->name) == 0){
+                       return *d;
+               }
+               d++;
+       }
+       return NULL;
+}
diff --git a/client/tag/0.5.3/reader_master.h b/client/tag/0.5.3/reader_master.h
new file mode 100644 (file)
index 0000000..d39bcca
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _READER_MASTER_H_
+#define _READER_MASTER_H_
+#include "type.h"
+//C++ ¤Î Class ¤â¤É¤­¤ò C ¤Ç¼ÂÁõ¤·¤Æ¤¤¤ë´¶¤¬Áý¤·¤Æ¤­¤¿...
+struct reader_driver{
+       int (*open_or_close)(int oc);
+       void (*init)(void);
+       void (*cpu_read)(long address, long length, u8 *data);
+       void (*ppu_read)(long address, long length, u8 *data);
+       void (*cpu_6502_write)(long address, long data, long wait_msec);
+       void (*cpu_flash_write)(long address, long data);
+       void (*ppu_write)(long address, long data);
+       const char *name;
+};
+int paralellport_open_or_close(int oc);
+const struct reader_driver *reader_driver_get(const char *name);
+enum{
+       READER_OPEN, READER_CLOSE
+};
+#endif
diff --git a/client/tag/0.5.3/reader_onajimi.c b/client/tag/0.5.3/reader_onajimi.c
new file mode 100644 (file)
index 0000000..703b42b
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+famicom ROM cartridge utility - unagi
+emuste.net ¤Ç¤ª¤Ê¤¸¤ß¤Î¤â¤Î¤Î¥Ï¡¼¥É¥É¥é¥¤¥Ð
+
+Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+memo:
+* -O0 ¤Ê¤é inline asm ¤Ç¤âÈ¿±þ¤Ç¤­¤ë¤¬¡¢-O2 ¤À¤ÈÆ°¤«¤Ê¤¤
+ * Í½ÁÛ¤ËÈ¿¤·¤Æ out ¤ÏÆ°¤¯¤¬¡¢ in ¤Ë wait ¤¬É¬Íפߤ¿¤¤
+* gcc ¤Î¥¢¥»¥ó¥Ö¥é¤Ï x86 ¤Ç¤¢¤í¤¦¤È src,dst ¤Î½ç¤Çȿž¤·¤Æ¤¤¤ë
+* http://download.intel.com/jp/developer/jpdoc/IA32_Arh_Dev_Man_Vol2A_i.pdf
+ * out,in ¤Î¥¢¥É¥ì¥¹¤Ë dx ¤ò»È¤ï¤Ê¤¤¤È 8bit ¥¢¥É¥ì¥¹¤Ë¤Ê¤ë
+ * out,in ¤Î¥Ç¡¼¥¿¤Ï¥ì¥¸¥¹¥¿¤Ç¥Ç¡¼¥¿Éý¤¬ÊѤï¤ë al:8bit, ax:16bit, eax:32bit
+*/
+#include "type.h"
+#include "paralellport.h"
+#include "hard_onajimi.h"
+#include "reader_master.h"
+#include "reader_onajimi.h"
+
+static inline void bus_control(int data)
+{
+#if ASM_ENABLE==0
+       _outp(PORT_DATA, data);
+#else
+       asm(
+               " movl %0,%%edx\n"
+               " movl %1,%%eax\n"
+               " out %%al,%%dx\n"
+               :: "i"(PORT_DATA), "q"(data): "%edx", "%eax"
+       );
+#endif
+}
+
+/*
+CONTROL bit0 STROBE
+¥Ç¡¼¥¿¤¬È¿Å¾¤¹¤ë
+*/
+static inline void address_control(int data)
+{
+       data &= 0x01;
+       data ^= 0x01;
+#if ASM_ENABLE==0
+       _outp(PORT_CONTROL, data);
+#else
+       asm(
+               " movl %0,%%edx\n"
+               " movl %1,%%eax\n"
+               " out %%al,%%dx\n"
+               :: "i"(PORT_CONTROL), "q"(data): "%edx", "%eax"
+       );
+#endif
+}
+
+/* address control data & function */
+static long past_address = 0;
+
+static void address_reset(void)
+{
+       address_control(ADDRESS_RESET);
+       address_control(ADDRESS_ENABLE);
+       past_address = 0;
+}
+
+/*
+H->L ¤Çaddressincrement
+*/
+static inline void address_increment(int data)
+{
+       data = bit_set(data, BITNUM_ADDRESS_INCREMENT);
+       bus_control(data);
+
+       data = bit_clear(data, BITNUM_ADDRESS_INCREMENT);
+       bus_control(data);
+       past_address += 1;
+       past_address &= ADDRESS_MASK_A0toA14;
+}
+
+static void address_set(long address, int control)
+{
+       address &= ADDRESS_MASK_A0toA14;
+       long increment_count = address - past_address;
+       if(increment_count < 0){
+               address_reset();
+               increment_count = address;
+       }
+               
+       while(increment_count != 0){
+               address_increment(control);
+               increment_count -= 1;
+       }
+}
+
+/*
+STATUS bit7 BUSY
+¥Ç¡¼¥¿¤¬È¿Å¾¤¹¤ë
+*/
+static inline int data_bit_get(void)
+{
+#if ASM_ENABLE==1
+       int data;
+       asm(
+               " xorl %%eax,%%eax\n"
+               " movl %1,%%edx\n"
+               " in %%dx,%%al\n"
+               " movl %%eax,%0"
+               :"=q"(data) : "i"(PORT_BUSY) :"%edx", "%eax"
+       );
+#else
+       int data = _inp(PORT_BUSY);
+#endif
+       data >>= 7;
+       data &= 0x01;
+       return data ^ 0x01;
+}
+
+/* 
+L->H ¤Çshift 
+*/
+static inline void data_shift(int control)
+{
+       control = bit_clear(control, BITNUM_DATA_SHIFT_RIGHT);
+       bus_control(control);
+       control = bit_set(control, BITNUM_DATA_SHIFT_RIGHT);
+       bus_control(control);
+}
+
+/*ºÇ¾å°Ìbit¤«¤é½çÈ֤ˤȤë*/
+static u8 data_get(int control)
+{
+       int data = 0;
+       int i;
+       //fcbus 8bit data load, shift count reset
+       control = bit_set(control, BITNUM_DATA_DIRECTION);
+       data_shift(control);
+       //shift mode
+       control = bit_clear(control, BITNUM_DATA_DIRECTION);
+       bus_control(control);
+       for(i = 0; i < 8; i++){
+               data |= (data_bit_get() << i);
+               data_shift(control);
+       }
+       return (u8) data;
+}
+
+//¤³¤³¤Î data ¤Ï 0 or 1
+static inline int writedata_set(long data)
+{
+       data &= 1;
+       return data << BITNUM_DATA_WRITE_DATA;
+}
+
+static void data_set(int control, long data)
+{
+       int i;
+       for(i = 0; i < 8; i++){
+               control = bit_clear(control, BITNUM_DATA_WRITE_DATA);
+               control |= writedata_set(data >> i);
+               bus_control(control);
+               data_shift(control);
+       }
+}
+
+static const int BUS_CONTROL_INIT = (
+       ADDRESS_NOP | DATA_SHIFT_NOP |
+       (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
+       (PPU_DISABLE << BITNUM_PPU_SELECT) |
+       (PPU_WRITE__CPU_DISABLE << BITNUM_CPU_M2) |
+       (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
+       (CPU_READ << BITNUM_CPU_RW)
+);
+static void reader_init(void)
+{
+       int c = BUS_CONTROL_INIT;
+       int i = 0x80;
+       bus_control(c);
+       address_reset();
+       /*
+       namcot bus °ÂÄê½èÃÖ
+       reader_hongkong »²¾È
+       */
+       while(i != 0){
+               c = bit_set(c, BITNUM_CPU_M2);
+               bus_control(c);
+               c = bit_clear(c, BITNUM_CPU_M2);
+               bus_control(c);
+               i--;
+       }
+}
+
+static const int BUS_CONTROL_CPU_READ = (
+       ADDRESS_NOP | DATA_SHIFT_NOP |
+       (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
+       (PPU_DISABLE << BITNUM_PPU_SELECT) |
+       (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) | //H
+       (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
+       (CPU_READ << BITNUM_CPU_RW)
+);
+
+static const int BUS_CONTROL_PPU_READ = (
+       ADDRESS_NOP | DATA_SHIFT_NOP |
+       (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
+       (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) |
+       (PPU_ENABLE << BITNUM_PPU_SELECT) |
+       (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
+       (CPU_READ << BITNUM_CPU_RW)
+);
+
+static const int BUS_CONTROL_BUS_WRITE = (
+       ADDRESS_NOP | DATA_SHIFT_NOP |
+       (DATA_DIRECTION_WRITE << BITNUM_DATA_DIRECTION) |
+       (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) |
+       (PPU_DISABLE << BITNUM_PPU_SELECT) |
+       (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
+       (CPU_READ << BITNUM_CPU_RW)
+);
+
+static void fc_bus_read(long address, long length, u8 *data, int control, int m2_control)
+{
+       address_set(address, control);
+       if(m2_control == M2_CONTROL_TRUE){
+               control = bit_clear(control, BITNUM_CPU_M2);
+               bus_control(control); //H->L: mapper ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
+       }
+       while(length != 0){
+               if(m2_control == M2_CONTROL_TRUE){
+                       //L->H: mapper ¤¬ data ¤ò½Ð¤¹
+                       control = bit_set(control, BITNUM_CPU_M2);
+               }
+               *data = data_get(control);
+               if(m2_control == M2_CONTROL_TRUE){
+                       //H->L: ¤ª¤ä¤¹¤ß
+                       control = bit_clear(control, BITNUM_CPU_M2);
+                       bus_control(control);
+                       //L->H: increment
+                       control = bit_set(control, BITNUM_CPU_M2);
+               }
+               address_increment(control);
+
+               if(m2_control == M2_CONTROL_TRUE){
+                       //H->L: mapper ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
+                       control = bit_clear(control, BITNUM_CPU_M2);
+                       bus_control(control);
+               }
+
+               data++;
+               length--;
+       }
+       control = bit_set(control, BITNUM_CPU_M2);
+}
+
+static void cpu_read(long address, long length, u8 *data)
+{
+       int control = BUS_CONTROL_CPU_READ;
+       if(address & ADDRESS_MASK_A15){
+               control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
+       }
+       fc_bus_read(address, length, data, control, M2_CONTROL_TRUE);
+}
+
+static void ppu_read(long address, long length, u8 *data)
+{
+       fc_bus_read(address, length, data, BUS_CONTROL_PPU_READ, M2_CONTROL_FALSE);
+}
+/*
+6502 write cycle
+t   |01234
+----+-----
+¦Õ2 |HLHLH
+/ROM|HHxxH
+R/W |HHLLH
+
+0 H bus:addressset
+1 H->L bus:data set, mapper:address get
+2 L->H bus:data write
+3 H->L mapper: data write enable
+4 L->H mapper: data get, bus:close
+
+H:1, L:0, x:ROMareaaccess»þ0, ¤½¤ì°Ê³°1
+*/
+static void cpu_6502_write(long address, long data, long wait_msec)
+{
+       int control = BUS_CONTROL_BUS_WRITE;
+       //addressÀßÄê + Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
+       address_set(address, control);
+
+       //¦Õ2 = L, R/W=L, data set, dataout
+       control = bit_clear(control, BITNUM_CPU_M2);
+       data_set(control, data);
+       control = bit_clear(control, BITNUM_CPU_RW);
+       bus_control(control);
+       if(address & ADDRESS_MASK_A15){
+               control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
+       }
+       wait(wait_msec);
+       
+       //¦Õ2 = H, data out
+       control = bit_set(control, BITNUM_CPU_M2);
+       bus_control(control);
+       wait(wait_msec);
+       //¦Õ2 = L, H ¤Ë¤¹¤ë¤Þ¤Ç R/W, address, Data ¤òÍ­¸ú¾õÂ֤ˤ¹¤ë
+       control = bit_clear(control, BITNUM_CPU_M2);
+       bus_control(control);
+       wait(wait_msec);
+       //¦Õ2 = H, R/W = H, address disable, data out disable
+       bus_control(BUS_CONTROL_BUS_WRITE);
+}
+
+static void ppu_write(long address, long data)
+{
+       int control = BUS_CONTROL_BUS_WRITE;
+
+       address_set(address, control);
+       bus_control(control);
+       data_set(control, data);
+       control = bit_clear(control, BITNUM_PPU_RW);
+       control = bit_clear(control, BITNUM_PPU_SELECT);
+       bus_control(control);
+       bus_control(BUS_CONTROL_BUS_WRITE);
+}
+
+static const int BUS_CONTROL_CPU_FLASH_WRITE = (
+       ADDRESS_NOP | DATA_SHIFT_NOP |
+       (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
+       (PPU_DISABLE << BITNUM_PPU_SELECT) |
+       (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) | //H
+       (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
+       (CPU_READ << BITNUM_CPU_RW)
+);
+
+static void cpu_flash_write(long address, long data)
+{
+       int control = BUS_CONTROL_BUS_WRITE;
+       control = bit_clear(control, BITNUM_CPU_M2);
+       address_set(address, control);
+       
+       //WE down
+       control = bit_clear(control, BITNUM_CPU_RW);
+       data_set(control, data);
+       //CS down
+       control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
+       bus_control(control);
+       //CS up
+       control = bit_set(control, BITNUM_CPU_RAMROM_SELECT);
+       bus_control(control);
+       //WE up
+       control = bit_set(control, BITNUM_CPU_RW);
+       bus_control(control);
+}
+
+const struct reader_driver DRIVER_ONAJIMI = {
+       .name = "onajimi",
+       .open_or_close = paralellport_open_or_close,
+       .init = reader_init,
+       .cpu_read = cpu_read,
+       .ppu_read = ppu_read,
+       .cpu_6502_write = cpu_6502_write,
+       .cpu_flash_write = cpu_flash_write,
+       .ppu_write = ppu_write
+};
diff --git a/client/tag/0.5.3/reader_onajimi.h b/client/tag/0.5.3/reader_onajimi.h
new file mode 100644 (file)
index 0000000..6e67b47
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _READER_ONAJIMI_H_
+#define _READER_ONAJIMI_H_
+const struct reader_driver DRIVER_ONAJIMI;
+#endif
diff --git a/client/tag/0.5.3/release/release.mak b/client/tag/0.5.3/release/release.mak
new file mode 100644 (file)
index 0000000..9ca2830
--- /dev/null
@@ -0,0 +1,10 @@
+include ../file.mak
+CFLAGS += -O2 -DDEBUG=0 -DNDEBUG -fomit-frame-pointer 
+VPATH = ..
+$(TARGET): $(OBJ)
+       $(CC) -o $@ $(OBJ)
+       strip $@
+
+include ../rule.mak
+#---- depend file ----
+-include unagi.d
diff --git a/client/tag/0.5.3/rule.mak b/client/tag/0.5.3/rule.mak
new file mode 100644 (file)
index 0000000..89ab0dc
--- /dev/null
@@ -0,0 +1,8 @@
+all: $(TARGET) unagi.d
+unagi.d:
+       $(CC) -MM $(CFLAGS) ../*.c > $@
+clean: 
+       rm -f $(OBJ) $(TARGET) unagi.d
+unagi.res.o: unagi.rc unagi.ico
+       windres -I.. -i $< -o $@
+all: $(TARGET) unagi.d
diff --git a/client/tag/0.5.3/script.c b/client/tag/0.5.3/script.c
new file mode 100644 (file)
index 0000000..277a857
--- /dev/null
@@ -0,0 +1,1373 @@
+/*
+famicom ROM cartridge utility - unagi
+script engine
+
+Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+todo: 
+* ÊÑ¿ô´ÉÍý¤Î¥°¥í¡¼¥Ð¥ëÃͤò¡¢logical_test(), excute() ¥í¡¼¥«¥ë¤Ë¤·¤¿¤¤
+*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "type.h"
+#include "file.h"
+#include "reader_master.h"
+#include "textutil.h"
+#include "config.h"
+#include "header.h"
+#include "script.h"
+
+/*
+MAPPER num
+MIRROR [HV]
+CPU_ROMSIZE num
+CPU_RAMSIZE num
+PPU_ROMSIZE num
+DUMP_START
+CPU_READ address size
+CPU_WRITE address data -> ÊÑ¿ôŸ³«+±é»»»Ò»ÈÍѲÄǽ
+PPU_READ address size
+STEP_START variable start end step -> for(i=start;i<end;i+=step)
+STEP_END
+DUMP_END
+*/
+#include "syntax.h"
+
+//ÊÑ¿ô´ÉÍý
+struct variable_manage{
+       char name;
+       long start,end,step;
+       long val;
+       const struct script *Continue;
+};
+
+enum{
+       STEP_MAX = 2,
+       VARIABLE_MAX = STEP_MAX
+};
+
+static const struct variable_manage VARIABLE_INIT = {
+       .name = '\0', 
+       .start = 0, .end = 0, .step = 0,
+       .val = 0,
+       .Continue = NULL
+};
+static struct variable_manage variable_bank[VARIABLE_MAX];
+static int variable_num = 0;
+
+static void variable_init_single(int num)
+{
+       memcpy(&variable_bank[num], &VARIABLE_INIT, sizeof(struct variable_manage));
+}
+
+static void variable_init_all(void)
+{
+       int i;
+       variable_num = 0;
+       for(i = 0; i < VARIABLE_MAX; i++){
+               variable_init_single(i);
+       }
+}
+
+static int variable_get(char name, long *val)
+{
+       int i;
+       struct variable_manage *v;
+       v = variable_bank;
+       for(i = 0; i < variable_num; i++){
+               if(v->name == name){
+                       *val = v->val;
+                       return OK;
+               }
+               v++;
+       }
+       return NG;
+}
+
+//ÊÑ¿ôŸ³«
+static int expression_calc(const struct st_expression *e, long *val)
+{
+       long left, right;
+       if(e->left.type == EXPRESSION_TYPE_VARIABLE){
+               if(variable_get(e->left.variable, &left) == NG){
+                       return NG;
+               }
+       }else{
+               left = e->left.value;
+       }
+       if(e->operator == OPERATOR_NONE){
+               *val = left;
+               return OK;
+       }
+       if(e->right.type == EXPRESSION_TYPE_VARIABLE){
+               if(variable_get(e->right.variable, &right) == NG){
+                       return NG;
+               }
+       }else{
+               right = e->right.value;
+       }
+       switch(e->operator){
+       case OPERATOR_PLUS:
+               *val = left + right;
+               break;
+       case OPERATOR_SHIFT_LEFT:
+               *val = left >> right;
+               //*val &= 1;
+               break;
+       case OPERATOR_SHIFT_RIGHT:
+               *val = left << right;
+               break;
+       case OPERATOR_AND:
+               *val = left & right;
+               break;
+       case OPERATOR_OR:
+               *val = left | right;
+               break;
+       case OPERATOR_XOR:
+               *val = left ^ right;
+               break;
+       }
+       
+       return OK;
+}
+
+static int step_new(char name, long start, long end, long step, const struct script *Continue)
+{
+       if(variable_num >= VARIABLE_MAX){
+               return NG; //ÊÑ¿ôÄêµÁ¤¬Â¿¤¹¤®
+       }
+       struct variable_manage *v;
+       int i;
+       v = variable_bank;
+       for(i = 0; i < variable_num; i++){
+               if(v->name == name){
+                       return NG; //ÊÑ¿ô̾½ÅÊ£
+               }
+               v++;
+       }
+       v = variable_bank;
+       v += variable_num;
+       v->name = name;
+       v->start = start;
+       v->end = end;
+       v->step = step;
+       v->val = start;
+       v->Continue = Continue;
+       variable_num++;
+       return OK;
+}
+
+static const struct script *step_end(const struct script *Break)
+{
+       //¸½ºß¤Î¥ë¡¼¥×¤ÎÂоÝÊÑ¿ô¤òÆÀ¤ë
+       struct variable_manage *v;
+       v = variable_bank;
+       v += (variable_num - 1);
+       //ÊÑ¿ô¹¹¿·
+       v->val += v->step;
+       if(v->val < v->end){
+               return v->Continue;
+       }
+       //¥ë¡¼¥×¤¬½ª¤ï¤Ã¤¿¤Î¤Ç¤½¤ÎÊÑ¿ô¤òÇË´þ¤¹¤ë
+       variable_init_single(variable_num - 1);
+       variable_num--;
+       return Break;
+}
+
+static int syntax_check_expression(char **word, int word_num, struct st_expression *e)
+{
+       if(word_num == 0){
+               return NG;
+       }
+       //left
+       if(value_get(word[0], &(e->left.value)) == OK){
+               e->left.type = EXPRESSION_TYPE_VALUE;
+       }else{
+               e->left.type = EXPRESSION_TYPE_VARIABLE;
+               e->left.variable = word[0][0];
+       }
+       word_num--;
+       if(word_num == 0){
+               e->operator = OPERATOR_NONE;
+               return OK;
+       }
+       //operator
+       e->operator = operator_get(word[1]);
+       if(e->operator == OPERATOR_ERROR){
+               return NG;
+       }
+       word_num--;
+       if(word_num == 0){
+               return NG;
+       }
+       //right
+       if(value_get(word[2], &(e->right.value)) == OK){
+               e->right.type = EXPRESSION_TYPE_VALUE;
+       }else{
+               e->right.type = EXPRESSION_TYPE_VARIABLE;
+               e->right.variable = word[2][0];
+       }
+       return OK;
+}
+
+static const char SYNTAX_ERROR_PREFIX[] = "syntax error:";
+
+/*
+return: error count, ¤³¤³¤Ç¤Ï 0 or 1
+*/
+static int syntax_check_phase(char **word, int word_num, struct script *s, const int mode)
+{
+       int i = sizeof(SCRIPT_SYNTAX) / sizeof(SCRIPT_SYNTAX[0]);
+       const struct script_syntax *syntax;
+       syntax = SCRIPT_SYNTAX;
+       while(i != 0){
+               if(strcmp(syntax->name, word[0]) == 0){
+                       int j;
+                       
+                       s->opcode = syntax->script_opcode;
+                       if((mode & syntax->permittion) == 0){
+                               printf("%s opcode %s not allowed on current mode\n", SYNTAX_ERROR_PREFIX, syntax->name);
+                               return 1;
+                       };
+                       {
+                               int compare = 0;
+                               switch(syntax->compare){
+                               case SYNTAX_COMPARE_EQ:
+                                       compare = (syntax->argc == (word_num - 1));
+                                       break;
+                               case SYNTAX_COMPARE_GT:
+                                       compare = (syntax->argc <= (word_num - 1));
+                                       break;
+                               }
+                               if(!compare){
+                                       printf("%s parameter number not much %s\n", SYNTAX_ERROR_PREFIX, word[0]);
+                                       return 1;
+                               }
+                       }
+                       for(j = 0; j < syntax->argc; j++){
+                               switch(syntax->argv_type[j]){
+                               case SYNTAX_ARGVTYPE_NULL:
+                                       printf("%s ARGV_NULL select\n", SYNTAX_ERROR_PREFIX);
+                                       return 1;
+                               case SYNTAX_ARGVTYPE_VALUE:
+                                       if(value_get(word[j + 1], &(s->value[j])) == NG){
+                                               printf("%s value error %s %s\n", SYNTAX_ERROR_PREFIX, word[0], word[j+1]);
+                                               return 1;
+                                       }
+                                       break;
+                               case SYNTAX_ARGVTYPE_HV:
+                                       switch(word[j + 1][0]){
+                                       case 'H':
+                                       case 'h':
+                                               s->value[j] = MIRROR_HORIZONAL;
+                                               break;
+                                       case 'V':
+                                       case 'v':
+                                               s->value[j] = MIRROR_VERTICAL;
+                                               break;
+                                       case 'A':
+                                       case 'a':
+                                               s->value[j] = MIRROR_PROGRAMABLE;
+                                               break;
+                                       default:
+                                               printf("%s unknown scroll mirroring type %s\n", SYNTAX_ERROR_PREFIX, word[j+1]);
+                                               return 1;
+                                       }
+                                       break;
+                               case SYNTAX_ARGVTYPE_EXPRESSION:
+                                       s->value[j] = VALUE_EXPRESSION;
+                                       //Ì¿Îá̾¤Îñ¸ì¤Èñ¸ì¿ô¤ò½ü³°¤·¤ÆÅϤ¹
+                                       if(syntax_check_expression(&word[j+1], word_num - 2, &s->expression) == NG){
+                                               printf("%s expression error\n", SYNTAX_ERROR_PREFIX);
+                                               return 1;
+                                       }
+                                       //²ÄÊѤ˰ú¿ô¤ò¼è¤ë¤Î¤Ç¤³¤³¤Ç½ª¤ï¤ê
+                                       return 0;
+                               case SYNTAX_ARGVTYPE_VARIABLE:{
+                                       const char v = word[j+1][0];
+                                       if((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')){
+                                               s->value[j] = VALUE_VARIABLE;
+                                               s->variable = v;
+                                       }else{
+                                               printf("%s variable must use [A-Za-z] %s\n", SYNTAX_ERROR_PREFIX, word[j+1]);
+                                               return 1;
+                                       }
+                                       }break;
+                               }
+                       }
+                       //opcode found and ÆþÎÏʸ»ú¼ïÀµ¾ï
+                       return 0;
+               }
+               syntax++;
+               i--;
+       }
+       printf("%s unknown opcode %s\n", SYNTAX_ERROR_PREFIX, word[0]);
+       return 1;
+}
+
+/*
+return: error count
+*/
+static int syntax_check(char **text, int text_num, struct script *s, int mode)
+{
+       int error = 0;
+       int i;
+       mode = 1<< mode; //permittion ¤Ï bitflag ¤Ê¤Î¤Ç¤³¤³¤ÇÊÑ´¹¤¹¤ë
+       variable_init_all();
+       for(i = 0; i < text_num; i++){
+               char *word[TEXT_MAXWORD];
+               const int n = word_load(text[i], word);
+               if(word[0][0] == '#'){
+                       s->opcode = SCRIPT_OPCODE_COMMENT;
+               }else{
+                       error += syntax_check_phase(word, n, s, mode);
+               }
+               s++;
+       }
+       return error;
+}
+
+/*
+logical_check() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
+*/
+static const char LOGICAL_ERROR_PREFIX[] = "logical error:";
+
+static inline void logical_print_illgalarea(const char *area, long address)
+{
+       printf("%s illgal %s area $%06x\n", LOGICAL_ERROR_PREFIX, area, (int) address);
+}
+
+static inline void logical_print_illgallength(const char *area, long length)
+{
+       printf("%s illgal %s length $%04x\n", LOGICAL_ERROR_PREFIX, area, (int) length);
+}
+
+static inline void logical_print_overdump(const char *area, long start, long end)
+{
+       printf("%s %s area over dump $%06x-$%06x\n", LOGICAL_ERROR_PREFIX, area, (int)start ,(int)end);
+}
+
+static inline void logical_print_access(const char *area, const char *rw, long addr, long len)
+{
+       printf("%s %s $%04x $%02x\n", area, rw, (int) addr, (int) len);
+}
+
+static inline void logical_print_byteerror(const char *area, long data)
+{
+       printf("%s write data byte range over, %s $%x\n", LOGICAL_ERROR_PREFIX, area, (int) data);
+}
+
+static int dump_length_conform(const char *name, long logicallength, long configlength)
+{
+       if(configlength != logicallength){
+               printf("%s %s dump length error\n", LOGICAL_ERROR_PREFIX, name);
+               printf("%s: 0x%06x, dump length: 0x%06x\n", name, (int) configlength, (int) logicallength);
+               return 1;
+       }
+       return 0;
+}
+static inline int is_region_cpurom(long address)
+{
+       return (address >= 0x8000) && (address < 0x10000);
+}
+
+static inline int is_region_cpuram(long address)
+{
+       return (address >= 0x6000) && (address < 0x8000);
+}
+
+static inline int is_region_ppurom(long address)
+{
+       return (address >= 0) && (address < 0x2000);
+}
+
+static inline int is_data_byte(long data)
+{
+       return (data >= 0) && (data < 0x100);
+}
+
+//¤³¤ì¤À¤± is ·Ï¤Ç <= ±é»»»Ò¤ò»ÈÍѤ·¤Æ¤¤¤ë¤Î¤ÇÃí°Õ
+static inline int is_range(long data, long start, long end)
+{
+       return (data >= start) && (data <= end);
+}
+static const char STR_REGION_CPU[] = "cpu";
+static const char STR_REGION_PPU[] = "ppu";
+static const char STR_ACCESS_READ[] = "read";
+static const char STR_ACCESS_WRITE[] = "write";
+
+enum{
+       SETTING, DUMP, END
+};
+static int command_mask(const int region, const long address, const long offset, long size, struct flash_order *f)
+{
+       const char *str_region = STR_REGION_CPU;
+       if(region == MEMORY_AREA_PPU){
+               str_region = STR_REGION_PPU;
+       }
+       switch(region){
+       case MEMORY_AREA_CPU_ROM:
+               switch(offset){
+               case 0x8000: case 0xa000: case 0xc000:
+                       break;
+               default:
+                       printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
+                       return NG;
+               }
+               switch(size){
+               case 0x2000: case 0x4000: case 0x8000:
+                       break;
+               default:
+                       printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
+                       return NG;
+               }
+               break;
+       case MEMORY_AREA_PPU:
+               switch(offset){
+               case 0x0000: case 0x0400: case 0x0800: case 0x0c00:
+               case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
+                       break;
+               default:
+                       printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
+                       return NG;
+               }
+               switch(size){
+               case 0x0400: case 0x0800: case 0x1000: case 0x2000: 
+                       break;
+               default:
+                       printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
+                       return NG;
+               }
+               break;
+       default:
+               assert(0); //unknown memory area
+       }
+
+       const long mask = size - 1;
+       const long data = (address & mask) | offset;
+       switch(address){
+       case 0:
+               f->command_0000 = data;
+               break;
+       case 0x2aaa: case 0x02aa: 
+               f->command_2aaa = data;
+               break;
+       case 0x5555: case 0x0555:
+               f->command_5555 = data;
+               break;
+       default:
+               printf("%s %s_COMMAND unknown commnand address\n", LOGICAL_ERROR_PREFIX, str_region);
+               return NG;
+       }
+       return OK;
+}
+
+static int logical_check(const struct script *s, const struct st_config *c, struct romimage *r)
+{
+       long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
+       int imagesize = 0; //for write or program mode
+       int setting = SETTING;
+       int error = 0;
+       
+       variable_init_all();
+       while(s->opcode != SCRIPT_OPCODE_DUMP_END){
+               //printf("opcode exec %s\n", SCRIPT_SYNTAX[s->opcode].name);
+               if((setting == DUMP) && (s->opcode < SCRIPT_OPCODE_DUMP_START)){
+                       printf("%s config script include DUMPSTART area\n", LOGICAL_ERROR_PREFIX);
+                       error += 1;
+               }
+
+               //romimage open for write or program mode
+               if((imagesize == 0) && (setting == DUMP)){
+                       switch(c->mode){
+                       case MODE_RAM_WRITE:
+                               assert(r->cpu_ram.attribute == MEMORY_ATTR_READ);
+                               r->cpu_ram.data = buf_load_full(c->ramimage, &imagesize);
+                               if(r->cpu_ram.data == NULL){
+                                       printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
+                                       imagesize = -1;
+                                       error += 1;
+                               }else if(r->cpu_ram.size != imagesize){
+                                       printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
+                                       free(r->cpu_ram.data);
+                                       r->cpu_ram.data = NULL;
+                                       imagesize = -1;
+                                       error += 1;
+                               }
+                               break;
+                       case MODE_ROM_PROGRAM:
+                               assert(c->cpu_flash_driver->write != NULL);
+                               assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
+                               assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
+                               if(nesfile_load(LOGICAL_ERROR_PREFIX, c->romimage, r)== NG){
+                                       error += 1;
+                               }
+                               imagesize = -1;
+                               break;
+                       default: 
+                               imagesize = -1;
+                               break;
+                       }
+               }
+       
+               switch(s->opcode){
+               case SCRIPT_OPCODE_COMMENT:
+                       break;
+               case SCRIPT_OPCODE_MAPPER:
+                       r->mappernum = s->value[0];
+                       break;
+               case SCRIPT_OPCODE_MIRROR:
+                       r->mirror = s->value[0];
+                       break;
+               case SCRIPT_OPCODE_CPU_ROMSIZE:{
+                       const long size = s->value[0];
+                       r->cpu_rom.size = size;
+                       if(memorysize_check(size, MEMORY_AREA_CPU_ROM)){
+                               printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_ROMSIZE);
+                               error += 1;
+                       }
+                       //flash memory capacity check
+                       //¤¤¤Þ¤Î¤È¤³¤í == ¤Ë¤·¤Æ¾®¤µ¤¤ÍÆÎ̤⤽¤Î¤¦¤ÁÂбþ
+                       else if((c->mode == MODE_ROM_PROGRAM) && (size > c->cpu_flash_driver->capacity)){
+                               printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
+                               error += 1;
+                       }
+                       }break;
+               case SCRIPT_OPCODE_CPU_RAMSIZE:
+                       //memory size ¤Ï̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
+                       r->cpu_ram.size = s->value[0];
+                       break;
+               case SCRIPT_OPCODE_CPU_COMMAND:
+                       if(command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash)) == NG){
+                               error += 1;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_ROMSIZE:{
+                       const long size = s->value[0];
+                       r->ppu_rom.size = size;
+                       if(memorysize_check(size, MEMORY_AREA_PPU)){
+                               printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
+                               error += 1;
+                       }
+                       else if((c->mode == MODE_ROM_PROGRAM) && (size > c->ppu_flash_driver->capacity)){
+                               printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
+                               error += 1;
+                       }
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_COMMAND:
+                       if(command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash)) == NG){
+                               error += 1;
+                       }
+                       break;
+               case SCRIPT_OPCODE_DUMP_START:
+                       setting = DUMP;
+                       break;
+               case SCRIPT_OPCODE_CPU_READ:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       const long end = address + length - 1;
+                       
+                       assert(r->cpu_rom.attribute == MEMORY_ATTR_WRITE);
+                       //length filter. 0 ¤Ï¤À¤á
+                       if(!is_range(length, 1, 0x4000)){
+                               logical_print_illgallength(STR_REGION_CPU, length);
+                               error += 1;
+                       }
+                       //address filter
+                       else if(!is_region_cpurom(address)){
+                               logical_print_illgalarea(STR_REGION_CPU, address);
+                               error += 1;
+                       }else if(end >= 0x10000){
+                               logical_print_overdump(STR_REGION_CPU, address, end);
+                               error += 1;
+                       }
+                       cpu_romsize += length;
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_CPU_WRITE:{
+                       const long address = s->value[0];
+                       long data;
+                       if(expression_calc(&s->expression, &data) == NG){
+                               printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
+                               error += 1;
+                       }
+                       if(address < 0x5000 || address >= 0x10000){
+                               logical_print_illgalarea(STR_REGION_CPU, address);
+                               error += 1;
+                       }else if(!is_data_byte(data)){
+                               logical_print_byteerror(STR_REGION_CPU, data);
+                               error += 1;
+                       }
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_CPU_RAMRW:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       const long end = address + length - 1;
+                       switch(c->mode){
+                       case MODE_RAM_READ:
+                               assert(r->cpu_ram.attribute == MEMORY_ATTR_WRITE);
+                               break;
+                       case MODE_RAM_WRITE:
+                               assert(r->cpu_ram.attribute = MEMORY_ATTR_READ);
+                               break;
+                       }
+                       //length filter. 0 ¤Ï¤À¤á
+                       if(!is_range(length, 1, 0x2000)){
+                               logical_print_illgallength(STR_REGION_CPU, length);
+                               error += 1;
+                       }
+                       //address filter
+                       else if(address < 0x6000 || address >= 0x8000){
+                               logical_print_illgalarea(STR_REGION_CPU, address);
+                               error += 1;
+                       }else if(end >= 0x8000){
+                               logical_print_overdump(STR_REGION_CPU, address, end);
+                               error += 1;
+                       }
+                       cpu_ramsize += length;
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_CPU_PROGRAM:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       const long end = address + length - 1;
+                       
+                       assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
+                       assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
+                       //length filter.
+                       if(!is_range(length, 0x80, 0x2000)){
+                               logical_print_illgallength(STR_REGION_CPU, length);
+                               error += 1;
+                       }
+                       //address filter
+                       else if(!is_region_cpurom(address)){
+                               logical_print_illgalarea(STR_REGION_CPU, address);
+                               error += 1;
+                       }else if(end >= 0x10000){
+                               logical_print_overdump(STR_REGION_CPU, address, end);
+                               error += 1;
+                       }
+                       cpu_romsize += length;
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_RAMFIND:
+                       //¥ë¡¼¥×ÆâÉô¤ËÆþ¤Ã¤Æ¤¿¤é¥¨¥é¡¼
+                       if(variable_num != 0){
+                               printf("%s PPU_RAMTEST must use outside loop\n", LOGICAL_ERROR_PREFIX);
+                               error += 1;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_SRAMTEST:
+               case SCRIPT_OPCODE_PPU_READ:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       const long end = address + length - 1;
+                       assert(r->ppu_rom.attribute == MEMORY_ATTR_WRITE);
+                       //length filter. 0 ¤òÍÆǧ¤¹¤ë
+                       long min = 0;
+                       if(s->opcode == SCRIPT_OPCODE_PPU_SRAMTEST){
+                               min = 1;
+                       }
+                       if(!is_range(length, min, 0x2000)){
+                               logical_print_illgallength(STR_REGION_PPU, length);
+                               error += 1;
+                       }
+                       //address filter
+                       else if(!is_region_ppurom(address)){
+                               logical_print_illgalarea(STR_REGION_PPU, address);
+                               error += 1;
+                       }else if (end >= 0x2000){
+                               logical_print_overdump(STR_REGION_PPU, address, end);
+                               error += 1;
+                       }
+                       //dump length update
+                       if((s->opcode == SCRIPT_OPCODE_PPU_READ) && is_region_ppurom(address)){
+                               ppu_romsize += length;
+                       }
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_WRITE:{
+                       if(DEBUG==0){
+                               break;
+                       }
+                       const long address = s->value[0];
+                       long data;
+                       if(expression_calc(&s->expression, &data) == NG){
+                               printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
+                               error += 1;
+                       }
+                       setting = DUMP;
+                       if(!is_region_ppurom(address)){
+                               logical_print_illgalarea(STR_REGION_PPU, address);
+                               error += 1;
+                       }else if(!is_data_byte(data)){
+                               logical_print_byteerror(STR_REGION_PPU, data);
+                               error += 1;
+                       }
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_PROGRAM:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       const long end = address + length - 1;
+                       
+                       assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
+                       //length filter.
+                       if(!is_range(length, 0x80, 0x1000)){
+                               logical_print_illgallength(STR_REGION_PPU, length);
+                               error += 1;
+                       }
+                       //address filter
+                       else if(!is_region_ppurom(address)){
+                               logical_print_illgalarea(STR_REGION_PPU, address);
+                               error += 1;
+                       }else if(end >= 0x2000){
+                               logical_print_overdump(STR_REGION_PPU, address, end);
+                               error += 1;
+                       }
+                       ppu_romsize += length;
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_STEP_START:{
+                       int i;
+                       {
+                               const int v = s->value[1];
+                               if((v < 0) || (v > 0xff)){
+                                       printf("%s step start must 0-0xff 0x%x\n", LOGICAL_ERROR_PREFIX, v);
+                                       error += 1;
+                               }
+                       }
+                       for(i = 2; i <4; i++){
+                               const int v = s->value[i];
+                               if((v < 1) || (v > 0x100)){
+                                       printf("%s end or next must 1-0x100 0x%x\n", LOGICAL_ERROR_PREFIX, v);
+                                       error += 1;
+                               }
+                       }
+                       //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç s[1]
+                       if(step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]) == NG){
+                               printf("%s step loop too much\n", LOGICAL_ERROR_PREFIX);
+                               error += 1;
+                               return error;
+                       }
+                       setting = DUMP;
+                       }break;
+               case SCRIPT_OPCODE_DUMP_END:
+                       setting = END;
+                       break;
+               }
+               if(setting == END){
+                       break;
+               }
+               if(s->opcode == SCRIPT_OPCODE_STEP_END){
+                       if(variable_num == 0){
+                               printf("%s loop closed, missing STEP_START\n", LOGICAL_ERROR_PREFIX);
+                               return error + 1;
+                       }
+                       s = step_end(&s[1]);
+                       setting = DUMP;
+               }else{
+                       s++;
+               }
+       }
+       
+       //loop open conform
+       if(variable_num != 0){
+               printf("%s loop opened, missing STEP_END\n", LOGICAL_ERROR_PREFIX);
+               error += 1;
+       }
+       //dump length conform
+       error += dump_length_conform(OPSTR_CPU_ROMSIZE, cpu_romsize, r->cpu_rom.size);
+       error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram.size);
+       error += dump_length_conform(OPSTR_PPU_ROMSIZE, ppu_romsize, r->ppu_rom.size);
+       
+       //command line config override
+       if(c->mirror != CONFIG_OVERRIDE_UNDEF){
+               r->mirror = c->mirror;
+       }
+       if(c->backupram != CONFIG_OVERRIDE_UNDEF){
+               r->backupram = 1;
+       }
+       if(c->mapper != CONFIG_OVERRIDE_UNDEF){
+               //program mode ¤Ç mapper Êѹ¹¤òËɤ°
+               assert(c->mode == MODE_ROM_DUMP);
+               r->mappernum = c->mapper;
+       }
+       if(c->syntaxtest == 1){
+               if(error == 0){
+                       printf("syntax ok!\n");
+               }
+               error += 1;
+       }
+       return error;
+}
+
+/*
+execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
+*/
+static int execute_connection_check(const struct reader_driver *d)
+{
+       int ret = OK;
+       const int testsize = 0x80;
+       int testcount = 3;
+       u8 *master, *reload;
+       master = malloc(testsize);
+       reload = malloc(testsize);
+
+       d->cpu_read(0xfee0, testsize, master);
+       
+       while(testcount != 0){
+               d->cpu_read(0xfee0, testsize, reload);
+               if(memcmp(master, reload, testsize) != 0){
+                       ret = NG;
+                       break;
+               }
+               testcount--;
+       }
+       
+       free(master);
+       free(reload);
+       return ret;
+}
+
+enum {PPU_TEST_RAM, PPU_TEST_ROM};
+const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
+static int ppu_ramfind(const struct reader_driver *d)
+{
+       const int length = sizeof(PPU_TEST_DATA);
+       const long testaddr = 123;
+       //ppu ram data fill 0
+       {
+               int i = length;
+               long address = testaddr;
+               while(i != 0){
+                       d->ppu_write(address++, 0);
+                       i--;
+               }
+       }
+       
+       //ppu test data write
+       {
+               const u8 *data;
+               int i = length;
+               long address = testaddr;
+               data = PPU_TEST_DATA;
+               while(i != 0){
+                       d->ppu_write(address++, (long) *data);
+                       data++;
+                       i--;
+               }
+       }
+
+       u8 writedata[length];
+       d->ppu_read(testaddr, length, writedata);
+       if(memcmp(writedata, PPU_TEST_DATA, length) == 0){
+               return PPU_TEST_RAM;
+       }
+       return PPU_TEST_ROM;
+}
+
+static int ramtest(const int region, const struct reader_driver *d, long address, long length, u8 *writedata, u8 *testdata, const long filldata)
+{
+       long i = length;
+       long a = address;
+       while(i != 0){
+               switch(region){
+               case MEMORY_AREA_CPU_RAM:
+                       d->cpu_6502_write(a, filldata, 0);
+                       break;
+               case MEMORY_AREA_PPU:
+                       d->ppu_write(a, filldata);
+                       break;
+               default:
+                       assert(0);
+               }
+               a++;
+               i--;
+       }
+       switch(region){
+       case MEMORY_AREA_CPU_RAM:
+               d->cpu_read(address, length, testdata);
+               break;
+       case MEMORY_AREA_PPU:
+               d->ppu_read(address, length, testdata);
+               break;
+       default:
+               assert(0);
+       }
+       memset(writedata, filldata, length);
+       if(memcmp(writedata, testdata, length) == 0){
+               return 0;
+       }
+       return 1;
+}
+
+static const long SRAMTESTDATA[] = {0xff, 0xaa, 0x55, 0x00};
+static int sramtest(const int region, const struct reader_driver *d, long address, long length)
+{
+       u8 *writedata, *testdata;
+       int error = 0;
+       int i;
+       testdata = malloc(length);
+       writedata = malloc(length);
+       for(i = 0; i < sizeof(SRAMTESTDATA) / sizeof(long); i++){
+               const long filldata = SRAMTESTDATA[i];
+               error += ramtest(region, d, address, length, testdata, writedata, filldata);
+       }
+       free(testdata);
+       free(writedata);
+       return error;
+}
+
+static void readbuffer_print(const struct memory *m, long length)
+{
+       if(length >= 0x10){
+               length = 0x10;
+       }
+       printf("%s ROM 0x%05x:", m->name, m->offset);
+       int offset = 0;
+       const u8 *data;
+       data = m->data;
+       while(length != 0){
+               char safix;
+               switch(offset & 0xf){
+               default:
+                       safix = ' ';
+                       break;
+               case 0x7:
+                       safix = '-';
+                       break;
+               case 0xf:
+                       safix = ';';
+                       break;
+               }
+               printf("%02x%c", (int) *data, safix);
+               data++;
+               offset++;
+               length--;
+       }
+}
+
+static void checksum_print(const u8 *data, long length)
+{
+       int sum = 0;
+       while(length != 0){
+               sum += (int) *data;
+               data++;
+               length--;
+       }
+       printf(" 0x%06x\n", sum);
+}
+
+static void read_result_print(const struct memory *m, long length)
+{
+       readbuffer_print(m, length);
+       checksum_print(m->data, length);
+       fflush(stdout);
+}
+
+static void execute_program_begin(const struct memory *m)
+{
+       if(0){ //DEBUG==1){
+               return;
+       }
+       printf("writing %s area 0x%06x ... ", m->name, m->offset);
+       fflush(stdout);
+}
+
+static const char STR_OK[] = "OK";
+static const char STR_NG[] = "NG";
+
+//memcmp ¤ÎÌá¤êÃͤ¬Æþ¤ë¤Î¤Ç 0 ¤¬Àµ¾ï
+static void execute_program_finish(int result)
+{
+       const char *str;
+       str = STR_NG;
+       if(result == 0){
+               str = STR_OK;
+       }
+       printf("%s\n", str);
+       fflush(stdout);
+}
+static const char EXECUTE_ERROR_PREFIX[] = "execute error:";
+static const char EXECUTE_PROGRAM_PREPARE[] = "%s device initialize ... ";
+static const char EXECUTE_PROGRAM_DONE[] = "done\n";
+static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length, long wait)
+{
+       if(mode == MODE_RAM_WRITE){
+               const u8 *writedata;
+               long a = address;
+               long l = length;
+               writedata = ram->data;
+               while(l != 0){
+                       d->cpu_6502_write(a++, *writedata, wait);
+                       writedata += 1;
+                       l--;
+               }
+               u8 *compare;
+               compare = malloc(length);
+               d->cpu_read(address, length, compare);
+               if(memcmp(ram->data, compare, length) == 0){
+                       printf("RAM data write success\n");
+               }else{
+                       printf("RAM data write failed\n");
+               }
+               free(compare);
+       }else{
+               d->cpu_read(address, length, ram->data);
+       }
+}
+
+static int execute(const struct script *s, const struct st_config *c, struct romimage *r)
+{
+       const struct reader_driver *const d = c->reader;
+       switch(d->open_or_close(READER_OPEN)){
+       case OK:
+               d->init();
+               break;
+       case NG:
+               printf("%s driver open error\n", EXECUTE_ERROR_PREFIX);
+               return NG;
+       default:
+               assert(0);
+       }
+       if(execute_connection_check(d) == NG){
+               printf("%s maybe connection error\n", EXECUTE_ERROR_PREFIX);
+               d->open_or_close(READER_CLOSE);
+               return NG;
+       }
+       u8 *program_compare;
+       program_compare = NULL;
+       if(c->mode == MODE_ROM_PROGRAM){
+               printf("flashmemory/SRAM program mode. To abort programming, press Ctrl+C\n");
+               if(r->ppu_rom.size != 0){
+                       c->ppu_flash_driver->init(&(r->ppu_flash));
+               }
+               int size = r->cpu_rom.size;
+               if(size < r->ppu_rom.size){
+                       size = r->ppu_rom.size;
+               }
+               program_compare = malloc(size);
+       }
+       struct memory cpu_rom, ppu_rom, cpu_ram;
+       cpu_rom = r->cpu_rom;
+       ppu_rom = r->ppu_rom;
+       cpu_ram = r->cpu_ram;
+       
+       int programcount_cpu = 0, programcount_ppu = 0;
+       variable_init_all();
+       while(s->opcode != SCRIPT_OPCODE_DUMP_END){
+               int end = 1;
+               switch(s->opcode){
+               case SCRIPT_OPCODE_CPU_READ:{
+                       struct memory *m;
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       m = &cpu_rom;
+                       d->cpu_read(address, length, m->data);
+                       read_result_print(m, length);
+                       m->data += length;
+                       m->offset += length;
+                       }break;
+               case SCRIPT_OPCODE_CPU_WRITE:{
+                       long data;
+                       expression_calc(&s->expression, &data);
+                       d->cpu_6502_write(s->value[0], data, c->write_wait);
+                       }
+                       break;
+               case SCRIPT_OPCODE_CPU_RAMRW:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       if(c->mode == MODE_RAM_WRITE){
+                               if(sramtest(MEMORY_AREA_CPU_RAM, d, address, length) != 0){
+                                       printf("SRAM test NG\n");
+                                       end = 0;
+                                       break;
+                               }
+                       }
+                       execute_cpu_ramrw(d, &cpu_ram, c->mode, address, length, c->write_wait);
+                       read_result_print(&cpu_ram, length);
+                       cpu_ram.data += length;
+                       cpu_ram.offset += length;
+                       }
+                       break;
+               case SCRIPT_OPCODE_CPU_PROGRAM:{
+                       if(c->cpu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
+                               break;
+                       }
+                       if(programcount_cpu++ == 0){
+                               printf(EXECUTE_PROGRAM_PREPARE, cpu_rom.name);
+                               fflush(stdout);
+                               //device ¤Ë¤è¤Ã¤Æ¤Ï erase
+                               c->cpu_flash_driver->init(&(r->cpu_flash));
+                               printf(EXECUTE_PROGRAM_DONE);
+                               fflush(stdout);
+                       }
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       execute_program_begin(&cpu_rom);
+                       c->cpu_flash_driver->write(
+                               &(r->cpu_flash),
+                               address, length,
+                               &cpu_rom
+                       );
+                       d->cpu_read(address, length, program_compare);
+                       const int result = memcmp(program_compare, cpu_rom.data, length);
+                       execute_program_finish(result);
+                       cpu_rom.data += length;
+                       cpu_rom.offset += length;
+                       
+                       if((DEBUG==0) && (result != 0)){
+                               end = 0;
+                       }
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_RAMFIND:
+                       if(ppu_ramfind(d) == PPU_TEST_RAM){
+                               printf("PPU_RAMFIND: charcter RAM found\n");
+                               r->ppu_rom.size = 0;
+                               end = 0;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_SRAMTEST:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       printf("PPU_SRAMTEST: 0x%06x-0x%06x ", (int)ppu_rom.offset, (int) (ppu_rom.offset + length) - 1);
+                       if(sramtest(MEMORY_AREA_PPU, d, address, length) == 0){
+                               printf("%s\n", STR_OK);
+                       }else{
+                               printf("%s\n", STR_NG);
+                               //end = 0;
+                       }
+                       }break;
+               case SCRIPT_OPCODE_PPU_READ:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       if(length == 0){
+                               /*for mmc2,4 protect.
+                               ¤³¤Î¤È¤­¤Ï1byteÆɤ߹þ¤ó¤Ç¡¢¤½¤ÎÆâÍƤϥХåե¡¤Ë¤¤¤ì¤Ê¤¤*/
+                               u8 dummy;
+                               d->ppu_read(address, 1, &dummy);
+                       }else{
+                               d->ppu_read(address, length, ppu_rom.data);
+                               read_result_print(&ppu_rom, length);
+                       }
+                       ppu_rom.data += length;
+                       ppu_rom.offset += length;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_WRITE:
+                       if(DEBUG == 1){
+                               long data;
+                               expression_calc(&s->expression, &data);
+                               d->ppu_write(s->value[0], data);
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_PROGRAM:{
+                       if(c->ppu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
+                               break;
+                       }
+                       if(programcount_ppu++ == 0){
+                               printf(EXECUTE_PROGRAM_PREPARE, ppu_rom.name);
+                               fflush(stdout);
+                               c->ppu_flash_driver->init(&(r->ppu_flash));
+                               printf(EXECUTE_PROGRAM_DONE);
+                               fflush(stdout);
+                       }
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       execute_program_begin(&ppu_rom);
+                       c->ppu_flash_driver->write(
+                               &(r->ppu_flash),
+                               address, length,
+                               &ppu_rom
+                       );
+                       d->ppu_read(address, length, program_compare);
+                       const int result = memcmp(program_compare, ppu_rom.data, length);
+                       execute_program_finish(result);
+                       ppu_rom.data += length;
+                       ppu_rom.offset += length;
+                       
+                       if((DEBUG==0) && (result != 0)){
+                               end = 0;
+                       }
+                       }
+                       break;
+               case SCRIPT_OPCODE_STEP_START:
+                       //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç &s[1]
+                       step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]);
+                       break;
+               case SCRIPT_OPCODE_DUMP_END:
+                       end = 0;
+                       break;
+               }
+               if(end == 0){
+                       break;
+               }
+               if(s->opcode == SCRIPT_OPCODE_STEP_END){
+                       s = step_end(++s);
+               }else{
+                       s++;
+               }
+       }
+       d->open_or_close(READER_CLOSE);
+       if(program_compare != NULL){
+               free(program_compare);
+       }
+       return OK;
+}
+
+void script_load(const struct st_config *c)
+{
+       struct script *s;
+       {
+               int scriptsize = 0;
+               char *buf;
+               
+               buf = buf_load_full(c->script, &scriptsize);
+               if(buf == NULL){
+                       printf("scriptfile open error\n");
+                       return;
+               }
+               char **text;
+               text = malloc(sizeof(char*) * TEXT_MAXLINE);
+               const int text_num = text_load(buf, scriptsize, text);
+               if(text_num == 0){
+                       printf("script line too much\n");
+                       free(buf);
+                       free(text);
+                       return;
+               }
+               s = malloc(sizeof(struct script) * (text_num + 1));
+               //logical_check, execute ¶¦¤Ë s->opcode ¤¬ DUMP_END ¤Ë¤Ê¤ë¤Þ¤Ç³¤±¤ë¡£DUMP_END ¤ÎÆþ¤ì˺¤ìÍѤËËöÈø¤Îscript¤Ëɬ¤º DUMP_END ¤ò¤¤¤ì¤ë
+               {
+                       struct script *k;
+                       k = s;
+                       k += text_num;
+                       k->opcode = SCRIPT_OPCODE_DUMP_END;
+               }
+               const int error = syntax_check(text, text_num, s, c->mode);
+               free(buf);
+               free(text);
+               if(error != 0){
+                       free(s);
+                       return;
+               }
+       }
+       struct romimage r = {
+               .cpu_rom = {
+                       .size = 0, .offset = 0,
+                       .data = NULL,
+                       .attribute = MEMORY_ATTR_NOTUSE,
+                       .name = "program"
+               },
+               .ppu_rom = {
+                       .size = 0, .offset = 0,
+                       .data = NULL,
+                       .attribute = MEMORY_ATTR_NOTUSE,
+                       .name = "charcter"
+               },
+               .cpu_ram = {
+                       .size = 0, .offset = 0,
+                       .data = NULL,
+                       .attribute = MEMORY_ATTR_NOTUSE,
+                       .name = STR_REGION_CPU
+               },
+               //device ¤Ë±þ¤¸¤¿´Ø¿ô¥Ý¥¤¥ó¥¿¤ò flash_order ¤ËÅϤ¹
+               .cpu_flash = {
+                       .command_0000 = 0,
+                       .command_2aaa = 0,
+                       .command_5555 = 0,
+                       .pagesize = c->cpu_flash_driver->pagesize,
+                       .erase_wait = c->cpu_flash_driver->erase_wait,
+                       .command_mask = c->cpu_flash_driver->command_mask,
+                       .flash_write = c->reader->cpu_flash_write,
+                       .read = c->reader->cpu_read
+               },
+               .ppu_flash = {
+                       .command_0000 = 0,
+                       .command_2aaa = 0,
+                       .command_5555 = 0,
+                       .pagesize = c->ppu_flash_driver->pagesize,
+                       .erase_wait = c->ppu_flash_driver->erase_wait,
+                       .command_mask = c->ppu_flash_driver->command_mask,
+                       .flash_write = c->reader->ppu_write,
+                       .read = c->reader->ppu_read
+               },
+               .mappernum = 0,
+               .mirror = MIRROR_PROGRAMABLE
+       };
+       //attribute ¤Ï¤½¤Î struct data ¤ËÂФ·¤Æ¤Î RW ¤Ê¤Î¤ÇÍ×Ãí°Õ
+       switch(c->mode){
+       case MODE_ROM_DUMP:
+               r.cpu_rom.attribute = MEMORY_ATTR_WRITE;
+               r.ppu_rom.attribute = MEMORY_ATTR_WRITE;
+               break;
+       case MODE_RAM_READ:
+               r.cpu_ram.attribute = MEMORY_ATTR_WRITE;
+               break;
+       case MODE_RAM_WRITE:
+               r.cpu_ram.attribute = MEMORY_ATTR_READ;
+               break;
+       case MODE_ROM_PROGRAM:
+               r.cpu_rom.attribute = MEMORY_ATTR_READ;
+               r.ppu_rom.attribute = MEMORY_ATTR_READ;
+               break;
+       default:
+               assert(0);
+       }
+       
+       if(logical_check(s, c, &r) == 0){
+               //dump RAM Îΰè¼èÆÀ
+               if(nesbuffer_malloc(&r, c->mode) == NG){
+                       free(s);
+                       if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
+                               free(r.cpu_ram.data);
+                       }
+                       return;
+               }
+               //script execute!!
+               if(execute(s, c, &r) == OK){
+                       //À®²Ì½ÐÎÏ
+                       switch(c->mode){
+                       case MODE_ROM_DUMP:
+                               nesfile_create(&r, c->romimage);
+                               break;
+                       case MODE_RAM_READ:
+                               backupram_create(&(r.cpu_ram), c->ramimage);
+                               break;
+                       }
+               }
+               //dump RAM Îΰè²òÊü
+               nesbuffer_free(&r, c->mode);
+               if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
+                       free(r.cpu_ram.data);
+               }
+       }
+       free(s);
+}
diff --git a/client/tag/0.5.3/script.h b/client/tag/0.5.3/script.h
new file mode 100644 (file)
index 0000000..9f538d5
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _SCRIPT_H_
+#define _SCRIPT_H_
+struct st_config;
+void script_load(const struct st_config *config);
+
+struct st_variable{
+       int type;
+       char variable;
+       long value;
+};
+
+struct st_expression{
+       struct st_variable left, right;
+       int operator;
+};
+
+struct script{
+       int opcode;
+       long value[4];
+       struct st_expression expression;
+       char variable;
+};
+
+enum{
+       VALUE_EXPRESSION = 0x1000000,
+       VALUE_VARIABLE
+};
+enum{
+       EXPRESSION_TYPE_VARIABLE,
+       EXPRESSION_TYPE_VALUE
+};
+
+#endif
diff --git a/client/tag/0.5.3/syntax.h b/client/tag/0.5.3/syntax.h
new file mode 100644 (file)
index 0000000..8297b94
--- /dev/null
@@ -0,0 +1,225 @@
+//included from script.c only
+struct script_syntax{
+       const char *name;
+       int script_opcode;
+       int permittion;
+       int argc, compare;
+       const int *argv_type;
+};
+enum{
+       SYNTAX_ARGVTYPE_NULL,
+       SYNTAX_ARGVTYPE_VALUE,
+       SYNTAX_ARGVTYPE_HV,
+       SYNTAX_ARGVTYPE_EXPRESSION,
+       SYNTAX_ARGVTYPE_VARIABLE
+};
+enum{
+       SYNTAX_COMPARE_EQ,
+       SYNTAX_COMPARE_GT
+};
+enum{
+       SYNTAX_ARGV_TYPE_NUM = 4
+};
+enum{
+       SCRIPT_OPCODE_MAPPER,
+       SCRIPT_OPCODE_MIRROR,
+       SCRIPT_OPCODE_CPU_ROMSIZE,
+       SCRIPT_OPCODE_CPU_RAMSIZE,
+       SCRIPT_OPCODE_CPU_COMMAND,
+       SCRIPT_OPCODE_PPU_COMMAND,
+       SCRIPT_OPCODE_PPU_ROMSIZE,
+       SCRIPT_OPCODE_DUMP_START,
+       SCRIPT_OPCODE_CPU_READ,
+       SCRIPT_OPCODE_CPU_WRITE,
+       SCRIPT_OPCODE_CPU_RAMRW,
+       SCRIPT_OPCODE_CPU_PROGRAM,
+       SCRIPT_OPCODE_PPU_RAMFIND,
+       SCRIPT_OPCODE_PPU_SRAMTEST,
+       SCRIPT_OPCODE_PPU_READ,
+       SCRIPT_OPCODE_PPU_WRITE,
+       SCRIPT_OPCODE_PPU_PROGRAM,
+       SCRIPT_OPCODE_STEP_START,
+       SCRIPT_OPCODE_STEP_END,
+//     SCRIPT_OPCODE_WAIT,
+       SCRIPT_OPCODE_DUMP_END,
+       SCRIPT_OPCODE_COMMENT,
+       SCRIPT_OPCODE_NUM
+};
+enum{
+       PERMITTION_ROM_DUMP = 1 << MODE_ROM_DUMP,
+       PERMITTION_RAM_READ = 1 << MODE_RAM_READ,
+       PERMITTION_RAM_WRITE = 1 << MODE_RAM_WRITE,
+       PERMITTION_ROM_PROGRAM = 1 << MODE_ROM_PROGRAM,
+       PERMITTION_ALL = 0xffff
+};
+static const char OPSTR_CPU_ROMSIZE[] = "CPU_ROMSIZE";
+static const char OPSTR_CPU_RAMSIZE[] = "CPU_RAMSIZE";
+static const char OPSTR_PPU_ROMSIZE[] = "PPU_ROMSIZE";
+static const char OPSTR_CPU_RAMRW[] = "CPU_RAMRW";
+static const int ARGV_TYPE_VALUE_ONLY[SYNTAX_ARGV_TYPE_NUM] = {
+       SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL,
+       SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL
+};
+static const int ARGV_TYPE_HV[SYNTAX_ARGV_TYPE_NUM] = {
+       SYNTAX_ARGVTYPE_HV, SYNTAX_ARGVTYPE_NULL,
+       SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL
+};
+static const int ARGV_TYPE_NULL[SYNTAX_ARGV_TYPE_NUM] = {
+       SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL,
+       SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL
+};
+static const int ARGV_TYPE_ADDRESS_EXPRESSION[SYNTAX_ARGV_TYPE_NUM] = {
+       SYNTAX_ARGVTYPE_VALUE,
+       SYNTAX_ARGVTYPE_EXPRESSION, SYNTAX_ARGVTYPE_EXPRESSION, SYNTAX_ARGVTYPE_EXPRESSION
+};
+static const int ARGV_TYPE_ADDRESS_LENGTH[SYNTAX_ARGV_TYPE_NUM] = {
+       SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE,
+       SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL
+};
+static const int ARGV_TYPE_STEP_START[SYNTAX_ARGV_TYPE_NUM] = {
+       SYNTAX_ARGVTYPE_VARIABLE, SYNTAX_ARGVTYPE_VALUE,
+       SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE
+};
+static const int ARGV_TYPE_ADDRESS_COMMAND[SYNTAX_ARGV_TYPE_NUM] = {
+       SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE,
+       SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL
+};
+static const struct script_syntax SCRIPT_SYNTAX[] = {
+       {
+               name: "MAPPER",
+               script_opcode: SCRIPT_OPCODE_MAPPER,
+               permittion: PERMITTION_ROM_DUMP | PERMITTION_ROM_PROGRAM,
+               argc: 1, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_VALUE_ONLY
+       },{
+               name: "MIRROR",
+               script_opcode: SCRIPT_OPCODE_MIRROR,
+               permittion: PERMITTION_ROM_DUMP,
+               argc: 1, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_HV
+       },{
+               name: OPSTR_CPU_ROMSIZE,
+               script_opcode: SCRIPT_OPCODE_CPU_ROMSIZE,
+               permittion: PERMITTION_ROM_DUMP | PERMITTION_ROM_PROGRAM,
+               argc: 1, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_VALUE_ONLY
+       },{
+               name: OPSTR_CPU_RAMSIZE,
+               script_opcode: SCRIPT_OPCODE_CPU_RAMSIZE,
+               permittion: PERMITTION_RAM_READ | PERMITTION_RAM_WRITE,
+               argc: 1, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_VALUE_ONLY
+       },{
+               name: OPSTR_PPU_ROMSIZE,
+               script_opcode: SCRIPT_OPCODE_PPU_ROMSIZE,
+               permittion: PERMITTION_ROM_DUMP | PERMITTION_ROM_PROGRAM,
+               argc: 1, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_VALUE_ONLY
+       },{
+               name: "CPU_COMMAND",
+               script_opcode: SCRIPT_OPCODE_CPU_COMMAND,
+               permittion: PERMITTION_ROM_PROGRAM,
+               argc:3, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_COMMAND
+       },{
+               name: "PPU_COMMAND",
+               script_opcode: SCRIPT_OPCODE_PPU_COMMAND,
+               permittion: PERMITTION_ROM_PROGRAM,
+               argc:3, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_COMMAND
+       },{
+               name: "DUMP_START",
+               script_opcode: SCRIPT_OPCODE_DUMP_START,
+               permittion: PERMITTION_ALL,
+               argc: 0, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_NULL
+       },{
+               name: "CPU_READ",
+               script_opcode: SCRIPT_OPCODE_CPU_READ,
+               permittion: PERMITTION_ROM_DUMP,
+               argc: 2, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_LENGTH
+       },{
+               name: "CPU_WRITE",
+               script_opcode: SCRIPT_OPCODE_CPU_WRITE,
+               permittion: PERMITTION_ALL,
+               argc: 2, compare: SYNTAX_COMPARE_GT,
+               argv_type: ARGV_TYPE_ADDRESS_EXPRESSION
+       },{
+               name: OPSTR_CPU_RAMRW,
+               script_opcode: SCRIPT_OPCODE_CPU_RAMRW,
+               permittion: PERMITTION_RAM_READ | PERMITTION_RAM_WRITE,
+               argc: 2, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_LENGTH
+       },{
+               name: "CPU_PROGRAM",
+               script_opcode: SCRIPT_OPCODE_CPU_PROGRAM,
+               permittion: PERMITTION_ROM_PROGRAM,
+               argc: 2, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_LENGTH
+       },{
+               name: "PPU_RAMFIND",
+               script_opcode: SCRIPT_OPCODE_PPU_RAMFIND,
+               permittion: PERMITTION_ROM_DUMP | PERMITTION_ROM_PROGRAM,
+               argc: 0, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_NULL
+       },{
+               name: "PPU_SRAMTEST",
+               script_opcode: SCRIPT_OPCODE_PPU_SRAMTEST,
+               permittion: PERMITTION_ROM_DUMP,
+               argc: 2, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_LENGTH
+       },{
+               name: "PPU_READ",
+               script_opcode: SCRIPT_OPCODE_PPU_READ,
+               permittion: PERMITTION_ROM_DUMP,
+               argc: 2, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_LENGTH
+       },
+#if DEBUG==1
+       {
+               name: "PPU_WRITE",
+               script_opcode: SCRIPT_OPCODE_PPU_WRITE,
+               permittion: PERMITTION_ROM_DUMP | PERMITTION_ROM_PROGRAM,
+               argc: 2, compare: SYNTAX_COMPARE_GT,
+               argv_type: ARGV_TYPE_ADDRESS_EXPRESSION
+       },
+#endif
+       {
+               name: "PPU_PROGRAM",
+               script_opcode: SCRIPT_OPCODE_PPU_PROGRAM,
+               permittion: PERMITTION_ROM_PROGRAM,
+               argc: 2, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_ADDRESS_LENGTH,
+       },
+       {
+               name: "STEP_START",
+               script_opcode: SCRIPT_OPCODE_STEP_START,
+               permittion: PERMITTION_ALL,
+               argc: 4, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_STEP_START
+       },{
+               name: "STEP_END",
+               script_opcode: SCRIPT_OPCODE_STEP_END,
+               permittion: PERMITTION_ALL,
+               argc: 0, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_NULL
+       },
+#if 0
+       {
+               name: "WAIT",
+               script_opcode: SCRIPT_OPCODE_WAIT,
+               permittion: PERMITTION_ROM_PROGRAM,
+               argc: 1, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_VALUE_ONLY
+       },
+#endif
+       {
+               name: "DUMP_END",
+               script_opcode: SCRIPT_OPCODE_DUMP_END,
+               permittion: PERMITTION_ALL,
+               argc: 0, compare: SYNTAX_COMPARE_EQ,
+               argv_type: ARGV_TYPE_NULL
+       }
+};
+
diff --git a/client/tag/0.5.3/textutil.c b/client/tag/0.5.3/textutil.c
new file mode 100644 (file)
index 0000000..21e4b34
--- /dev/null
@@ -0,0 +1,204 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "type.h"
+#include "textutil.h"
+#ifndef DEBUG
+ #define DEBUG 0
+#endif
+
+#define PRINT(msg) \
+       if(DEBUG == 1){ \
+               printf("%s %s\n",  __FUNCTION__, msg);\
+       }
+
+int text_load(char *buf, int length, char **text)
+{
+       int line = 0;
+       char pastdata = '#';
+       
+       text[line] = buf;
+       line++;
+       while(length != 0){
+               int current_crlf = 0;
+               switch(*buf){
+               case '\n':
+               case '\r':
+                       *buf = '\0';
+                       current_crlf = 1;
+                       break;
+               }
+               switch(pastdata){
+               case '\0':
+                       if(line >= TEXT_MAXLINE){
+                               PRINT("line over")
+                               return 0;
+                       }
+                       if(current_crlf == 0){
+                               text[line] = buf;
+                               line++;
+                       }
+                       break;
+               }
+               pastdata = *buf;
+               buf++;
+               length--;
+       }
+       buf--;
+       *buf = '\0';
+       return line;
+}
+
+int word_load(char *buf, char **text)
+{
+       int word = 0;
+       char pastdata = '#';
+       
+       switch(*buf){
+       case '\t':
+       case ' ':
+               break;
+       case '#': //¹ÔƬ¥³¥á¥ó¥È
+               text[word] = buf;
+               return 1;
+       default:
+               text[word] = buf;
+               word++;
+               break;
+       }
+       
+       while(*buf != '\0'){
+               int current_spc = 0;
+               switch(*buf){
+               case '\t':
+               case ' ':
+                       *buf = '\0';
+                       current_spc = 1;
+                       break;
+               }
+               switch(pastdata){
+               case '\0':
+                       if(word >= TEXT_MAXWORD){
+                               PRINT("word over")
+                               return 0;
+                       }
+                       if(current_spc == 0){
+                               /*if(*buf == '#'){
+                                       return word;
+                               }*/
+                               text[word] = buf;
+                               word++;
+                       }
+                       break;
+               }
+               pastdata = *buf;
+               buf++;
+       }
+       return word;
+}
+
+int value_get(const char *str, long *val)
+{
+       int base = 10;
+       int sign = 1;
+       //-¤¬¤Ä¤¤¤Æ¤ë¤«
+       switch(*str){
+       case '\0':
+               return NG;
+       case '-':
+               sign = -1;
+               str++;
+               if(*str == '\0'){
+                       return NG;
+               }
+               break;
+       }
+       //0x, 0b, $, % ¤¬¤Ä¤¤¤Æ¤ë¤«
+       switch(*str){
+       case '0':
+               switch(str[1]){
+               case '\0':
+                       //¤¿¤ó¤Ê¤ë 0 ¤Ê¤Î¤Ç OK
+                       break;
+               case 'x':
+                       base = 0x10;
+                       str += 2;
+                       break;
+               case 'b':
+                       base = 2;
+                       str += 2;
+                       break;
+               case '0': case '1': case '2': case '3':
+               case '4': case '5': case '6': case '7':
+               case '8': case '9':
+                       //C¤Ê¤é8¿Ê¿ô°·¤¤¤À¤±¤É10¿Ê¿ô°·¤¤¤Ë¤¹¤ë
+                       break;
+               default:
+                       return NG;
+               }
+               break;
+       case '$':
+               base = 0x10;
+               str += 1;
+               break;
+       case '%':
+               base = 2;
+               str += 1;
+               break;
+       }
+       //¤³¤Î»þÅÀ¤Ç¤Î str ¤Ï ¿ô»ú¤ÎÀèƬ¤È¤·¤Æ¤¿¾ì½ê
+       char *error;
+       *val = strtol(str, &error, base);
+       if(error[0] != '\0'){
+               //x01
+               //4M\0
+               if((error[1] == '\0') && (base == 10)){
+                       switch(error[0]){
+                       /*case 'K': ¤¤¤¯¤Ä¤À¤Ã¤±?
+                               *val *= 0x400;
+                               break;*/
+                       case 'M':
+                               *val *= 0x20000;
+                               break;
+                       default:
+                               return NG;
+                       }
+               }else{
+                       return NG;
+               }
+       }
+       
+       if(sign == -1){
+               *val = -(*val);
+       }
+       return OK;
+}
+
+struct operator_cmp{
+       char *str;
+       int operator;
+};
+static const struct operator_cmp CMP[] = {
+       {"+", OPERATOR_PLUS},
+       {">>", OPERATOR_SHIFT_LEFT},
+       {"<<", OPERATOR_SHIFT_RIGHT},
+       {"&", OPERATOR_AND},
+       {"|", OPERATOR_OR},
+       {"^", OPERATOR_XOR}
+};
+
+int operator_get(char *str)
+{
+       const struct operator_cmp *c;
+       int i = OPERATOR_ERROR;
+       c = CMP;
+       while(i != 0){
+               if(strcmp(c->str, str) == 0){
+                       return c->operator;
+               }
+               c++;
+               i--;
+       }
+       return OPERATOR_ERROR;
+}
+
diff --git a/client/tag/0.5.3/textutil.h b/client/tag/0.5.3/textutil.h
new file mode 100644 (file)
index 0000000..98f7588
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _TEXTUTIL_H_
+#define _TEXTUTIL_H_
+enum{
+       TEXT_MAXLINE = 0x100,
+       TEXT_MAXWORD = 10
+};
+int text_load(char *buf, int length, char **text);
+int word_load(char *buf, char **text);
+int value_get(const char *str, long *val);
+
+enum{
+       OPERATOR_PLUS,
+       OPERATOR_SHIFT_LEFT,
+       OPERATOR_SHIFT_RIGHT,
+       OPERATOR_AND,
+       OPERATOR_OR,
+       OPERATOR_XOR,
+       OPERATOR_ERROR,
+       OPERATOR_NONE,
+};
+
+int operator_get(char *str);
+#endif
diff --git a/client/tag/0.5.3/type.h b/client/tag/0.5.3/type.h
new file mode 100644 (file)
index 0000000..84e33e3
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _TYPE_H_
+#define _TYPE_H_
+#include <stdint.h>
+typedef uint8_t u8;
+enum{
+       OK = 0, NG
+};
+#endif
diff --git a/client/tag/0.5.3/unagi.c b/client/tag/0.5.3/unagi.c
new file mode 100644 (file)
index 0000000..4a964bf
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+famicom ROM cartridge utility - unagi
+command line interface, config file parser
+
+Copyright (C) 2008-2009 ±·³«È¯¶¨Æ±Áȹç
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "type.h"
+#include "reader_master.h"
+#include "giveio.h"
+#include "file.h"
+#include "script.h"
+#include "header.h"
+#include "textutil.h"
+#include "config.h"
+#include "flashmemory.h"
+#include "client_test.h"
+
+static int flag_get(const char *flag, struct st_config *c)
+{
+       while(*flag != '\0'){
+               switch(*flag){
+               case 'S': case 's':
+                       c->backupram = CONFIG_OVERRIDE_TRUE;
+                       break;
+               case 'H': case 'h':
+                       c->mirror = MIRROR_HORIZONAL;
+                       break;
+               case 'V': case 'v':
+                       c->mirror = MIRROR_VERTICAL;
+                       break;
+               case '_':
+                       break;
+               case 'r':
+                       c->syntaxtest = 1;
+                       break;
+               default:
+                       return NG;
+               }
+               flag++;
+       }
+       return OK;
+}
+
+static const char PREFIX_CONFIG_ERROR[] = "config error:";
+static int config_file_load(struct st_config *c)
+{
+       char *buf;
+       int size = 0;
+       c->reader = NULL;
+       buf = buf_load_full("unagi.cfg", &size);
+       if(buf == NULL){
+               printf("%s config file open error\n", PREFIX_CONFIG_ERROR);
+               return NG;
+       }
+       char **text;
+       text = malloc(sizeof(char*) * TEXT_MAXLINE);
+       const int text_num = text_load(buf, size, text);
+       if(text_num == 0){
+               printf("%s script line too much\n", PREFIX_CONFIG_ERROR);
+               free(buf);
+               free(text);
+               return NG;
+       }
+       int i;
+       for(i=0; i<text_num; i++){
+               char *word[TEXT_MAXWORD];
+               word_load(text[i], word);
+               if(word[0][0] == '#'){
+                       continue;
+               }
+               if(strcmp("DRIVER", word[0]) == 0){
+                       c->reader = reader_driver_get(word[1]);
+               }else if((DEBUG == 1) && (strcmp("WRITE_WAIT", word[0]) == 0)){
+                       if(value_get(word[1], &(c->write_wait)) == NG){
+                               printf("%s write_wait parameter is illigal", PREFIX_CONFIG_ERROR);
+                               free(buf);
+                               free(text);
+                               return NG;
+                       }
+               }else if(strcmp("TEST_DEVICE", word[0]) == 0){
+                       if(DEBUG == 1){
+                               strncpy(c->flash_test_device, word[1], CONFIG_STR_LENGTH);
+                       }
+               }else if(strcmp("TEST_MAPPER", word[0]) == 0){
+                       if(DEBUG == 1){
+                               strncpy(c->flash_test_mapper, word[1], CONFIG_STR_LENGTH);
+                       }
+               }else{
+                       printf("%s unknown config title %s", PREFIX_CONFIG_ERROR, word[1]);
+                       free(buf);
+                       free(text);
+                       return NG;
+               }
+       }
+       
+       free(text);
+       if(c->reader == NULL){
+               printf("%s hardware not selected or not found\n", PREFIX_CONFIG_ERROR);
+               free(buf);
+               return NG;
+       }
+       free(buf);
+       return OK;
+}
+
+static const struct flash_driver DRIVER_UNDEF = {
+       .name = "undefined",
+       .capacity = 0,
+       .pagesize = 1,
+       .erase_wait = 0,
+       .command_mask = 0,
+       .id_manufacurer = 0,
+       .id_device = 0,
+       .productid_check = NULL,
+#if DEBUG==1
+       .erase = NULL,
+#endif
+       .init = NULL,
+       .write = NULL
+};
+static int flash_pointer_init(const char *device, const struct flash_driver **f)
+{
+       *f = flash_driver_get(device);
+       if(*f == NULL){
+               printf("%s unknown flash device %s\n", PREFIX_CONFIG_ERROR, device);
+               return NG;
+       }
+       return OK;
+}
+
+enum{
+       ARGC_MODE = 1,
+       ARGC_SCRIPTFILE,
+       //DUMP MODE
+       ARGC_DUMP_OUT_NESFILE,
+       ARGC_DUMP_FLAG,
+       ARGC_DUMP_MAPPER,
+       //RAM RW MODE
+       ARGC_READ_OUT_RAMFILE = ARGC_DUMP_OUT_NESFILE,
+       ARGC_WRITE_IN_RAMFILE = ARGC_DUMP_OUT_NESFILE,
+       ARGC_RW_NUM,
+       //PROGRAM MODE
+       ARGC_PROGRAM_IN_NESFILE = ARGC_DUMP_OUT_NESFILE,
+       ARGC_PROGRAM_CPU_DEVICE,
+       ARGC_PROGRAM_PPU_DEVICE,
+       //TESTMODE
+       ARGC_TEST_OPTION = ARGC_SCRIPTFILE,
+       ARGC_TEST_FILE,
+       ARGC_TEST_NUM
+};
+
+static int config_init(const int argc, const char **argv, struct st_config *c)
+{
+       c->script = argv[ARGC_SCRIPTFILE];
+       c->romimage = NULL;
+       c->ramimage = NULL;
+       c->mapper = CONFIG_OVERRIDE_UNDEF;
+       c->mirror = CONFIG_OVERRIDE_UNDEF;
+       c->backupram = CONFIG_OVERRIDE_UNDEF;
+       c->mapper = CONFIG_OVERRIDE_UNDEF;
+       c->syntaxtest = 0;
+       c->cpu_flash_driver = &DRIVER_UNDEF;
+       c->ppu_flash_driver = &DRIVER_UNDEF;
+       c->write_wait = 0;
+       //mode ÊÌ target file ½é´ü²½
+       switch(argv[ARGC_MODE][0]){
+       case 'd':
+               c->mode = MODE_ROM_DUMP;
+               c->romimage = argv[ARGC_DUMP_OUT_NESFILE];
+               break;
+       case 'r':
+               c->mode = MODE_RAM_READ;
+               c->ramimage = argv[ARGC_READ_OUT_RAMFILE];
+               break;
+       case 'w':
+               c->mode = MODE_RAM_WRITE;
+               c->ramimage = argv[ARGC_WRITE_IN_RAMFILE];
+               break;
+       case 'f':
+               c->mode = MODE_ROM_PROGRAM;
+               c->romimage = argv[ARGC_PROGRAM_IN_NESFILE];
+               break;
+       case 't':
+               if(DEBUG == 1){
+                       c->mode = MODE_TEST;
+                       break;
+               }
+               //²¼¤Ø
+       default:
+               printf("%s unkown mode %s\n", PREFIX_CONFIG_ERROR, argv[ARGC_MODE]);
+               return NG;
+       };
+       if(config_file_load(c) == NG){
+               return NG;
+       }
+       /*mode ÊÌ argc check. 
+       DEBUG==0  argc: 4,5,6
+       DEBUG==1  argc: 3,4,5,6
+       */
+       switch(c->mode){
+       case MODE_ROM_DUMP:{
+               int flag_error = OK, mapper_error = OK;
+               switch(argc){
+               case 3:
+                       return NG;
+               case 5:
+                       flag_error = flag_get(argv[ARGC_DUMP_FLAG], c);
+                       break;
+               case 6:
+                       flag_error = flag_get(argv[ARGC_DUMP_FLAG], c);
+                       mapper_error = value_get(argv[ARGC_DUMP_MAPPER], &c->mapper);
+                       break;
+               }
+               if(flag_error != OK){
+                       printf("%s unknown flag %s\n", PREFIX_CONFIG_ERROR, argv[ARGC_DUMP_FLAG]);
+                       return NG;
+               }
+               if(mapper_error != OK){
+                       printf("%s unknown mapper %s\n", PREFIX_CONFIG_ERROR, argv[ARGC_DUMP_MAPPER]);
+                       return NG;
+               }
+               }break;
+       case MODE_RAM_READ:
+       case MODE_RAM_WRITE:
+               if(argc != ARGC_RW_NUM){
+                       printf("%s too many argument\n", PREFIX_CONFIG_ERROR);
+                       return NG;
+               }
+               break;
+       case MODE_ROM_PROGRAM:
+               switch(argc){
+               case 3:
+               case 4:
+                       printf("%s few argument\n", PREFIX_CONFIG_ERROR);
+                       return NG;
+               case 5:
+                       if(flash_pointer_init(argv[ARGC_PROGRAM_CPU_DEVICE], &(c->cpu_flash_driver)) == NG){
+                               return NG;
+                       }
+                       break;
+               case 6:
+                       if(flash_pointer_init(argv[ARGC_PROGRAM_CPU_DEVICE], &(c->cpu_flash_driver)) == NG){
+                               return NG;
+                       }
+                       if(flash_pointer_init(argv[ARGC_PROGRAM_PPU_DEVICE], &(c->ppu_flash_driver)) == NG){
+                               return NG;
+                       }
+                       break;
+               }
+               break;
+       
+       case MODE_TEST:
+               if(DEBUG == 0){
+                       break;
+               }
+               switch(argc){
+               case 3:
+                       client_test(c->reader, argv[ARGC_TEST_OPTION], NULL, c->flash_test_device, c->flash_test_mapper);
+                       break;
+               case 4:
+                       client_test(c->reader, argv[ARGC_TEST_OPTION], argv[ARGC_TEST_FILE], c->flash_test_device, c->flash_test_mapper);
+                       break;
+               default:
+                       printf("%s test argc error\n", PREFIX_CONFIG_ERROR);
+               }
+               break;
+       }
+
+       return OK;
+}
+
+#include "version.h"
+int main(int c, char **v)
+{
+       struct st_config config;
+       int config_result = NG;
+       switch(c){
+       case 3: //t testmode target
+               if(DEBUG == 0){
+                       goto usage;
+               }
+               //²¼¤Ø
+       case 4: //mode script target
+       case 5:
+               //mode script target flag
+               //mode script target cpu_flash_device
+       case 6:
+               //mode script target flag mapper
+               //mode script target cpu_flash_device ppu_flash_device
+               config_result = config_init(c, (const char **) v, &config);
+               break;
+       usage:
+       default:
+               printf("famicom ROM cartridge utility - unagi version %s\n", STR_VERSION);
+               printf("%s [mode] [mapper script] [target file] [flag]\n", v[0]);
+               printf("mode - [d]ump ROM / [r]ead RAM/ [w]rite RAM/ [f]lash memory program\n");
+               break;
+       }
+       if((config.mode != MODE_TEST) && (config_result == OK)){
+               script_load(&config);
+       }
+       return 0;
+}
diff --git a/client/tag/0.5.3/unagi.ico b/client/tag/0.5.3/unagi.ico
new file mode 100644 (file)
index 0000000..c9badff
Binary files /dev/null and b/client/tag/0.5.3/unagi.ico differ
diff --git a/client/tag/0.5.3/unagi.rc b/client/tag/0.5.3/unagi.rc
new file mode 100644 (file)
index 0000000..86089e8
--- /dev/null
@@ -0,0 +1 @@
+UNAGI ICON "unagi.ico"
diff --git a/client/tag/0.5.3/unagi.txt b/client/tag/0.5.3/unagi.txt
new file mode 100644 (file)
index 0000000..c0c8b77
--- /dev/null
@@ -0,0 +1,98 @@
+famicom ROM cartridge utility - unagi
+client version 0.5.3
+by \89V\8aJ\94­\8b¦\93¯\91g\8d\87
+\8cö\8e®\83T\83C\83g http://unagi.sourceforge.jp/
+\8cf\8e¦\94     http://unagi.sourceforge.jp/t/bbs.html
+
+--\82Í\82\82ß\82É--
+famicom ROM cartridge \82Ì\83f\81[\83^\93]\91\97\82ð\8ds\82¢\82Ü\82·\81\83n\81[\83h\83E\83F\83A\82Í\8d\91\93à\82Å\97L
+\96¼\82È2\8eí\97Þ\82É\91Î\89\9e\82µ\82Ä\82¢\82Ü\82·\81B
+
+--\93Á\92¥--
+\91¼\82Ì\93Ç\82Ý\8fo\82µ\83v\83\8d\83O\83\89\83\80\82Å\82Í\83}\83b\83p\95Ê\82Ì\91Î\89\9e\82Í\83v\83\8d\83O\83\89\83\80\82É\93à\91 \82³\82ê\82Ä\82¨\82è\81A
+\96¢\91Î\89\9e\82Ì\83}\83b\83p\82Ì\92Ç\89Á\82ª\82Å\82«\82é\82Ì\82Í\83v\83\8d\83O\83\89\83}\82¾\82¯\82Å\82µ\82½\81Bunagi \82Å\82Í\83}\83b\83p
+\91Î\89\9e\82ð\83X\83N\83\8a\83v\83g\82É\8bL\8dÚ\82·\82é\82±\82Æ\82É\82æ\82Á\82Ä\83\86\81[\83U\81[\82ª\92Ç\89Á\82·\82é\82±\82Æ\82ª\82Å\82«\82Ü\82·\81B
+\83o\83\93\83N\90Ø\82è\91Ö\82¦\82Ì\8ed\97l\82ð\82µ\82é\82±\82Æ\82É\82æ\82Á\82Ä\8bZ\8fp\93I\82È\8b»\96¡\82ª\82í\82­\82©\82à\82µ\82ê\82Ü\82¹\82ñ\81B
+
+\83R\83}\83\93\83h\83\89\83C\83\93\82Å\82Ì\96³\96¡\8a£\91\87\82È\83C\83\93\83^\83t\83F\81[\83X\82É\82æ\82è\83r\83M\83i\81[\82¨\92f\82è\82Æ\82È\82Á\82Ä
+\82¨\82è\82Ü\82·\81B
+
+--\93®\8dì\8aÂ\8b«--
+\83p\83\89\83\8c\83\8b\83|\81[\83g\82Æ\93Ç\82Ý\8fo\82µ\83n\81[\83h\82ð\90Ú\91±\82µ\82½ Windows \8aÂ\8b«
+* Windows XP \82É\82Ä\93®\8dì\8am\94F\82µ\82Ä\82¢\82Ü\82·\81B\82½\82Ô\82ñ Win95 \82Ü\82Å\82È\82ç\91å\8fä\95v\81B
+* \83p\83\89\83\8c\83\8b\83|\81[\83g\83A\83h\83\8c\83X\82Í 0x0378 \8cÅ\92è\82Å\82·\81BUSB \90Ú\91±\82Ì\82à\82Ì\82Í\8eg\82¦\82é\82©\95ª
+  \82©\82è\82Ü\82¹\82ñ\81B
+
+GIVEIO.SYS \82ð\83C\83\93\83X\83g\81[\83\8b\82µ\82½\8aÂ\8b«
+* \83p\83b\83P\81[\83W\82É\82Í\8aÜ\82Ü\82ê\82Ä\82¢\82Ü\82¹\82ñ\82Ì\82Å\95Ê\93r\97p\88Ó\82µ\82Ä\82­\82¾\82³\82¢\81B
+
+cmd.exe, rxvt \82È\82Ç\82Ì\83R\83}\83\93\83h\83\89\83C\83\93\83V\83F\83\8b
+
+--\83n\81[\83h\83E\83F\83A\82Ì\91I\91ð--
+\83N\83\89\83C\83A\83\93\83g\82É\82Â\82¢\82Ä\82¢\82é unagi.cfg \82ð\83e\83L\83X\83g\83G\83f\83B\83^\82Å\95Ò\8fW\82µ\82Ä\8eg\97p\82·
+\82é\83n\81[\83h\82ð\91I\82ñ\82Å\82­\82¾\82³\82¢\81B\8ds\93ª\82É # \82ª\82Â\82¢\82Ä\82¢\82é\82à\82Ì\82Í\96³\8e\8b\82³\82ê\82Ü\82·\81B
+
+--\83R\83}\83\93\83h\83\89\83C\83\93\88ø\90\94--
+unagi.exe [mode] [script file] [target file] ...
+== d ROM DUMP MODE ==
+ROM \83C\83\81\81[\83W\82ð\8dì\90¬\82µ\82Ü\82·\81B
+unagi.exe d [script file] [dump file] [flag] [mapper]
+script file - \91Î\89\9e\82·\82é\83}\83b\83p\82Ì ROM \83X\83N\83\8a\83v\83g\83t\83@\83C\83\8b\82ð\8ew\92è\82µ\82Ü\82·\81B
+dump file   - \8fo\97Í\82·\82é ROM \83C\83\81\81[\83W\83t\83@\83C\83\8b\82ð\8ew\92è\82µ\82Ü\82·\81B
+\88È\89º\82Í\81A\92Ê\8fí\82Í\95K\97v\82 \82è\82Ü\82¹\82ñ\81B
+flag        - \8fo\97Í\82·\82é\83w\83b\83_\82ð\90Ý\92è\82µ\82Ü\82·\81B\95¡\90\94\82Ì\8fê\8d\87\82Í\83X\83y\81[\83X\82ð\82¢\82ê\82¸\82É              \8bL\8fq\82µ\82Ü\82·\81B
+  S \83J\81[\83g\83\8a\83b\83W\82É backup RAM \82ª\82Â\82¢\82Ä\82¢\82é\8fê\8d\87
+  V \83X\83N\83\8a\83v\83g\82Ì\90Ý\92è\82ð\96³\8e\8b\82µ\82Ä mirroring \82ð Vertical \82É\82·\82é
+  H \83X\83N\83\8a\83v\83g\82Ì\90Ý\92è\82ð\96³\8e\8b\82µ\82Ä mirroring \82ð Horizonal \82É\82·\82é
+  _ mapper\95Ï\8dX\82¾\82¯\82ð\93K\97p\82·\82é\8fê\8d\87
+mapper      - \83X\83N\83\8a\83v\83g\82Ì\90Ý\92è\82ð\96³\8e\8b\82µ\82Ä\83}\83b\83p\94Ô\8d\86\82ð\90Ý\92è\82µ\82Ü\82·\81B
+
+== r RAM READ MODE ==
+\83o\83b\83N\83A\83b\83v RAM \83C\83\81\81[\83W\82ð PC \8fã\82É\8dì\90¬\82µ\82Ü\82·\81B
+unagi.exe r [script file] [dump file]
+script file - \91Î\89\9e\82·\82é\83}\83b\83p\82Ì RAM \83X\83N\83\8a\83v\83g\83t\83@\83C\83\8b\82ð\8ew\92è\82µ\82Ü\82·\81B
+dump file   - \8fo\97Í\82·\82é RAM \83C\83\81\81[\83W\83t\83@\83C\83\8b\82ð\8ew\92è\82µ\82Ü\82·\81B
+
+== w RAM WRITE MODE ==
+\83o\83b\83N\83A\83b\83v RAM \83C\83\81\81[\83W\82ð\83J\81[\83g\83\8a\83b\83W\82Ö\93]\91\97\82µ\82Ü\82·\81B
+unagi.exe w [script file] [ram file]
+script file - \91Î\89\9e\82·\82é\83}\83b\83p\82Ì RAM \83X\83N\83\8a\83v\83g\83t\83@\83C\83\8b\82ð\8ew\92è\82µ\82Ü\82·\81B
+ram file    - \93ü\97Í\82·\82é RAM \83C\83\81\81[\83W\83t\83@\83C\83\8b\82ð\8ew\92è\82µ\82Ü\82·\81B
+
+== f flashmemory/SRAM PROGRAM MODE ==
+\83J\81[\83g\83\8a\83b\83W\8fã\82Ì ROM \82ð flashmemory \82© SRAM \82É\8cð\8a·\82µ\82½\8fã\82Å\81AROM \83C\83\81\81[
+\83W\83f\81[\83^\82ð\91ã\91Ö\83f\83o\83C\83X\82É\93]\91\97\82·\82é\83\82\81[\83h\82Å\82·\81B\90§\8cÀ\82Í\91½\82¢\82Å\82·\82ª\81A\88ê\89\9e\93®\8dì
+\8eÀ\90Ñ\82ª\82 \82è\82Ü\82·\81B
+\8eÀ\8c±\97v\91f\82ª\91½\82¢\8eÀ\91\95\82Ì\82½\82ß\81A\8fÚ\8d×\82Í\8cÂ\95Ê\82É\96â\82¢\8d\87\82í\82¹\82Ä\82­\82¾\82³\82¢\81B
+email: unagi.kaihatu@gmail.com
+
+--\83X\83N\83\8a\83v\83g\8ed\97l--
+ROM dump script \83p\83b\83P\81[\83W\82Ì syntax.txt \82ð\8eQ\8fÆ\82µ\82Ä\82­\82¾\82³\82¢\81B
+
+--\83\89\83C\83Z\83\93\83X--
+unagi \83N\83\89\83C\83A\83\93\83g\82Ì\83o\83C\83i\83\8a\82Æ\83\\81[\83X\83R\81[\83h(\97á\8aO\97L\82è)\82Í\89º\8bL\82ª\93K\97p\82³\82ê\82Ü
+\82·\81Bunagi \83X\83N\83\8a\83v\83g\82Í sato_tiff \82ª\8dì\90¬\82µ\82½\82à\82Ì\82Í\89º\8bL\82ª\93K\97p\82³\82ê\82Ü\82·\81B
+GNU Lesser General Public License v2
+
+\97á\8aO\95¨
+- GIVEIO.SYS\83A\83N\83Z\83X\83\89\83C\83u\83\89\83\8a\82É\8aÜ\82Ü\82ê\82é giveio.c, giveio.h
+\82¦\82Ó\81E\82Ò\81[\81E\82\81[\81E\82¦\81[\81E\82Ï\81[\82­\8aÇ\97\9d\90l\82Ì\81u\82³\82Æ\82¤\81v\82³\82ñ\82Ì\82²\8cú\88Ó\82É\82æ\82è\83\\81[
+\83X\83R\81[\83h\82à\94z\95z\83\\81[\83X\82É\8aÜ\82ß\82Ä\82æ\82¢\8b\96\89Â\82ð\82¢\82½\82¾\82¢\82Ä\82¨\82è\82Ü\82·\81B\93ñ\8e\9f\94z\95z\82È\82Ç
+\82Ì\8eæ\82è\88µ\82¢\82Í\82³\82Æ\82¤\82³\82ñ\82Ì\8b\96\89Â\82ð\93¾\82Ä\82­\82¾\82³\82¢\81B
+
+- GIVEIO.SYS
+\94z\95z\83p\83b\83P\81[\83W\82É\82à\8aÜ\82ß\82Ü\82¹\82ñ\82µ\81A\8dì\8eÒ\82ª\92N\82È\82Ì\82©\82à\82í\82©\82ç\82È\82¢\82Ì\82Å\83p\83b\83P\81[
+\83W\82É\8aÜ\82ß\82È\82¢\82Å\82­\82¾\82³\82¢\81B
+
+- client_test.c
+\8eÀ\8c±\93I\82È\83\\81[\83X\82ª\93ü\82Á\82Ä\82¢\82é\82Ì\82Æ\81A\82È\82­\82Ä\82à RELEASE \83r\83\8b\83h\82Í\89Â\94\\82È\82±\82Æ\81A
+\96³\92f\93]\97p\82Å\82Ì\83g\83\89\83u\83\8b\82ð\96h\82®\82½\82ß\82É\94ñ\8cö\8aJ\82É\82µ\82Ü\82µ\82½\81B\8cÂ\95Ê\82É\97v\96]\82ª\82 \82ê\82Î
+\83\\81[\83X\82Í\8cö\8aJ\82µ\82Ü\82·\81B
+
+--\8eÓ\8e«--
+* \8e\91\97¿\92ñ\8b\9f\82ð\82µ\82Ä\82­\82ê\82½ color \82³\82ñ, VirtuaNES \82Ì\83\\81[\83X, nesdev
+* GIVEIO.SYS\83A\83N\83Z\83X\83\89\83C\83u\83\89\83\8a\82Ì\82³\82Æ\82¤\82³\82ñ
+* \83n\81[\83h\83E\83F\83A\82ð\91Ý\82µ\82Ä\82­\82ê\82½\83J\83V\83I\83\93
+* \83A\83C\83R\83\93\82ð\95`\82¢\82Ä\82­\82ê\82½\82Ð\82ë\82Ð\82ë\82«\82³\82ñ
+* \83v\83\8d\83O\83\89\83~\83\93\83O\8aÂ\8b«\82Ì mingw \82Æ rxvt
+* \8ae\8eí\8eÀ\8c±\82É\8b¦\97Í\82µ\82Ä\82­\82¾\82³\82Á\82Ä\82¢\82é\82Î\82­\82Ä\82ñ\82³\82ñ
diff --git a/client/tag/0.5.3/version.h b/client/tag/0.5.3/version.h
new file mode 100644 (file)
index 0000000..b6a71ec
--- /dev/null
@@ -0,0 +1,8 @@
+//include from unagi.c only
+static const char STR_VERSION[] = "0.5.3 "
+#if DEBUG==1
+"debug "
+#else
+"release "
+#endif
+"build";