From 75a05652e5851d9b6189088093a13b391e2a8b0c Mon Sep 17 00:00:00 2001 From: Neil Millstone Date: Sat, 30 Jun 2007 23:03:03 +0000 Subject: - Show mouse cursor option - Support for SAGA, CINE, and AGI - Key bindings for Gob3 - Assembler optimisations submitted by Robin Watts svn-id: r27803 --- backends/platform/ds/arm9/data/icons.raw | Bin 15360 -> 24576 bytes backends/platform/ds/arm9/makefile | 121 ++++++- backends/platform/ds/arm9/source/blitters.cpp | 402 --------------------- backends/platform/ds/arm9/source/blitters.h | 18 + backends/platform/ds/arm9/source/blitters.s | 339 +++++++++++++++++ backends/platform/ds/arm9/source/dsmain.cpp | 361 ++++++++++++++---- backends/platform/ds/arm9/source/dsmain.h | 25 +- backends/platform/ds/arm9/source/dsoptions.cpp | 54 ++- backends/platform/ds/arm9/source/dsoptions.h | 3 +- backends/platform/ds/arm9/source/fat/disc_io.c | 2 +- backends/platform/ds/arm9/source/fat/disc_io.h | 4 + backends/platform/ds/arm9/source/fat/gba_nds_fat.c | 13 +- backends/platform/ds/arm9/source/fat/io_dldi.h | 2 +- backends/platform/ds/arm9/source/gbampsave.cpp | 15 +- backends/platform/ds/arm9/source/gbampsave.h | 2 +- backends/platform/ds/arm9/source/osystem_ds.cpp | 61 ++-- backends/platform/ds/arm9/source/osystem_ds.h | 22 +- backends/platform/ds/arm9/source/touchkeyboard.cpp | 180 ++++++++- backends/platform/ds/arm9/source/touchkeyboard.h | 7 + .../platform/ds/arm9/source/wordcompletion.cpp | 67 ++++ backends/platform/ds/arm9/source/wordcompletion.h | 8 + backends/platform/ds/arm9/source/zipreader.cpp | 6 +- 22 files changed, 1144 insertions(+), 568 deletions(-) delete mode 100644 backends/platform/ds/arm9/source/blitters.cpp create mode 100644 backends/platform/ds/arm9/source/blitters.s create mode 100644 backends/platform/ds/arm9/source/wordcompletion.cpp create mode 100644 backends/platform/ds/arm9/source/wordcompletion.h diff --git a/backends/platform/ds/arm9/data/icons.raw b/backends/platform/ds/arm9/data/icons.raw index c2915b2914..c8fbfd6e9a 100644 Binary files a/backends/platform/ds/arm9/data/icons.raw and b/backends/platform/ds/arm9/data/icons.raw differ diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile index cb41774064..c9ca5467f3 100644 --- a/backends/platform/ds/arm9/makefile +++ b/backends/platform/ds/arm9/makefile @@ -4,18 +4,32 @@ libndsdir = /home/neil/devkitpro/libnds # Select the build you want by uncommenting one of the following lines: -DS_BUILD_A = 1 + +#DS_BUILD_A = 1 #DS_BUILD_B = 1 #DS_BUILD_C = 1 -#DS_BUILD_D = 1 +DS_BUILD_D = 1 +#DS_BUILD_E = 1 +#DS_BUILD_F = 1 # Uncomment the following line to build in support for MP3 audio # using libmad: -USE_MAD = 1 + +ifdef DS_BUILD_F + # TODO: Fix this. When libmad is compiled in, the Kyrandia resource loading + # searches through it's entire index to find an mp3 each time a voice sample is requested + # this causes a nasty pause. +else + USE_MAD = 1 +endif # Uncomment the following line to enable support for the # ace DS Debugger (remembering to make the same change in the arm7 makefile): #USE_DEBUGGER = 1 + +# Uncomment the following line to enable the profiler +#USE_PROFILER = 1 + # NOTE: The header and libs for the debugger is assumed to be in the libnds # folder. @@ -24,6 +38,7 @@ VPATH = $(srcdir) # Command to build libmad is: # ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' +ARM = 1 ifdef DS_BUILD_A DEFINES = -DDS_SCUMM_BUILD -DDS_BUILD_A @@ -44,6 +59,7 @@ ifdef DS_BUILD_A DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 BUILD=scummvm-A endif @@ -66,6 +82,7 @@ ifdef DS_BUILD_B DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 BUILD=scummvm-B endif @@ -81,13 +98,14 @@ ifdef DS_BUILD_C DISABLE_SWORD2 = 1 DISABLE_QUEEN = 1 DISABLE_SAGA = 1 - #DISABLE_KYRA = 1 - #DISABLE_GOB = 1 + DISABLE_KYRA = 1 + DISABLE_GOB = 1 DISABLE_LURE = 1 DISABLE_CINE = 1 DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 BUILD=scummvm-C endif @@ -104,15 +122,62 @@ ifdef DS_BUILD_D DISABLE_QUEEN = 1 DISABLE_SAGA = 1 DISABLE_KYRA = 1 - DISABLE_GOB = 1 + #DISABLE_GOB = 1 DISABLE_LURE = 1 #DISABLE_CINE = 1 #DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 - BUILD=scummvm-A + DISABLE_CRUISE = 1 + BUILD=scummvm-D endif +ifdef DS_BUILD_E + DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_E + LOGO = logoc.bmp + DISABLE_HE = 1 + DISABLE_SCUMM = 1 + DISABLE_SCUMM_7_8 = 1 + DISABLE_AGOS = 1 + DISABLE_SKY = 1 + DISABLE_SWORD1 = 1 + DISABLE_SWORD2 = 1 + DISABLE_QUEEN = 1 + #DISABLE_SAGA = 1 + DISABLE_KYRA = 1 + DISABLE_GOB = 1 + DISABLE_LURE = 1 + DISABLE_CINE = 1 + DISABLE_AGI = 1 + DISABLE_TOUCHE = 1 + DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 + BUILD=scummvm-E +endif + +ifdef DS_BUILD_F + DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_F + LOGO = logoc.bmp + DISABLE_HE = 1 + DISABLE_SCUMM = 1 + DISABLE_SCUMM_7_8 = 1 + DISABLE_AGOS = 1 + DISABLE_SKY = 1 + DISABLE_SWORD1 = 1 + DISABLE_SWORD2 = 1 + DISABLE_QUEEN = 1 + DISABLE_SAGA = 1 + #DISABLE_KYRA = 1 + DISABLE_GOB = 1 + DISABLE_LURE = 1 + DISABLE_CINE = 1 + DISABLE_AGI = 1 + DISABLE_TOUCHE = 1 + DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 + BUILD=scummvm-F + +endif ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;" @@ -120,7 +185,7 @@ ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;" CC = arm-eabi-gcc CXX = arm-eabi-g++ -CFLAGS = -Wno-multichar -Wall -Os\ +CFLAGS = -Wno-multichar -Wall\ -Wno-multichar -mcpu=arm9tdmi -mtune=arm9tdmi \ -mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\ -ffast-math -mthumb-interwork @@ -129,12 +194,17 @@ ifdef USE_DEBUGGER DEFINES += -DUSE_DEBUGGER CFLAGS += -g endif + +ifdef USE_PROFILER + CFLAGS += -mpoke-function-name -finstrument-functions -g + DEFINES += -DUSE_PROFILER +endif CXXFLAGS= $(CFLAGS) -Wno-non-virtual-dtor -Wno-non-virtual-dtor \ -fno-exceptions -fno-rtti ASFLAGS = -mcpu=arm9tdmi -mthumb-interwork -DEFINES += -D__DS__ -DNDS -DARM9 -DNONSTANDARD_PORT -DDISABLE_FANCY_THEMES -DDISABLE_DEFAULT_SAVEFILEMANAGER +DEFINES += -D__DS__ -DNDS -DARM9 -DNONSTANDARD_PORT -DDISABLE_FANCY_THEMES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DARM ifdef USE_MAD DEFINES += -DUSE_MAD endif @@ -182,9 +252,14 @@ PORT_OBJS := $(portdir)/source/blitters.o $(portdir)/source/cdaudio.o $(portdir) $(portdir)/../../../fs/ds/ds-fs.o $(portdir)/source/gbampsave.o $(portdir)/source/scummhelp.o\ $(portdir)/source/osystem_ds.o $(portdir)/source/portdefs.o $(portdir)/source/ramsave.o\ $(portdir)/source/scummconsole.o $(portdir)/source/touchkeyboard.o $(portdir)/source/zipreader.o\ - $(portdir)/source/dsoptions.o $(portdir)/source/keys.o + $(portdir)/source/dsoptions.o $(portdir)/source/keys.o $(portdir)/source/wordcompletion.o -DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o +ifdef USE_PROFILER + PORT_OBJS += $(portdir)/source/profiler/cyg-profile.o +endif + + +DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o COMPRESSOR_OBJS := $(portdir)/source/compressor/lz.o @@ -209,7 +284,9 @@ FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o LIBCARTRESET_OBJS := $(portdir)/source/libcartreset/cartreset.o - +# Files in this list will be compiled with -O2, otherwise they will be compiled with -Os +OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp fmopl.cpp rate.cpp mixer.cpp +#OPTLIST := OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS) @@ -269,6 +346,7 @@ endef # rm $(*).tmp #endef + ############## # Replacement rule for the one in makefile.common ############## @@ -276,6 +354,7 @@ ifndef HAVE_GCC3 # If you use GCC, disable the above and enable this for intelligent # dependency tracking. .cpp.o: + $(MKDIR) $(*D)/$(DEPDIR) $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o # $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d @@ -287,9 +366,19 @@ else # Also, with this GCC inserts additional dummy rules for the involved headers, # which ensures a smooth compilation even if said headers become obsolete. .cpp.o: +# echo !!!!!!!!!!!! $(notdir $<) +# ifeq ( $(notdir $<), $(findstring $(notdir $<), $(OPTLIST)) ) +# OPTFLAG=-O3 +# else +# OPTFLAG=-Os +# endif + +# export OPTFLAG = ; +# echo !!!!!!!! $(OPTFLAG) + $(MKDIR) $(*D)/$(DEPDIR) -# $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - $(CXX) -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o + $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o + $(CXX) -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o $(if $(findstring $(notdir $<), $(OPTLIST)), -O2, -Os) endif @@ -333,8 +422,8 @@ endif #--------------------------------------------------------------------------------- %.nds: %.bin - @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.11.0svn;DS Port" - ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.11.0svn;DS Port" + @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.10.0;DS Port" + ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.10.0;DS Port" dsbuild $@ -l ../ndsloader.bin padbin 16 $(basename $@).ds.gba diff --git a/backends/platform/ds/arm9/source/blitters.cpp b/backends/platform/ds/arm9/source/blitters.cpp deleted file mode 100644 index 9af3c5d611..0000000000 --- a/backends/platform/ds/arm9/source/blitters.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#include "stdafx.h" -#include "blitters.h" -#define CHARSET_MASK_TRANSPARENCY 253 - -//#define PERFECT_5_TO_4_RESCALING - -namespace DS { - -void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, - int vsPitch, int vmScreenWidth, int textSurfacePitch) { - - - if (height <= 0) height = 1; - if (width < 4) return; - - - width &= ~4; -// src = (const byte *) (((int) (src)) & (~4)); -// dst = (byte *) (((int) (dst)) & (~4)); -// text = (const byte *) (((int) (text)) & (~4)); - - asm ( "mov r5, %0\n" // Height - "yLoop:\n" - "mov r3, #0\n" // X pos - - "xLoop:\n" - - "ldr r4, [%2, r3]\n" // Load text layer word - "cmp r4, %5\n" - "bne singleByteCompare\n" - "ldr r4, [%3, r3]\n" - "str r4, [%4, r3]\n" - "add r3, r3, #4\n" - "cmp r3, %1\n" // x == width? - "blt xLoop\n" - - "add %2, %2, %8\n" // src += vs->pitch - "add %3, %3, %6\n" // dst += _vm->_screenWidth - "add %4, %4, %7\n" // text += _textSurface.pitch - "sub r5, r5, #1\n" // y -= 1 - "cmp r5, #0\n" // y == 0? - "bne yLoop\n" - "b end\n" - - - "singleByteCompare:\n" - "ldrb r4, [%2, r3]\n" // Load text byte - "cmps r4, %5, lsr #24\n" // Compare with mask - "strneb r4, [%4, r3]\n" // Store if not equal - "ldreqb r4, [%3, r3]\n" // Otherwise Load src byte - "streqb r4, [%4, r3]\n" // Store it - "add r3, r3, #1\n" - - "ldrb r4, [%2, r3]\n" // Load text byte - "cmps r4, %5, lsr #24\n" // Compare with mask - "strneb r4, [%4, r3]\n" // Store if not equal - "ldreqb r4, [%3, r3]\n" // Otherwise Load src byte - "streqb r4, [%4, r3]\n" // Store it - "add r3, r3, #1\n" - - "ldrb r4, [%2, r3]\n" // Load text byte - "cmps r4, %5, lsr #24\n" // Compare with mask - "strneb r4, [%4, r3]\n" // Store if not equal - "ldreqb r4, [%3, r3]\n" // Otherwise Load src byte - "streqb r4, [%4, r3]\n" // Store it - "add r3, r3, #1\n" - - "ldrb r4, [%2, r3]\n" // Load text byte - "cmps r4, %5, lsr #24\n" // Compare with mask - "strneb r4, [%4, r3]\n" // Store if not equal - "ldreqb r4, [%3, r3]\n" // Otherwise Load src byte - "streqb r4, [%4, r3]\n" // Store it - "add r3, r3, #1\n" - - "cmps r3, %1\n" // x == width? - "blt xLoop\n" // Repeat - "add %2, %2, %8\n" // src += vs->pitch - "add %3, %3, %6\n" // dst += _vm->_screenWidth - "add %4, %4, %7\n" // text += _textSurface.pitch - "sub r5, r5, #1\n" // y -= 1 - "cmp r5, #0\n" // y == 0? - "bne yLoop\n" - - "end:\n" - : /* no output registers */ - : "r" (height), "r" (width), "r" (text), "r" (src), "r" (dst), "r" (CHARSET_MASK_TRANSPARENCY | (CHARSET_MASK_TRANSPARENCY << 8) | (CHARSET_MASK_TRANSPARENCY << 16) | (CHARSET_MASK_TRANSPARENCY << 24)), - "r" (vsPitch), "r" (vmScreenWidth), "r" (textSurfacePitch) - : "r5", "r3", "r4", "%2", "%3", "%4", "memory"); -} - - - -void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height) { - asm("ands r0, %3, #1\n" - "addne %3, %3, #1\n" - "bne roll2\n" - - "yLoop2:\n" - "ldr r0, [%2, #0]\n" - "str r0, [%0, #0]\n" - "ldr r0, [%2, #4]\n" - "str r0, [%0, #4]\n" - "add %0, %0, %1\n" - "add %2, %2, %1\n" - "roll2:\n" - "ldr r0, [%2, #0]\n" - "str r0, [%0, #0]\n" - "ldr r0, [%2, #4]\n" - "str r0, [%0, #4]\n" - "add %0, %0, %1\n" - "add %2, %2, %1\n" - "subs %3, %3, #2\n" - "bne yLoop2\n" - - : /* no output registers */ - : "r" (dst), "r" (dstPitch), "r" (src), "r" (height) - : "r0", "%0", "%2", "%3"); -} - -static bool isDivBy5Ready = false; -static u32 DIV_BY_5[160]; - -void ComputeDivBy5TableIFN() -{ - if (isDivBy5Ready) - return; - isDivBy5Ready = true; - - for(int i=0; i<160; ++i) - { - DIV_BY_5[i] = (2*i+5)/10; - } -} - -#ifdef PERFECT_5_TO_4_RESCALING -static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3, u16 s4, - u16* dest) -{ - u32 bs0 = s0 & 0x1F; - u32 bs1 = s1 & 0x1F; - u32 bs2 = s2 & 0x1F; - u32 bs3 = s3 & 0x1F; - u32 bs4 = s4 & 0x1F; - -#if 0 - u32 gs0 = (s0 >> 5) & 0x1F; - u32 gs1 = (s1 >> 5) & 0x1F; - u32 gs2 = (s2 >> 5) & 0x1F; - u32 gs3 = (s3 >> 5) & 0x1F; - u32 gs4 = (s4 >> 5) & 0x1F; - - u32 rs0 = (s0 >> 10) & 0x1F; - u32 rs1 = (s1 >> 10) & 0x1F; - u32 rs2 = (s2 >> 10) & 0x1F; - u32 rs3 = (s3 >> 10) & 0x1F; - u32 rs4 = (s4 >> 10) & 0x1F; -#else - // The compiler absolutely wants to use 0x1F as an immediate, which makes it unable to fold the shift during the and - u32 mask = 0x1F; - u32 gs0, gs1, gs2, gs3, gs4; - asm("and %0, %2, %1, lsr #5" : "=r"(gs0) : "r"(s0), "r"(mask) : ); - asm("and %0, %2, %1, lsr #5" : "=r"(gs1) : "r"(s1), "r"(mask) : ); - asm("and %0, %2, %1, lsr #5" : "=r"(gs2) : "r"(s2), "r"(mask) : ); - asm("and %0, %2, %1, lsr #5" : "=r"(gs3) : "r"(s3), "r"(mask) : ); - asm("and %0, %2, %1, lsr #5" : "=r"(gs4) : "r"(s4), "r"(mask) : ); - u32 rs0, rs1, rs2, rs3, rs4; - asm("and %0, %2, %1, lsr #10" : "=r"(rs0) : "r"(s0), "r"(mask) : ); - asm("and %0, %2, %1, lsr #10" : "=r"(rs1) : "r"(s1), "r"(mask) : ); - asm("and %0, %2, %1, lsr #10" : "=r"(rs2) : "r"(s2), "r"(mask) : ); - asm("and %0, %2, %1, lsr #10" : "=r"(rs3) : "r"(s3), "r"(mask) : ); - asm("and %0, %2, %1, lsr #10" : "=r"(rs4) : "r"(s4), "r"(mask) : ); -#endif - - u32 rd0 = 4*rs0 + rs1; - u32 rd1 = 2*rs1 + rs1 + 2*rs2; - u32 rd2 = 2*rs2 + 2*rs3 + rs3; - u32 rd3 = rs3 + 4*rs4; - - u32 gd0 = 4*gs0 + gs1; - u32 gd1 = 2*gs1 + gs1 + 2*gs2; - u32 gd2 = 2*gs2 + 2*gs3 + gs3; - u32 gd3 = gs3 + 4*gs4; - - u32 bd0 = 4*bs0 + bs1; - u32 bd1 = 2*bs1 + bs1 + 2*bs2; - u32 bd2 = 2*bs2 + 2*bs3 + bs3; - u32 bd3 = bs3 + 4*bs4; - -#if 0 - // Offsetting for correct rounding - rd0 = rd0*2+5; rd1 = rd1*2+5; rd2 = rd2*2+5; rd3 = rd3*2+5; - gd0 = gd0*2+5; gd1 = gd1*2+5; gd2 = gd2*2+5; gd3 = gd3*2+5; - bd0 = bd0*2+5; bd1 = bd1*2+5; bd2 = bd2*2+5; bd3 = bd3*2+5; - - rd0 = (rd0 * 51) >> 9; rd1 = (rd1 * 51) >> 9; rd2 = (rd2 * 51) >> 9; rd3 = (rd3 * 51) >> 9; - gd0 = (gd0 * 51) >> 9; gd1 = (gd1 * 51) >> 9; gd2 = (gd2 * 51) >> 9; gd3 = (gd3 * 51) >> 9; - bd0 = (bd0 * 51) >> 9; bd1 = (bd1 * 51) >> 9; bd2 = (bd2 * 51) >> 9; bd3 = (bd3 * 51) >> 9; -#else - rd0 = DIV_BY_5[rd0]; rd1 = DIV_BY_5[rd1]; rd2 = DIV_BY_5[rd2]; rd3 = DIV_BY_5[rd3]; - gd0 = DIV_BY_5[gd0]; gd1 = DIV_BY_5[gd1]; gd2 = DIV_BY_5[gd2]; gd3 = DIV_BY_5[gd3]; - bd0 = DIV_BY_5[bd0]; bd1 = DIV_BY_5[bd1]; bd2 = DIV_BY_5[bd2]; bd3 = DIV_BY_5[bd3]; -#endif - - u32 d10 = 0x80008000 | (rd1 << 26) | (gd1 << 21) | (bd1 << 16) | (rd0 << 10) | (gd0 << 5) | bd0; - u32 d32 = 0x80008000 | (rd3 << 26) | (gd3 << 21) | (bd3 << 16) | (rd2 << 10) | (gd2 << 5) | bd2; - - ((u32*)dest)[0] = d10; - ((u32*)dest)[1] = d32; -} -#else -static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3, u16 s4, - u16* dest) -{ - u32 ar0bs0 = s0 & 0x7C1F; - u32 ar0bs1 = s1 & 0x7C1F; - u32 ar0bs2 = s2 & 0x7C1F; - u32 ar0bs3 = s3 & 0x7C1F; - u32 ar0bs4 = s4 & 0x7C1F; - - u32 gs0 = s0 & 0x03E0; - u32 gs1 = s1 & 0x03E0; - u32 gs2 = s2 & 0x03E0; - u32 gs3 = s3 & 0x03E0; - u32 gs4 = s4 & 0x03E0; - - u32 ar0bd0 = (3*ar0bs0 + ar0bs1) >> 2; - u32 ar0bd1 = ( ar0bs1 + ar0bs2) >> 1; - u32 ar0bd2 = ( ar0bs2 + ar0bs3) >> 1; - u32 ar0bd3 = ( ar0bs3 + 3*ar0bs4) >> 2; - - u32 gd0 = (3*gs0 + gs1) >> 2; - u32 gd1 = ( gs1 + gs2) >> 1; - u32 gd2 = ( gs2 + gs3) >> 1; - u32 gd3 = ( gs3 + 3*gs4) >> 2; - - u32 d0 = (ar0bd0 & 0xFC1F) | (gd0 & 0x03E0); - u32 d1 = (ar0bd1 & 0xFC1F) | (gd1 & 0x03E0); - u32 d2 = (ar0bd2 & 0xFC1F) | (gd2 & 0x03E0); - u32 d3 = (ar0bd3 & 0xFC1F) | (gd3 & 0x03E0); - - u32 d10 = 0x80008000 | (d1 << 16) | d0; - u32 d32 = 0x80008000 | (d3 << 16) | d2; - - ((u32*)dest)[0] = d10; - ((u32*)dest)[1] = d32; -} -#endif - -static inline void RescaleBlock_5x8888_To_4x1555( u32 s0, u32 s1, u32 s2, u32 s3, u32 s4, - u16* dest) -{ - u32 d0 = 4*s0 + s1; - u32 d1 = 2*s1 + s1 + 2*s2; - - u32 bd0 = (d0 << 24) >> 24; - u32 bd1 = (d1 << 24) >> 24; - u32 gd0 = (d0 << 16) >> 24; - u32 gd1 = (d1 << 16) >> 24; - u32 rd0 = (d0 >> 16); - u32 rd1 = (d1 >> 16); - - rd0 = DIV_BY_5[rd0]; rd1 = DIV_BY_5[rd1]; - gd0 = DIV_BY_5[gd0]; gd1 = DIV_BY_5[gd1]; - bd0 = DIV_BY_5[bd0]; bd1 = DIV_BY_5[bd1]; - u32 d10 = 0x80008000 | (rd1 << 26) | (gd1 << 21) | (bd1 << 16) | (rd0 << 10) | (gd0 << 5) | bd0; - ((u32*)dest)[0] = d10; - - u32 d2 = 2*s2 + 2*s3 + s3; - u32 d3 = s3 + 4*s4; - - u32 bd2 = (d2 << 24) >> 24; - u32 bd3 = (d3 << 24) >> 24; - u32 gd2 = (d2 << 16) >> 24; - u32 gd3 = (d3 << 16) >> 24; - u32 rd2 = (d2 >> 16); - u32 rd3 = (d3 >> 16); - - rd2 = DIV_BY_5[rd2]; rd3 = DIV_BY_5[rd3]; - gd2 = DIV_BY_5[gd2]; gd3 = DIV_BY_5[gd3]; - bd2 = DIV_BY_5[bd2]; bd3 = DIV_BY_5[bd3]; - u32 d32 = 0x80008000 | (rd3 << 26) | (gd3 << 21) | (bd3 << 16) | (rd2 << 10) | (gd2 << 5) | bd2; - - ((u32*)dest)[1] = d32; -} - -// Can't work in place -#ifdef PERFECT_5_TO_4_RESCALING -static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const u8* src, const u32* palette) -{ - ComputeDivBy5TableIFN(); - - for(size_t i=0; i<64; ++i) - { - u32 s0 = palette[src[5*i+0]]; - u32 s1 = palette[src[5*i+1]]; - u32 s2 = palette[src[5*i+2]]; - u32 s3 = palette[src[5*i+3]]; - u32 s4 = palette[src[5*i+4]]; - - RescaleBlock_5x8888_To_4x1555(s0, s1, s2, s3, s4, dest+4*i); - } -} -#else -static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const u8* src, const u16* palette) -{ - for(size_t i=0; i<64; ++i) - { - u16 s0 = palette[src[5*i+0]]; - u16 s1 = palette[src[5*i+1]]; - u16 s2 = palette[src[5*i+2]]; - u16 s3 = palette[src[5*i+3]]; - u16 s4 = palette[src[5*i+4]]; - - RescaleBlock_5x1555_To_4x1555(s0, s1, s2, s3, s4, dest+4*i); - } -} -#endif - - -// Can work in place, because it's a contraction -static inline void Rescale_320x1555Scanline_To_256x1555Scanline(u16* dest, const u16* src) -{ - ComputeDivBy5TableIFN(); - - for(size_t i=0; i<64; ++i) - { - u16 s0 = src[5*i+0]; - u16 s1 = src[5*i+1]; - u16 s2 = src[5*i+2]; - u16 s3 = src[5*i+3]; - u16 s4 = src[5*i+4]; - - RescaleBlock_5x1555_To_4x1555(s0, s1, s2, s3, s4, dest+4*i); - } -} - -#ifdef PERFECT_5_TO_4_RESCALING -void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, const u16* palette, int destStride, int srcStride) -{ - u32 fastRam[768]; - - // Palette lookup -> 0_888 - for(size_t i=0; i<256; ++i) - { - u32 col = palette[i]; - u32 result = col & 0x0000001F; - result |= (col << 3) & 0x00001F00; - result |= (col << 6) & 0x001F0000; - - fastRam[i] = result; - } - - for(size_t i=0; i<200; ++i) - { - Rescale_320xPAL8Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride, fastRam); - } -} -#else -void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, const u16* palette, int destStride, int srcStride) -{ - u16 fastRam[256]; - for(size_t i=0; i<128; ++i) - ((u32*)fastRam)[i] = ((const u32*)palette)[i]; - - for(size_t i=0; i<200; ++i) - { - Rescale_320xPAL8Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride, fastRam); - } -} -#endif - -void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride) -{ - for(size_t i=0; i<200; ++i) - { - Rescale_320x1555Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride); - } -} - -} diff --git a/backends/platform/ds/arm9/source/blitters.h b/backends/platform/ds/arm9/source/blitters.h index 9fb50cdf0d..fe6966fdae 100644 --- a/backends/platform/ds/arm9/source/blitters.h +++ b/backends/platform/ds/arm9/source/blitters.h @@ -23,6 +23,10 @@ #ifndef _BLITTERS_H_ #define _BLITTERS_H_ +#define USING_ARM_BLITTERS + +#ifndef USING_ARM_BLITTERS + namespace DS { void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, @@ -33,4 +37,18 @@ void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStr } +#else + +extern "C" { + +void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, + int vsPitch, int vmScreenWidth, int textSurfacePitch); +void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height); +void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, const u16* palette, int destStride, int srcStride); +void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride); + +} + +#endif + #endif diff --git a/backends/platform/ds/arm9/source/blitters.s b/backends/platform/ds/arm9/source/blitters.s new file mode 100644 index 0000000000..2f14c5a140 --- /dev/null +++ b/backends/platform/ds/arm9/source/blitters.s @@ -0,0 +1,339 @@ +@ ScummVM Scumm Interpreter +@ Copyright (C) 2007 The ScummVM project +@ +@ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +@ +@ $URL: $ +@ $Id: $ +@ +@ @author Robin Watts (robin@wss.co.uk) + + .text + + .global asmDrawStripToScreen + .global asmCopy8Col + .global Rescale_320x256xPAL8_To_256x256x1555 + .global Rescale_320x256x1555_To_256x256x1555 + + @ ARM implementation of asmDrawStripToScreen. + @ + @ C prototype would be: + @ + @ extern "C" void asmDrawStripToScreen(int height, + @ int width, + @ byte const *text, + @ byte const *src, + @ byte *dst, + @ int vsPitch, + @ int vsScreenWidth, + @ int textSurfacePitch); + @ + @ In addition, we assume that text, src and dst are all word (4 byte) + @ aligned. This is the same assumption that the old 'inline' version + @ made. +asmDrawStripToScreen: + @ r0 = height + @ r1 = width + @ r2 = text + @ r3 = src + MOV r12,r13 + STMFD r13!,{r4-r7,r9-r11,R14} + LDMIA r12,{r4,r5,r6,r7} + @ r4 = dst + @ r5 = vsPitch + @ r6 = vmScreenWidth + @ r7 = textSurfacePitch + + CMP r0,#0 @ If height<=0 + MOVLE r0,#1 @ height=1 + CMP r1,#4 @ If width<4 + BLT end @ return + + @ Width &= ~4 ? What's that about then? Width &= ~3 I could have + @ understood... + BIC r1,r1,#4 + + SUB r5,r5,r1 @ vsPitch -= width + SUB r6,r6,r1 @ vmScreenWidth -= width + SUB r7,r7,r1 @ textSurfacePitch -= width + MOV r10,#253 + ORR r10,r10,r10,LSL #8 + ORR r10,r10,r10,LSL #16 @ r10 = mask +yLoop: + MOV r14,r1 @ r14 = width +xLoop: + LDR r12,[r2],#4 @ r12 = [text] + LDR r11,[r3],#4 @ r11 = [src] + CMP r12,r10 + BNE singleByteCompare + SUBS r14,r14,#4 + STR r11,[r4], #4 @ r4 = [dst] + BGT xLoop + + ADD r2,r2,r7 @ text += textSurfacePitch + ADD r3,r3,r5 @ src += vsPitch + ADD r4,r4,r6 @ dst += vmScreenWidth + SUBS r0,r0,#1 + BGT yLoop + LDMFD r13!,{r4-r7,r9-r11,PC} + +singleByteCompare: + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + STR r12,[r4],#4 + SUBS r14,r14,#4 + BGT xLoop + + ADD r2,r2,r7 @ text += textSurfacePitch + ADD r3,r3,r5 @ src += vsPitch + ADD r4,r4,r6 @ dst += vmScreenWidth + SUBS r0,r0,#1 + BGT yLoop +end: + LDMFD r13!,{r4-r7,r9-r11,PC} + + + @ ARM implementation of asmCopy8Col + @ + @ C prototype would be: + @ + @ extern "C" void asmCopy8Col(byte *dst, + @ int dstPitch, + @ const byte *src, + @ int height); + @ + @ In addition, we assume that src and dst are both word (4 byte) + @ aligned. This is the same assumption that the old 'inline' version + @ made. +asmCopy8Col: + @ r0 = dst + @ r1 = dstPitch + @ r2 = src + @ r3 = height + STMFD r13!,{r14} + SUB r1,r1,#4 + + TST r3,#1 + ADDNE r3,r3,#1 + BNE roll2 +yLoop2: + LDR r12,[r2],#4 + LDR r14,[r2],r1 + STR r12,[r0],#4 + STR r14,[r0],r1 +roll2: + LDR r12,[r2],#4 + LDR r14,[r2],r1 + SUBS r3,r3,#2 + STR r12,[r0],#4 + STR r14,[r0],r1 + BNE yLoop2 + + LDMFD r13!,{PC} + + + @ ARM implementation of Rescale_320x256x1555_To_256x256x1555 + @ + @ C prototype would be: + @ + @ extern "C" void Rescale_320x256x1555_To_256x256x1555( + @ u16 *dst, + @ const u16 *src, + @ int dstStride, + @ int srcStride); +Rescale_320x256x1555_To_256x256x1555: + @ r0 = dst + @ r1 = src + @ r2 = dstStride + @ r3 = srcStride + STMFD r13!,{r4-r5,r8-r11,r14} + + SUB r2,r2,#64*5 @ srcStride -= line length + SUB r3,r3,#64*4 @ dstStride -= line length + + MOV r8, #0x0000001F + ORR r8, r8,#0x00007C00 + ORR r8, r8,#0x03E00000 @ r8 = mask + MOV r5, #200 @ r5 = y +yLoop3: + MOV r4, #64 @ r4 = x +xLoop3: + LDRH r9, [r0],#2 @ r9 = src0 + LDRH r10,[r0],#2 @ r10= src1 + LDRH r11,[r0],#2 @ r11= src2 + LDRH r12,[r0],#2 @ r12= src3 + LDRH r14,[r0],#2 @ r14= src4 + + ORR r9, r9, r9, LSL #16 @ r9 = src0 | src0 + ORR r10,r10,r10,LSL #16 @ r10= src1 | src1 + ORR r11,r11,r11,LSL #16 @ r11= src2 | src2 + ORR r12,r12,r12,LSL #16 @ r12= src3 | src3 + ORR r14,r14,r14,LSL #16 @ r13= src4 | src4 + + AND r9, r9, r8 @ r9 = 0 | G0 | 0 | B0 | 0 | R0 + AND r10,r10,r8 @ r10= 0 | G1 | 0 | B1 | 0 | R1 + AND r11,r11,r8 @ r11= 0 | G2 | 0 | B2 | 0 | R2 + AND r12,r12,r8 @ r12= 0 | G3 | 0 | B3 | 0 | R3 + AND r14,r14,r8 @ r14= 0 | G4 | 0 | B4 | 0 | R4 + + ADD r9, r9, r9, LSL #1 @ r9 = 3*src0 + ADD r9, r9, r10 @ r9 = dst0<<2 + ADD r10,r10,r11 @ r10= dst1 + ADD r11,r11,r12 @ r11= dst2 + ADD r12,r12,r14 @ r12= src3 + src4 + ADD r12,r12,r14,LSL #1 @ r12= src3 + src4*3 = dst3<<2 + + AND r9, r8, r9, LSR #2 @ r9 = dst0 (split) + AND r10,r8, r10,LSR #1 @ r10= dst1 (split) + AND r11,r8, r11,LSR #1 @ r11= dst2 (split) + AND r12,r8, r12,LSR #2 @ r12= dst3 (split) + + ORR r9, r9, r9, LSR #16 @ r9 = dst0 + ORR r10,r10,r10,LSR #16 @ r10= dst1 + ORR r11,r11,r11,LSR #16 @ r11= dst2 + ORR r12,r12,r12,LSR #16 @ r12= dst3 + + ORR r9, r9, #0x8000 + ORR r10,r10,#0x8000 + ORR r11,r11,#0x8000 + ORR r12,r12,#0x8000 + + STRH r9, [r1],#2 + STRH r10,[r1],#2 + STRH r11,[r1],#2 + STRH r12,[r1],#2 + + SUBS r4,r4,#1 + BGT xLoop3 + + ADD r0,r0,r2,LSL #1 + ADD r1,r2,r3,LSL #1 + SUBS r5,r5,#1 + BGT yLoop3 + + LDMFD r13!,{r4-r5,r8-r11,PC} + + @ ARM implementation of Rescale_320x256xPAL8_To_256x256x1555 + @ + @ C prototype would be: + @ + @ extern "C" void Rescale_320x256xPAL8_To_256x256x1555( + @ u16 *dst, + @ const u8 *src, + @ int dstStride, + @ int srcStride, + @ const u16 *pal); + @ + @ This is a slight reordering of the params from the existing C one. + @ Sorry, but it makes the code easier. +Rescale_320x256xPAL8_To_256x256x1555: + @ r0 = dst + @ r1 = src + @ r2 = dstStride + @ r3 = srcStride + STMFD r13!,{r4-r5,r8-r11,r14} + MOV r8, #0x0000001F + ORR r8, r8,#0x00007C00 + ORR r8, r8,#0x03E00000 @ r8 = mask + LDR r9, [r13,#7*4] @ r9 = palette + + SUB r13,r13,#256*4 @ r13 = 1K of space on the stack. + MOV r5, r13 @ r5 points to this space + MOV r14,#256 +palLoop: + LDRH r10,[r9],#2 @ r10 = palette entry + SUBS r14,r14,#1 + ORR r10,r10,r10,LSL #16 + AND r10,r10,r8 @ r10 = separated palette entry + STR r10,[r5], #4 + BGT palLoop + + SUB r2,r2,#64*5 @ srcStride -= line length + SUB r3,r3,#64*4 @ dstStride -= line length + + MOV r5,#200 @ r5 = y +yLoop4: + MOV r4,#64 @ r4 = x +xLoop4: + LDRB r9, [r0],#1 @ r9 = src0 + LDRB r10,[r0],#1 @ r10= src1 + LDRB r11,[r0],#1 @ r11= src2 + LDRB r12,[r0],#1 @ r12= src3 + LDRB r14,[r0],#1 @ r14= src4 + + LDR r9, [r13,r9, LSL #2] @ r9 = pal[src0] + LDR r10,[r13,r10,LSL #2] @ r10= pal[src1] + LDR r11,[r13,r11,LSL #2] @ r11= pal[src2] + LDR r12,[r13,r12,LSL #2] @ r12= pal[src3] + LDR r14,[r13,r14,LSL #2] @ r13= pal[src4] + + ADD r9, r9, r9, LSL #1 @ r9 = 3*src0 + ADD r9, r9, r10 @ r9 = dst0<<2 + ADD r10,r10,r11 @ r10= dst1 + ADD r11,r11,r12 @ r11= dst2 + ADD r12,r12,r14 @ r12= src3 + src4 + ADD r12,r12,r14,LSL #1 @ r12= src3 + src4*3 = dst3<<2 + + AND r9, r8, r9, LSR #2 @ r9 = dst0 (split) + AND r10,r8, r10,LSR #1 @ r10= dst1 (split) + AND r11,r8, r11,LSR #1 @ r11= dst2 (split) + AND r12,r8, r12,LSR #2 @ r12= dst3 (split) + + ORR r9, r9, r9, LSR #16 @ r9 = dst0 + ORR r10,r10,r10,LSR #16 @ r10= dst1 + ORR r11,r11,r11,LSR #16 @ r11= dst2 + ORR r12,r12,r12,LSR #16 @ r12= dst3 + + ORR r9, r9, #0x8000 + ORR r10,r10,#0x8000 + ORR r11,r11,#0x8000 + ORR r12,r12,#0x8000 + + STRH r9, [r1],#2 + STRH r10,[r1],#2 + STRH r11,[r1],#2 + STRH r12,[r1],#2 + + SUBS r4,r4,#1 + BGT xLoop4 + + ADD r0,r0,r2 + ADD r1,r2,r3,LSL #1 + SUBS r5,r5,#1 + BGT yLoop4 + + ADD r13,r13,#256*4 + + LDMFD r13!,{r4-r5,r8-r11,PC} + + diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp index bd7df9b977..48632533ef 100644 --- a/backends/platform/ds/arm9/source/dsmain.cpp +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -44,9 +44,32 @@ // - Delete saves? // - Software scaler? // - 100% scale + +// - Arrow keys cause key events when keyboard enabled - Done +// - Mouse cursor display - Done +// - Disable scaler on options menu - Done +// - Fix scale icons on top screen - Done +// - Fseek optimisation? - No need +// - Fix agi hack to be cleaner - done +// - Fix not typing looong words - Done +// - Show keyboard by default in AGI games +// - Fix mouse moving when cursor on keyboard screen - Done +// - Fix 'fit' thingy always appearing - Done +// - check cine backbuffer code - Done +// - Add long filename support - Done +// - New icons +// - Add key config for gob engine: Start:F1, Shift-numbers: F keys - Done +// - Fix [ds] appearing in game menu + // - Find out what's going wrong when you turn the console off +// - enable console when asserting + +// - AGI: Adding keyboard hack +// - CINE: Framebuffer modification should check if it works without, fix for overwrite crash +// - KYRA: GetFileSize modification + -#define USE_LIBCARTRESET +//#define USE_LIBCARTRESET //#define USE_BUILT_IN_DRIVER_SELECTION #include @@ -78,6 +101,8 @@ #include "blitters.h" #include "cartreset_nolibfat.h" #include "keys.h" +#include "profiler/cyg-profile.h" + namespace DS { @@ -151,13 +176,16 @@ bool displayModeIs8Bit = false; // Game id u8 gameID; -bool consoleEnable = true; +bool consoleEnable = false; bool gameScreenSwap = false; bool isCpuScalerEnabled(); //#define HEAVY_LOGGING MouseMode mouseMode; +int storedMouseX = 0; +int storedMouseY = 0; + // Sprites SpriteEntry sprites[128]; SpriteEntry spritesMain[128]; @@ -173,6 +201,9 @@ bool keyboardIcon = false; // Touch int touchScX, touchScY, touchX, touchY; +int mouseHotspotX, mouseHotspotY; +bool cursorEnable = false; +bool mouseCursorVisible = true; // Dragging int dragStartX, dragStartY; @@ -188,20 +219,12 @@ int gameHeight = 200; // Scale bool twoHundredPercentFixedScale = false; +#define NUM_SUPPORTED_GAMES 17 -enum controlType { - CONT_SCUMM_ORIGINAL, - CONT_SCUMM_SAMNMAX, - CONT_SKY, - CONT_SIMON, -}; - -struct gameListType { - char gameId[16]; - controlType control; -}; +#ifdef USE_PROFILER +int hBlankCount = 0; +#endif -#define NUM_SUPPORTED_GAMES 15 gameListType gameList[NUM_SUPPORTED_GAMES] = { // Unknown game - use normal SCUMM controls @@ -222,8 +245,10 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = { {"sky", CONT_SKY}, {"simon1", CONT_SIMON}, {"simon2", CONT_SIMON}, - {"gob1", CONT_SCUMM_ORIGINAL}, - {"queen", CONT_SCUMM_ORIGINAL} + {"gob", CONT_GOBLINS}, + {"queen", CONT_SCUMM_ORIGINAL}, + {"cine", CONT_FUTURE_WARS}, + {"agi", CONT_AGI} }; gameListType* currentGame = NULL; @@ -259,9 +284,11 @@ int getKeysChanged(); void updateStatus(); void triggerIcon(int imageNum); void setIcon(int num, int x, int y, int imageNum, int flags, bool enable); +void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable); TransferSound soundControl; + bool isCpuScalerEnabled() { return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds")); @@ -332,20 +359,21 @@ void initSprites() { void saveGameBackBuffer() { #ifdef DISABLE_SCUMM - if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight]; + if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight]; for (int r = 0; r < gameHeight; r++) { memcpy(savedBuffer + (r * gameWidth), ((u8 *) (get8BitBackBuffer())) + (r * 512), gameWidth); + } #endif } void restoreGameBackBuffer() { #ifdef DISABLE_SCUMM if (savedBuffer) { - for (int r = 0; r < gameHeight; r++) { - memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); - memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); - } - + for (int r = 0; r < gameHeight; r++) { + memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + } + delete savedBuffer; savedBuffer = NULL; } @@ -413,7 +441,7 @@ void initGame() { //strcpy(gameName, ConfMan.getActiveDomain().c_str()); strcpy(gameName, ConfMan.get("gameid").c_str()); -// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); + //consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); currentGame = &gameList[0]; // Default game @@ -590,7 +618,51 @@ void checkSleepMode() { } } -void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) { +void setShowCursor(bool enable) +{ + if (currentGame->control == CONT_SCUMM_SAMNMAX) + { + if (cursorEnable) { + sprites[1].attribute[0] = ATTR0_BMP | 150; + } else { + sprites[1].attribute[0] = ATTR0_DISABLED; + } + + } + + cursorEnable = enable; +} + +void setMouseCursorVisible(bool enable) +{ + mouseCursorVisible = enable; +} + +void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY) { + + mouseHotspotX = hotspotX; + mouseHotspotY = hotspotY; + + { + int off = 128*64; + + + memset(SPRITE_GFX + off, 0, 32 * 32 * 2); + + for (uint y=0; ycontrol != CONT_SCUMM_SAMNMAX) return; @@ -619,6 +691,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) { for (uint y=0; yisEventQueueEmpty()) { @@ -1051,7 +1142,7 @@ void addEventsToQueue() { if (!indyFightState) { - if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (getKeysChanged() & KEY_B)) { event.kbd.keycode = 27; event.kbd.ascii = 27; event.kbd.flags = 0; @@ -1073,8 +1164,37 @@ void addEventsToQueue() { } } + if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeyboardEnable())) { + event.kbd.flags = 0; + + if (getKeysChanged() & KEY_LEFT) { + event.kbd.keycode = SDLK_LEFT; + event.kbd.ascii = SDLK_LEFT; + event.type = getKeyEvent(KEY_LEFT); + } + + if (getKeysChanged() & KEY_RIGHT) { + event.kbd.keycode = SDLK_RIGHT; + event.kbd.ascii = SDLK_RIGHT; + event.type = getKeyEvent(KEY_RIGHT); + } + + if (getKeysChanged() & KEY_UP) { + event.kbd.keycode = SDLK_UP; + event.kbd.ascii = SDLK_UP; + event.type = getKeyEvent(KEY_UP); + } + + if (getKeysChanged() & KEY_DOWN) { + event.kbd.keycode = SDLK_DOWN; + event.kbd.ascii = SDLK_DOWN; + event.type = getKeyEvent(KEY_DOWN); + } + + system->addEvent(event); + } - if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState())) { + if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) { if ((getKeysDown() & KEY_A) && (!indyFightState)) { gameScreenSwap = !gameScreenSwap; @@ -1084,16 +1204,25 @@ void addEventsToQueue() { if (getKeysDown() & KEY_LEFT) { mouseMode = MOUSE_LEFT; } + if (getKeysDown() & KEY_RIGHT) { - if (currentGame->control != CONT_SCUMM_SAMNMAX) { + if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS)) { mouseMode = MOUSE_RIGHT; } else { // If we're playing sam and max, click and release the right mouse // button to change verb Common::Event event; + + if (currentGame->control == CONT_FUTURE_WARS) { + event.mouse = Common::Point(320 - 128, 200 - 128); + event.type = Common::EVENT_MOUSEMOVE; + system->addEvent(event); + } else { + event.mouse = Common::Point(getPenX(), getPenY()); + } + event.type = Common::EVENT_RBUTTONDOWN; - event.mouse = Common::Point(getPenX(), getPenY()); system->addEvent(event); event.type = Common::EVENT_RBUTTONUP; @@ -1126,14 +1255,16 @@ void addEventsToQueue() { Common::Event event; - if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { - event.type = Common::EVENT_MOUSEMOVE; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); - } if (!keyboardEnable) { + + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + event.type = Common::EVENT_MOUSEMOVE; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); + } + if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) { if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? Common::EVENT_LBUTTONDOWN: Common::EVENT_RBUTTONDOWN; @@ -1253,8 +1384,18 @@ void addEventsToQueue() { if ((getKeysChanged() & KEY_START)) { event.type = getKeyEvent(KEY_START); - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = Common::ASCII_F5; + if (currentGame->control == CONT_FUTURE_WARS) { + event.kbd.keycode = Common::KEYCODE_F10; + event.kbd.ascii = Common::ASCII_F10; + } else if (currentGame->control == CONT_GOBLINS) { + event.kbd.keycode = Common::KEYCODE_F1; + event.kbd.ascii = Common::ASCII_F1; +// consolePrintf("!!!!!F1!!!!!"); + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = Common::ASCII_F5; +// consolePrintf("!!!!!F5!!!!!"); + } event.kbd.flags = 0; system->addEvent(event); } @@ -1280,11 +1421,17 @@ void triggerIcon(int imageNum) { void setIcon(int num, int x, int y, int imageNum, int flags, bool enable) { - sprites[num].attribute[0] = ATTR0_BMP | y | (!enable? ATTR0_DISABLED: 0); + sprites[num].attribute[0] = ATTR0_BMP | (enable? y: 192) | (!enable? ATTR0_DISABLED: 0); sprites[num].attribute[1] = ATTR1_SIZE_32 | x | flags; sprites[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16); } +void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable) { + spritesMain[num].attribute[0] = ATTR0_BMP | (y & 0x1FF) | (!enable? ATTR0_DISABLED: 0); + spritesMain[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags; + spritesMain[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16); +} + void updateStatus() { int offs; @@ -1313,7 +1460,7 @@ void updateStatus() { if (indyFightState) { setIcon(1, (190 - 32), 150, 3, (indyFightRight? 0: ATTR1_FLIP_X), true); - consolePrintf("%d\n", indyFightRight); +// consolePrintf("%d\n", indyFightRight); } else { // setIcon(1, 0, 0, 0, 0, false); } @@ -1324,7 +1471,7 @@ void updateStatus() { } else { setIcon(4, 0, 0, 0, 0, false); } - + } else { setIcon(0, 0, 0, 0, 0, false); setIcon(1, 0, 0, 0, 0, false); @@ -1334,14 +1481,16 @@ void updateStatus() { } if ((keyboardIcon) && (!keyboardEnable) && (!displayModeIs8Bit)) { - spritesMain[0].attribute[0] = ATTR0_BMP | 160; - spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0; - spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64; +// spritesMain[0].attribute[0] = ATTR0_BMP | 160; +// spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0; +// spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64; + setIconMain(0, 0, 160, 4, 0, true); } else { - spritesMain[0].attribute[0] = ATTR0_DISABLED; - spritesMain[0].attribute[1] = 0; - spritesMain[0].attribute[2] = 0; - spritesMain[0].attribute[3] = 0; +// spritesMain[0].attribute[0] = ATTR0_DISABLED; +// spritesMain[0].attribute[1] = 0; +// spritesMain[0].attribute[2] = 0; +// spritesMain[0].attribute[3] = 0; + setIconMain(0, 0, 0, 0, 0, false); } } @@ -1428,6 +1577,10 @@ void setZoomedScreenScale(int x, int y) { } } +#ifdef USE_PROFILER +void VBlankHandler(void) __attribute__ ((no_instrument_function)); +#endif + void VBlankHandler(void) { // BG_PALETTE[0] = RGB15(31, 31, 31); // if (*((int *) (0x023FFF00)) != 0xBEEFCAFE) { @@ -1473,6 +1626,19 @@ void VBlankHandler(void) { frameCount++; + if ((cursorEnable) && (mouseCursorVisible)) + { + if (!keyboardEnable) { + storedMouseX = penX; + storedMouseY = penY; + } + + setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true); + } + else + { + setIconMain(3, 0, 0, 0, 0, false); + } if (callback) { @@ -1563,7 +1729,7 @@ void VBlankHandler(void) { if (zooming) { subScX = subScTargetX; subScY = subScTargetY; - triggerIcon(0); + triggerIcon(5); } } else if ( ((subScreenWidth) > 128 - 8) && ((subScreenWidth) < 128 + 8) ) { subScreenWidth = 128; @@ -1571,7 +1737,7 @@ void VBlankHandler(void) { if (zooming) { subScX = subScTargetX; subScY = subScTargetY; - triggerIcon(1); + triggerIcon(6); } } else if (subScreenWidth > 256) { subScreenWidth = 320; @@ -1579,10 +1745,10 @@ void VBlankHandler(void) { if (zooming) { subScX = subScTargetX; subScY = subScTargetY; - triggerIcon(2); + triggerIcon(7); } } else { - triggerIcon(-1); + //triggerIcon(-1); } } @@ -1745,6 +1911,14 @@ void setTopScreenTarget(int x, int y) { subScTargetY <<=8; } +#ifdef USE_PROFILER +void hBlankHanlder() __attribute__ ((no_instrument_function)); + +void hBlankHandler() { + hBlankCount++; +} +#endif + void initHardware() { // Guard band //((int *) (0x023FFF00)) = 0xBEEFCAFE; @@ -1757,7 +1931,7 @@ void initHardware() { vramSetBankB(VRAM_B_MAIN_BG); vramSetBankC(VRAM_C_SUB_BG); */ vramSetBankI(VRAM_I_SUB_SPRITE); - vramSetBankG(VRAM_G_MAIN_SPRITE); + vramSetBankE(VRAM_E_MAIN_SPRITE); currentTimeMillis = 0; @@ -1825,6 +1999,11 @@ void initHardware() { irqEnable(IRQ_VBLANK); irqEnable(IRQ_TIMER0); irqEnable(IRQ_TIMER2); + +#ifdef USE_PROFILER + irqSet(IRQ_HBLANK, hBlankHandler); + irqEnable(IRQ_HBLANK); +#endif // Set up a millisecond timer @@ -1847,14 +2026,22 @@ void initHardware() { // Convert texture from 24bit 888 to 16bit 1555, remembering to set top bit! u8* srcTex = (u8 *) icons_raw; - for (int r = 32 * 160 ; r >= 0; r--) { + for (int r = 32 * 256 ; r >= 0; r--) { SPRITE_GFX_SUB[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); SPRITE_GFX[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); } + + + + WAIT_CR &= ~(0x0080); // REG_WRAM_CNT = 0; + // This is a bodge to get around the fact that the cursor is turned on before it's image is set + // during startup in Sam & Max. This bodge moves the cursor offscreen so it is not seen. + sprites[1].attribute[1] = ATTR1_SIZE_64 | 192; + } @@ -2067,23 +2254,28 @@ bool getIndyFightState() { return indyFightState; } +gameListType* getCurrentGame() { + return currentGame; +} + /////////////////// // Fast Ram /////////////////// -#define FAST_RAM_SIZE (30000) +#define FAST_RAM_SIZE (24000) u8* fastRamPointer; u8 fastRamData[FAST_RAM_SIZE] ITCM_DATA; void* fastRamAlloc(int size) { +// return malloc(size); void* result = (void *) fastRamPointer; fastRamPointer += size; return (void *) (result); } void fastRamReset() { - fastRamPointer = fastRamData; + fastRamPointer = &fastRamData[0]; } @@ -2308,24 +2500,34 @@ int main(void) // } - + //2372 consolePrintf("-------------------------------\n"); consolePrintf("ScummVM DS\n"); consolePrintf("Ported by Neil Millstone\n"); - FIXME: Change this code to make use of base/internal_version.h - resp. uses gScummVMVersion from base/version.h - consolePrintf("Version 0.10.0SVN "); + consolePrintf("Version 0.10.0 beta1 "); #if defined(DS_BUILD_A) consolePrintf("build A\n"); - consolePrintf("Supports: Lucasarts SCUMM\n"); + consolePrintf("Lucasarts SCUMM games (SCUMM)\n"); consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_B) consolePrintf("build B\n"); - consolePrintf("Supports: BASS, QUEEN\n"); + consolePrintf("BASS, QUEEN\n"); consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_C) consolePrintf("build C\n"); - consolePrintf("Supports: SIMON, KYRA, GOB\n"); + consolePrintf("Simon the Sorcerer 1/2 (SIMON)\n"); + consolePrintf("-------------------------------\n"); +#elif defined(DS_BUILD_D) + consolePrintf("build D\n"); + consolePrintf("AGI, CINE, GOB\n"); + consolePrintf("-------------------------------\n"); +#elif defined(DS_BUILD_E) + consolePrintf("build E\n"); + consolePrintf("Inherit the earth (SAGA)\n"); + consolePrintf("-------------------------------\n"); +#elif defined(DS_BUILD_F) + consolePrintf("build F\n"); + consolePrintf("The Legend of Kyrandia (KYRA)\n"); consolePrintf("-------------------------------\n"); #endif consolePrintf("L/R + D-pad/pen: Scroll view\n"); @@ -2333,7 +2535,7 @@ int main(void) consolePrintf("D-pad right: Right mouse button\n"); consolePrintf("D-pad up: Hover mouse\n"); consolePrintf("B button: Skip cutscenes\n"); - consolePrintf("Select: DS Options menu\n"); + consolePrintf("Select: DS Options menu\n"); consolePrintf("Start: Game menu (some games)\n"); consolePrintf("Y (in game): Toggle console\n"); consolePrintf("X: Toggle keyboard\n"); @@ -2457,10 +2659,13 @@ int main(void) #elif defined(DS_BUILD_C) char* argv[2] = {"/scummvmds", "--config=scummvmc.ini"}; #elif defined(DS_BUILD_D) - char* argv[2] = {"/scummvmds", "--config=scummvmd.ini"}; + char* argv[3] = {"/scummvmds", "--config=scummvmd.ini"}; +#elif defined(DS_BUILD_E) + char* argv[3] = {"/scummvmds", "--config=scummvme.ini"}; +#elif defined(DS_BUILD_F) + char* argv[3] = {"/scummvmds", "--config=scummvmf.ini"}; #endif - #ifdef DS_NON_SCUMM_BUILD while (1) { @@ -2482,3 +2687,13 @@ int main(void) int main() { DS::main(); } + + +#ifdef USE_PROFILER +int cygprofile_getHBlanks() __attribute__ ((no_instrument_function)); + + +int cygprofile_getHBlanks() { + return DS::hBlankCount; +} +#endif diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h index 58a5be9240..94f02145a2 100644 --- a/backends/platform/ds/arm9/source/dsmain.h +++ b/backends/platform/ds/arm9/source/dsmain.h @@ -31,6 +31,22 @@ namespace DS { + +enum controlType { + CONT_SCUMM_ORIGINAL, + CONT_SCUMM_SAMNMAX, + CONT_SKY, + CONT_SIMON, + CONT_FUTURE_WARS, + CONT_AGI, + CONT_GOBLINS +}; + +struct gameListType { + char gameId[16]; + controlType control; +}; + // Pen reading functions void penInit(); void penUpdate(); @@ -83,7 +99,9 @@ void VBlankHandler(); // Sam and Max Stuff void setGameID(int id); -void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor); +void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY); +void setShowCursor(bool enable); +void setMouseCursorVisible(bool visible); // Shake void setShakePos(int shakePos); @@ -123,7 +141,12 @@ void fastRamReset(); void* fastRamAlloc(int size); +gameListType* getCurrentGame(); + + } +int cygprofile_getHBlanks(); + #endif diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp index 171d1e044c..b29b1d9fa7 100644 --- a/backends/platform/ds/arm9/source/dsoptions.cpp +++ b/backends/platform/ds/arm9/source/dsoptions.cpp @@ -55,7 +55,8 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) { _twoHundredPercentCheckbox = new GUI::CheckboxWidget(this, 20, 70, 230, 20, "Zoomed screen at fixed 200% zoom", 0, 'T'); _highQualityAudioCheckbox = new GUI::CheckboxWidget(this, 20, 85, 250, 20, "High quality audio (slower) (reboot)", 0, 'T'); _disablePowerOff = new GUI::CheckboxWidget(this, 20, 100, 250, 20, "Disable power off on quit", 0, 'T'); - _cpuScaler = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "CPU scaler", 0, 'T'); +// _cpuScaler = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "CPU scaler", 0, 'T'); + _showCursorCheckbox = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "Show mouse cursor", 0, 'T'); new GUI::StaticTextWidget(this, 20, 130, 110, 15, "Touch X Offset", GUI::kTextAlignLeft); _touchX = new GUI::SliderWidget(this, 130, 130, 130, 12, 1); @@ -79,6 +80,12 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) { _delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm); #endif + if (ConfMan.hasKey("showcursor", "ds")) { + _showCursorCheckbox->setState(ConfMan.getBool("showcursor", "ds")); + } else { + _showCursorCheckbox->setState(false); + } + if (ConfMan.hasKey("lefthanded", "ds")) { _leftHandedCheckbox->setState(ConfMan.getBool("lefthanded", "ds")); } else { @@ -108,13 +115,13 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) { } else { _disablePowerOff->setState(false); } - +/* if (ConfMan.hasKey("cpu_scaler", "ds")) { _cpuScaler->setState(ConfMan.getBool("cpu_scaler", "ds")); } else { _cpuScaler->setState(false); } - +*/ _indyFightCheckbox->setState(DS::getIndyFightState()); if (ConfMan.hasKey("xoffset", "ds")) { @@ -137,9 +144,10 @@ DSOptionsDialog::~DSOptionsDialog() { ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds"); ConfMan.setBool("22khzaudio", _highQualityAudioCheckbox->getState(), "ds"); ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds"); - ConfMan.setBool("cpu_scaler", _cpuScaler->getState(), "ds"); +// ConfMan.setBool("cpu_scaler", _cpuScaler->getState(), "ds"); ConfMan.setInt("xoffset", _touchX->getValue(), "ds"); ConfMan.setInt("yoffset", _touchY->getValue(), "ds"); + ConfMan.setBool("showcursor", _showCursorCheckbox->getState(), "ds"); DS::setOptions(); DS::setIndyFightState(_indyFightCheckbox->getState()); ConfMan.flushToDisk(); @@ -181,15 +189,27 @@ void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint } +void togglePause() { + // Toggle pause mode by simulating pressing 'p'. Not a good way of doing things! + + if (getCurrentGame()->control == CONT_SCUMM_ORIGINAL) { + Common::Event event; + OSystem_DS* system = OSystem_DS::instance(); + + event.type = Common::EVENT_KEYDOWN; + event.kbd.keycode = 'p'; + event.kbd.ascii = 'p'; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event); + } +} + void showOptionsDialog() { - OSystem_DS* system = OSystem_DS::instance(); - Common::Event event; - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = 'P'; // F5 - event.kbd.ascii = 'P'; - event.kbd.flags = 0; - system->addEvent(event); + togglePause(); DS::displayMode16Bit(); @@ -201,11 +221,7 @@ void showOptionsDialog() { DS::displayMode8Bit(); - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = 'P'; // F5 - event.kbd.ascii = 'P'; - event.kbd.flags = 0; - system->addEvent(event); + togglePause(); } void setOptions() { @@ -217,6 +233,12 @@ void setOptions() { DS::setLeftHanded(false); } + if (ConfMan.hasKey("showcursor", "ds")) { + DS::setMouseCursorVisible(ConfMan.getBool("showcursor", "ds")); + } else { + DS::setMouseCursorVisible(true); + } + if (ConfMan.hasKey("unscaled", "ds")) { DS::setUnscaledMode(ConfMan.getBool("unscaled", "ds")); } else { diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h index 8dde086f57..6976fb1a59 100644 --- a/backends/platform/ds/arm9/source/dsoptions.h +++ b/backends/platform/ds/arm9/source/dsoptions.h @@ -43,7 +43,7 @@ public: protected: virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); - + void togglePause(); GUI::SliderWidget* _touchX; GUI::SliderWidget* _touchY; @@ -54,6 +54,7 @@ protected: GUI::CheckboxWidget* _highQualityAudioCheckbox; GUI::CheckboxWidget* _disablePowerOff; GUI::CheckboxWidget* _cpuScaler; + GUI::CheckboxWidget* _showCursorCheckbox; #ifdef DS_SCUMM_BUILD Scumm::SaveLoadChooser* _delDialog; diff --git a/backends/platform/ds/arm9/source/fat/disc_io.c b/backends/platform/ds/arm9/source/fat/disc_io.c index c706cf8b3e..3cb70f510b 100644 --- a/backends/platform/ds/arm9/source/fat/disc_io.c +++ b/backends/platform/ds/arm9/source/fat/disc_io.c @@ -358,7 +358,7 @@ void disc_getDldiId(char* id) { bool disc_setDsSlotInterface (void) { #ifdef ARM9 - REG_EXMEMCNT &= ~(1<<11); + REG_EXEMEMCNT &= ~(1<<11); #endif #ifdef ARM7 REG_EXEMEMCNT |= (1<<11); diff --git a/backends/platform/ds/arm9/source/fat/disc_io.h b/backends/platform/ds/arm9/source/fat/disc_io.h index 1fbcc78c19..06804afec7 100644 --- a/backends/platform/ds/arm9/source/fat/disc_io.h +++ b/backends/platform/ds/arm9/source/fat/disc_io.h @@ -33,7 +33,11 @@ // Disk caching is disabled on GBA to conserve memory #define DISC_CACHE // uncomment this line to enable disc caching +#ifdef DS_BUILD_F +#define DISC_CACHE_COUNT 128 // maximum number of sectors to cache (512 bytes per sector) +#else #define DISC_CACHE_COUNT 32 // maximum number of sectors to cache (512 bytes per sector) +#endif //#define DISK_CACHE_DMA // use DMA for cache copies. If this is enabled, the data buffers must be word aligned diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c index f343c4b997..b5fdd665df 100644 --- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c +++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c @@ -1362,9 +1362,18 @@ DIR_ENT FAT_DirEntFromPath (const char* path) DIR_ENT dirEntry; u32 dirCluster; bool flagLFN, dotSeen; - // Start at beginning of path pathPos = 0; + +#ifdef DS_BUILD_F + // Problems with Kyrandia doing a load of path lookups are reduced by this hack. + if (strstr(path, ".voc") || strstr(path, ".voc")) + { + dirEntry.name[0] = FILE_FREE; + dirEntry.attrib = 0x00; + return; + } +#endif if (path[pathPos] == '/') { @@ -2499,6 +2508,7 @@ int FAT_fseek(FAT_FILE* file, s32 offset, int origin) u32 position; u32 curPos; + if ((file == NULL) || (file->inUse == false)) // invalid file { return -1; @@ -2613,6 +2623,7 @@ int FAT_fseek(FAT_FILE* file, s32 offset, int origin) } return 0; + } /*----------------------------------------------------------------- diff --git a/backends/platform/ds/arm9/source/fat/io_dldi.h b/backends/platform/ds/arm9/source/fat/io_dldi.h index 86c3407374..053de3a94c 100644 --- a/backends/platform/ds/arm9/source/fat/io_dldi.h +++ b/backends/platform/ds/arm9/source/fat/io_dldi.h @@ -30,7 +30,7 @@ extern u8 _dldi_driver_name; static inline LPIO_INTERFACE DLDI_GetInterface(void) { #ifdef NDS // NDM: I'm really not sure about this change ARM9 - ARM7 - REG_EXMEMCNT &= ~(ARM7_OWNS_ROM | ARM7_OWNS_CARD); + REG_EXEMEMCNT &= ~(ARM7_OWNS_ROM | ARM7_OWNS_CARD); #endif // defined NDS return &_io_dldi; } diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp index 7f7bf958df..0131040e1d 100644 --- a/backends/platform/ds/arm9/source/gbampsave.cpp +++ b/backends/platform/ds/arm9/source/gbampsave.cpp @@ -29,7 +29,7 @@ GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) { handle = DS::std_fopen(name, saveOrLoad? "w": "r"); -// consolePrintf("%s handle is %d\n", name, handle); + consolePrintf("%s handle is %d\n", name, handle); // consolePrintf("Created %s\n", name); bufferPos = 0; saveSize = 0; @@ -39,6 +39,7 @@ GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) { GBAMPSaveFile::~GBAMPSaveFile() { flushSaveBuffer(); if (handle) DS::std_fclose(handle); + consolePrintf("Closed file\n"); } uint32 GBAMPSaveFile::read(void *buf, uint32 size) { @@ -57,7 +58,7 @@ void GBAMPSaveFile::skip(uint32 bytes) { void GBAMPSaveFile::flushSaveBuffer() { if (bufferPos != 0) { - consolePrintf("Flushing %d bytes from %x\n", bufferPos, buffer); +// consolePrintf("Flushing %d bytes from %x\n", bufferPos, buffer); flushed += bufferPos; DS::std_fwrite(buffer, 1, bufferPos, handle); bufferPos = 0; @@ -174,8 +175,10 @@ void GBAMPSaveFileManager::listSavefiles(char const* prefix, bool* marks, int nu char path[128]; DS::std_cwd((char *) getSavePath()); + + consolePrintf("Save path: %s\n", getSavePath()); - int fileType = FAT_FindFirstFile(name); + int fileType = FAT_FindFirstFileLFN(name); for (int r = 0; r < num; r++) { marks[r] = false; @@ -192,17 +195,17 @@ void GBAMPSaveFileManager::listSavefiles(char const* prefix, bool* marks, int nu sprintf(str, "%s%02d", prefix, r); -// consolePrintf("%s != %s", str, name); + consolePrintf("%s != %s", str, name); if (!stricmp(str, name)) { marks[r] = true; -// consolePrintf("Matched %d", r); + consolePrintf("Matched %d", r); } } } - } while ((fileType = FAT_FindNextFile(name))); + } while ((fileType = FAT_FindNextFileLFN(name))); FAT_chdir("/"); } diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h index 1580533f66..c7d9732d4c 100644 --- a/backends/platform/ds/arm9/source/gbampsave.h +++ b/backends/platform/ds/arm9/source/gbampsave.h @@ -37,7 +37,7 @@ class GBAMPSaveFile : public Common::InSaveFile, public Common::OutSaveFile { public: GBAMPSaveFile(char* name, bool saveOrLoad); - ~GBAMPSaveFile(); + virtual ~GBAMPSaveFile(); virtual uint32 read(void *buf, uint32 size); virtual uint32 write(const void *buf, uint32 size); diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index cad6ad6b78..32eafe1af7 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -37,6 +37,7 @@ #include "common/str.h" #include "cdaudio.h" #include "graphics/surface.h" +#include "touchkeyboard.h" OSystem_DS* OSystem_DS::_instance = NULL; @@ -138,9 +139,12 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) { green >>= 3; blue >>= 3; - BG_PALETTE[r] = red | (green << 5) | (blue << 10); - if (!DS::getKeyboardEnable()) { - BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10); +// if (r != 255) + { + BG_PALETTE[r] = red | (green << 5) | (blue << 10); + if (!DS::getKeyboardEnable()) { + BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10); + } } // if (num == 16) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue); @@ -173,8 +177,8 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int u16* src = (u16 *) buf; if (DS::getKeyboardEnable()) { - for (int dy = y; dy < y + h; dy++) - { + + for (int dy = y; dy < y + h; dy++) { u16* dest = bg + (dy << 8) + (x >> 1); DC_FlushRange(src, w << 1); @@ -185,8 +189,7 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int } } else { - for (int dy = y; dy < y + h; dy++) - { + for (int dy = y; dy < y + h; dy++) { u16* dest1 = bg + (dy << 8) + (x >> 1); u16* dest2 = bgSub + (dy << 8) + (x >> 1); @@ -294,6 +297,7 @@ int16 OSystem_DS::getOverlayWidth() bool OSystem_DS::showMouse(bool visible) { + DS::setShowCursor(visible); return true; } @@ -302,7 +306,7 @@ void OSystem_DS::warpMouse(int x, int y) } void OSystem_DS::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetCursorScale) { - DS::setCursorIcon(buf, w, h, keycolor); + DS::setCursorIcon(buf, w, h, keycolor, hotspotX, hotspotY); } void OSystem_DS::addEvent(Common::Event& e) { @@ -323,11 +327,11 @@ bool OSystem_DS::pollEvent(Common::Event &event) event.kbd.ascii = 0; event.kbd.keycode = 0; event.kbd.flags = 0; - consolePrintf("type: %d\n", event.type); +// consolePrintf("type: %d\n", event.type); return false; } else { event = eventQueue[eventNum++]; - consolePrintf("type: %d\n", event.type); +// consolePrintf("type: %d\n", event.type); return true; } } @@ -474,36 +478,25 @@ Common::SaveFileManager* OSystem_DS::getSavefileManager() } } -Graphics::Surface *OSystem_DS::lockScreen() { - // For now, we create a full temporary screen surface, to which we copy the - // the screen content. Later unlockScreen will copy everything back. - // Not very nice nor efficient, but at least works, and is not worse - // than in the bad old times where we used grabRawScreen + copyRectToScreen. - - _framebuffer.create(DS::getGameWidth(), DS::getGameHeight(), 1); +bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) { + surf->create(DS::getGameWidth(), DS::getGameHeight(), 1); // Ensure we copy using 16 bit quantities due to limitation of VRAM addressing + size_t imageStrideInBytes = DS::isCpuScalerEnabled()? DS::getGameWidth() : 512; + size_t imageStrideInWords = imageStrideInBytes / 2; u16* image = (u16 *) DS::get8BitBackBuffer(); for (int y = 0; y < DS::getGameHeight(); y++) { - DC_FlushRange(image + (y << 8), DS::getGameWidth()); + DC_FlushRange(image + (y * imageStrideInWords), DS::getGameWidth()); for (int x = 0; x < DS::getGameWidth() >> 1; x++) { - *(((u16 *) (_framebuffer.pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y << 8 + x]; + *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y * imageStrideInWords + x]; } } - return &_framebuffer; -} - -void OSystem_DS::unlockScreen() { - // Copy temp framebuffer back to screen - copyRectToScreen((byte *)_framebuffer.pixels, _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h); - - // Free memory - _framebuffer.free(); + return true; } void OSystem_DS::setFocusRectangle(const Common::Rect& rect) { @@ -515,6 +508,18 @@ void OSystem_DS::clearFocusRectangle() { } +void OSystem_DS::addAutoComplete(const char *word) { + DS::addAutoComplete((char *) word); +} + +void OSystem_DS::clearAutoComplete() { + DS::clearAutoComplete(); +} + +void OSystem_DS::setCharactersEntered(int count) { + DS::setCharactersEntered(count); +} + OSystem *OSystem_DS_create() { return new OSystem_DS(); } diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 58b940af2c..d943a362ca 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -41,11 +41,12 @@ class DSTimerManager : public DefaultTimerManager { class OSystem_DS : public OSystem { public: + static OSystem_DS *instance() { return _instance; } int eventNum; int lastPenFrame; - Common::Event eventQueue[64]; + Common::Event eventQueue[96]; int queuePos; DSSaveFileManager saveManager; @@ -53,9 +54,8 @@ public: DSAudioMixer* _mixer; DSTimerManager* _timer; - Graphics::Surface _framebuffer; - static OSystem_DS* _instance; + typedef void (*SoundProc)(void *param, byte *buf, int len); typedef int (*TimerProc)(int interval); @@ -129,8 +129,7 @@ public: void addEvent(Common::Event& e); bool isEventQueueEmpty() { return queuePos == 0; } - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); + virtual bool grabRawScreen(Graphics::Surface* surf); virtual void setFocusRectangle(const Common::Rect& rect); @@ -141,6 +140,14 @@ public: virtual Audio::Mixer* getMixer() { return _mixer; } virtual Common::TimerManager* getTimerManager() { return _timer; } static int timerHandler(int t); + + + virtual void addAutoComplete(const char *word); + virtual void clearAutoComplete(); + virtual void setCharactersEntered(int count); + + + }; static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { @@ -162,9 +169,4 @@ void OSystem_DS::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) //consolePrintf("coltorgb\n"); } -namespace DS -{ -bool isCpuScalerEnabled(); -} - #endif diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp index 8f7af668d8..26f03ca9d1 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.cpp +++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp @@ -23,6 +23,7 @@ #include "touchkeyboard.h" #include "keyboard_raw.h" #include "keyboard_pal_raw.h" +#include "8x8font_tga_raw.h" #include "dsmain.h" #include "osystem_ds.h" @@ -127,11 +128,22 @@ int keyboardY; int mapBase; int tileBase; +u16* baseAddress; + bool shiftState; bool capsLockState; bool closed; +char autoCompleteWord[NUM_WORDS][32]; +int autoCompleteCount; + +char autoCompleteBuffer[128]; + +int selectedCompletion = -1; +int charactersEntered = 0; + + void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) { /* for (int r = 0; r < 32 * 32; r++) { ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = *saveSpace++; @@ -159,6 +171,26 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { BG_PALETTE_SUB[r] = ((u16 *) (keyboard_pal_raw))[r]; } + // this is the font + for (int tile = 0; tile < 94; tile++) { + + u16* tileAddr = (u16 *) (CHAR_BASE_BLOCK_SUB(tileBase) + (8192 + (tile * 32))); + u8* src = ((u8 *) (_8x8font_tga_raw)) + 18 + tile * 8; + + for (int y = 0 ; y < 8; y++) { + for (int x = 0; x < 2; x++) { + *(tileAddr + (y * 2) + x) =(*(src + (y * 752) + (x * 4) + 0) & 0x0F) + | ((*(src + (y * 752) + (x * 4) + 1) & 0x0F) << 4) + | ((*(src + (y * 752) + (x * 4) + 2) & 0x0F) << 8) + | ((*(src + (y * 752) + (x * 4) + 3) & 0x0F) << 12); + + } + } + } + + + + for (int r = 0; r < 16; r++) { int col = ((u16 *) (keyboard_pal_raw))[r]; @@ -167,17 +199,19 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { int blue = (col & 0x7C00) >> 10; red = (red * 8) / 16; - green = (green * 8) / 16; + green = (green * 24) / 16; blue = (blue * 8) / 16; + + if (green > 31) green = 31; BG_PALETTE_SUB[16 + r] = red | (green << 5) | (blue << 10); } keyboardX = -2; - keyboardY = 2; + keyboardY = 1; - mapBase = mapBase; - tileBase = tileBase; + DS::mapBase = mapBase; + DS::tileBase = tileBase; shiftState = false; capsLockState = false; @@ -186,6 +220,7 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { int y = keyboardY; u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase)); + baseAddress = base; for (int r = 0; r < DS_NUM_KEYS; r++) { base[(y + keys[r].y) * 32 + x + keys[r].x] = keys[r].keyNum * 2; @@ -198,6 +233,36 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { } closed = false; + clearAutoComplete(); +} + +void drawAutoComplete() { + + for (int y = 12; y < 24; y++) { + for (int x = 0; x < 32; x++) { + baseAddress[y * 32 + x] = 127; + } + } + + + for (int r = 0; r < autoCompleteCount; r++) { + int y = 12 + (r % 6) * 2; + int x = 0 + ((r / 6) * 16); + + for (int p = 0; p < strlen(autoCompleteWord[r]); p++) { + char c = autoCompleteWord[r][p]; + + int tile = c - 32 + 255; + + if (selectedCompletion == r) { + tile |= 0x1000; + } + + baseAddress[y * 32 + x + p] = tile; + + + } + } } bool getKeyboardClosed() { @@ -220,13 +285,106 @@ void setKeyHighlight(int key, bool highlight) { } } +void addAutoComplete(char* word) { + if (autoCompleteCount == NUM_WORDS) return; + strcpy(&autoCompleteWord[autoCompleteCount++][0], word); + drawAutoComplete(); +} + +void setCharactersEntered(int count) { + charactersEntered = count; +} + +void clearAutoComplete() { + autoCompleteCount = 0; + selectedCompletion = -1; + drawAutoComplete(); +} + +void typeCompletion(int current) { + Common::Event event; + OSystem_DS* system = OSystem_DS::instance(); + + strcat(autoCompleteBuffer, &autoCompleteWord[current][charactersEntered]); + strcat(autoCompleteBuffer, " "); + +/* consolePrintf("Typing word: %s\n", autoCompleteWord[current]); + + for (int r = charactersEntered; r < strlen(autoCompleteWord[current]); r++) { + event.kbd.keycode = autoCompleteWord[current][r]; + event.kbd.ascii = autoCompleteWord[current][r]; + event.type = Common::EVENT_KEYDOWN; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event); + } + + event.kbd.keycode = ' '; + event.kbd.ascii = ' '; + + event.type = Common::EVENT_KEYDOWN; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event);*/ +} + +void updateTypeEvents() +{ + if (autoCompleteBuffer[0] != '\0') + { + Common::Event event; + OSystem_DS* system = OSystem_DS::instance(); + + event.kbd.keycode = autoCompleteBuffer[0]; + event.kbd.ascii = autoCompleteBuffer[0]; + event.type = Common::EVENT_KEYDOWN; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event); + + for (int r = 0; r < strlen(autoCompleteBuffer); r++) + { + autoCompleteBuffer[r] = autoCompleteBuffer[r + 1]; + } + } +} + + void addKeyboardEvents() { + updateTypeEvents(); + if (DS::getPenDown()) { int x = IPC->touchXpx; int y = IPC->touchYpx; - int tx = (x >> 3) - keyboardX; - int ty = (y >> 3) - keyboardY; + int tx = (x >> 3); + int ty = (y >> 3); + + if (ty >= 12) { + int current = -1; + + if (tx < 12) { + current = (ty - 12) / 2; + } else { + current = 6 + (ty - 12) / 2; + } + + if (selectedCompletion == current) { + typeCompletion(current); + } else { + selectedCompletion = current; + } + + drawAutoComplete(); + } + + tx -= keyboardX; + ty -= keyboardY; // consolePrintf("x=%d y=%d\n", tx, ty); @@ -241,8 +399,14 @@ void addKeyboardEvents() { // Close button DS::closed = true; } else if ((keys[r].character >= '0') && (keys[r].character <= '9')) { - event.kbd.ascii = keys[r].character; - event.kbd.keycode = 0; + + if (!DS::shiftState) { + event.kbd.ascii = keys[r].character; + event.kbd.keycode = 0; + } else { + event.kbd.keycode = SDLK_F1 - (keys[r].character - '1'); + event.kbd.ascii = 0; + } } else if ((keys[r].character >= 'A') && (keys[r].character <= 'Z')) { diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h index e8f5fda37e..42051a1f11 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.h +++ b/backends/platform/ds/arm9/source/touchkeyboard.h @@ -25,11 +25,18 @@ namespace DS { +static const int NUM_WORDS = 12; + + void drawKeyboard(int tileBase, int mapBase, u16* saveSpace); void restoreVRAM(int tileBase, int mapBase, u16* saveSpace); void addKeyboardEvents(); bool getKeyboardClosed(); +void addAutoComplete(char* word); +void clearAutoComplete(); +void setCharactersEntered(int count); + } #endif diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp new file mode 100644 index 0000000000..a73656ea61 --- /dev/null +++ b/backends/platform/ds/arm9/source/wordcompletion.cpp @@ -0,0 +1,67 @@ +#include "wordcompletion.h" +#include "engines/agi/agi.h" +#include "osystem_ds.h" + +#ifndef DISABLE_AGI + +namespace DS { + +void findWordCompletions(char* input) { + int start = 0; + for (int r = strlen(input) - 1; r>0; r--) { + if (input[r] == ' ') { + start = r + 1; + break; + } + } + + char word[32]; + strcpy(word, &input[start]); + + int fchr = word[0] - 'a'; + int len = strlen(word); + + OSystem_DS* system = (OSystem_DS *) g_system; + system->clearAutoComplete(); + system->setCharactersEntered(strlen(word)); + + if (strlen(word) == 0) { + return; + } + + uint8 *wordList = Agi::AgiEngine::getWordsData(); + uint8 *wordListEnd = Agi::AgiEngine::getWordsData() + Agi::AgiEngine::getWordsDataSize(); + + /* Get the offset to the first word beginning with the + * right character + */ + wordList += READ_BE_UINT16(wordList + 2 * fchr); + + char currentWord[32]; + + + while (wordList < wordListEnd) { + int pos = *wordList++; // Number of chars to keep from previous word + + if (wordList == wordListEnd) + break; + + char c; + do { + c = *wordList++; + currentWord[pos++] = (~c) & 0x7F; + } while ((c & 0x80) == 0); // Top bit indicates end of word + currentWord[pos++] = '\0'; + + if (!strncmp(currentWord, word, strlen(word))) { + system->addAutoComplete(currentWord); + } + + wordList += 2; // Skip the two byte word id. + + } + +} + +} +#endif diff --git a/backends/platform/ds/arm9/source/wordcompletion.h b/backends/platform/ds/arm9/source/wordcompletion.h new file mode 100644 index 0000000000..b0d43713cc --- /dev/null +++ b/backends/platform/ds/arm9/source/wordcompletion.h @@ -0,0 +1,8 @@ + + + +namespace DS { + +extern void findWordCompletions(char* input); + +} \ No newline at end of file diff --git a/backends/platform/ds/arm9/source/zipreader.cpp b/backends/platform/ds/arm9/source/zipreader.cpp index 59f695ebce..0c86bd97ae 100644 --- a/backends/platform/ds/arm9/source/zipreader.cpp +++ b/backends/platform/ds/arm9/source/zipreader.cpp @@ -31,7 +31,7 @@ ZipFile::ZipFile() { // Locate a zip file in cartridge memory space - consolePrintf("ZIP file check..."); +// consolePrintf("ZIP file check..."); char* p = (char *) ZF_SEARCH_START; bool found = false; @@ -52,9 +52,9 @@ ZipFile::ZipFile() { } if (_zipFile) { - consolePrintf("Ok!\n"); + consolePrintf("ZIP File found Ok!\n"); } else { - consolePrintf("Not in use!\n"); +// consolePrintf("Not in use!\n"); return; } -- cgit v1.2.3