Files
fdskey/FdsKey/Core/Src/sideselect.c
2023-08-06 15:38:48 +04:00

272 lines
6.8 KiB
C

#include <fdsemugui.h>
#include <string.h>
#include <stdio.h>
#include "sideselect.h"
#include "fdsemu.h"
#include "oled.h"
#include "ff.h"
#include "splash.h"
#include "buttons.h"
#include "settings.h"
static void fds_side_draw(uint8_t side, uint8_t side_count, char* game_name, int text_scroll)
{
char side_name[8];
DotMatrixImage *disk_image;
int max_width, text_width, total_scroll;
int line = oled_get_line() + OLED_HEIGHT;
int l;
// clear screen
oled_draw_rectangle(0, line, OLED_WIDTH - 1, line + OLED_HEIGHT - 1, 1, 0);
if (side_count <= 2)
{
side_name[0] = 'A' + side;
side_name[1] = 0;
} else {
sprintf(side_name, "%d%c", side / 2 + 1, 'A' + (side % 2));
}
l = strlen(side_name);
disk_image = side_select_get_disk_image(side, side_count);
// arrows
if ((text_scroll / 8) % 2)
{
if (side + 1 < side_count)
oled_draw_image(&IMAGE_CURSOR_DOWN, l > 1 ? 85 : 81, line + OLED_HEIGHT - IMAGE_CURSOR_DOWN.height, 0, 0);
if (side > 0)
oled_draw_image(&IMAGE_CURSOR_UP, l > 1 ? 85 : 81, line + 16, 0, 0);
}
max_width = OLED_WIDTH - disk_image->width - 4;
text_width = oled_get_text_length(&SIDE_SELECT_GAME_NAME_FONT, game_name) - 1 /*spacing*/;
if (text_width > max_width)
{
total_scroll = SIDE_SELECT_HORIZONTAL_SCROLL_PAUSE + (text_width - max_width) + SIDE_SELECT_HORIZONTAL_SCROLL_PAUSE;
text_scroll /= SIDE_SELECT_HORIZONTAL_SCROLL_SPEED;
text_scroll %= total_scroll * 2;
// two-directional
if (text_scroll > total_scroll)
text_scroll = total_scroll * 2 - text_scroll;
if (text_scroll < SIDE_SELECT_HORIZONTAL_SCROLL_PAUSE)
text_scroll = 0;
else if (text_scroll >= SIDE_SELECT_HORIZONTAL_SCROLL_PAUSE + (text_width - max_width))
text_scroll = text_width - max_width;
else
text_scroll = text_scroll - SIDE_SELECT_HORIZONTAL_SCROLL_PAUSE;
} else {
text_scroll = 0;
}
oled_draw_text_cropped(&SIDE_SELECT_GAME_NAME_FONT, game_name,
1, line,
text_scroll, max_width,
0, 0,
0, 0);
oled_draw_image(
disk_image, OLED_WIDTH - disk_image->width - 1, line + 1,
0, 0);
oled_draw_text(&SIDE_SELECT_SIDE_NAME_FONT, "SIDE",
1, line + 12,
0, 0);
oled_draw_text(&SIDE_SELECT_SIDE_NAME_FONT, side_name,
l > 1 ? 55 : 60, line + 12,
0, 0);
}
// function to remove () and [] suffixes from text
void text_remove_brackets(char *text)
{
int shift = 0;
int pos = -1;
char last_char = ' ';
int bracket_open = 0;
while (1)
{
if (pos - shift >= 0)
last_char = text[pos - shift];
pos++;
char c = text[pos];
if (c == ' ' && last_char == ' ')
{
// remove double spaces
shift++;
continue;
}
else if (c == '[' || c == '(')
{
// open bracket
shift++;
bracket_open++;
continue;
}
else if (c == ']' || c == ')')
{
// close bracket
shift++;
if (bracket_open > 0)
bracket_open--;
continue;
} else if (bracket_open)
{
// skip text in brackets;
shift++;
continue;
}
// normal text
text[pos - shift] = text[pos];
if (!text[pos]) {
// trim end space if need
if (pos - shift - 1 >= 0 && text[pos - shift - 1] == ' ')
text[pos - shift - 1] = 0;
break;
}
}
}
void fds_side_select(char *directory, FILINFO *fno, uint8_t load_first)
{
FRESULT fr;
uint8_t side_count, side = 0;
char game_name[256];
int dl = strlen(directory);
int fl = strlen(fno->fname);
char full_path[dl + fl + 2];
int i, text_scroll = 0;
// save state if need
if (fdskey_settings.remember_last_state_mode == REMEMBER_LAST_STATE_ROM
&& fdskey_settings.last_state != LAST_STATE_ROM)
{
fdskey_settings.last_state = LAST_STATE_ROM;
settings_save();
}
strcpy(full_path, directory);
strcat(full_path, "\\");
strcat(full_path, fno->fname);
strcpy(game_name, fno->fname);
// trim extension
for (i = fl - 1; i >= 0; i--)
{
if (game_name[i] == '.')
{
game_name[i] = 0;
break;
}
}
// remove brackets
text_remove_brackets(game_name);
if (fno->fsize % FDS_ROM_SIDE_SIZE == FDS_ROM_HEADER_SIZE)
fno->fsize -= FDS_ROM_HEADER_SIZE;
if (fno->fsize % FDS_ROM_SIDE_SIZE != 0)
{
show_error_screen_fr(FDSR_INVALID_ROM, 0);
return;
}
side_count = fno->fsize / FDS_ROM_SIDE_SIZE;
if (!side_count)
{
// empty ROM
show_error_screen_fr(FDSR_INVALID_ROM, 0);
return;
}
if (side_count == 1)
{
// Single sided ROM, do not show side select dialog
fr = fds_gui_load_side(full_path, game_name, &side, side_count, fno->fattrib & AM_RDO);
show_error_screen_fr(fr, fr < 0x80);
return;
}
if (load_first)
{
// need to load first side
fr = fds_gui_load_side(full_path, game_name, 0, side_count, fno->fattrib & AM_RDO);
show_error_screen_fr(fr, fr < 0x80);
}
while (1)
{
fds_side_draw(side, side_count, game_name, text_scroll);
oled_update_invisible();
oled_switch_to_invisible();
// if (!text_scroll)
// oled_screenshot("ss_side_select.bmp");
text_scroll++;
if (button_up_newpress() && side > 0)
{
side--;
fds_side_draw(side, side_count, game_name, text_scroll);
oled_update_invisible();
for (i = 0; i < OLED_HEIGHT; i++)
{
oled_set_line(oled_get_line() - 1);
HAL_Delay(2);
}
}
if (button_down_newpress() && side + 1 < side_count)
{
side++;
fds_side_draw(side, side_count, game_name, text_scroll);
oled_update_invisible();
for (i = 0; i < OLED_HEIGHT; i++)
{
oled_set_line(oled_get_line() + 1);
HAL_Delay(2);
}
}
if (button_right_newpress())
{
fr = fds_gui_load_side(full_path, game_name, &side, side_count, fno->fattrib & AM_RDO);
show_error_screen_fr(fr, fr < 0x80);
// back to side select
fds_side_draw(side, side_count, game_name, text_scroll);
oled_update_invisible();
oled_switch_to_invisible();
}
if (button_left_newpress())
return;
button_check_screen_off();
}
}
DotMatrixImage* side_select_get_disk_image(uint8_t side, uint8_t side_count)
{
if (side_count <= 1)
return (DotMatrixImage*)&IMAGE_CARD_SINGLE;
switch (side)
{
case 0:
if (side_count <= 2)
return (DotMatrixImage*)&IMAGE_CARD_A;
else
return (DotMatrixImage*)&IMAGE_CARD_1A;
case 1:
if (side_count <= 2)
return (DotMatrixImage*)&IMAGE_CARD_B;
else
return (DotMatrixImage*)&IMAGE_CARD_1B;
case 2:
return (DotMatrixImage*)&IMAGE_CARD_2A;
case 3:
return (DotMatrixImage*)&IMAGE_CARD_2B;
case 4:
return (DotMatrixImage*)&IMAGE_CARD_3A;
case 5:
return (DotMatrixImage*)&IMAGE_CARD_3B;
case 6:
return (DotMatrixImage*)&IMAGE_CARD_4A;
case 7:
return (DotMatrixImage*)&IMAGE_CARD_4B;
default:
return (DotMatrixImage*)&IMAGE_CARD_UNKNOWN;
}
}