PANDORA: First Port, using X11/Linux and OSS for Sound Output

This commit is contained in:
ptitSeb 2013-12-20 16:24:38 +01:00
parent 32dcba0db0
commit aa385f3320
7 changed files with 347 additions and 9 deletions

6
newdc/build.h Normal file → Executable file
View File

@ -45,7 +45,7 @@
#define COMPILER_GCC 0x30000002
///
#if (!defined(TARGET_WIN86) && !defined(TARGET_BEAGLE) && !defined(TARGET_NACL32) && !defined(TARGET_GCW0))
#if (!defined(TARGET_WIN86) && !defined(TARGET_BEAGLE) && !defined(TARGET_NACL32) && !defined(TARGET_GCW0) && !defined(TARGET_PANDORA))
#define TARGET_WIN86
#endif
@ -53,6 +53,10 @@
#define HOST_OS OS_WINDOWS
#define HOST_CPU CPU_X86
#define BUILD_COMPILER COMPILER_VC
#elif TARGET_PANDORA
#define HOST_OS OS_LINUX
#define HOST_CPU CPU_ARM
#define BUILD_COMPILER COMPILER_GCC
#elif TARGET_BEAGLE
#define HOST_OS OS_LINUX
#define HOST_CPU CPU_ARM

190
newdc/linux-dist/main.cpp Normal file → Executable file
View File

@ -28,10 +28,18 @@
#include <linux/joystick.h>
#endif
#ifdef TARGET_PANDORA
#include <signal.h>
#include <execinfo.h>
#include <sys/soundcard.h>
#define WINDOW_WIDTH 800
#else
#define WINDOW_WIDTH 640
#endif
#define WINDOW_HEIGHT 480
void* x11_win,* x11_disp;
void* x11_win=0,* x11_disp=0;
void* libPvr_GetRenderTarget()
{
return x11_win;
@ -92,6 +100,10 @@ void emit_WriteCodeCache();
static int JoyFD = -1; // Joystick file descriptor
static int kbfd = -1;
#ifdef TARGET_PANDORA
static int audio_fd = -1;
#endif
#define MAP_SIZE 32
@ -121,7 +133,11 @@ void SetupInput()
}
if (true) {
#ifdef TARGET_PANDORA
const char* device = "/dev/input/event4";
#else
const char* device = "/dev/event2";
#endif
char name[256]= "Unknown";
if ((kbfd = open(device, O_RDONLY)) > 0) {
@ -170,9 +186,48 @@ bool HandleKb(u32 port) {
if (kbfd < 0)
return false;
#ifdef TARGET_PANDORA
static int keys[13];
while(read(kbfd,&ie,sizeof(ie))==sizeof(ie)) {
if (ie.type=EV_KEY)
//printf("type %i key %i state %i\n", ie.type, ie.code, ie.value);
switch (ie.code) {
case KEY_SPACE: keys[0]=ie.value; break;
case KEY_UP: keys[1]=ie.value; break;
case KEY_DOWN: keys[2]=ie.value; break;
case KEY_LEFT: keys[3]=ie.value; break;
case KEY_RIGHT: keys[4]=ie.value; break;
case KEY_PAGEUP:keys[5]=ie.value; break;
case KEY_PAGEDOWN:keys[6]=ie.value; break;
case KEY_END: keys[7]=ie.value; break;
case KEY_HOME: keys[8]=ie.value; break;
case KEY_MENU: keys[9]=ie.value; break;
case KEY_RIGHTSHIFT: keys[10]=ie.value; break;
case KEY_RIGHTCTRL: keys[11]=ie.value; break;
case KEY_LEFTALT: keys[12]=ie.value; break;
}
}
if (keys[0]) { kcode[port] &= ~Btn_C; }
if (keys[6]) { kcode[port] &= ~Btn_A; }
if (keys[7]) { kcode[port] &= ~Btn_B; }
if (keys[5]) { kcode[port] &= ~Btn_Y; }
if (keys[8]) { kcode[port] &= ~Btn_X; }
if (keys[1]) { kcode[port] &= ~DPad_Up; }
if (keys[2]) { kcode[port] &= ~DPad_Down; }
if (keys[3]) { kcode[port] &= ~DPad_Left; }
if (keys[4]) { kcode[port] &= ~DPad_Right; }
if (keys[12]){ kcode[port] &= ~Btn_Start; }
if (keys[9]){ die("death by escape key"); }
if (keys[10]) rt[port]=255;
if (keys[11]) lt[port]=255;
return true;
#else
while(read(kbfd,&ie,sizeof(ie))==sizeof(ie)) {
printf("type %i key %i state %i\n", ie.type, ie.code, ie.value);
}
#endif
}
@ -268,16 +323,40 @@ bool HandleJoystick(u32 port)
extern bool KillTex;
#ifdef TARGET_PANDORA
static Cursor CreateNullCursor(Display *display, Window root)
{
Pixmap cursormask;
XGCValues xgc;
GC gc;
XColor dummycolour;
Cursor cursor;
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
#endif
void UpdateInputState(u32 port)
{
static char key = 0;
if (HandleJoystick(port)) return;
if (HandleKb(port)) return;
kcode[port]=0xFFFF;
rt[port]=0;
lt[port]=0;
if (HandleJoystick(port)) return;
if (HandleKb(port)) return;
for(;;)
{
@ -287,6 +366,17 @@ void UpdateInputState(u32 port)
if (0 == key || EOF == key) break;
if ('k' == key) KillTex=true;
#ifdef TARGET_PANDORA
if (' ' == key) { kcode[port] &= ~Btn_C; }
if ('6' == key) { kcode[port] &= ~Btn_A; }
if ('O' == key) { kcode[port] &= ~Btn_B; }
if ('5' == key) { kcode[port] &= ~Btn_Y; }
if ('H' == key) { kcode[port] &= ~Btn_X; }
if ('A' == key) { kcode[port] &= ~DPad_Up; }
if ('B' == key) { kcode[port] &= ~DPad_Down; }
if ('D' == key) { kcode[port] &= ~DPad_Left; }
if ('C' == key) { kcode[port] &= ~DPad_Right; }
#else
if ('b' == key) { kcode[port] &= ~Btn_C; }
if ('v' == key) { kcode[port] &= ~Btn_A; }
if ('c' == key) { kcode[port] &= ~Btn_B; }
@ -296,8 +386,11 @@ void UpdateInputState(u32 port)
if ('k' == key) { kcode[port] &= ~DPad_Down; }
if ('j' == key) { kcode[port] &= ~DPad_Left; }
if ('l' == key) { kcode[port] &= ~DPad_Right; }
#endif
if (0x0A== key) { kcode[port] &= ~Btn_Start; }
#ifdef TARGET_PANDORA
if ('q' == key){ die("death by escape key"); }
#endif
//if (0x1b == key){ die("death by escape key"); } //this actually quits when i press left for some reason
if ('a' == key) rt[port]=255;
@ -311,7 +404,6 @@ void UpdateInputState(u32 port)
}
}
void os_DoEvents()
{
@ -379,8 +471,13 @@ void os_CreateWindow()
sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;
ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
#ifdef TARGET_PANDORA
int width=800;
int height=480;
#else
int width=cfgLoadInt("x11","width", WINDOW_WIDTH);
int height=cfgLoadInt("x11","height", WINDOW_HEIGHT);
#endif
if (width==-1)
{
@ -390,9 +487,20 @@ void os_CreateWindow()
// Creates the X11 window
x11Window = XCreateWindow( x11Display, RootWindow(x11Display, x11Screen), (ndcid%3)*640, (ndcid/3)*480, width, height,
0, CopyFromParent, InputOutput, CopyFromParent, ui32Mask, &sWA);
#ifdef TARGET_PANDORA
// fullscreen
Atom wmState = XInternAtom(x11Display, "_NET_WM_STATE", False);
Atom wmFullscreen = XInternAtom(x11Display, "_NET_WM_STATE_FULLSCREEN", False);
XChangeProperty(x11Display, x11Window, wmState, XA_ATOM, 32, PropModeReplace, (unsigned char *)&wmFullscreen, 1);
XMapRaised(x11Display, x11Window);
#else
XMapWindow(x11Display, x11Window);
#endif
XFlush(x11Display);
//(EGLNativeDisplayType)x11Display;
x11_disp=(void*)x11Display;
x11_win=(void*)x11Window;
@ -448,12 +556,75 @@ void common_linux_setup();
int dc_init(int argc,wchar* argv[]);
void dc_run();
#ifdef TARGET_PANDORA
void gl_term();
void clean_exit(int sig_num) {
void *array[10];
size_t size;
// close files
if (JoyFD>=0) close(JoyFD);
if (kbfd>=0) close(kbfd);
if(audio_fd>=0) close(audio_fd);
// Close EGL context ???
if (sig_num!=0)
gl_term();
// close XWindow
if (x11_win) {
XDestroyWindow(x11_disp, x11_win);
x11_win = 0;
}
if (x11_disp) {
XCloseDisplay(x11_disp);
x11_disp = 0;
}
// finish cleaning
if (sig_num!=0) {
write(2, "\nSignal received\n", sizeof("\nSignal received\n"));
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
}
void init_sound()
{
if((audio_fd=open("/dev/dsp",O_WRONLY))<0)
printf("Couldn't open /dev/dsp.\n");
else
{
printf("sound enabled, dsp openned for write\n");
int tmp=44100;
int err_ret;
err_ret=ioctl(audio_fd,SNDCTL_DSP_SPEED,&tmp);
printf("set Frequency to %i, return %i (rate=%i)\n", 44100, err_ret, tmp);
int channels=2;
err_ret=ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels);
printf("set dsp to stereo (%i => %i)\n", channels, err_ret);
int format=AFMT_S16_LE;
err_ret=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
printf("set dsp to %s audio (%i/%i => %i)\n", "16bits signed" ,AFMT_S16_LE, format, err_ret);
}
}
#endif
int main(int argc, wchar* argv[])
{
//if (argc==2)
//ndcid=atoi(argv[1]);
if (setup_curses() < 0) die("failed to setup curses!\n");
#ifdef TARGET_PANDORA
signal(SIGSEGV, clean_exit);
signal(SIGKILL, clean_exit);
init_sound();
#endif
SetHomeDir(".");
printf("Home dir is: %s\n",GetPath("/").c_str());
@ -467,12 +638,19 @@ int main(int argc, wchar* argv[])
dc_init(argc,argv);
dc_run();
#ifdef TARGET_PANDORA
clean_exit(0);
#endif
return 0;
}
u32 os_Push(void* frame, u32 samples, bool wait)
{
#ifdef TARGET_PANDORA
write(audio_fd, frame, samples*4);
#endif
return 1;
}
#endif

9
newdc/newdc.mk Normal file → Executable file
View File

@ -37,9 +37,18 @@ RZDCY_FILES := $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(w
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.c))
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.S))
ifdef FOR_PANDORA
RZDCY_CXXFLAGS := \
$(CFLAGS) -c -g -O3 -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/deps \
-DRELEASE -DPANDORA\
-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp \
-frename-registers -fsingle-precision-constant -ffast-math \
-ftree-vectorize -fomit-frame-pointer -fno-exceptions -fno-rtti -std=gnu++11
else
RZDCY_CXXFLAGS := \
$(CFLAGS) -c -g -O3 -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/deps \
-D_ANDROID -DRELEASE -DTARGET_BEAGLE\
-march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -mfloat-abi=softfp \
-frename-registers -fsingle-precision-constant -ffast-math \
-ftree-vectorize -fomit-frame-pointer -fno-exceptions -fno-rtti -std=gnu++11
endif

2
newdc/nullDC.cpp Normal file → Executable file
View File

@ -230,7 +230,7 @@ void LoadSettings()
settings.pvr.ta_skip = cfgLoadInt("config","ta.skip",0);
settings.pvr.rend = cfgLoadInt("config","pvr.rend",0);
#if (HOST_OS != OS_LINUX || defined(_ANDROID))
#if (HOST_OS != OS_LINUX || defined(_ANDROID) || defined(TARGET_PANDORA))
settings.aica.BufferSize=2048;
#else
settings.aica.BufferSize=1024;

48
newdc/rend/gles/gles.cpp Normal file → Executable file
View File

@ -3,6 +3,18 @@
#include "rend/TexCache.h"
#include "cfg/cfg.h"
#ifdef TARGET_PANDORA
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#ifndef FBIO_WAITFORVSYNC
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
#endif
int fbdev = -1;
#endif
/*
GL|ES 2
Slower, smaller subset of gl2
@ -304,12 +316,16 @@ int screen_height;
//create a basic gles context
bool gl_init(EGLNativeWindowType wind, EGLNativeDisplayType disp)
{
#ifndef _ANDROID
#if !defined(_ANDROID)
gl.setup.native_wind=wind;
gl.setup.native_disp=disp;
//try to get a display
#ifdef TARGET_PANDORA0
gl.setup.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
#else
gl.setup.display = eglGetDisplay(gl.setup.native_disp);
#endif
//if failed, get the default display (this will not happen in win32)
if(gl.setup.display == EGL_NO_DISPLAY)
@ -342,7 +358,11 @@ bool gl_init(EGLNativeWindowType wind, EGLNativeDisplayType disp)
return false;
}
#ifdef TARGET_PANDORA0
gl.setup.surface = eglCreateWindowSurface(gl.setup.display, config, (NativeWindowType)NULL, NULL);
#else
gl.setup.surface = eglCreateWindowSurface(gl.setup.display, config, wind, NULL);
#endif
if (eglCheck())
return false;
@ -384,6 +404,12 @@ void egl_stealcntx()
//swap buffers
void gl_swap()
{
#ifdef TARGET_PANDORA0
if (fbdev >= 0) {
int arg = 0;
ioctl(fbdev,FBIO_WAITFORVSYNC,&arg);
}
#endif
eglSwapBuffers(gl.setup.display, gl.setup.surface);
}
@ -393,6 +419,21 @@ void gl_term()
#if HOST_OS==OS_WINDOWS
ReleaseDC((HWND)gl.setup.native_wind,(HDC)gl.setup.native_disp);
#endif
#ifdef TARGET_PANDORA
eglMakeCurrent( gl.setup.display, NULL, NULL, EGL_NO_CONTEXT );
if (gl.setup.context)
eglDestroyContext(gl.setup.display, gl.setup.context);
if (gl.setup.surface)
eglDestroySurface(gl.setup.display, gl.setup.surface);
if (gl.setup.display)
eglTerminate(gl.setup.display);
if (fbdev>=0) close( fbdev );
fbdev=-1;
gl.setup.context=0;
gl.setup.surface=0;
gl.setup.display=0;
#endif
}
@ -683,7 +724,11 @@ bool gles_init()
return false;
#ifdef TARGET_PANDORA
fbdev=open("/dev/fb0", O_RDONLY);
#else
eglSwapInterval(gl.setup.display,1);
#endif
//clean up all buffers ...
for (int i=0;i<10;i++)
@ -697,6 +742,7 @@ bool gles_init()
}
float fog_coefs[]={0,0};
void tryfit(float* x,float* y)
{

View File

@ -21,6 +21,10 @@
#define VERTEX_COL_OFFS_ARRAY 2
#define VERTEX_UV_ARRAY 3
#ifdef TARGET_PANDORA
#define WEIRD_SLOWNESS
#endif
//vertex types
extern u32 gcflip;

97
reicast/pandora/Makefile Executable file
View File

@ -0,0 +1,97 @@
LOCAL_PATH := $(call my-dir)
FOR_LINUX :=1
FOR_ARM :=1
FOR_PANDORA :=1
RZDCY_SRC_DIR = ../../newdc
include $(RZDCY_SRC_DIR)/newdc.mk
CC_PREFIX ?=
CXX=${CC_PREFIX}g++
CC=${CC_PREFIX}gcc
AS=${CC_PREFIX}as
STRIP=${CC_PREFIX}strip
LD=${CC}
MFLAGS := -marm -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp -funroll-loops -fpermissive
ASFLAGS := -march=armv7-a -mfpu=neon -mfloat-abi=softfp
LDFLAGS := -g -Wl,-Map,$(notdir $@).map,--gc-sections -Wl,-O3 -Wl,--sort-common
SOURCES := cfg/ hw/arm7/ hw/aica/ hw/asic/ hw/ hw/gdrom/ hw/maple/ \
hw/mem/ hw/pvr/ hw/sh4/ hw/sh4/rec_v2/ plugins/ profiler/ serial_ipc/ \
hw/extdev/ hw/arm/ imgread/ linux/ linux-dist/ ./ rec-ARM/ deps/zlib/ deps/chdr/ deps/crypto/ arm_emitter/
CXXFLAGS := -g -O3 -D RELEASE -c -D TARGET_PANDORA
CXXFLAGS += -frename-registers -fno-strict-aliasing -fsingle-precision-constant
CXXFLAGS += -ffast-math -ftree-vectorize -fprefetch-loop-arrays
#-std=c++0x
CXXFLAGS += $(CFLAGS) $(MFLAGS) -fno-exceptions -fno-rtti
CXXFLAGS += -D SUPPORT_X11
ifdef PGO_MAKE
CXXFLAGS += -fprofile-generate -pg
LDFLAGS += -fprofile-generate
else
CXXFLAGS += -fomit-frame-pointer
endif
ifdef PGO_USE
CXXFLAGS += -fprofile-use
endif
ifdef LTO_TEST
CXXFLAGS += -flto -fwhole-program
LDFLAGS +=-flto -fwhole-program
endif
INCS := -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/deps -I$(RZDCY_SRC_DIR)/khronos
#-I../linux-deps/include
LIBS := -L../linux-deps/lib
LIBS += -lm -lrt -lEGL -lGLESv2 #-lglslcompiler -lIMGegl -lpvr2d -lsrv_um
LIBS += -lpthread -lasound -lX11 -lXdmcp -lXau
OBJECTS=$(RZDCY_FILES:.cpp=.build_obj)
OBJECTS:=$(OBJECTS:.c=.build_obj)
OBJECTS:=$(OBJECTS:.S=.build_obj)
OBJECTS:=$(patsubst $(RZDCY_SRC_DIR)/%,obj/%,$(OBJECTS))
EXECUTABLE_STRIPPED=nosym-reicast.elf
EXECUTABLE=reicast.elf
all: $(CPPFILES) $(EXECUTABLE) $(EXECUTABLE_STRIPPED)
echo $(RZDCY_FILES)
$(EXECUTABLE): $(OBJECTS)
echo $(RZDCY_FILES)
$(CXX) $(MFLAGS) $(EXTRAFLAGS) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@
$(EXECUTABLE_STRIPPED): $(EXECUTABLE)
cp $< $@ && $(STRIP) $@
obj/%.build_obj : $(RZDCY_SRC_DIR)/%.cpp
mkdir -p $(dir $@)
$(CXX) $(EXTRAFLAGS) $(INCS) $(CXXFLAGS) $< -o $@
obj/%.build_obj : $(RZDCY_SRC_DIR)/%.c
mkdir -p $(dir $@)
$(CC) $(EXTRAFLAGS) $(INCS) $(CXXFLAGS) $< -o $@
obj/%.build_obj : $(RZDCY_SRC_DIR)/%.S
mkdir -p $(dir $@)
$(AS) $(ASFLAGS) $(INCS) $< -o $@
clean:
rm $(OBJECTS) $(EXECUTABLE) -f