summaryrefslogtreecommitdiff
path: root/arm9/source/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/source/main.c')
-rw-r--r--arm9/source/main.c427
1 files changed, 427 insertions, 0 deletions
diff --git a/arm9/source/main.c b/arm9/source/main.c
new file mode 100644
index 0000000..b32174a
--- /dev/null
+++ b/arm9/source/main.c
@@ -0,0 +1,427 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 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 2
+ 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ $Id$
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <nds.h>
+#include <fat.h>
+
+#include "framebuffer.h"
+#include "gui.h"
+#include "keyboard.h"
+#include "z80.h"
+#include "config.h"
+#include "textmode.h"
+#include "monitor.h"
+#include "tapes.h"
+#include "spec.h"
+
+#include "splashimg_bin.h"
+
+#ifndef DS48_VERSION
+#define DS48_VERSION "DEV " __TIME__ "/" __DATE__
+#endif
+
+
+/* ---------------------------------------- STATIC DATA
+*/
+static const char *main_menu[]=
+ {
+ "Reset Spectrum",
+ "Select Tape",
+ "Configure",
+ "Map Joypad to Keys",
+ "Machine Code Monitor",
+ "Cancel",
+ NULL
+ };
+
+typedef enum
+{
+ MenuReset,
+ MenuSelectTape,
+ MenuConfigure,
+ MenuMapJoypad,
+ MenuMonitor,
+} MenuOpt;
+
+/* ---------------------------------------- IRQ FUNCS
+*/
+
+/* ---------------------------------------- DISPLAY FUNCS
+*/
+static void VBlankFunc(void)
+{
+ scanKeys();
+}
+
+static void Splash(void)
+{
+ static char scroller[]=
+ {
+ " "
+ "Welcome to DS48, a ZX Spectrum emulator for the Ninetendo DS. "
+ "You may note a cunning similarity to the ZX81 emulator, DS81, in "
+ "some of this emulator's appearance... "
+ "Any similarity is purely intentional. "
+ "Thanks, as ever, to Slay Radio for coding fuel."
+ };
+
+ static const char *text[]=
+ {
+ "DS48 \177 2006 Ian C",
+ " ",
+ "Spectrum ROM \177 Amstrad",
+ " ",
+ "Amstrad have kindly given",
+ "permission for the Spectrum",
+ "ROM to be distributed along",
+ "with emulators.",
+ " ",
+ "PRESS A TO CONTINUE",
+ " ",
+ "http://www.noddybox.co.uk/",
+ " ",
+ " ",
+ "Checking for FAT device...",
+ NULL
+ };
+
+ static const char *fat_text[]=
+ {
+ "Found a FAT device.",
+ "If you place tape files in",
+ "the top directory or /SPECGAME",
+ "then you should be able to load",
+ "with the command LOAD \"FILE\"",
+ NULL
+ };
+
+ static const char *no_fat_text[]=
+ {
+ "Sorry, but you dont have a",
+ "supported FAT device.",
+ "Only the internal tape",
+ "files can be used.",
+ NULL
+ };
+
+ sImage img;
+ int f;
+ int y;
+ int res=FALSE;
+ int scr_x=0;
+
+ SUB_BG2_XDX = 0x080;
+ SUB_BG2_YDY = 0x080;
+
+ TM_printf(0,11,"%-18.18s",scroller);
+
+ FB_Clear();
+
+ loadPCX(splashimg_bin,&img);
+
+ FB_Blit(&img,0,0,1);
+
+ y = 10;
+
+ for(f=0;text[f];f++)
+ {
+ FB_Centre(text[f],y,COL_WHITE,COL_TRANSPARENT);
+ y += 8;
+ }
+
+ y += 8;
+
+#ifndef DS48_DISABLE_FAT
+ res = fatInitDefault();
+#endif
+
+ if (res)
+ {
+ SPECEnableFileSystem(TRUE);
+
+ for(f=0;fat_text[f];f++)
+ {
+ FB_Centre(fat_text[f],y,COL_WHITE,COL_TRANSPARENT);
+ y += 8;
+ }
+ }
+ else
+ {
+ SPECEnableFileSystem(FALSE);
+
+ for(f=0;no_fat_text[f];f++)
+ {
+ FB_Centre(no_fat_text[f],y,COL_WHITE,COL_TRANSPARENT);
+ y += 8;
+ }
+ }
+
+ while(!(keysDown() & KEY_A))
+ {
+ swiWaitForVBlank();
+
+ 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;
+
+ TM_printf(0,11,"%-18.18s",scroller);
+ }
+
+ SUB_BG2_CX = scr_x << 8;
+ }
+
+ SUB_BG2_XDX = 0x100;
+ SUB_BG2_YDY = 0x100;
+ SUB_BG2_CX = 0;
+
+ TM_Cls();
+}
+
+
+/* ---------------------------------------- JOYPAD MAPPING
+*/
+static void MapJoypad(void)
+{
+#if 0
+ SoftKeyEvent ev;
+ SoftKey pad = NUM_SOFT_KEYS;
+ int done = FALSE;
+ char text[256];
+
+ SK_DisplayKeyboard();
+
+ ZX SpectrumSuspendDisplay();
+
+ ZX SpectrumDisplayString("press the joypad button you want\n"
+ "to define and then the ZX Spectrum key\n"
+ "you want to use.\n\n"
+ "press on the config banner to\n"
+ "finish.");
+
+ while(!done)
+ {
+ 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;
+
+ /* Now, just how dumb was making % the inverse on/off...
+ */
+ sprintf(text,"defining\n %%%s%%",SK_KeyName(pad));
+ ZX SpectrumDisplayString(text);
+ }
+
+ if (ev.key<=SK_SPACE && pad!=NUM_SOFT_KEYS)
+ {
+ sprintf(text,"mapped\n %%%s%%\nto\n %%%s%%",
+ SK_KeyName(pad),SK_KeyName(ev.key));
+ ZX SpectrumDisplayString(text);
+
+ SK_DefinePad(pad,ev.key);
+
+ pad = NUM_SOFT_KEYS;
+ }
+ }
+ }
+
+ swiWaitForVBlank();
+ }
+
+ ZX SpectrumResumeDisplay();
+#endif
+}
+
+
+/* ---------------------------------------- MAIN
+*/
+int main(int argc, char *argv[])
+{
+ Z80 *z80;
+
+ powerON(POWER_ALL_2D);
+
+ /* Set up main screen for ZX Spectrum.
+ */
+ videoSetMode(MODE_3_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE);
+
+ vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
+ vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
+
+ BG0_CR = BG_COLOR_256 | BG_32x32 | BG_MAP_BASE(0) |
+ BG_TILE_BASE(1) | BG_PRIORITY(0);
+ BG0_X0 = 0;
+ BG0_Y0 = 0;
+
+ BG_PALETTE[0] = RGB15(31,31,31);
+ BG_PALETTE[1] = RGB15(0,0,0);
+
+ BG3_CR = BG_BMP16_256x256 | BG_BMP_BASE(2) | BG_PRIORITY(1);
+ BG3_XDX = 0x100;
+ BG3_XDY = 0;
+ BG3_YDX = 0;
+ BG3_YDY = 0x100;
+ BG3_CX = 0;
+ BG3_CY = 0;
+
+ /* Set up the sub-screen for rotation (basically for use as a framebuffer).
+ Now overlaid with a text screen for the monitor (I thought a bitmapped
+ printing routine would needlessly slow down the monitor when watching
+ the Spectrum run). Having said the overlay is currently a rotation map
+ for some pointless frippery! Still be quicker though.
+ */
+ videoSetModeSub(MODE_4_2D | DISPLAY_BG2_ACTIVE | DISPLAY_BG3_ACTIVE);
+ vramSetBankC(VRAM_C_SUB_BG_0x06200000);
+
+ SUB_BG2_CR = BG_COLOR_256 | BG_RS_32x32 | BG_MAP_BASE(4) |
+ BG_TILE_BASE(0) | BG_PRIORITY(0);
+ SUB_BG2_XDX = 0x100;
+ SUB_BG2_XDY = 0;
+ SUB_BG2_YDX = 0;
+ SUB_BG2_YDY = 0x100;
+ SUB_BG2_CX = 0;
+ SUB_BG2_CY = 0;
+
+ SUB_BG3_CR = BG_BMP8_256x256 | BG_BMP_BASE(1) | BG_PRIORITY(1);
+ SUB_BG3_XDX = 0x100;
+ SUB_BG3_XDY = 0;
+ SUB_BG3_YDX = 0;
+ SUB_BG3_YDY = 0x100;
+ SUB_BG3_CX = 0;
+ SUB_BG3_CY = 0;
+
+ /* Tell 'framebuffer' routines to use this
+ */
+ FB_Init((uint16*)BG_BMP_RAM_SUB(1), BG_PALETTE_SUB);
+
+ /* Set up lower screen text overlay
+ */
+ FB_LoadASCIITiles((uint16*)BG_TILE_RAM_SUB(0));
+ TM_Init((uint16*)BG_MAP_RAM_SUB(4),32,32,TRUE);
+
+ /* Set up interrupts and timers
+ */
+ irqInit();
+ irqSet(IRQ_VBLANK,VBlankFunc);
+ irqEnable(IRQ_VBLANK);
+
+ /* All required stuff initialised
+ */
+ keysSetRepeat(30,15);
+
+ z80 = Z80Init(SPECPeek,
+ SPECPoke,
+ SPECReadPort,
+ SPECWritePort,
+ SPECDisPeek);
+
+ if (!z80)
+ {
+ GUI_Alert(TRUE,"Failed to initialise\nthe Z80 CPU emulation!");
+ }
+
+ SPECInit((uint16*)BG_BMP_RAM(2), z80);
+
+ Splash();
+
+ LoadConfig();
+ SPECReconfigure();
+
+ SK_DisplayKeyboard();
+
+ SK_SetSticky(SK_CAPS_SHIFT,DS48_Config[DS48_STICKY_CAPS]);
+ SK_SetSticky(SK_SYMBOL_SHIFT,DS48_Config[DS48_STICKY_SYM]);
+
+ while(1)
+ {
+ SoftKeyEvent ev;
+
+ /* Z80Exec(z80); */
+
+ 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:
+ SelectTape();
+ break;
+
+ case MenuConfigure:
+ GUI_Config();
+ SK_SetSticky(SK_CAPS_SHIFT,
+ DS48_Config[DS48_STICKY_CAPS]);
+ SK_SetSticky(SK_SYMBOL_SHIFT,
+ DS48_Config[DS48_STICKY_SYM]);
+ SPECReconfigure();
+ break;
+
+ case MenuMapJoypad:
+ MapJoypad();
+ break;
+
+ case MenuMonitor:
+ MachineCodeMonitor(z80);
+ break;
+ }
+
+ SK_DisplayKeyboard();
+ }
+ break;
+
+ default:
+ SPECHandleKey(ev.key,ev.pressed);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}