From 0b81939104e65325979ac4e5475f6e05b87a71d3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Feb 2017 11:37:06 -0800 Subject: [PATCH] DS Video: Begin stubbing out rendering --- CMakeLists.txt | 4 +- include/mgba/internal/ds/video.h | 17 +++++++ src/ds/core.c | 19 +++++++- src/ds/renderers/software.c | 50 +++++++++++++++++++ src/ds/video.c | 84 ++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 src/ds/renderers/software.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f50b5161..b3569719b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ file(GLOB GBA_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/renderers/*.c) file(GLOB GBA_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/sio/lockstep.c) file(GLOB GB_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/sio/lockstep.c) file(GLOB GB_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/renderers/*.c) +file(GLOB DS_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/renderers/*.c) file(GLOB THIRD_PARTY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/inih/*.c) set(CLI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/commandline.c) set(CORE_VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-mem.c) @@ -640,7 +641,8 @@ if(M_CORE_DS) add_definitions(-DM_CORE_DS) list(APPEND CORE_SRC ${ARM_SRC} - ${DS_SRC}) + ${DS_SRC} + ${DS_RENDERER_SRC}) list(APPEND DEBUGGER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/cli-debugger.c ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/debugger.c diff --git a/include/mgba/internal/ds/video.h b/include/mgba/internal/ds/video.h index c156bd6da..a02f5cbec 100644 --- a/include/mgba/internal/ds/video.h +++ b/include/mgba/internal/ds/video.h @@ -29,9 +29,25 @@ enum { DS_VIDEO_TOTAL_LENGTH = DS_VIDEO_HORIZONTAL_LENGTH * DS_VIDEO_VERTICAL_TOTAL_PIXELS, }; +struct DSVideoRenderer { + void (*init)(struct DSVideoRenderer* renderer); + void (*reset)(struct DSVideoRenderer* renderer); + void (*deinit)(struct DSVideoRenderer* renderer); + + uint16_t (*writeVideoRegister)(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value); + void (*drawScanline)(struct DSVideoRenderer* renderer, int y); + void (*finishFrame)(struct DSVideoRenderer* renderer); + + void (*getPixels)(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels); + void (*putPixels)(struct DSVideoRenderer* renderer, size_t stride, const void* pixels); + + uint16_t* vram; +}; + struct DS; struct DSVideo { struct DS* p; + struct DSVideoRenderer* renderer; struct mTimingEvent event7; struct mTimingEvent event9; @@ -48,6 +64,7 @@ struct DSVideo { void DSVideoInit(struct DSVideo* video); void DSVideoReset(struct DSVideo* video); void DSVideoDeinit(struct DSVideo* video); +void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* renderer); struct DSCommon; void DSVideoWriteDISPSTAT(struct DSCommon* dscore, uint16_t value); diff --git a/src/ds/core.c b/src/ds/core.c index 3dd0dfc0c..6e0036300 100644 --- a/src/ds/core.c +++ b/src/ds/core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ struct DSCore { struct mCore d; struct ARMCore* arm7; struct ARMCore* arm9; + struct DSVideoSoftwareRenderer renderer; int keys; struct mCPUComponent* components[CPU_COMPONENT_MAX]; struct mDebuggerPlatform* debuggerPlatform; @@ -52,6 +54,9 @@ static bool _DSCoreInit(struct mCore* core) { ARMInit(arm7); ARMInit(arm9); + DSVideoSoftwareRendererCreate(&dscore->renderer); + dscore->renderer.outputBuffer = NULL; + dscore->keys = 0; ds->keySource = &dscore->keys; @@ -110,12 +115,19 @@ static void _DSCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, u } static void _DSCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) { + struct DSCore* dscore = (struct DSCore*) core; + dscore->renderer.outputBuffer = buffer; + dscore->renderer.outputBufferStride = stride; } static void _DSCoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) { + struct DSCore* dscore = (struct DSCore*) core; + dscore->renderer.d.getPixels(&dscore->renderer.d, stride, buffer); } static void _DSCorePutPixels(struct mCore* core, const void* buffer, size_t stride) { + struct DSCore* dscore = (struct DSCore*) core; + dscore->renderer.d.putPixels(&dscore->renderer.d, stride, buffer); } static struct blip_t* _DSCoreGetAudioChannel(struct mCore* core, int ch) { @@ -162,6 +174,11 @@ static void _DSCoreReset(struct mCore* core) { struct DSCore* dscore = (struct DSCore*) core; struct DS* ds = (struct DS*) core->board; + if (dscore->renderer.outputBuffer) { + struct DSVideoRenderer* renderer = &dscore->renderer.d; + DSVideoAssociateRenderer(&ds->video, renderer); + } + #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct VFile* bios7 = 0; struct VFile* bios9 = 0; @@ -240,7 +257,7 @@ static void _DSCoreClearKeys(struct mCore* core, uint32_t keys) { dscore->keys &= ~keys; } -static int32_t _DSCoreFrameCounter(struct mCore* core) { +static int32_t _DSCoreFrameCounter(const struct mCore* core) { struct DS* ds = core->board; return ds->video.frameCounter; } diff --git a/src/ds/renderers/software.c b/src/ds/renderers/software.c new file mode 100644 index 000000000..e11788ef1 --- /dev/null +++ b/src/ds/renderers/software.c @@ -0,0 +1,50 @@ +/* Copyright (c) 2013-2017 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + +static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer); +static void DSVideoSoftwareRendererDeinit(struct DSVideoRenderer* renderer); +static void DSVideoSoftwareRendererReset(struct DSVideoRenderer* renderer); +static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value); +static void DSVideoSoftwareRendererDrawScanline(struct DSVideoRenderer* renderer, int y); +static void DSVideoSoftwareRendererFinishFrame(struct DSVideoRenderer* renderer); +static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels); +static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels); + +void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) { + renderer->d.init = DSVideoSoftwareRendererInit; + renderer->d.reset = DSVideoSoftwareRendererReset; + renderer->d.deinit = DSVideoSoftwareRendererDeinit; + renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline; + renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame; + renderer->d.getPixels = DSVideoSoftwareRendererGetPixels; + renderer->d.putPixels = DSVideoSoftwareRendererPutPixels; +} + +static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer) { +} + +static void DSVideoSoftwareRendererReset(struct DSVideoRenderer* renderer) { +} + +static void DSVideoSoftwareRendererDeinit(struct DSVideoRenderer* renderer) { +} + +static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value) { + return value; +} + +static void DSVideoSoftwareRendererDrawScanline(struct DSVideoRenderer* renderer, int y) { +} + +static void DSVideoSoftwareRendererFinishFrame(struct DSVideoRenderer* renderer) { +} + +static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels) { +} + +static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels) { +} diff --git a/src/ds/video.c b/src/ds/video.c index 27ef4f866..af2090d71 100644 --- a/src/ds/video.c +++ b/src/ds/video.c @@ -14,6 +14,15 @@ mLOG_DEFINE_CATEGORY(DS_VIDEO, "DS Video"); +static void DSVideoDummyRendererInit(struct DSVideoRenderer* renderer); +static void DSVideoDummyRendererReset(struct DSVideoRenderer* renderer); +static void DSVideoDummyRendererDeinit(struct DSVideoRenderer* renderer); +static uint16_t DSVideoDummyRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value); +static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y); +static void DSVideoDummyRendererFinishFrame(struct DSVideoRenderer* renderer); +static void DSVideoDummyRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels); +static void DSVideoDummyRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels); + static void _startHblank7(struct mTiming*, void* context, uint32_t cyclesLate); static void _startHdraw7(struct mTiming*, void* context, uint32_t cyclesLate); static void _startHblank9(struct mTiming*, void* context, uint32_t cyclesLate); @@ -88,7 +97,19 @@ const struct DSVRAMBankInfo { }, }; +static struct DSVideoRenderer dummyRenderer = { + .init = DSVideoDummyRendererInit, + .reset = DSVideoDummyRendererReset, + .deinit = DSVideoDummyRendererDeinit, + .writeVideoRegister = DSVideoDummyRendererWriteVideoRegister, + .drawScanline = DSVideoDummyRendererDrawScanline, + .finishFrame = DSVideoDummyRendererFinishFrame, + .getPixels = DSVideoDummyRendererGetPixels, + .putPixels = DSVideoDummyRendererPutPixels, +}; + void DSVideoInit(struct DSVideo* video) { + video->renderer = &dummyRenderer; video->vram = NULL; video->frameskip = 0; video->event7.name = "DS7 Video"; @@ -118,6 +139,7 @@ void DSVideoReset(struct DSVideo* video) { mappedMemoryFree(video->vram, DS_SIZE_VRAM); } video->vram = anonymousMemoryMap(DS_SIZE_VRAM); + video->renderer->vram = video->vram; video->p->memory.vramBank[0] = &video->vram[0x00000]; video->p->memory.vramBank[1] = &video->vram[0x10000]; @@ -128,9 +150,20 @@ void DSVideoReset(struct DSVideo* video) { video->p->memory.vramBank[6] = &video->vram[0x4A000]; video->p->memory.vramBank[7] = &video->vram[0x4C000]; video->p->memory.vramBank[8] = &video->vram[0x50000]; + + video->renderer->deinit(video->renderer); + video->renderer->init(video->renderer); +} + +void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* renderer) { + video->renderer->deinit(video->renderer); + video->renderer = renderer; + renderer->vram = video->vram; + video->renderer->init(video->renderer); } void DSVideoDeinit(struct DSVideo* video) { + DSVideoAssociateRenderer(video, &dummyRenderer); mappedMemoryFree(video->vram, DS_SIZE_VRAM); } @@ -160,6 +193,9 @@ void _startHdraw7(struct mTiming* timing, void* context, uint32_t cyclesLate) { switch (video->vcount) { case DS_VIDEO_VERTICAL_PIXELS: video->p->ds7.memory.io[DS_REG_DISPSTAT >> 1] = GBARegisterDISPSTATFillInVblank(dispstat); + if (video->frameskipCounter <= 0) { + video->renderer->finishFrame(video->renderer); + } if (GBARegisterDISPSTATIsVblankIRQ(dispstat)) { DSRaiseIRQ(video->p->ds7.cpu, video->p->ds7.memory.io, DS_IRQ_VBLANK); } @@ -179,6 +215,9 @@ void _startHblank7(struct mTiming* timing, void* context, uint32_t cyclesLate) { // Begin Hblank dispstat = GBARegisterDISPSTATFillInHblank(dispstat); + if (video->vcount < DS_VIDEO_VERTICAL_PIXELS && video->frameskipCounter <= 0) { + video->renderer->drawScanline(video->renderer, video->vcount); + } if (GBARegisterDISPSTATIsHblankIRQ(dispstat)) { DSRaiseIRQ(video->p->ds7.cpu, video->p->ds7.memory.io, DS_IRQ_HBLANK); @@ -272,3 +311,48 @@ void DSVideoConfigureVRAM(struct DSMemory* memory, int index, uint8_t value) { } } } + +static void DSVideoDummyRendererInit(struct DSVideoRenderer* renderer) { + UNUSED(renderer); + // Nothing to do +} + +static void DSVideoDummyRendererReset(struct DSVideoRenderer* renderer) { + UNUSED(renderer); + // Nothing to do +} + +static void DSVideoDummyRendererDeinit(struct DSVideoRenderer* renderer) { + UNUSED(renderer); + // Nothing to do +} + +static uint16_t DSVideoDummyRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value) { + UNUSED(renderer); + return value; +} + +static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y) { + UNUSED(renderer); + UNUSED(y); + // Nothing to do +} + +static void DSVideoDummyRendererFinishFrame(struct DSVideoRenderer* renderer) { + UNUSED(renderer); + // Nothing to do +} + +static void DSVideoDummyRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels) { + UNUSED(renderer); + UNUSED(stride); + UNUSED(pixels); + // Nothing to do +} + +static void DSVideoDummyRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels) { + UNUSED(renderer); + UNUSED(stride); + UNUSED(pixels); + // Nothing to do +}