TIC-80-guile/src/run.c

214 lines
4.6 KiB
C
Raw Normal View History

2017-09-26 08:59:34 +02:00
// MIT License
// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "run.h"
#include "console.h"
#include "fs.h"
#include "ext/md5.h"
#include <time.h>
2017-09-26 08:59:34 +02:00
static void onTrace(void* data, const char* text, u8 color)
{
Run* run = (Run*)data;
run->console->trace(run->console, text, color);
}
static void onError(void* data, const char* info)
{
Run* run = (Run*)data;
setStudioMode(TIC_CONSOLE_MODE);
run->console->error(run->console, info);
}
static void onExit(void* data)
{
Run* run = (Run*)data;
run->exit = true;
}
2018-08-03 09:48:15 +02:00
static const char* data2md5(const void* data, s32 length)
2017-09-26 08:59:34 +02:00
{
const char *str = data;
MD5_CTX c;
static char out[33];
MD5_Init(&c);
while (length > 0)
{
MD5_Update(&c, str, length > 512 ? 512: length);
length -= 512;
str += 512;
}
{
2018-08-03 09:48:15 +02:00
enum{Size = 16};
u8 digest[Size];
2017-09-26 08:59:34 +02:00
MD5_Final(digest, &c);
2018-08-03 09:48:15 +02:00
for (s32 n = 0; n < Size; ++n)
snprintf(out + n*2, sizeof("ff"), "%02x", digest[n]);
2017-09-26 08:59:34 +02:00
}
return out;
}
static void initPMemName(Run* run)
2017-09-26 08:59:34 +02:00
{
2018-09-05 12:10:14 +02:00
const char* data = strlen(run->tic->saveid) ? run->tic->saveid : run->tic->cart.code.data;
2018-08-03 09:48:15 +02:00
const char* md5 = data2md5(data, strlen(data));
strcpy(run->saveid, TIC_LOCAL);
strcat(run->saveid, md5);
2017-09-26 08:59:34 +02:00
}
static void tick(Run* run)
{
if (getStudioMode() != TIC_RUN_MODE)
return;
run->tic->api.tick(run->tic, &run->tickData);
enum {Size = sizeof(tic_persistent)};
2018-02-15 15:19:04 +01:00
if(run->tickData.syncPMEM)
2017-09-26 08:59:34 +02:00
{
fsSaveRootFile(run->console->fs, run->saveid, &run->tic->persistent, Size, true);
2018-02-06 20:15:56 +01:00
memcpy(&run->persistent, &run->tic->persistent, Size);
2018-02-15 15:19:04 +01:00
run->tickData.syncPMEM = false;
2017-09-26 08:59:34 +02:00
}
if(run->exit)
setStudioMode(TIC_CONSOLE_MODE);
}
2017-11-27 17:38:10 +01:00
static void processDoFile(void* data, char* dst)
{
Run* run = (Run*)data;
tic_mem* tic = run->tic;
static const char DoFileTag[] = "dofile(";
enum {Size = sizeof DoFileTag - 1};
2018-09-05 12:10:14 +02:00
if (memcmp(tic->cart.code.data, DoFileTag, Size) == 0)
2017-11-27 17:38:10 +01:00
{
2018-09-05 12:10:14 +02:00
const char* start = tic->cart.code.data + Size;
2017-11-27 17:38:10 +01:00
const char* end = strchr(start, ')');
if(end && *start == *(end-1) && (*start == '"' || *start == '\''))
{
char filename[FILENAME_MAX] = {0};
memcpy(filename, start + 1, end - start - 2);
memset(dst, 0, sizeof(tic_code));
s32 size = 0;
void* buffer = fsReadFile(filename, &size);
if(buffer)
{
if(size > 0)
{
if(size > TIC_CODE_SIZE)
{
char buffer[256];
sprintf(buffer, "code is larger than %i symbols", TIC_CODE_SIZE);
onError(run, buffer);
return;
}
2018-02-06 20:15:56 +01:00
else memcpy(dst, buffer, size);
2017-11-27 17:38:10 +01:00
}
}
else
{
char buffer[256];
sprintf(buffer, "dofile: file '%s' not found", filename);
onError(run, buffer);
return;
}
}
}
return;
}
static bool forceExit(void* data)
{
2018-02-15 15:06:03 +01:00
getSystem()->poll();
tic_mem* tic = ((Run*)data)->tic;
return tic->api.key(tic, tic_key_escape);
}
2017-09-26 08:59:34 +02:00
void initRun(Run* run, Console* console, tic_mem* tic)
{
*run = (Run)
{
.tic = tic,
.console = console,
.tick = tick,
.exit = false,
.tickData =
{
.error = onError,
.trace = onTrace,
2018-02-14 12:52:10 +01:00
.counter = getSystem()->getPerformanceCounter,
.freq = getSystem()->getPerformanceFrequency,
2017-09-26 08:59:34 +02:00
.start = 0,
.data = run,
.exit = onExit,
2017-11-27 17:38:10 +01:00
.preprocessor = processDoFile,
.forceExit = forceExit,
2018-02-15 15:19:04 +01:00
.syncPMEM = false,
2017-09-26 08:59:34 +02:00
},
};
{
enum {Size = sizeof(tic_persistent)};
2018-02-06 20:15:56 +01:00
memset(&run->tic->persistent, 0, Size);
initPMemName(run);
2017-09-26 08:59:34 +02:00
s32 size = 0;
void* data = fsLoadRootFile(run->console->fs, run->saveid, &size);
if(size > Size) size = Size;
2017-09-26 08:59:34 +02:00
if(data)
2017-09-26 08:59:34 +02:00
{
2018-02-06 20:15:56 +01:00
memcpy(&run->tic->persistent, data, size);
memcpy(&run->persistent, data, size);
2017-09-26 08:59:34 +02:00
}
2018-02-06 20:15:56 +01:00
if(data) free(data);
2017-09-26 08:59:34 +02:00
}
2018-02-14 14:22:33 +01:00
getSystem()->preseed();
2017-09-26 08:59:34 +02:00
}