Files
Momentum-Firmware/applications/plugins/chip8/chip8.c
RogueMaster 61e922399d more apps
2022-09-16 20:16:27 -04:00

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");
}