Added xMasterX API v11.x source
@@ -0,0 +1,10 @@
|
||||
# FlipperZeroBrainfuck
|
||||
|
||||
Brainfuck interpreter and editor for the F0.
|
||||
Supports text inputs and outputs.
|
||||
No protection against infinite loops or syntax errors.
|
||||
Major limitation is that programs MUST terminate, or it will freeze at "RUNNING"
|
||||
|
||||

|
||||
|
||||

|
||||
@@ -0,0 +1,14 @@
|
||||
App(
|
||||
appid="Brainfuck",
|
||||
name="Brainfuck",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="brainfuck_app",
|
||||
requires=[
|
||||
"storage",
|
||||
"gui",
|
||||
],
|
||||
stack_size=8 * 1024,
|
||||
fap_icon="bfico.png",
|
||||
fap_category="Misc_Extra",
|
||||
fap_icon_assets="icons",
|
||||
)
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,137 @@
|
||||
#include "brainfuck_i.h"
|
||||
|
||||
/*
|
||||
Due to the lack of documentation on the flipper i copied the picopass app,
|
||||
ripped its insides out and used its hollow corpse to build this app inside of.
|
||||
|
||||
i dont know how this stuff works and after 6 hours of trying to learn it, i dont care
|
||||
*/
|
||||
|
||||
bool brainfuck_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
BFApp* brainfuck = context;
|
||||
return scene_manager_handle_custom_event(brainfuck->scene_manager, event);
|
||||
}
|
||||
|
||||
bool brainfuck_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
BFApp* brainfuck = context;
|
||||
return scene_manager_handle_back_event(brainfuck->scene_manager);
|
||||
}
|
||||
|
||||
BFApp* brainfuck_alloc() {
|
||||
BFApp* brainfuck = malloc(sizeof(BFApp));
|
||||
|
||||
brainfuck->dataSize = 0;
|
||||
brainfuck->view_dispatcher = view_dispatcher_alloc();
|
||||
brainfuck->scene_manager = scene_manager_alloc(&brainfuck_scene_handlers, brainfuck);
|
||||
view_dispatcher_enable_queue(brainfuck->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(brainfuck->view_dispatcher, brainfuck);
|
||||
view_dispatcher_set_custom_event_callback(brainfuck->view_dispatcher, brainfuck_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(brainfuck->view_dispatcher, brainfuck_back_event_callback);
|
||||
|
||||
// Open GUI record
|
||||
brainfuck->gui = furi_record_open(RECORD_GUI);
|
||||
view_dispatcher_attach_to_gui(brainfuck->view_dispatcher, brainfuck->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Open Notification record
|
||||
brainfuck->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// Submenu
|
||||
brainfuck->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(brainfuck->view_dispatcher, brainfuckViewMenu, submenu_get_view(brainfuck->submenu));
|
||||
|
||||
// Popup
|
||||
brainfuck->popup = popup_alloc();
|
||||
view_dispatcher_add_view(brainfuck->view_dispatcher, brainfuckViewPopup, popup_get_view(brainfuck->popup));
|
||||
|
||||
// Text Input
|
||||
brainfuck->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(brainfuck->view_dispatcher, brainfuckViewTextInput, text_input_get_view(brainfuck->text_input));
|
||||
|
||||
// Textbox
|
||||
brainfuck->text_box = text_box_alloc();
|
||||
view_dispatcher_add_view(brainfuck->view_dispatcher, brainfuckViewTextBox, text_box_get_view(brainfuck->text_box));
|
||||
brainfuck->text_box_store = furi_string_alloc();
|
||||
|
||||
// Dev environment
|
||||
brainfuck->BF_dev_env = bf_dev_env_alloc(brainfuck);
|
||||
view_dispatcher_add_view(brainfuck->view_dispatcher, brainfuckViewDev, bf_dev_env_get_view(brainfuck->BF_dev_env));
|
||||
|
||||
// File path
|
||||
brainfuck->BF_file_path = furi_string_alloc();
|
||||
|
||||
return brainfuck;
|
||||
}
|
||||
|
||||
void brainfuck_free(BFApp* brainfuck) {
|
||||
furi_assert(brainfuck);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(brainfuck->view_dispatcher, brainfuckViewMenu);
|
||||
submenu_free(brainfuck->submenu);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(brainfuck->view_dispatcher, brainfuckViewPopup);
|
||||
popup_free(brainfuck->popup);
|
||||
|
||||
// TextInput
|
||||
view_dispatcher_remove_view(brainfuck->view_dispatcher, brainfuckViewTextInput);
|
||||
text_input_free(brainfuck->text_input);
|
||||
|
||||
// TextBox
|
||||
view_dispatcher_remove_view(brainfuck->view_dispatcher, brainfuckViewTextBox);
|
||||
text_box_free(brainfuck->text_box);
|
||||
furi_string_free(brainfuck->text_box_store);
|
||||
|
||||
//dev env
|
||||
view_dispatcher_remove_view(brainfuck->view_dispatcher, brainfuckViewDev);
|
||||
bf_dev_env_free(brainfuck->BF_dev_env);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_free(brainfuck->view_dispatcher);
|
||||
|
||||
// Scene Manager
|
||||
scene_manager_free(brainfuck->scene_manager);
|
||||
|
||||
// GUI
|
||||
furi_record_close(RECORD_GUI);
|
||||
brainfuck->gui = NULL;
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
brainfuck->notifications = NULL;
|
||||
|
||||
free(brainfuck);
|
||||
}
|
||||
|
||||
void brainfuck_show_loading_popup(void* context, bool show) {
|
||||
BFApp* brainfuck = context;
|
||||
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
|
||||
|
||||
if(show) {
|
||||
// Raise timer priority so that animations can play
|
||||
vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
|
||||
view_dispatcher_switch_to_view(brainfuck->view_dispatcher, brainfuckViewLoading);
|
||||
} else {
|
||||
// Restore default timer priority
|
||||
vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t brainfuck_app(void* p) {
|
||||
UNUSED(p);
|
||||
BFApp* brainfuck = brainfuck_alloc();
|
||||
if(!brainfuck){ return 0; }
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_simply_mkdir(storage, "/ext/brainfuck");
|
||||
|
||||
scene_manager_next_scene(brainfuck->scene_manager, brainfuckSceneStart);
|
||||
|
||||
view_dispatcher_run(brainfuck->view_dispatcher);
|
||||
|
||||
brainfuck_free(brainfuck);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct BFApp BFApp;
|
||||
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct BFDevEnv BFDevEnv;
|
||||
typedef struct BFExecEnv BFExecEnv;
|
||||
typedef unsigned char byte;
|
||||
|
||||
#include "brainfuck.h"
|
||||
#include "worker.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/loading.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/text_box.h>
|
||||
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#include "scenes/brainfuck_scene.h"
|
||||
|
||||
#include "views/bf_dev_env.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <Brainfuck_icons.h>
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <stream/stream.h>
|
||||
#include <stream/buffered_file_stream.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
|
||||
#define BF_INST_BUFFER_SIZE 2048
|
||||
#define BF_OUTPUT_SIZE 512
|
||||
#define BF_STACK_INITIAL_SIZE 128
|
||||
#define BF_INPUT_BUFFER_SIZE 64
|
||||
#define BF_STACK_STEP_SIZE 32
|
||||
|
||||
enum brainfuckCustomEvent {
|
||||
// Reserve first 100 events for button types and indexes, starting from 0
|
||||
brainfuckCustomEventReserved = 100,
|
||||
|
||||
brainfuckCustomEventViewExit,
|
||||
brainfuckCustomEventWorkerExit,
|
||||
brainfuckCustomEventByteInputDone,
|
||||
brainfuckCustomEventTextInputDone,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
EventTypeTick,
|
||||
EventTypeKey,
|
||||
} EventType;
|
||||
|
||||
struct BFApp {
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
SceneManager* scene_manager;
|
||||
Submenu* submenu;
|
||||
Popup* popup;
|
||||
TextInput* text_input;
|
||||
TextBox* text_box;
|
||||
FuriString* text_box_store;
|
||||
FuriString* BF_file_path;
|
||||
BFDevEnv* BF_dev_env;
|
||||
int dataSize;
|
||||
char dataBuffer[BF_INST_BUFFER_SIZE];
|
||||
char inputBuffer[BF_INPUT_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
brainfuckViewMenu,
|
||||
brainfuckViewPopup,
|
||||
brainfuckViewLoading,
|
||||
brainfuckViewTextInput,
|
||||
brainfuckViewTextBox,
|
||||
brainfuckViewWidget,
|
||||
brainfuckViewDev,
|
||||
brainfuckViewExec,
|
||||
} brainfuckView;
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,30 @@
|
||||
#include "brainfuck_scene.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const brainfuck_on_enter_handlers[])(void*) = {
|
||||
#include "brainfuck_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const brainfuck_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "brainfuck_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const brainfuck_on_exit_handlers[])(void* context) = {
|
||||
#include "brainfuck_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers brainfuck_scene_handlers = {
|
||||
.on_enter_handlers = brainfuck_on_enter_handlers,
|
||||
.on_event_handlers = brainfuck_on_event_handlers,
|
||||
.on_exit_handlers = brainfuck_on_exit_handlers,
|
||||
.scene_num = brainfuckSceneNum,
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) brainfuckScene##id,
|
||||
typedef enum {
|
||||
#include "brainfuck_scene_config.h"
|
||||
brainfuckSceneNum,
|
||||
} brainfuckScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers brainfuck_scene_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||
#include "brainfuck_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||
#include "brainfuck_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||
#include "brainfuck_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
@@ -0,0 +1,6 @@
|
||||
ADD_SCENE(brainfuck, start, Start)
|
||||
ADD_SCENE(brainfuck, file_select, FileSelect)
|
||||
ADD_SCENE(brainfuck, file_create, FileCreate)
|
||||
ADD_SCENE(brainfuck, dev_env, DevEnv)
|
||||
ADD_SCENE(brainfuck, exec_env, ExecEnv)
|
||||
ADD_SCENE(brainfuck, set_input, SetInput)
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "../brainfuck_i.h"
|
||||
|
||||
void brainfuck_scene_dev_env_on_enter(void* context) {
|
||||
BFApp* app = context;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, brainfuckViewDev);
|
||||
}
|
||||
|
||||
bool brainfuck_scene_dev_env_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void brainfuck_scene_dev_env_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "../brainfuck_i.h"
|
||||
|
||||
void brainfuck_scene_exec_env_on_enter(void* context) {
|
||||
BFApp* app = context;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, brainfuckViewTextBox);
|
||||
}
|
||||
|
||||
bool brainfuck_scene_exec_env_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void brainfuck_scene_exec_env_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "../brainfuck_i.h"
|
||||
|
||||
void file_name_text_input_callback(void* context) {
|
||||
BFApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, brainfuckCustomEventTextInputDone);
|
||||
}
|
||||
|
||||
char tmpName[64] = {};
|
||||
byte empty[1] = {0x00};
|
||||
void brainfuck_scene_file_create_on_enter(void* context) {
|
||||
BFApp* app = context;
|
||||
TextInput* text_input = app->text_input;
|
||||
|
||||
text_input_set_header_text(text_input, "New script name");
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
file_name_text_input_callback,
|
||||
app,
|
||||
tmpName,
|
||||
64,
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, brainfuckViewTextInput);
|
||||
}
|
||||
|
||||
bool brainfuck_scene_file_create_on_event(void* context, SceneManagerEvent event) {
|
||||
BFApp* app = context;
|
||||
UNUSED(app);
|
||||
|
||||
bool consumed = false;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == brainfuckCustomEventTextInputDone) {
|
||||
furi_string_cat_printf(app->BF_file_path, "/ext/brainfuck/%s.b", tmpName);
|
||||
|
||||
//remove old file
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_simply_remove(storage, furi_string_get_cstr(app->BF_file_path));
|
||||
|
||||
//save new file
|
||||
Stream* stream = buffered_file_stream_alloc(storage);
|
||||
buffered_file_stream_open(stream, furi_string_get_cstr(app->BF_file_path), FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||
stream_write(stream, (const uint8_t*)empty, 1);
|
||||
buffered_file_stream_close(stream);
|
||||
|
||||
//scene_manager_next_scene(app->scene_manager, brainfuckSceneFileSelect);
|
||||
scene_manager_next_scene(app->scene_manager, brainfuckSceneDevEnv);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void brainfuck_scene_file_create_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "../brainfuck_i.h"
|
||||
|
||||
void brainfuck_scene_file_select_on_enter(void* context) {
|
||||
BFApp* app = context;
|
||||
|
||||
DialogsApp* dialogs = furi_record_open("dialogs");
|
||||
FuriString* path;
|
||||
path = furi_string_alloc();
|
||||
furi_string_set(path, "/ext/brainfuck");
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(&browser_options, ".b", &I_bfico);
|
||||
browser_options.base_path = "/ext/brainfuck";
|
||||
browser_options.hide_ext = false;
|
||||
|
||||
bool selected = dialog_file_browser_show(dialogs, path, path, &browser_options);
|
||||
|
||||
if(selected){
|
||||
furi_string_set(app->BF_file_path, path);
|
||||
scene_manager_next_scene(app->scene_manager, brainfuckSceneDevEnv);
|
||||
}
|
||||
else{
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, brainfuckSceneStart);
|
||||
}
|
||||
}
|
||||
|
||||
bool brainfuck_scene_file_select_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void brainfuck_scene_file_select_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "../brainfuck_i.h"
|
||||
|
||||
void set_input_text_input_callback(void* context) {
|
||||
BFApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, brainfuckCustomEventTextInputDone);
|
||||
}
|
||||
|
||||
void brainfuck_scene_set_input_on_enter(void* context) {
|
||||
BFApp* app = context;
|
||||
TextInput* text_input = app->text_input;
|
||||
|
||||
text_input_set_header_text(text_input, "Edit input buffer");
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
set_input_text_input_callback,
|
||||
app,
|
||||
app->inputBuffer,
|
||||
64,
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, brainfuckViewTextInput);
|
||||
}
|
||||
|
||||
bool brainfuck_scene_set_input_on_event(void* context, SceneManagerEvent event) {
|
||||
BFApp* app = context;
|
||||
|
||||
bool consumed = false;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == brainfuckCustomEventTextInputDone) {
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, brainfuckSceneDevEnv);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void brainfuck_scene_set_input_on_exit(void* context) {
|
||||
BFApp* app = context;
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, brainfuckSceneDevEnv);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "../brainfuck_i.h"
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexNew,
|
||||
SubmenuIndexOpen,
|
||||
SubmenuIndexAbout,
|
||||
};
|
||||
|
||||
void brainfuck_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
BFApp* brainfuck = context;
|
||||
view_dispatcher_send_custom_event(brainfuck->view_dispatcher, index);
|
||||
}
|
||||
void brainfuck_scene_start_on_enter(void* context) {
|
||||
BFApp* brainfuck = context;
|
||||
|
||||
Submenu* submenu = brainfuck->submenu;
|
||||
submenu_add_item(submenu, "New", SubmenuIndexNew, brainfuck_scene_start_submenu_callback, brainfuck);
|
||||
submenu_add_item(submenu, "Open", SubmenuIndexOpen, brainfuck_scene_start_submenu_callback, brainfuck);
|
||||
submenu_add_item(submenu, "About", SubmenuIndexAbout, brainfuck_scene_start_submenu_callback, brainfuck);
|
||||
|
||||
submenu_set_selected_item(submenu, scene_manager_get_scene_state(brainfuck->scene_manager, brainfuckSceneStart));
|
||||
view_dispatcher_switch_to_view(brainfuck->view_dispatcher, brainfuckViewMenu);
|
||||
}
|
||||
|
||||
bool brainfuck_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
BFApp* brainfuck = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexNew) {
|
||||
scene_manager_next_scene(brainfuck->scene_manager, brainfuckSceneFileCreate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexOpen) {
|
||||
scene_manager_next_scene(brainfuck->scene_manager, brainfuckSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexAbout) {
|
||||
text_box_set_text(brainfuck->text_box, "FlipperBrainfuck\n\nAn F0 brainfuck intepretor\nBy github.com/Nymda");
|
||||
scene_manager_next_scene(brainfuck->scene_manager, brainfuckSceneExecEnv);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(brainfuck->scene_manager, brainfuckSceneStart, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void brainfuck_scene_start_on_exit(void* context) {
|
||||
BFApp* brainfuck = context;
|
||||
submenu_reset(brainfuck->submenu);
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
#include "bf_dev_env.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
typedef struct BFDevEnv {
|
||||
View* view;
|
||||
DevEnvOkCallback callback;
|
||||
void* context;
|
||||
BFApp* appDev;
|
||||
} BFDevEnv;
|
||||
|
||||
typedef struct {
|
||||
uint32_t row;
|
||||
uint32_t col;
|
||||
} BFDevEnvModel;
|
||||
|
||||
typedef struct{
|
||||
int up;
|
||||
int down;
|
||||
int left;
|
||||
int right;
|
||||
}bMapping;
|
||||
|
||||
static bool bf_dev_process_up(BFDevEnv* devEnv);
|
||||
static bool bf_dev_process_down(BFDevEnv* devEnv);
|
||||
static bool bf_dev_process_left(BFDevEnv* devEnv);
|
||||
static bool bf_dev_process_right(BFDevEnv* devEnv);
|
||||
static bool bf_dev_process_ok(BFDevEnv* devEnv, InputEvent* event);
|
||||
|
||||
BFApp* appDev;
|
||||
|
||||
char bfChars[9] = {'<', '>', '[', ']', '+', '-', '.', ',', 0x00};
|
||||
|
||||
int selectedButton = 0;
|
||||
int saveNotifyCountdown = 0;
|
||||
int execCountdown = 0;
|
||||
|
||||
char dspLine0[25] = {};
|
||||
char dspLine1[25] = {};
|
||||
char dspLine2[25] = {};
|
||||
|
||||
static bMapping buttonMappings[12] = {
|
||||
{ 8, 8, 7, 1}, //0
|
||||
{ 8, 8, 0, 2}, //1
|
||||
{ 9, 9, 1, 3}, //2
|
||||
{ 9, 9, 2, 4}, //3
|
||||
{10, 10, 3, 5}, //4
|
||||
{10, 10, 4, 6}, //5
|
||||
{11, 11, 5, 7}, //6
|
||||
{11, 11, 6, 0}, //7
|
||||
|
||||
{ 0, 0, 11, 9}, //8
|
||||
{ 3, 3, 8, 10}, //9
|
||||
{ 5, 5, 9, 11}, //10
|
||||
{ 6, 6, 10, 8} //11
|
||||
};
|
||||
|
||||
#define BT_X 14
|
||||
#define BT_Y 14
|
||||
static void bf_dev_draw_button(Canvas* canvas, int x, int y, bool selected, const char* lbl){
|
||||
UNUSED(lbl);
|
||||
|
||||
if(selected){
|
||||
canvas_draw_rbox(canvas, x, y, BT_X, BT_Y, 3);
|
||||
canvas_invert_color(canvas);
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
canvas_draw_str_aligned(canvas, x + (BT_X/2), y + (BT_Y/2) - 1, AlignCenter, AlignCenter, lbl);
|
||||
canvas_invert_color(canvas);
|
||||
}
|
||||
else{
|
||||
canvas_draw_rbox(canvas, x, y, BT_X, BT_Y, 3);
|
||||
canvas_invert_color(canvas);
|
||||
canvas_draw_rbox(canvas, x+2, y-1, BT_X - 2, BT_Y - 1, 3);
|
||||
canvas_invert_color(canvas);
|
||||
canvas_draw_rframe(canvas, x, y, BT_X, BT_Y, 3);
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
canvas_draw_str_aligned(canvas, x + (BT_X/2), y + (BT_Y/2) - 1, AlignCenter, AlignCenter, lbl);
|
||||
}
|
||||
}
|
||||
|
||||
static void bf_dev_draw_callback(Canvas* canvas, void* _model) {
|
||||
UNUSED(_model);
|
||||
|
||||
if(execCountdown > 0){
|
||||
execCountdown--;
|
||||
canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, "RUNNING...");
|
||||
if(execCountdown == 0){
|
||||
initWorker(appDev);
|
||||
beginWorker();
|
||||
text_box_set_text(appDev->text_box, workerGetOutput());
|
||||
scene_manager_next_scene(appDev->scene_manager, brainfuckSceneExecEnv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(saveNotifyCountdown > 0){
|
||||
canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, "SAVED");
|
||||
saveNotifyCountdown--;
|
||||
return;
|
||||
}
|
||||
|
||||
bf_dev_draw_button(canvas, 1, 36, (selectedButton == 0), "+"); //T 0
|
||||
bf_dev_draw_button(canvas, 17, 36, (selectedButton == 1), "-"); //T 1
|
||||
bf_dev_draw_button(canvas, 33, 36, (selectedButton == 2), "<"); //T 2
|
||||
bf_dev_draw_button(canvas, 49, 36, (selectedButton == 3), ">"); //T 3
|
||||
bf_dev_draw_button(canvas, 65, 36, (selectedButton == 4), "["); //B 0
|
||||
bf_dev_draw_button(canvas, 81, 36, (selectedButton == 5), "]"); //B 1
|
||||
bf_dev_draw_button(canvas, 97, 36, (selectedButton == 6), "."); //B 2
|
||||
bf_dev_draw_button(canvas, 113, 36, (selectedButton == 7), ","); //B 3
|
||||
|
||||
//backspace, input, run, save
|
||||
canvas_draw_icon(canvas, 1, 52, (selectedButton == 8) ? &I_KeyBackspaceSelected_24x11 : &I_KeyBackspace_24x11);
|
||||
canvas_draw_icon(canvas, 45, 52, (selectedButton == 9) ? &I_KeyInputSelected_30x11 : &I_KeyInput_30x11);
|
||||
canvas_draw_icon(canvas, 77, 52, (selectedButton == 10) ? &I_KeyRunSelected_24x11 : &I_KeyRun_24x11);
|
||||
canvas_draw_icon(canvas, 103, 52, (selectedButton == 11) ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11);
|
||||
|
||||
if(saveNotifyCountdown > 0){
|
||||
canvas_draw_icon(canvas, 98, 54, &I_ButtonRightSmall_3x5);
|
||||
saveNotifyCountdown--;
|
||||
}
|
||||
|
||||
//textbox
|
||||
//grossly overcomplicated. not fixing it.
|
||||
canvas_draw_rframe(canvas, 1, 1, 125, 33, 2);
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
|
||||
int dbOffset = 0;
|
||||
if(appDev->dataSize > 72){
|
||||
dbOffset = (appDev->dataSize - 72);
|
||||
}
|
||||
|
||||
memset(dspLine0, 0x00, 25);
|
||||
memset(dspLine1, 0x00, 25);
|
||||
memset(dspLine2, 0x00, 25);
|
||||
|
||||
int tpM = 0;
|
||||
int tp0 = 0;
|
||||
int tp1 = 0;
|
||||
int tp2 = 0;
|
||||
|
||||
for(int p = dbOffset; p < appDev->dataSize; p++){
|
||||
if(tpM < 24 * 1){
|
||||
dspLine0[tp0] = appDev->dataBuffer[p];
|
||||
tp0++;
|
||||
}
|
||||
else if(tpM < 24 * 2){
|
||||
dspLine1[tp1] = appDev->dataBuffer[p];
|
||||
tp1++;
|
||||
}
|
||||
else if(tpM < 24 * 3){
|
||||
dspLine2[tp2] = appDev->dataBuffer[p];
|
||||
tp2++;
|
||||
}
|
||||
tpM++;
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 3, 8, AlignLeft, AlignCenter, dspLine0);
|
||||
canvas_draw_str_aligned(canvas, 3, 17, AlignLeft, AlignCenter, dspLine1);
|
||||
canvas_draw_str_aligned(canvas, 3, 26, AlignLeft, AlignCenter, dspLine2);
|
||||
}
|
||||
|
||||
|
||||
static bool bf_dev_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
BFDevEnv* devEnv = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyRight) {
|
||||
consumed = bf_dev_process_right(devEnv);
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
consumed = bf_dev_process_left(devEnv);
|
||||
} else if(event->key == InputKeyUp) {
|
||||
consumed = bf_dev_process_up(devEnv);
|
||||
} else if(event->key == InputKeyDown) {
|
||||
consumed = bf_dev_process_down(devEnv);
|
||||
}
|
||||
} else if(event->key == InputKeyOk) {
|
||||
consumed = bf_dev_process_ok(devEnv, event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static bool bf_dev_process_up(BFDevEnv* devEnv) {
|
||||
UNUSED(devEnv);
|
||||
selectedButton = buttonMappings[selectedButton].up;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bf_dev_process_down(BFDevEnv* devEnv) {
|
||||
UNUSED(devEnv);
|
||||
selectedButton = buttonMappings[selectedButton].down;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bf_dev_process_left(BFDevEnv* devEnv) {
|
||||
UNUSED(devEnv);
|
||||
selectedButton = buttonMappings[selectedButton].left;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bf_dev_process_right(BFDevEnv* devEnv) {
|
||||
UNUSED(devEnv);
|
||||
selectedButton = buttonMappings[selectedButton].right;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bf_dev_process_ok(BFDevEnv* devEnv, InputEvent* event) {
|
||||
UNUSED(devEnv);
|
||||
UNUSED(event);
|
||||
|
||||
if(event->type != InputTypePress){ return false; }
|
||||
|
||||
switch(selectedButton){
|
||||
case 0:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)'+';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)'-';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)'<';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)'>';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)'[';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)']';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)'.';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
if(appDev->dataSize < BF_INST_BUFFER_SIZE){
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)',';
|
||||
appDev->dataSize++; }
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
if(appDev->dataSize > 0){
|
||||
appDev->dataSize--;
|
||||
appDev->dataBuffer[appDev->dataSize] = (uint32_t)0x00;}
|
||||
break;
|
||||
}
|
||||
|
||||
case 9:
|
||||
{
|
||||
//todo: input
|
||||
scene_manager_next_scene(appDev->scene_manager, brainfuckSceneSetInput);
|
||||
break;
|
||||
}
|
||||
|
||||
case 10:
|
||||
{
|
||||
execCountdown = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
case 11:
|
||||
{
|
||||
//remove old file
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_simply_remove(storage, furi_string_get_cstr(appDev->BF_file_path));
|
||||
|
||||
//save new file
|
||||
Stream* stream = buffered_file_stream_alloc(storage);
|
||||
buffered_file_stream_open(stream, furi_string_get_cstr(appDev->BF_file_path), FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||
stream_write(stream, (const uint8_t*)appDev->dataBuffer, appDev->dataSize);
|
||||
buffered_file_stream_close(stream);
|
||||
|
||||
//notify
|
||||
saveNotifyCountdown = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool consumed = false;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void bf_dev_enter_callback(void* context) {
|
||||
furi_assert(context);
|
||||
BFDevEnv* devEnv = context;
|
||||
|
||||
with_view_model(
|
||||
devEnv->view,
|
||||
BFDevEnvModel* model,
|
||||
{
|
||||
model->col = 0;
|
||||
model->row = 0;
|
||||
},
|
||||
true);
|
||||
|
||||
appDev = devEnv->appDev;
|
||||
selectedButton = 0;
|
||||
|
||||
//clear the bf instruction buffer
|
||||
memset(appDev->dataBuffer, 0x00, BF_INST_BUFFER_SIZE * sizeof(char));
|
||||
|
||||
//open the file
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
Stream* stream = buffered_file_stream_alloc(storage);
|
||||
buffered_file_stream_open(stream, furi_string_get_cstr(appDev->BF_file_path), FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
|
||||
//read into the buffer
|
||||
appDev->dataSize = stream_size(stream);
|
||||
stream_read(stream, (uint8_t*)appDev->dataBuffer, appDev->dataSize);
|
||||
buffered_file_stream_close(stream);
|
||||
|
||||
//replaces any invalid characters with an underscore. strips out newlines, comments, etc
|
||||
for(int i = 0; i < appDev->dataSize; i++){
|
||||
if(!strchr(bfChars, appDev->dataBuffer[i])){
|
||||
appDev->dataBuffer[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
//find the end of the file to begin editing
|
||||
int tptr = 0;
|
||||
while(appDev->dataBuffer[tptr] != 0x00){ tptr++; }
|
||||
appDev->dataSize = tptr;
|
||||
}
|
||||
|
||||
BFDevEnv* bf_dev_env_alloc(BFApp* appDev) {
|
||||
BFDevEnv* devEnv = malloc(sizeof(BFDevEnv));
|
||||
|
||||
devEnv->view = view_alloc();
|
||||
devEnv->appDev = appDev;
|
||||
view_allocate_model(devEnv->view, ViewModelTypeLocking, sizeof(BFDevEnvModel));
|
||||
|
||||
with_view_model(
|
||||
devEnv->view,
|
||||
BFDevEnvModel* model,
|
||||
{
|
||||
model->col = 0;
|
||||
model->row = 0;
|
||||
},
|
||||
true);
|
||||
|
||||
view_set_context(devEnv->view, devEnv);
|
||||
view_set_draw_callback(devEnv->view, bf_dev_draw_callback);
|
||||
view_set_input_callback(devEnv->view, bf_dev_input_callback);
|
||||
view_set_enter_callback(devEnv->view, bf_dev_enter_callback);
|
||||
return devEnv;
|
||||
}
|
||||
|
||||
void bf_dev_env_free(BFDevEnv* devEnv) {
|
||||
furi_assert(devEnv);
|
||||
view_free(devEnv->view);
|
||||
free(devEnv);
|
||||
}
|
||||
|
||||
View* bf_dev_env_get_view(BFDevEnv* devEnv) {
|
||||
furi_assert(devEnv);
|
||||
return devEnv->view;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "../brainfuck_i.h"
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef void (*DevEnvOkCallback)(InputType type, void* context);
|
||||
|
||||
BFDevEnv* bf_dev_env_alloc(BFApp* application);
|
||||
|
||||
void bf_dev_set_file_path(FuriString* path);
|
||||
|
||||
void bf_dev_env_free(BFDevEnv* devEnv);
|
||||
|
||||
View* bf_dev_env_get_view(BFDevEnv* devEnv);
|
||||
|
||||
void bf_dev_env_set_ok(
|
||||
BFDevEnv* devEnv,
|
||||
DevEnvOkCallback callback,
|
||||
void* context);
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "worker.h"
|
||||
|
||||
int status = 0; //0: idle, 1: running, 2: failure
|
||||
|
||||
char* inst = 0;
|
||||
int instCount = 0;
|
||||
int instPtr = 0;
|
||||
int runOpCount = 0;
|
||||
|
||||
char* wOutput = 0;
|
||||
int wOutputPtr = 0;
|
||||
|
||||
char* wInput = 0;
|
||||
int wInputPtr = 0;
|
||||
|
||||
uint8_t* bfStack = 0;
|
||||
int stackPtr = 0;
|
||||
int stackSize = BF_STACK_INITIAL_SIZE;
|
||||
int stackSizeReal = 0;
|
||||
|
||||
bool validateInstPtr(){
|
||||
if(instPtr > instCount || instPtr < 0){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validateStackPtr(){
|
||||
if(stackPtr > stackSize || stackPtr < 0){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char* workerGetOutput(){
|
||||
return wOutput;
|
||||
}
|
||||
|
||||
int getStackSize(){
|
||||
return stackSizeReal;
|
||||
}
|
||||
|
||||
int getOpCount(){
|
||||
return runOpCount;
|
||||
}
|
||||
|
||||
int getStatus(){
|
||||
return status;
|
||||
}
|
||||
|
||||
void initWorker(BFApp* app){
|
||||
//rebuild output
|
||||
if(wOutput){ free(wOutput); }
|
||||
wOutput = (char*)malloc(BF_OUTPUT_SIZE);
|
||||
wOutputPtr = 0;
|
||||
|
||||
//rebuild stack
|
||||
if(bfStack){ free(bfStack); }
|
||||
bfStack = (uint8_t*)malloc(BF_STACK_INITIAL_SIZE);
|
||||
memset(bfStack, 0x00, BF_STACK_INITIAL_SIZE);
|
||||
stackSize = BF_STACK_INITIAL_SIZE;
|
||||
stackSizeReal = 0;
|
||||
stackPtr = 0;
|
||||
|
||||
//set instructions
|
||||
inst = app->dataBuffer;
|
||||
instCount = app->dataSize;
|
||||
instPtr = 0;
|
||||
runOpCount = 0;
|
||||
|
||||
//set input
|
||||
wInput = app->inputBuffer;
|
||||
wInputPtr = 0;
|
||||
|
||||
//set status
|
||||
status = 0;
|
||||
}
|
||||
|
||||
void rShift(){
|
||||
runOpCount++;
|
||||
stackPtr++;
|
||||
if(!validateStackPtr()){ status = 2; return; }
|
||||
|
||||
while(stackPtr > stackSize){
|
||||
stackSize += BF_STACK_STEP_SIZE;
|
||||
void* tmp = realloc(bfStack, stackSize);
|
||||
|
||||
if(!tmp){
|
||||
status = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
memset((tmp + stackSize) - BF_STACK_STEP_SIZE, 0x00, BF_STACK_STEP_SIZE);
|
||||
bfStack = (uint8_t*)tmp;
|
||||
};
|
||||
if(stackPtr > stackSizeReal){
|
||||
stackSizeReal = stackPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void lShift(){
|
||||
runOpCount++;
|
||||
stackPtr--;
|
||||
if(!validateStackPtr()){ status = 2; return; }
|
||||
}
|
||||
|
||||
void inc(){
|
||||
runOpCount++;
|
||||
if(!validateStackPtr()){ status = 2; return; }
|
||||
bfStack[stackPtr]++;
|
||||
}
|
||||
|
||||
void dec(){
|
||||
runOpCount++;
|
||||
if(!validateStackPtr()){ status = 2; return; }
|
||||
bfStack[stackPtr]--;
|
||||
}
|
||||
|
||||
void print(){
|
||||
runOpCount++;
|
||||
wOutput[wOutputPtr] = bfStack[stackPtr];
|
||||
wOutputPtr++;
|
||||
if(wOutputPtr > (BF_OUTPUT_SIZE - 1)){ wOutputPtr = 0;}
|
||||
}
|
||||
|
||||
void input(){
|
||||
runOpCount++;
|
||||
|
||||
bfStack[stackPtr] = (uint8_t)wInput[wInputPtr];
|
||||
if(wInput[wInputPtr] == 0x00 || wInputPtr >= 64){
|
||||
wInputPtr = 0;
|
||||
}
|
||||
else{
|
||||
wInputPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
runOpCount++;
|
||||
if (bfStack[stackPtr] == 0) {
|
||||
int loopCount = 1;
|
||||
while (loopCount > 0) {
|
||||
instPtr++;
|
||||
if(!validateInstPtr()){ status = 2; return; }
|
||||
if (inst[instPtr] == '[') { loopCount++; }
|
||||
else if (inst[instPtr] == ']') { loopCount--; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endLoop() {
|
||||
runOpCount++;
|
||||
if (bfStack[stackPtr] != 0) {
|
||||
int loopCount = 1;
|
||||
while (loopCount > 0) {
|
||||
instPtr--;
|
||||
if(!validateInstPtr()){ status = 2; return; }
|
||||
if (inst[instPtr] == ']') { loopCount++; }
|
||||
else if (inst[instPtr] == '[') { loopCount--; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void beginWorker(){
|
||||
status = 1;
|
||||
while (inst[instPtr] != 0x00) {
|
||||
if(status == 2){ return; }
|
||||
switch (inst[instPtr]) {
|
||||
case '>':
|
||||
rShift();
|
||||
break;
|
||||
case '<':
|
||||
lShift();
|
||||
break;
|
||||
|
||||
case '+':
|
||||
inc();
|
||||
break;
|
||||
|
||||
case '-':
|
||||
dec();
|
||||
break;
|
||||
|
||||
case '.':
|
||||
print();
|
||||
break;
|
||||
|
||||
case ',':
|
||||
input();
|
||||
break;
|
||||
|
||||
case '[':
|
||||
loop();
|
||||
break;
|
||||
|
||||
case ']':
|
||||
endLoop();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
instPtr++;
|
||||
if(!validateInstPtr()){ status = 2; return; }
|
||||
}
|
||||
status = 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "brainfuck_i.h"
|
||||
|
||||
void initWorker(BFApp* application);
|
||||
char* workerGetOutput();
|
||||
int getStackSize();
|
||||
int getOpCount();
|
||||
int getStatus();
|
||||
void beginWorker();
|
||||