Added xMasterX API v11.x source

This commit is contained in:
UberGuidoZ
2023-01-25 23:52:38 -08:00
parent 33322c0d73
commit e292fbfcd5
1094 changed files with 102160 additions and 0 deletions
@@ -0,0 +1,16 @@
# Flipper Zero Dice App
<div style="text-align:center"><img src="sources/flipper-screen.png"/></div>
## Screenshots
<div style="text-align:center"><img src="sources/main-screen.png"/></div>
<br />
<div style="text-align:center"><img src="sources/roll-screen.png"/></div>
## Compiling
1. Clone the [flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware) repository or another firmware that you use.
2. Create a symbolic link in `applications_user` named **dice**, pointing to this repository.
3. Compile by command `./fbt fap_dice_app`
4. Copy `build/f7-firmware-D/.extapps/dice_app.fap` to **apps/Tools** on the SD card or by [qFlipper](https://flipperzero.one/update) app.
@@ -0,0 +1,13 @@
App(
appid="dice_app",
name="Dice",
apptype=FlipperAppType.PLUGIN,
entry_point="dice_tool_app",
cdefines=["APP_DICE"],
requires=["gui"],
stack_size=1 * 1024,
order=90,
fap_icon="icon.png",
fap_category="Games_Extra",
fap_icon_assets="assets",
)
Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

@@ -0,0 +1,116 @@
#include <gui/icon.h>
#include "dice_app_icons.h"
#define TAG "DiceApp"
#define DICE_TYPES 8
#define MAX_DICE_COUNT 10
#define MAX_COIN_FRAMES 9
#define MAX_DICE_FRAMES 4
#define DICE_X 45
#define DICE_Y 6
#define DICE_Y_T 0
#define DICE_GAP 44
#define SWIPE_DIST 11
const Icon* coin_heads_start[] = {&I_coin_1, &I_coin_2};
const Icon* coin_heads_end[] = {&I_coin_7, &I_coin_1};
const Icon* coin_tails_start[] = {&I_coin_5, &I_coin_6};
const Icon* coin_tails_end[] = {&I_coin_4, &I_coin_5};
const Icon* coin_frames[] = {
&I_coin_1,
&I_coin_2,
&I_coin_3,
&I_coin_4,
&I_coin_5,
&I_coin_6,
&I_coin_3,
&I_coin_7,
&I_coin_1,
};
const Icon* dice_frames[] = {
&I_d4_1, &I_d4_2, &I_d4_3, &I_d4_1, // d4
&I_d6_1, &I_d6_2, &I_d6_3, &I_d6_4, // d6
&I_d8_1, &I_d8_2, &I_d8_3, &I_d8_4, // d8
&I_d10_1, &I_d10_2, &I_d10_3, &I_d10_4, // d10
&I_d12_1, &I_d12_2, &I_d12_3, &I_d12_4, // d12
&I_d20_1, &I_d20_2, &I_d20_3, &I_d20_4, // d20
&I_d100_1, &I_d100_2, &I_d100_3, &I_d100_4, // d100
};
typedef struct {
uint8_t type;
int x;
int y;
char* name;
} Dice;
const uint8_t screen_pos[] = {};
static const Dice dice_types[] = {
{2, 0, 0, "Coin"},
{4, 0, 0, "d4"},
{6, 0, 0, "d6"},
{8, 0, 0, "d8"},
{10, 0, 0, "d10"},
{12, 0, 0, "d12"},
{20, 0, 0, "d20"},
{100, 0, 0, "d100"},
};
typedef enum { EventTypeTick, EventTypeKey } EventType;
typedef enum { SelectState, SwipeLeftState, SwipeRightState, AnimState, ResultState } AppState;
typedef struct {
EventType type;
InputEvent input;
} AppEvent;
typedef struct {
AppState app_state;
uint16_t roll_result;
uint8_t rolled_dices[MAX_DICE_COUNT];
uint8_t anim_frame;
uint8_t dice_index;
uint8_t dice_count;
Dice dices[DICE_TYPES];
} State;
void init(State* const state) {
state->app_state = SelectState;
state->roll_result = 0;
state->dice_index = 0;
state->anim_frame = 0;
state->dice_count = 1;
for(uint8_t i = 0; i < DICE_TYPES; i++) {
state->dices[i] = dice_types[i];
state->dices[i].x = DICE_X + (i * DICE_GAP);
state->dices[i].y = i == 0 ? DICE_Y_T : DICE_Y;
}
}
void coin_set_start(uint16_t type) {
if(type == 1) {
coin_frames[0] = coin_heads_start[0];
coin_frames[1] = coin_heads_start[1];
} else {
coin_frames[0] = coin_tails_start[0];
coin_frames[1] = coin_tails_start[1];
}
}
void coin_set_end(uint16_t type) {
if(type == 1) {
coin_frames[MAX_COIN_FRAMES - 2] = coin_heads_end[0];
coin_frames[MAX_COIN_FRAMES - 1] = coin_heads_end[1];
} else {
coin_frames[MAX_COIN_FRAMES - 2] = coin_tails_end[0];
coin_frames[MAX_COIN_FRAMES - 1] = coin_tails_end[1];
}
}
@@ -0,0 +1,267 @@
#include <furi.h>
#include <input/input.h>
#include <gui/gui.h>
#include "constants.h"
const Icon* draw_dice_frame;
static void update(State* const state) {
if(state->app_state == SwipeLeftState) {
for(uint8_t i = 0; i < DICE_TYPES; i++) {
state->dices[i].x -= SWIPE_DIST;
state->dices[i].y = DICE_Y;
}
if(state->dices[state->dice_index].x == DICE_X) {
state->app_state = SelectState;
state->dices[state->dice_index].y = DICE_Y_T;
}
} else if(state->app_state == SwipeRightState) {
for(uint8_t i = 0; i < DICE_TYPES; i++) {
state->dices[i].x += SWIPE_DIST;
state->dices[i].y = DICE_Y;
}
if(state->dices[state->dice_index].x == DICE_X) {
state->app_state = SelectState;
state->dices[state->dice_index].y = DICE_Y_T;
}
} else if(state->app_state == AnimState) {
state->anim_frame += 1;
if(state->dice_index == 0) {
if(state->anim_frame == 3) coin_set_start(state->roll_result); // change coin anim
if(state->anim_frame >= MAX_COIN_FRAMES) {
state->anim_frame = 0;
state->app_state = ResultState;
}
} else {
if(state->anim_frame >= MAX_DICE_FRAMES) {
state->anim_frame = 0;
state->app_state = ResultState;
}
}
}
}
static void roll(State* const state) {
state->roll_result = 0;
for(uint8_t i = 0; i < MAX_DICE_COUNT; i++) {
if(i < state->dice_count) {
state->rolled_dices[i] = (rand() % dice_types[state->dice_index].type) + 1;
state->roll_result += state->rolled_dices[i];
} else {
state->rolled_dices[i] = 0;
}
}
if(state->dice_index == 0) coin_set_end(state->roll_result); // change coin anim
state->app_state = AnimState;
}
static void draw_ui(const State* state, Canvas* canvas) {
canvas_set_font(canvas, FontSecondary);
FuriString* count = furi_string_alloc();
furi_string_printf(count, "%01d", state->dice_count);
// dice name and arrows
if(state->app_state != SwipeLeftState && state->app_state != SwipeRightState) {
canvas_draw_str_aligned(
canvas, 63, 50, AlignCenter, AlignBottom, dice_types[state->dice_index].name);
if(state->dice_index > 0) canvas_draw_icon(canvas, 45, 44, &I_ui_button_left);
if(state->dice_index < DICE_TYPES - 1)
canvas_draw_icon(canvas, 78, 44, &I_ui_button_right);
}
// dice settings
if(state->dice_index == 0)
canvas_draw_icon(canvas, 48, 51, &I_ui_count_1);
else
canvas_draw_icon(canvas, 48, 51, &I_ui_count);
canvas_draw_str_aligned(canvas, 58, 61, AlignCenter, AlignBottom, furi_string_get_cstr(count));
// buttons
canvas_draw_icon(canvas, 92, 54, &I_ui_button_roll);
canvas_draw_icon(canvas, 0, 54, &I_ui_button_exit);
furi_string_free(count);
}
static void draw_dice(const State* state, Canvas* canvas) {
for(uint8_t i = 0; i < DICE_TYPES; i++) {
if(state->app_state == ResultState && state->dice_index == i && state->dice_index != 0)
continue; // draw results except coin
if(state->dices[i].x > 128 || state->dices[i].x < -35) continue; // outside the screen
if(i == state->dice_index) { // draw dice with animation
if(i == 0) { // coin
draw_dice_frame = coin_frames[state->anim_frame];
} else { // dices
draw_dice_frame = dice_frames[(i - 1) * MAX_DICE_FRAMES + state->anim_frame];
}
} else { // draw first dice frame
if(i == 0) { // coin
draw_dice_frame = coin_frames[0];
} else { // dices
draw_dice_frame = dice_frames[(i - 1) * MAX_DICE_FRAMES];
}
}
canvas_draw_icon(canvas, state->dices[i].x, state->dices[i].y, draw_dice_frame);
}
}
static void draw_results(const State* state, Canvas* canvas) {
if(state->app_state != ResultState) return;
if(state->dice_index == 0) return; // skip for coin
canvas_set_font(canvas, FontPrimary);
FuriString* sum = furi_string_alloc();
furi_string_printf(sum, "%01d", state->roll_result);
// result text
canvas_draw_str_aligned(canvas, 64, 20, AlignCenter, AlignCenter, furi_string_get_cstr(sum));
// ui frame
if(state->roll_result > 99)
canvas_draw_icon(canvas, 52, 26, &I_ui_result_3);
else if(state->roll_result > 9)
canvas_draw_icon(canvas, 56, 26, &I_ui_result_2);
else
canvas_draw_icon(canvas, 58, 26, &I_ui_result_1);
furi_string_free(sum);
}
static void draw_callback(Canvas* canvas, void* ctx) {
const State* state = acquire_mutex((ValueMutex*)ctx, 25);
if(state == NULL) {
return;
}
canvas_clear(canvas);
draw_ui(state, canvas);
draw_dice(state, canvas);
draw_results(state, canvas);
release_mutex((ValueMutex*)ctx, state);
}
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
furi_assert(event_queue);
AppEvent event = {.type = EventTypeKey, .input = *input_event};
furi_message_queue_put(event_queue, &event, FuriWaitForever);
}
static void timer_callback(FuriMessageQueue* event_queue) {
furi_assert(event_queue);
AppEvent event = {.type = EventTypeTick};
furi_message_queue_put(event_queue, &event, 0);
}
int32_t dice_tool_app(void* p) {
UNUSED(p);
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));
FURI_LOG_E(TAG, ">>> Started...\r\n");
State* state = malloc(sizeof(State));
init(state);
ValueMutex state_mutex;
if(!init_mutex(&state_mutex, state, sizeof(State))) {
FURI_LOG_E(TAG, "cannot create mutex\r\n");
free(state);
return 255;
}
// Set callbacks
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, draw_callback, &state_mutex);
view_port_input_callback_set(view_port, input_callback, event_queue);
FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue);
furi_timer_start(timer, furi_kernel_get_tick_frequency() * 0.2);
// Create GUI, register view port
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
AppEvent event;
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
State* state = (State*)acquire_mutex_block(&state_mutex);
if(event_status == FuriStatusOk) {
// timer evetn
if(event.type == EventTypeTick) {
update(state);
}
// button events
if(event.type == EventTypeKey) {
if(event.input.type == InputTypePress) {
// lock input while animations
if(state->app_state == SelectState || state->app_state == ResultState) {
// input
if(event.input.key == InputKeyUp) {
if(state->dice_index != 0) {
state->dice_count += 1;
if(state->dice_count > MAX_DICE_COUNT) {
state->dice_count = MAX_DICE_COUNT;
}
}
} else if(event.input.key == InputKeyDown) {
state->dice_count -= 1;
if(state->dice_count < 1) {
state->dice_count = 1;
}
} else if(event.input.key == InputKeyRight) {
if(state->dice_index < DICE_TYPES - 1) {
state->dice_index += 1;
state->app_state = SwipeLeftState;
}
} else if(event.input.key == InputKeyLeft) {
if(state->dice_index > 0) {
state->dice_index -= 1;
state->app_state = SwipeRightState;
if(state->dice_index == 0) state->dice_count = 1;
}
} else if(event.input.key == InputKeyOk) {
roll(state);
}
}
// quit from app
if(event.input.key == InputKeyBack) {
processing = false;
}
}
}
} else {
FURI_LOG_D(TAG, "osMessageQueue: event timeout");
}
view_port_update(view_port);
release_mutex(&state_mutex, state);
}
// Clear
free(state);
furi_timer_free(timer);
furi_message_queue_free(event_queue);
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
furi_record_close(RECORD_GUI);
view_port_free(view_port);
delete_mutex(&state_mutex);
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB