mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
210 lines
5 KiB
C++
210 lines
5 KiB
C++
// testffi/libs/api.cpp
|
|
|
|
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
#include <thread>
|
|
#include <atomic>
|
|
#include <iostream>
|
|
#include <chrono>
|
|
#include <stdbool.h>
|
|
|
|
#include "chip32_vm.h"
|
|
#include "dlib_export.h"
|
|
#include "story_machine.h"
|
|
|
|
|
|
static char root_dir[260];
|
|
static bool gMusicLoaded = false;
|
|
char fileNameToLoad[512] = { 0 };
|
|
|
|
typedef void (*media_callback)(int32_t, const char*);
|
|
|
|
static media_callback gMediaCallback = nullptr;
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
// VM Stuff
|
|
//---------------------------------------------------------------------------------------
|
|
static uint8_t rom_data[16*1024];
|
|
static uint8_t ram_data[16*1024];
|
|
static chip32_ctx_t chip32_ctx;
|
|
|
|
|
|
static chip32_result_t run_result;
|
|
static uint32_t event_mask = 0;
|
|
|
|
static uint8_t IndexBuf[260];
|
|
static uint8_t ImageBuf[100];
|
|
static uint8_t SoundBuf[100];
|
|
|
|
static bool IsValidEvent(uint32_t event) {
|
|
return (event_mask & event) != 0;
|
|
}
|
|
|
|
|
|
int get_filename_from_memory(chip32_ctx_t *ctx, uint32_t addr, char *filename_mem)
|
|
{
|
|
int valid = 0;
|
|
|
|
// Test if address is valid
|
|
|
|
bool isRam = addr & 0x80000000;
|
|
addr &= 0xFFFF; // mask the RAM/ROM bit, ensure 16-bit addressing
|
|
if (isRam) {
|
|
strcpy(&filename_mem[0], (const char *)&ctx->ram.mem[addr]);
|
|
} else {
|
|
strcpy(&filename_mem[0], (const char *)&ctx->rom.mem[addr]);
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t story_player_syscall(chip32_ctx_t *ctx, uint8_t code)
|
|
{
|
|
uint8_t retCode = SYSCALL_RET_OK;
|
|
|
|
static char image_path[260];
|
|
static char sound_path[260];
|
|
|
|
if (code == 1) // // Execute media
|
|
{
|
|
std::cout << "[STORYVM] Syscall 1" << std::endl;
|
|
// for (int i = 0; i< REGISTER_COUNT; i++) {
|
|
// std::cout << "[STORYVM] Reg: " << i << ", value: " << (int)ctx->registers[i] << std::endl;
|
|
// }
|
|
|
|
if (ctx->registers[R0] != 0)
|
|
{
|
|
// sound file name address is in R1
|
|
char image[100];
|
|
get_filename_from_memory(ctx, ctx->registers[R0], image);
|
|
|
|
if (gMediaCallback)
|
|
{
|
|
std::cout << "[STORYVM] Execute callback (image)" << std::endl;
|
|
gMediaCallback(0, image);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "[STORYVM] No image" << std::endl;
|
|
}
|
|
|
|
if (ctx->registers[R1] != 0)
|
|
{
|
|
// sound file name address is in R1
|
|
char sound[100];
|
|
get_filename_from_memory(ctx, ctx->registers[R1], sound);
|
|
|
|
if (gMediaCallback)
|
|
{
|
|
std::cout << "[STORYVM] Execute callback (sound)" << std::endl;
|
|
gMediaCallback(1, sound);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "[STORYVM] No sound" << std::endl;
|
|
}
|
|
|
|
retCode = SYSCALL_RET_OK; // set the VM in pause
|
|
}
|
|
else if (code == 2) // Wait Event
|
|
{
|
|
std::cout << "[STORYVM] Syscall 2 (wait for event)" << std::endl;
|
|
event_mask = ctx->registers[R0];
|
|
retCode = SYSCALL_RET_WAIT_EV; // set the VM in pause
|
|
}
|
|
else if (code == 3) // Signal
|
|
{
|
|
if (ctx->registers[R0] == 1)
|
|
{
|
|
// EXIT
|
|
std::cout << "[STORYVM] Syscall 3 (exit)" << std::endl;
|
|
if (gMediaCallback)
|
|
{
|
|
std::cout << "[STORYVM] Execute callback (sound)" << std::endl;
|
|
gMediaCallback(2, "");
|
|
}
|
|
}
|
|
}
|
|
return retCode;
|
|
}
|
|
|
|
|
|
extern "C" void storyvm_run()
|
|
{
|
|
// VM next instruction
|
|
if (run_result == VM_OK)
|
|
{
|
|
run_result = chip32_step(&chip32_ctx);
|
|
|
|
// for (int i = 0; i< REGISTER_COUNT; i++) {
|
|
// std::cout << "[STORYVM] Reg: " << i << ", value: " << (int)chip32_ctx.registers[i] << std::endl;
|
|
// }
|
|
}
|
|
}
|
|
|
|
|
|
extern "C" void storyvm_stop()
|
|
{
|
|
std::cout << "[STORYVM] Stop: " << std::endl;
|
|
run_result = VM_FINISHED;
|
|
}
|
|
|
|
|
|
extern "C" void storyvm_initialize(media_callback cb)
|
|
{
|
|
std::cout << "[STORYVM] Initialize: " << (void *)cb << std::endl;
|
|
gMediaCallback = cb;
|
|
|
|
chip32_ctx.stack_size = 512;
|
|
|
|
chip32_ctx.rom.mem = rom_data;
|
|
chip32_ctx.rom.addr = 0;
|
|
chip32_ctx.rom.size = sizeof(rom_data);
|
|
|
|
chip32_ctx.ram.mem = ram_data;
|
|
chip32_ctx.ram.addr = sizeof(rom_data);
|
|
chip32_ctx.ram.size = sizeof(ram_data);
|
|
|
|
chip32_ctx.syscall = story_player_syscall;
|
|
|
|
run_result = VM_FINISHED;
|
|
|
|
storyvm_stop();
|
|
}
|
|
|
|
extern "C" void storyvm_send_event(int event)
|
|
{
|
|
if (IsValidEvent(event))
|
|
{
|
|
chip32_ctx.registers[R0] = event;
|
|
run_result = VM_OK;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "[STORYVM] Invalid event" << std::endl;
|
|
}
|
|
}
|
|
|
|
extern "C" void storyvm_start(const uint8_t *data, uint32_t size)
|
|
{
|
|
if (size <= chip32_ctx.rom.size)
|
|
{
|
|
memcpy(chip32_ctx.rom.mem, data, size);
|
|
run_result = VM_OK;
|
|
chip32_initialize(&chip32_ctx);
|
|
std::cout << "[STORYVM] Start" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
run_result = VM_FINISHED;
|
|
std::cout << "[STORYVM] Not started (not enough memory)" << std::endl;
|
|
}
|
|
}
|
|
|