diff --git a/applications/plugins/hex_viewer/LICENSE b/applications/plugins/hex_viewer/LICENSE new file mode 100644 index 000000000..69004dc62 --- /dev/null +++ b/applications/plugins/hex_viewer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Roman Shchekin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/applications/plugins/hex_viewer/hex_viewer.c b/applications/plugins/hex_viewer/hex_viewer.c index 5289c8654..50c34d634 100644 --- a/applications/plugins/hex_viewer/hex_viewer.c +++ b/applications/plugins/hex_viewer/hex_viewer.c @@ -16,14 +16,14 @@ #define HEX_VIEWER_APP_PATH_FOLDER "/any" #define HEX_VIEWER_APP_EXTENSION "*" -#define HEX_VIEWER_BYTES_PER_ROW 4 -#define HEX_VIEWER_ROW_COUNT 4 -#define HEX_VIEWER_BUF_SIZE (HEX_VIEWER_BYTES_PER_ROW * HEX_VIEWER_ROW_COUNT) +#define HEX_VIEWER_BYTES_PER_LINE 4u +#define HEX_VIEWER_LINES_ON_SCREEN 4u +#define HEX_VIEWER_BUF_SIZE (HEX_VIEWER_LINES_ON_SCREEN * HEX_VIEWER_BYTES_PER_LINE) typedef struct { - uint8_t file_bytes[HEX_VIEWER_ROW_COUNT][HEX_VIEWER_ROW_COUNT]; - uint32_t line; - uint32_t read_bytes; + uint8_t file_bytes[HEX_VIEWER_LINES_ON_SCREEN][HEX_VIEWER_BYTES_PER_LINE]; + uint32_t file_offset; + uint32_t file_read_bytes; uint32_t file_size; Stream* stream; bool mode; // Print address or content @@ -54,27 +54,28 @@ static void render_callback(Canvas* canvas, void* ctx) { int TOP_OFFSET = 10; int LEFT_OFFSET = 3; - uint32_t line_count = hex_viewer->model->file_size / HEX_VIEWER_BYTES_PER_ROW; - if(hex_viewer->model->file_size % HEX_VIEWER_BYTES_PER_ROW != 0) line_count += 1; - if(line_count > HEX_VIEWER_ROW_COUNT) { + uint32_t line_count = hex_viewer->model->file_size / HEX_VIEWER_BYTES_PER_LINE; + if(hex_viewer->model->file_size % HEX_VIEWER_BYTES_PER_LINE != 0) line_count += 1; + uint32_t first_line_on_screen = hex_viewer->model->file_offset / HEX_VIEWER_BYTES_PER_LINE; + if(line_count > HEX_VIEWER_LINES_ON_SCREEN) { uint8_t width = canvas_width(canvas); elements_scrollbar_pos( canvas, width, 0, - ROW_HEIGHT * HEX_VIEWER_ROW_COUNT, - hex_viewer->model->line, - line_count - (HEX_VIEWER_ROW_COUNT - 1)); + ROW_HEIGHT * HEX_VIEWER_LINES_ON_SCREEN, + first_line_on_screen, // TODO + line_count - (HEX_VIEWER_LINES_ON_SCREEN - 1)); } char temp_buf[32]; - uint32_t row_iters = hex_viewer->model->read_bytes / HEX_VIEWER_BYTES_PER_ROW; - if(hex_viewer->model->read_bytes % HEX_VIEWER_BYTES_PER_ROW != 0) row_iters += 1; + uint32_t row_iters = hex_viewer->model->file_read_bytes / HEX_VIEWER_BYTES_PER_LINE; + if(hex_viewer->model->file_read_bytes % HEX_VIEWER_BYTES_PER_LINE != 0) row_iters += 1; for(uint32_t i = 0; i < row_iters; ++i) { - uint32_t bytes_left_per_row = hex_viewer->model->read_bytes - i * HEX_VIEWER_BYTES_PER_ROW; - if(bytes_left_per_row > HEX_VIEWER_BYTES_PER_ROW) - bytes_left_per_row = HEX_VIEWER_BYTES_PER_ROW; + uint32_t bytes_left_per_row = + hex_viewer->model->file_read_bytes - i * HEX_VIEWER_BYTES_PER_LINE; + bytes_left_per_row = MIN(bytes_left_per_row, HEX_VIEWER_BYTES_PER_LINE); if(hex_viewer->model->mode) { memcpy(temp_buf, hex_viewer->model->file_bytes[i], bytes_left_per_row); @@ -85,8 +86,8 @@ static void render_callback(Canvas* canvas, void* ctx) { canvas_set_font(canvas, FontKeyboard); canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf); } else { - int addr = (i + hex_viewer->model->line) * HEX_VIEWER_BYTES_PER_ROW; - snprintf(temp_buf, 32, "%04X", addr); + uint32_t addr = hex_viewer->model->file_offset + i * HEX_VIEWER_BYTES_PER_LINE; + snprintf(temp_buf, 32, "%04lX", addr); canvas_set_font(canvas, FontKeyboard); canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf); @@ -105,7 +106,7 @@ static void render_callback(Canvas* canvas, void* ctx) { static void input_callback(InputEvent* input_event, void* ctx) { HexViewer* hex_viewer = ctx; - if(input_event->type == InputTypeShort) { + if(input_event->type == InputTypeShort || input_event->type == InputTypeRepeat) { furi_message_queue_put(hex_viewer->input_queue, input_event, 0); } } @@ -173,19 +174,20 @@ static bool hex_viewer_open_file(HexViewer* hex_viewer, const char* file_path) { static bool hex_viewer_read_file(HexViewer* hex_viewer) { furi_assert(hex_viewer); furi_assert(hex_viewer->model->stream); + furi_assert(hex_viewer->model->file_offset % HEX_VIEWER_BYTES_PER_LINE == 0); memset(hex_viewer->model->file_bytes, 0x0, HEX_VIEWER_BUF_SIZE); bool isOk = true; do { - uint32_t offset = hex_viewer->model->line * HEX_VIEWER_BYTES_PER_ROW; + uint32_t offset = hex_viewer->model->file_offset; if(!stream_seek(hex_viewer->model->stream, offset, true)) { FURI_LOG_E(TAG, "Unable to seek stream"); isOk = false; break; } - hex_viewer->model->read_bytes = stream_read( + hex_viewer->model->file_read_bytes = stream_read( hex_viewer->model->stream, (uint8_t*)hex_viewer->model->file_bytes, HEX_VIEWER_BUF_SIZE); @@ -221,6 +223,8 @@ int32_t hex_viewer_app(void* p) { } } + FURI_LOG_I(TAG, "File selected: %s", furi_string_get_cstr(file_path)); + if(!hex_viewer_open_file(hex_viewer, furi_string_get_cstr(file_path))) break; hex_viewer_read_file(hex_viewer); @@ -231,19 +235,18 @@ int32_t hex_viewer_app(void* p) { break; } else if(input.key == InputKeyUp) { furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk); - if(hex_viewer->model->line > 0) { - hex_viewer->model->line--; - + if(hex_viewer->model->file_offset > 0) { + hex_viewer->model->file_offset -= HEX_VIEWER_BYTES_PER_LINE; if(!hex_viewer_read_file(hex_viewer)) break; } furi_mutex_release(hex_viewer->mutex); } else if(input.key == InputKeyDown) { furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk); - uint32_t cur_pos = hex_viewer->model->line * HEX_VIEWER_BYTES_PER_ROW + - hex_viewer->model->read_bytes; + uint32_t last_byte_on_screen = + hex_viewer->model->file_offset + hex_viewer->model->file_read_bytes; - if(hex_viewer->model->file_size > cur_pos) { - hex_viewer->model->line++; + if(hex_viewer->model->file_size > last_byte_on_screen) { + hex_viewer->model->file_offset += HEX_VIEWER_BYTES_PER_LINE; if(!hex_viewer_read_file(hex_viewer)) break; } furi_mutex_release(hex_viewer->mutex); @@ -256,13 +259,14 @@ int32_t hex_viewer_app(void* p) { buffer = furi_string_alloc(); furi_string_printf( buffer, - "File path: %s\nFile size: %lu bytes", + "File path: %s\nFile size: %lu (0x%lX)", furi_string_get_cstr(file_path), + hex_viewer->model->file_size, hex_viewer->model->file_size); DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "Hex Viewer", 16, 2, AlignLeft, AlignTop); + dialog_message_set_header(message, "Hex Viewer v1.1", 16, 2, AlignLeft, AlignTop); dialog_message_set_icon(message, &I_hex_10px, 3, 2); dialog_message_set_text( message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);