summaryrefslogtreecommitdiff
path: root/source/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/main.c')
-rw-r--r--source/main.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/source/main.c b/source/main.c
new file mode 100644
index 0000000..83dd070
--- /dev/null
+++ b/source/main.c
@@ -0,0 +1,350 @@
+/*
+ 3dsspec - Nintendo 3DS Spectrum emulator.
+
+ Copyright (C) 2021 Ian Cowburn <ianc@noddybox.co.uk>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 3
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>
+
+ $Id: main.c 77 2010-11-23 08:10:25Z ianc $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <3ds.h>
+
+#include "framebuffer.h"
+#include "gui.h"
+#include "keyboard.h"
+#include "z80.h"
+#include "spec.h"
+#include "config.h"
+#include "snapshot.h"
+
+#ifndef DSSPEC_VERSION
+#define DSSPEC_VERSION "DEV " __TIME__ "/" __DATE__
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define DEBUG(x) \
+ do \
+ { \
+ printf(x); \
+ gfxFlushBuffers(); \
+ gfxSwapBuffers(); \
+ } while(0); \
+ do \
+ { \
+ hidScanInput(); \
+ } while(!(hidKeysDown() & KEY_TOUCH)) \
+
+/* ---------------------------------------- STATIC DATA
+*/
+static const char *main_menu[]=
+ {
+ "Reset SPEC",
+ "Select Tape",
+ "Configure",
+ "Map Joypad to Keys",
+ "Save Memory Snapshot",
+ "Load Memory Snapshot",
+ "Save Joypad/Key State",
+ "Load Joypad/Key State",
+ "Exit 3DSSPEC",
+ "Cancel",
+ NULL
+ };
+
+typedef enum
+{
+ MenuReset,
+ MenuSelectTape,
+ MenuConfigure,
+ MenuMapJoypad,
+ MenuSaveSnapshot,
+ MenuLoadSnapshot,
+ MenuSaveMappings,
+ MenuLoadMappings,
+ MenuExit
+} MenuOpt;
+
+
+/* ---------------------------------------- DISPLAY FUNCS
+*/
+static void Splash(void)
+{
+ static char scroller[]=
+ {
+ " "
+ "Welcome to 3DSSPEC, a Sinclair Spectrum 48K emulator for the Nintendo "
+ "3DS. You can safely ignore this message. I was just bored for half "
+ "an hour. And no retro game is complete without a side-scroller... "
+ "Thanks to Slay Radio, Ladytron, the Genki Rockets, the High "
+ "Voltage SID Collection, The Prodigy, Paradise Lost and "
+ "Retro Gamer for coding fuel."
+ };
+
+ static const char *text[]=
+ {
+ "3DSSPEC \177 2021 Ian Cowburn",
+ " ",
+ "Spectrum ROM \177 1982 Amstrad",
+ " ",
+ "PRESS A TO CONTINUE",
+ " ",
+ "https://noddybox.co.uk/",
+ " ",
+ NULL
+ };
+
+ int f;
+ int y;
+ int scr_x = 0;
+ int scr_y = 240;
+ Framebuffer upper;
+ Framebuffer lower;
+
+ SPECEnableFileSystem(TRUE);
+ SNAP_Enable(TRUE);
+
+ while(!(hidKeysDown() & KEY_A))
+ {
+ FB_StartFrame(&upper, &lower);
+
+ FB_Clear(&upper, COL_BLACK);
+ FB_Clear(&lower, COL_BLACK);
+
+ FB_Blit(&upper, IMG_SPLASH, 0, scr_y);
+
+ FB_Print(&upper, "10 REM VERSION \001" DSSPEC_VERSION "\001\n"
+ "20 PRINT \"\001THE SPEC IS ACE\001\"\n"
+ "30 GOTO 20",
+ 0, 230, COL_WHITE, COL_TRANSPARENT);
+
+ FB_printf(&lower, scr_x, 8, COL_WHITE, COL_TRANSPARENT,
+ "%-42.42s",scroller);
+
+ y = lower.height - 20;
+
+ for(f=0;text[f];f++)
+ {
+ FB_Centre(&lower, text[f], y, COL_WHITE, COL_TRANSPARENT);
+ y -= 8;
+ }
+
+ FB_EndFrame();
+
+ if (scr_y > 0)
+ {
+ scr_y--;
+ }
+
+ if (--scr_x == -8)
+ {
+ size_t l = sizeof scroller;
+ char c;
+
+ scr_x = 0;
+
+ c = scroller[0];
+ memmove(scroller, scroller+1, l-2);
+ scroller[l-2] = c;
+ }
+ }
+}
+
+
+/* ---------------------------------------- JOYPAD MAPPING
+*/
+static void MapJoypad(void)
+{
+ SoftKeyEvent ev;
+ SoftKey pad = NUM_SOFT_KEYS;
+ int done = FALSE;
+ Framebuffer upper;
+ Framebuffer lower;
+
+ while(!done)
+ {
+ FB_StartFrame(&upper, &lower);
+
+ SK_DisplayKeyboard();
+
+ FB_Clear(&upper, COL_WHITE);
+
+ FB_Print(&upper, "Press the joypad button you want\n"
+ "to define and then the SPEC key\n"
+ "you want to use.\n\n"
+ "Press CONFIG to finish.",
+ 0, upper.height - 40, COL_BLACK,COL_TRANSPARENT);
+
+ if (pad != NUM_SOFT_KEYS)
+ {
+ FB_printf(&upper, 0, 80, COL_BLACK, COL_TRANSPARENT,
+ "defining\n \001%s\001",SK_KeyName(pad));
+ }
+
+ FB_EndFrame();
+
+ while(SK_GetBareEvent(&ev))
+ {
+ if (ev.pressed)
+ {
+ if (ev.key==SK_ABOUT || ev.key==SK_CONFIG)
+ {
+ done = true;
+ }
+ }
+ else
+ {
+ if (ev.key>=SK_PAD_UP && ev.key<=SK_PAD_SELECT)
+ {
+ pad = ev.key;
+ }
+
+ if (ev.key<=SK_SPACE && pad!=NUM_SOFT_KEYS)
+ {
+ SK_DefinePad(pad,ev.key);
+ pad = NUM_SOFT_KEYS;
+ }
+ }
+ }
+ }
+}
+
+
+/* ---------------------------------------- MAIN
+*/
+int main(int argc, char *argv[])
+{
+ Z80 *z80;
+ int quit = FALSE;
+
+ gfxInit(GSP_RGB565_OES, GSP_RGB565_OES, false);
+
+ FB_Init();
+
+ z80 = Z80Init(SPECReadMem,
+ SPECWriteMem,
+ SPECReadPort,
+ SPECWritePort,
+ SPECReadDisassem);
+
+ if (!z80)
+ {
+ GUI_Alert(TRUE,"Failed to initialise\nthe Z80 CPU emulation!");
+ }
+
+ SPECInit(z80);
+
+ Splash();
+
+ LoadConfig();
+ SPECReconfigure();
+
+ SK_DisplayKeyboard();
+
+ SK_SetSticky(SK_SHIFT,DSSPEC_Config[DSSPEC_STICKY_SHIFT]);
+
+ if (DSSPEC_Config[DSSPEC_LOAD_DEFAULT_SNAPSHOT])
+ {
+ SNAP_Load(z80, "AUTO", SNAP_TYPE_FULL);
+ }
+
+ while(!quit && aptMainLoop())
+ {
+ SoftKeyEvent ev;
+ Framebuffer upper;
+ Framebuffer lower;
+
+ FB_StartFrame(&upper, &lower);
+
+ SK_DisplayKeyboard();
+
+ Z80Exec(z80);
+
+ SPECRenderDisplay(&upper, z80);
+
+ FB_EndFrame();
+
+ while(SK_GetEvent(&ev))
+ {
+ switch(ev.key)
+ {
+ case SK_ABOUT:
+ case SK_CONFIG:
+ if (ev.pressed)
+ {
+ switch(GUI_Menu(main_menu))
+ {
+ case MenuReset:
+ SPECReset(z80);
+ break;
+
+ case MenuSelectTape:
+ break;
+
+ case MenuConfigure:
+ GUI_Config();
+ SK_SetSticky
+ (SK_SHIFT,
+ DSSPEC_Config[DSSPEC_STICKY_SHIFT]);
+ SPECReconfigure();
+ break;
+
+ case MenuMapJoypad:
+ MapJoypad();
+ break;
+
+ case MenuSaveSnapshot:
+ SNAP_Save(z80, SNAP_TYPE_FULL);
+ break;
+
+ case MenuLoadSnapshot:
+ SNAP_Load(z80, NULL, SNAP_TYPE_FULL);
+ break;
+
+ case MenuSaveMappings:
+ SNAP_Save(z80, SNAP_TYPE_KEYBOARD);
+ break;
+
+ case MenuLoadMappings:
+ SNAP_Load(z80, NULL, SNAP_TYPE_KEYBOARD);
+ break;
+
+ case MenuExit:
+ quit = TRUE;
+ break;
+ }
+ }
+ break;
+
+ default:
+ SPECHandleKey(ev.key,ev.pressed);
+ break;
+ }
+ }
+ }
+
+ gfxExit();
+
+ return 0;
+}