mirror of https://github.com/mgba-emu/mgba.git
Wii: Initial port
This commit is contained in:
parent
dc33a4f173
commit
4f04c30f70
|
@ -202,6 +202,14 @@ if(BUILD_BBB OR BUILD_RASPI OR BUILD_PANDORA)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(WII)
|
||||
list(APPEND VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c)
|
||||
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5)
|
||||
file(GLOB WII_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/*.c)
|
||||
add_executable(${BINARY_NAME}.elf ${WII_SRC})
|
||||
target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} fat ogc)
|
||||
endif()
|
||||
|
||||
if(BUILD_PANDORA)
|
||||
add_definitions(-DBUILD_PANDORA)
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
if(DEFINED ENV{DEVKITPRO})
|
||||
set(DEVKITPRO $ENV{DEVKITPRO})
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find DEVKITPRO in environment")
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{DEVKITPPC})
|
||||
set(DEVKITPPC $ENV{DEVKITPPC})
|
||||
else()
|
||||
set(DEVKITPPC ${DEVKITPRO}/devkitPPC)
|
||||
endif()
|
||||
|
||||
set(toolchain_bin_dir ${DEVKITPPC}/bin)
|
||||
set(cross_prefix ${toolchain_bin_dir}/powerpc-eabi-)
|
||||
set(inc_flags -I${DEVKITPRO}/libogc/include)
|
||||
set(arch_flags "-mrvl -mcpu=750 -meabi -mhard-float -g")
|
||||
set(link_flags "-L${DEVKITPRO}/libogc/lib/wii ${arch_flags}")
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic CACHE INTERNAL "system name")
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm CACHE INTERNAL "processor")
|
||||
set(CMAKE_LIBRARY_ARCHITECTURE powerpc-none-eabi CACHE INTERNAL "abi")
|
||||
set(CMAKE_AR ${cross_prefix}ar CACHE INTERNAL "archiver")
|
||||
set(CMAKE_C_COMPILER ${cross_prefix}gcc CACHE INTERNAL "c compiler")
|
||||
set(CMAKE_CXX_COMPILER ${cross_prefix}g++ CACHE INTERNAL "cxx compiler")
|
||||
set(CMAKE_ASM_COMPILER ${cross_prefix}gcc CACHE INTERNAL "assembler")
|
||||
set(common_flags "${arch_flags} ${inc_flags}")
|
||||
set(CMAKE_C_FLAGS ${common_flags} CACHE INTERNAL "c compiler flags")
|
||||
set(CMAKE_ASM_FLAGS ${common_flags} CACHE INTERNAL "c compiler flags")
|
||||
set(CMAKE_CXX_FLAGS ${common_flags} CACHE INTERNAL "cxx compiler flags")
|
||||
set(CMAKE_LINKER ${cross_prefix}ld CACHE INTERNAL "linker")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "exe link flags")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "module link flags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS ${link_flags} CACHE INTERNAL "shared link flags")
|
||||
|
||||
set(ELF2DOL ${toolchain_bin_dir}/elf2dol)
|
||||
|
||||
set(WII ON)
|
||||
add_definitions(-DGEKKO)
|
|
@ -0,0 +1,283 @@
|
|||
/* Copyright (c) 2013-2015 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/. */
|
||||
#define asm __asm__
|
||||
|
||||
#include <fat.h>
|
||||
#include <gccore.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "util/common.h"
|
||||
|
||||
#include "gba/gba.h"
|
||||
#include "gba/renderers/video-software.h"
|
||||
#include "gba/serialize.h"
|
||||
#include "gba/supervisor/overrides.h"
|
||||
#include "gba/video.h"
|
||||
#include "util/vfs.h"
|
||||
|
||||
#define SAMPLES 1024
|
||||
|
||||
static void GBAWiiLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
|
||||
static void GBAWiiFrame(void);
|
||||
static bool GBAWiiLoadGame(const char* path);
|
||||
|
||||
static void _postVideoFrame(struct GBAAVStream*, struct GBAVideoRenderer* renderer);
|
||||
|
||||
static struct GBA gba;
|
||||
static struct ARMCore cpu;
|
||||
static struct GBAVideoSoftwareRenderer renderer;
|
||||
static struct VFile* rom;
|
||||
static struct VFile* save;
|
||||
static struct GBAAVStream stream;
|
||||
static FILE* logfile;
|
||||
static GXRModeObj* mode;
|
||||
static Mtx model, view, modelview;
|
||||
static uint16_t* texmem;
|
||||
static GXTexObj tex;
|
||||
|
||||
static void* framebuffer[2];
|
||||
static int whichFb = 0;
|
||||
|
||||
int main() {
|
||||
VIDEO_Init();
|
||||
PAD_Init();
|
||||
|
||||
int fmt;
|
||||
#ifdef COLOR_16_BIT
|
||||
#ifdef COLOR_5_6_5
|
||||
fmt = GX_PF_RGB565_Z16;
|
||||
#else
|
||||
#error This pixel format is unsupported. Please use -DCOLOR_16-BIT -DCOLOR_5_6_5
|
||||
#endif
|
||||
#else
|
||||
#error This pixel format is unsupported. Please use -DCOLOR_16-BIT -DCOLOR_5_6_5
|
||||
#endif
|
||||
|
||||
mode = VIDEO_GetPreferredMode(0);
|
||||
framebuffer[0] = SYS_AllocateFramebuffer(mode);
|
||||
framebuffer[1] = SYS_AllocateFramebuffer(mode);
|
||||
|
||||
VIDEO_Configure(mode);
|
||||
VIDEO_SetNextFramebuffer(framebuffer[whichFb]);
|
||||
VIDEO_SetBlack(FALSE);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
if (mode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
|
||||
GXColor bg = { 0, 0, 0, 0xFF };
|
||||
void* fifo = memalign(32, 0x40000);
|
||||
memset(fifo, 0, 0x40000);
|
||||
GX_Init(fifo, 0x40000);
|
||||
GX_SetPixelFmt(fmt, GX_ZC_LINEAR);
|
||||
GX_SetCopyClear(bg, 0x00FFFFFF);
|
||||
GX_SetViewport(0, 0, mode->fbWidth, mode->efbHeight, 0, 1);
|
||||
|
||||
GX_SetCullMode(GX_CULL_NONE);
|
||||
GX_CopyDisp(framebuffer[whichFb], GX_TRUE);
|
||||
GX_SetDispCopyGamma(GX_GM_1_0);
|
||||
|
||||
GX_ClearVtxDesc();
|
||||
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||
|
||||
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0);
|
||||
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0);
|
||||
|
||||
GX_SetNumChans(1);
|
||||
GX_SetNumTexGens(1);
|
||||
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
||||
GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE);
|
||||
|
||||
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
|
||||
GX_InvVtxCache();
|
||||
GX_InvalidateTexAll();
|
||||
|
||||
Mtx44 proj;
|
||||
guOrtho(proj, 0, VIDEO_VERTICAL_PIXELS, 0, VIDEO_HORIZONTAL_PIXELS, 0, 300);
|
||||
GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC);
|
||||
|
||||
guVector cam = { 0.0f, 0.0f, 0.0f };
|
||||
guVector up = { 0.0f, 1.0f, 0.0f };
|
||||
guVector look = { 0.0f, 0.0f, -1.0f };
|
||||
guLookAt(view, &cam, &up, &look);
|
||||
GX_LoadPosMtxImm(view, GX_PNMTX0);
|
||||
|
||||
guMtxIdentity(model);
|
||||
guMtxTransApply(model, model, 0.0f, 0.0f, -6.0f);
|
||||
guMtxConcat(view, model, modelview);
|
||||
GX_LoadPosMtxImm(modelview, GX_PNMTX0);
|
||||
|
||||
texmem = memalign(32, 256 * 256 * BYTES_PER_PIXEL);
|
||||
GX_InitTexObj(&tex, texmem, 256, 256, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||
|
||||
fatInitDefault();
|
||||
|
||||
logfile = fopen("/mgba.log", "w");
|
||||
|
||||
stream.postAudioFrame = 0;
|
||||
stream.postAudioBuffer = 0;
|
||||
stream.postVideoFrame = _postVideoFrame;
|
||||
|
||||
GBACreate(&gba);
|
||||
ARMSetComponents(&cpu, &gba.d, 0, 0);
|
||||
ARMInit(&cpu);
|
||||
gba.logLevel = 0; // TODO: Settings
|
||||
gba.logHandler = GBAWiiLog;
|
||||
gba.stream = &stream;
|
||||
gba.idleOptimization = IDLE_LOOP_REMOVE; // TODO: Settings
|
||||
rom = 0;
|
||||
|
||||
GBAVideoSoftwareRendererCreate(&renderer);
|
||||
renderer.outputBuffer = memalign(32, 256 * 256 * BYTES_PER_PIXEL);
|
||||
renderer.outputBufferStride = 256;
|
||||
GBAVideoAssociateRenderer(&gba.video, &renderer.d);
|
||||
|
||||
GBAAudioResizeBuffer(&gba.audio, SAMPLES);
|
||||
|
||||
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
|
||||
blip_set_rates(gba.audio.left, GBA_ARM7TDMI_FREQUENCY, 44100);
|
||||
blip_set_rates(gba.audio.right, GBA_ARM7TDMI_FREQUENCY, 44100);
|
||||
#endif
|
||||
|
||||
if (!GBAWiiLoadGame("/rom.gba")) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
PAD_ScanPads();
|
||||
u16 padkeys = PAD_ButtonsDown(0);
|
||||
int keys = 0;
|
||||
gba.keySource = &keys;
|
||||
if (padkeys & PAD_BUTTON_A) {
|
||||
keys |= 1 << GBA_KEY_A;
|
||||
}
|
||||
if (padkeys & PAD_BUTTON_B) {
|
||||
keys |= 1 << GBA_KEY_B;
|
||||
}
|
||||
if (padkeys & PAD_TRIGGER_L) {
|
||||
keys |= 1 << GBA_KEY_L;
|
||||
}
|
||||
if (padkeys & PAD_TRIGGER_R) {
|
||||
keys |= 1 << GBA_KEY_R;
|
||||
}
|
||||
if (padkeys & PAD_BUTTON_START) {
|
||||
keys |= 1 << GBA_KEY_START;
|
||||
}
|
||||
if (padkeys & (PAD_BUTTON_X | PAD_BUTTON_Y)) {
|
||||
keys |= 1 << GBA_KEY_SELECT;
|
||||
}
|
||||
if (padkeys & PAD_BUTTON_LEFT) {
|
||||
keys |= 1 << GBA_KEY_LEFT;
|
||||
}
|
||||
if (padkeys & PAD_BUTTON_RIGHT) {
|
||||
keys |= 1 << GBA_KEY_RIGHT;
|
||||
}
|
||||
if (padkeys & PAD_BUTTON_UP) {
|
||||
keys |= 1 << GBA_KEY_UP;
|
||||
}
|
||||
if (padkeys & PAD_BUTTON_DOWN) {
|
||||
keys |= 1 << GBA_KEY_DOWN;
|
||||
}
|
||||
if (padkeys & PAD_TRIGGER_Z) {
|
||||
break;
|
||||
}
|
||||
int frameCount = gba.video.frameCounter;
|
||||
while (gba.video.frameCounter == frameCount) {
|
||||
ARMRunLoop(&cpu);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(logfile);
|
||||
free(fifo);
|
||||
|
||||
rom->close(rom);
|
||||
save->close(save);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void GBAWiiFrame(void) {
|
||||
size_t x, y;
|
||||
uint64_t* texdest = (uint64_t*) texmem;
|
||||
uint64_t* texsrc = (uint64_t*) renderer.outputBuffer;
|
||||
for (y = 0; y < VIDEO_VERTICAL_PIXELS; y += 4) {
|
||||
for (x = 0; x < VIDEO_HORIZONTAL_PIXELS >> 2; ++x) {
|
||||
texdest[0 + x * 4 + y * 64] = texsrc[0 + x + y * 64];
|
||||
texdest[1 + x * 4 + y * 64] = texsrc[64 + x + y * 64];
|
||||
texdest[2 + x * 4 + y * 64] = texsrc[128 + x + y * 64];
|
||||
texdest[3 + x * 4 + y * 64] = texsrc[192 + x + y * 64];
|
||||
}
|
||||
}
|
||||
DCFlushRange(texdest, 256 * 256 * BYTES_PER_PIXEL);
|
||||
|
||||
GX_SetViewport(0, 0, mode->fbWidth, mode->efbHeight, 0, 1);
|
||||
GX_InvalidateTexAll();
|
||||
GX_LoadTexObj(&tex, GX_TEXMAP0);
|
||||
|
||||
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||||
GX_Position2s16(0, 256);
|
||||
GX_TexCoord2s16(0, 1);
|
||||
|
||||
GX_Position2s16(256, 256);
|
||||
GX_TexCoord2s16(1, 1);
|
||||
|
||||
GX_Position2s16(256, 0);
|
||||
GX_TexCoord2s16(1, 0);
|
||||
|
||||
GX_Position2s16(0, 0);
|
||||
GX_TexCoord2s16(0, 0);
|
||||
GX_End();
|
||||
|
||||
GX_DrawDone();
|
||||
|
||||
whichFb = !whichFb;
|
||||
|
||||
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
||||
GX_SetColorUpdate(GX_TRUE);
|
||||
GX_CopyDisp(framebuffer[whichFb], GX_TRUE);
|
||||
VIDEO_SetNextFramebuffer(framebuffer[whichFb]);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
|
||||
bool GBAWiiLoadGame(const char* path) {
|
||||
rom = VFileFOpen(path, "rb");
|
||||
|
||||
if (!rom) {
|
||||
return false;
|
||||
}
|
||||
if (!GBAIsROM(rom)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
save = VFileFOpen("test.sav", "w+b");
|
||||
|
||||
GBALoadROM(&gba, rom, save, path);
|
||||
|
||||
struct GBACartridgeOverride override;
|
||||
const struct GBACartridge* cart = (const struct GBACartridge*) gba.memory.rom;
|
||||
memcpy(override.id, &cart->id, sizeof(override.id));
|
||||
if (GBAOverrideFind(0, &override)) {
|
||||
GBAOverrideApply(&gba, &override);
|
||||
}
|
||||
|
||||
ARMReset(&cpu);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GBAWiiLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args) {
|
||||
UNUSED(thread);
|
||||
UNUSED(level);
|
||||
vfprintf(logfile, format, args);
|
||||
fprintf(logfile, "\n");
|
||||
fflush(logfile);
|
||||
}
|
||||
|
||||
static void _postVideoFrame(struct GBAAVStream* stream, struct GBAVideoRenderer* renderer) {
|
||||
UNUSED(stream);
|
||||
UNUSED(renderer);
|
||||
GBAWiiFrame();
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/* Copyright (c) 2013-2015 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 "util/memory.h"
|
||||
|
||||
void* anonymousMemoryMap(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void mappedMemoryFree(void* memory, size_t size) {
|
||||
UNUSED(size);
|
||||
free(memory);
|
||||
}
|
|
@ -32,6 +32,9 @@ typedef int32_t ssize_t;
|
|||
#define strcasecmp _stricmp
|
||||
#define strncasecmp _strnicmp
|
||||
#define ftruncate _chsize
|
||||
#elif defined(__wii__)
|
||||
typedef int32_t ssize_t;
|
||||
#define SSIZE_MAX ((ssize_t) SIZE_MAX)
|
||||
#else
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
|
Loading…
Reference in New Issue