diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | data/cpatrol_inlay.bin | bin | 28889 -> 7485 bytes | |||
-rw-r--r-- | data/keyb.bin | bin | 16390 -> 13447 bytes | |||
-rw-r--r-- | data/maze_inlay.bin | bin | 32392 -> 10654 bytes | |||
-rw-r--r-- | data/mazogs_inlay.bin | bin | 36155 -> 15329 bytes | |||
-rw-r--r-- | data/sabotage_inlay.bin | bin | 26323 -> 12794 bytes | |||
-rw-r--r-- | data/splashimg.bin | bin | 23615 -> 19171 bytes | |||
-rw-r--r-- | include/framebuffer.h | 69 | ||||
-rw-r--r-- | include/monitor.h | 27 | ||||
-rw-r--r-- | include/textmode.h | 37 | ||||
-rw-r--r-- | include/z80_config.h | 2 | ||||
-rw-r--r-- | include/zx81.h | 2 | ||||
-rw-r--r-- | source/framebuffer.c | 193 | ||||
-rw-r--r-- | source/gui.c | 70 | ||||
-rw-r--r-- | source/keyboard.c | 18 | ||||
-rw-r--r-- | source/main.c | 105 | ||||
-rw-r--r-- | source/monitor.c | 32 | ||||
-rw-r--r-- | source/tapes.c | 19 | ||||
-rw-r--r-- | source/textmode.c | 146 |
19 files changed, 578 insertions, 145 deletions
@@ -34,3 +34,6 @@ Changes from V1.1a to V1.2 + Added file selector with LOAD "*" + Handling of 1K display files is a bit better. + Added option for RAM in place of ROM mirror. + + Changed lower screen to 8-bit deep so I can overlay a tiled mode. + * Added lower screen console routines. + * Added Machine Code Monitor. diff --git a/data/cpatrol_inlay.bin b/data/cpatrol_inlay.bin Binary files differindex af70c60..6349d6f 100644 --- a/data/cpatrol_inlay.bin +++ b/data/cpatrol_inlay.bin diff --git a/data/keyb.bin b/data/keyb.bin Binary files differindex 3759ec5..adbfd5d 100644 --- a/data/keyb.bin +++ b/data/keyb.bin diff --git a/data/maze_inlay.bin b/data/maze_inlay.bin Binary files differindex 26a7e97..d48cb22 100644 --- a/data/maze_inlay.bin +++ b/data/maze_inlay.bin diff --git a/data/mazogs_inlay.bin b/data/mazogs_inlay.bin Binary files differindex a725c57..1088716 100644 --- a/data/mazogs_inlay.bin +++ b/data/mazogs_inlay.bin diff --git a/data/sabotage_inlay.bin b/data/sabotage_inlay.bin Binary files differindex da3f094..904c29a 100644 --- a/data/sabotage_inlay.bin +++ b/data/sabotage_inlay.bin diff --git a/data/splashimg.bin b/data/splashimg.bin Binary files differindex 38161e4..de16798 100644 --- a/data/splashimg.bin +++ b/data/splashimg.bin diff --git a/include/framebuffer.h b/include/framebuffer.h index 7b04685..3055e51 100644 --- a/include/framebuffer.h +++ b/include/framebuffer.h @@ -22,17 +22,64 @@ #ifndef DS81_FRAMEBUFFER_H #define DS81_FRAMEBUFFER_H -#define FB_RGB(r,g,b) ((RGB15(r,g,b))|0x8000) - -void FB_Init(uint16 *vram); -void FB_Print(const char *text, int x, int y, int colour, int paper); -void FB_Centre(const char *text, int y, int colour, int paper); -void FB_printf(int x, int y, int colour, int paper, const char *format, ...); -void FB_HLine(int x1, int x2, int y, int colour); -void FB_VLine(int x, int y1, int y2, int colour); -void FB_Box(int x, int y, int w, int h, int colour); -void FB_FillBox(int x, int y, int w, int h, int colour); +/* Predefined colours. +*/ +typedef enum +{ + COL_TRANSPARENT = -1, + COL_BLACK = 0, + COL_WHITE = 240, + COL_RED = 241, + COL_GREEN = 242, + COL_BLUE = 243, + COL_GUISELECT = 244, + COL_GREY = 245, + COL_LIGHTGREY = 246, + COL_DARKGREY = 247, + COL_YELLOW = 248 +} FB_Colour; + + +/* Initialise 'framebuffer' code. vram is where the 8-bit framebuffer is. + palette is the palette to use/set. +*/ +void FB_Init(uint16 *vram, uint16 *palette); + +/* Load the internal framebuffer font as a set of ASCII tiles (starting with + space) at tiles. The tiles will use colour COL_WHITE. +*/ +void FB_LoadASCIITiles(uint16 *tiles); + +/* Print the text into the framebuffer. +*/ +void FB_Print(const char *text, int x, int y, + FB_Colour colour, FB_Colour paper); +void FB_Centre(const char *text, int y, + FB_Colour colour, FB_Colour paper); +void FB_printf(int x, int y, FB_Colour colour, FB_Colour paper, + const char *format, ...); + +/* Lines and boxes. +*/ +void FB_HLine(int x1, int x2, int y, FB_Colour colour); +void FB_VLine(int x, int y1, int y2, FB_Colour colour); +void FB_Box(int x, int y, int w, int h, FB_Colour colour); +void FB_FillBox(int x, int y, int w, int h, FB_Colour colour); + +/* Clear to background +*/ void FB_Clear(void); -void FB_Blit(sImage *img, int x, int y); + +/* Draw the image. The image must be an 8-bit image, but with only the first + 16 palette entries used. Just to complicate matters! + + The image is assumed to be an even number of pixels wide. Also the passed + X co-ord will be forced even. + + offset is used to give an offset into the palette to place colours from the + image. Palette entries 1 - 128 will always be safe to use (these routines + will never use them). +*/ +void FB_Blit(sImage *img, int x, int y, int offset); #endif /* DS81_FRAMEBUFFER_H */ diff --git a/include/monitor.h b/include/monitor.h new file mode 100644 index 0000000..5bbdc8b --- /dev/null +++ b/include/monitor.h @@ -0,0 +1,27 @@ +/* + ds81 - Nintendo DS ZX81 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$ +*/ +#ifndef DS81_MONITOR_H +#define DS81_MONITOR_H + +void MachineCodeMonitor(void); + +#endif /* DS81_MONITOR_H */ diff --git a/include/textmode.h b/include/textmode.h new file mode 100644 index 0000000..751ad05 --- /dev/null +++ b/include/textmode.h @@ -0,0 +1,37 @@ +/* + ds81 - Nintendo DS ZX81 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$ +*/ +#ifndef DS81_TEXTMODE_H +#define DS81_TEXTMODE_H + +/* Note that the co-ords are into the map -- the user is free to use this and + move the map around, scale it, blend it, do want they want with it... + + The routines assume they can write into this map using the ASCII code + with 32 subtracted for each char. +*/ +void TM_Init(uint16 *vram, int map_width, int map_height, int map_is_rotation); + +void TM_Cls(void); +void TM_Put(int x, int y, const char *str); +void TM_printf(int x, int y, const char *format, ...); + +#endif /* DS81_TEXTMODE_H */ diff --git a/include/z80_config.h b/include/z80_config.h index 8be062b..af36944 100644 --- a/include/z80_config.h +++ b/include/z80_config.h @@ -34,8 +34,8 @@ /* Define this to enable the disassembly interface -#define ENABLE_DISASSEM */ +#define ENABLE_DISASSEM /* Define this to enable the array-based memory model. In this mode diff --git a/include/zx81.h b/include/zx81.h index c50c1a4..2606c98 100644 --- a/include/zx81.h +++ b/include/zx81.h @@ -77,6 +77,8 @@ void ZX81WriteMem(Z80 *z80, Z80Word addr, Z80Byte val); Z80Byte ZX81ReadPort(Z80 *z80, Z80Word port); void ZX81WritePort(Z80 *z80, Z80Word port, Z80Byte val); +#define ZX81ReadDisassem ZX81ReadMem + #endif diff --git a/source/framebuffer.c b/source/framebuffer.c index 691862e..6d16529 100644 --- a/source/framebuffer.c +++ b/source/framebuffer.c @@ -25,12 +25,16 @@ #include <stdarg.h> #include <string.h> +#include "framebuffer.h" + /* ---------------------------------------- STATIC DATA */ #define WIDTH 256 +#define SCAN 128 #define HEIGHT 192 -static uint16 *buff=0; +static uint16 *buff; +static uint16 *pal; static uint8 font[]= { @@ -132,60 +136,138 @@ static uint8 font[]= 0x3c, 0x42, 0x99, 0x85, 0x85, 0x99, 0x42, 0x3c }; + +/* ---------------------------------------- PRIVATE INTERFACES +*/ +static inline void Plot(int x, int y, int col) +{ + uint16 *base; + uint16 cur; + int odd; + + if (col == -1) + return; + + odd = x&1; + x /= 2; + + base = buff+x+y*SCAN; + cur = *base; + + if (odd) + { + cur = (cur & 0xff) | (col<<8); + } + else + { + cur = (cur & 0xff00) | col; + } + + *base = cur; +} + + /* ---------------------------------------- PUBLIC INTERFACES */ -void FB_Init(uint16 *vram) +void FB_Init(uint16 *vram, uint16 *palette) { - buff=vram; + buff = vram; + pal = palette; + + pal[COL_BLACK] = RGB15(0,0,0); + pal[COL_WHITE] = RGB15(31,31,31); + pal[COL_RED] = RGB15(31,0,0); + pal[COL_GREEN] = RGB15(0,31,0); + pal[COL_BLUE] = RGB15(0,0,31); + pal[COL_GUISELECT] = RGB15(8,8,31); + pal[COL_GREY] = RGB15(15,15,15); + pal[COL_LIGHTGREY] = RGB15(22,22,22); + pal[COL_DARKGREY] = RGB15(8,8,8); + pal[COL_YELLOW] = RGB15(31,31,0); } -void FB_Print(const char *text, int x, int y, int colour, int paper) +void FB_LoadASCIITiles(uint16 *tiles) { - uint16 *base; + uint8 *src; + int c; + int row; + int val; + int mask; - base=buff+y*WIDTH+x; + src = font; - while(*text) + for(c = 32; c < 127; c++) { - int x,y; - int ch; + for(row = 0; row < 8; row++) + { + for(mask = 1; mask < 0xff; mask<<=1) + { + if (*src & mask) + { + val = COL_WHITE; + } + else + { + val = 0; + } + + mask <<= 1; + + if (*src & mask) + { + val |= COL_WHITE << 8; + } + + *tiles++ = val; + } + + src++; + } + } +} + +void FB_Print(const char *text, int x, int y, FB_Colour colour, FB_Colour paper) +{ + int cx,cy; + int ch; + + while(*text) + { ch=((*text)-32)*8; - for(y=0;y<8;y++) + for(cy=0;cy<8;cy++) { - for(x=0;x<8;x++) + for(cx=0;cx<8;cx++) { - if (font[ch]&(1<<x)) + if (font[ch]&(1<<cx)) { - *(base+x+y*WIDTH)=colour; + Plot(x+cx, y+cy, colour); } else { - if (paper!=-1) - { - *(base+x+y*WIDTH)=paper; - } + Plot(x+cx, y+cy, paper); } } ch++; } - base+=8; + x+=8; text++; } } -void FB_Centre(const char *text, int y, int colour, int paper) +void FB_Centre(const char *text, int y, FB_Colour colour, FB_Colour paper) { FB_Print(text,WIDTH/2-strlen(text)*4,y,colour,paper); } -void FB_printf(int x, int y, int colour, int paper, const char *format, ...) +void FB_printf(int x, int y, FB_Colour colour, FB_Colour paper, + const char *format, ...) { char buff[80]; va_list va; @@ -198,7 +280,7 @@ void FB_printf(int x, int y, int colour, int paper, const char *format, ...) } -void FB_HLine(int x1, int x2, int y, int colour) +void FB_HLine(int x1, int x2, int y, FB_Colour colour) { uint16 *line; @@ -206,28 +288,21 @@ void FB_HLine(int x1, int x2, int y, int colour) while(x1<=x2) { - *line++=colour; - x1++; + Plot(x1++,y,colour); } } -void FB_VLine(int x, int y1, int y2, int colour) +void FB_VLine(int x, int y1, int y2, FB_Colour colour) { - uint16 *line; - - line=buff+y1*WIDTH+x; - while(y1<=y2) { - *line=colour; - line+=WIDTH; - y1++; + Plot(x,y1++,colour); } } -void FB_Box(int x, int y, int w, int h, int colour) +void FB_Box(int x, int y, int w, int h, FB_Colour colour) { FB_HLine(x,x+w-1,y,colour); FB_HLine(x,x+w-1,y+h-1,colour); @@ -236,21 +311,11 @@ void FB_Box(int x, int y, int w, int h, int colour) } -void FB_FillBox(int x, int y, int w, int h, int colour) +void FB_FillBox(int x, int y, int w, int h, FB_Colour colour) { - int f; - uint16 *base; - - base=buff+x+y*WIDTH; - while(h--) { - for(f=0;f<w;f++) - { - *(base+f)=colour; - } - - base+=WIDTH; + FB_HLine(x,x+w-1,y++,colour); } } @@ -260,30 +325,50 @@ void FB_Clear(void) uint16 *p; int f; - f=WIDTH*HEIGHT; + f=WIDTH*HEIGHT/2; p=buff; while(f--) { - *p++=0x8000; + *p++=0; } } -void FB_Blit(sImage *img, int x, int y) +void FB_Blit(sImage *img, int x, int y, int offset) { - if (img->width==WIDTH && img->height==HEIGHT) + uint16 *dest; + uint16 *row; + uint8 *src; + uint16 pix; + int hww; + int ht; + int f; + + x /= 2; + + ht = img->height; + hww = img->width / 2; + dest = buff+x+y*SCAN; + src = img->image.data8; + + for(f=0;f<16;f++) { - dmaCopy(img->image.data8,buff,SCREEN_WIDTH*SCREEN_HEIGHT*2); + pal[offset+f] = img->palette[f]; } - else + + while(ht--) { - int f; + row = dest; - for(f=0;f<img->height;f++) + for(f=0;f<hww;f++) { - dmaCopy(img->image.data16+(f*img->width), - buff+x+(y+f)*WIDTH,img->width*2); + pix = *src++ + offset; + pix |= (*src++ + offset) << 8; + + *row++ = pix; } + + dest += SCAN; } } diff --git a/source/gui.c b/source/gui.c index 92f6836..2027a37 100644 --- a/source/gui.c +++ b/source/gui.c @@ -219,13 +219,13 @@ int GUI_Menu(const char *opts[]) { uint32 key=0; - FB_FillBox(x,y,w,h,FB_RGB(0,0,0)); - FB_Box(x,y,w,h,FB_RGB(31,31,31)); - FB_FillBox(x+1,y+sel*16+1,w-2,14,FB_RGB(8,8,31)); + FB_FillBox(x,y,w,h,COL_BLACK); + FB_Box(x,y,w,h,COL_WHITE); + FB_FillBox(x+1,y+sel*16+1,w-2,14,COL_GUISELECT); for(f=0;f<no;f++) { - FB_Centre(opts[f],y+4+f*16,FB_RGB(31,31,31),-1); + FB_Centre(opts[f],y+4+f*16,COL_WHITE,COL_TRANSPARENT); } do @@ -290,8 +290,8 @@ void GUI_Alert(int fatal, const char *text) } } - FB_FillBox(0,0,SCREEN_WIDTH,h,FB_RGB(0,0,0)); - FB_Box(1,1,SCREEN_WIDTH-2,h-2,FB_RGB(31,0,0)); + FB_FillBox(0,0,SCREEN_WIDTH,h,COL_BLACK); + FB_Box(1,1,SCREEN_WIDTH-2,h-2,COL_WHITE); p=text; h=4; @@ -303,7 +303,7 @@ void GUI_Alert(int fatal, const char *text) { *d++=0; p++; - FB_Centre(line,h,FB_RGB(31,31,31),-1); + FB_Centre(line,h,COL_WHITE,COL_TRANSPARENT); h+=8; d=line; } @@ -316,13 +316,13 @@ void GUI_Alert(int fatal, const char *text) if (d>line) { *d=0; - FB_Centre(line,h,FB_RGB(31,31,31),-1); + FB_Centre(line,h,COL_WHITE,COL_TRANSPARENT); h+=8; } if (!fatal) { - FB_Centre("PRESS ANY BUTTON OR SCREEN",h+16,FB_RGB(31,31,0),-1); + FB_Centre("PRESS ANY BUTTON OR SCREEN",h+16,COL_YELLOW,COL_TRANSPARENT); while(!keysDown()) { @@ -336,7 +336,7 @@ void GUI_Alert(int fatal, const char *text) } else { - FB_Centre("PLEASE RESET YOUR CONSOLE",h+16,FB_RGB(31,31,0),-1); + FB_Centre("PLEASE RESET YOUR CONSOLE",h+16,COL_YELLOW,COL_TRANSPARENT); while(1) { @@ -359,18 +359,18 @@ void GUI_Config(void) FB_Clear(); - FB_Centre("Up/Down to select",140,FB_RGB(31,31,0),-1); - FB_Centre("A to toggle",150,FB_RGB(31,31,0),-1); - FB_Centre("Or use touchscreen",160,FB_RGB(31,31,0),-1); - FB_Centre("START to finish",170,FB_RGB(31,31,0),-1); + FB_Centre("Up/Down to select",140,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("A to toggle",150,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("Or use touchscreen",160,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("START to finish",170,COL_YELLOW,COL_TRANSPARENT); #ifndef DS81_DISABLE_FAT - FB_Centre("SELECT to finish and save",180,FB_RGB(31,31,0),-1); + FB_Centre("SELECT to finish and save",180,COL_YELLOW,COL_TRANSPARENT); #endif for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) { - FB_Print(ConfigDesc(f),14,20+f*14,FB_RGB(31,31,31),-1); + FB_Print(ConfigDesc(f),14,20+f*14,COL_WHITE,COL_TRANSPARENT); } while(!done) @@ -380,19 +380,19 @@ void GUI_Config(void) for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) { FB_FillBox(2,20+f*14-1,10,10, - DS81_Config[f] ? FB_RGB(31,31,31):FB_RGB(0,0,0)); + DS81_Config[f] ? COL_WHITE : COL_BLACK); - FB_Box(2,20+f*14-1,10,10,FB_RGB(18,18,18)); + FB_Box(2,20+f*14-1,10,10,COL_GREY); } - FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(18,18,31)); + FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,COL_GUISELECT); do { swiWaitForVBlank(); } while(!(key=keysDownRepeat())); - FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(0,0,0)); + FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,COL_BLACK); if (key & KEY_START) { @@ -448,8 +448,7 @@ bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) double bar_step; bool done; bool ret; - int pen; - int paper; + FB_Colour paper; int off; int f; bool drag; @@ -459,12 +458,12 @@ bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) FB_Clear(); - FB_printf(0,0,FB_RGB(0,0,0),FB_RGB(22,22,22),"%-32.32s",pwd); + FB_printf(0,0,COL_BLACK,COL_LIGHTGREY,"%-32.32s",pwd); - FB_Centre("Use pad and A to select",140,FB_RGB(31,31,0),-1); - FB_Centre("L and R to page up/down",150,FB_RGB(31,31,0),-1); - FB_Centre("Or use touchscreen",160,FB_RGB(31,31,0),-1); - FB_Centre("B to cancel",170,FB_RGB(31,31,0),-1); + FB_Centre("Use pad and A to select",140,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("L and R to page up/down",150,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("Or use touchscreen",160,COL_YELLOW,COL_TRANSPARENT); + FB_Centre("B to cancel",170,COL_YELLOW,COL_TRANSPARENT); no = LoadDir(pwd,filter); @@ -498,16 +497,14 @@ bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) { if (off == sel) { - pen = FB_RGB(0,0,0); - paper = FB_RGB(31,31,31); + paper = COL_GUISELECT; } else { - pen = FB_RGB(31,31,31); - paper = FB_RGB(0,0,0); + paper = COL_BLACK; } - FB_printf(8,FSEL_LIST_Y+f*8,pen,paper, + FB_printf(8,FSEL_LIST_Y+f*8,COL_WHITE,paper, "%-*s %s", FSEL_FILENAME_LEN, fsel[off].name, @@ -515,7 +512,7 @@ bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) } else { - FB_printf(8,FSEL_LIST_Y+f*8,FB_RGB(31,31,31),FB_RGB(0,0,0), + FB_printf(8,FSEL_LIST_Y+f*8,COL_WHITE,COL_BLACK, "%-*s %s", FSEL_FILENAME_LEN, off==0 ? "No Files!" : "", @@ -523,8 +520,8 @@ bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) } } - FB_FillBox(240,FSEL_LIST_Y,16,FSEL_LIST_H,FB_RGB(10,10,10)); - FB_FillBox(240,FSEL_LIST_Y+top*bar_step,16,bar_size,FB_RGB(31,31,31)); + FB_FillBox(240,FSEL_LIST_Y,16,FSEL_LIST_H,COL_DARKGREY); + FB_FillBox(240,FSEL_LIST_Y+top*bar_step,16,bar_size,COL_WHITE); if (drag) { @@ -681,8 +678,7 @@ bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) { AddPath(pwd,fsel[sel].name); - FB_printf(0,0,FB_RGB(0,0,0),FB_RGB(22,22,22), - "%-32.32s",pwd); + FB_printf(0,0,COL_BLACK,COL_LIGHTGREY,"%-32.32s",pwd); no = LoadDir(pwd,filter); diff --git a/source/keyboard.c b/source/keyboard.c index 37ae4ef..8853dd1 100644 --- a/source/keyboard.c +++ b/source/keyboard.c @@ -29,8 +29,6 @@ /* ---------------------------------------- STATIC DATA */ -static uint16 white = FB_RGB(31, 31, 31); -static uint16 black = FB_RGB(0, 0, 0); static struct { @@ -238,7 +236,8 @@ static int GetEvent(SoftKeyEvent *ev, int map) x = 3 + (f % 10) * 25; y = 37 + (f / 10) * 30; - FB_Box(x, y, 25, 18, key_state[f].new_state ? white:black); + FB_Box(x, y, 25, 18, key_state[f].new_state ? + COL_WHITE : COL_BLACK); } } } @@ -270,11 +269,16 @@ static int GetEvent(SoftKeyEvent *ev, int map) */ void SK_DisplayKeyboard(uint16 *vram) { - sImage img; + static sImage img; + static int loaded; - loadPCX(keyb_bin,&img); - image8to16(&img); - dmaCopy(img.image.data8,vram,SCREEN_WIDTH*SCREEN_HEIGHT*2); + if (!loaded) + { + loadPCX(keyb_bin,&img); + loaded = true; + } + + FB_Blit(&img,0,0,110); } diff --git a/source/main.c b/source/main.c index cfdf231..9d25ee0 100644 --- a/source/main.c +++ b/source/main.c @@ -33,6 +33,8 @@ #include "zx81.h" #include "tapes.h" #include "config.h" +#include "textmode.h" +#include "monitor.h" #include "splashimg_bin.h" #include "rom_font_bin.h" @@ -45,6 +47,7 @@ static const char *main_menu[]= "Select Tape", "Configure", "Map Joypad to Keys", + "Machine Code Monitor", "Cancel", NULL }; @@ -55,6 +58,7 @@ typedef enum MenuSelectTape, MenuConfigure, MenuMapJoypad, + MenuMonitor, } MenuOpt; /* ---------------------------------------- IRQ FUNCS @@ -69,6 +73,15 @@ static void VBlankFunc(void) 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. " + "Thanks to Slay Radio for coding fuel." + }; + static const char *text[]= { "DS81 \177 2006 Ian C", @@ -91,22 +104,24 @@ static void Splash(void) int f; int y; int res=FALSE; + int scr_x=0; ZX81SuspendDisplay(); ZX81DisplayString("10 print '%the zx81 is ace%'\n20 goto 10"); + TM_printf(0,23,"%-34.34s",scroller); + FB_Clear(); loadPCX(splashimg_bin,&img); - image8to16(&img); - FB_Blit(&img,0,0); + FB_Blit(&img,0,0,1); y = 10; for(f=0;text[f];f++) { - FB_Centre(text[f],y,FB_RGB(31,31,31),-1); + FB_Centre(text[f],y,COL_WHITE,COL_TRANSPARENT); y += 8; } @@ -120,46 +135,65 @@ static void Splash(void) { ZX81EnableFileSystem(TRUE); - FB_Centre("Found a FAT device.",y,FB_RGB(31,31,31),-1); + FB_Centre("Found a FAT device.",y,COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("If you place .P tape files in",y,FB_RGB(31,31,31),-1); + FB_Centre("If you place .P tape files in",y,COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("the top directory or ZX81SNAP",y,FB_RGB(31,31,31),-1); + FB_Centre("the top directory or ZX81SNAP",y,COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("then you should be able to load",y,FB_RGB(31,31,31),-1); + FB_Centre("then you should be able to load",y, + COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("GAME.P with the command",y,FB_RGB(31,31,31),-1); + FB_Centre("GAME.P with the command",y,COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("LOAD \"GAME\"",y,FB_RGB(31,31,31),-1); + FB_Centre("LOAD \"GAME\"",y,COL_WHITE,COL_TRANSPARENT); y += 8; } else { ZX81EnableFileSystem(FALSE); - FB_Centre("Sorry, but you don't have a",y,FB_RGB(31,31,31),-1); + FB_Centre("Sorry, but you don't have a",y,COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("supported FAT device.",y,FB_RGB(31,31,31),-1); + FB_Centre("supported FAT device.",y,COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("Only the internal tape",y,FB_RGB(31,31,31),-1); + FB_Centre("Only the internal tape",y,COL_WHITE,COL_TRANSPARENT); y += 8; - FB_Centre("files can be used.",y,FB_RGB(31,31,31),-1); + 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,23,"%-34.34s",scroller); + } + + SUB_BG0_X0 = scr_x; } + SUB_BG0_X0 = 0; + ZX81ResumeDisplay(); } @@ -241,7 +275,8 @@ int main(int argc, char *argv[]) vramSetBankA(VRAM_A_MAIN_BG_0x06000000); vramSetBankB(VRAM_B_MAIN_BG_0x06020000); - BG0_CR = BG_COLOR_256 | BG_MAP_BASE(0) | BG_TILE_BASE(1) | BG_PRIORITY(0); + BG0_CR = BG_COLOR_256 | BG_32x32 | BG_MAP_BASE(0) | + BG_TILE_BASE(1) | BG_PRIORITY(0); BG0_X0 = 0; BG0_Y0 = 0; @@ -258,22 +293,35 @@ int main(int argc, char *argv[]) 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) + /* 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). */ - videoSetModeSub(MODE_5_2D | DISPLAY_BG2_ACTIVE); + videoSetModeSub(MODE_3_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE); vramSetBankC(VRAM_C_SUB_BG_0x06200000); - SUB_BG2_CR = BG_BMP16_256x256; - 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_BG0_CR = BG_COLOR_256 | BG_64x32 | BG_MAP_BASE(4) | + BG_TILE_BASE(0) | BG_PRIORITY(0); + SUB_BG0_X0 = 0; + SUB_BG0_Y0 = 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(BG_GFX_SUB); + 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),64,32,FALSE); /* Set up interrupts and timers */ @@ -289,7 +337,7 @@ int main(int argc, char *argv[]) ZX81WriteMem, ZX81ReadPort, ZX81WritePort, - NULL); + ZX81ReadDisassem); if (!z80) { @@ -311,6 +359,9 @@ int main(int argc, char *argv[]) { SoftKeyEvent ev; + TM_printf(0,0,"HL = %4.4x",z80->HL.w); + TM_printf(0,23,"PC = %4.4x",z80->PC); + Z80Exec(z80); while(SK_GetEvent(&ev)) @@ -341,6 +392,10 @@ int main(int argc, char *argv[]) case MenuMapJoypad: MapJoypad(); break; + + case MenuMonitor: + MachineCodeMonitor(); + break; } SK_DisplayKeyboard(BG_GFX_SUB); diff --git a/source/monitor.c b/source/monitor.c new file mode 100644 index 0000000..62d5f3b --- /dev/null +++ b/source/monitor.c @@ -0,0 +1,32 @@ +/* + 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$ +*/ + +#include <nds.h> +#include <stdlib.h> + +#include "monitor.h" + +/* ---------------------------------------- PUBLIC INTERFACES +*/ +void MachineCodeMonitor(void) +{ +} diff --git a/source/tapes.c b/source/tapes.c index 8f141f9..b6df688 100644 --- a/source/tapes.c +++ b/source/tapes.c @@ -204,22 +204,21 @@ static void InitTapes(void) for(f=0;f<NO_TAPES;f++) { loadPCX(tapes[f].source_pcx,&tapes[f].img); - image8to16(&tapes[f].img); } } static void DisplayTape(Tape *t) { FB_Clear(); - FB_Blit(&t->img,255-t->img.width,0); - - FB_Print("LEFT/RIGHT",0,0,FB_RGB(255,255,255),-1); - FB_Print("to choose",0,10,FB_RGB(255,255,255),-1); - FB_Print("A to select",0,30,FB_RGB(255,255,255),-1); - FB_Print("B to cancel",0,40,FB_RGB(255,255,255),-1); - FB_Print("REMEMBER TO",0,60,FB_RGB(255,255,255),-1); - FB_Print("LOAD \"\"",0,70,FB_RGB(255,255,255),-1); - FB_Print("ON THE ZX81!",0,80,FB_RGB(255,255,255),-1); + FB_Blit(&t->img,255-t->img.width,0,1); + + FB_Print("LEFT/RIGHT",0,0,COL_WHITE,COL_TRANSPARENT); + FB_Print("to choose",0,10,COL_WHITE,COL_TRANSPARENT); + FB_Print("A to select",0,30,COL_WHITE,COL_TRANSPARENT); + FB_Print("B to cancel",0,40,COL_WHITE,COL_TRANSPARENT); + FB_Print("REMEMBER TO",0,60,COL_WHITE,COL_TRANSPARENT); + FB_Print("LOAD \"\"",0,70,COL_WHITE,COL_TRANSPARENT); + FB_Print("ON THE ZX81!",0,80,COL_WHITE,COL_TRANSPARENT); ZX81DisplayString(t->text); } diff --git a/source/textmode.c b/source/textmode.c new file mode 100644 index 0000000..aa6de44 --- /dev/null +++ b/source/textmode.c @@ -0,0 +1,146 @@ +/* + ds81 - Nintendo DS ZX81 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 <nds.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#include "textmode.h" + +/* ---------------------------------------- STATIC DATA +*/ +static int mapw; +static int maph; +static uint16 *text; +static int is_rot; +static void (*draw_string)(const char *str, int x, int y); + + +/* ---------------------------------------- PRIVATE INTERFACES +*/ +static inline void Plot_Text(int x, int y, int c) +{ + int xw; + int yw; + + xw = x/32; + yw = y/32; + x %= 32; + y %= 32; + + *(text + x + y*32 + (xw+yw) * 1024) = c; +} + + +static inline void Plot_RS(int x, int y, int c) +{ + int xw; + int yw; + + xw = x/32; + yw = y/32; + x %= 32; + y %= 32; + + *(text + x + y*32 + (xw+yw) * 1024) = c; +} + + +static void Text_Put(const char *str, int x, int y) +{ + while(*str && x<mapw) + { + Plot_Text(x,y,*str - 32); + x++; + str++; + } +} + +static void RS_Put(const char *str, int x, int y) +{ + while(*str && x<mapw) + { + Plot_RS(x,y,*str - 32); + x++; + str++; + } +} + +/* ---------------------------------------- PUBLIC INTERFACES +*/ +void TM_Init(uint16 *vram, int map_width, int map_height, int map_is_rotation) +{ + text = vram; + + mapw = map_width; + maph = map_height; + + is_rot = map_is_rotation; + + draw_string = map_is_rotation ? Text_Put : RS_Put; + + TM_Cls(); +} + + +void TM_Cls(void) +{ + uint16 *scr; + int f; + + scr = text; + + if (is_rot) + { + for(f=0;f<mapw*maph/2;f++) + { + *scr++=0; + } + } + else + { + for(f=0;f<mapw*maph;f++) + { + *scr++=0; + } + } +} + + +void TM_Put(int x, int y, const char *str) +{ + draw_string(str,x,y); +} + + +void TM_printf(int x, int y, const char *format, ...) +{ + char buff[128]; + va_list va; + + va_start(va,format); + vsnprintf(buff,sizeof buff,format,va); + va_end(va); + + draw_string(buff,x,y); +} |