1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14
15 #define USE_CLIB
16 #include "aldumb.h"
17 #include "ac/asset_helper.h"
18 #include "ac/file.h"
19 #include "ac/common.h"
20 #include "ac/gamesetup.h"
21 #include "ac/gamesetupstruct.h"
22 #include "ac/global_file.h"
23 #include "ac/path_helper.h"
24 #include "ac/runtime_defines.h"
25 #include "ac/string.h"
26 #include "debug/debug_log.h"
27 #include "debug/debugger.h"
28 #include "util/misc.h"
29 #include "platform/base/agsplatformdriver.h"
30 #include "util/stream.h"
31 #include "core/assetmanager.h"
32 #include "core/asset.h"
33 #include "main/engine.h"
34 #include "main/game_file.h"
35 #include "util/directory.h"
36 #include "util/path.h"
37 #include "util/string.h"
38 #include "util/string_utils.h"
39
40 using namespace AGS::Common;
41
42 extern GameSetup usetup;
43 extern GameSetupStruct game;
44 extern char saveGameDirectory[260];
45 extern AGSPlatformDriver *platform;
46
47 extern int MAXSTRLEN;
48
49 // TODO: the asset path configuration should certainly be revamped at some
50 // point, with uniform method of configuring auxiliary paths and packages.
51
52 // Installation directory, may contain absolute or relative path
53 String installDirectory;
54 // Installation directory, containing audio files
55 String installAudioDirectory;
56 // Installation directory, containing voice-over files
57 String installVoiceDirectory;
58
59 // object-based File routines
60
File_Exists(const char * fnmm)61 int File_Exists(const char *fnmm) {
62
63 String path, alt_path;
64 if (!ResolveScriptPath(fnmm, true, path, alt_path))
65 return 0;
66
67 return (File::TestReadFile(path) || File::TestReadFile(alt_path)) ? 1 : 0;
68 }
69
File_Delete(const char * fnmm)70 int File_Delete(const char *fnmm) {
71
72 String path, alt_path;
73 if (!ResolveScriptPath(fnmm, false, path, alt_path))
74 return 0;
75
76 if (unlink(path) == 0)
77 return 1;
78 if (errno == ENOENT && !alt_path.IsEmpty() && alt_path.Compare(path) != 0)
79 return unlink(alt_path) == 0 ? 1 : 0;
80 return 0;
81 }
82
sc_OpenFile(const char * fnmm,int mode)83 void *sc_OpenFile(const char *fnmm, int mode) {
84 if ((mode < scFileRead) || (mode > scFileAppend))
85 quit("!OpenFile: invalid file mode");
86
87 sc_File *scf = new sc_File();
88 if (scf->OpenFile(fnmm, mode) == 0) {
89 delete scf;
90 return 0;
91 }
92 ccRegisterManagedObject(scf, scf);
93 return scf;
94 }
95
File_Close(sc_File * fil)96 void File_Close(sc_File *fil) {
97 fil->Close();
98 }
99
File_WriteString(sc_File * fil,const char * towrite)100 void File_WriteString(sc_File *fil, const char *towrite) {
101 FileWrite(fil->handle, towrite);
102 }
103
File_WriteInt(sc_File * fil,int towrite)104 void File_WriteInt(sc_File *fil, int towrite) {
105 FileWriteInt(fil->handle, towrite);
106 }
107
File_WriteRawChar(sc_File * fil,int towrite)108 void File_WriteRawChar(sc_File *fil, int towrite) {
109 FileWriteRawChar(fil->handle, towrite);
110 }
111
File_WriteRawLine(sc_File * fil,const char * towrite)112 void File_WriteRawLine(sc_File *fil, const char *towrite) {
113 FileWriteRawLine(fil->handle, towrite);
114 }
115
File_ReadRawLine(sc_File * fil,char * buffer)116 void File_ReadRawLine(sc_File *fil, char* buffer) {
117 Stream *in = get_valid_file_stream_from_handle(fil->handle, "File.ReadRawLine");
118 check_strlen(buffer);
119 int i = 0;
120 while (i < MAXSTRLEN - 1) {
121 buffer[i] = in->ReadInt8();
122 if (buffer[i] == 13) {
123 // CR -- skip LF and abort
124 in->ReadInt8();
125 break;
126 }
127 if (buffer[i] == 10) // LF only -- abort
128 break;
129 if (in->EOS()) // EOF -- abort
130 break;
131 i++;
132 }
133 buffer[i] = 0;
134 }
135
File_ReadRawLineBack(sc_File * fil)136 const char* File_ReadRawLineBack(sc_File *fil) {
137 char readbuffer[MAX_MAXSTRLEN + 1];
138 File_ReadRawLine(fil, readbuffer);
139 return CreateNewScriptString(readbuffer);
140 }
141
File_ReadString(sc_File * fil,char * toread)142 void File_ReadString(sc_File *fil, char *toread) {
143 FileRead(fil->handle, toread);
144 }
145
File_ReadStringBack(sc_File * fil)146 const char* File_ReadStringBack(sc_File *fil) {
147 Stream *in = get_valid_file_stream_from_handle(fil->handle, "File.ReadStringBack");
148 if (in->EOS()) {
149 return CreateNewScriptString("");
150 }
151
152 int lle = in->ReadInt32();
153 if ((lle >= 20000) || (lle < 1))
154 quit("!File.ReadStringBack: file was not written by WriteString");
155
156 char *retVal = (char*)malloc(lle);
157 in->Read(retVal, lle);
158
159 return CreateNewScriptString(retVal, false);
160 }
161
File_ReadInt(sc_File * fil)162 int File_ReadInt(sc_File *fil) {
163 return FileReadInt(fil->handle);
164 }
165
File_ReadRawChar(sc_File * fil)166 int File_ReadRawChar(sc_File *fil) {
167 return FileReadRawChar(fil->handle);
168 }
169
File_ReadRawInt(sc_File * fil)170 int File_ReadRawInt(sc_File *fil) {
171 return FileReadRawInt(fil->handle);
172 }
173
File_Seek(sc_File * fil,int offset,int origin)174 int File_Seek(sc_File *fil, int offset, int origin)
175 {
176 Stream *in = get_valid_file_stream_from_handle(fil->handle, "File.Seek");
177 return (int)in->Seek(offset, (StreamSeek)origin);
178 }
179
File_GetEOF(sc_File * fil)180 int File_GetEOF(sc_File *fil) {
181 if (fil->handle <= 0)
182 return 1;
183 return FileIsEOF(fil->handle);
184 }
185
File_GetError(sc_File * fil)186 int File_GetError(sc_File *fil) {
187 if (fil->handle <= 0)
188 return 1;
189 return FileIsError(fil->handle);
190 }
191
File_GetPosition(sc_File * fil)192 int File_GetPosition(sc_File *fil)
193 {
194 if (fil->handle <= 0)
195 return -1;
196 Stream *stream = get_valid_file_stream_from_handle(fil->handle, "File.Position");
197 // TODO: a problem is that AGS script does not support unsigned or long int
198 return (int)stream->GetPosition();
199 }
200
201 //=============================================================================
202
203
204 const String GameInstallRootToken = "$INSTALLDIR$";
205 const String UserSavedgamesRootToken = "$MYDOCS$";
206 const String GameSavedgamesDirToken = "$SAVEGAMEDIR$";
207 const String GameDataDirToken = "$APPDATADIR$";
208
FixupFilename(char * filename)209 void FixupFilename(char *filename)
210 {
211 const char *illegal = platform->GetIllegalFileChars();
212 for (char *name_ptr = filename; *name_ptr; ++name_ptr)
213 {
214 if (*name_ptr < ' ')
215 {
216 *name_ptr = '_';
217 }
218 else
219 {
220 for (const char *ch_ptr = illegal; *ch_ptr; ++ch_ptr)
221 if (*name_ptr == *ch_ptr)
222 *name_ptr = '_';
223 }
224 }
225 }
226
227 // Tests if there is a special path token in the beginning of the given path;
228 // if there is and there is no slash between token and the rest of the string,
229 // then assigns new string that has such slash.
230 // Returns TRUE if the new string was created, and FALSE if the path was good.
FixSlashAfterToken(const String & path,const String & token,String & new_path)231 bool FixSlashAfterToken(const String &path, const String &token, String &new_path)
232 {
233 if (path.CompareLeft(token) == 0 && path.GetLength() > token.GetLength() &&
234 path[token.GetLength()] != '/')
235 {
236 new_path = String::FromFormat("%s/%s", token.GetCStr(), path.Mid(token.GetLength()).GetCStr());
237 return true;
238 }
239 return false;
240 }
241
FixSlashAfterToken(const String & path)242 String FixSlashAfterToken(const String &path)
243 {
244 String fixed_path = path;
245 Path::FixupPath(fixed_path);
246 if (FixSlashAfterToken(fixed_path, GameInstallRootToken, fixed_path) ||
247 FixSlashAfterToken(fixed_path, UserSavedgamesRootToken, fixed_path) ||
248 FixSlashAfterToken(fixed_path, GameSavedgamesDirToken, fixed_path) ||
249 FixSlashAfterToken(fixed_path, GameDataDirToken, fixed_path))
250 return fixed_path;
251 return path;
252 }
253
MakeSpecialSubDir(const String & sp_dir)254 String MakeSpecialSubDir(const String &sp_dir)
255 {
256 if (is_relative_filename(sp_dir))
257 return sp_dir;
258 String full_path = sp_dir;
259 if (full_path.GetLast() != '/' && full_path.GetLast() != '\\')
260 full_path.AppendChar('/');
261 full_path.Append(game.saveGameFolderName);
262 Directory::CreateDirectory(full_path);
263 return full_path;
264 }
265
MakeAppDataPath()266 String MakeAppDataPath()
267 {
268 String app_data_path = usetup.shared_data_dir;
269 if (app_data_path.IsEmpty())
270 app_data_path = MakeSpecialSubDir(PathOrCurDir(platform->GetAllUsersDataDirectory()));
271 Directory::CreateDirectory(app_data_path);
272 app_data_path.AppendChar('/');
273 return app_data_path;
274 }
275
ResolveScriptPath(const String & orig_sc_path,bool read_only,String & path,String & alt_path)276 bool ResolveScriptPath(const String &orig_sc_path, bool read_only, String &path, String &alt_path)
277 {
278 path.Empty();
279 alt_path.Empty();
280
281 bool is_absolute = !is_relative_filename(orig_sc_path);
282 if (is_absolute && !read_only)
283 {
284 debug_script_warn("Attempt to access file '%s' denied (cannot write to absolute path)", orig_sc_path.GetCStr());
285 return false;
286 }
287
288 String parent_dir;
289 String child_path;
290
291 if (is_absolute)
292 {
293 path = orig_sc_path;
294 return true;
295 }
296
297 String sc_path = FixSlashAfterToken(orig_sc_path);
298
299 if (sc_path.CompareLeft(GameInstallRootToken, GameInstallRootToken.GetLength()) == 0)
300 {
301 if (!read_only)
302 {
303 debug_script_warn("Attempt to access file '%s' denied (cannot write to game installation directory)",
304 sc_path.GetCStr());
305 return false;
306 }
307 parent_dir = get_install_dir();
308 parent_dir.AppendChar('/');
309 child_path = sc_path.Mid(GameInstallRootToken.GetLength());
310 }
311 else if (sc_path.CompareLeft(GameSavedgamesDirToken, GameSavedgamesDirToken.GetLength()) == 0)
312 {
313 parent_dir = saveGameDirectory;
314 child_path = sc_path.Mid(GameSavedgamesDirToken.GetLength());
315 }
316 else if (sc_path.CompareLeft(GameDataDirToken, GameDataDirToken.GetLength()) == 0)
317 {
318 parent_dir = MakeAppDataPath();
319 child_path = sc_path.Mid(GameDataDirToken.GetLength());
320 }
321 else
322 {
323 child_path = sc_path;
324
325 // For games which were made without having safe paths in mind,
326 // provide two paths: a path to the local directory and a path to
327 // AppData directory.
328 // This is done in case game writes a file by local path, and would
329 // like to read it back later. Since AppData path has higher priority,
330 // game will first check the AppData location and find a previously
331 // written file.
332 // If no file was written yet, but game is trying to read a pre-created
333 // file in the installation directory, then such file will be found
334 // following the 'alt_path'.
335 parent_dir = MakeAppDataPath();
336 // Set alternate non-remapped "unsafe" path for read-only operations
337 if (read_only)
338 alt_path = String::FromFormat("%s/%s", get_install_dir().GetCStr(), sc_path.GetCStr());
339
340 // For games made in the safe-path-aware versions of AGS, report a warning
341 // if the unsafe path is used for write operation
342 if (!read_only && game.options[OPT_SAFEFILEPATHS])
343 {
344 debug_script_warn("Attempt to access file '%s' denied (cannot write to game installation directory);\nPath will be remapped to the app data directory: '%s'",
345 sc_path.GetCStr(), parent_dir.GetCStr());
346 }
347 }
348
349 if (child_path[0u] == '\\' || child_path[0u] == '/')
350 child_path.ClipLeft(1);
351
352 path = String::FromFormat("%s%s", parent_dir.GetCStr(), child_path.GetCStr());
353 // don't allow write operations for relative paths outside game dir
354 if (!read_only)
355 {
356 if (!Path::IsSameOrSubDir(parent_dir, path))
357 {
358 debug_script_warn("Attempt to access file '%s' denied (outside of game directory)", sc_path.GetCStr());
359 path = "";
360 return false;
361 }
362 }
363 return true;
364 }
365
LocateAsset(const AssetPath & path,AssetLocation & loc)366 bool LocateAsset(const AssetPath &path, AssetLocation &loc)
367 {
368 String assetlib = path.first;
369 String assetname = path.second;
370 bool needsetback = false;
371 // Change to the different library, if required
372 // TODO: teaching AssetManager to register multiple libraries simultaneously
373 // will let us skip this step, and also make this operation much faster.
374 if (!assetlib.IsEmpty() && assetlib.CompareNoCase(game_file_name) != 0)
375 {
376 AssetManager::SetDataFile(find_assetlib(assetlib));
377 needsetback = true;
378 }
379 bool res = AssetManager::GetAssetLocation(assetname, loc);
380 if (needsetback)
381 AssetManager::SetDataFile(game_file_name);
382 return res;
383 }
384
PackfileFromAsset(const AssetPath & path)385 PACKFILE *PackfileFromAsset(const AssetPath &path)
386 {
387 AssetLocation loc;
388 if (LocateAsset(path, loc))
389 {
390 PACKFILE *pf = pack_fopen(loc.FileName, File::GetCMode(kFile_Open, kFile_Read));
391 if (pf)
392 {
393 pack_fseek(pf, loc.Offset);
394 pf->normal.todo = loc.Size;
395 }
396 return pf;
397 }
398 return NULL;
399 }
400
DUMBfileFromAsset(const AssetPath & path)401 DUMBFILE *DUMBfileFromAsset(const AssetPath &path)
402 {
403 PACKFILE *pf = PackfileFromAsset(path);
404 if (pf)
405 return dumbfile_open_packfile(pf);
406 return NULL;
407 }
408
DoesAssetExistInLib(const AssetPath & assetname)409 bool DoesAssetExistInLib(const AssetPath &assetname)
410 {
411 bool needsetback = false;
412 // Change to the different library, if required
413 // TODO: teaching AssetManager to register multiple libraries simultaneously
414 // will let us skip this step, and also make this operation much faster.
415 if (!assetname.first.IsEmpty() && assetname.first.CompareNoCase(game_file_name) != 0)
416 {
417 AssetManager::SetDataFile(find_assetlib(assetname.first));
418 needsetback = true;
419 }
420 bool res = AssetManager::DoesAssetExist(assetname.second);
421 if (needsetback)
422 AssetManager::SetDataFile(game_file_name);
423 return res;
424 }
425
set_install_dir(const String & path,const String & audio_path,const String & voice_path)426 void set_install_dir(const String &path, const String &audio_path, const String &voice_path)
427 {
428 if (path.IsEmpty())
429 installDirectory = ".";
430 else
431 installDirectory = Path::MakePathNoSlash(path);
432 if (audio_path.IsEmpty())
433 installAudioDirectory = ".";
434 else
435 installAudioDirectory = Path::MakePathNoSlash(audio_path);
436 if (voice_path.IsEmpty())
437 installVoiceDirectory = ".";
438 else
439 installVoiceDirectory = Path::MakePathNoSlash(voice_path);
440 }
441
get_install_dir()442 String get_install_dir()
443 {
444 return installDirectory;
445 }
446
get_audio_install_dir()447 String get_audio_install_dir()
448 {
449 return installAudioDirectory;
450 }
451
get_voice_install_dir()452 String get_voice_install_dir()
453 {
454 return installVoiceDirectory;
455 }
456
get_install_dir_path(char * buffer,const char * fileName)457 void get_install_dir_path(char* buffer, const char *fileName)
458 {
459 sprintf(buffer, "%s/%s", installDirectory.GetCStr(), fileName);
460 }
461
find_assetlib(const String & filename)462 String find_assetlib(const String &filename)
463 {
464 String libname = free_char_to_string( ci_find_file(usetup.data_files_dir, filename) );
465 if (AssetManager::IsDataFile(libname))
466 return libname;
467 if (Path::ComparePaths(usetup.data_files_dir, installDirectory) != 0)
468 {
469 // Hack for running in Debugger
470 libname = free_char_to_string( ci_find_file(installDirectory, filename) );
471 if (AssetManager::IsDataFile(libname))
472 return libname;
473 }
474 return "";
475 }
476
find_open_asset(const String & filename)477 Stream *find_open_asset(const String &filename)
478 {
479 Stream *asset_s = Common::AssetManager::OpenAsset(filename);
480 if (!asset_s && Path::ComparePaths(usetup.data_files_dir, installDirectory) != 0)
481 {
482 // Just in case they're running in Debug, try standalone file in compiled folder
483 asset_s = ci_fopen(String::FromFormat("%s/%s", installDirectory.GetCStr(), filename.GetCStr()));
484 }
485 return asset_s;
486 }
487
get_audio_clip_assetpath(int bundling_type,const String & filename)488 AssetPath get_audio_clip_assetpath(int bundling_type, const String &filename)
489 {
490 // Special case is explicitly defined audio directory, which should be
491 // tried first regardless of bundling type.
492 if (Path::ComparePaths(usetup.data_files_dir, installAudioDirectory) != 0)
493 {
494 String filepath = String::FromFormat("%s/%s", installAudioDirectory.GetCStr(), filename.GetCStr());
495 if (Path::IsFile(filepath))
496 return AssetPath("", filepath);
497 }
498
499 if (bundling_type == AUCL_BUNDLE_EXE)
500 return AssetPath(game_file_name, filename);
501 else if (bundling_type == AUCL_BUNDLE_VOX)
502 return AssetPath(game.GetAudioVOXName(), filename);
503 return AssetPath();
504 }
505
get_voice_over_assetpath(const String & filename)506 AssetPath get_voice_over_assetpath(const String &filename)
507 {
508 // Special case is explicitly defined voice-over directory, which should be
509 // tried first.
510 if (Path::ComparePaths(usetup.data_files_dir, installVoiceDirectory) != 0)
511 {
512 String filepath = String::FromFormat("%s/%s", installVoiceDirectory.GetCStr(), filename.GetCStr());
513 if (Path::IsFile(filepath))
514 return AssetPath("", filepath);
515 }
516 return AssetPath(speech_file, filename);
517 }
518
519 ScriptFileHandle valid_handles[MAX_OPEN_SCRIPT_FILES + 1];
520 // [IKM] NOTE: this is not precisely the number of files opened at this moment,
521 // but rather maximal number of handles that were used simultaneously during game run
522 int num_open_script_files = 0;
check_valid_file_handle_ptr(Stream * stream_ptr,const char * operation_name)523 ScriptFileHandle *check_valid_file_handle_ptr(Stream *stream_ptr, const char *operation_name)
524 {
525 if (stream_ptr)
526 {
527 for (int i = 0; i < num_open_script_files; ++i)
528 {
529 if (stream_ptr == valid_handles[i].stream)
530 {
531 return &valid_handles[i];
532 }
533 }
534 }
535
536 String exmsg = String::FromFormat("!%s: invalid file handle; file not previously opened or has been closed", operation_name);
537 quit(exmsg);
538 return NULL;
539 }
540
check_valid_file_handle_int32(int32_t handle,const char * operation_name)541 ScriptFileHandle *check_valid_file_handle_int32(int32_t handle, const char *operation_name)
542 {
543 if (handle > 0)
544 {
545 for (int i = 0; i < num_open_script_files; ++i)
546 {
547 if (handle == valid_handles[i].handle)
548 {
549 return &valid_handles[i];
550 }
551 }
552 }
553
554 String exmsg = String::FromFormat("!%s: invalid file handle; file not previously opened or has been closed", operation_name);
555 quit(exmsg);
556 return NULL;
557 }
558
get_valid_file_stream_from_handle(int32_t handle,const char * operation_name)559 Stream *get_valid_file_stream_from_handle(int32_t handle, const char *operation_name)
560 {
561 ScriptFileHandle *sc_handle = check_valid_file_handle_int32(handle, operation_name);
562 return sc_handle ? sc_handle->stream : NULL;
563 }
564
565 //=============================================================================
566 //
567 // Script API Functions
568 //
569 //=============================================================================
570
571 #include "debug/out.h"
572 #include "script/script_api.h"
573 #include "script/script_runtime.h"
574 #include "ac/dynobj/scriptstring.h"
575
576 extern ScriptString myScriptStringImpl;
577
578 // int (const char *fnmm)
Sc_File_Delete(const RuntimeScriptValue * params,int32_t param_count)579 RuntimeScriptValue Sc_File_Delete(const RuntimeScriptValue *params, int32_t param_count)
580 {
581 API_SCALL_INT_POBJ(File_Delete, const char);
582 }
583
584 // int (const char *fnmm)
Sc_File_Exists(const RuntimeScriptValue * params,int32_t param_count)585 RuntimeScriptValue Sc_File_Exists(const RuntimeScriptValue *params, int32_t param_count)
586 {
587 API_SCALL_INT_POBJ(File_Exists, const char);
588 }
589
590 // void *(const char *fnmm, int mode)
Sc_sc_OpenFile(const RuntimeScriptValue * params,int32_t param_count)591 RuntimeScriptValue Sc_sc_OpenFile(const RuntimeScriptValue *params, int32_t param_count)
592 {
593 API_SCALL_OBJAUTO_POBJ_PINT(sc_File, sc_OpenFile, const char);
594 }
595
596 // void (sc_File *fil)
Sc_File_Close(void * self,const RuntimeScriptValue * params,int32_t param_count)597 RuntimeScriptValue Sc_File_Close(void *self, const RuntimeScriptValue *params, int32_t param_count)
598 {
599 API_OBJCALL_VOID(sc_File, File_Close);
600 }
601
602 // int (sc_File *fil)
Sc_File_ReadInt(void * self,const RuntimeScriptValue * params,int32_t param_count)603 RuntimeScriptValue Sc_File_ReadInt(void *self, const RuntimeScriptValue *params, int32_t param_count)
604 {
605 API_OBJCALL_INT(sc_File, File_ReadInt);
606 }
607
608 // int (sc_File *fil)
Sc_File_ReadRawChar(void * self,const RuntimeScriptValue * params,int32_t param_count)609 RuntimeScriptValue Sc_File_ReadRawChar(void *self, const RuntimeScriptValue *params, int32_t param_count)
610 {
611 API_OBJCALL_INT(sc_File, File_ReadRawChar);
612 }
613
614 // int (sc_File *fil)
Sc_File_ReadRawInt(void * self,const RuntimeScriptValue * params,int32_t param_count)615 RuntimeScriptValue Sc_File_ReadRawInt(void *self, const RuntimeScriptValue *params, int32_t param_count)
616 {
617 API_OBJCALL_INT(sc_File, File_ReadRawInt);
618 }
619
620 // void (sc_File *fil, char* buffer)
Sc_File_ReadRawLine(void * self,const RuntimeScriptValue * params,int32_t param_count)621 RuntimeScriptValue Sc_File_ReadRawLine(void *self, const RuntimeScriptValue *params, int32_t param_count)
622 {
623 API_OBJCALL_VOID_POBJ(sc_File, File_ReadRawLine, char);
624 }
625
626 // const char* (sc_File *fil)
Sc_File_ReadRawLineBack(void * self,const RuntimeScriptValue * params,int32_t param_count)627 RuntimeScriptValue Sc_File_ReadRawLineBack(void *self, const RuntimeScriptValue *params, int32_t param_count)
628 {
629 API_OBJCALL_OBJ(sc_File, const char, myScriptStringImpl, File_ReadRawLineBack);
630 }
631
632 // void (sc_File *fil, char *toread)
Sc_File_ReadString(void * self,const RuntimeScriptValue * params,int32_t param_count)633 RuntimeScriptValue Sc_File_ReadString(void *self, const RuntimeScriptValue *params, int32_t param_count)
634 {
635 API_OBJCALL_VOID_POBJ(sc_File, File_ReadString, char);
636 }
637
638 // const char* (sc_File *fil)
Sc_File_ReadStringBack(void * self,const RuntimeScriptValue * params,int32_t param_count)639 RuntimeScriptValue Sc_File_ReadStringBack(void *self, const RuntimeScriptValue *params, int32_t param_count)
640 {
641 API_OBJCALL_OBJ(sc_File, const char, myScriptStringImpl, File_ReadStringBack);
642 }
643
644 // void (sc_File *fil, int towrite)
Sc_File_WriteInt(void * self,const RuntimeScriptValue * params,int32_t param_count)645 RuntimeScriptValue Sc_File_WriteInt(void *self, const RuntimeScriptValue *params, int32_t param_count)
646 {
647 API_OBJCALL_VOID_PINT(sc_File, File_WriteInt);
648 }
649
650 // void (sc_File *fil, int towrite)
Sc_File_WriteRawChar(void * self,const RuntimeScriptValue * params,int32_t param_count)651 RuntimeScriptValue Sc_File_WriteRawChar(void *self, const RuntimeScriptValue *params, int32_t param_count)
652 {
653 API_OBJCALL_VOID_PINT(sc_File, File_WriteRawChar);
654 }
655
656 // void (sc_File *fil, const char *towrite)
Sc_File_WriteRawLine(void * self,const RuntimeScriptValue * params,int32_t param_count)657 RuntimeScriptValue Sc_File_WriteRawLine(void *self, const RuntimeScriptValue *params, int32_t param_count)
658 {
659 API_OBJCALL_VOID_POBJ(sc_File, File_WriteRawLine, const char);
660 }
661
662 // void (sc_File *fil, const char *towrite)
Sc_File_WriteString(void * self,const RuntimeScriptValue * params,int32_t param_count)663 RuntimeScriptValue Sc_File_WriteString(void *self, const RuntimeScriptValue *params, int32_t param_count)
664 {
665 API_OBJCALL_VOID_POBJ(sc_File, File_WriteString, const char);
666 }
667
Sc_File_Seek(void * self,const RuntimeScriptValue * params,int32_t param_count)668 RuntimeScriptValue Sc_File_Seek(void *self, const RuntimeScriptValue *params, int32_t param_count)
669 {
670 API_OBJCALL_INT_PINT2(sc_File, File_Seek);
671 }
672
673 // int (sc_File *fil)
Sc_File_GetEOF(void * self,const RuntimeScriptValue * params,int32_t param_count)674 RuntimeScriptValue Sc_File_GetEOF(void *self, const RuntimeScriptValue *params, int32_t param_count)
675 {
676 API_OBJCALL_INT(sc_File, File_GetEOF);
677 }
678
679 // int (sc_File *fil)
Sc_File_GetError(void * self,const RuntimeScriptValue * params,int32_t param_count)680 RuntimeScriptValue Sc_File_GetError(void *self, const RuntimeScriptValue *params, int32_t param_count)
681 {
682 API_OBJCALL_INT(sc_File, File_GetError);
683 }
684
Sc_File_GetPosition(void * self,const RuntimeScriptValue * params,int32_t param_count)685 RuntimeScriptValue Sc_File_GetPosition(void *self, const RuntimeScriptValue *params, int32_t param_count)
686 {
687 API_OBJCALL_INT(sc_File, File_GetPosition);
688 }
689
690
RegisterFileAPI()691 void RegisterFileAPI()
692 {
693 ccAddExternalStaticFunction("File::Delete^1", Sc_File_Delete);
694 ccAddExternalStaticFunction("File::Exists^1", Sc_File_Exists);
695 ccAddExternalStaticFunction("File::Open^2", Sc_sc_OpenFile);
696 ccAddExternalObjectFunction("File::Close^0", Sc_File_Close);
697 ccAddExternalObjectFunction("File::ReadInt^0", Sc_File_ReadInt);
698 ccAddExternalObjectFunction("File::ReadRawChar^0", Sc_File_ReadRawChar);
699 ccAddExternalObjectFunction("File::ReadRawInt^0", Sc_File_ReadRawInt);
700 ccAddExternalObjectFunction("File::ReadRawLine^1", Sc_File_ReadRawLine);
701 ccAddExternalObjectFunction("File::ReadRawLineBack^0", Sc_File_ReadRawLineBack);
702 ccAddExternalObjectFunction("File::ReadString^1", Sc_File_ReadString);
703 ccAddExternalObjectFunction("File::ReadStringBack^0", Sc_File_ReadStringBack);
704 ccAddExternalObjectFunction("File::WriteInt^1", Sc_File_WriteInt);
705 ccAddExternalObjectFunction("File::WriteRawChar^1", Sc_File_WriteRawChar);
706 ccAddExternalObjectFunction("File::WriteRawLine^1", Sc_File_WriteRawLine);
707 ccAddExternalObjectFunction("File::WriteString^1", Sc_File_WriteString);
708 ccAddExternalObjectFunction("File::Seek^2", Sc_File_Seek);
709 ccAddExternalObjectFunction("File::get_EOF", Sc_File_GetEOF);
710 ccAddExternalObjectFunction("File::get_Error", Sc_File_GetError);
711 ccAddExternalObjectFunction("File::get_Position", Sc_File_GetPosition);
712
713 /* ----------------------- Registering unsafe exports for plugins -----------------------*/
714
715 ccAddExternalFunctionForPlugin("File::Delete^1", (void*)File_Delete);
716 ccAddExternalFunctionForPlugin("File::Exists^1", (void*)File_Exists);
717 ccAddExternalFunctionForPlugin("File::Open^2", (void*)sc_OpenFile);
718 ccAddExternalFunctionForPlugin("File::Close^0", (void*)File_Close);
719 ccAddExternalFunctionForPlugin("File::ReadInt^0", (void*)File_ReadInt);
720 ccAddExternalFunctionForPlugin("File::ReadRawChar^0", (void*)File_ReadRawChar);
721 ccAddExternalFunctionForPlugin("File::ReadRawInt^0", (void*)File_ReadRawInt);
722 ccAddExternalFunctionForPlugin("File::ReadRawLine^1", (void*)File_ReadRawLine);
723 ccAddExternalFunctionForPlugin("File::ReadRawLineBack^0", (void*)File_ReadRawLineBack);
724 ccAddExternalFunctionForPlugin("File::ReadString^1", (void*)File_ReadString);
725 ccAddExternalFunctionForPlugin("File::ReadStringBack^0", (void*)File_ReadStringBack);
726 ccAddExternalFunctionForPlugin("File::WriteInt^1", (void*)File_WriteInt);
727 ccAddExternalFunctionForPlugin("File::WriteRawChar^1", (void*)File_WriteRawChar);
728 ccAddExternalFunctionForPlugin("File::WriteRawLine^1", (void*)File_WriteRawLine);
729 ccAddExternalFunctionForPlugin("File::WriteString^1", (void*)File_WriteString);
730 ccAddExternalFunctionForPlugin("File::get_EOF", (void*)File_GetEOF);
731 ccAddExternalFunctionForPlugin("File::get_Error", (void*)File_GetError);
732 }
733