diff options
Diffstat (limited to 'shell/menu')
-rw-r--r-- | shell/menu/config.h | 11 | ||||
-rw-r--r-- | shell/menu/font_drawing.c | 131 | ||||
-rw-r--r-- | shell/menu/font_drawing.h | 13 | ||||
-rw-r--r-- | shell/menu/font_menudata.h | 135 | ||||
-rw-r--r-- | shell/menu/menu.c | 597 | ||||
-rw-r--r-- | shell/menu/menu.h | 18 |
6 files changed, 905 insertions, 0 deletions
diff --git a/shell/menu/config.h b/shell/menu/config.h new file mode 100644 index 0000000..9b71fc2 --- /dev/null +++ b/shell/menu/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_H__ +#define CONFIG_H__ + +typedef struct { + int32_t fullscreen; + /* For input remapping */ + uint32_t config_buttons[6][19]; +} t_config; +extern t_config option; + +#endif diff --git a/shell/menu/font_drawing.c b/shell/menu/font_drawing.c new file mode 100644 index 0000000..c1c97b9 --- /dev/null +++ b/shell/menu/font_drawing.c @@ -0,0 +1,131 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#include "video_blit.h" +#include "font_drawing.h" +#include "font_menudata.h" + +extern int32_t screen_width; +//#define setPixel(buffer, x,y,c) + +static inline void setPixel(uint16_t* restrict buffer, uint32_t x, uint32_t y, uint16_t c) +{ + if (x < HOST_WIDTH_RESOLUTION && y < HOST_HEIGHT_RESOLUTION) + { + *((uint16_t* restrict)buffer + ((x) + (y) * HOST_WIDTH_RESOLUTION)) = c; + } +} + +static int32_t isOutlinePixel(uint8_t* charfont, uint32_t x, uint32_t y) +{ + uint32_t xis0 = !x, xis7 = x == 7, yis0 = !y, yis7 = y == 7; + + if(xis0) + { + if (yis0) + { + return !(*charfont & 0x80) && ((*charfont & 0x40) || (charfont[1] & 0x80) || (charfont[1] & 0x40)); + } + else if (yis7) + { + return !(charfont[7] & 0x80) && ((charfont[7] & 0x40) || (charfont[6] & 0x80) || (charfont[6] & 0x40)); + } + else + { + return !(charfont[y] & 0x80) && ( + (charfont[y - 1] & 0x80) || (charfont[y - 1] & 0x40) || + (charfont[y] & 0x40) || + (charfont[y + 1] & 0x80) || (charfont[y + 1] & 0x40)); + } + } + else if (xis7) + { + if (yis0) + { + return !(*charfont & 0x01) && ((*charfont & 0x02) || (charfont[1] & 0x01) || (charfont[1] & 0x02)); + } + else if (yis7) + { + return !(charfont[7] & 0x01) && ((charfont[7] & 0x02) || (charfont[6] & 0x01) || (charfont[6] & 0x02)); + } + else + { + return !(charfont[y] & 0x01) && ( + (charfont[y - 1] & 0x01) || (charfont[y - 1] & 0x02) || + (charfont[y] & 0x02) || + (charfont[y + 1] & 0x01) || (charfont[y + 1] & 0x02)); + } + } + else + { + uint32_t b = 1 << (7 - x); + if (yis0) + { + return !(*charfont & b) && ( + (*charfont & (b << 1)) || (*charfont & (b >> 1)) || + (charfont[1] & (b << 1)) || (charfont[1] & b) || (charfont[1] & (b >> 1))); + } + else if (yis7) + { + return !(charfont[7] & b) && ( + (charfont[7] & (b << 1)) || (charfont[7] & (b >> 1)) || + (charfont[6] & (b << 1)) || (charfont[6] & b) || (charfont[6] & (b >> 1))); + } + else + { + return !(charfont[y] & b) && ( + (charfont[y] & (b << 1)) || (charfont[y] & (b >> 1)) || + (charfont[y - 1] & (b << 1)) || (charfont[y - 1] & b) || (charfont[y - 1] & (b >> 1)) || + (charfont[y + 1] & (b << 1)) || (charfont[y + 1] & b) || (charfont[y + 1] & (b >> 1))); + } + } +} + +static void drawChar(uint16_t* restrict buffer, uint32_t *x, uint32_t *y, uint32_t margin, char ch, uint16_t fc, uint16_t olc) +{ + uint32_t i, j; + uint8_t *charSprite; + if (ch == '\n') + { + *x = margin; + *y += 8; + } + else if(*y < (HOST_HEIGHT_RESOLUTION-1)) + { + charSprite = ch * 8 + n2DLib_font; + // Draw charSprite as monochrome 8*8 image using given color + for(i = 0; i < 8; i++) + { + for(j = 7; j; j--) + { + if((charSprite[i] >> j) & 1) + { + setPixel(buffer, *x + (7 - j), *y + i, fc); + } + else if(isOutlinePixel(charSprite, 7 - j, i)) + { + setPixel(buffer, *x + (7 - j), *y + i, olc); + } + } + } + *x += 8; + } +} + +static void drawString(uint16_t* restrict buffer, uint32_t *x, uint32_t *y, uint32_t _x, const char *str, uint16_t fc, uint16_t olc) +{ + uint32_t i; + size_t size_font; + + size_font = strnlen(str, (HOST_WIDTH_RESOLUTION/8)) + 1; + for(i = 0; i < size_font; i++) + drawChar(buffer, x, y, _x, str[i], fc, olc); +} + +void print_string(const char *s, const uint16_t fg_color, const uint16_t bg_color, uint32_t x, uint32_t y, uint16_t* restrict buffer) +{ + if (!s) return; + + drawString(buffer, &x, &y, 0, s, fg_color, bg_color); +} diff --git a/shell/menu/font_drawing.h b/shell/menu/font_drawing.h new file mode 100644 index 0000000..e18ea04 --- /dev/null +++ b/shell/menu/font_drawing.h @@ -0,0 +1,13 @@ +#ifndef FONT_DRAWING_H +#define FONT_DRAWING_H + +#include <stdint.h> +#include <string.h> + +#define TextWhite 65535 +#define TextRed ((255>>3)<<11) + ((0>>2)<<5) + (0>>3) +#define TextBlue ((0>>3)<<11) + ((0>>2)<<5) + (255>>3) + +void print_string(const char *s, const uint16_t fg_color, const uint16_t bg_color, uint32_t x, uint32_t y, uint16_t* restrict buffer); + +#endif diff --git a/shell/menu/font_menudata.h b/shell/menu/font_menudata.h new file mode 100644 index 0000000..f5a8cbc --- /dev/null +++ b/shell/menu/font_menudata.h @@ -0,0 +1,135 @@ +#ifndef n2DLIB_FONT
+#define n2DLIB_FONT
+
+static uint8_t n2DLib_font[] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 000 (.) */
+ 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, /* Char 001 (.) */
+ 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, /* Char 002 (.) */
+ 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, /* Char 003 (.) */
+ 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, /* Char 004 (.) */
+ 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x7C, 0x38, 0x7C, /* Char 005 (.) */
+ 0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, /* Char 006 (.) */
+ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, /* Char 007 (.) */
+ 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, /* Char 008 (.) */
+ 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, /* Char 009 (.) */
+ 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, /* Char 010 (.) */
+ 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, /* Char 011 (.) */
+ 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, /* Char 012 (.) */
+ 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, /* Char 013 (.) */
+ 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, /* Char 014 (.) */
+ 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, /* Char 015 (.) */
+ 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, /* Char 016 (.) */
+ 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, /* Char 017 (.) */
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, /* Char 018 (.) */
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, /* Char 019 (.) */
+ 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, /* Char 020 (.) */
+ 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0xCC, 0x78, /* Char 021 (.) */
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, /* Char 022 (.) */
+ 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, /* Char 023 (.) */
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, /* Char 024 (.) */
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, /* Char 025 (.) */
+ 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, /* Char 026 (<=)*/
+ 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, /* Char 027 (.) */
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, /* Char 028 (.) */
+ 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, /* Char 029 (.) */
+ 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, /* Char 030 (.) */
+ 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, /* Char 031 (.) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 032 ( ) */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x00, /* Char 033 (!) */
+ 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 034 (") */
+ 0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00, /* Char 035 (#) */
+ 0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00, /* Char 036 ($) */
+ 0xC8, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x98, 0x00, /* Char 037 (%) */
+ 0x70, 0x88, 0x50, 0x20, 0x54, 0x88, 0x74, 0x00, /* Char 038 (&) */
+ 0x60, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 039 (') */
+ 0x20, 0x40, 0x80, 0x80, 0x80, 0x40, 0x20, 0x00, /* Char 040 (() */
+ 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, /* Char 041 () */
+ 0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00, /* Char 042 (*) */
+ 0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, /* Char 043 (+) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x40, /* Char 044 (,) */
+ 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, /* Char 045 (-) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, /* Char 046 (.) */
+ 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, /* Char 047 (/) */
+ 0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70, 0x00, /* Char 048 (0) */
+ 0x40, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, /* Char 049 (1) */
+ 0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8, 0x00, /* Char 050 (2) */
+ 0x70, 0x88, 0x08, 0x10, 0x08, 0x88, 0x70, 0x00, /* Char 051 (3) */
+ 0x08, 0x18, 0x28, 0x48, 0xFC, 0x08, 0x08, 0x00, /* Char 052 (4) */
+ 0xF8, 0x80, 0x80, 0xF0, 0x08, 0x88, 0x70, 0x00, /* Char 053 (5) */
+ 0x20, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00, /* Char 054 (6) */
+ 0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40, 0x00, /* Char 055 (7) */
+ 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, /* Char 056 (8) */
+ 0x70, 0x88, 0x88, 0x78, 0x08, 0x08, 0x70, 0x00, /* Char 057 (9) */
+ 0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, /* Char 058 (:) */
+ 0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x20, /* Char 059 (;) */
+ 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x00, /* Char 060 (<) */
+ 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, /* Char 061 (=) */
+ 0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80, 0x00, /* Char 062 (>) */
+ 0x78, 0x84, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, /* Char 063 (?) */
+ 0x70, 0x88, 0x88, 0xA8, 0xB8, 0x80, 0x78, 0x00, /* Char 064 (@) */
+ 0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, /* Char 065 (A) */
+ 0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00, /* Char 066 (B) */
+ 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, /* Char 067 (C) */
+ 0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x00, /* Char 068 (D) */
+ 0xF8, 0x80, 0x80, 0xE0, 0x80, 0x80, 0xF8, 0x00, /* Char 069 (E) */
+ 0xF8, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x80, 0x00, /* Char 070 (F) */
+ 0x70, 0x88, 0x80, 0x80, 0x98, 0x88, 0x78, 0x00, /* Char 071 (G) */
+ 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00, /* Char 072 (H) */
+ 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, /* Char 073 (I) */
+ 0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, /* Char 074 (J) */
+ 0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00, /* Char 075 (K) */
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00, /* Char 076 (L) */
+ 0x82, 0xC6, 0xAA, 0x92, 0x82, 0x82, 0x82, 0x00, /* Char 077 (M) */
+ 0x84, 0xC4, 0xA4, 0x94, 0x8C, 0x84, 0x84, 0x00, /* Char 078 (N) */
+ 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, /* Char 079 (O) */
+ 0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00, /* Char 080 (P) */
+ 0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00, /* Char 081 (Q) */
+ 0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00, /* Char 082 (R) */
+ 0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, /* Char 083 (S) */
+ 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, /* Char 084 (T) */
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, /* Char 085 (U) */
+ 0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x20, 0x00, /* Char 086 (V) */
+ 0x82, 0x82, 0x82, 0x82, 0x92, 0x92, 0x6C, 0x00, /* Char 087 (W) */
+ 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, /* Char 088 (X) */
+ 0x88, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00, /* Char 089 (Y) */
+ 0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, /* Char 090 (Z) */
+ 0xE0, 0x80, 0x80, 0x80, 0x80, 0x80, 0xE0, 0x00, /* Char 091 ([) */
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, /* Char 092 (\) */
+ 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x00, /* Char 093 (]) */
+ 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 094 (^) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, /* Char 095 (_) */
+ 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 096 (`) */
+ 0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x74, 0x00, /* Char 097 (a) */
+ 0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00, /* Char 098 (b) */
+ 0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00, /* Char 099 (c) */
+ 0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00, /* Char 100 (d) */
+ 0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, /* Char 101 (e) */
+ 0x30, 0x48, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x00, /* Char 102 (f) */
+ 0x00, 0x00, 0x34, 0x48, 0x48, 0x38, 0x08, 0x30, /* Char 103 (g) */
+ 0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, /* Char 104 (h) */
+ 0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, /* Char 105 (i) */
+ 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x90, 0x60, /* Char 106 (j) */
+ 0x80, 0x80, 0x88, 0x90, 0xA0, 0xD0, 0x88, 0x00, /* Char 107 (k) */
+ 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, /* Char 108 (l) */
+ 0x00, 0x00, 0xEC, 0x92, 0x92, 0x92, 0x92, 0x00, /* Char 109 (m) */
+ 0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, /* Char 110 (n) */
+ 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, /* Char 111 (o) */
+ 0x00, 0x00, 0xB0, 0xC8, 0xC8, 0xB0, 0x80, 0x80, /* Char 112 (p) */
+ 0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x08, /* Char 113 (q) */
+ 0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00, /* Char 114 (r) */
+ 0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00, /* Char 115 (s) */
+ 0x40, 0x40, 0xE0, 0x40, 0x40, 0x50, 0x20, 0x00, /* Char 116 (t) */
+ 0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, /* Char 117 (u) */
+ 0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00, /* Char 118 (v) */
+ 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x6C, 0x00, /* Char 119 (w) */
+ 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, /* Char 120 (x) */
+ 0x00, 0x00, 0x88, 0x88, 0x98, 0x68, 0x08, 0x70, /* Char 121 (y) */
+ 0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00, /* Char 122 (z) */
+ 0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00, /* Char 123 ({) */
+ 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, /* Char 124 (|) */
+ 0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40, 0x00, /* Char 125 (}) */
+ 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 126 (~) */
+ 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00 /* Char 127 (.) */
+};
+#endif
diff --git a/shell/menu/menu.c b/shell/menu/menu.c new file mode 100644 index 0000000..70096bf --- /dev/null +++ b/shell/menu/menu.c @@ -0,0 +1,597 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <libgen.h> +#include <errno.h> +#include <sys/stat.h> +#include <unistd.h> +#include <time.h> +#include <SDL/SDL.h> + +#include "scaler.h" +#include "font_drawing.h" +#include "sound_output.h" +#include "video_blit.h" +#include "config.h" +#include "menu.h" + +t_config option; +uint32_t emulator_state = 0; + +extern uint8_t exit_snes; + +static char home_path[256], save_path[256], sram_path[256], conf_path[256], rtc_path[256]; +static uint32_t controls_chosen = 0; + +extern SDL_Surface *sdl_screen; +extern char GameName_emu[512]; + +extern void SRAM_file(char* path, uint_fast8_t state); +extern void RTC_Save(char* path, uint_fast8_t state); +extern void SaveState(char* path, uint_fast8_t state); +extern void SRAM_Save(char* path, uint_fast8_t state); + +static uint8_t selectpressed = 0; +static uint8_t save_slot = 0; +static const int8_t upscalers_available = 2 +#ifdef SCALE2X_UPSCALER ++1 +#endif +; + +static void SaveState_Menu(uint_fast8_t load_mode, uint_fast8_t slot) +{ + char tmp[512]; + snprintf(tmp, sizeof(tmp), "%s/%s_%d.sts", save_path, GameName_emu, slot); + SaveState(tmp,load_mode); +} + +static void SRAM_Menu(uint_fast8_t load_mode) +{ + char tmp[512]; + snprintf(tmp, sizeof(tmp), "%s/%s.srm", sram_path, GameName_emu); + SRAM_Save(tmp,load_mode); +} + +static void RTC_Menu(uint_fast8_t load_mode) +{ + char tmp[512]; + snprintf(tmp, sizeof(tmp), "%s/%s.rtc", rtc_path, GameName_emu); + RTC_Save(tmp,load_mode); +} + +static void config_load() +{ + uint_fast8_t i; + char config_path[512]; + FILE* fp; + snprintf(config_path, sizeof(config_path), "%s/%s.cfg", conf_path, GameName_emu); + + fp = fopen(config_path, "rb"); + if (fp) + { + fread(&option, sizeof(option), sizeof(int8_t), fp); + fclose(fp); + } + else + { + /* Default mapping for Horizontal */ + option.config_buttons[0][0] = 273; + option.config_buttons[0][1] = 275; + option.config_buttons[0][2] = 274; + option.config_buttons[0][3] = 276; + + option.config_buttons[0][4] = 306; + option.config_buttons[0][5] = 308; + option.config_buttons[0][6] = 304; + option.config_buttons[0][7] = 32; + + option.config_buttons[0][8] = 9; + option.config_buttons[0][9] = 8; + + option.config_buttons[0][10] = 13; + option.config_buttons[0][11] = 27; + + option.fullscreen = 1; + } +} + +static void config_save() +{ + FILE* fp; + char config_path[512]; + snprintf(config_path, sizeof(config_path), "%s/%s.cfg", conf_path, GameName_emu); + + fp = fopen(config_path, "wb"); + if (fp) + { + fwrite(&option, sizeof(option), sizeof(int8_t), fp); + fclose(fp); + } +} + +static const char* Return_Text_Button(uint32_t button) +{ + switch(button) + { + /* UP button */ + case 273: + return "DPAD UP"; + break; + /* DOWN button */ + case 274: + return "DPAD DOWN"; + break; + /* LEFT button */ + case 276: + return "DPAD LEFT"; + break; + /* RIGHT button */ + case 275: + return "DPAD RIGHT"; + break; + /* A button */ + case 306: + return "A button"; + break; + /* B button */ + case 308: + return "B button"; + break; + /* X button */ + case 304: + return "X button"; + break; + /* Y button */ + case 32: + return "Y button"; + break; + /* L button */ + case 9: + return "L button"; + break; + /* R button */ + case 8: + return "R button"; + break; + /* Power button */ + case 279: + return "L2 button"; + break; + /* Brightness */ + case 51: + return "R2 button"; + break; + /* Volume - */ + case 38: + return "Volume -"; + break; + /* Volume + */ + case 233: + return "Volume +"; + break; + /* Start */ + case 13: + return "Start button"; + break; + /* Select */ + case 1: + return "Select button"; + break; + default: + return "Unknown key"; + break; + case 0: + return "..."; + break; + } +} + +static void Input_Remapping() +{ + SDL_Event Event; + char text[50]; + uint32_t pressed = 0; + int32_t currentselection = 1; + int32_t exit_input = 0; + uint32_t exit_map = 0; + + while(!exit_input) + { + pressed = 0; + SDL_FillRect( backbuffer, NULL, 0 ); + + while (SDL_PollEvent(&Event)) + { + if (Event.type == SDL_KEYDOWN) + { + switch(Event.key.keysym.sym) + { + case SDLK_UP: + currentselection--; + if (currentselection < 1) + { + if (currentselection > 9) currentselection = 12; + else currentselection = 9; + } + break; + case SDLK_DOWN: + currentselection++; + if (currentselection == 10) + { + currentselection = 1; + } + break; + case SDLK_LCTRL: + case SDLK_RETURN: + pressed = 1; + break; + case SDLK_ESCAPE: + option.config_buttons[controls_chosen][currentselection - 1] = 0; + break; + case SDLK_LALT: + exit_input = 1; + break; + case SDLK_LEFT: + if (currentselection > 9) currentselection -= 9; + break; + case SDLK_RIGHT: + if (currentselection < 10) currentselection += 9; + break; + case SDLK_BACKSPACE: + controls_chosen = 1; + break; + case SDLK_TAB: + controls_chosen = 0; + break; + default: + break; + } + } + } + + if (pressed) + { + SDL_Delay(1); + switch(currentselection) + { + default: + exit_map = 0; + while( !exit_map ) + { + SDL_FillRect( backbuffer, NULL, 0 ); + print_string("Please press button for mapping", TextWhite, TextBlue, 37, 108, backbuffer->pixels); + bitmap_scale(0,0,320,240,sdl_screen->w,sdl_screen->h,320,0,(uint16_t* restrict)backbuffer->pixels,(uint16_t* restrict)sdl_screen->pixels); + + while (SDL_PollEvent(&Event)) + { + if (Event.type == SDL_KEYDOWN) + { + if (Event.key.keysym.sym != SDLK_RCTRL) + { + option.config_buttons[controls_chosen][currentselection - 1] = Event.key.keysym.sym; + exit_map = 1; + } + } + } + SDL_Flip(sdl_screen); + } + break; + } + } + + if (currentselection > 12) currentselection = 12; + + if (controls_chosen == 0) print_string("Player 1", TextWhite, 0, 100, 10, backbuffer->pixels); + else print_string("Player 2", TextWhite, 0, 100, 10, backbuffer->pixels); + + print_string("Press [A] to map to a button", TextWhite, TextBlue, 50, 210, backbuffer->pixels); + print_string("Press [B] to Exit", TextWhite, TextBlue, 85, 225, backbuffer->pixels); + + snprintf(text, sizeof(text), "UP : %d\n", (option.config_buttons[controls_chosen][0])); + if (currentselection == 1) print_string(text, TextRed, 0, 5, 25+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 25+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "DOWN : %d\n", (option.config_buttons[controls_chosen][1])); + if (currentselection == 2) print_string(text, TextRed, 0, 5, 45+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 45+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "LEFT : %d\n", (option.config_buttons[controls_chosen][2])); + if (currentselection == 3) print_string(text, TextRed, 0, 5, 65+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 65+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "RIGHT : %d\n", (option.config_buttons[controls_chosen][3])); + if (currentselection == 4) print_string(text, TextRed, 0, 5, 85+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 85+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "A : %d\n", (option.config_buttons[controls_chosen][4])); + if (currentselection == 5) print_string(text, TextRed, 0, 5, 105+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 105+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "B : %d\n", (option.config_buttons[controls_chosen][5])); + if (currentselection == 6) print_string(text, TextRed, 0, 5, 125+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 125+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "X : %d\n", (option.config_buttons[controls_chosen][6])); + if (currentselection == 7) print_string(text, TextRed, 0, 5, 145+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 145+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "Y : %d\n", (option.config_buttons[controls_chosen][7])); + if (currentselection == 8) print_string(text, TextRed, 0, 5, 165+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 165+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "L : %d\n", (option.config_buttons[controls_chosen][8])); + if (currentselection == 9) print_string(text, TextRed, 0, 5, 185+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 185+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "R : %d\n", (option.config_buttons[controls_chosen][9])); + if (currentselection == 10) print_string(text, TextRed, 0, 165, 25+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 165, 25+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "START : %d\n", (option.config_buttons[controls_chosen][10])); + if (currentselection == 11) print_string(text, TextRed, 0, 165, 45+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 165, 45+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "SELECT : %d\n", (option.config_buttons[controls_chosen][11])); + if (currentselection == 12) print_string(text, TextRed, 0, 165, 65+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 165, 65+2, backbuffer->pixels); + + bitmap_scale(0,0,320,240,sdl_screen->w,sdl_screen->h,320,0,(uint16_t* restrict)backbuffer->pixels,(uint16_t* restrict)sdl_screen->pixels); + SDL_Flip(sdl_screen); + } + + config_save(); +} + +void Menu() +{ + char text[50]; + int16_t pressed = 0; + int16_t currentselection = 1; + SDL_Rect dstRect; + SDL_Event Event; + + Set_Video_Menu(); + + /* Save sram settings each time we bring up the menu */ + SRAM_Menu(0); + RTC_Menu(0); + + while (((currentselection != 1) && (currentselection != 6)) || (!pressed)) + { + pressed = 0; + + SDL_FillRect( backbuffer, NULL, 0 ); + + print_string("SNESEmu - Built on " __DATE__, TextWhite, 0, 5, 15, backbuffer->pixels); + + if (currentselection == 1) print_string("Continue", TextRed, 0, 5, 45, backbuffer->pixels); + else print_string("Continue", TextWhite, 0, 5, 45, backbuffer->pixels); + + snprintf(text, sizeof(text), "Load State %d", save_slot); + + if (currentselection == 2) print_string(text, TextRed, 0, 5, 65, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 65, backbuffer->pixels); + + snprintf(text, sizeof(text), "Save State %d", save_slot); + + if (currentselection == 3) print_string(text, TextRed, 0, 5, 85, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 85, backbuffer->pixels); + + if (currentselection == 4) + { + switch(option.fullscreen) + { + case 0: + print_string("Scaling : Native", TextRed, 0, 5, 105, backbuffer->pixels); + break; + case 1: + print_string("Scaling : Stretched", TextRed, 0, 5, 105, backbuffer->pixels); + break; + case 2: + print_string("Scaling : Bilinear", TextRed, 0, 5, 105, backbuffer->pixels); + break; + case 3: + print_string("Scaling : EPX/Scale2x", TextRed, 0, 5, 105, backbuffer->pixels); + break; + } + } + else + { + switch(option.fullscreen) + { + case 0: + print_string("Scaling : Native", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + case 1: + print_string("Scaling : Stretched", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + case 2: + print_string("Scaling : Bilinear", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + case 3: + print_string("Scaling : EPX/Scale2x", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + } + } + + if (currentselection == 5) print_string("Input remapping", TextRed, 0, 5, 125, backbuffer->pixels); + else print_string("Input remapping", TextWhite, 0, 5, 125, backbuffer->pixels); + + if (currentselection == 6) print_string("Quit", TextRed, 0, 5, 145, backbuffer->pixels); + else print_string("Quit", TextWhite, 0, 5, 145, backbuffer->pixels); + + print_string("Libretro Fork by gameblabla", TextWhite, 0, 5, 205, backbuffer->pixels); + print_string("Credits: Snes9x dev team, libretro", TextWhite, 0, 5, 225, backbuffer->pixels); + + while (SDL_PollEvent(&Event)) + { + if (Event.type == SDL_KEYDOWN) + { + switch(Event.key.keysym.sym) + { + case SDLK_UP: + currentselection--; + if (currentselection == 0) + currentselection = 6; + break; + case SDLK_DOWN: + currentselection++; + if (currentselection == 7) + currentselection = 1; + break; + case SDLK_END: + case SDLK_RCTRL: + case SDLK_LALT: + pressed = 1; + currentselection = 1; + break; + case SDLK_LCTRL: + case SDLK_RETURN: + pressed = 1; + break; + case SDLK_LEFT: + switch(currentselection) + { + case 2: + case 3: + if (save_slot > 0) save_slot--; + break; + case 4: + option.fullscreen--; + if (option.fullscreen < 0) + option.fullscreen = upscalers_available; + break; + } + break; + case SDLK_RIGHT: + switch(currentselection) + { + case 2: + case 3: + save_slot++; + if (save_slot == 10) + save_slot = 9; + break; + case 4: + option.fullscreen++; + if (option.fullscreen > upscalers_available) + option.fullscreen = 0; + break; + } + break; + default: + break; + } + } + else if (Event.type == SDL_QUIT) + { + currentselection = 6; + pressed = 1; + } + } + + if (pressed) + { + switch(currentselection) + { + case 5: + Input_Remapping(); + break; + case 4 : + option.fullscreen++; + if (option.fullscreen > upscalers_available) + option.fullscreen = 0; + break; + case 2 : + SaveState_Menu(1, save_slot); + currentselection = 1; + break; + case 3 : + SaveState_Menu(0, save_slot); + currentselection = 1; + break; + default: + break; + } + } + + bitmap_scale(0,0,320,240,sdl_screen->w,sdl_screen->h,320,0,(uint16_t* restrict)backbuffer->pixels,(uint16_t* restrict)sdl_screen->pixels); + SDL_Flip(sdl_screen); + } + + SDL_FillRect(sdl_screen, NULL, 0); + SDL_Flip(sdl_screen); + #ifdef SDL_TRIPLEBUF + SDL_FillRect(sdl_screen, NULL, 0); + SDL_Flip(sdl_screen); + #endif + + if (currentselection == 6) + { + exit_snes = 1; + } + + /* Switch back to emulator core */ + emulator_state = 0; + Set_Video_InGame(); +} + +static void Cleanup(void) +{ +#ifdef SCALE2X_UPSCALER + if (scale2x_buf) SDL_FreeSurface(scale2x_buf); +#endif + if (sdl_screen) SDL_FreeSurface(sdl_screen); + if (backbuffer) SDL_FreeSurface(backbuffer); + + // Deinitialize audio and video output + Audio_Close(); + + SDL_Quit(); +} + +void Init_Configuration() +{ + snprintf(home_path, sizeof(home_path), "%s/.snesemu", getenv("HOME")); + + snprintf(conf_path, sizeof(conf_path), "%s/conf", home_path); + snprintf(save_path, sizeof(save_path), "%s/sstates", home_path); + snprintf(sram_path, sizeof(sram_path), "%s/sram", home_path); + snprintf(rtc_path, sizeof(sram_path), "%s/rtc", home_path); + + /* We check first if folder does not exist. + * Let's only try to create it if so in order to decrease boot times. + * */ + + if (access( home_path, F_OK ) == -1) + { + mkdir(home_path, 0755); + } + + if (access( save_path, F_OK ) == -1) + { + mkdir(save_path, 0755); + } + + if (access( conf_path, F_OK ) == -1) + { + mkdir(conf_path, 0755); + } + + if (access( sram_path, F_OK ) == -1) + { + mkdir(sram_path, 0755); + } + + if (access( rtc_path, F_OK ) == -1) + { + mkdir(rtc_path, 0755); + } + + /* Load sram file if it exists */ + SRAM_Menu(1); + RTC_Menu(1); + + config_load(); +} diff --git a/shell/menu/menu.h b/shell/menu/menu.h new file mode 100644 index 0000000..8b81ac3 --- /dev/null +++ b/shell/menu/menu.h @@ -0,0 +1,18 @@ +#ifndef MENU_H +#define MENU_H + +#include <stdint.h> + +#ifndef PATH_MAX +#define PATH_MAX 2048 +#endif + +#define RGB565(r,g,b) ((r << 8) | (g << 3) | (b >> 3)) + +extern uint32_t emulator_state; +extern uint32_t done; + +extern void Menu(void); +extern void Init_Configuration(void); + +#endif |