Skip to content

Commit 0e9258a

Browse files
mardyjtsiomb
authored andcommitted
OGC: video, joystick, keyboard and mouse support
1 parent 0a94037 commit 0e9258a

9 files changed

+436
-19
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ ELSEIF(CMAKE_SYSTEM_NAME MATCHES "NintendoWii|NintendoGameCube")
214214
src/ogc/fg_structure_ogc.c
215215
src/ogc/fg_window_ogc.c
216216
)
217+
LIST(APPEND LIBS wiikeyboard fat)
217218
SET(FREEGLUT_BUILD_SHARED_LIBS OFF)
218219
# Only used in fg_window.c, to declare support for double buffering
219220
ADD_DEFINITIONS(-DEGL_VERSION_1_0)

src/ogc/fg_common_ogc.h

+17
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,21 @@
2525
#include <GL/freeglut.h>
2626
#include "../fg_internal.h"
2727

28+
#define MAX_GC_JOYSTICKS 4
29+
30+
#ifdef __wii__
31+
#define MAX_WII_JOYSTICKS 4
32+
#else
33+
#define MAX_WII_JOYSTICKS 0
34+
#endif
35+
36+
#define MAX_OGC_JOYSTICKS (MAX_GC_JOYSTICKS + MAX_WII_JOYSTICKS)
37+
38+
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height,
39+
GLboolean forceNotify);
40+
41+
void fgOgcDisplaySetupVideoMode();
42+
void fgOgcDisplaySetupXfb();
43+
void fgOgcDisplayShowEFB();
44+
2845
#endif /* FREEGLUT_COMMON_OGC_H */

src/ogc/fg_display_ogc.c

+76-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,83 @@
2121

2222
#include "fg_common_ogc.h"
2323

24+
void fgOgcDisplaySetupXfb()
25+
{
26+
GXRModeObj *vmode = fgDisplay.pDisplay.vmode;
27+
28+
if (fgDisplay.pDisplay.vmode_changed) {
29+
/* The size of the XFB might be different, so reallocate it */
30+
if (fgDisplay.pDisplay.xfb[0]) {
31+
free(MEM_K1_TO_K0(fgDisplay.pDisplay.xfb[0]));
32+
fgDisplay.pDisplay.xfb[0] = NULL;
33+
}
34+
if (fgDisplay.pDisplay.xfb[1]) {
35+
free(MEM_K1_TO_K0(fgDisplay.pDisplay.xfb[1]));
36+
fgDisplay.pDisplay.xfb[1] = NULL;
37+
}
38+
}
39+
40+
if (!fgDisplay.pDisplay.xfb[0]) {
41+
fgDisplay.pDisplay.xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
42+
}
43+
if (fgState.DisplayMode & GLUT_DOUBLE && !fgDisplay.pDisplay.xfb[1]) {
44+
fgDisplay.pDisplay.xfb[1] =
45+
MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
46+
}
47+
}
48+
49+
void fgOgcDisplaySetupVideoMode()
50+
{
51+
GXRModeObj *vmode = fgDisplay.pDisplay.vmode;
52+
53+
fgOgcDisplaySetupXfb();
54+
55+
VIDEO_Configure(vmode);
56+
VIDEO_SetNextFramebuffer(fgDisplay.pDisplay.xfb[0]);
57+
VIDEO_SetBlack(FALSE);
58+
VIDEO_Flush();
59+
60+
VIDEO_WaitVSync();
61+
if (vmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
62+
63+
f32 yscale = GX_GetYScaleFactor(vmode->efbHeight, vmode->xfbHeight);
64+
GX_SetDispCopyYScale(yscale);
65+
GX_SetDispCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight);
66+
GX_SetDispCopyDst(vmode->fbWidth, vmode->xfbHeight);
67+
GX_SetCopyFilter(vmode->aa, vmode->sample_pattern, GX_TRUE, vmode->vfilter);
68+
69+
fgDisplay.ScreenWidth = vmode->fbWidth;
70+
fgDisplay.ScreenHeight = vmode->efbHeight;
71+
fgDisplay.pDisplay.vmode_changed = 0;
72+
}
73+
74+
void fgOgcDisplayShowEFB()
75+
{
76+
void *xfb;
77+
u8 mustClear, mustWait;
78+
79+
if (fgState.DisplayMode & GLUT_DOUBLE) {
80+
mustClear = GX_TRUE;
81+
mustWait = GX_TRUE;
82+
xfb = fgDisplay.pDisplay.xfb[fgDisplay.pDisplay.fbIndex];
83+
fgDisplay.pDisplay.fbIndex ^= 1;
84+
} else {
85+
mustClear = GX_FALSE;
86+
mustWait = GX_FALSE;
87+
xfb = fgDisplay.pDisplay.xfb[0];
88+
}
89+
GX_CopyDisp(xfb, mustClear);
90+
GX_DrawDone();
91+
GX_Flush();
92+
93+
VIDEO_SetNextFramebuffer(xfb);
94+
VIDEO_Flush();
95+
if (mustWait)
96+
VIDEO_WaitVSync();
97+
}
98+
2499
void fgPlatformGlutSwapBuffers(SFG_PlatformDisplay *pDisplayPtr,
25100
SFG_Window *CurrentWindow)
26101
{
27-
fgWarning("%s() : not implemented", __func__);
102+
fgOgcDisplayShowEFB();
28103
}

src/ogc/fg_ext_ogc.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@
2323

2424
SFG_Proc fgPlatformGetProcAddress(const char *procName)
2525
{
26-
fgWarning("%s() : not implemented", __func__);
26+
#define CHECK_NAME(x) if (strcmp(procName, #x) == 0) return (SFG_Proc)x
27+
/* TODO: add functions here */
28+
#undef CHECK_NAME
29+
fgWarning("%s() : not implemented (%s)", __func__, procName);
2730
return NULL;
2831
}
2932

3033
GLUTproc fgPlatformGetGLUTProcAddress(const char *procName)
3134
{
32-
fgWarning("%s() : not implemented", __func__);
35+
if (strncmp(procName, "glut", 4) != 0)
36+
return NULL;
37+
38+
fgWarning("%s() : not implemented (%s)", __func__, procName);
3339
return NULL;
3440
}
3541

src/ogc/fg_init_ogc.c

+22-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,30 @@
2121

2222
#include "fg_common_ogc.h"
2323

24+
#include <fat.h>
25+
#include <malloc.h>
26+
#include <opengx.h>
27+
28+
#define FIFO_SIZE (256*1024)
29+
2430
void fgPlatformInitialize(const char *displayName)
2531
{
26-
fgWarning("%s() : not implemented", __func__);
32+
VIDEO_Init();
33+
34+
void *fifoBuffer = MEM_K0_TO_K1(memalign(32, FIFO_SIZE));
35+
memset(fifoBuffer, 0, FIFO_SIZE);
36+
37+
GX_Init(fifoBuffer, FIFO_SIZE);
38+
fgDisplay.pDisplay.vmode = VIDEO_GetPreferredMode(NULL);
39+
fgOgcDisplaySetupVideoMode();
40+
41+
ogx_initialize();
42+
43+
fatInitDefault();
44+
45+
fgState.Time = fgSystemTime();
46+
fgState.FPSInterval = 2000;
47+
fgState.Initialised = GL_TRUE;
2748
}
2849

2950
void fgPlatformDeinitialiseInputDevices(void)

src/ogc/fg_internal_ogc.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,22 @@
2323
#define FREEGLUT_INTERNAL_OGC_H
2424

2525
/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */
26-
/* TODO: add libogc and opengx */
26+
#include <ogc/gx.h>
27+
#include <ogc/gx_struct.h>
28+
#include <ogc/system.h>
29+
#include <ogc/video.h>
2730

2831
/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
2932
/* The structure used by display initialization in fg_init.c */
3033
typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
3134
struct tagSFG_PlatformDisplay
3235
{
33-
bool unused;
36+
/* The pointer(s) to the XFB(s). The second one can be NULL if double
37+
* buffering is not used. */
38+
void *xfb[2];
39+
u8 fbIndex;
40+
bool vmode_changed;
41+
GXRModeObj *vmode;
3442
};
3543

3644
/* The structure used by window creation in fg_window.c */
@@ -67,6 +75,7 @@ typedef uint32_t SFG_WindowColormapType;
6775
#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
6876
#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
6977

70-
#define _JS_MAX_AXES 9
78+
#define _JS_MAX_AXES 4
79+
#define MAX_NUM_JOYSTICKS 8
7180

7281
#endif /* FREEGLUT_INTERNAL_OGC_H */

src/ogc/fg_joystick_ogc.c

+77-3
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,93 @@
2121

2222
#include "fg_common_ogc.h"
2323

24+
#include <wiiuse/wpad.h>
25+
2426
void fgPlatformJoystickRawRead(SFG_Joystick *joy, int *buttons, float *axes)
2527
{
26-
fgWarning("%s() : not implemented", __func__);
28+
*buttons = 0;
29+
30+
if (joy->id < MAX_GC_JOYSTICKS) {
31+
u16 btns = PAD_ButtonsHeld(joy->id);
32+
if (btns & PAD_BUTTON_A) *buttons |= 0x1;
33+
if (btns & PAD_BUTTON_B) *buttons |= 0x2;
34+
if (btns & PAD_BUTTON_X) *buttons |= 0x4;
35+
if (btns & PAD_BUTTON_Y) *buttons |= 0x8;
36+
if (btns & PAD_TRIGGER_L) *buttons |= 0x10;
37+
if (btns & PAD_TRIGGER_R) *buttons |= 0x20;
38+
if (btns & PAD_TRIGGER_Z) *buttons |= 0x40;
39+
if (btns & PAD_BUTTON_MENU) *buttons |= 0x80;
40+
if (btns & PAD_BUTTON_START) *buttons |= 0x100;
41+
axes[0] = PAD_StickX(joy->id) / 127.0;
42+
axes[1] = PAD_StickY(joy->id) / 127.0;
43+
axes[2] = PAD_SubStickX(joy->id) / 127.0;
44+
axes[3] = PAD_SubStickY(joy->id) / 127.0;
45+
return;
46+
}
47+
48+
#ifdef __wii__
49+
int id = joy->id - MAX_GC_JOYSTICKS;
50+
if (id < MAX_WII_JOYSTICKS) {
51+
WPADData *data = WPAD_Data(id);
52+
u32 btns = data->btns_h;
53+
axes[0] = 0.0;
54+
axes[1] = 0.0;
55+
if (btns & WPAD_BUTTON_LEFT) axes[0] = -1.0;
56+
if (btns & WPAD_BUTTON_RIGHT) axes[0] = 1.0;
57+
if (btns & WPAD_BUTTON_UP) axes[1] = 1.0;
58+
if (btns & WPAD_BUTTON_DOWN) axes[1] = -1.0;
59+
60+
if (btns & WPAD_BUTTON_1) *buttons |= 0x1;
61+
if (btns & WPAD_BUTTON_2) *buttons |= 0x2;
62+
if (btns & WPAD_BUTTON_A) *buttons |= 0x4;
63+
if (btns & WPAD_BUTTON_B) *buttons |= 0x8;
64+
if (btns & WPAD_BUTTON_MINUS) *buttons |= 0x10;
65+
if (btns & WPAD_BUTTON_PLUS) *buttons |= 0x20;
66+
if (btns & WPAD_BUTTON_HOME) *buttons |= 0x40;
67+
}
68+
#endif
2769
}
2870

2971
void fgPlatformJoystickOpen(SFG_Joystick *joy)
3072
{
31-
fgWarning("%s() : not implemented", __func__);
73+
fgWarning("%s() called for joystick %d", __func__, joy->id);
74+
joy->error = GL_FALSE;
75+
if (joy->id < MAX_GC_JOYSTICKS) {
76+
sprintf(joy->name, "GameCube #%d", joy->id);
77+
joy->num_axes = 4;
78+
joy->num_buttons = 8;
79+
} else {
80+
sprintf(joy->name, "Wiimote #%d", joy->id - MAX_GC_JOYSTICKS);
81+
joy->num_axes = 2;
82+
joy->num_buttons = 7;
83+
}
84+
85+
for (int i = 0; i < joy->num_axes; i++) {
86+
joy->center[i] = 0.0;
87+
joy->max[i] = 1.0;
88+
joy->min[i] = -1.0;
89+
joy->dead_band[i] = 0.0;
90+
joy->saturate[i] = 1.0;
91+
}
3292
}
3393

3494
void fgPlatformJoystickInit(SFG_Joystick *fgJoystick[], int ident)
3595
{
36-
fgWarning("%s() : not implemented", __func__);
96+
static bool initialized = false;
97+
if (!initialized) {
98+
initialized = true;
99+
100+
PAD_Init();
101+
/* WPAD is initialized in fgPlatformMainLoopPreliminaryWork(), since
102+
* it's used for mouse emulation as well. */
103+
}
104+
105+
fgWarning("%s called for ident %d\n", __func__, ident);
106+
if (ident < MAX_OGC_JOYSTICKS) {
107+
SFG_Joystick *joy = fgJoystick[ident];
108+
joy->id = ident;
109+
joy->error = GL_FALSE;
110+
}
37111
}
38112

39113
void fgPlatformJoystickClose(int ident)

0 commit comments

Comments
 (0)