aboutsummaryrefslogtreecommitdiff
path: root/shell/menu
diff options
context:
space:
mode:
authorgameblabla2019-10-05 03:04:57 +0200
committergameblabla2019-10-05 03:04:57 +0200
commitd4753076e89d42cdad4a4f1ca4688fad3c56d873 (patch)
treec8641cf282f427d9329db00325e16609acca8663 /shell/menu
parent943821f94b9b2e22315fce876c2e369da7a79bcf (diff)
downloadsnesemu-d4753076e89d42cdad4a4f1ca4688fad3c56d873.tar.gz
snesemu-d4753076e89d42cdad4a4f1ca4688fad3c56d873.tar.bz2
snesemu-d4753076e89d42cdad4a4f1ca4688fad3c56d873.zip
Port the libretro core and make it standalone.
TODO : - Input should use our config file instead. - Missing audio in some games. (Star Ocean, doesn't happen with stock retroarch code. Odd...)
Diffstat (limited to 'shell/menu')
-rw-r--r--shell/menu/config.h11
-rw-r--r--shell/menu/font_drawing.c131
-rw-r--r--shell/menu/font_drawing.h13
-rw-r--r--shell/menu/font_menudata.h135
-rw-r--r--shell/menu/menu.c597
-rw-r--r--shell/menu/menu.h18
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