OSDN Git Service

0.4.0 release
authorsato_tiff <sato_tiff@24ea1065-a21e-4ca1-99c9-f5125deb0858>
Wed, 19 Nov 2008 02:44:27 +0000 (02:44 +0000)
committersato_tiff <sato_tiff@24ea1065-a21e-4ca1-99c9-f5125deb0858>
Wed, 19 Nov 2008 02:44:27 +0000 (02:44 +0000)
git-svn-id: svn+ssh://svn.osdn.net/svnroot/unagi@34 24ea1065-a21e-4ca1-99c9-f5125deb0858

20 files changed:
client/tag/0.4.0/Makefile [new file with mode: 0644]
client/tag/0.4.0/file.c [new file with mode: 0644]
client/tag/0.4.0/file.h [new file with mode: 0644]
client/tag/0.4.0/giveio.c [new file with mode: 0644]
client/tag/0.4.0/giveio.h [new file with mode: 0644]
client/tag/0.4.0/header.c [new file with mode: 0644]
client/tag/0.4.0/header.h [new file with mode: 0644]
client/tag/0.4.0/kairo.h [new file with mode: 0644]
client/tag/0.4.0/meg.ico [new file with mode: 0644]
client/tag/0.4.0/paralellport.c [new file with mode: 0644]
client/tag/0.4.0/paralellport.h [new file with mode: 0644]
client/tag/0.4.0/script.c [new file with mode: 0644]
client/tag/0.4.0/script.h [new file with mode: 0644]
client/tag/0.4.0/textutil.c [new file with mode: 0644]
client/tag/0.4.0/textutil.h [new file with mode: 0644]
client/tag/0.4.0/type.h [new file with mode: 0644]
client/tag/0.4.0/unagi.c [new file with mode: 0644]
client/tag/0.4.0/unagi.ico [new file with mode: 0644]
client/tag/0.4.0/unagi.rc [new file with mode: 0644]
client/tag/0.4.0/unagi.txt [new file with mode: 0644]

diff --git a/client/tag/0.4.0/Makefile b/client/tag/0.4.0/Makefile
new file mode 100644 (file)
index 0000000..59bb98a
--- /dev/null
@@ -0,0 +1,22 @@
+OBJ = \
+       unagi.o paralellport.o script.o header.o \
+       file.o textutil.o giveio.o unagi.res.o
+TARGET = unagi.exe
+CFLAGS = -O0 -Wall -g -DDEBUG=1
+#CFLAGS = -O2 -Wall -DDEBUG=0
+
+all: $(TARGET)
+clean: 
+       rm -f $(OBJ)
+$(TARGET): $(OBJ)
+       gcc -o $@ $(OBJ)
+unagi.res.o: unagi.rc unagi.ico
+       windres -i $< -o $@
+file.o: file.c file.h type.h
+giveio.o: giveio.c giveio.h
+header.o: header.c type.h file.h header.h
+paralellport.o: paralellport.c type.h kairo.h paralellport.h
+script.o: script.c type.h file.h paralellport.h giveio.h textutil.h \
+  header.h script.h
+unagi.o: unagi.c type.h paralellport.h giveio.h script.h
+textutil.o: textutil.c type.h textutil.h
diff --git a/client/tag/0.4.0/file.c b/client/tag/0.4.0/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.4.0/file.h b/client/tag/0.4.0/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.4.0/giveio.c b/client/tag/0.4.0/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.4.0/giveio.h b/client/tag/0.4.0/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.4.0/header.c b/client/tag/0.4.0/header.c
new file mode 100644 (file)
index 0000000..f9b555d
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+famicom ROM cartridge dump program - unagi
+iNES header/buffer control
+
+todo:
+* buffer ¤Î malloc ÊýË¡¤Î¤ä¤êľ¤·?
+* (¤³¤Î¥½¡¼¥¹³°¤Î»Å»ö¤À¤±¤É)mirror, battery, mapper number ¤ò¥³¥Þ¥ó¥É¥é¥¤¥ó¤«¤é¤â»ØÄê¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
+*/
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "type.h"
+#include "file.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
+};
+
+static void nesheader_set(const struct romimage *r, u8 *header)
+{
+       memcpy(header, NES_HEADER_INIT, NES_HEADER_SIZE);
+       header[4] = r->cpu_rom.size >> (4*3 + 2);
+       header[5] = r->ppu_rom.size >> (4*3 + 1);
+       if(r->mirror == MIRROR_VERTICAL){
+               header[6] |= 0x01;
+       }
+       if(r->cpu_ram.size != 0){
+               header[6] |= 0x02;
+       }
+       //4 screen ¤Ï̵»ë
+       header[6] |= (r->mappernum & 0x0f) << 4;
+       header[7] |= r->mappernum & 0xf0;
+}
+
+static void 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;
+               }
+               mirror_size /= 2;
+       }
+       if(m->size != min){
+               printf("mirroring %s rom fixed\n", m->name);
+       }
+       m->size = min;
+}
+
+void nesfile_create(struct romimage *r, const char *romfilename)
+{
+       mirroring_fix(&(r->cpu_rom), PROGRAM_ROM_MIN);
+       if(r->ppu_rom.size != 0){
+               mirroring_fix(&(r->ppu_rom), CHARCTER_ROM_MIN);
+       }
+
+       FILE *f;
+       nesheader_set(r, r->neshead);
+       f = fopen(romfilename, "wb");
+       fseek(f, 0, SEEK_SET);
+       fwrite(r->neshead, 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);
+}
+
+/*
+NES fileimage ¤¬¤½¤Î¤Þ¤Þ»È¤¨¤ë¤è¤¦¤ÊÎΰè¤ò³ÎÊݤ·¡¢³ÆÍÑÅÓÊ̥ݥ¤¥ó¥¿¤òÄ¥¤ë
++0     NESHEADER
++0x10  Program ROM
++....  Charcter ROM (¤Ê¤¤¾ì¹ç¤Ï NULL)
++....  Backup RAM (¤Ê¤¤¾ì¹ç¤Ï NULL)
+
+NES file ½ÐÎÏ»þ¤Ï neshead ¤«¤é ROM ¥µ¥¤¥ºÊ¬½ÐÎϤ¹¤ë¤À¤±¡£
+²òÊü»þ¤Ï nesheader ¤ò free ¤¹¤ë¤À¤±
+*/
+int nesbuffer_malloc(struct romimage *r)
+{
+       u8 *p;
+       const int nessize = NES_HEADER_SIZE + r->cpu_rom.size + r->ppu_rom.size + r->cpu_ram.size;
+       r->neshead = malloc(nessize);
+       if(r->neshead == NULL){
+               printf("%s: malloc failed\n", __FUNCTION__);
+               return NG;
+       }
+       p = r->neshead + NES_HEADER_SIZE;
+       r->cpu_rom.data = p;
+       p += r->cpu_rom.size;
+       if(r->ppu_rom.size != 0){
+               r->ppu_rom.data = p;
+       }
+       p += r->ppu_rom.size;
+       if(r->cpu_ram.size != 0){
+               r->cpu_ram.data = p;
+       }
+       return OK;
+}
+
+void nesbuffer_free(struct romimage *t)
+{
+       free(t->neshead);
+}
+
+void backupram_create(const struct memory *r, const char *ramfilename)
+{
+       buf_save(r->data, ramfilename, r->size);
+}
diff --git a/client/tag/0.4.0/header.h b/client/tag/0.4.0/header.h
new file mode 100644 (file)
index 0000000..cc80dea
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _HEADER_H_
+#define _HEADER_H_
+struct memory{
+       const char *name;
+       int size, offset;
+       u8 *data;
+};
+struct romimage{
+       u8 *neshead;
+       struct memory cpu_rom, cpu_ram, ppu_rom;
+       int mappernum;
+       int mirror;
+};
+
+enum{
+       MIRROR_HORIZONAL = 0,
+       MIRROR_VERTICAL,
+       MIRROR_PROGRAMABLE = MIRROR_HORIZONAL
+};
+int nesbuffer_malloc(struct romimage *r);
+void nesfile_create(struct romimage *r, const char *romfilename);
+void nesbuffer_free(struct romimage *r);
+void backupram_create(const struct memory *r, const char *ramfilename);
+#endif
diff --git a/client/tag/0.4.0/kairo.h b/client/tag/0.4.0/kairo.h
new file mode 100644 (file)
index 0000000..c41facf
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef _KAIRO_H_
+#define _KAIRO_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.4.0/meg.ico b/client/tag/0.4.0/meg.ico
new file mode 100644 (file)
index 0000000..d2d452b
Binary files /dev/null and b/client/tag/0.4.0/meg.ico differ
diff --git a/client/tag/0.4.0/paralellport.c b/client/tag/0.4.0/paralellport.c
new file mode 100644 (file)
index 0000000..c4dd6ee
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+famicom ROM cartridge dump program - unagi
+emuste.net ¤Ç¤ª¤Ê¤¸¤ß¤Î¤â¤Î¤Î¥Ï¡¼¥É¥É¥é¥¤¥Ð
+
+todo: 
+* battery backup RAM ¤òÆɤá¤ë¤è¤¦¤Ë¤¹¤ë(namco109 ¤ÏÆɤá¤Æ¤¤¤ë¤Î¤«ÅÅÃÓ¤¬ÀÚ¤ì¤Æ¤ë¤Î¤«¤è¤¯¤ï¤«¤é¤Ê¤¤¡¢¤½¤Î¾¤ÏÁ´ÌÇ)
+* _outp(), _inp() ¤òÌÀ³Î¤Ë»È¤¨¤ë¤è¤¦¤Ë¤¹¤ë¤«¡¢¥¤¥ó¥é¥¤¥ó¥¢¥»¥ó¥Ö¥é¤Ë¤¹¤ë
+* Ê̤Υϡ¼¥É¥¦¥§¥¢¤ËÂбþ¤·¤¿¾ì¹ç¤Ï PORT_DATA ¤«¤é wait ¤Þ¤Ç¤ò¥Ø¥Ã¥À¤Ë¤Þ¤È¤á¤ë
+*/
+//#include <dos.h> ?
+//#include <windows.h>
+#include "type.h"
+#include "kairo.h"
+#include "paralellport.h"
+
+enum{
+       PORT_DATA = 0x0378,
+       PORT_STATUS,
+       PORT_CONTROL
+};
+enum{
+       ADDRESS_MASK_A0toA14 = 0x7fff,
+       ADDRESS_MASK_A15 = 0x8000
+};
+//mingw ¤À¤È conio.h ¤Ë _outp, _inp ¤¬¤Ê¤¤¤±¤É¡¢¥ê¥ó¥¯¤Ç¤­¤ë...
+//¼«Á°¥×¥í¥È¥¿¥¤¥×¤Ç¤¤¤¤¤Î¤«?
+void _outp(int, int);
+int _inp(int);
+
+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(void)
+{
+       //const long waittime = 100000;
+       //SleepEx(20,TRUE);
+}
+
+static inline void bus_control(int data)
+{
+       _outp(PORT_DATA, data);
+       wait();
+}
+
+/*
+CONTROL bit0 STROBE
+¥Ç¡¼¥¿¤¬È¿Å¾¤¹¤ë
+*/
+static inline void address_control(int data)
+{
+       data &= 0x01;
+       data ^= 0x01;
+       _outp(PORT_CONTROL, data);
+       wait();
+}
+
+/* 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)
+{
+       int data = _inp(PORT_STATUS);
+       data >>= 7;
+       data &= 0x01;
+       return data ^ 0x01;
+}
+
+/* 
+L->H ¤Çshift 
+*/
+static 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)
+);
+void reader_init(void)
+{
+       bus_control(BUS_CONTROL_INIT);
+       address_reset();
+}
+
+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)
+);
+
+#define M2_SET_READ (0)
+static void fc_bus_read(long address, long length, u8 *data, int control)
+{
+       address_set(address, control);
+       bus_control(control);
+       if(M2_SET_READ == 1){
+               control = bit_clear(control, BITNUM_CPU_M2);
+               bus_control(control); //H->L: mapper ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
+       }
+       while(length != 0){
+               if(M2_SET_READ == 1){
+                       //L->H: mapper ¤¬ data ¤ò½Ð¤¹
+                       control = bit_set(control, BITNUM_CPU_M2);
+               }
+               *data = data_get(control);
+               if(M2_SET_READ == 1){
+                       //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_SET_READ == 1){
+                       //H->L: mapper ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
+                       control = bit_clear(control, BITNUM_CPU_M2);
+                       bus_control(control);
+               }
+
+               data++;
+               length--;
+       }
+       control = bit_set(control, BITNUM_CPU_M2);
+}
+
+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);
+}
+
+void ppu_read(long address, long length, u8 *data)
+{
+       fc_bus_read(address, length, data, BUS_CONTROL_PPU_READ);
+}
+/*
+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
+*/
+void cpu_write(long address, long data)
+{
+       int control = BUS_CONTROL_BUS_WRITE;
+       //addressÀßÄê + Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
+       address_set(address, control);
+
+       control = bit_clear(control, BITNUM_CPU_M2);
+       //printf("%02x ", (int) data);
+       data_set(control, data);
+
+       control = bit_clear(control, BITNUM_CPU_RW);
+       //bus_control(control); //
+       control = bit_set(control, BITNUM_CPU_M2);
+       //bus_control(control); //
+       if(address & ADDRESS_MASK_A15){
+               control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
+       }
+       bus_control(control);
+       control = bit_clear(control, BITNUM_CPU_M2);
+       bus_control(control);
+       bus_control(BUS_CONTROL_BUS_WRITE);
+}
+
+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); //mmc1 ¤Ï¤Ê¤¯¤Æ¤â¤¤¤±¤ë¤¬ mmc3 ¤Ë¤ÏɬÍ×
+       bus_control(control);
+       bus_control(BUS_CONTROL_BUS_WRITE);
+}
diff --git a/client/tag/0.4.0/paralellport.h b/client/tag/0.4.0/paralellport.h
new file mode 100644 (file)
index 0000000..8f0acb3
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _PARALELLPORT_H
+#define _PARALELLPORT_H
+
+void reader_init(void);
+void cpu_read(long address, long length, u8 *data);
+void ppu_read(long address, long length, u8 *data);
+void cpu_write(long address, long data);
+void ppu_write(long address, long data);
+#endif
diff --git a/client/tag/0.4.0/script.c b/client/tag/0.4.0/script.c
new file mode 100644 (file)
index 0000000..cca9fb2
--- /dev/null
@@ -0,0 +1,882 @@
+/*
+famicom ROM cartridge dump program - unagi
+script engine
+
+todo: 
+* Ê̤ÎÆɤ߽Ф·¥Ï¡¼¥É¤ËÂбþ¤·¤¿¤È¤­¤Ï cpu_read ¤Ê¤É¤ò´Ø¿ô¥Ý¥¤¥ó¥¿¤Ë¤Þ¤È¤á¤¿ struct ¤òÍÑ°Õ¤·¤Æ¼Â¹Ô¤¹¤ë
+* ÊÑ¿ô´ÉÍý¤Î¥°¥í¡¼¥Ð¥ëÃͤò¡¢logical_test(), excute() ¥í¡¼¥«¥ë¤Ë¤·¤¿¤¤
+* RAM ¥¢¥¯¥»¥¹¤¬¤Ç¤­¼¡Âè¡¢RAM Æɤ߽Ф·¥¹¥¯¥ê¥×¥È¤âÀ߷פ¹¤ë
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "type.h"
+#include "file.h"
+#include "paralellport.h"
+#include "giveio.h"
+#include "textutil.h"
+#include "header.h"
+#include "script.h"
+
+#define OP_PPU_WRITE_ENABLE (0)
+/*
+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
+*/
+struct script_syntax{
+       const char *name;
+       int script_opcode;
+       int argc, compare;
+       int argv_type[4];
+};
+enum{
+       SYNTAX_ARGVTYPE_NULL,
+       SYNTAX_ARGVTYPE_VALUE,
+       SYNTAX_ARGVTYPE_HV,
+       SYNTAX_ARGVTYPE_EXPRESSION,
+       SYNTAX_ARGVTYPE_VARIABLE
+};
+enum{
+       SYNTAX_COMPARE_EQ,
+       SYNTAX_COMPARE_GT
+};
+enum{
+       SCRIPT_OPCODE_MAPPER,
+       SCRIPT_OPCODE_MIRROR,
+       SCRIPT_OPCODE_CPU_ROMSIZE,
+       SCRIPT_OPCODE_CPU_RAMSIZE,
+       SCRIPT_OPCODE_PPU_ROMSIZE,
+       SCRIPT_OPCODE_DUMP_START,
+       SCRIPT_OPCODE_CPU_READ,
+       SCRIPT_OPCODE_CPU_WRITE,
+       SCRIPT_OPCODE_PPU_RAMTEST,
+       SCRIPT_OPCODE_PPU_READ,
+       SCRIPT_OPCODE_PPU_WRITE,
+       SCRIPT_OPCODE_STEP_START,
+       SCRIPT_OPCODE_STEP_END,
+       SCRIPT_OPCODE_DUMP_END,
+       SCRIPT_OPCODE_COMMENT,
+       SCRIPT_OPCODE_NUM
+};
+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 struct script_syntax SCRIPT_SYNTAX[] = {
+       {"MAPPER", SCRIPT_OPCODE_MAPPER, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {"MIRROR", SCRIPT_OPCODE_MIRROR, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_HV, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {OPSTR_CPU_ROMSIZE, SCRIPT_OPCODE_CPU_ROMSIZE, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+//     {OPSTR_CPU_RAMSIZE, SCRIPT_OPCODE_CPU_RAMSIZE, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {OPSTR_PPU_ROMSIZE, SCRIPT_OPCODE_PPU_ROMSIZE, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {"DUMP_START", SCRIPT_OPCODE_DUMP_START, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {"CPU_READ", SCRIPT_OPCODE_CPU_READ, 2, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {"CPU_WRITE", SCRIPT_OPCODE_CPU_WRITE, 2, SYNTAX_COMPARE_GT, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_EXPRESSION, SYNTAX_ARGVTYPE_EXPRESSION, SYNTAX_ARGVTYPE_EXPRESSION}},
+       {"PPU_RAMTEST", SCRIPT_OPCODE_PPU_RAMTEST, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {"PPU_READ", SCRIPT_OPCODE_PPU_READ, 2, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+#if OP_PPU_WRITE_ENABLE==1
+       {"PPU_WRITE", SCRIPT_OPCODE_PPU_WRITE, 2, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+#endif
+       {"STEP_START", SCRIPT_OPCODE_STEP_START, 4, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VARIABLE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE}},
+       {"STEP_END", SCRIPT_OPCODE_STEP_END, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
+       {"DUMP_END", SCRIPT_OPCODE_DUMP_END, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}}
+};
+
+//ÊÑ¿ô´ÉÍý
+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 = {
+       '\0', 0, 0, 0, 0,
+       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:";
+
+static int syntax_check_phase(char **word, int word_num, struct script *s)
+{
+       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;
+                       {
+                               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;
+                               }
+                       }
+                       return 0;
+               }
+               syntax++;
+               i--;
+       }
+       printf("%s unknown opcode %s\n", SYNTAX_ERROR_PREFIX, word[0]);
+       return 1;
+}
+
+static int syntax_check(char **text, int text_num, struct script *s)
+{
+       int error = 0;
+       int i;
+       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);
+               }
+               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 logical_check(const struct script *s, struct romimage *r, const int test)
+{
+       long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
+       int setting = SETTING, error = 0;
+       //romimage init
+       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;
+               }
+               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:
+                       r->cpu_rom.size = s->value[0];
+                       break;
+               case SCRIPT_OPCODE_CPU_RAMSIZE:
+                       r->cpu_ram.size = s->value[0];
+                       break;
+               case SCRIPT_OPCODE_PPU_ROMSIZE:
+                       r->ppu_rom.size = s->value[0];
+                       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;
+                       //length filter. 0 ¤Ï¤À¤á
+                       if(!is_range(length, 1, 0x4000)){
+                               logical_print_illgallength(STR_REGION_CPU, length);
+                               error += 1;
+                       }
+                       //address filter
+                       else if(address < 0x6000 || address >= 0x10000){
+                               logical_print_illgalarea(STR_REGION_CPU, address);
+                               error += 1;
+                       }else if (end >= 0x10000){
+                               logical_print_overdump(STR_REGION_CPU, address, end);
+                               error += 1;
+                       }
+                       //dump length update
+                       if(is_region_cpuram(address)){
+                               cpu_ramsize += length;
+                       }else if(is_region_cpurom(address)){
+                               cpu_romsize += length;
+                       }
+                       if(test == 1){
+                               logical_print_access(STR_REGION_CPU, STR_ACCESS_READ, address, 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;
+                       }
+                       if(test == 1){
+                               logical_print_access(STR_REGION_CPU, STR_ACCESS_WRITE, address, data);
+                       }
+                       setting = DUMP;
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_RAMTEST:
+                       //logical check ¤Ç¤Ï¤Ê¤Ë¤â¤·¤Ê¤¤
+                       break;
+               case SCRIPT_OPCODE_PPU_READ:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       const long end = address + length - 1;
+                       //length filter. 0 ¤òÍÆǧ¤¹¤ë
+                       if(!is_range(length, 0, 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(is_region_ppurom(address)){
+                               ppu_romsize += length;
+                       }
+                       if(test == 1){
+                               logical_print_access(STR_REGION_PPU, STR_ACCESS_READ, address, length);
+                       }
+                       setting = DUMP;
+                       }
+                       break;
+#if OP_PPU_WRITE_ENABLE==1
+               case SCRIPT_OPCODE_PPU_WRITE:{
+                       const long address = s->value[0];
+                       const long data = s->value[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;
+                       }
+                       if(test == 1){
+                               logical_print_access(STR_REGION_PPU, STR_ACCESS_WRITE, address, data);
+                       }
+                       }
+                       break;
+#endif
+               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);
+       return error;
+}
+
+/*
+execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
+*/
+enum {PPU_TEST_RAM, PPU_TEST_ROM};
+const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
+/*static*/ int ppu_ramtest(void)
+{
+       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){
+                       ppu_write(address++, 0);
+                       i--;
+               }
+       }
+       
+       //ppu test data write
+       {
+               const u8 *d;
+               int i = length;
+               long address = testaddr;
+               d = PPU_TEST_DATA;
+               while(i != 0){
+                       ppu_write(address++, (long) *d);
+                       d++;
+                       i--;
+               }
+       }
+
+       u8 writedata[length];
+       ppu_read(testaddr, length, writedata);
+       if(memcmp(writedata, PPU_TEST_DATA, length) == 0){
+               return PPU_TEST_RAM;
+       }
+       return PPU_TEST_ROM;
+}
+
+static void readbuffer_print(const struct memory *m, long length)
+{
+       if(length >= 0x10){
+               length = 0x10;
+       }
+       printf("%s 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);
+       fflush(stdout);
+}
+
+static void read_result_print(const struct memory *m, long length)
+{
+       readbuffer_print(m, length);
+       checksum_print(m->data, length);
+}
+
+static int execute(const struct script *s, struct romimage *r)
+{
+       const int gg = giveio_start();
+       switch(gg){
+       case GIVEIO_OPEN:
+       case GIVEIO_START:
+       case GIVEIO_WIN95:
+               reader_init();
+               break;
+       default:
+       case GIVEIO_ERROR:
+               printf("execute error: Can't Access Direct IO %d\n", gg);
+               return NG;
+       }
+       struct memory cpu_rom, cpu_ram, ppu_rom;
+       cpu_rom = r->cpu_rom;
+       cpu_ram = r->cpu_ram;
+       ppu_rom = r->ppu_rom;
+       
+       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 addr = s->value[0];
+                       const long length = s->value[1];
+                       m = &cpu_rom;
+                       if(is_region_cpuram(addr)){
+                               m = &cpu_ram;
+                       }
+                       cpu_read(addr, 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);
+                       cpu_write(s->value[0], data);
+                       }
+                       break;
+               case SCRIPT_OPCODE_PPU_RAMTEST:
+                       if(ppu_ramtest() == PPU_TEST_RAM){
+                               printf("PPU_RAMTEST: charcter RAM found\n");
+                               r->ppu_rom.size = 0;
+                               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;
+                               ppu_read(address, 1, &dummy);
+                       }else{
+                               ppu_read(address, length, ppu_rom.data);
+                               read_result_print(&ppu_rom, length);
+                       }
+                       ppu_rom.data += length;
+                       ppu_rom.offset += length;
+                       }
+                       break;
+#if OP_PPU_WRITE_ENABLE==1
+               case SCRIPT_OPCODE_PPU_WRITE:
+                       ppu_write(s->value[0], s->value[1]);
+                       break;
+#endif
+               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++;
+               }
+       }
+       if(gg != GIVEIO_WIN95){
+               giveio_stop(GIVEIO_STOP);
+       }
+       return OK;
+}
+
+void script_load(const char *scriptfile, const char *nesfile, const int test_only)
+{
+       struct script *s;
+       {
+               int scriptsize = 0;
+               char *buf;
+               
+               buf = buf_load_full(scriptfile, &scriptsize);
+               if(buf == NULL){
+                       printf("scriptfile open error\n");
+                       return;
+               }
+               char *text[TEXT_MAXLINE];
+               const int text_num = text_load(buf, scriptsize, text);
+               if(text_num == 0){
+                       printf("script line too much\n");
+                       free(buf);
+                       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);
+               free(buf);
+               if(error != 0){
+                       free(s);
+                       return;
+               }
+       }
+       struct romimage r = {
+               cpu_rom: {
+                       size: 0, offset: 0,
+                       data: NULL,
+                       name: STR_REGION_CPU
+               },
+               cpu_ram: {
+                       size: 0, offset: 0,
+                       data: NULL,
+                       name: STR_REGION_CPU
+               },
+               ppu_rom: {
+                       size: 0, offset: 0,
+                       data: NULL,
+                       name: STR_REGION_PPU
+               },
+               neshead: NULL,
+               mappernum: 0,
+               mirror: MIRROR_PROGRAMABLE
+       };
+       if((logical_check(s, &r, test_only) == 0) && (test_only == 0)){
+               //dump RAM Îΰè¼èÆÀ
+               if(nesbuffer_malloc(&r) == NG){
+                       free(s);
+                       return;
+               }
+               //dump
+               if(execute(s, &r) == OK){
+                       //À®²Ì½ÐÎÏ
+                       nesfile_create(&r, nesfile);
+                       if(r.cpu_ram.size != 0){
+                               backupram_create(&(r.cpu_ram), "hoe.sav");
+                       }
+               }
+               //dump RAM Îΰè²òÊü
+               nesbuffer_free(&r);
+       }
+       free(s);
+}
diff --git a/client/tag/0.4.0/script.h b/client/tag/0.4.0/script.h
new file mode 100644 (file)
index 0000000..a76dadf
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _SCRIPT_H_
+#define _SCRIPT_H_
+int ppu_ramtest(void);
+void script_load(const char *scriptfile, const char *nesfile, const int test_only);
+
+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.4.0/textutil.c b/client/tag/0.4.0/textutil.c
new file mode 100644 (file)
index 0000000..7bbe6c2
--- /dev/null
@@ -0,0 +1,183 @@
+#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;
+       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){
+                               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[10];
+       *val = strtol(str, error, base);
+       if(error[0][0] != '\0'){
+               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.4.0/textutil.h b/client/tag/0.4.0/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.4.0/type.h b/client/tag/0.4.0/type.h
new file mode 100644 (file)
index 0000000..75e7d71
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _TYPE_H_
+#define _TYPE_H_
+typedef unsigned char u8;
+enum{
+       OK = 0, NG
+};
+#endif
diff --git a/client/tag/0.4.0/unagi.c b/client/tag/0.4.0/unagi.c
new file mode 100644 (file)
index 0000000..21f94ad
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+famicom ROM cartridge dump program - unagi
+command line interface
+
+todo:
+* test ÍѤδؿô¤Ê¤É¤Î¥³¥Þ¥ó¥É¥é¥¤¥ó·ÏÅý¤òÅý°ì¤¹¤ë
+* mirror, battery, mapper number ¤ò¥³¥Þ¥ó¥É¥é¥¤¥ó¤«¤é¤â»ØÄê¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include "type.h"
+#include "paralellport.h"
+#include "giveio.h"
+#include "file.h"
+#include "script.h"
+
+static void backupram_test(const char *file)
+{
+       const int gg = giveio_start();
+       switch(gg){
+       case GIVEIO_OPEN:
+       case GIVEIO_START:
+       case GIVEIO_WIN95:
+               reader_init();
+               break;
+       default:
+       case GIVEIO_ERROR:
+               printf("Can't Access Direct IO %d\n", gg);
+               return;
+       }
+
+       switch(file[0]){
+       case 'p':
+               printf("%d\n", ppu_ramtest());
+               break;
+       case 'b':{
+               const int testbufsize = 0x2000;
+               u8 testbuf[testbufsize];
+               int i;
+               /*cpu_write(0x8000, 0x80);
+               cpu_write(0xe000, 0);
+               cpu_write(0xe000, 0);
+               cpu_write(0xe000, 0);
+               cpu_write(0xe000, 0);
+               cpu_write(0xe000, 0);*/
+               for(i=0;i<0x10;i++){
+                       cpu_write(0x6000 + i, i);
+               }
+               cpu_read(0x6000, testbufsize, testbuf);
+               buf_save(testbuf, file, testbufsize);
+               }break;
+       }
+       
+       if(gg != GIVEIO_WIN95){
+               giveio_stop(GIVEIO_STOP);
+       }
+       return;
+}
+
+int main(int c, char **v)
+{
+       switch(c){
+       case 2:
+               backupram_test(v[1]);
+               break;
+       case 3:
+               script_load(v[1], v[2], 0);
+               break;
+       case 4:
+               script_load(v[1], v[2], 1);
+               break;
+       default:
+               printf("%s [mapper script] [dump file]", v[0]);
+       }
+       return 0;
+}
diff --git a/client/tag/0.4.0/unagi.ico b/client/tag/0.4.0/unagi.ico
new file mode 100644 (file)
index 0000000..af88f63
Binary files /dev/null and b/client/tag/0.4.0/unagi.ico differ
diff --git a/client/tag/0.4.0/unagi.rc b/client/tag/0.4.0/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.4.0/unagi.txt b/client/tag/0.4.0/unagi.txt
new file mode 100644 (file)
index 0000000..9a8dbf1
--- /dev/null
@@ -0,0 +1,67 @@
+unagi version 0.04
+by sato_tiff, sato at kitanaka.net
+\8cö\8e®\83T\83C\83g http://sourceforge.jp/projects/unagi/
+
+--\82Í\82\82ß\82É--
+\83t\83@\83~\83R\83\93ROM\83C\83\81\81[\83W\93Ç\82Ý\8fo\82µ\83v\83\8d\83O\83\89\83\80\82Å\82·\81B\83n\81[\83h\83E\83F\83A\82Í 
+www.emusta.net \82Å\82¨\82È\82\82Ý\82à\82Ì\82ð\8eg\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
+
+--\8eÀ\91\95\82Å\82«\82Ä\82È\82¢\82±\82Æ--
+\83o\83b\83N\83A\83b\83vRAM\82Ì\93Ç\82Ý\8fo\82µ/\8f\91\82«\8d\9e\82Ý
+\8e\91\97¿\82ª\82È\82¢\82Ì\82Å\82Ç\82¤\8eÀ\91\95\82µ\82Ä\82¢\82¢\82©\95ª\82©\82è\82Ü\82¹\82ñ\81B\92m\82Á\82Ä\82é\90l\82Í\8b³\82¦\82Ä\82­\82¾\82³
+\82¢\81B
+
+--\83R\83}\83\93\83h\83\89\83C\83\93\88ø\90\94--
+soon.exe [script file] [dump file] [testflag]
+script file - \91Î\89\9e\82·\82é\83}\83b\83p\82Ì\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
+testflag    - \83X\83N\83\8a\83v\83g\82ð\83e\83X\83g\82¾\82¯\82·\82é\8fê\8d\87\82Í\82È\82É\82©\95\8e\9a\82ð\82¢\82ê\82Ä\82­\82¾\82³
+              \82¢\81B\82±\82Ì\83I\83v\83V\83\87\83\93\82ð\82Â\82¯\82é\82Æ\83n\81[\83h\83E\83F\83A\82É\83A\83N\83Z\83X\82µ\82Ü\82¹
+              \82ñ\81B
+
+--\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
+
+--\83X\83N\83\8a\83v\83g\95å\8fW--
+150\82­\82ç\82¢\82 \82é\83}\83b\83p\82Ì\83X\83N\83\8a\83v\83g\82ð\91S\82Ä\8e\84\82¾\82¯\82Å\8f\91\82­\82±\82Æ\82Í\8fo\97\88\82Ü\82¹\82ñ\81B\8eè
+\8cy\82É\83X\83N\83\8a\83v\83g\82ð\92Ç\89Á\82·\82é\82±\82Æ\82ª\8fo\97\88\82é\82Ì\82Å\81A\83X\83N\83\8a\83v\83g\82ª\8f\91\82¯\82½\90l\82Í\8cö\8e®\83T
+\83C\83g\82Ü\82Å\98A\97\8d\82ð\82­\82¾\82³\82¢\81B
+\8dÌ\97p\8aî\8f\80\82Í\89º\8bL\82Æ\82³\82¹\82Ä\82¢\82½\82¾\82«\82Ü\82·\81B
+
+* \82»\82Ì\83X\83N\83\8a\83v\83g\82ð\8eg\82Á\82Ä\8eÀ\8dÛ\82É\93®\8dì\8am\94F\82ð\82µ\82Ä\93Ç\82Ý\8fo\82¹\82½\82±\82Æ
+* \93®\8dì\8am\94F\82ð\82µ\82½\83\\83t\83g\90\94\96{\82Ì\96¼\8fÌ\82©\8c^\94Ô\82ð\83X\83N\83\8a\83v\83g\90æ\93ª\82É\83R\83\81\83\93\83g\82ð\82¢\82ê
+  \82é\82±\82Æ
+* \93Ç\82Ý\8fo\82µ\82É\95K\97v\82È\83\8c\83W\83X\83^\82Í\8f\89\8aú\89»\82µ\82Ä\82©\82ç\93Ç\82Ý\8fo\82·\82±\82Æ (\83}\83b\83p\82Ì\83}\83C
+  \83i\81[\83o\81[\83W\83\87\83\93\82É\82æ\82Á\82Ä\93d\8c¹\93\8a\93ü\8cã\82Ì\8f\89\8aú\92l\82ª\88Ù\82È\82é\8fê\8d\87\82ª\82 \82é\82Ì\82Å\95K\82¸
+  \8ds\82Á\82Ä\82­\82¾\82³\82¢)
+
+--\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
+
+--\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