From 0cb9c41a4a4252e806d3d3f6cc081b6bda2d37b2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 27 Feb 2017 11:14:36 -0800 Subject: [PATCH] DS: Initial touch support --- include/mgba/core/core.h | 2 ++ include/mgba/internal/ds/ds.h | 3 +++ src/ds/core.c | 19 +++++++++++++++++++ src/ds/io.c | 2 ++ src/ds/spi.c | 22 +++++++++++++++++----- src/gb/core.c | 8 ++++++++ src/gba/core.c | 8 ++++++++ src/platform/sdl/sdl-events.c | 23 +++++++++++++++++++++++ 8 files changed, 82 insertions(+), 5 deletions(-) diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index 0b289bf6e..385cbe58e 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -104,6 +104,8 @@ struct mCore { void (*addKeys)(struct mCore*, uint32_t keys); void (*clearKeys)(struct mCore*, uint32_t keys); + void (*setCursor)(struct mCore*, int x, int y, bool down); + int32_t (*frameCounter)(const struct mCore*); int32_t (*frameCycles)(const struct mCore*); int32_t (*frequency)(const struct mCore*); diff --git a/include/mgba/internal/ds/ds.h b/include/mgba/internal/ds/ds.h index 6eba5ae9f..205d9b8fd 100644 --- a/include/mgba/internal/ds/ds.h +++ b/include/mgba/internal/ds/ds.h @@ -95,6 +95,9 @@ struct DS { uint32_t bios7Checksum; uint32_t bios9Checksum; int* keySource; + int* cursorSourceX; + int* cursorSourceY; + bool* touchSource; struct mRTCSource* rtcSource; struct mRumble* rumble; diff --git a/src/ds/core.c b/src/ds/core.c index 0abf32c01..2ebfd0cbf 100644 --- a/src/ds/core.c +++ b/src/ds/core.c @@ -22,6 +22,9 @@ struct DSCore { struct ARMCore* arm9; struct DSVideoSoftwareRenderer renderer; int keys; + int cursorX; + int cursorY; + bool touchDown; struct mCPUComponent* components[CPU_COMPONENT_MAX]; struct mDebuggerPlatform* debuggerPlatform; struct mCheatDevice* cheatDevice; @@ -59,6 +62,12 @@ static bool _DSCoreInit(struct mCore* core) { dscore->keys = 0; ds->keySource = &dscore->keys; + dscore->cursorX = 0; + ds->cursorSourceX = &dscore->cursorX; + dscore->cursorY = 0; + ds->cursorSourceY = &dscore->cursorY; + dscore->touchDown = false; + ds->touchSource = &dscore->touchDown; #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 mDirectorySetInit(&core->dirs); @@ -308,6 +317,15 @@ static void _DSCoreClearKeys(struct mCore* core, uint32_t keys) { dscore->keys &= ~keys; } +static void _DSCoreSetCursor(struct mCore* core, int x, int y, bool down) { + struct DSCore* dscore = (struct DSCore*) core; + dscore->cursorX = x; + dscore->cursorY = y - DS_VIDEO_VERTICAL_PIXELS; + if ((down && y >= 0) || !down) { + dscore->touchDown = down; + } +} + static int32_t _DSCoreFrameCounter(const struct mCore* core) { struct DS* ds = core->board; return ds->video.frameCounter; @@ -493,6 +511,7 @@ struct mCore* DSCoreCreate(void) { core->setKeys = _DSCoreSetKeys; core->addKeys = _DSCoreAddKeys; core->clearKeys = _DSCoreClearKeys; + core->setCursor = _DSCoreSetCursor; core->frameCounter = _DSCoreFrameCounter; core->frameCycles = _DSCoreFrameCycles; core->frequency = _DSCoreFrequency; diff --git a/src/ds/io.c b/src/ds/io.c index cf5355a90..d5fbd7727 100644 --- a/src/ds/io.c +++ b/src/ds/io.c @@ -213,6 +213,7 @@ static uint16_t DSIOReadExKeyInput(struct DS* ds) { } input = ~(input >> 10) & 0x3; input |= 0x3C; + input |= ds->memory.io7[DS7_REG_EXTKEYIN >> 1] & 0xC0; return input; } @@ -259,6 +260,7 @@ void DS7IOInit(struct DS* ds) { memset(ds->memory.io7, 0, sizeof(ds->memory.io7)); ds->memory.io7[DS_REG_IPCFIFOCNT >> 1] = 0x0101; ds->memory.io7[DS_REG_POSTFLG >> 1] = 0x0001; + ds->memory.io7[DS7_REG_EXTKEYIN >> 1] = 0x007F; } void DS7IOWrite(struct DS* ds, uint32_t address, uint16_t value) { diff --git a/src/ds/spi.c b/src/ds/spi.c index d6c16d179..2c2ef3ac6 100644 --- a/src/ds/spi.c +++ b/src/ds/spi.c @@ -64,7 +64,6 @@ static void _tscEvent(struct mTiming* timing, void* context, uint32_t cyclesLate DSSPICNT control = ds->memory.io7[DS7_REG_SPICNT >> 1]; uint8_t newValue = 0; - // TODO: /PENIRQ if (ds->memory.spiBus.tscOffset > 0) { // TODO: Make generic? if (ds->memory.spiBus.tscOffset < 12) { @@ -75,15 +74,28 @@ static void _tscEvent(struct mTiming* timing, void* context, uint32_t cyclesLate } } else if (ds->memory.spiBus.tscControlByte) { switch (DSTSCControlByteGetChannel(ds->memory.spiBus.tscControlByte)) { + // TODO: Calibrate from firmware case DS_TSC_CHANNEL_TS_X: - mLOG(DS_SPI, STUB, "Unimplemented TSC channel X"); - ds->memory.spiBus.tscRegister = 0; + if (*ds->touchSource) { + ds->memory.spiBus.tscRegister = (*ds->cursorSourceX * 0xDD0 / DS_VIDEO_HORIZONTAL_PIXELS) + 0x100; + } else { + ds->memory.spiBus.tscRegister = 0; + } break; case DS_TSC_CHANNEL_TS_Y: - mLOG(DS_SPI, STUB, "Unimplemented TSC channel Y"); - ds->memory.spiBus.tscRegister = 0xFFF; + if (*ds->touchSource) { + ds->memory.spiBus.tscRegister = (*ds->cursorSourceY * 0xE70 / DS_VIDEO_VERTICAL_PIXELS) + 0x0B0; + } else { + ds->memory.spiBus.tscRegister = 0xFFF; + } break; case DS_TSC_CHANNEL_TEMP_0: + if (*ds->touchSource) { + ds->memory.io7[DS7_REG_EXTKEYIN >> 1] &= ~0x040; + } else { + ds->memory.io7[DS7_REG_EXTKEYIN >> 1] |= 0x040; + } + break; case DS_TSC_CHANNEL_BATTERY_V: case DS_TSC_CHANNEL_TS_Z1: case DS_TSC_CHANNEL_TS_Z2: diff --git a/src/gb/core.c b/src/gb/core.c index df64296c9..ef006d265 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -360,6 +360,13 @@ static void _GBCoreClearKeys(struct mCore* core, uint32_t keys) { gbcore->keys &= ~keys; } +static void _GBCoreSetCursor(struct mCore* core, int x, int y, bool down) { + UNUSED(core); + UNUSED(x); + UNUSED(y); + UNUSED(down); +} + static int32_t _GBCoreFrameCounter(const struct mCore* core) { const struct GB* gb = core->board; return gb->video.frameCounter; @@ -595,6 +602,7 @@ struct mCore* GBCoreCreate(void) { core->setKeys = _GBCoreSetKeys; core->addKeys = _GBCoreAddKeys; core->clearKeys = _GBCoreClearKeys; + core->setCursor = _GBCoreSetCursor; core->frameCounter = _GBCoreFrameCounter; core->frameCycles = _GBCoreFrameCycles; core->frequency = _GBCoreFrequency; diff --git a/src/gba/core.c b/src/gba/core.c index 6b0d80b69..fef994b0f 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -373,6 +373,13 @@ static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) { gbacore->keys &= ~keys; } +static void _GBACoreSetCursor(struct mCore* core, int x, int y, bool down) { + UNUSED(core); + UNUSED(x); + UNUSED(y); + UNUSED(down); +} + static int32_t _GBACoreFrameCounter(const struct mCore* core) { const struct GBA* gba = core->board; return gba->video.frameCounter; @@ -609,6 +616,7 @@ struct mCore* GBACoreCreate(void) { core->setKeys = _GBACoreSetKeys; core->addKeys = _GBACoreAddKeys; core->clearKeys = _GBACoreClearKeys; + core->setCursor = _GBACoreSetCursor; core->frameCounter = _GBACoreFrameCounter; core->frameCycles = _GBACoreFrameCycles; core->frequency = _GBACoreFrequency; diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index 81eaffff2..713e82340 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -516,6 +516,25 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer* } } +static void _mSDLHandleMouseButton(struct mCore* core, struct mSDLPlayer* sdlContext, const struct SDL_MouseButtonEvent* event) { + if (event->button != SDL_BUTTON_LEFT) { + return; + } + int x = event->x; + int y = event->y; +#if SDL_VERSION_ATLEAST(2, 0, 0) + int windowW; + int windowH; + SDL_GetWindowSize(sdlContext->window, &windowW, &windowH); + unsigned coreW; + unsigned coreH; + core->desiredVideoDimensions(core, &coreW, &coreH); + x = x * coreW / windowW; + y = y * coreH / windowH; +#endif + core->setCursor(core, x, y, event->state == SDL_PRESSED); +} + static void _mSDLHandleJoyButton(struct mCore* core, struct mSDLPlayer* sdlContext, const struct SDL_JoyButtonEvent* event) { int key = 0; key = mInputMapKey(sdlContext->bindings, SDL_BINDING_BUTTON, event->button); @@ -579,6 +598,10 @@ void mSDLHandleEvent(struct mCoreThread* context, struct mSDLPlayer* sdlContext, case SDL_KEYUP: _mSDLHandleKeypress(context, sdlContext, &event->key); break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + _mSDLHandleMouseButton(context->core, sdlContext, &event->button); + break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: _mSDLHandleJoyButton(context->core, sdlContext, &event->jbutton);