diff options
author | Ian C <ianc@noddybox.co.uk> | 2010-11-26 15:00:08 +0000 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2010-11-26 15:00:08 +0000 |
commit | 5601353fc9cd66dbcca4d06fc7068af853317442 (patch) | |
tree | 88a85955b3fce3c4b23dbbeca623020328fb50e7 /source/main.c | |
parent | 1007ee9a4027826cf9c9067e0f1d1e1be1123b1f (diff) |
Diffstat (limited to 'source/main.c')
-rw-r--r-- | source/main.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..349e49e --- /dev/null +++ b/source/main.c @@ -0,0 +1,461 @@ +/* + ds81 - Nintendo DS ZX81 emulator. + + Copyright (C) 2006 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: main.c 77 2010-11-23 08:10:25Z ianc $ +*/ + +#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 "zx81.h" +#include "tapes.h" +#include "config.h" +#include "textmode.h" +#include "monitor.h" +#include "snapshot.h" + +#include "splashimg_bin.h" +#include "rom_font_bin.h" + +#include "ds81_debug.h" + +#ifndef DS81_VERSION +#define DS81_VERSION "DEV " __TIME__ "/" __DATE__ +#endif + + +/* ---------------------------------------- STATIC DATA +*/ +static const char *main_menu[]= + { + "Reset ZX81", + "Select Tape", + "Configure", + "Map Joypad to Keys", + "Machine Code Monitor", +#ifndef DS81_DISABLE_FAT + "Save Memory Snapshot", + "Load Memory Snapshot", + "Save Joypad/Key State", + "Load Joypad/Key State", +#endif + "Cancel", + NULL + }; + +typedef enum +{ + MenuReset, + MenuSelectTape, + MenuConfigure, + MenuMapJoypad, + MenuMonitor, +#ifndef DS81_DISABLE_FAT + MenuSaveSnapshot, + MenuLoadSnapshot, + MenuSaveMappings, + MenuLoadMappings +#endif +} MenuOpt; + + +/* Backgrounds +*/ +static int main_bitmap_bg; +static int main_text_overlay_bg; +static int sub_bitmap_bg; +static int sub_text_overlay_bg; + +/* ---------------------------------------- IRQ FUNCS +*/ + +/* ---------------------------------------- DISPLAY FUNCS +*/ +static void VBlankFunc(void) +{ + scanKeys(); +} + +static void Splash(void) +{ + static char scroller[]= + { + " " + "Welcome to DS81, a ZX81 emulator for the Ninetendo DS. " + "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 and Retro Gamer for coding fuel." + }; + + static const char *text[]= + { + "DS81 \177 2006 Ian C", + " ", + "ZX81 ROM \177 1981", + "Nine Tiles Networks LTD", + " ", + "PRESS A TO CONTINUE", + " ", + "http://www.noddybox.co.uk/", + " ", + " ", + " ", + " ", + "Checking for FAT device...", + NULL + }; + + sImage img; + int f; + int y; + int res=FALSE; + int scr_x=0; + + ZX81SuspendDisplay(); + ZX81DisplayString("10 rem " DS81_VERSION "\n" + "20 print \"%the zx81 is ace%\"\n" + "30 goto 20"); + + bgSetScale(sub_text_overlay_bg, 0x80, 0x80); + + 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 DS81_DISABLE_FAT + res = fatInitDefault(); +#endif + + if (res) + { + ZX81EnableFileSystem(TRUE); + SNAP_Enable(TRUE); + + FB_Centre("Found a FAT device.",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("If you place .P tape files in",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("the top directory or ZX81SNAP",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("then you should be able to load",y, + COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("GAME.P with the command",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("LOAD \"GAME\"",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + } + else + { + ZX81EnableFileSystem(FALSE); + SNAP_Enable(FALSE); + + FB_Centre("Sorry, but you don't have a",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("supported FAT device.",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("Only the internal tape",y,COL_WHITE,COL_TRANSPARENT); + y += 8; + + FB_Centre("files can be used.",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); + } + + bgSetScroll(sub_text_overlay_bg, scr_x << 8, 0); + bgUpdate(); + } + + bgSetScale(sub_text_overlay_bg, 0x100, 0x100); + bgSetScroll(sub_text_overlay_bg, 0, 0); + bgUpdate(); + + TM_Cls(); + + ZX81ResumeDisplay(); +} + + +/* ---------------------------------------- JOYPAD MAPPING +*/ +static void MapJoypad(void) +{ + SoftKeyEvent ev; + SoftKey pad = NUM_SOFT_KEYS; + int done = FALSE; + char text[256]; + + SK_DisplayKeyboard(); + + ZX81SuspendDisplay(); + + ZX81DisplayString("press the joypad button you want\n" + "to define and then the ZX81 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)); + ZX81DisplayString(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)); + ZX81DisplayString(text); + + SK_DefinePad(pad,ev.key); + + pad = NUM_SOFT_KEYS; + } + } + } + + swiWaitForVBlank(); + } + + ZX81ResumeDisplay(); +} + + +/* ---------------------------------------- MAIN +*/ +int main(int argc, char *argv[]) +{ + Z80 *z80; + + powerOn(POWER_ALL_2D); + + /* Set up main screen for ZX81 and load the ROM character data + */ + videoSetMode(MODE_3_2D); + + vramSetBankA(VRAM_A_MAIN_BG_0x06000000); + vramSetBankB(VRAM_B_MAIN_BG_0x06020000); + + main_bitmap_bg = bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 2, 0); + main_text_overlay_bg = bgInit(0, BgType_Text8bpp, BgSize_T_256x256, 0, 1); + + bgSetPriority(main_bitmap_bg, 1); + bgSetPriority(main_text_overlay_bg, 0); + + BG_PALETTE[0] = RGB15(31,31,31); + BG_PALETTE[1] = RGB15(0,0,0); + + dmaCopy(rom_font_bin,(void *)BG_TILE_RAM(1),rom_font_bin_size); + + /* 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 ZX81 run). Having said the overlay is currently a rotation map + for some pointless frippery! Still be quicker though. + */ + videoSetModeSub(MODE_4_2D); + + vramSetBankC(VRAM_C_SUB_BG_0x06200000); + + sub_bitmap_bg = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0); + sub_text_overlay_bg = bgInitSub(2, BgType_Rotation, BgSize_R_256x256, 4, 0); + + bgSetPriority(sub_bitmap_bg, 1); + bgSetPriority(sub_text_overlay_bg, 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(ZX81ReadMem, + ZX81WriteMem, + ZX81ReadPort, + ZX81WritePort, + ZX81ReadDisassem); + + if (!z80) + { + GUI_Alert(TRUE,"Failed to initialise\nthe Z80 CPU emulation!"); + } + + ZX81Init((uint16*)BG_MAP_RAM(0), (uint16*)BG_BMP_RAM(2), z80); + + Splash(); + + LoadConfig(); + ZX81Reconfigure(); + + SK_DisplayKeyboard(); + + SK_SetSticky(SK_SHIFT,DS81_Config[DS81_STICKY_SHIFT]); + + if (DS81_Config[DS81_LOAD_DEFAULT_SNAPSHOT]) + { + SNAP_Load(z80, "AUTO", SNAP_TYPE_FULL); + } + + 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: + ZX81Reset(z80); + break; + + case MenuSelectTape: + SelectTape(); + break; + + case MenuConfigure: + GUI_Config(); + SK_SetSticky(SK_SHIFT, + DS81_Config[DS81_STICKY_SHIFT]); + ZX81Reconfigure(); + break; + + case MenuMapJoypad: + MapJoypad(); + break; + + case MenuMonitor: + MachineCodeMonitor(z80); + break; + +#ifndef DS81_DISABLE_FAT + 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; +#endif + } + + SK_DisplayKeyboard(); + } + break; + + default: + ZX81HandleKey(ev.key,ev.pressed); + break; + } + } + } + + return 0; +} |