DS: Rewrite event handling

This commit is contained in:
Cameron Cawley 2020-08-06 15:04:24 +01:00 committed by Eugene Sandulenko
parent 1f8dc4d204
commit 438c2d8714
25 changed files with 267 additions and 2901 deletions

View File

@ -0,0 +1,102 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <nds.h>
#include "dsmain.h"
#include "backends/events/ds/ds-events.h"
bool DSEventSource::pollEvent(Common::Event &event) {
if (_eventQueue.empty()) {
if (!_firstPoll) {
_firstPoll = true;
return false;
}
addEventsToQueue();
if (_eventQueue.empty())
return false;
_firstPoll = false;
}
event = _eventQueue.pop();
if (Common::isMouseEvent(event)) {
g_system->warpMouse(event.mouse.x, event.mouse.y);
}
return true;
}
void DSEventSource::addJoyButtonEvent(u32 keysPressed, u32 keysReleased, u32 ndsKey, uint8 svmButton) {
if (keysPressed & ndsKey || keysReleased & ndsKey) {
Common::Event event;
event.type = (keysPressed & ndsKey) ? Common::EVENT_JOYBUTTON_DOWN : Common::EVENT_JOYBUTTON_UP;
event.joystick.button = svmButton;
_eventQueue.push(event);
}
}
void DSEventSource::addEventsToQueue() {
Common::Event event;
scanKeys();
uint32 held = keysHeld(), keysPressed = keysDown(), keysReleased = keysUp();
// Touch screen events
if (held & KEY_TOUCH) {
touchPosition touchPos;
touchRead(&touchPos);
event.mouse = DS::transformPoint(touchPos.px, touchPos.py);
if (keysPressed & KEY_TOUCH) {
event.type = Common::EVENT_LBUTTONDOWN;
_eventQueue.push(event);
} else if (event.mouse.x != _lastTouch.x || event.mouse.y != _lastTouch.y) {
event.type = Common::EVENT_MOUSEMOVE;
_eventQueue.push(event);
}
_lastTouch = event.mouse;
} else if (keysReleased & KEY_TOUCH) {
event.mouse = _lastTouch;
event.type = Common::EVENT_LBUTTONUP;
_eventQueue.push(event);
}
// Button events
addJoyButtonEvent(keysPressed, keysReleased, KEY_L, Common::JOYSTICK_BUTTON_LEFT_SHOULDER);
addJoyButtonEvent(keysPressed, keysReleased, KEY_R, Common::JOYSTICK_BUTTON_RIGHT_SHOULDER);
addJoyButtonEvent(keysPressed, keysReleased, KEY_A, Common::JOYSTICK_BUTTON_A);
addJoyButtonEvent(keysPressed, keysReleased, KEY_B, Common::JOYSTICK_BUTTON_B);
addJoyButtonEvent(keysPressed, keysReleased, KEY_X, Common::JOYSTICK_BUTTON_X);
addJoyButtonEvent(keysPressed, keysReleased, KEY_Y, Common::JOYSTICK_BUTTON_Y);
addJoyButtonEvent(keysPressed, keysReleased, KEY_UP, Common::JOYSTICK_BUTTON_DPAD_UP);
addJoyButtonEvent(keysPressed, keysReleased, KEY_DOWN, Common::JOYSTICK_BUTTON_DPAD_DOWN);
addJoyButtonEvent(keysPressed, keysReleased, KEY_LEFT, Common::JOYSTICK_BUTTON_DPAD_LEFT);
addJoyButtonEvent(keysPressed, keysReleased, KEY_RIGHT, Common::JOYSTICK_BUTTON_DPAD_RIGHT);
addJoyButtonEvent(keysPressed, keysReleased, KEY_START, Common::JOYSTICK_BUTTON_START);
addJoyButtonEvent(keysPressed, keysReleased, KEY_SELECT, Common::JOYSTICK_BUTTON_BACK);
}

View File

@ -20,18 +20,30 @@
*
*/
#ifndef _SCUMMHELP_H_
#define _SCUMMHELP_H_
#ifndef BACKEND_EVENTS_DS_H
#define BACKEND_EVENTS_DS_H
#include "common/ustr.h"
#include "common/platform.h"
#include "common/events.h"
namespace DS {
/**
* The Nintendo DS event source.
*/
class DSEventSource : public Common::EventSource {
public:
DSEventSource() : _firstPoll(true) {}
void updateStrings(byte gameId, byte version, Common::Platform platform,
int page, Common::U32String &title, Common::U32String *&key, Common::U32String *&dsc);
/**
* Gets and processes events.
*/
virtual bool pollEvent(Common::Event &event);
} // End of namespace DS
protected:
Common::Queue<Common::Event> _eventQueue;
Common::Point _lastTouch;
bool _firstPoll;
void addEventsToQueue();
void addJoyButtonEvent(u32 keysPressed, u32 keysReleased, u32 ndsKey, uint8 svmButton);
};
#endif

View File

@ -284,6 +284,7 @@ endif
ifeq ($(BACKEND),ds)
MODULE_OBJS += \
events/ds/ds-events.o \
fs/posix/posix-fs.o \
fs/posix/posix-fs-factory.o \
fs/posix/posix-iostream.o \

File diff suppressed because it is too large Load Diff

View File

@ -30,45 +30,6 @@
namespace DS {
enum controlType {
CONT_SCUMM_ORIGINAL,
CONT_SCUMM_SAMNMAX,
CONT_SKY,
CONT_SIMON,
CONT_FUTURE_WARS,
CONT_AGI,
CONT_GOBLINS,
CONT_NIPPON
};
struct gameListType {
char gameId[16];
controlType control;
};
// Pen reading functions
void penInit();
void penUpdate();
bool getPenDown();
bool getPenHeld();
bool getPenReleased();
int getPenX();
int getPenY();
GLvector getPenPos();
void consumePenEvents();
controlType getControlType();
// Pad reading
int getKeysHeld();
void keysUpdate();
int getKeysDown();
int getKeysReleased();
void consumeKeys();
int leftHandedSwap(int keys);
void setGameScreenSwap(bool enable);
void setSensitivity(int sensitivity);
// Video
void displayMode8Bit(); // Switch to 8-bit mode5
void displayMode16Bit(); // Switch to 16-bit mode5
@ -93,40 +54,25 @@ void setTimerCallback(OSystem_DS::TimerProc proc, int interval); // Setup a ca
int getMillis(bool skipRecord = false); // Return the current runtime in milliseconds
void doTimerCallback(); // Call callback function if required
// Event queue
void addEventsToQueue();
// Events
void VBlankHandler();
Common::Point transformPoint(uint16 x, uint16 y);
// Sam and Max Stuff
void setGameID(int id);
void setCursorIcon(const u8 *icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY);
void setShowCursor(bool enable);
void setMouseCursorVisible(bool visible);
void warpMouse(int penX, int penY);
void updateMouse();
// Shake
void setShakePos(int shakeXOffset, int shakeYOffset);
// Reports
void memoryReport();
// Virtual keyboard
void setKeyboardIcon(bool enable);
bool getKeyboardIcon();
void setKeyboardEnable(bool en);
bool getKeyboardEnable();
// Options
void setLeftHanded(bool enable);
void setTouchXOffset(int x);
void setTouchYOffset(int y);
void setGameScreenSwap(bool enable);
void setUnscaledMode(bool enable);
void setSnapToBorder(bool enable);
void setIndyFightState(bool st);
bool getIndyFightState();
bool isCpuScalerEnabled();
void setCpuScalerEnable(bool enable);
void setTrackPadStyleEnable(bool enable);
void setTapScreenClicksEnable(bool enable);
// Display
bool getIsDisplayMode8Bit();
@ -138,8 +84,6 @@ int getGameHeight();
void fastRamReset();
void* fastRamAlloc(int size);
void exitGame();
} // End of namespace DS

View File

@ -28,7 +28,6 @@
#include "gui/widgets/tab.h"
#include "osystem_ds.h"
#include "engines/scumm/scumm.h"
#include "touchkeyboard.h"
#include "gui/widgets/popup.h"
#include "common/translation.h"
@ -58,44 +57,10 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
_tab = new GUI::TabWidget(this, 10, 5, 300, 230 - 20 - 40 - 20);
_tab->addTab(_("Controls"), "");
_leftHandedCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 130, 20, _("~L~eft handed mode"));
_indyFightCheckbox = new GUI::CheckboxWidget(_tab, 5, 20, 140, 20, _("~I~ndy fight controls"));
_showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, _("Show mouse cursor"), U32String(), 0, 'T');
_snapToBorderCheckbox = new GUI::CheckboxWidget(_tab, 150, 20, 130, 20, _("Snap to edges"), U32String(), 0, 'T');
new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, _("Touch X Offset"), Graphics::kTextAlignLeft);
_touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, U32String("TODO: Add tooltip"), 1);
_touchX->setMinValue(-8);
_touchX->setMaxValue(+8);
_touchX->setValue(0);
_touchX->setFlags(GUI::WIDGET_CLEARBG);
new GUI::StaticTextWidget(_tab, 20, 50, 100, 15, _("Touch Y Offset"), Graphics::kTextAlignLeft);
_touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, U32String("TODO: Add tooltip"), 2);
_touchY->setMinValue(-8);
_touchY->setMaxValue(+8);
_touchY->setValue(0);
_touchY->setFlags(GUI::WIDGET_CLEARBG);
new GUI::StaticTextWidget(_tab, 130 + 65 - 10, 65, 20, 15, U32String("0"), Graphics::kTextAlignCenter);
new GUI::StaticTextWidget(_tab, 130 + 130 - 10, 65, 20, 15, U32String("8"), Graphics::kTextAlignCenter);
new GUI::StaticTextWidget(_tab, 130 - 20, 65, 20, 15, U32String("-8"), Graphics::kTextAlignCenter);
_touchPadStyle = new GUI::CheckboxWidget(_tab, 5, 80, 270, 20, _("Use laptop trackpad-style cursor control"), U32String(), 0x20000001, 'T');
_screenTaps = new GUI::CheckboxWidget(_tab, 5, 95, 285, 20, _("Tap for left click, double tap right click"), U32String(), 0x20000002, 'T');
_sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, _("Sensitivity"), Graphics::kTextAlignLeft);
_sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, U32String("TODO: Add tooltip"), 1);
_sensitivity->setMinValue(4);
_sensitivity->setMaxValue(16);
_sensitivity->setValue(8);
_sensitivity->setFlags(GUI::WIDGET_CLEARBG);
_tab->addTab(_("Graphics"), "");
_showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, _("Show mouse cursor"), U32String(), 0, 'T');
new GUI::StaticTextWidget(_tab, 5, 67, 180, 15, _("Initial top screen scale:"), Graphics::kTextAlignLeft);
_100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 82, 80, 20, U32String("100%"), U32String("TODO: Add tooltip"), 0x30000001, 'T');
@ -115,23 +80,11 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
_gammaCorrection->setValue(0);
_tab->addTab(_("General"), "");
_disablePowerOff = new GUI::CheckboxWidget(_tab, 5, 20, 200, 20, _("Disable power off"), U32String(), 0, 'T');
_tab->setActiveTab(0);
_radioButtonMode = false;
#ifdef DS_BUILD_D
_snapToBorderCheckbox->setState(confGetBool("snaptoborder", true));
#else
_snapToBorderCheckbox->setState(confGetBool("snaptoborder", false));
#endif
_showCursorCheckbox->setState(confGetBool("showcursor", true));
_leftHandedCheckbox->setState(confGetBool("lefthanded", false));
_unscaledCheckbox->setState(confGetBool("unscaled", false));
@ -171,26 +124,10 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
_gammaCorrection->setValue(0);
}
_disablePowerOff->setState(confGetBool("disablepoweroff", false));
#ifdef ALLOW_CPU_SCALER
_cpuScaler->setState(confGetBool("cpu_scaler", false));
#endif
_indyFightCheckbox->setState(DS::getIndyFightState());
_touchX->setValue(confGetInt("xoffset", 0));
_touchY->setValue(confGetInt("yoffset", 0));
_sensitivity->setValue(confGetInt("sensitivity", 8));
_touchPadStyle->setState(confGetBool("touchpad", false));
_screenTaps->setState(confGetBool("screentaps", false));
_screenTaps->setEnabled(!_touchPadStyle->getState());
_sensitivity->setEnabled(_touchPadStyle->getState());
_sensitivityLabel->setEnabled(_touchPadStyle->getState());
_sensitivityLabel->draw();
if (!_cpuScaler->getState() && !_unscaledCheckbox->getState()) {
_hardScaler->setState(true);
}
@ -199,27 +136,18 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
}
DSOptionsDialog::~DSOptionsDialog() {
DS::setIndyFightState(_indyFightCheckbox->getState());
ConfMan.flushToDisk();
}
void DSOptionsDialog::updateConfigManager() {
ConfMan.setBool("lefthanded", _leftHandedCheckbox->getState(), "ds");
ConfMan.setBool("unscaled", _unscaledCheckbox->getState(), "ds");
ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds");
#ifdef ALLOW_CPU_SCALER
ConfMan.setBool("cpu_scaler", _cpuScaler->getState(), "ds");
#endif
ConfMan.setInt("xoffset", _touchX->getValue(), "ds");
ConfMan.setInt("yoffset", _touchY->getValue(), "ds");
ConfMan.setBool("showcursor", _showCursorCheckbox->getState(), "ds");
ConfMan.setBool("snaptoborder", _snapToBorderCheckbox->getState(), "ds");
ConfMan.setBool("touchpad", _touchPadStyle->getState(), "ds");
ConfMan.setBool("screentaps", _screenTaps->getState(), "ds");
ConfMan.setInt("sensitivity", _sensitivity->getValue(), "ds");
ConfMan.setInt("gamma", _gammaCorrection->getValue(), "ds");
u32 zoomLevel = 150;
int zoomLevel = 150;
if (_100PercentCheckbox->getState()) {
zoomLevel = 100;
@ -266,39 +194,6 @@ void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint
}
if ((!guard) && (_radioButtonMode)) {
guard = true;
if ((sender == _touchPadStyle) && (cmd == 0x20000001)) {
if (_touchPadStyle->getState()) {
// Swap screens when turning on trackpad style, it feels
// much more natural!
DS::setGameScreenSwap(true);
_screenTaps->setState(true);
_screenTaps->setEnabled(false);
_screenTaps->draw();
_sensitivity->setEnabled(true);
_sensitivityLabel->setEnabled(true);
_sensitivityLabel->draw();
_sensitivity->draw();
} else {
DS::setGameScreenSwap(false);
_screenTaps->setEnabled(true);
_screenTaps->setState(false);
_screenTaps->draw();
_sensitivity->setEnabled(false);
_sensitivityLabel->setEnabled(false);
_sensitivityLabel->draw();
_sensitivity->draw();
}
}
guard = false;
}
if ((!guard) && (_radioButtonMode)) {
guard = true;
@ -361,15 +256,8 @@ void setOptions() {
ConfMan.addGameDomain("ds");
DS::setLeftHanded(confGetBool("lefthanded", false));
DS::setMouseCursorVisible(confGetBool("showcursor", true));
#ifdef DS_BUILD_D
DS::setSnapToBorder(confGetBool("snaptoborder", true));
#else
DS::setSnapToBorder(confGetBool("snaptoborder", false));
#endif
DS::setUnscaledMode(confGetBool("unscaled", false));
if (firstLoad) {
@ -384,39 +272,12 @@ void setOptions() {
}
}
DS::setTouchXOffset(confGetInt("xoffset", 0));
DS::setTouchYOffset(confGetInt("yoffset", 0));
DS::setSensitivity(confGetInt("sensitivity", 8));
#ifdef ALLOW_CPU_SCALER
DS::setCpuScalerEnable(confGetBool("cpu_scaler", false));
#endif
DS::setTapScreenClicksEnable(confGetBool("screentaps", false));
DS::setGamma(confGetInt("gamma", 0));
if (ConfMan.hasKey("touchpad", "ds")) {
bool enable = ConfMan.getBool("touchpad", "ds");
DS::setTrackPadStyleEnable(enable);
if (enable && firstLoad) {
// If we've just booted up, want to swap screens when trackpad mode is in use
// but not every time we enter the options dialog.
DS::setGameScreenSwap(true);
}
if (enable) {
DS::setTapScreenClicksEnable(true);
}
} else {
DS::setTrackPadStyleEnable(false);
}
firstLoad = false;
}

View File

@ -51,28 +51,16 @@ protected:
GUI::TabWidget *_tab;
GUI::StaticTextWidget *_sensitivityLabel;
GUI::SliderWidget *_touchX;
GUI::SliderWidget *_touchY;
GUI::SliderWidget *_sensitivity;
GUI::SliderWidget *_gammaCorrection;
GUI::CheckboxWidget *_leftHandedCheckbox;
GUI::CheckboxWidget *_unscaledCheckbox;
GUI::CheckboxWidget *_100PercentCheckbox;
GUI::CheckboxWidget *_150PercentCheckbox;
GUI::CheckboxWidget *_200PercentCheckbox;
GUI::CheckboxWidget *_indyFightCheckbox;
GUI::CheckboxWidget *_disablePowerOff;
GUI::CheckboxWidget *_showCursorCheckbox;
GUI::CheckboxWidget *_snapToBorderCheckbox;
GUI::CheckboxWidget *_hardScaler;
GUI::CheckboxWidget *_cpuScaler;
GUI::CheckboxWidget *_touchPadStyle;
GUI::CheckboxWidget *_screenTaps;
bool _radioButtonMode;
};

View File

@ -33,6 +33,7 @@
#include "common/util.h"
#include "common/rect.h"
#include "common/savefile.h"
#include "common/translation.h"
#include "osystem_ds.h"
#include "nds.h"
@ -40,23 +41,20 @@
#include "common/config-manager.h"
#include "common/str.h"
#include "graphics/surface.h"
#include "touchkeyboard.h"
#include "backends/fs/devoptab/devoptab-fs-factory.h"
#include "backends/keymapper/hardware-input.h"
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/events/default/default-events.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
#ifdef ENABLE_AGI
#include "wordcompletion.h"
#endif
#include <time.h>
OSystem_DS *OSystem_DS::_instance = NULL;
OSystem_DS::OSystem_DS()
: eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _frameBufferExists(false),
: _eventSource(NULL), _mixer(NULL), _frameBufferExists(false),
_disableCursorPalette(true), _graphicsEnable(true), _gammaValue(0)
{
_instance = this;
@ -78,6 +76,9 @@ void OSystem_DS::initBackend() {
ConfMan.setInt("autosave_period", 0);
ConfMan.setBool("FM_medium_quality", true);
_eventSource = new DSEventSource();
_eventManager = new DefaultEventManager(_eventSource);
_savefileManager = new DefaultSaveFileManager();
_timerManager = new DefaultTimerManager();
DS::setTimerCallback(&OSystem_DS::timerHandler, 10);
@ -85,25 +86,21 @@ void OSystem_DS::initBackend() {
_mixer = new Audio::MixerImpl(11025);
_mixer->setReady(true);
EventsBaseBackend::initBackend();
BaseBackend::initBackend();
}
bool OSystem_DS::hasFeature(Feature f) {
return (f == kFeatureVirtualKeyboard) || (f == kFeatureCursorPalette);
return (f == kFeatureCursorPalette);
}
void OSystem_DS::setFeatureState(Feature f, bool enable) {
if (f == kFeatureVirtualKeyboard)
DS::setKeyboardIcon(enable);
else if (f == kFeatureCursorPalette) {
if (f == kFeatureCursorPalette) {
_disableCursorPalette = !enable;
refreshCursor();
}
}
bool OSystem_DS::getFeatureState(Feature f) {
if (f == kFeatureVirtualKeyboard)
return DS::getKeyboardIcon();
if (f == kFeatureCursorPalette)
return !_disableCursorPalette;
return false;
@ -145,10 +142,7 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
if (DS::getIsDisplayMode8Bit()) {
int col = applyGamma(paletteValue);
BG_PALETTE[r] = col;
if (!DS::getKeyboardEnable()) {
BG_PALETTE_SUB[r] = col;
}
BG_PALETTE_SUB[r] = col;
}
_palette[r] = paletteValue;
@ -164,9 +158,7 @@ void OSystem_DS::restoreHardwarePalette() {
for (int r = 0; r < 255; r++) {
int col = applyGamma(_palette[r]);
BG_PALETTE[r] = col;
if (!DS::getKeyboardEnable()) {
BG_PALETTE_SUB[r] = col;
}
BG_PALETTE_SUB[r] = col;
}
}
@ -230,115 +222,59 @@ void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int
int by = 0;
if (DS::getKeyboardEnable()) {
// When they keyboard is on screen, we don't update the subscreen because
// the keyboard image uses the same VRAM addresses.
for (int dy = y; dy < y + h; dy++) {
u8 *dest = ((u8 *) (bg)) + (dy * stride) + x;
u8 *destSub = ((u8 *) (bgSub)) + (dy * 512) + x;
const u8 *src = (const u8 *) buf + (pitch * by);
for (int dy = y; dy < y + h; dy++) {
u8 *dest = ((u8 *) (bg)) + (dy * stride) + x;
const u8 *src = (const u8 *) buf + (pitch * by);
u32 dx;
u32 dx;
u32 pixelsLeft = w;
u32 pixelsLeft = w;
if (MISALIGNED16(dest)) {
// Read modify write
if (MISALIGNED16(dest)) {
// Read modify write
dest--;
u16 mix = *((u16 *) dest);
dest--;
u16 mix = *((u16 *) dest);
mix = (mix & 0x00FF) | (*src++ << 8);
mix = (mix & 0x00FF) | (*src++ << 8);
*dest = mix;
*destSub = mix;
*dest = mix;
dest += 2;
pixelsLeft--;
}
// We can now assume dest is aligned
u16 *dest16 = (u16 *) dest;
for (dx = 0; dx < pixelsLeft; dx+=2) {
u16 mix;
mix = *src + (*(src + 1) << 8);
*dest16++ = mix;
src += 2;
}
pixelsLeft -= dx;
// At the end we may have one pixel left over
if (pixelsLeft != 0) {
u16 mix = *dest16;
mix = (mix & 0x00FF) | ((*src++) << 8);
*dest16 = mix;
}
by++;
dest += 2;
destSub += 2;
pixelsLeft--;
}
} else {
// When they keyboard is not on screen, update both vram copies
// We can now assume dest is aligned
u16 *dest16 = (u16 *) dest;
u16 *destSub16 = (u16 *) destSub;
for (int dy = y; dy < y + h; dy++) {
u8 *dest = ((u8 *) (bg)) + (dy * stride) + x;
u8 *destSub = ((u8 *) (bgSub)) + (dy * 512) + x;
const u8 *src = (const u8 *) buf + (pitch * by);
u32 dx;
u32 pixelsLeft = w;
if (MISALIGNED16(dest)) {
// Read modify write
dest--;
u16 mix = *((u16 *) dest);
mix = (mix & 0x00FF) | (*src++ << 8);
*dest = mix;
*destSub = mix;
dest += 2;
destSub += 2;
pixelsLeft--;
}
// We can now assume dest is aligned
u16 *dest16 = (u16 *) dest;
u16 *destSub16 = (u16 *) destSub;
for (dx = 0; dx < pixelsLeft; dx+=2) {
u16 mix;
mix = *src + (*(src + 1) << 8);
*dest16++ = mix;
*destSub16++ = mix;
src += 2;
}
pixelsLeft -= dx;
// At the end we may have one pixel left over
if (pixelsLeft != 0) {
u16 mix = *dest16;
mix = (mix & 0x00FF) | ((*src++) << 8);
*dest16 = mix;
*destSub16 = mix;
}
by++;
for (dx = 0; dx < pixelsLeft; dx+=2) {
u16 mix;
mix = *src + (*(src + 1) << 8);
*dest16++ = mix;
*destSub16++ = mix;
src += 2;
}
pixelsLeft -= dx;
// At the end we may have one pixel left over
if (pixelsLeft != 0) {
u16 mix = *dest16;
mix = (mix & 0x00FF) | ((*src++) << 8);
*dest16 = mix;
*destSub16 = mix;
}
by++;
}
} else {
@ -347,39 +283,23 @@ void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int
u16 *src = (u16 *) buf;
if (DS::getKeyboardEnable()) {
for (int dy = y; dy < y + h; dy++) {
u16 *dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
u16 *dest2 = bgSub + (dy << 8) + (x >> 1);
for (int dy = y; dy < y + h; dy++) {
u16 *dest = bg + (dy * (stride >> 1)) + (x >> 1);
DC_FlushRange(src, w << 1);
DC_FlushRange(dest1, w << 1);
DC_FlushRange(dest2, w << 1);
DC_FlushRange(src, w << 1);
DC_FlushRange(dest, w << 1);
dmaCopyHalfWords(3, src, dest, w);
dmaCopyHalfWords(3, src, dest1, w);
while (dmaBusy(3));
src += pitch >> 1;
if ((!_frameBufferExists) || (buf == _framebuffer.getPixels())) {
dmaCopyHalfWords(2, src, dest2, w);
}
} else {
for (int dy = y; dy < y + h; dy++) {
u16 *dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
u16 *dest2 = bgSub + (dy << 8) + (x >> 1);
while (dmaBusy(2) || dmaBusy(3));
DC_FlushRange(src, w << 1);
DC_FlushRange(dest1, w << 1);
DC_FlushRange(dest2, w << 1);
dmaCopyHalfWords(3, src, dest1, w);
if ((!_frameBufferExists) || (buf == _framebuffer.getPixels())) {
dmaCopyHalfWords(2, src, dest2, w);
}
while (dmaBusy(2) || dmaBusy(3));
src += pitch >> 1;
}
src += pitch >> 1;
}
}
}
@ -393,13 +313,12 @@ void OSystem_DS::updateScreen() {
}
DS::displayMode16BitFlipBuffer();
DS::addEventsToQueue();
// FIXME: Evil game specific hack.
// Force back buffer usage for Nippon Safes, as it doesn't double buffer it's output
if (DS::getControlType() == DS::CONT_NIPPON) {
lockScreen();
}
// if (DS::getControlType() == DS::CONT_NIPPON) {
// lockScreen();
// }
}
void OSystem_DS::setShakePos(int shakeXOffset, int shakeYOffset) {
@ -466,6 +385,7 @@ bool OSystem_DS::showMouse(bool visible) {
}
void OSystem_DS::warpMouse(int x, int y) {
DS::warpMouse(x, y);
}
void OSystem_DS::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, u32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
@ -487,45 +407,16 @@ void OSystem_DS::refreshCursor() {
DS::setCursorIcon(_cursorImage, _cursorW, _cursorH, _cursorKey, _cursorHotX, _cursorHotY);
}
void OSystem_DS::addEvent(const Common::Event& e) {
eventQueue[queuePos++] = e;
}
bool OSystem_DS::pollEvent(Common::Event &event) {
if (lastPenFrame != DS::getMillis()) {
if (eventNum == queuePos) {
eventNum = 0;
queuePos = 0;
// Bodge - this last event seems to be processed sometimes and not others.
// So we make it something harmless which won't cause any adverse effects.
event.type = Common::EVENT_KEYUP;
event.kbd.ascii = 0;
event.kbd.keycode = Common::KEYCODE_INVALID;
event.kbd.flags = 0;
return false;
} else {
event = eventQueue[eventNum++];
return true;
}
}
return false;
}
uint32 OSystem_DS::getMillis(bool skipRecord) {
return DS::getMillis();
}
void OSystem_DS::delayMillis(uint msecs) {
int st = getMillis();
DS::addEventsToQueue();
while (st + msecs >= getMillis());
DS::doTimerCallback();
DS::addEventsToQueue();
}
@ -627,19 +518,6 @@ void OSystem_DS::clearFocusRectangle() {
}
void OSystem_DS::addAutoComplete(const char *word) {
DS::addAutoComplete(word);
}
void OSystem_DS::clearAutoComplete() {
DS::clearAutoComplete();
}
void OSystem_DS::setCharactersEntered(int count) {
DS::setCharactersEntered(count);
}
void OSystem_DS::logMessage(LogMessageType::Type type, const char *message) {
#ifndef DISABLE_TEXT_CONSOLE
nocashMessage((char *)message);
@ -673,11 +551,38 @@ u16 OSystem_DS::applyGamma(u16 color) {
return 0x8000 | r | (g << 5) | (b << 10);
}
void OSystem_DS::engineDone() {
DS::exitGame();
static const Common::HardwareInputTableEntry ndsJoystickButtons[] = {
{ "JOY_A", Common::JOYSTICK_BUTTON_A, _s("A") },
{ "JOY_B", Common::JOYSTICK_BUTTON_B, _s("B") },
{ "JOY_X", Common::JOYSTICK_BUTTON_X, _s("X") },
{ "JOY_Y", Common::JOYSTICK_BUTTON_Y, _s("Y") },
{ "JOY_BACK", Common::JOYSTICK_BUTTON_BACK, _s("Select") },
{ "JOY_START", Common::JOYSTICK_BUTTON_START, _s("Start") },
{ "JOY_LEFT_SHOULDER", Common::JOYSTICK_BUTTON_LEFT_SHOULDER, _s("L") },
{ "JOY_RIGHT_SHOULDER", Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("R") },
{ "JOY_UP", Common::JOYSTICK_BUTTON_DPAD_UP, _s("D-pad Up") },
{ "JOY_DOWN", Common::JOYSTICK_BUTTON_DPAD_DOWN, _s("D-pad Down") },
{ "JOY_LEFT", Common::JOYSTICK_BUTTON_DPAD_LEFT, _s("D-pad Left") },
{ "JOY_RIGHT", Common::JOYSTICK_BUTTON_DPAD_RIGHT, _s("D-pad Right") },
{ nullptr, 0, nullptr }
};
#ifdef ENABLE_AGI
DS::clearAutoCompleteWordList();
#endif
static const Common::AxisTableEntry ndsJoystickAxes[] = {
{ nullptr, 0, Common::kAxisTypeFull, nullptr }
};
const Common::HardwareInputTableEntry ndsMouseButtons[] = {
{ "MOUSE_LEFT", Common::MOUSE_BUTTON_LEFT, _s("Touch") },
{ nullptr, 0, nullptr }
};
Common::HardwareInputSet *OSystem_DS::getHardwareInputSet() {
using namespace Common;
CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
// Touch input sends mouse events for now, so we need to declare we have a mouse...
inputSet->addHardwareInputSet(new MouseHardwareInputSet(ndsMouseButtons));
inputSet->addHardwareInputSet(new JoystickHardwareInputSet(ndsJoystickButtons, ndsJoystickAxes));
return inputSet;
}

View File

@ -29,21 +29,14 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#include "backends/base-backend.h"
#include "common/events.h"
#include "backends/events/ds/ds-events.h"
#include "nds.h"
#include "audio/mixer_intern.h"
#include "graphics/surface.h"
#include "graphics/palette.h"
class OSystem_DS : public EventsBaseBackend, public PaletteManager {
class OSystem_DS : public BaseBackend, public PaletteManager {
protected:
int eventNum;
int lastPenFrame;
Common::Event eventQueue[96];
int queuePos;
Audio::MixerImpl *_mixer;
Graphics::Surface _framebuffer;
bool _frameBufferExists;
@ -62,6 +55,7 @@ protected:
byte _cursorKey;
int _cursorScale;
DSEventSource *_eventSource;
Graphics::Surface *createTempFrameBuffer();
bool _disableCursorPalette;
@ -111,11 +105,13 @@ public:
virtual void warpMouse(int x, int y);
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, u32 keycolor, bool dontScale, const Graphics::PixelFormat *format);
virtual bool pollEvent(Common::Event &event);
virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual void getTimeAndDate(TimeDate &t) const;
virtual Common::EventSource *getDefaultEventSource() { return _eventSource; }
virtual Common::HardwareInputSet *getHardwareInputSet();
virtual MutexRef createMutex(void);
virtual void lockMutex(MutexRef mutex);
virtual void unlockMutex(MutexRef mutex);
@ -123,9 +119,6 @@ public:
virtual void quit();
void addEvent(const Common::Event& e);
bool isEventQueueEmpty() const { return queuePos == 0; }
virtual void setFocusRectangle(const Common::Rect& rect);
virtual void clearFocusRectangle();
@ -139,11 +132,6 @@ public:
static int timerHandler(int t);
virtual void addAutoComplete(const char *word);
virtual void clearAutoComplete();
virtual void setCharactersEntered(int count);
u16 getDSPaletteEntry(u32 entry) const { return _palette[entry]; }
u16 getDSCursorPaletteEntry(u32 entry) const { return !_disableCursorPalette? _cursorPalette[entry]: _palette[entry]; }
@ -155,8 +143,6 @@ public:
u16 applyGamma(u16 color);
void setGammaValue(int gamma) { _gammaValue = gamma; }
void engineDone();
};
#endif

View File

@ -1,101 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "scummhelp.h"
#include "common/translation.h"
#define ADD_BIND(k,d) do { key[i] = k; dsc[i] = d; i++; } while (0)
#define ADD_TEXT(d) ADD_BIND("",d)
#define ADD_LINE ADD_BIND("","")
#define HELP_NUM_LINES 15
namespace DS {
void updateStrings(byte gameId, byte version, Common::Platform platform,
int page, Common::U32String &title, Common::U32String *&key, Common::U32String *&dsc) {
key = new Common::U32String[HELP_NUM_LINES];
dsc = new Common::U32String[HELP_NUM_LINES];
int i = 0;
switch (page) {
case 1: {
title = _("DS Controls (right handed):");
ADD_BIND(_("Pad Left"), _("Left mouse button"));
ADD_BIND(_("Pad Right"), _("Right mouse button"));
ADD_BIND(_("Pad Up"), _("Mouse hover mode (no click)"));
ADD_BIND(_("Pad Down"), _("Skip dialog line (some games)"));
ADD_BIND(_("Start"), _("Pause/Game menu"));
ADD_BIND(_("Select"), _("DS Options menu"));
ADD_BIND("B", _("Skip cutscenes"));
ADD_BIND("A", _("Switch screens"));
ADD_BIND("Y", _("Show/hide debug console"));
ADD_BIND("X", _("Show/hide keyboard"));
ADD_BIND("L+Pad/Pen", _("Scroll current touch screen view"));
ADD_BIND("L+B/A", _("Zoom in/out"));
break;
}
case 2: {
title = _("DS Controls (left handed):");
ADD_BIND("Y", _("Left mouse button"));
ADD_BIND("A", _("Right mouse button"));
ADD_BIND("X", _("Mouse hover mode (no click)"));
ADD_BIND("B", _("Skip dialog line (some games)"));
ADD_BIND(_("Start"), _("Pause/Game menu"));
ADD_BIND(_("Select"), _("DS Options menu"));
ADD_BIND(_("Pad Down"), _("Skip cutscenes"));
ADD_BIND(_("Pad Up"), _("Show/hide keyboard"));
ADD_BIND(_("Pad Left"), _("Show/hide debug console"));
ADD_BIND(_("Pad Right"), _("Swap screens"));
ADD_BIND("R+Pad/Pen", _("Scroll current touch screen view"));
ADD_BIND("R+dwn/rgt", _("Zoom in/out"));
break;
}
case 3: {
title = _("Indiana Jones Fight controls:");
ADD_BIND(_("Pad Left"), _("Move left"));
ADD_BIND(_("Pad Right"), _("Move right"));
ADD_BIND(_("Pad Up"), _("High guard"));
ADD_BIND(_("Pad Down"), _("Guard down"));
ADD_BIND("Y", _("Guard middle"));
ADD_BIND("X", _("Punch high"));
ADD_BIND("A", _("Punch middle"));
ADD_BIND("B", _("Punch low"));
break;
}
}
while (i < HELP_NUM_LINES) {
ADD_LINE;
}
}
} // End of namespace DS
#undef ADD_BIND
#undef ADD_TEXT
#undef ADD_LINE

View File

@ -1,538 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <nds.h>
#include "touchkeyboard.h"
#include "keyboard_raw.h"
#include "keyboard_pal_raw.h"
#include "8x8font_tga_raw.h"
#include "dsmain.h"
#include "osystem_ds.h"
namespace DS {
struct key_data {
char keyNum;
signed char x, y;
int character;
bool pressed;
};
#define DS_NUM_KEYS 72
#define DS_SHIFT 2
#define DS_BACKSPACE 8
#define DS_RETURN 13
#define DS_CAPSLOCK 1
static key_data keys[DS_NUM_KEYS] = {
// Key number x y character
// Numbers
{28, 3, 0, '1', false},
{29, 5, 0, '2', false},
{30, 7, 0, '3', false},
{31, 9, 0, '4', false},
{32, 11, 0, '5', false},
{33, 13, 0, '6', false},
{34, 15, 0, '7', false},
{35, 17, 0, '8', false},
{36, 19, 0, '9', false},
{27, 21, 0, '0', false},
{45, 23, 0, Common::KEYCODE_MINUS, false},
{50, 25, 0, Common::KEYCODE_EQUALS, false},
{52, 27, 0, Common::KEYCODE_BACKSPACE, false},
// Top row
{'Q'-'A' + 1, 4, 2, 'Q', false},
{'W'-'A' + 1, 6, 2, 'W', false},
{'E'-'A' + 1, 8, 2, 'E', false},
{'R'-'A' + 1, 10, 2, 'R', false},
{'T'-'A' + 1, 12, 2, 'T', false},
{'Y'-'A' + 1, 14, 2, 'Y', false},
{'U'-'A' + 1, 16, 2, 'U', false},
{'I'-'A' + 1, 18, 2, 'I', false},
{'O'-'A' + 1, 20, 2, 'O', false},
{'P'-'A' + 1, 22, 2, 'P', false},
{43, 24, 2, Common::KEYCODE_LEFTBRACKET, false},
{44, 26, 2, Common::KEYCODE_RIGHTBRACKET, false},
// Middle row
{55, 3, 4, DS_CAPSLOCK, false},
{'A'-'A' + 1, 5, 4, 'A', false},
{'S'-'A' + 1, 7, 4, 'S', false},
{'D'-'A' + 1, 9, 4, 'D', false},
{'F'-'A' + 1, 11, 4, 'F', false},
{'G'-'A' + 1, 13, 4, 'G', false},
{'H'-'A' + 1, 15, 4, 'H', false},
{'J'-'A' + 1, 17, 4, 'J', false},
{'K'-'A' + 1, 19, 4, 'K', false},
{'L'-'A' + 1, 21, 4, 'L', false},
{42, 23, 4, Common::KEYCODE_SEMICOLON, false},
{41, 25, 4, Common::KEYCODE_QUOTE, false},
{46, 27, 4, Common::KEYCODE_RETURN, false},
// Bottom row
{51, 4, 6, DS_SHIFT, false},
{'Z'-'A' + 1, 6, 6, 'Z', false},
{'X'-'A' + 1, 8, 6, 'X', false},
{'C'-'A' + 1, 10, 6, 'C', false},
{'V'-'A' + 1, 12, 6, 'V', false},
{'B'-'A' + 1, 14, 6, 'B', false},
{'N'-'A' + 1, 16, 6, 'N', false},
{'M'-'A' + 1, 18, 6, 'M', false},
{38, 20, 6, Common::KEYCODE_COMMA, false},
{39, 22, 6, Common::KEYCODE_PERIOD, false},
{40, 24, 6, Common::KEYCODE_SLASH, false},
// Space bar
{47, 9, 8, Common::KEYCODE_SPACE, false},
{48, 11, 8, Common::KEYCODE_SPACE, false},
{48, 13, 8, Common::KEYCODE_SPACE, false},
{48, 15, 8, Common::KEYCODE_SPACE, false},
{48, 17, 8, Common::KEYCODE_SPACE, false},
{49, 19, 8, Common::KEYCODE_SPACE, false},
// Cursor arrows
{52, 27, 8, Common::KEYCODE_LEFT, false},
{54, 29, 8, Common::KEYCODE_DOWN, false},
{53, 31, 8, Common::KEYCODE_RIGHT, false},
{51, 29, 6, Common::KEYCODE_UP, false},
// Close button
{56, 30, 0, Common::KEYCODE_INVALID, false},
// Function keys (needed for AGI)
{57, 4, -2, Common::KEYCODE_F1, false},
{58, 6, -2, Common::KEYCODE_F2, false},
{59, 8, -2, Common::KEYCODE_F3, false},
{60, 10, -2, Common::KEYCODE_F4, false},
{61, 14, -2, Common::KEYCODE_F5, false},
{62, 16, -2, Common::KEYCODE_F6, false},
{63, 18, -2, Common::KEYCODE_F7, false},
{64, 20, -2, Common::KEYCODE_F8, false},
{65, 24, -2, Common::KEYCODE_F9, false},
{66, 26, -2, Common::KEYCODE_F10, false},
{67, 28, -2, Common::KEYCODE_F11, false},
{68, 30, -2, Common::KEYCODE_F12, false},
};
static int keyboardX;
static int keyboardY;
static int s_mapBase;
static int s_tileBase;
static u16 *baseAddress;
static bool shiftState;
static bool capsLockState;
static bool closed;
static char autoCompleteWord[NUM_WORDS][32];
static int autoCompleteCount;
static char autoCompleteBuffer[128];
static int selectedCompletion = -1;
static int charactersEntered = 0;
static int typingTimeout = 0;
// Render text onto the tiled screen
void drawText(int tx, int ty, const char *string, bool highlight) {
u16 baseValue = 0;
if (highlight) {
baseValue |= 0x1000;
}
for (int p = 0; *string; string++, p++) {
char c = *string;
if (c != ' ') {
int tile = c - 33 + (KEYBOARD_DATA_SIZE / 32);
baseAddress[ty * 32 + tx + p] = baseValue | tile;
}
}
}
void drawKeyboard(int tileBase, int mapBase, u16 *saveSpace) {
for (int r = 0; r < 32 * 32; r++) {
((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = 0;
}
for (int r = 0; r < KEYBOARD_DATA_SIZE / 2; r++) {
((u16 *) CHAR_BASE_BLOCK_SUB(tileBase))[r] = ((u16 *) (::keyboard_raw))[r];
}
for (int r = 0; r < 16; r++) {
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) + ((KEYBOARD_DATA_SIZE) + (tile * 32)));
const u8 *src = ((const 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];
int red = col & 0x001F;
int green = (col & 0x03E0) >> 5;
int blue = (col & 0x7C00) >> 10;
red = (red * 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;
DS::s_mapBase = mapBase;
DS::s_tileBase = tileBase;
shiftState = false;
capsLockState = false;
int x = keyboardX;
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] = 10 + keys[r].keyNum * 2;
base[(y + keys[r].y) * 32 + x + keys[r].x + 1] = 10 + keys[r].keyNum * 2 + 1;
base[(y + keys[r].y + 1) * 32 + x + keys[r].x] = 10 + 148 + keys[r].keyNum * 2;
base[(y + keys[r].y + 1) * 32 + x + keys[r].x + 1] = 10 + 148 + keys[r].keyNum * 2 + 1;
keys[r].pressed = false;
}
closed = false;
clearAutoComplete();
}
void drawAutoComplete() {
// Clear the auto complete area at the bottom of the screen.
for (int y = 12; y < 24; y++) {
for (int x = 0; x < 32; x++) {
baseAddress[y * 32 + x] = 0;
}
}
if ((autoCompleteCount == 0) || (typingTimeout > 0)) {
// When there's no completions on the bottom of the screen, it acts like a mouse pad
// so this text indicates that
drawText(11, 18, "MOUSE AREA", true);
} else {
printf("time: %d\n", typingTimeout);
// Otherwise, draw autocompletions if one isn't being entered and there are
// some available.
for (int r = 0; r < autoCompleteCount; r++) {
int y = 12 + (r % 6) * 2;
int x = 0 + ((r / 6) * 16);
drawText(x, y, autoCompleteWord[r], selectedCompletion == r);
}
}
}
bool getKeyboardClosed() {
return closed;
}
void setKeyHighlight(int key, bool highlight) {
u16 *base = ((u16 *) SCREEN_BASE_BLOCK_SUB(DS::s_mapBase));
if (highlight) {
base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x] |= 0x1000;
base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x + 1] |= 0x1000;
base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x] |= 0x1000;
base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x + 1] |= 0x1000;
} else {
base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x] &= ~0x1000;
base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x + 1] &= ~0x1000;
base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x] &= ~0x1000;
base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x + 1] &= ~0x1000;
}
}
void addAutoComplete(const char *word) {
if (autoCompleteCount == NUM_WORDS) return;
strcpy(&autoCompleteWord[autoCompleteCount++][0], word);
drawAutoComplete();
}
void setCharactersEntered(int count) {
charactersEntered = count;
}
bool isInsideKeyboard(int x, int y) {
// When completions are available, keyboard covers the whole screen.
// otherwise, it only covers the area above KEYBOARD_BOTTOM_Y
return (autoCompleteCount > 0) || (y < KEYBOARD_BOTTOM_Y);
}
void clearAutoComplete() {
autoCompleteCount = 0;
selectedCompletion = -1;
drawAutoComplete();
}
void typeCompletion(int current) {
Common::Event event;
strcat(autoCompleteBuffer, &autoCompleteWord[current][charactersEntered]);
strcat(autoCompleteBuffer, " ");
}
void updateTypeEvents() {
if (autoCompleteBuffer[0] != '\0') {
Common::Event event;
OSystem_DS *system = OSystem_DS::instance();
event.kbd.keycode = (Common::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 < (int)strlen(autoCompleteBuffer); r++) {
autoCompleteBuffer[r] = autoCompleteBuffer[r + 1];
}
typingTimeout = 100;
}
}
void createKeyEvent(int keyNum, Common::Event& event) {
event.kbd.flags = 0;
if ((keys[keyNum].character >= '0') && (keys[keyNum].character <= '9')) {
if (!DS::shiftState) {
event.kbd.ascii = keys[keyNum].character;
event.kbd.keycode = (Common::KeyCode) keys[keyNum].character;
} else {
event.kbd.keycode = (Common::KeyCode) (Common::KEYCODE_F1 - (keys[keyNum].character - '1'));
event.kbd.ascii = 0;
}
} else if ((keys[keyNum].character >= 'A') && (keys[keyNum].character <= 'Z')) {
if ((!DS::shiftState) && (!DS::capsLockState)) {
event.kbd.ascii = keys[keyNum].character + 32; // Make key lowercase.
} else {
event.kbd.ascii = keys[keyNum].character;
}
event.kbd.keycode = (Common::KeyCode) event.kbd.ascii;
} else {
if ((keys[keyNum].character >= Common::KEYCODE_F1) && (keys[keyNum].character >= Common::KEYCODE_F12)) {
event.kbd.keycode = (Common::KeyCode) keys[keyNum].character;
event.kbd.ascii = keys[keyNum].character - Common::KEYCODE_F1 + Common::ASCII_F1;
} else {
event.kbd.ascii = keys[keyNum].character;
event.kbd.keycode = (Common::KeyCode) keys[keyNum].character;
}
}
}
void releaseAllKeys() {
for (int r = 0; r < DS_NUM_KEYS; r++) {
if (keys[r].pressed) {
DS::setKeyHighlight(r, false);
OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
createKeyEvent(r, event);
event.type = Common::EVENT_KEYUP;
system->addEvent(event);
keys[r].pressed = false;
}
}
}
void addKeyboardEvents() {
bool resetShift = false;
updateTypeEvents();
if (typingTimeout > 0) {
typingTimeout--;
if (typingTimeout == 0) {
drawAutoComplete();
}
}
if (DS::getPenDown()) {
touchPosition touchPos;
touchRead(&touchPos);
int tx = (touchPos.px >> 3);
int ty = (touchPos.py >> 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 {
if (current < autoCompleteCount) {
selectedCompletion = current;
}
}
drawAutoComplete();
}
tx -= keyboardX;
ty -= keyboardY;
for (int r = 0; r < DS_NUM_KEYS; r++) {
if (( (tx >= keys[r].x) && (tx <= keys[r].x + 1)) &&
(ty >= keys[r].y) && (ty <= keys[r].y + 1)) {
OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
if ((keys[r].character != Common::KEYCODE_INVALID)) {
createKeyEvent(r, event);
}
event.type = Common::EVENT_KEYDOWN;
system->addEvent(event);
switch (keys[r].character) {
case DS_SHIFT: {
DS::shiftState = !DS::shiftState;
DS::setKeyHighlight(r, DS::shiftState);
break;
}
case DS_CAPSLOCK: {
DS::capsLockState = !DS::capsLockState;
DS::setKeyHighlight(r, DS::capsLockState);
break;
}
default: {
DS::setKeyHighlight(r, true);
keys[r].pressed = true;
break;
}
}
}
}
}
if (DS::getPenReleased()) {
for (int r = 0; r < DS_NUM_KEYS; r++) {
if (keys[r].pressed) {
DS::setKeyHighlight(r, false);
OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
if ((keys[r].character == Common::KEYCODE_INVALID)) {
// Close button
DS::closed = true;
} else {
createKeyEvent(r, event);
event.type = Common::EVENT_KEYUP;
system->addEvent(event);
}
keys[r].pressed = false;
if (keys[r].character != DS_SHIFT) {
resetShift = true;
}
}
}
}
if ((resetShift) && (DS::shiftState)) {
DS::shiftState = false;
resetShift = false;
for (int t = 0; t < DS_NUM_KEYS; t++) {
if (keys[t].character == DS_SHIFT) {
DS::setKeyHighlight(t, false);
}
}
}
}
} // End of namespace DS

View File

@ -1,50 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _TOUCHKEYBOARD_H_
#define _TOUCHKEYBOARD_H_
#include "osystem_ds.h"
namespace DS {
enum {
NUM_WORDS = 12,
KEYBOARD_DATA_SIZE = 4736 * 2,
KEYBOARD_BOTTOM_Y = 105
};
void createKeyEvent(int keyNum, Common::Event& event);
void drawKeyboard(int tileBase, int mapBase, u16 *saveSpace);
void addKeyboardEvents();
bool getKeyboardClosed();
bool isInsideKeyboard(int x, int y);
void addAutoComplete(const char *word);
void clearAutoComplete();
void setCharactersEntered(int count);
void releaseAllKeys();
} // End of namespace DS
#endif

View File

@ -1,196 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "osystem_ds.h"
#include "wordcompletion.h"
#include "engines/agi/agi.h" // Caution for #define for NUM_CHANNELS, causes problems in mixer_intern.h
#ifdef ENABLE_AGI
namespace DS {
// Default dictionary is about 64Kb, so 96Kb should be enough for future expansion
#define WORD_BUFFER_SIZE (96 * 1024)
// Default dictionary has ~8000 words
#define MAX_WORD_COUNT 12000
char wordBuffer[WORD_BUFFER_SIZE];
int wordBufferPos = 0;
char *wordBufferPtr[MAX_WORD_COUNT];
int wordBufferPtrPos = 0;
void addAutoCompleteLine(const char *line) {
while (*line != 0) {
char word[32];
int length;
// Skip the T9-style numbers
while (*line != ' ') {
line++;
}
line++;
do {
length = 0;
if (*line == ' ') line++;
// Copy the new word
do {
word[length++] = *line++;
} while ((*line != '\0') && (*line != ' ') && (*line != '\n'));
word[length] = '\0';
// Store a pointer to the start of the word
wordBufferPtr[wordBufferPtrPos++] = &wordBuffer[wordBufferPos];
// copy the new word into the buffer
strcpy(&wordBuffer[wordBufferPos], word);
wordBufferPos += strlen(word) + 1;
} while (*line == ' ');
}
}
int stringCompare(const void *a, const void *b) {
const char** as = (const char **) a;
const char** bs = (const char **) b;
return scumm_stricmp(*as, *bs);
}
void clearAutoCompleteWordList() {
wordBufferPtrPos = 0;
wordBufferPos = 0;
}
void sortAutoCompleteWordList() {
// Sort the whole word list into alphabetical order
qsort((void *)wordBufferPtr, wordBufferPtrPos, 4, stringCompare);
}
// Sends the current available words to the virtual keyboard code for display
bool findWordCompletions(const char *input) {
int min = 0;
int max = wordBufferPtrPos - 1;
char *word;
int position;
char partialWord[32];
// Early out if dictionary not loaded
if (wordBufferPtrPos == 0)
return false;
OSystem_DS *system = dynamic_cast<OSystem_DS *>(g_system);
system->clearAutoComplete();
int start = 0;
for (int r = strlen(input) - 1; r>0; r--) {
if (input[r] == ' ') {
start = r + 1;
break;
}
}
strcpy(partialWord, &input[start]);
if (*partialWord == 0) {
return false;
}
do {
position = min + ((max - min) / 2);
// Get the word from the dictonary line
word = wordBufferPtr[position];
// Now check to see if the word is before or after the stub we're after
int result = scumm_stricmp(partialWord, word);
if (result == 0) {
// We've found the whole word. Aren't we good.
break;
} else if (result > 0) {
// We're too early, so change the minimum position
min = position + 1;
} else if (result < 0) {
// We're too early, so change the maximum position
max = position - 1;
}
} while (max - min > 0);
position = min;
word = wordBufferPtr[position];
system->setCharactersEntered(strlen(partialWord));
bool match = true;
for (int r = 0; partialWord[r] != 0; r++) {
if (word[r] != partialWord[r]) {
match = false;
break;
}
}
if (!match) {
position++;
if (position == wordBufferPtrPos)
return false;
word = wordBufferPtr[position];
}
match = true;
do {
for (int r = 0; partialWord[r] != 0; r++) {
if (word[r] != partialWord[r]) {
match = false;
break;
}
}
if (match) {
system->addAutoComplete(word);
}
position++;
if (position < wordBufferPtrPos) {
word = wordBufferPtr[position];
}
} while ((match) && (position < wordBufferPtrPos));
return true;
}
} // End of namespace DS
#endif

View File

@ -1,30 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
namespace DS {
extern void clearAutoCompleteWordList();
extern bool findWordCompletions(const char *input);
extern void addAutoCompleteLine(const char *line);
extern void sortAutoCompleteWordList();
} // End of namespace DS

View File

@ -1,74 +1,10 @@
MODULE := backends/platform/ds
PORT_OBJS := \
MODULE_OBJS := \
arm9/source/blitters_arm.o \
arm9/source/dsmain.o \
arm9/source/scummhelp.o \
arm9/source/osystem_ds.o \
arm9/source/touchkeyboard.o \
arm9/source/dsoptions.o \
arm9/source/wordcompletion.o
DATA_OBJS := \
arm9/data/icons.o \
arm9/data/keyboard.o \
arm9/data/keyboard_pal.o \
arm9/data/default_font.o \
arm9/data/8x8font_tga.o
MODULE_OBJS := $(DATA_OBJS) $(PORT_OBJS)
#---------------------------------------------------------------------------------
# canned command sequence for binary data
#---------------------------------------------------------------------------------
define bin2o
$(MKDIR) $(*D)
bin2s $< | $(AS) -mthumb -mthumb-interwork -o $(@)
endef
define bin2h
$(MKDIR) $(*D)
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > $@
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@
echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@
endef
vpath %.raw $(srcdir)
vpath %.pal $(srcdir)
vpath %.bin $(srcdir)
%.o: %.raw
$(bin2o)
%_raw.h: %.raw
$(bin2h)
%.o: %.pal
$(bin2o)
%_raw.h: %.pal
$(bin2h)
%.o: %.bin
$(bin2o)
%_raw.h: %.bin
$(bin2h)
# Mark files which require the *_raw.h files manually (for now, at least)
$(MODULE)/arm9/source/dsmain.o: \
$(MODULE)/arm9/data/icons_raw.h \
$(MODULE)/arm9/data/keyboard_raw.h \
$(MODULE)/arm9/data/keyboard_pal_raw.h
$(MODULE)/arm9/source/touchkeyboard.o: \
$(MODULE)/arm9/data/keyboard_raw.h \
$(MODULE)/arm9/data/keyboard_pal_raw.h \
$(MODULE)/arm9/data/8x8font_tga_raw.h
arm9/source/dsoptions.o
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))

View File

@ -167,14 +167,6 @@ int AgiEngine::agiInit() {
if (ec == errOK)
ec = _loader->loadResource(RESOURCETYPE_LOGIC, 0);
#ifdef __DS__
// Normally, the engine loads the predictive text dictionary when the predictive dialog
// is shown. On the DS version, the word completion feature needs the dictionary too.
// FIXME - loadDict() no long exists in AGI as this has been moved to within the
// GUI Predictive Dialog, but DS Word Completion is probably broken due to this...
#endif
_keyHoldMode = false;
_keyHoldModeLastKey = Common::KEYCODE_INVALID;

View File

@ -28,9 +28,6 @@
#include "agi/text.h"
#include "agi/systemui.h"
#include "agi/words.h"
#ifdef __DS__
#include "wordcompletion.h"
#endif
namespace Agi {
@ -829,9 +826,6 @@ void TextMgr::promptClear() {
}
void TextMgr::promptRememberForAutoComplete(bool entered) {
#ifdef __DS__
DS::findWordCompletions((char *)_prompt);
#endif
}
void TextMgr::promptCommandWindow(bool recallLastCommand, uint16 newKey) {
@ -1000,9 +994,6 @@ void TextMgr::stringKeyPress(uint16 newKey) {
}
void TextMgr::stringRememberForAutoComplete(bool entered) {
#ifdef __DS__
DS::findWordCompletions((char *)_inputString);
#endif
}
/**

View File

@ -30,10 +30,6 @@
#include "graphics/scaler.h"
#ifdef __DS__
#include "scummhelp.h"
#endif
#include "gui/gui-manager.h"
#include "gui/widget.h"
#include "gui/ThemeEval.h"
@ -329,12 +325,7 @@ void HelpDialog::reflowLayout() {
void HelpDialog::displayKeyBindings() {
U32String titleStr, *keyStr, *dscStr;
#ifndef __DS__
ScummHelp::updateStrings(_game.id, _game.version, _game.platform, _page, titleStr, keyStr, dscStr);
#else
// DS version has a different help screen
DS::updateStrings(_game.id, _game.version, _game.platform, _page, titleStr, keyStr, dscStr);
#endif
_title->setLabel(titleStr);
for (int i = 0; i < _numLines; i++) {

View File

@ -35,10 +35,6 @@
#include "common/file.h"
#include "common/savefile.h"
#if defined(__DS__) && defined(ENABLE_AGI)
#include "backends/platform/ds/arm9/source/wordcompletion.h"
#endif
namespace GUI {
enum {
@ -976,10 +972,6 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict
while ((ptr = strchr(ptr, '\n'))) {
*ptr = 0;
ptr++;
#if defined(__DS__) && defined(ENABLE_AGI)
// Pass the line on to the DS word list
DS::addAutoCompleteLine(dict.dictLine[i - 1]);
#endif
dict.dictLine[i++] = ptr;
}
if (dict.dictLine[lines - 1][0] == 0)
@ -989,12 +981,7 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict
debug(5, "Predictive Dialog: Loaded %d lines", dict.dictLineCount);
// FIXME: We use binary search on _predictiveDict.dictLine, yet we make no at_tempt
// to ever sort this array (except for the DS port). That seems risky, doesn't it?
#if defined(__DS__) && defined(ENABLE_AGI)
// Sort the DS word completion list, to allow for a binary chop later (in the ds backend)
DS::sortAutoCompleteWordList();
#endif
// to ever sort this array. That seems risky, doesn't it?
uint32 time3 = g_system->getMillis();
debug(5, "Predictive Dialog: Time to parse %s: %d, total: %d", ConfMan.get(dict.nameDict).c_str(), time3 - time2, time3 - time1);