mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-25 03:29:58 -07:00
204 lines
6.4 KiB
C
204 lines
6.4 KiB
C
#include <furi.h>
|
|
#include <furi_hal.h>
|
|
#include <gui/gui.h>
|
|
#include <input/input.h>
|
|
#include <lib/toolbox/args.h>
|
|
#include <storage/storage.h>
|
|
#include "chip8.h"
|
|
#include "emulator_core/flipper_chip.h"
|
|
|
|
#define TAG "Chip8Emulator"
|
|
#define WORKER_TAG TAG "Worker"
|
|
#define FILE_BUFFER_LEN 16
|
|
|
|
typedef enum {
|
|
WorkerEvtToggle = (1 << 1),
|
|
WorkerEvtEnd = (1 << 2),
|
|
} WorkerEvtFlags;
|
|
|
|
struct Chip8Emulator {
|
|
Chip8State st;
|
|
string_t file_path;
|
|
FuriThread* thread;
|
|
};
|
|
|
|
static int32_t chip8_worker(void* context) {
|
|
Chip8Emulator* chip8 = context;
|
|
|
|
FURI_LOG_I(WORKER_TAG, "Start furi record open");
|
|
Storage* furi_storage_record = furi_record_open(RECORD_STORAGE);
|
|
FURI_LOG_I(WORKER_TAG, "furi record opened");
|
|
|
|
FURI_LOG_I(WORKER_TAG, "Start storage file alloc");
|
|
File* rom_file = storage_file_alloc(furi_storage_record);
|
|
FURI_LOG_I(
|
|
WORKER_TAG, "Start storage file open, path = %s", string_get_cstr(chip8->file_path));
|
|
|
|
uint8_t* rom_data = malloc(4096);
|
|
FURI_LOG_I(WORKER_TAG, "4096 array gotten");
|
|
|
|
while(1) {
|
|
if(chip8->st.worker_state == WorkerStateBackPressed) {
|
|
FURI_LOG_I(WORKER_TAG, "WorkerStateBackPressed");
|
|
break;
|
|
}
|
|
|
|
if(chip8->st.worker_state == WorkerStateLoadingRom) {
|
|
bool is_file_opened = storage_file_open(
|
|
rom_file, string_get_cstr(chip8->file_path), FSAM_READ, FSOM_OPEN_EXISTING);
|
|
|
|
if(!is_file_opened) {
|
|
FURI_LOG_I(WORKER_TAG, "Cannot open storage");
|
|
storage_file_close(rom_file);
|
|
storage_file_free(rom_file);
|
|
chip8->st.worker_state = WorkerStateRomLoadError;
|
|
return 0;
|
|
}
|
|
|
|
FURI_LOG_I(WORKER_TAG, "File was opened, try read this");
|
|
|
|
int rom_len = read_rom_data(rom_file, rom_data);
|
|
|
|
FURI_LOG_I(WORKER_TAG, "Rom data finished reading");
|
|
|
|
FURI_LOG_I(WORKER_TAG, "Load chip8 core data");
|
|
t_chip8_load_game(chip8->st.t_chip8_state, rom_data, rom_len);
|
|
FURI_LOG_I(WORKER_TAG, "chip8 core data loaded");
|
|
|
|
FURI_LOG_I(WORKER_TAG, "Wipe screen start");
|
|
for(int i = 0; i < CHIP8_SCREEN_H; i++) {
|
|
FURI_LOG_I(WORKER_TAG, "Wipe screen line %d", i);
|
|
for(int j = 0; j < CHIP8_SCREEN_W; j++) {
|
|
chip8->st.t_chip8_state->screen[i][j] = 0;
|
|
}
|
|
furi_delay_ms(15);
|
|
}
|
|
FURI_LOG_I(WORKER_TAG, "Wipe screen end");
|
|
|
|
chip8->st.worker_state = WorkerStateRomLoaded;
|
|
}
|
|
|
|
if(chip8->st.worker_state == WorkerStateRomLoaded) {
|
|
if(chip8->st.t_chip8_state->go_render) {
|
|
continue;
|
|
}
|
|
t_chip8_execute_next_opcode(chip8->st.t_chip8_state);
|
|
FURI_LOG_I(
|
|
"chip8_executing",
|
|
"current: 0x%X next: 0x%X",
|
|
chip8->st.t_chip8_state->current_opcode,
|
|
chip8->st.t_chip8_state->next_opcode);
|
|
furi_delay_ms(2);
|
|
//t_chip8_tick(chip8->st.t_chip8_state);
|
|
}
|
|
}
|
|
|
|
FURI_LOG_I("CHIP8", "Prepare to ending app");
|
|
storage_file_close(rom_file);
|
|
storage_file_free(rom_file);
|
|
t_chip8_free_memory(chip8->st.t_chip8_state, free);
|
|
FURI_LOG_I("CHIP8", "End ending");
|
|
return 0;
|
|
}
|
|
|
|
Chip8Emulator* chip8_make_emulator(string_t file_path) {
|
|
furi_assert(file_path);
|
|
FURI_LOG_I("CHIP8", "make emulator, file_path=", string_get_cstr(file_path));
|
|
|
|
Chip8Emulator* chip8 = malloc(sizeof(Chip8Emulator));
|
|
string_init(chip8->file_path);
|
|
string_set(chip8->file_path, file_path);
|
|
chip8->st.worker_state = WorkerStateLoadingRom;
|
|
chip8->st.t_chip8_state = t_chip8_init(malloc);
|
|
|
|
// FURI_LOG_I(WORKER_TAG, "Start wipe screen");
|
|
// furi_delay_ms(1500);
|
|
// for (int i = 0; i < CHIP8_SCREEN_H; i++)
|
|
// {
|
|
// FURI_LOG_I(WORKER_TAG, "Start wipe line %d", i);
|
|
// for (int j = 0; j < CHIP8_SCREEN_W; j++)
|
|
// {
|
|
// chip8->st.t_chip8_state->screen[i][j] = 0;
|
|
// }
|
|
// }
|
|
// FURI_LOG_I(WORKER_TAG, "End wipe screen");
|
|
|
|
chip8->thread = furi_thread_alloc();
|
|
furi_thread_set_name(chip8->thread, "Chip8Worker");
|
|
furi_thread_set_stack_size(chip8->thread, 4096);
|
|
furi_thread_set_context(chip8->thread, chip8);
|
|
furi_thread_set_callback(chip8->thread, chip8_worker);
|
|
|
|
furi_thread_start(chip8->thread);
|
|
return chip8;
|
|
}
|
|
|
|
void chip8_close_emulator(Chip8Emulator* chip8) {
|
|
FURI_LOG_I("chip_8_close_emulator", "start");
|
|
furi_assert(chip8);
|
|
furi_thread_flags_set(furi_thread_get_id(chip8->thread), WorkerEvtEnd);
|
|
furi_thread_join(chip8->thread);
|
|
furi_thread_free(chip8->thread);
|
|
string_clear(chip8->file_path);
|
|
free(chip8);
|
|
FURI_LOG_I("chip_8_close_emulator", "end");
|
|
}
|
|
|
|
void chip8_toggle(Chip8Emulator* chip8) {
|
|
furi_assert(chip8);
|
|
furi_thread_flags_set(furi_thread_get_id(chip8->thread), WorkerEvtToggle);
|
|
}
|
|
|
|
Chip8State* chip8_get_state(Chip8Emulator* chip8) {
|
|
furi_assert(chip8);
|
|
return &(chip8->st);
|
|
}
|
|
|
|
uint16_t read_rom_data(File* file, uint8_t* data) {
|
|
furi_assert(file);
|
|
furi_assert(data);
|
|
|
|
const uint8_t buffer_size = 32;
|
|
uint16_t file_pointer = 0;
|
|
uint8_t buff[buffer_size];
|
|
|
|
while(1) {
|
|
uint16_t bytes_were_read = storage_file_read(file, buff, buffer_size);
|
|
|
|
if(bytes_were_read == 0) {
|
|
break;
|
|
}
|
|
|
|
for(uint16_t i = 0; i < bytes_were_read; i++) {
|
|
data[file_pointer] = buff[i];
|
|
file_pointer++;
|
|
}
|
|
}
|
|
|
|
return file_pointer;
|
|
}
|
|
|
|
void chip8_set_back_pressed(Chip8Emulator* chip8) {
|
|
chip8->st.worker_state = WorkerStateBackPressed;
|
|
chip8->st.t_chip8_state->go_render = true;
|
|
FURI_LOG_I(WORKER_TAG, "SET BACK PRESSED. EMULATION IS STOPPED");
|
|
}
|
|
|
|
void chip8_set_up_pressed(Chip8Emulator* chip8) {
|
|
chip8->st.t_chip8_state->go_render = true;
|
|
t_chip8_set_input(chip8->st.t_chip8_state, k_1);
|
|
FURI_LOG_I(WORKER_TAG, "UP PRESSED");
|
|
}
|
|
|
|
void chip8_set_down_pressed(Chip8Emulator* chip8) {
|
|
chip8->st.t_chip8_state->go_render = true;
|
|
t_chip8_set_input(chip8->st.t_chip8_state, k_4);
|
|
FURI_LOG_I(WORKER_TAG, "DOWN PRESSED");
|
|
}
|
|
|
|
void chip8_release_keyboard(Chip8Emulator* chip8) {
|
|
chip8->st.t_chip8_state->go_render = true;
|
|
t_chip8_release_input(chip8->st.t_chip8_state);
|
|
FURI_LOG_I(WORKER_TAG, "chip8_release_keyboard Release input");
|
|
}
|