// testffi/libs/api.cpp #include #include #include #include #include #include #include #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; } }