1 /* -*- C++ -*-
2  *
3  *  ONScripter_file.cpp - FILE I/O of ONScripter
4  *
5  *  Copyright (c) 2001-2018 Ogapee. All rights reserved.
6  *
7  *  ogapee@aqua.dti2.ne.jp
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "ONScripter.h"
25 
26 #if defined(LINUX) || defined(MACOSX) || defined(IOS)
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <time.h>
31 #elif defined(WIN32)
32 #include <windows.h>
33 extern "C" { FILE __iob_func[3] = { *stdin,*stdout,*stderr }; }
34 #elif defined(MACOS9)
35 #include <DateTimeUtils.h>
36 #include <Files.h>
37 extern "C" void c2pstrcpy(Str255 dst, const char *src);	//#include <TextUtils.h>
38 #elif defined(PSP)
39 #include <pspiofilemgr.h>
40 #endif
41 
42 #define SAVEFILE_MAGIC_NUMBER "ONS"
43 #define SAVEFILE_VERSION_MAJOR 2
44 #define SAVEFILE_VERSION_MINOR 8
45 
46 #define READ_LENGTH 4096
47 
searchSaveFile(SaveFileInfo & save_file_info,int no)48 void ONScripter::searchSaveFile( SaveFileInfo &save_file_info, int no )
49 {
50     char file_name[256];
51 
52     script_h.getStringFromInteger( save_file_info.sjis_no, no, (num_save_file >= 10)?2:1 );
53 #if defined(LINUX) || defined(MACOSX) || defined(IOS)
54     sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
55     struct stat buf;
56     struct tm *tm;
57     if ( stat( file_name, &buf ) != 0 ){
58         save_file_info.valid = false;
59         return;
60     }
61     time_t mtime = buf.st_mtime;
62     tm = localtime( &mtime );
63 
64     save_file_info.month  = tm->tm_mon + 1;
65     save_file_info.day    = tm->tm_mday;
66     save_file_info.hour   = tm->tm_hour;
67     save_file_info.minute = tm->tm_min;
68 #elif defined(WIN32)
69     sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
70     HANDLE  handle;
71     FILETIME    tm, ltm;
72     SYSTEMTIME  stm;
73 
74     WCHAR file_nameW[256];
75     MultiByteToWideChar(CP_ACP, 0, file_name, -1, file_nameW, 256);
76     handle = CreateFile( file_nameW, GENERIC_READ, 0, NULL,
77                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
78     if ( handle == INVALID_HANDLE_VALUE ){
79         save_file_info.valid = false;
80         return;
81     }
82 
83     GetFileTime( handle, NULL, NULL, &tm );
84     FileTimeToLocalFileTime( &tm, &ltm );
85     FileTimeToSystemTime( &ltm, &stm );
86     CloseHandle( handle );
87 
88     save_file_info.month  = stm.wMonth;
89     save_file_info.day    = stm.wDay;
90     save_file_info.hour   = stm.wHour;
91     save_file_info.minute = stm.wMinute;
92 #elif defined(MACOS9)
93     sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
94     CInfoPBRec  pb;
95     Str255      p_file_name;
96     FSSpec      file_spec;
97     DateTimeRec tm;
98     c2pstrcpy( p_file_name, file_name );
99     if ( FSMakeFSSpec(0, 0, p_file_name, &file_spec) != noErr ){
100         save_file_info.valid = false;
101         return;
102     }
103     pb.hFileInfo.ioNamePtr = file_spec.name;
104     pb.hFileInfo.ioVRefNum = file_spec.vRefNum;
105     pb.hFileInfo.ioFDirIndex = 0;
106     pb.hFileInfo.ioDirID = file_spec.parID;
107     if (PBGetCatInfoSync(&pb) != noErr) {
108         save_file_info.valid = false;
109         return;
110     }
111     SecondsToDate( pb.hFileInfo.ioFlMdDat, &tm );
112     save_file_info.month  = tm.month;
113     save_file_info.day    = tm.day;
114     save_file_info.hour   = tm.hour;
115     save_file_info.minute = tm.minute;
116 #elif defined(PSP)
117     sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
118     SceIoStat buf;
119     if ( sceIoGetstat(file_name, &buf)<0 ){
120         save_file_info.valid = false;
121         return;
122     }
123 
124     save_file_info.month  = buf.st_mtime.month;
125     save_file_info.day    = buf.st_mtime.day;
126     save_file_info.hour   = buf.st_mtime.hour;
127     save_file_info.minute = buf.st_mtime.minute;
128 #else
129     sprintf( file_name, "save%d.dat", no );
130     FILE *fp;
131     if ( (fp = fopen( file_name, "rb", true )) == NULL ){
132         save_file_info.valid = false;
133         return;
134     }
135     fclose( fp );
136 
137     save_file_info.month  = 1;
138     save_file_info.day    = 1;
139     save_file_info.hour   = 0;
140     save_file_info.minute = 0;
141 #endif
142     save_file_info.valid = true;
143     script_h.getStringFromInteger( save_file_info.sjis_month,  save_file_info.month,  2 );
144     script_h.getStringFromInteger( save_file_info.sjis_day,    save_file_info.day,    2 );
145     script_h.getStringFromInteger( save_file_info.sjis_hour,   save_file_info.hour,   2 );
146     script_h.getStringFromInteger( save_file_info.sjis_minute, save_file_info.minute, 2, true );
147 }
148 
readSaveStrFromFile(int no)149 char *ONScripter::readSaveStrFromFile( int no )
150 {
151     char filename[32];
152     sprintf( filename, "save%d.dat", no );
153     size_t len = loadFileIOBuf( filename );
154     if (len == 0){
155         fprintf( stderr, "readSaveStrFromFile: can't open save file %s\n", filename );
156         return NULL;
157     }
158 
159     int p = len - 1;
160     if ( p < 3 || file_io_buf[p] != '*' || file_io_buf[p-1] != '"' ) return NULL;
161     p -= 2;
162 
163     while( file_io_buf[p] != '"' && p>0 ) p--;
164     if ( file_io_buf[p] != '"' ) return NULL;
165 
166     len = len - p - 3;
167     char *buf = new char[len+1];
168 
169     unsigned int i;
170     for (i=0 ; i<len ; i++)
171         buf[i] = file_io_buf[p+i+1];
172     buf[i] = 0;
173 
174     return buf;
175 }
176 
loadSaveFile(int no)177 int ONScripter::loadSaveFile( int no )
178 {
179     char filename[32];
180     sprintf( filename, "save%d.dat", no );
181     if (loadFileIOBuf( filename ) == 0){
182         fprintf( stderr, "can't open save file %s\n", filename );
183         return -1;
184     }
185 
186     /* ---------------------------------------- */
187     /* Load magic number */
188     int i;
189     for ( i=0 ; i<(int)strlen( SAVEFILE_MAGIC_NUMBER ) ; i++ )
190         if ( readChar() != SAVEFILE_MAGIC_NUMBER[i] ) break;
191 
192     if ( i != (int)strlen( SAVEFILE_MAGIC_NUMBER ) ){
193         file_io_buf_ptr = 0;
194         printf("Save file version is unknown\n" );
195         return loadSaveFile2( SAVEFILE_VERSION_MAJOR*100 + SAVEFILE_VERSION_MINOR );
196     }
197 
198     int file_version = readChar() * 100;
199     file_version += readChar();
200     printf("Save file version is %d.%d\n", file_version/100, file_version%100 );
201     if ( file_version > SAVEFILE_VERSION_MAJOR*100 + SAVEFILE_VERSION_MINOR ){
202         fprintf( stderr, "Save file is newer than %d.%d, please use the latest ONScripter.\n", SAVEFILE_VERSION_MAJOR, SAVEFILE_VERSION_MINOR );
203         return -1;
204     }
205 
206     if ( file_version >= 200 )
207         return loadSaveFile2( file_version );
208 
209     fprintf( stderr, "Save file is too old.\n");
210 
211     return -1;
212 }
213 
saveMagicNumber(bool output_flag)214 void ONScripter::saveMagicNumber( bool output_flag )
215 {
216     for ( unsigned int i=0 ; i<strlen( SAVEFILE_MAGIC_NUMBER ) ; i++ )
217         writeChar( SAVEFILE_MAGIC_NUMBER[i], output_flag );
218     writeChar( SAVEFILE_VERSION_MAJOR, output_flag );
219     writeChar( SAVEFILE_VERSION_MINOR, output_flag );
220 }
221 
storeSaveFile()222 void ONScripter::storeSaveFile()
223 {
224     file_io_buf_ptr = 0;
225     saveMagicNumber( false );
226     saveSaveFile2( false );
227     allocFileIOBuf();
228     saveMagicNumber( true );
229     saveSaveFile2( true );
230     save_data_len = file_io_buf_ptr;
231     memcpy(save_data_buf, file_io_buf, save_data_len);
232 }
233 
writeSaveFile(int no,const char * savestr)234 int ONScripter::writeSaveFile( int no, const char *savestr )
235 {
236     saveAll();
237 
238     char filename[32];
239     sprintf( filename, "save%d.dat", no );
240 
241     memcpy(file_io_buf, save_data_buf, save_data_len);
242     file_io_buf_ptr = save_data_len;
243     if (saveFileIOBuf( filename, 0, savestr )){
244         fprintf( stderr, "can't open save file %s for writing\n", filename );
245         return -1;
246     }
247 
248     size_t magic_len = strlen(SAVEFILE_MAGIC_NUMBER)+2;
249     sprintf( filename, RELATIVEPATH "sav%csave%d.dat", DELIMITER, no );
250     if (saveFileIOBuf( filename, magic_len, savestr ))
251         fprintf( stderr, "can't open save file %s for writing (not an error)\n", filename );
252 
253     return 0;
254 }
255