Get rid of PND_BUILD/RPI_BUILD/POLLUX_BUILD/GIZ_BUILD
This commit is contained in:
parent
862e940b8c
commit
093a70482f
36
common.h
36
common.h
|
@ -49,9 +49,6 @@
|
|||
#include <sys/time.h>
|
||||
#endif /* _WIN32_WCE */
|
||||
|
||||
#ifdef GIZ_BUILD
|
||||
#include "giz/giz.h"
|
||||
#endif
|
||||
#endif /* ARM_ARCH */
|
||||
|
||||
// Huge thanks to pollux for the heads up on using native file I/O
|
||||
|
@ -140,21 +137,9 @@
|
|||
#define file_check_valid(filename_tag) \
|
||||
(filename_tag) \
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
|
||||
#define file_close(filename_tag) \
|
||||
{ \
|
||||
fclose(filename_tag); \
|
||||
sync(); \
|
||||
} \
|
||||
|
||||
#else
|
||||
|
||||
#define file_close(filename_tag) \
|
||||
fclose(filename_tag) \
|
||||
|
||||
#endif
|
||||
|
||||
#define file_read(filename_tag, buffer, size) \
|
||||
fread(buffer, 1, size, filename_tag) \
|
||||
|
||||
|
@ -253,25 +238,4 @@ typedef u32 fixed8_24;
|
|||
//#define REGISTER_USAGE_ANALYZE
|
||||
#endif
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
#include <strings.h>
|
||||
#include "gp2x/gp2x.h"
|
||||
|
||||
#define printf(format, ...) \
|
||||
fprintf(stderr, format, ##__VA_ARGS__) \
|
||||
|
||||
#define vprintf(format, ap) \
|
||||
vfprintf(stderr, format, ap) \
|
||||
|
||||
// #define STDIO_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef PND_BUILD
|
||||
#include "pandora/pnd.h"
|
||||
#endif
|
||||
|
||||
#ifdef RPI_BUILD
|
||||
#include "raspberrypi/rpi.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
# gpSP makefile
|
||||
# Gilead Kutnick - Exophase
|
||||
# GP2X port(ion) - Z
|
||||
|
||||
# Global definitions
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
|
||||
OBJS = main.o cpu.o memory.u video.o input.o sound.o gp2x.o gui.o \
|
||||
cheats.o zip.o cpu_threaded.z arm_stub.o video_blend.o \
|
||||
warm.o upscale_aspect.o
|
||||
ifeq ($(WIZ),1)
|
||||
POLLUX = 1
|
||||
OBJS += pollux_dpc_set.o
|
||||
BIN = gpsp_wiz
|
||||
endif
|
||||
ifeq ($(CAANOO),1)
|
||||
POLLUX = 1
|
||||
OBJS += pollux_dpc_set.o
|
||||
BIN = gpsp_caanoo
|
||||
endif
|
||||
ifeq ($(BIN),)
|
||||
BIN = gpsp_gp2x
|
||||
endif
|
||||
|
||||
-include Makefile.local
|
||||
|
||||
# Platform specific definitions
|
||||
|
||||
VPATH += .. ../arm
|
||||
CFLAGS += -DARM_ARCH -DGP2X_BUILD
|
||||
ifeq ($(WIZ),1)
|
||||
CFLAGS += -DWIZ_BUILD
|
||||
endif
|
||||
ifeq ($(POLLUX),1)
|
||||
CFLAGS += -DPOLLUX_BUILD
|
||||
endif
|
||||
CFLAGS += -std=c99 -msoft-float -funsigned-char -Wall -ggdb
|
||||
ifndef DEBUG
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
INCLUDES = `sdl-config --cflags`
|
||||
LIBS = `sdl-config --libs` \
|
||||
-lm -ldl -lpthread -lz
|
||||
ifeq ($(WIZ)$(CAANOO),)
|
||||
LIBS += -static
|
||||
endif
|
||||
|
||||
# Compilation:
|
||||
|
||||
.SUFFIXES: .c
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
cpu.o cpu_threaded.z: CFLAGS += -Wno-unused-variable -Wno-unused-label
|
||||
|
||||
%.z: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.u: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.o: %.S
|
||||
$(CC) $(ASFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.o: %.s
|
||||
$(CC) $(ASFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(OBJS) $(LIBS) -o $(BIN)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.u *.z $(BIN)
|
||||
|
||||
rel: gpsp_caanoo gpsp_caanoo.ini gpsp_caanoo.gpe warm_2.6.24.ko \
|
||||
../COPYING.DOC ../readme.txt readme_gp2x.txt ../game_config.txt
|
||||
rm -rf out
|
||||
mkdir -p out/gpsp_caanoo
|
||||
cp $^ out/gpsp_caanoo/
|
||||
mv out/gpsp_caanoo/gpsp_caanoo.ini out/
|
||||
mv out/gpsp_caanoo/readme_gp2x.txt out/gpsp_caanoo/readme_caanoo.txt
|
||||
echo -n '/mnt/sd' > out/gpsp_caanoo/romdir.txt
|
||||
cd out && zip -9 -r ../gpsp_caanoo.zip *
|
545
gp2x/gp2x.c
545
gp2x/gp2x.c
|
@ -1,545 +0,0 @@
|
|||
/*
|
||||
Parts used from cpuctrl, Copyright (C) 2005 Hermes/PS2Reality
|
||||
Portions Copyright (C) 2009 notaz
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include "../common.h"
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <linux/input.h>
|
||||
#include "gp2x.h"
|
||||
#include "pollux_dpc_set.h"
|
||||
|
||||
static u32 gpsp_gp2x_dev_audio;
|
||||
static u32 gpsp_gp2x_dev;
|
||||
#ifdef POLLUX_BUILD
|
||||
static u32 gpsp_gp2x_indev;
|
||||
static u32 saved_405c, saved_4060, saved_4058;
|
||||
#endif
|
||||
|
||||
static u32 gp2x_audio_volume = 74/2;
|
||||
|
||||
static volatile u16 *gpsp_gp2x_memregs;
|
||||
static volatile u32 *gpsp_gp2x_memregl;
|
||||
|
||||
u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT] =
|
||||
{
|
||||
GP2X_UP,
|
||||
GP2X_LEFT,
|
||||
GP2X_DOWN,
|
||||
GP2X_RIGHT,
|
||||
GP2X_START,
|
||||
GP2X_SELECT,
|
||||
GP2X_L,
|
||||
GP2X_R,
|
||||
GP2X_A,
|
||||
GP2X_B,
|
||||
GP2X_X,
|
||||
GP2X_Y,
|
||||
#if defined(POLLUX_BUILD) && !defined(WIZ_BUILD)
|
||||
0,
|
||||
0,
|
||||
GP2X_PUSH,
|
||||
GP2X_HOME,
|
||||
#else
|
||||
GP2X_VOL_DOWN,
|
||||
GP2X_VOL_UP,
|
||||
GP2X_PUSH,
|
||||
GP2X_VOL_MIDDLE
|
||||
#endif
|
||||
};
|
||||
|
||||
u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
|
||||
{
|
||||
BUTTON_ID_UP, // Up
|
||||
BUTTON_ID_LEFT, // Left
|
||||
BUTTON_ID_DOWN, // Down
|
||||
BUTTON_ID_RIGHT, // Right
|
||||
BUTTON_ID_START, // Start
|
||||
BUTTON_ID_SELECT, // Select
|
||||
BUTTON_ID_L, // Ltrigger
|
||||
BUTTON_ID_R, // Rtrigger
|
||||
BUTTON_ID_FPS, // A
|
||||
BUTTON_ID_A, // B
|
||||
BUTTON_ID_B, // X
|
||||
BUTTON_ID_MENU, // Y
|
||||
BUTTON_ID_VOLDOWN, // Vol down
|
||||
BUTTON_ID_VOLUP, // Vol up
|
||||
BUTTON_ID_FPS, // Push
|
||||
BUTTON_ID_MENU // Vol middle / Home
|
||||
};
|
||||
|
||||
#ifdef POLLUX_BUILD
|
||||
#include <linux/fb.h>
|
||||
void *gpsp_gp2x_screen;
|
||||
#define fb_buf_count 4
|
||||
static u32 fb_paddr[fb_buf_count];
|
||||
static void *fb_vaddr[fb_buf_count];
|
||||
static u32 fb_work_buf;
|
||||
static int fb_buf_use;
|
||||
static int fbdev;
|
||||
|
||||
static void fb_video_init()
|
||||
{
|
||||
struct fb_fix_screeninfo fbfix;
|
||||
unsigned int r;
|
||||
int i, ret;
|
||||
|
||||
fbdev = open("/dev/fb0", O_RDWR);
|
||||
if (fbdev < 0) {
|
||||
perror("can't open fbdev");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix);
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("ioctl(fbdev) failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("framebuffer: \"%s\" @ %08lx\n", fbfix.id, fbfix.smem_start);
|
||||
fb_paddr[0] = fbfix.smem_start;
|
||||
|
||||
fb_vaddr[0] = mmap(0, 320*240*2*fb_buf_count, PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED, gpsp_gp2x_dev, fb_paddr[0]);
|
||||
if (fb_vaddr[0] == MAP_FAILED)
|
||||
{
|
||||
perror("mmap(fb_vaddr) failed");
|
||||
exit(1);
|
||||
}
|
||||
memset(fb_vaddr[0], 0, 320*240*2*fb_buf_count);
|
||||
|
||||
printf(" %p -> %08x\n", fb_vaddr[0], fb_paddr[0]);
|
||||
for (i = 1; i < fb_buf_count; i++)
|
||||
{
|
||||
fb_paddr[i] = fb_paddr[i-1] + 320*240*2;
|
||||
fb_vaddr[i] = (char *)fb_vaddr[i-1] + 320*240*2;
|
||||
printf(" %p -> %08x\n", fb_vaddr[i], fb_paddr[i]);
|
||||
}
|
||||
fb_work_buf = 0;
|
||||
fb_buf_use = fb_buf_count;
|
||||
|
||||
saved_405c = gpsp_gp2x_memregl[0x405c>>2];
|
||||
saved_4060 = gpsp_gp2x_memregl[0x4060>>2];
|
||||
saved_4058 = gpsp_gp2x_memregl[0x4058>>2];
|
||||
|
||||
// set mode; program both MLCs so that TV-out works
|
||||
gpsp_gp2x_memregl[0x405c>>2] = gpsp_gp2x_memregl[0x445c>>2] = 2;
|
||||
gpsp_gp2x_memregl[0x4060>>2] = gpsp_gp2x_memregl[0x4460>>2] = 320 * 2;
|
||||
|
||||
r = gpsp_gp2x_memregl[0x4058>>2];
|
||||
r = (r & 0xffff) | (0x4432 << 16) | 0x10;
|
||||
gpsp_gp2x_memregl[0x4058>>2] = r;
|
||||
|
||||
r = gpsp_gp2x_memregl[0x4458>>2];
|
||||
r = (r & 0xffff) | (0x4432 << 16) | 0x10;
|
||||
gpsp_gp2x_memregl[0x4458>>2] = r;
|
||||
|
||||
pollux_video_flip();
|
||||
warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1);
|
||||
}
|
||||
|
||||
void pollux_video_flip()
|
||||
{
|
||||
gpsp_gp2x_memregl[0x406C>>2] =
|
||||
gpsp_gp2x_memregl[0x446C>>2] = fb_paddr[fb_work_buf];
|
||||
gpsp_gp2x_memregl[0x4058>>2] |= 0x10;
|
||||
gpsp_gp2x_memregl[0x4458>>2] |= 0x10;
|
||||
fb_work_buf++;
|
||||
if (fb_work_buf >= fb_buf_use)
|
||||
fb_work_buf = 0;
|
||||
gpsp_gp2x_screen = fb_vaddr[fb_work_buf];
|
||||
}
|
||||
|
||||
void fb_use_buffers(int count)
|
||||
{
|
||||
if (count < 1)
|
||||
count = 1;
|
||||
else if (count > fb_buf_count)
|
||||
count = fb_buf_count;
|
||||
fb_buf_use = count;
|
||||
memset(fb_vaddr[0], 0, 320*240*2*count);
|
||||
}
|
||||
|
||||
void wiz_lcd_set_portrait(int y)
|
||||
{
|
||||
char *dpc_settings;
|
||||
#ifdef WIZ_BUILD
|
||||
static int old_y = -1;
|
||||
int cmd[2] = { 0, 0 };
|
||||
|
||||
if (old_y == y)
|
||||
return;
|
||||
cmd[0] = y ? 6 : 5;
|
||||
ioctl(fbdev, _IOW('D', 90, int[2]), cmd);
|
||||
gpsp_gp2x_memregl[0x4004>>2] = y ? 0x013f00ef : 0x00ef013f;
|
||||
gpsp_gp2x_memregl[0x4000>>2] |= 1 << 3;
|
||||
old_y = y;
|
||||
|
||||
/* the above ioctl resets LCD timings, so set them here */
|
||||
#endif
|
||||
|
||||
dpc_settings = getenv("pollux_dpc_set");
|
||||
if (dpc_settings != NULL)
|
||||
pollux_dpc_set(gpsp_gp2x_memregs, dpc_settings);
|
||||
}
|
||||
|
||||
static void fb_video_exit()
|
||||
{
|
||||
/* switch to default fb mem, turn portrait off */
|
||||
gpsp_gp2x_memregl[0x406c>>2] = fb_paddr[0];
|
||||
gpsp_gp2x_memregl[0x405c>>2] = saved_405c;
|
||||
gpsp_gp2x_memregl[0x4060>>2] = saved_4060;
|
||||
gpsp_gp2x_memregl[0x4058>>2] = saved_4058 | 0x10;
|
||||
wiz_lcd_set_portrait(0);
|
||||
close(fbdev);
|
||||
}
|
||||
|
||||
static int wiz_gamepak_fd = -1;
|
||||
static u32 wiz_gamepak_size;
|
||||
|
||||
static void wiz_gamepak_cleanup()
|
||||
{
|
||||
if (wiz_gamepak_size)
|
||||
munmap(gamepak_rom, wiz_gamepak_size);
|
||||
if (wiz_gamepak_fd >= 0)
|
||||
close(wiz_gamepak_fd);
|
||||
gamepak_rom = NULL;
|
||||
wiz_gamepak_size = 0;
|
||||
wiz_gamepak_fd = -1;
|
||||
}
|
||||
|
||||
u32 wiz_load_gamepak(char *name)
|
||||
{
|
||||
char *dot_position = strrchr(name, '.');
|
||||
u32 ret;
|
||||
|
||||
if (!strcasecmp(dot_position, ".zip"))
|
||||
{
|
||||
if (wiz_gamepak_fd >= 0)
|
||||
{
|
||||
wiz_gamepak_cleanup();
|
||||
printf("switching to ROM malloc\n");
|
||||
init_gamepak_buffer();
|
||||
}
|
||||
return load_file_zip(name);
|
||||
}
|
||||
|
||||
if (wiz_gamepak_fd < 0)
|
||||
{
|
||||
extern void *gamepak_memory_map;
|
||||
free(gamepak_rom);
|
||||
free(gamepak_memory_map);
|
||||
gamepak_memory_map = NULL;
|
||||
printf("switching to ROM mmap\n");
|
||||
}
|
||||
else
|
||||
wiz_gamepak_cleanup();
|
||||
|
||||
wiz_gamepak_fd = open(name, O_RDONLY|O_NOATIME, S_IRUSR);
|
||||
if (wiz_gamepak_fd < 0)
|
||||
{
|
||||
perror("wiz_load_gamepak: open failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = lseek(wiz_gamepak_fd, 0, SEEK_END);
|
||||
wiz_gamepak_size = gamepak_ram_buffer_size = ret;
|
||||
|
||||
gamepak_rom = mmap(0, ret, PROT_READ, MAP_SHARED, wiz_gamepak_fd, 0);
|
||||
if (gamepak_rom == MAP_FAILED)
|
||||
{
|
||||
perror("wiz_load_gamepak: mmap failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define KEYBITS_BIT(x) (keybits[(x)/sizeof(keybits[0])/8] & \
|
||||
(1 << ((x) & (sizeof(keybits[0])*8-1))))
|
||||
|
||||
static int abs_min, abs_max, lzone_step;
|
||||
|
||||
static int open_caanoo_pad(void)
|
||||
{
|
||||
long keybits[KEY_CNT / sizeof(long) / 8];
|
||||
long absbits[(ABS_MAX+1) / sizeof(long) / 8];
|
||||
struct input_absinfo ainfo;
|
||||
int fd = -1, i;
|
||||
|
||||
memset(keybits, 0, sizeof(keybits));
|
||||
memset(absbits, 0, sizeof(absbits));
|
||||
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
int support = 0, need;
|
||||
int ret;
|
||||
char name[64];
|
||||
|
||||
snprintf(name, sizeof(name), "/dev/input/event%d", i);
|
||||
fd = open(name, O_RDONLY|O_NONBLOCK);
|
||||
if (fd == -1)
|
||||
break;
|
||||
|
||||
/* check supported events */
|
||||
ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support);
|
||||
if (ret == -1) {
|
||||
printf("in_evdev: ioctl failed on %s\n", name);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
need = (1 << EV_KEY) | (1 << EV_ABS);
|
||||
if ((support & need) != need)
|
||||
goto skip;
|
||||
|
||||
ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
|
||||
if (ret == -1) {
|
||||
printf("in_evdev: ioctl failed on %s\n", name);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (!KEYBITS_BIT(BTN_JOYSTICK))
|
||||
goto skip;
|
||||
|
||||
ret = ioctl(fd, EVIOCGABS(ABS_X), &ainfo);
|
||||
if (ret == -1)
|
||||
goto skip;
|
||||
|
||||
abs_min = ainfo.minimum;
|
||||
abs_max = ainfo.maximum;
|
||||
lzone_step = (abs_max - abs_min) / 2 / 9;
|
||||
|
||||
ioctl(fd, EVIOCGNAME(sizeof(name)), name);
|
||||
printf("using \"%s\" (type %08x)\n", name, support);
|
||||
break;
|
||||
|
||||
skip:
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
if (fd == -1) {
|
||||
printf("missing input device\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
#endif // POLLUX_BUILD
|
||||
|
||||
void gpsp_plat_init(void)
|
||||
{
|
||||
gpsp_gp2x_dev = open("/dev/mem", O_RDWR);
|
||||
gpsp_gp2x_dev_audio = open("/dev/mixer", O_RDWR);
|
||||
gpsp_gp2x_memregl = (u32 *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED,
|
||||
gpsp_gp2x_dev, 0xc0000000);
|
||||
gpsp_gp2x_memregs = (u16 *)gpsp_gp2x_memregl;
|
||||
warm_init();
|
||||
#ifdef POLLUX_BUILD
|
||||
#ifdef WIZ_BUILD
|
||||
gpsp_gp2x_indev = open("/dev/GPIO", O_RDONLY);
|
||||
#else
|
||||
gpsp_gp2x_indev = open_caanoo_pad();
|
||||
#endif
|
||||
fb_video_init();
|
||||
(void)open_caanoo_pad;
|
||||
#endif
|
||||
|
||||
gp2x_sound_volume(1);
|
||||
}
|
||||
|
||||
void gpsp_plat_quit(void)
|
||||
{
|
||||
chdir(main_path);
|
||||
|
||||
warm_finish();
|
||||
#ifdef POLLUX_BUILD
|
||||
wiz_gamepak_cleanup();
|
||||
close(gpsp_gp2x_indev);
|
||||
fb_video_exit();
|
||||
#endif
|
||||
munmap((void *)gpsp_gp2x_memregl, 0x10000);
|
||||
close(gpsp_gp2x_dev_audio);
|
||||
close(gpsp_gp2x_dev);
|
||||
|
||||
fcloseall();
|
||||
sync();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void gp2x_sound_volume(u32 volume_up)
|
||||
{
|
||||
u32 volume;
|
||||
if((volume_up == 0) && (gp2x_audio_volume > 0))
|
||||
gp2x_audio_volume--;
|
||||
|
||||
if((volume_up != 0) && (gp2x_audio_volume < 100))
|
||||
gp2x_audio_volume++;
|
||||
|
||||
volume = (gp2x_audio_volume * 0x50) / 100;
|
||||
volume = (gp2x_audio_volume << 8) | gp2x_audio_volume;
|
||||
ioctl(gpsp_gp2x_dev_audio, SOUND_MIXER_WRITE_PCM, &volume);
|
||||
}
|
||||
|
||||
u32 gpsp_plat_joystick_read(void)
|
||||
{
|
||||
#ifdef WIZ_BUILD
|
||||
u32 value = 0;
|
||||
read(gpsp_gp2x_indev, &value, 4);
|
||||
if(value & 0x02)
|
||||
value |= 0x05;
|
||||
if(value & 0x08)
|
||||
value |= 0x14;
|
||||
if(value & 0x20)
|
||||
value |= 0x50;
|
||||
if(value & 0x80)
|
||||
value |= 0x41;
|
||||
return value;
|
||||
#elif defined(POLLUX_BUILD)
|
||||
// caanoo
|
||||
static const int evdev_to_gp2x[] = {
|
||||
GP2X_A, GP2X_X, GP2X_B, GP2X_Y, GP2X_L, GP2X_R,
|
||||
GP2X_HOME, 0, GP2X_START, GP2X_SELECT, GP2X_PUSH
|
||||
};
|
||||
int keybits[KEY_CNT / sizeof(int)];
|
||||
struct input_absinfo ainfo;
|
||||
int lzone = analog_sensitivity_level * lzone_step;
|
||||
u32 retval = 0;
|
||||
int i, ret;
|
||||
|
||||
ret = ioctl(gpsp_gp2x_indev, EVIOCGKEY(sizeof(keybits)), keybits);
|
||||
if (ret == -1) {
|
||||
perror("EVIOCGKEY ioctl failed");
|
||||
sleep(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(evdev_to_gp2x) / sizeof(evdev_to_gp2x[0]); i++) {
|
||||
if (KEYBITS_BIT(BTN_TRIGGER + i))
|
||||
retval |= evdev_to_gp2x[i];
|
||||
}
|
||||
|
||||
if (lzone != 0)
|
||||
lzone--;
|
||||
|
||||
ret = ioctl(gpsp_gp2x_indev, EVIOCGABS(ABS_X), &ainfo);
|
||||
if (ret != -1) {
|
||||
if (ainfo.value <= abs_min + lzone) retval |= GP2X_LEFT;
|
||||
else if (ainfo.value >= abs_max - lzone) retval |= GP2X_RIGHT;
|
||||
}
|
||||
ret = ioctl(gpsp_gp2x_indev, EVIOCGABS(ABS_Y), &ainfo);
|
||||
if (ret != -1) {
|
||||
if (ainfo.value <= abs_min + lzone) retval |= GP2X_UP;
|
||||
else if (ainfo.value >= abs_max - lzone) retval |= GP2X_DOWN;
|
||||
}
|
||||
|
||||
return retval;
|
||||
#else
|
||||
// GP2X
|
||||
u32 value = (gpsp_gp2x_memregs[0x1198 >> 1] & 0x00FF);
|
||||
|
||||
if(value == 0xFD)
|
||||
value = 0xFA;
|
||||
if(value == 0xF7)
|
||||
value = 0xEB;
|
||||
if(value == 0xDF)
|
||||
value = 0xAF;
|
||||
if(value == 0x7F)
|
||||
value = 0xBE;
|
||||
|
||||
return ~((gpsp_gp2x_memregs[0x1184 >> 1] & 0xFF00) | value |
|
||||
(gpsp_gp2x_memregs[0x1186 >> 1] << 16));
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 gpsp_plat_buttons_to_cursor(u32 buttons)
|
||||
{
|
||||
gui_action_type new_button = CURSOR_NONE;
|
||||
|
||||
if(buttons & GP2X_A)
|
||||
new_button = CURSOR_BACK;
|
||||
|
||||
if(buttons & GP2X_X)
|
||||
new_button = CURSOR_EXIT;
|
||||
|
||||
if(buttons & GP2X_B)
|
||||
new_button = CURSOR_SELECT;
|
||||
|
||||
if(buttons & GP2X_UP)
|
||||
new_button = CURSOR_UP;
|
||||
|
||||
if(buttons & GP2X_DOWN)
|
||||
new_button = CURSOR_DOWN;
|
||||
|
||||
if(buttons & GP2X_LEFT)
|
||||
new_button = CURSOR_LEFT;
|
||||
|
||||
if(buttons & GP2X_RIGHT)
|
||||
new_button = CURSOR_RIGHT;
|
||||
|
||||
if(buttons & GP2X_L)
|
||||
new_button = CURSOR_L;
|
||||
|
||||
if(buttons & GP2X_R)
|
||||
new_button = CURSOR_R;
|
||||
|
||||
return new_button;
|
||||
}
|
||||
|
||||
// Fout = (m * Fin) / (p * 2^s)
|
||||
void set_FCLK(u32 MHZ)
|
||||
{
|
||||
u32 v;
|
||||
u32 mdiv, pdiv, sdiv = 0;
|
||||
#ifdef POLLUX_BUILD
|
||||
int i;
|
||||
#define SYS_CLK_FREQ 27
|
||||
// m = MDIV, p = PDIV, s = SDIV
|
||||
pdiv = 9;
|
||||
mdiv = (MHZ * pdiv) / SYS_CLK_FREQ;
|
||||
if (mdiv & ~0x3ff)
|
||||
return;
|
||||
v = (pdiv<<18) | (mdiv<<8) | sdiv;
|
||||
|
||||
gpsp_gp2x_memregl[0xf004>>2] = v;
|
||||
gpsp_gp2x_memregl[0xf07c>>2] |= 0x8000;
|
||||
for (i = 0; (gpsp_gp2x_memregl[0xf07c>>2] & 0x8000) && i < 0x100000; i++)
|
||||
;
|
||||
|
||||
// must restart sound as it's PLL is shared with CPU one
|
||||
sound_exit();
|
||||
init_sound(0);
|
||||
#else
|
||||
#define SYS_CLK_FREQ 7372800
|
||||
// m = MDIV + 8, p = PDIV + 2, s = SDIV
|
||||
pdiv = 3;
|
||||
mdiv = (MHZ * pdiv * 1000000) / SYS_CLK_FREQ;
|
||||
mdiv &= 0xff;
|
||||
v = ((mdiv-8)<<8) | ((pdiv-2)<<2) | sdiv;
|
||||
gpsp_gp2x_memregs[0x910>>1] = v;
|
||||
#endif
|
||||
}
|
||||
|
62
gp2x/gp2x.h
62
gp2x/gp2x.h
|
@ -1,62 +0,0 @@
|
|||
#ifndef GP2X_H
|
||||
#define GP2X_H
|
||||
|
||||
enum
|
||||
{
|
||||
GP2X_UP = 1 << 0,
|
||||
GP2X_LEFT = 1 << 2,
|
||||
GP2X_DOWN = 1 << 4,
|
||||
GP2X_RIGHT = 1 << 6,
|
||||
GP2X_START = 1 << 8, // Wiz: Menu, Caanoo: I
|
||||
GP2X_SELECT = 1 << 9, // Caanoo: II
|
||||
GP2X_L = 1 << 10,
|
||||
GP2X_R = 1 << 11,
|
||||
GP2X_A = 1 << 12,
|
||||
GP2X_B = 1 << 13,
|
||||
GP2X_X = 1 << 14,
|
||||
GP2X_Y = 1 << 15,
|
||||
#ifdef WIZ_BUILD
|
||||
GP2X_VOL_UP = 1 << 16,
|
||||
GP2X_VOL_DOWN = 1 << 17,
|
||||
GP2X_PUSH = 1 << 18,
|
||||
#elif defined(POLLUX_BUILD)
|
||||
GP2X_HOME = 1 << 16,
|
||||
GP2X_PUSH = 1 << 17,
|
||||
GP2X_VOL_UP = 1 << 30, // dummy
|
||||
GP2X_VOL_DOWN = 1 << 29,
|
||||
#else
|
||||
GP2X_VOL_DOWN = 1 << 22,
|
||||
GP2X_VOL_UP = 1 << 23,
|
||||
GP2X_PUSH = 1 << 27,
|
||||
#endif
|
||||
GP2X_VOL_MIDDLE = (1 << 24), // fake, menu enter
|
||||
};
|
||||
|
||||
void gpsp_plat_init(void);
|
||||
void gpsp_plat_quit(void);
|
||||
|
||||
u32 gpsp_plat_joystick_read(void);
|
||||
u32 gpsp_plat_buttons_to_cursor(u32 buttons);
|
||||
|
||||
#define PLAT_BUTTON_COUNT 16
|
||||
#define PLAT_MENU_BUTTON 15
|
||||
extern u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT];
|
||||
|
||||
void gp2x_sound_volume(u32 volume_up);
|
||||
void gp2x_quit();
|
||||
|
||||
void set_FCLK(u32 MHZ);
|
||||
|
||||
void upscale_aspect(u16 *dst, u16 *src);
|
||||
|
||||
/* wiz only */
|
||||
extern void *gpsp_gp2x_screen;
|
||||
void fb_use_buffers(int count);
|
||||
void pollux_video_flip();
|
||||
void wiz_lcd_set_portrait(int y);
|
||||
u32 wiz_load_gamepak(char *name);
|
||||
|
||||
void do_rotated_blit(void *dst, void *linesx4, u32 y);
|
||||
void upscale_aspect_row(void *dst, void *linesx3, u32 row);
|
||||
|
||||
#endif
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# if you know good LCD settings, set them here
|
||||
# export pollux_dpc_set='lcd_timings=397,1,37,277,341,0,17,337;clkdiv0=9'
|
||||
|
||||
./gpsp_caanoo "$@"
|
||||
|
||||
cd /usr/gp2x
|
||||
exec ./gp2xmenu
|
|
@ -1,4 +0,0 @@
|
|||
[info]
|
||||
name="gpSP Caanoo"
|
||||
path="/gpsp_caanoo/gpsp_caanoo.gpe"
|
||||
group="GAMES"
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
* quick tool to set LCD timings for Wiz
|
||||
* (c) notaz, 2009
|
||||
* code dedicated to public domain.
|
||||
*
|
||||
* HTOTAL: X VTOTAL: 341
|
||||
* HSWIDTH: 1 VSWIDTH: 0
|
||||
* HASTART: 37 VASTART: 17
|
||||
* HAEND: 277 VAEND: 337
|
||||
*
|
||||
* 120Hz
|
||||
* pcd 8, 447: + 594us
|
||||
* pcd 9, 397: + 36us
|
||||
* pcd 10, 357: - 523us
|
||||
* pcd 11, 325: +1153us
|
||||
*
|
||||
* 'lcd_timings=397,1,37,277,341,0,17,337;clkdiv0=9'
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pollux_dpc_set.h"
|
||||
|
||||
/*
|
||||
* set LCD timings based on preformated string (see usage() below for params).
|
||||
* returns 0 on success.
|
||||
*/
|
||||
int pollux_dpc_set(volatile unsigned short *memregs, const char *str)
|
||||
{
|
||||
int timings[8], have_timings = 0;
|
||||
int pcd = 0, have_pcd = 0;
|
||||
const char *p;
|
||||
int i, ret;
|
||||
|
||||
if (str == NULL)
|
||||
return -1;
|
||||
|
||||
p = str;
|
||||
while (1)
|
||||
{
|
||||
if (strncmp(p, "lcd_timings=", 12) == 0)
|
||||
{
|
||||
int c;
|
||||
p += 12;
|
||||
ret = sscanf(p, "%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
&timings[0], &timings[1], &timings[2], &timings[3],
|
||||
&timings[4], &timings[5], &timings[6], &timings[7]);
|
||||
if (ret != 8)
|
||||
break;
|
||||
/* skip seven commas */
|
||||
for (c = 0; c < 7 && *p != 0; p++)
|
||||
if (*p == ',')
|
||||
c++;
|
||||
if (c != 7)
|
||||
break;
|
||||
/* skip last number */
|
||||
while ('0' <= *p && *p <= '9')
|
||||
p++;
|
||||
have_timings = 1;
|
||||
}
|
||||
else if (strncmp(p, "clkdiv0=", 8) == 0)
|
||||
{
|
||||
char *ep;
|
||||
p += 8;
|
||||
pcd = strtoul(p, &ep, 10);
|
||||
if (p == ep)
|
||||
break;
|
||||
p = ep;
|
||||
have_pcd = 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
while (*p == ';' || *p == ' ')
|
||||
p++;
|
||||
if (*p == 0)
|
||||
goto parse_done;
|
||||
}
|
||||
|
||||
fprintf(stderr, "dpc_set parser: error at '%s'\n", p);
|
||||
return -1;
|
||||
|
||||
parse_done:
|
||||
/* some validation */
|
||||
if (have_timings)
|
||||
{
|
||||
for (i = 0; i < 8; i++)
|
||||
if (timings[i] & ~0xffff) {
|
||||
fprintf(stderr, "dpc_set: invalid timing %d: %d\n", i, timings[i]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (have_pcd)
|
||||
{
|
||||
if ((pcd - 1) & ~0x3f) {
|
||||
fprintf(stderr, "dpc_set: invalid clkdiv0: %d\n", pcd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* write */
|
||||
if (have_timings)
|
||||
{
|
||||
for (i = 0; i < 8; i++)
|
||||
memregs[(0x307c>>1) + i] = timings[i];
|
||||
}
|
||||
|
||||
if (have_pcd)
|
||||
{
|
||||
int tmp;
|
||||
pcd = (pcd - 1) & 0x3f;
|
||||
tmp = memregs[0x31c4>>1];
|
||||
memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef BINARY
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void usage(const char *binary)
|
||||
{
|
||||
printf("usage:\n%s <set_str[;set_str[;...]]>\n"
|
||||
"set_str:\n"
|
||||
" lcd_timings=<htotal,hswidth,hastart,haend,vtotal,vswidth,vastart,vaend>\n"
|
||||
" clkdiv0=<divider>\n", binary);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
volatile unsigned short *memregs;
|
||||
int ret, memdev;
|
||||
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memdev = open("/dev/mem", O_RDWR);
|
||||
if (memdev == -1)
|
||||
{
|
||||
perror("open(/dev/mem) failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memregs = mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
|
||||
if (memregs == MAP_FAILED)
|
||||
{
|
||||
perror("mmap(memregs) failed");
|
||||
close(memdev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = pollux_dpc_set(memregs, argv[1]);
|
||||
|
||||
munmap((void *)memregs, 0x10000);
|
||||
close(memdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
|
@ -1,10 +0,0 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int pollux_dpc_set(volatile unsigned short *memregs, const char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,340 +0,0 @@
|
|||
-- porter's foreword --
|
||||
|
||||
Even though ZX-81 ported my Wiz version to Caanoo, some people kept
|
||||
asking me to do the port instead because of apparent sound problems,
|
||||
so here it is. Note that I did not use ZX-81's work for this release,
|
||||
because I had various changes for Pandora version and wanted to have
|
||||
them in, so different set of bugs then in ZX-81's version are
|
||||
possible. Savestates might also be incompatible.
|
||||
|
||||
To use this, you'll first need to copy authentic GBA BIOS to gpSP
|
||||
directory. It must be named gba_bios.bin and should be 16kB in size.
|
||||
|
||||
I've appended the original gpSP GP2X readme file as it contains lots
|
||||
of information that is still relevant for this version, as well as
|
||||
development history of this project.
|
||||
|
||||
- notaz
|
||||
|
||||
Changelog:
|
||||
|
||||
0.9-2xb u8
|
||||
- Caanoo port
|
||||
- fixed tv-out for pandora
|
||||
- integrated M-HT's neon scalers (pandora only)
|
||||
- merged an assortment of calc84maniac's bugfixes
|
||||
|
||||
0.9-2xb u7
|
||||
- Pandora port, using hardware scaler for video output.
|
||||
- Fixed a few portablility issues in ARM asm and sound code.
|
||||
- Tweaked timing to suit pandora's LCD refresh nicely.
|
||||
- Maybe fixed GBC/digital sound channel desync over time.
|
||||
- Some other not-that-relevant cleanups and tweaks.
|
||||
|
||||
Source code should be available at:
|
||||
http://notaz.gp2x.de/cgi-bin/gitweb.cgi
|
||||
|
||||
|
||||
-- gameplaySP2X Gameboy Advance emulator for GP2X --
|
||||
|
||||
gpSP2X is a version of my (Exophase)'s emulator originally for Sony PSP.
|
||||
A large amount of effort has been done to make it more optimized for the
|
||||
ARM CPU present in the GP2X, however it is still very much a work in
|
||||
progress.
|
||||
|
||||
See readme.txt for the PSP version readme, which contains a lot of
|
||||
information relevant to the GP2X version (note that some of it does
|
||||
not apply however).
|
||||
|
||||
|
||||
Changelog:
|
||||
|
||||
0.9-2xb u6
|
||||
- Fixed clock and scaling config saving.
|
||||
- Fixed occasional crash on first ROM load on 1.1 firmware.
|
||||
- Added LCD timing setup code, which can be controlled through
|
||||
'pollux_dpc_set' environment vatiable (see gpsp.gpe wrapper script).
|
||||
|
||||
0.9-2xb u5
|
||||
- Added portrait drawing modes. They eliminate tearing but are slightly
|
||||
slower.
|
||||
- Added page scrolling in ROM browser with L/R.
|
||||
- 32MB ROM support fixed.
|
||||
|
||||
0.9-2xb u4 (unofficial notaz release, done on Exophase's request)
|
||||
- Wiz port. No emulation related changes.
|
||||
- Wiz: dropped SDL for video and hitting hardware directly (GPH SDL can't
|
||||
be trusted, it doesn't do double buffering as of firmware 1.0).
|
||||
- Added new optimized software scaler with interpolation.
|
||||
- gpSP is now saving ROM dir on exit. Delete romdir.txt if you don't
|
||||
want that.
|
||||
- gpSP now comes with wARM, new kernel module+lib for ARM cache control
|
||||
(replaces mmuhack).
|
||||
- gpSP no longer invalidates whole icache after recompilation, might
|
||||
cause minor speedup.
|
||||
|
||||
0.9-2xb u3 (unofficial notaz release, released with permission):
|
||||
- Removed built-in CPU/LCD/RAM-Tweaker.
|
||||
- Improved usability of volume control.
|
||||
- Removed PSP-specific GUI options, adjusted help text.
|
||||
- Overclocking from menu now works, keep it at 200 if you don't want that
|
||||
(if you want to overclock using launcher, for example).
|
||||
- Fixed centering-on-first-run problem.
|
||||
- 3:2 scaled option now does what it says.
|
||||
|
||||
0.9-2xb u2 (unofficial notaz release):
|
||||
- Replaced non-working mmuhack.o with proper one, added cache flush calls
|
||||
to avoid artifacts.
|
||||
|
||||
0.9-2xb u1 (unofficial notaz release):
|
||||
- Fixed a problen in thread synchronization which caused deadlock after
|
||||
some time.
|
||||
|
||||
0.9-2xb:
|
||||
-- IMPORTANT-- If you're overwriting an old version, be sure to delete the
|
||||
gpsp.cfg file first, or be prepared to have a bunch of weird button
|
||||
settings that would require fixing.
|
||||
|
||||
- Fixed some bugs stunting compatability.
|
||||
- Optimized alpha blends in renderer.
|
||||
- Some more optimizations to dynarec output.
|
||||
- Savestates should work better now.
|
||||
- Cheat/misc menu won't crash the emulator.
|
||||
- Main button config window works (not all buttons are in yet)
|
||||
|
||||
0.9-2Xa: (Exophase release)
|
||||
- Redid autoframeskip. Should work more reliably.
|
||||
- Rewrote dynamic recompiler from x86 source (arm_emit.h, arm_stub.S).
|
||||
Has some more sophisticated behavior than the last version, more is
|
||||
still to come... Should notice a slight speed improvement over the
|
||||
last version.
|
||||
- Tweaked GUI to be a little more useable. Buttons are now mirroring the
|
||||
PSP version's.
|
||||
- Code unification + cleanup amongst versions.
|
||||
|
||||
|
||||
v9008: (zodttd release)
|
||||
- Updated the way autoframeskip works. Should be better now. Still has a max
|
||||
frameskip value.
|
||||
- Added a slight performance increase to the dynarec.
|
||||
- Added sync() to make sure files such as savestates and in-game saves are
|
||||
saved properly to the GP2X.
|
||||
|
||||
v9006: (zodttd release)
|
||||
- Initial public release
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
1. Place the "gpsp.gpe" and "game_config.txt" file in a directory on your SD
|
||||
card used with the GP2X.
|
||||
|
||||
2. Place your GBA BIOS in the directory from step 1. This file must be named
|
||||
"gba_bios.bin" in all lowercase as shown, so rename it if needed.
|
||||
|
||||
-- NOTE --
|
||||
|
||||
There are two commonly available BIOSes - one is the correct one used in
|
||||
production GBA's worldwide and the other is a prototype BIOS. The latter
|
||||
will not cause some games to not work correctly or crash. If you attempt
|
||||
to use this BIOS you will be presented with a warning before being
|
||||
allowed to continue. This screen will give you a checksum of the real
|
||||
BIOS image (see readme.txt for further information).
|
||||
|
||||
3. Place your GBA games in the directory from step 1. These files should have
|
||||
a ".gba" or ".bin" file extension. Zip compressed games should be supported
|
||||
and are recognized with the ".zip" file extension. Note that 32MB ROMs will
|
||||
probably not run if zipped. 16MB and smaller should be OK.
|
||||
|
||||
4. Done. Run gpsp.gpe.
|
||||
|
||||
|
||||
Controls:
|
||||
|
||||
How to use gpSP on the GP2X:
|
||||
Buttons are mapped as follows (GBA/ingame buttons can be changed in the menu):
|
||||
|
||||
GP2X--------------------GBA
|
||||
X -> A
|
||||
B -> B
|
||||
L TRIG -> L TRIG
|
||||
R TRIG -> R TRIG
|
||||
START -> START
|
||||
SELECT -> SELECT
|
||||
|
||||
GP2X--------------------------------gpSP
|
||||
|
||||
-- IN-GAME --
|
||||
|
||||
VOL MIDDLE (UP + DOWN) -> menu
|
||||
PUSH STICK -> fps display toggle (second number is
|
||||
frames actually drawn)
|
||||
|
||||
-- IN-MENU --
|
||||
B -> select option
|
||||
X -> cancel/exit menu
|
||||
A -> escape (up one director level in the
|
||||
file selector)
|
||||
|
||||
When gpSP is started, you are presented with the option to overclock your
|
||||
GP2X. Use the L/R TRIG to change the CPU clockspeed and press START to
|
||||
continue. You may also change RAM timings here - experiment with what
|
||||
works well. Note that going too high on overclocking or low on RAM
|
||||
timings can cause the game to crash or the GP2X to outright freeze up.
|
||||
|
||||
If you do not want to overclock, press START without using L/R.
|
||||
You will now be presented with a menu to choose a game. Press the IN-MENU
|
||||
"SELECT" button shown above to pick a game to load.
|
||||
|
||||
If you would like to test gpSP for the GP2X with a homebrew (free public
|
||||
domain) game, a game by Russ Prince works very well with gpSP. It is called
|
||||
Bust-A-Move and is a remake of the classic game it's named after.
|
||||
|
||||
|
||||
How to build from source:
|
||||
|
||||
The makefile included in the source is geared towards the Open2x toolchain.
|
||||
If you use Open2x and installed it in the way recommended then it should
|
||||
work okay, assuming you also have up to date HW-SDL (and have
|
||||
arm-linux-sdl-config installed in the right place). The makefile is in the
|
||||
gp2x directory, so go there first then just type make to build gpsp.gpe.
|
||||
Might need a little tweaking if your setup is different. If you need help
|
||||
you can ask me, but I'll probably nag you about why you want to build it in
|
||||
the first place.
|
||||
|
||||
|
||||
GP2X version FAQ:
|
||||
|
||||
Q) Help! This game doesn't work. Am I using a bad version of the ROM?
|
||||
|
||||
A) First, make sure you're using the correct BIOS version. If you aren't
|
||||
gpSP should tell you. Other than that, there are some games that are
|
||||
known to not work now (and will probably work later), and perhaps
|
||||
many more games that I don't know about that don't work. I haven't
|
||||
launched a full scale compatability test at this version, so it might
|
||||
take a while before the compatability levels are high.
|
||||
|
||||
|
||||
Q) Why is this version slower than the PSP version?
|
||||
|
||||
A) gpSP is still a work in progress. It might be possible to obtain more
|
||||
speed from both this version and the PSP one too (and others in the
|
||||
future). With that in mind, know that even a very agressively overclocked
|
||||
GP2X is still less powerful than a PSP, generally speaking. Still, I
|
||||
have a lot of ideas. It's unlikely that the GP2X version will ever be as
|
||||
fast/faster than the PSP version for anyone but anything's possible.
|
||||
|
||||
|
||||
Q) How high does my GP2X have to overclock to enjoy gpSP?
|
||||
|
||||
A) That depends on you. Higher overclocking will mean less frames skipped
|
||||
on autoframeskip, or less frameskip needed if on manual. Or it can
|
||||
make the difference between whether or not virtual 60fps can be reached.
|
||||
For some games no GP2X in the world will be able to run them fullspeed,
|
||||
with any amount of frameskip. A few might run well with no overclocking
|
||||
and a generous level of frameskip (probably manual). If you don't care
|
||||
about battery life (or you're plugged into an outlet) you should push
|
||||
it as high as you can while still maintaining stability, because
|
||||
chances are high that whatever you play will benefit from it. Right now
|
||||
you'll probably want 260MHz if you can achieve it, but with a lot of
|
||||
luck this number will lower slightly in the future (and is just a vague
|
||||
ballpark figure anyway). I don't want to scare anyone off from using the
|
||||
emulator, you should give it a try and see how it plays for you
|
||||
regardless of how high you can overclock. Just note that this is far
|
||||
from a locked smooth experience for everyone on every game.
|
||||
|
||||
|
||||
Q) GBA has an ARM processor, GP2X has an ARM processor. GP2X is more
|
||||
powerful than GBA. This emulator should run great without overclocking,
|
||||
so therefore you're doing it wrong.
|
||||
|
||||
A) That's not a question, but I'll field it anyway. Two things: first,
|
||||
"virtualization", or running the GBA code "natively" on the GP2X is
|
||||
probably not possible, at least not with the way I want to do things.
|
||||
For reasons why go read my blog (see below). So yes, you actually
|
||||
do need more than 16.7MHz of ARM9 power to emulate the GBA's CPU.
|
||||
Second: there is a whole lot of work behind emulating the pretty 2D
|
||||
graphics on the GBA, something it can do in hardware a lot better than
|
||||
this platform can.
|
||||
End result: GBA emulation on GP2X isn't as easy as you think it is.
|
||||
|
||||
|
||||
Q) What are you working on now? When will you release the next version?
|
||||
|
||||
A) See the gpSP development blog:
|
||||
|
||||
http://gpsp-dev.blogspot.com/
|
||||
|
||||
Note that I don't give release dates, ever, unless I'm right on the verge
|
||||
of releasing. Be grateful that I've decided to be much more open about
|
||||
the development of the emulator now.
|
||||
|
||||
|
||||
Q) Thanks to your blog I heard that you made some improvement. Can I have
|
||||
a copy of the new code?
|
||||
|
||||
A) No. Builds in transition often have a lot of problems, and I like for
|
||||
releases to be relatively substantial. I can probably be bribed out of
|
||||
them with donations though. :P
|
||||
|
||||
|
||||
Q) Why do the menu suck so much? Why do half the options not work or not
|
||||
make any sense?
|
||||
|
||||
A) Sorry, the menu still hasn't been modified very much to fit the GP2X
|
||||
version instead of the PSP version.. hopefully this will improve in the
|
||||
future.
|
||||
|
||||
|
||||
Q) Who's in charge of the GP2X version anyway?
|
||||
|
||||
A) Originally, zodttd was. I, Exophase, have basically usurped control of it
|
||||
now to encourage zodttd to work more on his PS1 emulator (that and I'm
|
||||
possessive of gpSP and get nervous when people work on it too heavily).
|
||||
zodttd will most likely still be around to work on things though.
|
||||
|
||||
|
||||
Q) I'm a super nice person and would like to donate some of my hard earned
|
||||
money to this one-off GBA emulator. Where do I send my money to?
|
||||
|
||||
A) Exophase: exophase@gmail.com on PayPal
|
||||
zodttd: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=heirloomer
|
||||
%40pobox%2ecom&item_number=1&no_shipping=1&no_note=1&tax=0&cy_code=USD&bn=
|
||||
PP%2dDonationsBF&charset=UTF%2d8
|
||||
^ Click there for donating on PayPal (remove whitespace/linebreaks).
|
||||
|
||||
GP2X people have already donated a lot more to me than PSP people have,
|
||||
even though there's an order of magnitude or two less users. And they've
|
||||
donated far more to zodttd than they have to me. So I'm not going to ask
|
||||
people to donate..
|
||||
|
||||
However I won't lie: donating ups the chances of me actually working on the
|
||||
next version (for which I have a lot of ideas, but not necessarily time to
|
||||
dedicate to.. that time might need more incentive to be allotted from other
|
||||
things). This could change depending on my employment situation, but right
|
||||
now I feel guilty doing anything that doesn't help guarantee that I'll be
|
||||
able to buy food a year from now.
|
||||
|
||||
|
||||
Q) Tell me all of your personal information.
|
||||
|
||||
A) Again not a question, but why not. I'm Exophase, real name: Gilead Kutnick,
|
||||
male, 23 years old, current residence Bloomington, IN; straight/single/not
|
||||
actively looking, almost have an MS in Computer Science (do have a BS
|
||||
underneath it), likes PSP more than GP2X, will not write a Nintendo DS
|
||||
emulator for either, am currently looking for a job for after I graduate.
|
||||
|
||||
|
||||
Q) You said you're looking for a job.
|
||||
|
||||
A) Yes. If you have one or know someone who needs a low level oriented
|
||||
programmer then I'm up for grabs. And this is my resume:
|
||||
http://exophase.devzero.co.uk/resume.pdf
|
||||
|
||||
|
||||
Credits:
|
||||
|
||||
Original codebase: Exophase (exophase@gmail.com)
|
||||
Foundation gp2x code: zodttd
|
||||
GP2X dynarec/stubs + current code maintainance: Exophase
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
// Betting on GCC aligning this for efficiency.
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned short int read_16 = 0xF1F2;
|
||||
unsigned int read_32 = 0xF1F2F3F4;
|
||||
|
||||
unsigned short int write_16 = 0xF00D;
|
||||
unsigned int write_32 = 0xF00DFEED;
|
||||
// 16bit unsigned reads, we expect 0xF1F2 and 0xF20000F1
|
||||
fprintf(stderr, "%04x %04x\n",
|
||||
*((unsigned short int *)((char *)&read_16)),
|
||||
*((unsigned short int *)((char *)&read_16 + 1)));
|
||||
|
||||
// 16bit signed reads, we expect 0xFFFFF1F2 and 0xFFFFFFF1
|
||||
fprintf(stderr, "%04x %04x\n",
|
||||
*((short int *)((char *)&read_16)),
|
||||
*((short int *)((char *)&read_16 + 1)));
|
||||
|
||||
// 32bit reads, we expect 0xF1F2F3F4, 0xF4F1F2F3, 0xF3F4F1F2,
|
||||
// and 0xF2F3F4F1
|
||||
|
||||
fprintf(stderr, "%08x %08x %08x %08x\n",
|
||||
*((int *)((char *)&read_32)),
|
||||
*((int *)((char *)&read_32 + 1)),
|
||||
*((int *)((char *)&read_32 + 2)),
|
||||
*((int *)((char *)&read_32 + 3)));
|
||||
|
||||
// 16bit writes, we expect write_16 to remain 0xF00D
|
||||
|
||||
*((short int *)((char *)&write_16)) = 0xF00D;
|
||||
*((short int *)((char *)&write_16) + 1) = 0xF00D;
|
||||
|
||||
fprintf(stderr, "%04x\n", write_16);
|
||||
|
||||
// 32bit writes, we expect write_32 to remain 0xF00DFEED
|
||||
|
||||
*((int *)((char *)&write_16)) = 0xF00DFEED;
|
||||
*((int *)((char *)&write_16) + 1) = 0xF00DFEED;
|
||||
*((int *)((char *)&write_16) + 2) = 0xF00DFEED;
|
||||
*((int *)((char *)&write_16) + 3) = 0xF00DFEED;
|
||||
|
||||
fprintf(stderr, "%08x\n", write_32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
typedef unsigned int u32;
|
||||
|
||||
u32 arm_imm_find_nonzero(u32 imm, u32 start_bit)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for(i = start_bit; i < 32; i += 2)
|
||||
{
|
||||
if((imm >> i) & 0x03)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations)
|
||||
{
|
||||
u32 store_count = 0;
|
||||
u32 left_shift = 0;
|
||||
|
||||
// Otherwise it'll return 0 things to store because it'll never
|
||||
// find anything.
|
||||
if(imm == 0)
|
||||
{
|
||||
rotations[0] = 0;
|
||||
stores[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find chunks of non-zero data at 2 bit alignments.
|
||||
while(1)
|
||||
{
|
||||
left_shift = arm_imm_find_nonzero(imm, left_shift);
|
||||
|
||||
if(left_shift == 32)
|
||||
{
|
||||
// We've hit the end of the useful data.
|
||||
return store_count;
|
||||
}
|
||||
|
||||
// Hit the end, it might wrap back around to the beginning.
|
||||
if(left_shift >= 24)
|
||||
{
|
||||
// Make a mask for the residual bits. IE, if we have
|
||||
// 5 bits of data at the end we can wrap around to 3
|
||||
// bits of data in the beginning. Thus the first
|
||||
// thing, after being shifted left, has to be less
|
||||
// than 111b, 0x7, or (1 << 3) - 1.
|
||||
u32 top_bits = 32 - left_shift;
|
||||
u32 residual_bits = 8 - top_bits;
|
||||
u32 residual_mask = (1 << residual_bits) - 1;
|
||||
|
||||
if((store_count > 1) && (left_shift > 24) &&
|
||||
((stores[0] << (32 - rotations[0])) < residual_mask))
|
||||
{
|
||||
// Then we can throw out the last bit and tack it on
|
||||
// to the first bit.
|
||||
u32 initial_bits = rotations[0];
|
||||
stores[0] = (stores[0] << (top_bits + (32 - rotations[0]))) |
|
||||
((imm >> left_shift) & 0xFF);
|
||||
rotations[0] = top_bits;
|
||||
|
||||
return store_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There's nothing to wrap over to in the beginning
|
||||
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||||
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||||
return store_count + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||||
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||||
|
||||
store_count++;
|
||||
left_shift += 8;
|
||||
}
|
||||
}
|
||||
|
||||
#define ror(value, shift) \
|
||||
((value) >> shift) | ((value) << (32 - shift)) \
|
||||
|
||||
u32 arm_assemble_imm_32bit(u32 *stores, u32 *rotations, u32 store_count)
|
||||
{
|
||||
u32 n = ror(stores[0], rotations[0]);
|
||||
u32 i;
|
||||
printf("%x : %x\n", stores[0], rotations[0]);
|
||||
|
||||
for(i = 1; i < store_count; i++)
|
||||
{
|
||||
printf("%x : %x\n", stores[i], rotations[i]);
|
||||
n |= ror(stores[i], rotations[i]);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
u32 n = 0;
|
||||
u32 stores[4];
|
||||
u32 rotations[4];
|
||||
u32 store_count;
|
||||
u32 n2;
|
||||
|
||||
if(argc != 1)
|
||||
{
|
||||
n = strtoul(argv[1], NULL, 16);
|
||||
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||||
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||||
printf("%08x -> %08x (%d stores)\n", n, n2, store_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||||
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||||
if(n != n2)
|
||||
{
|
||||
printf("Failure: %08x -/-> %08x\n", n, n2);
|
||||
return -1;
|
||||
}
|
||||
n++;
|
||||
} while(n != 0);
|
||||
|
||||
printf("Done!\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,579 +0,0 @@
|
|||
/*
|
||||
* 240x160 -> 320x213 upscaler for ARM with interpolation
|
||||
*
|
||||
* Written by Gražvydas "notaz" Ignotas
|
||||
* Prototyped by Rokas
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the organization nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 0 1 2 : 3 4 5
|
||||
* 6 7 8 : 9 10 11
|
||||
* 12 13 14 : 15 16 17
|
||||
* v
|
||||
* 0 1 2 3 : 4 5 6 7
|
||||
* 8 9 10 11 : 12 13 14 15
|
||||
* 16 17 18 19 : 20 21 22 23
|
||||
* 24 25 26 27 : 28 29 30 31
|
||||
*/
|
||||
|
||||
.macro unpack_hi dst, src
|
||||
mov \dst, \src, lsr #16
|
||||
orr \dst, \dst, \dst, lsl #16
|
||||
and \dst, \dst, lr
|
||||
.endm
|
||||
|
||||
.macro unpack_lo dst, src
|
||||
mov \dst, \src, lsl #16
|
||||
orr \dst, \dst, \dst, lsr #16
|
||||
and \dst, \dst, lr
|
||||
.endm
|
||||
|
||||
@ do 3:5 summing: r2 = (s1*3 + s2*5 + 4) / 8
|
||||
@ s2 != r2
|
||||
.macro do_3_5 s1, s2
|
||||
add r2,\s1,\s1, lsl #1 @ r2 = s1 * 3
|
||||
add r2, r2,\s2, lsl #2
|
||||
add r2, r2,\s2 @ r2 += s2 * 5
|
||||
add r2, r2, r12,lsl #2 @ sum += round * 4
|
||||
and r2, lr, r2, lsr #3 @ mask_to_unpacked(sum / 8)
|
||||
.endm
|
||||
|
||||
@ do 14:7:7:4: r2 = (s1*14 + s2*7 + s3*7 + s4*4 + 16) / 32
|
||||
@ {s2,s3,s4} != r2
|
||||
.macro do_14_7_7_4 s1, s2, s3, s4
|
||||
mov r2,\s1, lsl #4
|
||||
sub r2, r2,\s1, lsl #1 @ r2 = s1 * 14
|
||||
add r2, r2,\s2, lsl #3
|
||||
sub r2, r2,\s2 @ r2 += s2 * 7
|
||||
add r2, r2,\s3, lsl #3
|
||||
sub r2, r2,\s3 @ r2 += s3 * 7
|
||||
add r2, r2,\s4, lsl #2 @ r2 += s4 * 4
|
||||
add r2, r2, r12,lsl #3 @ sum += round * 16
|
||||
and r2, lr, r2, lsr #5 @ mask_to_unpacked(sum / 32)
|
||||
.endm
|
||||
|
||||
.global upscale_aspect @ u16 *dst, u16 *src
|
||||
upscale_aspect:
|
||||
stmfd sp!,{r4-r11,lr}
|
||||
mov lr, #0x0000001f
|
||||
orr lr, lr, #0x0000f800 @ for "unpacked" form of
|
||||
orr lr, lr, #0x07e00000 @ 00000ggg'ggg00000'rrrrr000'000bbbbb
|
||||
mov r12, #0x00000001
|
||||
orr r12,r12,#0x00000800
|
||||
orr r12,r12,#0x00200000 @ rounding constant
|
||||
|
||||
mov r8, #((240/6)-1) << 24 @ cols
|
||||
orr r8, r8, #160/3 @ rows
|
||||
|
||||
add r0, r0, #320*2*13
|
||||
loop1:
|
||||
ldr r10,[r1]
|
||||
ldr r11,[r1, #320*2*1]
|
||||
|
||||
unpack_lo r4, r10
|
||||
unpack_hi r5, r10
|
||||
unpack_lo r6, r11
|
||||
unpack_hi r7, r11
|
||||
|
||||
ldr r11,[r1, #4]
|
||||
|
||||
do_3_5 r4, r5
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r10, lsl #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0] @ 0,1
|
||||
|
||||
ldr r10,[r1, #320*2*2]
|
||||
|
||||
do_3_5 r4, r6
|
||||
orr r3, r2, r2, lsl #16
|
||||
mov r3, r3, lsr #16 @ 8
|
||||
|
||||
do_14_7_7_4 r7, r5, r6, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*1] @ 8,9
|
||||
|
||||
unpack_lo r4, r10
|
||||
unpack_hi r9, r10
|
||||
|
||||
do_3_5 r4, r6
|
||||
orr r3, r2, r2, lsl #16
|
||||
mov r3, r3, lsr #16
|
||||
|
||||
do_14_7_7_4 r7, r9, r6, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*2] @ 16,17
|
||||
|
||||
do_3_5 r4, r9
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r10, lsl #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*3] @ 24,25
|
||||
|
||||
ldr r10,[r1, #320*2*1+4]
|
||||
|
||||
unpack_lo r6, r11
|
||||
unpack_lo r4, r10
|
||||
|
||||
do_3_5 r6, r5
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r11, lsl #16
|
||||
orr r2, r3, r2, lsr #16
|
||||
str r2, [r0, #4] @ 2,3
|
||||
|
||||
do_14_7_7_4 r7, r4, r5, r6
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r2, lsr #16
|
||||
|
||||
ldr r5, [r1, #320*2*2+4]
|
||||
|
||||
do_3_5 r6, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*1+4] @ 10,11
|
||||
|
||||
unpack_lo r6, r5
|
||||
|
||||
do_14_7_7_4 r7, r4, r9, r6
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r2, lsr #16
|
||||
|
||||
do_3_5 r6, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*2+4] @ 18,19
|
||||
|
||||
unpack_hi r4, r10
|
||||
|
||||
ldr r10,[r1, #8]
|
||||
|
||||
do_3_5 r6, r9
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r2, r2, lsr #16
|
||||
orr r2, r2, r5, lsl #16
|
||||
str r2, [r0, #320*2*3+4] @ 26,27
|
||||
|
||||
unpack_hi r6, r11
|
||||
unpack_lo r7, r10
|
||||
|
||||
do_3_5 r6, r7
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r2, r2, lsl #16
|
||||
orr r2, r2, r11,lsr #16
|
||||
str r2, [r0, #8] @ 4,5
|
||||
|
||||
ldr r11,[r1, #320*2*1+8]
|
||||
|
||||
unpack_hi r9, r10
|
||||
|
||||
do_3_5 r9, r7
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r2, r2, lsl #16
|
||||
orr r2, r2, r10,lsr #16
|
||||
mov r2, r2, ror #16
|
||||
str r2, [r0, #12] @ 6,7
|
||||
|
||||
unpack_lo r10,r11
|
||||
|
||||
do_3_5 r6, r4
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r2, lsr #16
|
||||
|
||||
do_14_7_7_4 r10, r4, r7, r6
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*1+8] @ 12,13
|
||||
|
||||
unpack_hi r6, r11
|
||||
|
||||
ldr r11,[r1, #320*2*2+8]
|
||||
|
||||
do_14_7_7_4 r10, r6, r7, r9
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r2, lsr #16
|
||||
|
||||
do_3_5 r9, r6
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*1+12] @ 14,15
|
||||
|
||||
unpack_hi r7, r5
|
||||
unpack_lo r9, r11
|
||||
|
||||
do_3_5 r7, r4
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r2, lsr #16
|
||||
|
||||
do_14_7_7_4 r10, r4, r9, r7
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*2+8] @ 20,21
|
||||
|
||||
do_3_5 r7, r9
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r2, r2, lsl #16
|
||||
orr r2, r2, r5, lsr #16
|
||||
str r2, [r0, #320*2*3+8] @ 28,29
|
||||
|
||||
unpack_hi r5, r11
|
||||
|
||||
do_14_7_7_4 r10, r6, r9, r5
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r2, lsr #16
|
||||
|
||||
do_3_5 r5, r6
|
||||
orr r2, r2, r2, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #320*2*2+12] @ 22,23
|
||||
|
||||
do_3_5 r5, r9
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r11, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
mov r2, r2, ror #16
|
||||
str r2, [r0, #320*2*3+12] @ 30,31
|
||||
|
||||
add r0, r0, #16
|
||||
add r1, r1, #12
|
||||
|
||||
subs r8, r8, #1<<24
|
||||
bpl loop1
|
||||
|
||||
add r0, r0, #320*3*2
|
||||
add r1, r1, #(320*2+80)*2
|
||||
sub r8, r8, #1
|
||||
tst r8, #0xff
|
||||
add r8, r8, #(240/6) << 24 @ cols
|
||||
bne loop1
|
||||
|
||||
@@ last line
|
||||
mov r8, #240/6
|
||||
|
||||
loop2:
|
||||
ldmia r1!,{r9,r10,r11}
|
||||
|
||||
unpack_lo r4, r9
|
||||
unpack_hi r5, r9
|
||||
|
||||
do_3_5 r4, r5
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r9, lsl #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0], #4
|
||||
|
||||
unpack_lo r6, r10
|
||||
unpack_hi r7, r10
|
||||
|
||||
do_3_5 r6, r5
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r2, r2, lsr #16
|
||||
orr r2, r2, r10,lsl #16
|
||||
str r2, [r0], #4
|
||||
|
||||
unpack_lo r4, r11
|
||||
unpack_hi r5, r11
|
||||
|
||||
do_3_5 r7, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r10, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0], #4
|
||||
|
||||
do_3_5 r5, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r11, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
mov r2, r2, ror #16
|
||||
str r2, [r0], #4
|
||||
|
||||
subs r8, r8, #1
|
||||
bne loop2
|
||||
|
||||
ldmfd sp!,{r4-r11,pc}
|
||||
|
||||
|
||||
.global upscale_aspect_row @ void *dst, void *linesx4, u32 row
|
||||
upscale_aspect_row:
|
||||
stmfd sp!,{r4-r11,lr}
|
||||
mov lr, #0x0000001f
|
||||
orr lr, lr, #0x0000f800 @ for "unpacked" form of
|
||||
orr lr, lr, #0x07e00000 @ 00000ggg'ggg00000'rrrrr000'000bbbbb
|
||||
mov r12, #0x00000001
|
||||
orr r12,r12,#0x00000800
|
||||
orr r12,r12,#0x00200000 @ rounding constant
|
||||
|
||||
mov r8, #(240/6) @ cols
|
||||
|
||||
add r0, r0, #(240*320)*2
|
||||
add r0, r0, #12*2
|
||||
add r0, r0, r2, lsl #3
|
||||
|
||||
uar_loop:
|
||||
ldr r10,[r1]
|
||||
ldr r11,[r1, #240*2*1]
|
||||
|
||||
unpack_lo r4, r10
|
||||
unpack_hi r5, r10
|
||||
unpack_lo r6, r11
|
||||
unpack_hi r7, r11
|
||||
|
||||
ldr r11,[r1, #240*2*2]
|
||||
|
||||
do_3_5 r4, r6
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r10, lsl #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #-240*2]! @ 0,8
|
||||
|
||||
unpack_lo r10,r11
|
||||
unpack_hi r9, r11
|
||||
|
||||
do_3_5 r10,r6
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r11, lsl #16
|
||||
orr r2, r3, r2, lsr #16
|
||||
str r2, [r0, #4] @ 16,24
|
||||
|
||||
do_3_5 r4, r5
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_14_7_7_4 r7, r5, r6, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #-240*2]! @ 1,9
|
||||
|
||||
ldr r11,[r1, #4]
|
||||
|
||||
do_14_7_7_4 r7, r6, r9, r10
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_3_5 r10,r9
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #4] @ 17,25
|
||||
|
||||
ldr r10,[r1, #240*2*1+4]
|
||||
|
||||
unpack_lo r4, r11
|
||||
unpack_lo r6, r10
|
||||
|
||||
do_3_5 r4, r5
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_14_7_7_4 r7, r5, r6, r4
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #-240*2]! @ 2,10
|
||||
|
||||
do_3_5 r4, r6
|
||||
|
||||
ldr r4, [r1, #240*2*2+4]
|
||||
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r11, lsl #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #-240*2] @ 3,11
|
||||
|
||||
unpack_lo r5, r4
|
||||
|
||||
do_14_7_7_4 r7, r6, r9, r5
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_3_5 r5, r9
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r2, r2, lsl #16
|
||||
orr r2, r2, r3, lsr #16
|
||||
str r2, [r0, #4] @ 18,26
|
||||
|
||||
do_3_5 r5, r6
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r4, lsl #16
|
||||
orr r2, r3, r2, lsr #16
|
||||
str r2, [r0, #-240*2+4] @ 19,27
|
||||
|
||||
unpack_hi r5, r11
|
||||
unpack_hi r6, r10
|
||||
unpack_hi r7, r4
|
||||
|
||||
ldr r10,[r1, #8]
|
||||
|
||||
do_3_5 r5, r6
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r11, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #-240*2*2]! @ 4,12
|
||||
|
||||
ldr r11,[r1, #240*2*1+8]
|
||||
|
||||
do_3_5 r7, r6
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r4, lsr #16
|
||||
mov r3, r3, lsl #16
|
||||
orr r2, r3, r2, lsr #16
|
||||
str r2, [r0, #4] @ 20,28
|
||||
|
||||
unpack_lo r4, r10
|
||||
unpack_lo r9, r11
|
||||
|
||||
ldr r11,[r1, #240*2*2+8]
|
||||
|
||||
do_3_5 r5, r4
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_14_7_7_4 r9, r4, r6, r5
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r2, r2, lsl #16
|
||||
orr r2, r2, r3, lsr #16
|
||||
str r2, [r0, #-240*2]! @ 5,13
|
||||
|
||||
unpack_lo r5, r11
|
||||
|
||||
do_14_7_7_4 r9, r5, r6, r7
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_3_5 r7, r5
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #4] @ 21,29
|
||||
|
||||
ldr r7, [r1, #240*2*1+8]
|
||||
|
||||
unpack_hi r6, r10
|
||||
unpack_hi r7, r7
|
||||
|
||||
do_3_5 r6, r4
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_14_7_7_4 r9, r4, r7, r6
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r2, r2, lsl #16
|
||||
orr r2, r2, r3, lsr #16
|
||||
str r2, [r0, #-240*2]! @ 6,14
|
||||
|
||||
unpack_hi r4, r11
|
||||
|
||||
do_14_7_7_4 r9, r5, r7, r4
|
||||
orr r3, r2, r2, lsl #16
|
||||
|
||||
do_3_5 r4, r5
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r3, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #4] @ 22,30
|
||||
|
||||
do_3_5 r6, r7
|
||||
orr r2, r2, r2, lsr #16
|
||||
mov r3, r10, lsr #16
|
||||
orr r2, r3, r2, lsl #16
|
||||
str r2, [r0, #-240*2]! @ 7,15
|
||||
|
||||
do_3_5 r4, r7
|
||||
orr r2, r2, r2, lsl #16
|
||||
mov r3, r11, lsr #16
|
||||
mov r3, r3, lsl #16
|
||||
orr r2, r3, r2, lsr #16
|
||||
str r2, [r0, #4] @ 23,31
|
||||
|
||||
subs r8, r8, #1
|
||||
add r1, r1, #12
|
||||
bne uar_loop
|
||||
|
||||
ldmfd sp!,{r4-r11,pc}
|
||||
|
||||
|
||||
@ bonus function
|
||||
|
||||
@ input: r2-r5
|
||||
@ output: r7,r8
|
||||
@ trash: r6
|
||||
.macro rb_line_low
|
||||
mov r6, r2, lsl #16
|
||||
mov r7, r3, lsl #16
|
||||
orr r7, r7, r6, lsr #16
|
||||
mov r6, r4, lsl #16
|
||||
mov r8, r5, lsl #16
|
||||
orr r8, r8, r6, lsr #16
|
||||
.endm
|
||||
|
||||
.macro rb_line_hi
|
||||
mov r6, r2, lsr #16
|
||||
mov r7, r3, lsr #16
|
||||
orr r7, r6, r7, lsl #16
|
||||
mov r6, r4, lsr #16
|
||||
mov r8, r5, lsr #16
|
||||
orr r8, r6, r8, lsl #16
|
||||
.endm
|
||||
|
||||
.global do_rotated_blit @ void *dst, void *linesx4, u32 y
|
||||
do_rotated_blit:
|
||||
stmfd sp!,{r4-r8,lr}
|
||||
|
||||
add r0, r0, #(240*320)*2
|
||||
sub r0, r0, #(240*40)*2
|
||||
sub r0, r0, #(240-40+4)*2 @ y starts from 4
|
||||
add r0, r0, r2, lsl #1
|
||||
|
||||
mov lr, #240/4
|
||||
|
||||
rotated_blit_loop:
|
||||
ldr r2, [r1, #240*0*2]
|
||||
ldr r3, [r1, #240*1*2]
|
||||
ldr r4, [r1, #240*2*2]
|
||||
ldr r5, [r1, #240*3*2]
|
||||
rb_line_low
|
||||
stmia r0, {r7,r8}
|
||||
sub r0, r0, #240*2
|
||||
rb_line_hi
|
||||
stmia r0, {r7,r8}
|
||||
sub r0, r0, #240*2
|
||||
|
||||
ldr r2, [r1, #240*0*2+4]
|
||||
ldr r3, [r1, #240*1*2+4]
|
||||
ldr r4, [r1, #240*2*2+4]
|
||||
ldr r5, [r1, #240*3*2+4]
|
||||
rb_line_low
|
||||
stmia r0, {r7,r8}
|
||||
sub r0, r0, #240*2
|
||||
rb_line_hi
|
||||
stmia r0, {r7,r8}
|
||||
sub r0, r0, #240*2
|
||||
|
||||
subs lr, lr, #1
|
||||
add r1, r1, #8
|
||||
bne rotated_blit_loop
|
||||
|
||||
ldmfd sp!,{r4-r8,pc}
|
||||
|
||||
@ vim:filetype=armasm
|
||||
|
183
gui.c
183
gui.c
|
@ -32,20 +32,10 @@
|
|||
|
||||
// Blatantly stolen and trimmed from MZX (megazeux.sourceforge.net)
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
|
||||
#define FILE_LIST_ROWS 20
|
||||
#define FILE_LIST_POSITION 5
|
||||
#define DIR_LIST_POSITION 260
|
||||
|
||||
#else
|
||||
|
||||
#define FILE_LIST_ROWS 25
|
||||
#define FILE_LIST_POSITION 5
|
||||
#define DIR_LIST_POSITION (resolution_width * 3 / 4)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
|
||||
#define COLOR_BG color16(2, 8, 10)
|
||||
|
@ -78,29 +68,6 @@
|
|||
clock_speed = (clock_speed_number + 1) * 33
|
||||
#define get_clock_speed_number() \
|
||||
clock_speed_number = (clock_speed / 33) - 1
|
||||
#elif defined(POLLUX_BUILD)
|
||||
static const char *clock_speed_options[] =
|
||||
{
|
||||
"300MHz", "333MHz", "366MHz", "400MHz", "433MHz",
|
||||
"466MHz", "500MHz", "533MHz", "566MHz", "600MHz",
|
||||
"633MHz", "666MHz", "700MHz", "733MHz", "766MHz",
|
||||
"800MHz", "833MHz", "866MHz", "900MHz"
|
||||
};
|
||||
#define menu_get_clock_speed() \
|
||||
clock_speed = 300 + (clock_speed_number * 3333) / 100
|
||||
#define get_clock_speed_number() \
|
||||
clock_speed_number = (clock_speed - 300) / 33
|
||||
#elif defined(GP2X_BUILD)
|
||||
static const char *clock_speed_options[] =
|
||||
{
|
||||
"150MHz", "160MHz", "170MHz", "180MHz", "190MHz",
|
||||
"200MHz", "210MHz", "220MHz", "230MHz", "240MHz",
|
||||
"250MHz", "260MHz", "270MHz", "280MHz", "290MHz"
|
||||
};
|
||||
#define menu_get_clock_speed() \
|
||||
clock_speed = 150 + clock_speed_number * 10
|
||||
#define get_clock_speed_number() \
|
||||
clock_speed_number = (clock_speed - 150) / 10
|
||||
#else
|
||||
static const char *clock_speed_options[] =
|
||||
{
|
||||
|
@ -267,24 +234,15 @@ s32 load_file(const char **wildcards, char *result)
|
|||
if(current_dir_length > 80)
|
||||
{
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
snprintf(current_dir_short, 80,
|
||||
"...%s", current_dir_name + current_dir_length - 77);
|
||||
#else
|
||||
memcpy(current_dir_short, "...", 3);
|
||||
memcpy(current_dir_short + 3,
|
||||
current_dir_name + current_dir_length - 77, 77);
|
||||
current_dir_short[80] = 0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef GP2X_BUILD
|
||||
snprintf(current_dir_short, 80, "%s", current_dir_name);
|
||||
#else
|
||||
memcpy(current_dir_short, current_dir_name,
|
||||
current_dir_length + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
repeat = 1;
|
||||
|
@ -299,13 +257,8 @@ s32 load_file(const char **wildcards, char *result)
|
|||
flip_screen();
|
||||
|
||||
print_string(current_dir_short, COLOR_ACTIVE_ITEM, COLOR_BG, 0, 0);
|
||||
#ifdef GP2X_BUILD
|
||||
print_string("Press X to return to the main menu.",
|
||||
COLOR_HELP_TEXT, COLOR_BG, 20, 220);
|
||||
#else
|
||||
print_string("Press X to return to the main menu.",
|
||||
COLOR_HELP_TEXT, COLOR_BG, 20, 260);
|
||||
#endif
|
||||
|
||||
for(i = 0, current_file_number = i + current_file_scroll_value;
|
||||
i < FILE_LIST_ROWS; i++, current_file_number++)
|
||||
|
@ -732,42 +685,10 @@ u32 gamepad_config_line_to_button[] =
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
|
||||
u32 gamepad_config_line_to_button[] =
|
||||
{ 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 14, 15 };
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PND_BUILD
|
||||
|
||||
u32 gamepad_config_line_to_button[] =
|
||||
{ 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 12, 13, 14, 15 };
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef RPI_BUILD
|
||||
|
||||
u32 gamepad_config_line_to_button[] =
|
||||
{ 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 12, 13, 14, 15 };
|
||||
|
||||
#endif
|
||||
|
||||
static const char *scale_options[] =
|
||||
{
|
||||
#ifdef PSP_BUILD
|
||||
"unscaled 3:2", "scaled 3:2", "fullscreen 16:9"
|
||||
#elif defined(WIZ_BUILD)
|
||||
"unscaled 3:2", "scaled 3:2 (slower)",
|
||||
"unscaled 3:2 (anti-tear)", "scaled 3:2 (anti-tear)"
|
||||
#elif defined(POLLUX_BUILD)
|
||||
"unscaled 3:2", "scaled 3:2 (slower)"
|
||||
#elif defined(PND_BUILD)
|
||||
"unscaled", "2x", "3x", "fullscreen"
|
||||
#elif defined(GP2X_BUILD)
|
||||
"unscaled 3:2", "scaled 3:2", "fullscreen", "scaled 3:2 (software)"
|
||||
#elif defined(RPI_BUILD)
|
||||
"fullscreen"
|
||||
#else
|
||||
"unscaled 3:2"
|
||||
#endif
|
||||
|
@ -818,16 +739,8 @@ s32 load_game_config_file()
|
|||
random_skip = file_options[2] % 2;
|
||||
clock_speed = file_options[3];
|
||||
|
||||
#ifdef POLLUX_BUILD
|
||||
if(clock_speed > 900)
|
||||
clock_speed = 533;
|
||||
#elif defined(GP2X_BUILD)
|
||||
if(clock_speed >= 300)
|
||||
clock_speed = 200;
|
||||
#else
|
||||
if(clock_speed > 333)
|
||||
clock_speed = 333;
|
||||
#endif
|
||||
|
||||
if(clock_speed < 33)
|
||||
clock_speed = 33;
|
||||
|
@ -852,16 +765,8 @@ s32 load_game_config_file()
|
|||
if(file_loaded)
|
||||
return 0;
|
||||
|
||||
#ifdef RPI_BUILD
|
||||
current_frameskip_type = manual_frameskip;
|
||||
frameskip_value = 1;
|
||||
#else
|
||||
current_frameskip_type = auto_frameskip;
|
||||
frameskip_value = 4;
|
||||
#ifdef POLLUX_BUILD
|
||||
frameskip_value = 1;
|
||||
#endif
|
||||
#endif
|
||||
random_skip = 0;
|
||||
clock_speed = default_clock_speed;
|
||||
|
||||
|
@ -1085,9 +990,7 @@ void get_savestate_snapshot(char *savestate_filename)
|
|||
COLOR_BG, 10, 40);
|
||||
}
|
||||
|
||||
#ifndef GP2X_BUILD
|
||||
blit_to_screen(snapshot_buffer, 240, 160, 230, 40);
|
||||
#endif
|
||||
}
|
||||
|
||||
void get_savestate_filename_noshot(u32 slot, char *name_buffer)
|
||||
|
@ -1341,62 +1244,48 @@ u32 menu(u16 *original_screen)
|
|||
// Marker for help information, don't go past this mark (except \n)------*
|
||||
menu_option_type graphics_sound_options[] =
|
||||
{
|
||||
#ifndef RPI_BUILD
|
||||
string_selection_option(NULL, "Display scaling", scale_options,
|
||||
(u32 *)(&screen_scale),
|
||||
sizeof(scale_options) / sizeof(scale_options[0]),
|
||||
#ifndef GP2X_BUILD
|
||||
"Determines how the GBA screen is resized in relation to the\n"
|
||||
"entire screen."
|
||||
#ifdef PSP_BUILD
|
||||
" Select unscaled 3:2 for GBA resolution, scaled 3:2 for GBA\n"
|
||||
"aspect ratio scaled to fill the height of the PSP screen, and\n"
|
||||
"fullscreen to fill the entire PSP screen."
|
||||
#endif
|
||||
#endif
|
||||
"", 2),
|
||||
#endif
|
||||
|
||||
#ifndef GP2X_BUILD
|
||||
string_selection_option(NULL, "Screen filtering", yes_no_options,
|
||||
(u32 *)(&screen_filter), 2,
|
||||
"Determines whether or not filtering should be used when\n"
|
||||
"scaling the screen. Selecting this will produce a more even and\n"
|
||||
"smooth image, at the cost of being blurry and having less vibrant\n"
|
||||
"colors.", 3),
|
||||
#endif
|
||||
#if defined (PND_BUILD)
|
||||
string_selection_option(NULL, "Scaling filter", filter2_options,
|
||||
(u32 *)(&screen_filter2),
|
||||
sizeof(filter2_options) / sizeof(filter2_options[0]),
|
||||
"Optional pixel art scaling filter", 4),
|
||||
#endif
|
||||
string_selection_option(NULL, "Frameskip type", frameskip_options,
|
||||
(u32 *)(¤t_frameskip_type), 3,
|
||||
#ifndef GP2X_BUILD
|
||||
"Determines what kind of frameskipping to use.\n"
|
||||
"Frameskipping may improve emulation speed of many games.\n"
|
||||
#endif
|
||||
"Off: Do not skip any frames.\n"
|
||||
"Auto: Skip up to N frames (see next opt) as needed.\n"
|
||||
"Manual: Always render only 1 out of N + 1 frames."
|
||||
, 5),
|
||||
numeric_selection_option(NULL, "Frameskip value", &frameskip_value, 100,
|
||||
#ifndef GP2X_BUILD
|
||||
"For auto frameskip, determines the maximum number of frames that\n"
|
||||
"are allowed to be skipped consecutively.\n"
|
||||
"For manual frameskip, determines the number of frames that will\n"
|
||||
"always be skipped."
|
||||
#endif
|
||||
"", 6),
|
||||
string_selection_option(NULL, "Framskip variation",
|
||||
frameskip_variation_options, &random_skip, 2,
|
||||
#ifndef GP2X_BUILD
|
||||
"If objects in the game flicker at a regular rate certain manual\n"
|
||||
"frameskip values may cause them to normally disappear. Change this\n"
|
||||
"value to 'random' to avoid this. Do not use otherwise, as it tends\n"
|
||||
"to make the image quality worse, especially in high motion games."
|
||||
#endif
|
||||
"", 7),
|
||||
string_selection_option(NULL, "Audio output", yes_no_options,
|
||||
&global_enable_audio, 2,
|
||||
|
@ -1438,7 +1327,7 @@ u32 menu(u16 *original_screen)
|
|||
cheat_option(7),
|
||||
cheat_option(8),
|
||||
cheat_option(9),
|
||||
#if defined(PSP_BUILD) || defined(GP2X_BUILD)
|
||||
#if defined(PSP_BUILD)
|
||||
string_selection_option(NULL, "Clock speed",
|
||||
clock_speed_options, &clock_speed_number,
|
||||
sizeof(clock_speed_options) / sizeof(clock_speed_options[0]),
|
||||
|
@ -1448,17 +1337,12 @@ u32 menu(u16 *original_screen)
|
|||
#endif
|
||||
string_selection_option(NULL, "Update backup",
|
||||
update_backup_options, &update_backup_flag, 2,
|
||||
#ifdef GP2X_BUILD
|
||||
"Determines when in-game save files should be\n"
|
||||
"written back to SD card."
|
||||
#else
|
||||
"Determines when in-game save files should be written back to\n"
|
||||
"card. If set to 'automatic' writebacks will occur shortly after\n"
|
||||
"the game's backup is altered. On 'exit only' it will only be\n"
|
||||
"written back when you exit from this menu.\n"
|
||||
#ifdef PSP
|
||||
"(NOT from using the home button), use the latter with extreme care."
|
||||
#endif
|
||||
#endif
|
||||
"", 12),
|
||||
submenu_option(NULL, "Back", "Return to the main menu.", 14)
|
||||
|
@ -1530,62 +1414,7 @@ u32 menu(u16 *original_screen)
|
|||
|
||||
#endif
|
||||
|
||||
#if defined(GP2X_BUILD) || defined(PND_BUILD)
|
||||
|
||||
menu_option_type gamepad_config_options[] =
|
||||
{
|
||||
gamepad_config_option("D-pad up ", 0),
|
||||
gamepad_config_option("D-pad down ", 1),
|
||||
gamepad_config_option("D-pad left ", 2),
|
||||
gamepad_config_option("D-pad right ", 3),
|
||||
gamepad_config_option("A ", 4),
|
||||
gamepad_config_option("B ", 5),
|
||||
gamepad_config_option("X ", 6),
|
||||
gamepad_config_option("Y ", 7),
|
||||
gamepad_config_option("Left Trigger ", 8),
|
||||
gamepad_config_option("Right Trigger", 9),
|
||||
#ifdef WIZ_BUILD
|
||||
gamepad_config_option("Menu ", 10),
|
||||
gamepad_config_option("Select ", 11),
|
||||
#elif defined(POLLUX_BUILD)
|
||||
gamepad_config_option("I ", 10),
|
||||
gamepad_config_option("II ", 11),
|
||||
gamepad_config_option("Push ", 12),
|
||||
gamepad_config_option("Home ", 13),
|
||||
#elif defined(PND_BUILD)
|
||||
gamepad_config_option("Start ", 10),
|
||||
gamepad_config_option("Select ", 11),
|
||||
gamepad_config_option("1 ", 12),
|
||||
gamepad_config_option("2 ", 13),
|
||||
gamepad_config_option("3 ", 14),
|
||||
gamepad_config_option("4 ", 15),
|
||||
#else // GP2X
|
||||
gamepad_config_option("Start ", 10),
|
||||
gamepad_config_option("Select ", 11),
|
||||
gamepad_config_option("Stick Push ", 12),
|
||||
#endif
|
||||
#ifdef PND_BUILD
|
||||
submenu_option(NULL, "Back", "Return to the main menu.", 16)
|
||||
#else
|
||||
submenu_option(NULL, "Back", "Return to the main menu.", 14)
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
menu_option_type analog_config_options[] =
|
||||
{
|
||||
#if defined(POLLUX_BUILD)
|
||||
numeric_selection_option(NULL, "Analog sensitivity",
|
||||
&analog_sensitivity_level, 10,
|
||||
"Determine sensitivity/responsiveness of the analog input.\n"
|
||||
"Lower numbers are less sensitive.", 8),
|
||||
#endif
|
||||
submenu_option(NULL, "Back", "Return to the main menu.", 11)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(PC_BUILD) || defined(RPI_BUILD)
|
||||
#if defined(PC_BUILD)
|
||||
|
||||
menu_option_type gamepad_config_options[] =
|
||||
{
|
||||
|
@ -1624,10 +1453,8 @@ u32 menu(u16 *original_screen)
|
|||
submenu_option(&gamepad_config_menu, "Configure gamepad input",
|
||||
"Select to change the in-game behavior of buttons\n"
|
||||
"and d-pad.", 6),
|
||||
#ifndef WIZ_BUILD
|
||||
submenu_option(&analog_config_menu, "Configure analog input",
|
||||
"Select to change the in-game behavior of the analog nub.", 7),
|
||||
#endif
|
||||
submenu_option(&cheats_misc_menu, "Cheats and Miscellaneous options",
|
||||
"Select to manage cheats, set backup behavior,\n"
|
||||
"and set device clock speed.", 9),
|
||||
|
@ -1652,9 +1479,7 @@ u32 menu(u16 *original_screen)
|
|||
|
||||
clear_screen(COLOR_BG);
|
||||
|
||||
#ifndef GP2X_BUILD
|
||||
blit_to_screen(original_screen, 240, 160, 230, 40);
|
||||
#endif
|
||||
|
||||
current_menu = new_menu;
|
||||
current_option = new_menu->options;
|
||||
|
@ -1674,14 +1499,10 @@ u32 menu(u16 *original_screen)
|
|||
menu_update_clock();
|
||||
video_resolution_large();
|
||||
|
||||
#ifndef GP2X_BUILD
|
||||
SDL_LockMutex(sound_mutex);
|
||||
#endif
|
||||
SDL_PauseAudio(1);
|
||||
|
||||
#ifndef GP2X_BUILD
|
||||
SDL_UnlockMutex(sound_mutex);
|
||||
#endif
|
||||
|
||||
if(gamepak_filename[0] == 0)
|
||||
{
|
||||
|
|
8
gui.h
8
gui.h
|
@ -36,13 +36,7 @@ void get_savestate_filename_noshot(u32 slot, char *name_buffer);
|
|||
void get_savestate_filename(u32 slot, char *name_buffer);
|
||||
void get_savestate_snapshot(char *savestate_filename);
|
||||
|
||||
#ifdef POLLUX_BUILD
|
||||
#define default_clock_speed 533
|
||||
#elif defined(GP2X_BUILD)
|
||||
#define default_clock_speed 200
|
||||
#else
|
||||
#define default_clock_speed 333
|
||||
#endif
|
||||
#define default_clock_speed 333
|
||||
|
||||
#endif
|
||||
|
||||
|
|
302
input.c
302
input.c
|
@ -346,257 +346,6 @@ void init_input()
|
|||
#endif
|
||||
|
||||
|
||||
#if defined(GP2X_BUILD) || defined(PND_BUILD)
|
||||
|
||||
extern u32 fps_debug;
|
||||
|
||||
gui_action_type get_gui_input()
|
||||
{
|
||||
gui_action_type new_button = CURSOR_NONE;
|
||||
u32 buttons = gpsp_plat_joystick_read();
|
||||
u32 new_buttons;
|
||||
|
||||
static u32 last_buttons = 0;
|
||||
static u64 button_repeat_timestamp;
|
||||
|
||||
delay_us(25000);
|
||||
|
||||
new_buttons = (last_buttons ^ buttons) & buttons;
|
||||
last_buttons = buttons;
|
||||
|
||||
new_button = gpsp_plat_buttons_to_cursor(new_buttons);
|
||||
if(new_button != CURSOR_NONE)
|
||||
{
|
||||
get_ticks_us(&button_repeat_timestamp);
|
||||
button_repeat_state = BUTTON_HELD_INITIAL;
|
||||
button_repeat = new_buttons;
|
||||
cursor_repeat = new_button;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(buttons & button_repeat)
|
||||
{
|
||||
u64 new_ticks;
|
||||
get_ticks_us(&new_ticks);
|
||||
|
||||
if(button_repeat_state == BUTTON_HELD_INITIAL)
|
||||
{
|
||||
if((new_ticks - button_repeat_timestamp) >
|
||||
BUTTON_REPEAT_START)
|
||||
{
|
||||
new_button = cursor_repeat;
|
||||
button_repeat_timestamp = new_ticks;
|
||||
button_repeat_state = BUTTON_HELD_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
if(button_repeat_state == BUTTON_HELD_REPEAT)
|
||||
{
|
||||
if((new_ticks - button_repeat_timestamp) >
|
||||
BUTTON_REPEAT_CONTINUE)
|
||||
{
|
||||
new_button = cursor_repeat;
|
||||
button_repeat_timestamp = new_ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new_button;
|
||||
}
|
||||
|
||||
u32 button_id_to_gba_mask[] =
|
||||
{
|
||||
BUTTON_UP,
|
||||
BUTTON_DOWN,
|
||||
BUTTON_LEFT,
|
||||
BUTTON_RIGHT,
|
||||
BUTTON_A,
|
||||
BUTTON_B,
|
||||
BUTTON_L,
|
||||
BUTTON_R,
|
||||
BUTTON_START,
|
||||
BUTTON_SELECT,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE
|
||||
};
|
||||
|
||||
u32 update_input()
|
||||
{
|
||||
static u32 rapidfire_flag = 1;
|
||||
static u32 last_buttons;
|
||||
u32 handled_buttons;
|
||||
u32 button_id;
|
||||
u32 new_key = 0;
|
||||
u32 buttons = gpsp_plat_joystick_read();
|
||||
u32 i;
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
if((buttons & GP2X_VOL_DOWN) && (buttons & GP2X_VOL_UP))
|
||||
{
|
||||
buttons &= ~(GP2X_VOL_DOWN | GP2X_VOL_UP);
|
||||
buttons |= GP2X_VOL_MIDDLE;
|
||||
}
|
||||
|
||||
/* for Wiz */
|
||||
if((buttons & GP2X_VOL_DOWN) && (buttons & GP2X_SELECT))
|
||||
{
|
||||
buttons &= ~(GP2X_VOL_DOWN | GP2X_SELECT);
|
||||
buttons |= GP2X_VOL_MIDDLE;
|
||||
}
|
||||
|
||||
last_buttons &= ~(GP2X_VOL_DOWN | GP2X_VOL_UP);
|
||||
#endif
|
||||
|
||||
handled_buttons = (last_buttons ^ buttons) & buttons;
|
||||
last_buttons = buttons;
|
||||
|
||||
for(i = 0; i < PLAT_BUTTON_COUNT; i++)
|
||||
{
|
||||
if(handled_buttons & button_plat_mask_to_config[i])
|
||||
button_id = gamepad_config_map[i];
|
||||
else
|
||||
button_id = BUTTON_ID_NONE;
|
||||
|
||||
switch(button_id)
|
||||
{
|
||||
case BUTTON_ID_MENU:
|
||||
{
|
||||
u16 *screen_copy = copy_screen();
|
||||
u32 ret_val = menu(screen_copy);
|
||||
free(screen_copy);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
case BUTTON_ID_LOADSTATE:
|
||||
{
|
||||
char current_savestate_filename[512];
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
load_state(current_savestate_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case BUTTON_ID_SAVESTATE:
|
||||
{
|
||||
char current_savestate_filename[512];
|
||||
u16 *current_screen = copy_screen();
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
save_state(current_savestate_filename, current_screen);
|
||||
free(current_screen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BUTTON_ID_FASTFORWARD:
|
||||
synchronize_flag ^= 1;
|
||||
return 0;
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
case BUTTON_ID_VOLUP:
|
||||
gp2x_sound_volume(1);
|
||||
break;
|
||||
|
||||
case BUTTON_ID_VOLDOWN:
|
||||
gp2x_sound_volume(0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case BUTTON_ID_FPS:
|
||||
fps_debug ^= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(buttons & button_plat_mask_to_config[i])
|
||||
{
|
||||
button_id = gamepad_config_map[i];
|
||||
if(button_id < BUTTON_ID_MENU)
|
||||
{
|
||||
new_key |= button_id_to_gba_mask[button_id];
|
||||
}
|
||||
else
|
||||
|
||||
if((button_id >= BUTTON_ID_RAPIDFIRE_A) &&
|
||||
(button_id <= BUTTON_ID_RAPIDFIRE_L))
|
||||
{
|
||||
rapidfire_flag ^= 1;
|
||||
if(rapidfire_flag)
|
||||
{
|
||||
new_key |= button_id_to_gba_mask[button_id -
|
||||
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||
}
|
||||
else
|
||||
{
|
||||
new_key &= ~button_id_to_gba_mask[button_id -
|
||||
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((new_key | key) != key)
|
||||
trigger_key(new_key);
|
||||
|
||||
key = new_key;
|
||||
|
||||
io_registers[REG_P1] = (~key) & 0x3FF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_input()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(RPI_BUILD)
|
||||
|
||||
u32 key_map(SDLKey key_sym)
|
||||
{
|
||||
switch(key_sym)
|
||||
{
|
||||
case SDLK_a:
|
||||
return BUTTON_L;
|
||||
|
||||
case SDLK_s:
|
||||
return BUTTON_R;
|
||||
|
||||
case SDLK_DOWN:
|
||||
return BUTTON_DOWN;
|
||||
|
||||
case SDLK_UP:
|
||||
return BUTTON_UP;
|
||||
|
||||
case SDLK_LEFT:
|
||||
return BUTTON_LEFT;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
return BUTTON_RIGHT;
|
||||
|
||||
case SDLK_RETURN:
|
||||
return BUTTON_START;
|
||||
|
||||
case SDLK_BACKSPACE:
|
||||
return BUTTON_SELECT;
|
||||
|
||||
case SDLK_x:
|
||||
return BUTTON_B;
|
||||
|
||||
case SDLK_z:
|
||||
return BUTTON_A;
|
||||
|
||||
default:
|
||||
return BUTTON_NONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PC_BUILD)
|
||||
|
||||
u32 key_map(SDLKey key_sym)
|
||||
|
@ -637,8 +386,6 @@ u32 key_map(SDLKey key_sym)
|
|||
return BUTTON_NONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(PC_BUILD) || defined(RPI_BUILD)
|
||||
|
||||
u32 joy_map(u32 button)
|
||||
{
|
||||
|
@ -717,40 +464,6 @@ gui_action_type get_gui_input()
|
|||
}
|
||||
}
|
||||
break;
|
||||
#ifdef RPI_BUILD
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
{
|
||||
switch (event.jbutton.button)
|
||||
{
|
||||
case 2:
|
||||
gui_action = CURSOR_BACK;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
gui_action = CURSOR_EXIT;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
gui_action = CURSOR_SELECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_JOYAXISMOTION:
|
||||
{
|
||||
if (event.jaxis.axis==0) { //Left-Right
|
||||
if (event.jaxis.value < -3200) gui_action = CURSOR_LEFT;
|
||||
else if (event.jaxis.value > 3200) gui_action = CURSOR_RIGHT;
|
||||
}
|
||||
if (event.jaxis.axis==1) { //Up-Down
|
||||
if (event.jaxis.value < -3200) gui_action = CURSOR_UP;
|
||||
else if (event.jaxis.value > 3200) gui_action = CURSOR_DOWN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -875,21 +588,6 @@ u32 update_input()
|
|||
key &= ~(joy_map(event.jbutton.button));
|
||||
break;
|
||||
}
|
||||
#ifdef RPI_BUILD
|
||||
case SDL_JOYAXISMOTION:
|
||||
{
|
||||
if (event.jaxis.axis==0) { //Left-Right
|
||||
key &= ~(BUTTON_LEFT|BUTTON_RIGHT);
|
||||
if (event.jaxis.value < -3200) key |= BUTTON_LEFT;
|
||||
else if (event.jaxis.value > 3200) key |= BUTTON_RIGHT;
|
||||
}
|
||||
if (event.jaxis.axis==1) { //Up-Down
|
||||
key &= ~(BUTTON_UP|BUTTON_DOWN);
|
||||
if (event.jaxis.value < -3200) key |= BUTTON_UP;
|
||||
else if (event.jaxis.value > 3200) key |= BUTTON_DOWN;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
21
main.c
21
main.c
|
@ -38,13 +38,8 @@ debug_state current_debug_state = RUN;
|
|||
|
||||
//u32 breakpoint_value = 0;
|
||||
|
||||
#ifdef RPI_BUILD
|
||||
frameskip_type current_frameskip_type = manual_frameskip; //manual; //auto_frameskip;
|
||||
u32 global_cycles_per_instruction = 1;
|
||||
#else
|
||||
frameskip_type current_frameskip_type = auto_frameskip;
|
||||
u32 global_cycles_per_instruction = 1;
|
||||
#endif
|
||||
|
||||
u32 random_skip = 0;
|
||||
u32 fps_debug = 0;
|
||||
|
@ -83,11 +78,7 @@ u32 oam_update_count = 0;
|
|||
u32 synchronize_flag = 1;
|
||||
|
||||
u32 update_backup_flag = 1;
|
||||
#ifdef GP2X_BUILD
|
||||
u32 clock_speed = 200;
|
||||
#else
|
||||
u32 clock_speed = 333;
|
||||
#endif
|
||||
char main_path[512];
|
||||
|
||||
void trigger_ext_event();
|
||||
|
@ -275,11 +266,7 @@ int main(int argc, char *argv[])
|
|||
debug_screen_printl("a860e8c0b6d573d191e4ec7db1b1e4f6 ");
|
||||
debug_screen_printl(" ");
|
||||
debug_screen_printl("When you do get it name it gba_bios.bin and put it");
|
||||
#ifdef PND_BUILD
|
||||
debug_screen_printl("in <SD card>/pandora/appdata/gpsp/ . ");
|
||||
#else
|
||||
debug_screen_printl("in the same directory as gpSP. ");
|
||||
#endif
|
||||
debug_screen_printl(" ");
|
||||
debug_screen_printl("Press any button to exit. ");
|
||||
|
||||
|
@ -827,11 +814,7 @@ void synchronize()
|
|||
}
|
||||
else if (synchronize_flag)
|
||||
{
|
||||
#if defined(PND_BUILD) || defined(RPI_BUILD)
|
||||
fb_wait_vsync();
|
||||
#elif !defined(GP2X_BUILD) // sleeping on GP2X is a bad idea
|
||||
delay_us((u64)virtual_frame_count * 50000 / 3 - new_ticks + 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
frames++;
|
||||
|
@ -873,11 +856,9 @@ void synchronize()
|
|||
|
||||
interval_skipped_frames += skip_next_frame;
|
||||
|
||||
#if !defined(GP2X_BUILD) && !defined(PND_BUILD) && !defined(RPI_BUILD)
|
||||
char char_buffer[64];
|
||||
sprintf(char_buffer, "gpSP: %2d (%2d) fps", fps, frames_drawn);
|
||||
SDL_WM_SetCaption(char_buffer, "gpSP");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1034,8 +1015,6 @@ void set_clock_speed()
|
|||
printf("about to set CPU clock to %iMHz\n", clock_speed);
|
||||
#ifdef PSP_BUILD
|
||||
scePowerSetClockFrequency(clock_speed, clock_speed, clock_speed / 2);
|
||||
#elif defined(GP2X_BUILD)
|
||||
set_FCLK(clock_speed);
|
||||
#endif
|
||||
clock_speed_old = clock_speed;
|
||||
}
|
||||
|
|
4
memory.c
4
memory.c
|
@ -2166,14 +2166,10 @@ u32 load_gamepak(char *name)
|
|||
s32 file_size;
|
||||
char cheats_filename[256];
|
||||
|
||||
#ifdef WIZ_BUILD
|
||||
file_size = wiz_load_gamepak(name);
|
||||
#else
|
||||
if(!strcmp(dot_position, ".zip"))
|
||||
file_size = load_file_zip(name);
|
||||
else
|
||||
file_size = load_gamepak_raw(name);
|
||||
#endif
|
||||
|
||||
// A dumb April fool's joke was here once :o
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
# gpSP makefile
|
||||
# Gilead Kutnick - Exophase
|
||||
# pandora port - notaz
|
||||
|
||||
# Global definitions
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
|
||||
OBJS = pnd.o main.o cpu.o memory.o video.o input.o sound.o gui.o \
|
||||
cheats.o zip.o cpu_threaded.o arm_stub.o video_blend.o warm.o \
|
||||
neon_scale2x.o neon_scale3x.o neon_eagle2x.o \
|
||||
linux/fbdev.o linux/xenv.o
|
||||
BIN = gpsp
|
||||
|
||||
# Platform specific definitions
|
||||
|
||||
VPATH += .. ../arm
|
||||
CFLAGS += -DARM_ARCH -DPND_BUILD -Wall
|
||||
CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfloat-abi=softfp -mfpu=neon -ffast-math
|
||||
CFLAGS += -ggdb
|
||||
ifndef DEBUG
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
# expecting to have PATH set up to get correct sdl-config first
|
||||
CFLAGS += `sdl-config --cflags`
|
||||
LIBS += `sdl-config --libs`
|
||||
LIBS += -ldl -lpthread -lz
|
||||
|
||||
# Compilation:
|
||||
|
||||
all: $(BIN) picorestore
|
||||
|
||||
%.o: %.S
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(OBJS) $(LIBS) -o $(BIN)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(BIN) picorestore
|
||||
|
||||
# ----------- release -----------
|
||||
|
||||
PND_MAKE ?= $(HOME)/dev/pnd/src/pandora-libraries/testdata/scripts/pnd_make.sh
|
||||
|
||||
rel: gpsp gpsp.sh gpsp.pxml gba_icon.png picorestore readme.txt ../game_config.txt ../COPYING.DOC
|
||||
rm -rf out
|
||||
mkdir out
|
||||
cp $^ out/
|
||||
$(PND_MAKE) -p gpsp.pnd -d out -x out/gpsp.pxml -i out/gba_icon.png -c
|
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PXML xmlns="http://openpandora.org/namespaces/PXML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
|
||||
<package id="package.gpsp.notaz">
|
||||
<titles>
|
||||
<title lang="en_US">gpSP</title>
|
||||
</titles>
|
||||
<version major="0" minor="9" release="2" build="8"/>
|
||||
<author name="Exophase/notaz" website="http://notaz.gp2x.de/"/>
|
||||
</package>
|
||||
<application id="gpsp.notaz" appdata="gpsp">
|
||||
<titles>
|
||||
<title lang="en_US">gpSP</title>
|
||||
</titles>
|
||||
<title lang="en_US">gpSP</title>
|
||||
|
||||
<descriptions>
|
||||
<description lang="en_US">An optimized GBA emulator.</description>
|
||||
</descriptions>
|
||||
|
||||
<exec command="gpsp.sh"/>
|
||||
|
||||
<icon src="gba_icon.png"/>
|
||||
|
||||
<author name="Exophase/notaz" website="http://notaz.gp2x.de/"/>
|
||||
|
||||
<version major="0" minor="9" release="2" build="8"/>
|
||||
|
||||
<licenses>
|
||||
<license name="GPLv2+" url="http://www.gnu.org/licenses/gpl-2.0.html" sourcecodeurl="http://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=gpsp.git"/>
|
||||
</licenses>
|
||||
|
||||
<info name="gpSP u8 readme" type="text/plain" src="readme.txt"/>
|
||||
|
||||
<categories>
|
||||
<category name="Game">
|
||||
<subcategory name="Emulator"/>
|
||||
</category>
|
||||
</categories>
|
||||
</application>
|
||||
</PXML>
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ ! -f romdir.txt ]; then
|
||||
echo -n "/media/" > romdir.txt
|
||||
fi
|
||||
sudo -n /usr/pandora/scripts/op_lcdrate.sh 60
|
||||
|
||||
./gpsp "$@"
|
||||
|
||||
# restore stuff in case of crash
|
||||
./picorestore
|
|
@ -1,255 +0,0 @@
|
|||
/*
|
||||
* (C) Gražvydas "notaz" Ignotas, 2009-2010
|
||||
*
|
||||
* This work is licensed under the terms of any of these licenses
|
||||
* (at your option):
|
||||
* - GNU GPL, version 2 or later.
|
||||
* - GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/matroxfb.h>
|
||||
|
||||
#include "fbdev.h"
|
||||
|
||||
struct vout_fbdev {
|
||||
int fd;
|
||||
void *mem;
|
||||
size_t mem_size;
|
||||
struct fb_var_screeninfo fbvar_old;
|
||||
struct fb_var_screeninfo fbvar_new;
|
||||
int buffer_write;
|
||||
int fb_size;
|
||||
int buffer_count;
|
||||
int top_border, bottom_border;
|
||||
};
|
||||
|
||||
void *vout_fbdev_flip(struct vout_fbdev *fbdev)
|
||||
{
|
||||
int draw_buf;
|
||||
|
||||
if (fbdev->buffer_count < 2)
|
||||
return fbdev->mem;
|
||||
|
||||
draw_buf = fbdev->buffer_write;
|
||||
fbdev->buffer_write++;
|
||||
if (fbdev->buffer_write >= fbdev->buffer_count)
|
||||
fbdev->buffer_write = 0;
|
||||
|
||||
fbdev->fbvar_new.yoffset =
|
||||
(fbdev->top_border + fbdev->fbvar_new.yres + fbdev->bottom_border) * draw_buf +
|
||||
fbdev->top_border;
|
||||
|
||||
ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
|
||||
|
||||
return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write;
|
||||
}
|
||||
|
||||
void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev)
|
||||
{
|
||||
int arg = 0;
|
||||
ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg);
|
||||
}
|
||||
|
||||
/* it is recommended to call vout_fbdev_clear() before this */
|
||||
void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp,
|
||||
int left_border, int right_border, int top_border, int bottom_border, int buffer_cnt)
|
||||
{
|
||||
int w_total = left_border + w + right_border;
|
||||
int h_total = top_border + h + bottom_border;
|
||||
size_t mem_size;
|
||||
int ret;
|
||||
|
||||
// unblank to be sure the mode is really accepted
|
||||
ioctl(fbdev->fd, FBIOBLANK, FB_BLANK_UNBLANK);
|
||||
|
||||
if (fbdev->fbvar_new.bits_per_pixel != bpp ||
|
||||
fbdev->fbvar_new.xres != w ||
|
||||
fbdev->fbvar_new.yres != h ||
|
||||
fbdev->fbvar_new.xres_virtual != w_total||
|
||||
fbdev->fbvar_new.yres_virtual < h_total ||
|
||||
fbdev->fbvar_new.xoffset != left_border ||
|
||||
fbdev->buffer_count != buffer_cnt)
|
||||
{
|
||||
if (fbdev->fbvar_new.bits_per_pixel != bpp ||
|
||||
w != fbdev->fbvar_new.xres || h != fbdev->fbvar_new.yres)
|
||||
printf(" switching to %dx%d@%d\n", w, h, bpp);
|
||||
|
||||
fbdev->fbvar_new.xres = w;
|
||||
fbdev->fbvar_new.yres = h;
|
||||
fbdev->fbvar_new.xres_virtual = w_total;
|
||||
fbdev->fbvar_new.yres_virtual = h_total * buffer_cnt;
|
||||
fbdev->fbvar_new.xoffset = left_border;
|
||||
fbdev->fbvar_new.yoffset = top_border;
|
||||
fbdev->fbvar_new.bits_per_pixel = bpp;
|
||||
fbdev->fbvar_new.nonstd = 0; // can set YUV here on omapfb
|
||||
fbdev->buffer_count = buffer_cnt;
|
||||
fbdev->buffer_write = 1;
|
||||
|
||||
// seems to help a bit to avoid glitches
|
||||
vout_fbdev_wait_vsync(fbdev);
|
||||
|
||||
ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
|
||||
if (ret == -1) {
|
||||
// retry with no multibuffering
|
||||
fbdev->fbvar_new.yres_virtual = h_total;
|
||||
ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
|
||||
if (ret == -1) {
|
||||
perror("FBIOPUT_VSCREENINFO ioctl");
|
||||
return NULL;
|
||||
}
|
||||
fbdev->buffer_count = 1;
|
||||
fbdev->buffer_write = 0;
|
||||
fprintf(stderr, "Warning: failed to increase virtual resolution, "
|
||||
"multibuffering disabled\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fbdev->fb_size = w_total * h_total * bpp / 8;
|
||||
fbdev->top_border = top_border;
|
||||
fbdev->bottom_border = bottom_border;
|
||||
|
||||
mem_size = fbdev->fb_size * fbdev->buffer_count;
|
||||
if (fbdev->mem_size >= mem_size)
|
||||
goto out;
|
||||
|
||||
if (fbdev->mem != NULL)
|
||||
munmap(fbdev->mem, fbdev->mem_size);
|
||||
|
||||
fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
|
||||
if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) {
|
||||
fprintf(stderr, "Warning: can't map %zd bytes, doublebuffering disabled\n", mem_size);
|
||||
fbdev->buffer_count = 1;
|
||||
fbdev->buffer_write = 0;
|
||||
mem_size = fbdev->fb_size;
|
||||
fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
|
||||
}
|
||||
if (fbdev->mem == MAP_FAILED) {
|
||||
fbdev->mem = NULL;
|
||||
fbdev->mem_size = 0;
|
||||
perror("mmap framebuffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fbdev->mem_size = mem_size;
|
||||
|
||||
out:
|
||||
return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write;
|
||||
}
|
||||
|
||||
void vout_fbdev_clear(struct vout_fbdev *fbdev)
|
||||
{
|
||||
memset(fbdev->mem, 0, fbdev->mem_size);
|
||||
}
|
||||
|
||||
void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count)
|
||||
{
|
||||
int stride = fbdev->fbvar_new.xres_virtual * fbdev->fbvar_new.bits_per_pixel / 8;
|
||||
int i;
|
||||
|
||||
if (y + count > fbdev->top_border + fbdev->fbvar_new.yres)
|
||||
count = fbdev->top_border + fbdev->fbvar_new.yres - y;
|
||||
|
||||
if (y >= 0 && count > 0)
|
||||
for (i = 0; i < fbdev->buffer_count; i++)
|
||||
memset((char *)fbdev->mem + fbdev->fb_size * i + y * stride, 0, stride * count);
|
||||
}
|
||||
|
||||
int vout_fbdev_get_fd(struct vout_fbdev *fbdev)
|
||||
{
|
||||
return fbdev->fd;
|
||||
}
|
||||
|
||||
struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int bpp, int buffer_cnt)
|
||||
{
|
||||
struct vout_fbdev *fbdev;
|
||||
int req_w, req_h;
|
||||
void *pret;
|
||||
int ret;
|
||||
|
||||
fbdev = calloc(1, sizeof(*fbdev));
|
||||
if (fbdev == NULL)
|
||||
return NULL;
|
||||
|
||||
fbdev->fd = open(fbdev_name, O_RDWR);
|
||||
if (fbdev->fd == -1) {
|
||||
fprintf(stderr, "%s: ", fbdev_name);
|
||||
perror("open");
|
||||
goto fail_open;
|
||||
}
|
||||
|
||||
ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old);
|
||||
if (ret == -1) {
|
||||
perror("FBIOGET_VSCREENINFO ioctl");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fbdev->fbvar_new = fbdev->fbvar_old;
|
||||
|
||||
req_w = fbdev->fbvar_new.xres;
|
||||
if (*w != 0)
|
||||
req_w = *w;
|
||||
req_h = fbdev->fbvar_new.yres;
|
||||
if (*h != 0)
|
||||
req_h = *h;
|
||||
|
||||
pret = vout_fbdev_resize(fbdev, req_w, req_h, bpp, 0, 0, 0, 0, buffer_cnt);
|
||||
if (pret == NULL)
|
||||
goto fail;
|
||||
|
||||
printf("%s: %ix%i@%d\n", fbdev_name, fbdev->fbvar_new.xres, fbdev->fbvar_new.yres,
|
||||
fbdev->fbvar_new.bits_per_pixel);
|
||||
*w = fbdev->fbvar_new.xres;
|
||||
*h = fbdev->fbvar_new.yres;
|
||||
|
||||
memset(fbdev->mem, 0, fbdev->mem_size);
|
||||
|
||||
// some checks
|
||||
ret = 0;
|
||||
ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "Warning: vsync doesn't seem to be supported\n");
|
||||
|
||||
if (fbdev->buffer_count > 1) {
|
||||
fbdev->buffer_write = 0;
|
||||
fbdev->fbvar_new.yoffset = fbdev->fbvar_new.yres * (fbdev->buffer_count - 1);
|
||||
ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
|
||||
if (ret != 0) {
|
||||
fbdev->buffer_count = 1;
|
||||
fprintf(stderr, "Warning: can't pan display, doublebuffering disabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("fbdev initialized.\n");
|
||||
return fbdev;
|
||||
|
||||
fail:
|
||||
close(fbdev->fd);
|
||||
fail_open:
|
||||
free(fbdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vout_fbdev_finish(struct vout_fbdev *fbdev)
|
||||
{
|
||||
ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old);
|
||||
if (fbdev->mem != MAP_FAILED)
|
||||
munmap(fbdev->mem, fbdev->mem_size);
|
||||
if (fbdev->fd >= 0)
|
||||
close(fbdev->fd);
|
||||
fbdev->mem = NULL;
|
||||
fbdev->fd = -1;
|
||||
free(fbdev);
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
struct vout_fbdev;
|
||||
|
||||
struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int bpp, int buffer_count);
|
||||
void *vout_fbdev_flip(struct vout_fbdev *fbdev);
|
||||
void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev);
|
||||
void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp,
|
||||
int left_border, int right_border, int top_border, int bottom_border,
|
||||
int buffer_count);
|
||||
void vout_fbdev_clear(struct vout_fbdev *fbdev);
|
||||
void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count);
|
||||
int vout_fbdev_get_fd(struct vout_fbdev *fbdev);
|
||||
void vout_fbdev_finish(struct vout_fbdev *fbdev);
|
|
@ -1,427 +0,0 @@
|
|||
/*
|
||||
* File: arch/arm/plat-omap/include/mach/omapfb.h
|
||||
*
|
||||
* Framebuffer driver for TI OMAP boards
|
||||
*
|
||||
* Copyright (C) 2004 Nokia Corporation
|
||||
* Author: Imre Deak <imre.deak@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __OMAPFB_H
|
||||
#define __OMAPFB_H
|
||||
|
||||
#include <asm/ioctl.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
/* IOCTL commands. */
|
||||
|
||||
#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
|
||||
#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
|
||||
#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
|
||||
#define OMAP_IO(num) _IO('O', num)
|
||||
|
||||
#define OMAPFB_MIRROR OMAP_IOW(31, int)
|
||||
#define OMAPFB_SYNC_GFX OMAP_IO(37)
|
||||
#define OMAPFB_VSYNC OMAP_IO(38)
|
||||
#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
|
||||
#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
|
||||
#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
|
||||
#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
|
||||
#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
|
||||
#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
|
||||
#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
|
||||
#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
|
||||
#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
|
||||
#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
|
||||
#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
|
||||
#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
|
||||
#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
|
||||
#define OMAPFB_WAITFORVSYNC OMAP_IO(57)
|
||||
#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
|
||||
|
||||
#ifndef FBIO_WAITFORVSYNC
|
||||
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t)
|
||||
#endif
|
||||
|
||||
#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
|
||||
#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
|
||||
#define OMAPFB_CAPS_PANEL_MASK 0xff000000
|
||||
|
||||
#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
|
||||
#define OMAPFB_CAPS_TEARSYNC 0x00002000
|
||||
#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
|
||||
#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
|
||||
#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
|
||||
#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
|
||||
#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
|
||||
#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
|
||||
#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
|
||||
|
||||
/* Values from DSP must map to lower 16-bits */
|
||||
#define OMAPFB_FORMAT_MASK 0x00ff
|
||||
#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
|
||||
#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
|
||||
#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
|
||||
#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
|
||||
#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
|
||||
|
||||
#define OMAPFB_EVENT_READY 1
|
||||
#define OMAPFB_EVENT_DISABLED 2
|
||||
|
||||
#define OMAPFB_MEMTYPE_SDRAM 0
|
||||
#define OMAPFB_MEMTYPE_SRAM 1
|
||||
#define OMAPFB_MEMTYPE_MAX 1
|
||||
|
||||
enum omapfb_color_format {
|
||||
OMAPFB_COLOR_RGB565 = 0,
|
||||
OMAPFB_COLOR_YUV422,
|
||||
OMAPFB_COLOR_YUV420,
|
||||
OMAPFB_COLOR_CLUT_8BPP,
|
||||
OMAPFB_COLOR_CLUT_4BPP,
|
||||
OMAPFB_COLOR_CLUT_2BPP,
|
||||
OMAPFB_COLOR_CLUT_1BPP,
|
||||
OMAPFB_COLOR_RGB444,
|
||||
OMAPFB_COLOR_YUY422,
|
||||
|
||||
OMAPFB_COLOR_ARGB16,
|
||||
OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */
|
||||
OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */
|
||||
OMAPFB_COLOR_ARGB32,
|
||||
OMAPFB_COLOR_RGBA32,
|
||||
OMAPFB_COLOR_RGBX32,
|
||||
};
|
||||
|
||||
struct omapfb_update_window {
|
||||
__u32 x, y;
|
||||
__u32 width, height;
|
||||
__u32 format;
|
||||
__u32 out_x, out_y;
|
||||
__u32 out_width, out_height;
|
||||
__u32 reserved[8];
|
||||
};
|
||||
|
||||
struct omapfb_update_window_old {
|
||||
__u32 x, y;
|
||||
__u32 width, height;
|
||||
__u32 format;
|
||||
};
|
||||
|
||||
enum omapfb_plane {
|
||||
OMAPFB_PLANE_GFX = 0,
|
||||
OMAPFB_PLANE_VID1,
|
||||
OMAPFB_PLANE_VID2,
|
||||
};
|
||||
|
||||
enum omapfb_channel_out {
|
||||
OMAPFB_CHANNEL_OUT_LCD = 0,
|
||||
OMAPFB_CHANNEL_OUT_DIGIT,
|
||||
};
|
||||
|
||||
struct omapfb_plane_info {
|
||||
__u32 pos_x;
|
||||
__u32 pos_y;
|
||||
__u8 enabled;
|
||||
__u8 channel_out;
|
||||
__u8 mirror;
|
||||
__u8 reserved1;
|
||||
__u32 out_width;
|
||||
__u32 out_height;
|
||||
__u32 reserved2[12];
|
||||
};
|
||||
|
||||
struct omapfb_mem_info {
|
||||
__u32 size;
|
||||
__u8 type;
|
||||
__u8 reserved[3];
|
||||
};
|
||||
|
||||
struct omapfb_caps {
|
||||
__u32 ctrl;
|
||||
__u32 plane_color;
|
||||
__u32 wnd_color;
|
||||
};
|
||||
|
||||
enum omapfb_color_key_type {
|
||||
OMAPFB_COLOR_KEY_DISABLED = 0,
|
||||
OMAPFB_COLOR_KEY_GFX_DST,
|
||||
OMAPFB_COLOR_KEY_VID_SRC,
|
||||
};
|
||||
|
||||
struct omapfb_color_key {
|
||||
__u8 channel_out;
|
||||
__u32 background;
|
||||
__u32 trans_key;
|
||||
__u8 key_type;
|
||||
};
|
||||
|
||||
enum omapfb_update_mode {
|
||||
OMAPFB_UPDATE_DISABLED = 0,
|
||||
OMAPFB_AUTO_UPDATE,
|
||||
OMAPFB_MANUAL_UPDATE
|
||||
};
|
||||
|
||||
struct omapfb_memory_read {
|
||||
__u16 x;
|
||||
__u16 y;
|
||||
__u16 w;
|
||||
__u16 h;
|
||||
size_t buffer_size;
|
||||
void *buffer;
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <mach/board.h>
|
||||
|
||||
#define OMAP_LCDC_INV_VSYNC 0x0001
|
||||
#define OMAP_LCDC_INV_HSYNC 0x0002
|
||||
#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
|
||||
#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
|
||||
#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
|
||||
#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
|
||||
|
||||
#define OMAP_LCDC_SIGNAL_MASK 0x003f
|
||||
|
||||
#define OMAP_LCDC_PANEL_TFT 0x0100
|
||||
|
||||
#define OMAPFB_PLANE_XRES_MIN 8
|
||||
#define OMAPFB_PLANE_YRES_MIN 8
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#define OMAPFB_PLANE_NUM 1
|
||||
#else
|
||||
#define OMAPFB_PLANE_NUM 3
|
||||
#endif
|
||||
|
||||
struct omapfb_device;
|
||||
|
||||
struct lcd_panel {
|
||||
const char *name;
|
||||
int config; /* TFT/STN, signal inversion */
|
||||
int bpp; /* Pixel format in fb mem */
|
||||
int data_lines; /* Lines on LCD HW interface */
|
||||
|
||||
int x_res, y_res;
|
||||
int pixel_clock; /* In kHz */
|
||||
int hsw; /* Horizontal synchronization
|
||||
pulse width */
|
||||
int hfp; /* Horizontal front porch */
|
||||
int hbp; /* Horizontal back porch */
|
||||
int vsw; /* Vertical synchronization
|
||||
pulse width */
|
||||
int vfp; /* Vertical front porch */
|
||||
int vbp; /* Vertical back porch */
|
||||
int acb; /* ac-bias pin frequency */
|
||||
int pcd; /* pixel clock divider.
|
||||
Obsolete use pixel_clock instead */
|
||||
|
||||
int (*init) (struct lcd_panel *panel,
|
||||
struct omapfb_device *fbdev);
|
||||
void (*cleanup) (struct lcd_panel *panel);
|
||||
int (*enable) (struct lcd_panel *panel);
|
||||
void (*disable) (struct lcd_panel *panel);
|
||||
unsigned long (*get_caps) (struct lcd_panel *panel);
|
||||
int (*set_bklight_level)(struct lcd_panel *panel,
|
||||
unsigned int level);
|
||||
unsigned int (*get_bklight_level)(struct lcd_panel *panel);
|
||||
unsigned int (*get_bklight_max) (struct lcd_panel *panel);
|
||||
int (*run_test) (struct lcd_panel *panel, int test_num);
|
||||
};
|
||||
|
||||
struct extif_timings {
|
||||
int cs_on_time;
|
||||
int cs_off_time;
|
||||
int we_on_time;
|
||||
int we_off_time;
|
||||
int re_on_time;
|
||||
int re_off_time;
|
||||
int we_cycle_time;
|
||||
int re_cycle_time;
|
||||
int cs_pulse_width;
|
||||
int access_time;
|
||||
|
||||
int clk_div;
|
||||
|
||||
u32 tim[5]; /* set by extif->convert_timings */
|
||||
|
||||
int converted;
|
||||
};
|
||||
|
||||
struct lcd_ctrl_extif {
|
||||
int (*init) (struct omapfb_device *fbdev);
|
||||
void (*cleanup) (void);
|
||||
void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
|
||||
unsigned long (*get_max_tx_rate)(void);
|
||||
int (*convert_timings) (struct extif_timings *timings);
|
||||
void (*set_timings) (const struct extif_timings *timings);
|
||||
void (*set_bits_per_cycle)(int bpc);
|
||||
void (*write_command) (const void *buf, unsigned int len);
|
||||
void (*read_data) (void *buf, unsigned int len);
|
||||
void (*write_data) (const void *buf, unsigned int len);
|
||||
void (*transfer_area) (int width, int height,
|
||||
void (callback)(void * data), void *data);
|
||||
int (*setup_tearsync) (unsigned pin_cnt,
|
||||
unsigned hs_pulse_time, unsigned vs_pulse_time,
|
||||
int hs_pol_inv, int vs_pol_inv, int div);
|
||||
int (*enable_tearsync) (int enable, unsigned line);
|
||||
|
||||
unsigned long max_transmit_size;
|
||||
};
|
||||
|
||||
struct omapfb_notifier_block {
|
||||
struct notifier_block nb;
|
||||
void *data;
|
||||
int plane_idx;
|
||||
};
|
||||
|
||||
typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
|
||||
unsigned long event,
|
||||
void *fbi);
|
||||
|
||||
struct omapfb_mem_region {
|
||||
u32 paddr;
|
||||
void __iomem *vaddr;
|
||||
unsigned long size;
|
||||
u8 type; /* OMAPFB_PLANE_MEM_* */
|
||||
enum omapfb_color_format format;/* OMAPFB_COLOR_* */
|
||||
unsigned format_used:1; /* Must be set when format is set.
|
||||
* Needed b/c of the badly chosen 0
|
||||
* base for OMAPFB_COLOR_* values
|
||||
*/
|
||||
unsigned alloc:1; /* allocated by the driver */
|
||||
unsigned map:1; /* kernel mapped by the driver */
|
||||
};
|
||||
|
||||
struct omapfb_mem_desc {
|
||||
int region_cnt;
|
||||
struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
|
||||
};
|
||||
|
||||
struct lcd_ctrl {
|
||||
const char *name;
|
||||
void *data;
|
||||
|
||||
int (*init) (struct omapfb_device *fbdev,
|
||||
int ext_mode,
|
||||
struct omapfb_mem_desc *req_md);
|
||||
void (*cleanup) (void);
|
||||
void (*bind_client) (struct omapfb_notifier_block *nb);
|
||||
void (*get_caps) (int plane, struct omapfb_caps *caps);
|
||||
int (*set_update_mode)(enum omapfb_update_mode mode);
|
||||
enum omapfb_update_mode (*get_update_mode)(void);
|
||||
int (*setup_plane) (int plane, int channel_out,
|
||||
unsigned long offset,
|
||||
int screen_width,
|
||||
int pos_x, int pos_y, int width,
|
||||
int height, int color_mode);
|
||||
int (*set_rotate) (int angle);
|
||||
int (*setup_mem) (int plane, size_t size,
|
||||
int mem_type, unsigned long *paddr);
|
||||
int (*mmap) (struct fb_info *info,
|
||||
struct vm_area_struct *vma);
|
||||
int (*set_scale) (int plane,
|
||||
int orig_width, int orig_height,
|
||||
int out_width, int out_height);
|
||||
int (*enable_plane) (int plane, int enable);
|
||||
int (*update_window) (struct fb_info *fbi,
|
||||
struct omapfb_update_window *win,
|
||||
void (*callback)(void *),
|
||||
void *callback_data);
|
||||
void (*sync) (void);
|
||||
void (*suspend) (void);
|
||||
void (*resume) (void);
|
||||
int (*run_test) (int test_num);
|
||||
int (*setcolreg) (u_int regno, u16 red, u16 green,
|
||||
u16 blue, u16 transp,
|
||||
int update_hw_mem);
|
||||
int (*set_color_key) (struct omapfb_color_key *ck);
|
||||
int (*get_color_key) (struct omapfb_color_key *ck);
|
||||
};
|
||||
|
||||
enum omapfb_state {
|
||||
OMAPFB_DISABLED = 0,
|
||||
OMAPFB_SUSPENDED= 99,
|
||||
OMAPFB_ACTIVE = 100
|
||||
};
|
||||
|
||||
struct omapfb_plane_struct {
|
||||
int idx;
|
||||
struct omapfb_plane_info info;
|
||||
enum omapfb_color_format color_mode;
|
||||
struct omapfb_device *fbdev;
|
||||
};
|
||||
|
||||
struct omapfb_device {
|
||||
int state;
|
||||
int ext_lcdc; /* Using external
|
||||
LCD controller */
|
||||
struct mutex rqueue_mutex;
|
||||
|
||||
int palette_size;
|
||||
u32 pseudo_palette[17];
|
||||
|
||||
struct lcd_panel *panel; /* LCD panel */
|
||||
const struct lcd_ctrl *ctrl; /* LCD controller */
|
||||
const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
|
||||
struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
|
||||
interface */
|
||||
struct device *dev;
|
||||
struct fb_var_screeninfo new_var; /* for mode changes */
|
||||
|
||||
struct omapfb_mem_desc mem_desc;
|
||||
struct fb_info *fb_info[OMAPFB_PLANE_NUM];
|
||||
};
|
||||
|
||||
struct omapfb_platform_data {
|
||||
struct omap_lcd_config lcd;
|
||||
struct omapfb_mem_desc mem_desc;
|
||||
void *ctrl_platform_data;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
extern struct lcd_ctrl omap1_lcd_ctrl;
|
||||
#else
|
||||
extern struct lcd_ctrl omap2_disp_ctrl;
|
||||
#endif
|
||||
|
||||
extern void omapfb_set_platform_data(struct omapfb_platform_data *data);
|
||||
|
||||
extern void omapfb_reserve_sdram(void);
|
||||
extern void omapfb_register_panel(struct lcd_panel *panel);
|
||||
extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
|
||||
extern void omapfb_notify_clients(struct omapfb_device *fbdev,
|
||||
unsigned long event);
|
||||
extern int omapfb_register_client(struct omapfb_notifier_block *nb,
|
||||
omapfb_notifier_callback_t callback,
|
||||
void *callback_data);
|
||||
extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
|
||||
extern int omapfb_update_window_async(struct fb_info *fbi,
|
||||
struct omapfb_update_window *win,
|
||||
void (*callback)(void *),
|
||||
void *callback_data);
|
||||
|
||||
/* in arch/arm/plat-omap/fb.c */
|
||||
extern void omapfb_set_ctrl_platform_data(void *pdata);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __OMAPFB_H */
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
* (C) Gražvydas "notaz" Ignotas, 2009-2011
|
||||
*
|
||||
* This work is licensed under the terms of any of these licenses
|
||||
* (at your option):
|
||||
* - GNU GPL, version 2 or later.
|
||||
* - GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <linux/kd.h>
|
||||
|
||||
#define PFX "xenv: "
|
||||
|
||||
#define FPTR(f) typeof(f) * p##f
|
||||
#define FPTR_LINK(xf, dl, f) { \
|
||||
xf.p##f = dlsym(dl, #f); \
|
||||
if (xf.p##f == NULL) { \
|
||||
fprintf(stderr, "missing symbol: %s\n", #f); \
|
||||
goto fail; \
|
||||
} \
|
||||
}
|
||||
|
||||
struct xstuff {
|
||||
Display *display;
|
||||
FPTR(XCreateBitmapFromData);
|
||||
FPTR(XCreatePixmapCursor);
|
||||
FPTR(XFreePixmap);
|
||||
FPTR(XOpenDisplay);
|
||||
FPTR(XDisplayName);
|
||||
FPTR(XCloseDisplay);
|
||||
FPTR(XCreateSimpleWindow);
|
||||
FPTR(XChangeWindowAttributes);
|
||||
FPTR(XSelectInput);
|
||||
FPTR(XMapWindow);
|
||||
FPTR(XNextEvent);
|
||||
FPTR(XCheckTypedEvent);
|
||||
FPTR(XUnmapWindow);
|
||||
FPTR(XGrabKeyboard);
|
||||
FPTR(XPending);
|
||||
FPTR(XLookupKeysym);
|
||||
FPTR(XkbSetDetectableAutoRepeat);
|
||||
};
|
||||
|
||||
static struct xstuff g_xstuff;
|
||||
|
||||
static Cursor transparent_cursor(struct xstuff *xf, Display *display, Window win)
|
||||
{
|
||||
Cursor cursor;
|
||||
Pixmap pix;
|
||||
XColor dummy;
|
||||
char d = 0;
|
||||
|
||||
memset(&dummy, 0, sizeof(dummy));
|
||||
pix = xf->pXCreateBitmapFromData(display, win, &d, 1, 1);
|
||||
cursor = xf->pXCreatePixmapCursor(display, pix, pix,
|
||||
&dummy, &dummy, 0, 0);
|
||||
xf->pXFreePixmap(display, pix);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static int x11h_init(void)
|
||||
{
|
||||
unsigned int display_width, display_height;
|
||||
Display *display;
|
||||
XSetWindowAttributes attributes;
|
||||
Window win;
|
||||
Visual *visual;
|
||||
void *x11lib;
|
||||
int screen;
|
||||
|
||||
memset(&g_xstuff, 0, sizeof(g_xstuff));
|
||||
x11lib = dlopen("libX11.so.6", RTLD_LAZY);
|
||||
if (x11lib == NULL) {
|
||||
fprintf(stderr, "libX11.so load failed:\n%s\n", dlerror());
|
||||
goto fail;
|
||||
}
|
||||
FPTR_LINK(g_xstuff, x11lib, XCreateBitmapFromData);
|
||||
FPTR_LINK(g_xstuff, x11lib, XCreatePixmapCursor);
|
||||
FPTR_LINK(g_xstuff, x11lib, XFreePixmap);
|
||||
FPTR_LINK(g_xstuff, x11lib, XOpenDisplay);
|
||||
FPTR_LINK(g_xstuff, x11lib, XDisplayName);
|
||||
FPTR_LINK(g_xstuff, x11lib, XCloseDisplay);
|
||||
FPTR_LINK(g_xstuff, x11lib, XCreateSimpleWindow);
|
||||
FPTR_LINK(g_xstuff, x11lib, XChangeWindowAttributes);
|
||||
FPTR_LINK(g_xstuff, x11lib, XSelectInput);
|
||||
FPTR_LINK(g_xstuff, x11lib, XMapWindow);
|
||||
FPTR_LINK(g_xstuff, x11lib, XNextEvent);
|
||||
FPTR_LINK(g_xstuff, x11lib, XCheckTypedEvent);
|
||||
FPTR_LINK(g_xstuff, x11lib, XUnmapWindow);
|
||||
FPTR_LINK(g_xstuff, x11lib, XGrabKeyboard);
|
||||
FPTR_LINK(g_xstuff, x11lib, XPending);
|
||||
FPTR_LINK(g_xstuff, x11lib, XLookupKeysym);
|
||||
FPTR_LINK(g_xstuff, x11lib, XkbSetDetectableAutoRepeat);
|
||||
|
||||
//XInitThreads();
|
||||
|
||||
g_xstuff.display = display = g_xstuff.pXOpenDisplay(NULL);
|
||||
if (display == NULL)
|
||||
{
|
||||
fprintf(stderr, "cannot connect to X server %s, X handling disabled.\n",
|
||||
g_xstuff.pXDisplayName(NULL));
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
visual = DefaultVisual(display, 0);
|
||||
if (visual->class != TrueColor)
|
||||
fprintf(stderr, PFX "warning: non true color visual\n");
|
||||
|
||||
printf(PFX "X vendor: %s, rel: %d, display: %s, protocol ver: %d.%d\n", ServerVendor(display),
|
||||
VendorRelease(display), DisplayString(display), ProtocolVersion(display),
|
||||
ProtocolRevision(display));
|
||||
|
||||
screen = DefaultScreen(display);
|
||||
|
||||
display_width = DisplayWidth(display, screen);
|
||||
display_height = DisplayHeight(display, screen);
|
||||
printf(PFX "display is %dx%d\n", display_width, display_height);
|
||||
|
||||
win = g_xstuff.pXCreateSimpleWindow(display,
|
||||
RootWindow(display, screen),
|
||||
0, 0, display_width, display_height, 0,
|
||||
BlackPixel(display, screen),
|
||||
BlackPixel(display, screen));
|
||||
|
||||
attributes.override_redirect = True;
|
||||
attributes.cursor = transparent_cursor(&g_xstuff, display, win);
|
||||
g_xstuff.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
|
||||
|
||||
g_xstuff.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask);
|
||||
g_xstuff.pXMapWindow(display, win);
|
||||
g_xstuff.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
|
||||
// XSetIOErrorHandler
|
||||
|
||||
return 0;
|
||||
fail2:
|
||||
dlclose(x11lib);
|
||||
fail:
|
||||
g_xstuff.display = NULL;
|
||||
fprintf(stderr, "x11 handling disabled.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int x11h_update(int *is_down)
|
||||
{
|
||||
XEvent evt;
|
||||
|
||||
while (g_xstuff.pXPending(g_xstuff.display))
|
||||
{
|
||||
g_xstuff.pXNextEvent(g_xstuff.display, &evt);
|
||||
switch (evt.type)
|
||||
{
|
||||
case Expose:
|
||||
while (g_xstuff.pXCheckTypedEvent(g_xstuff.display, Expose, &evt))
|
||||
;
|
||||
break;
|
||||
|
||||
case KeyPress:
|
||||
*is_down = 1;
|
||||
return g_xstuff.pXLookupKeysym(&evt.xkey, 0);
|
||||
|
||||
case KeyRelease:
|
||||
*is_down = 0;
|
||||
return g_xstuff.pXLookupKeysym(&evt.xkey, 0);
|
||||
// printf("press %d\n", evt.xkey.keycode);
|
||||
}
|
||||
}
|
||||
|
||||
return NoSymbol;
|
||||
}
|
||||
|
||||
static struct termios g_kbd_termios_saved;
|
||||
static int g_kbdfd;
|
||||
|
||||
static int tty_init(void)
|
||||
{
|
||||
struct termios kbd_termios;
|
||||
int mode;
|
||||
|
||||
g_kbdfd = open("/dev/tty", O_RDWR);
|
||||
if (g_kbdfd == -1) {
|
||||
perror(PFX "open /dev/tty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(g_kbdfd, KDGETMODE, &mode) == -1) {
|
||||
perror(PFX "(not hiding FB): KDGETMODE");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (tcgetattr(g_kbdfd, &kbd_termios) == -1) {
|
||||
perror(PFX "tcgetattr");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
g_kbd_termios_saved = kbd_termios;
|
||||
kbd_termios.c_lflag &= ~(ICANON | ECHO); // | ISIG);
|
||||
kbd_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
|
||||
kbd_termios.c_cc[VMIN] = 0;
|
||||
kbd_termios.c_cc[VTIME] = 0;
|
||||
|
||||
if (tcsetattr(g_kbdfd, TCSAFLUSH, &kbd_termios) == -1) {
|
||||
perror(PFX "tcsetattr");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ioctl(g_kbdfd, KDSETMODE, KD_GRAPHICS) == -1) {
|
||||
perror(PFX "KDSETMODE KD_GRAPHICS");
|
||||
tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
close(g_kbdfd);
|
||||
g_kbdfd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void tty_end(void)
|
||||
{
|
||||
if (g_kbdfd <= 0)
|
||||
return;
|
||||
|
||||
if (ioctl(g_kbdfd, KDSETMODE, KD_TEXT) == -1)
|
||||
perror(PFX "KDSETMODE KD_TEXT");
|
||||
|
||||
if (tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved) == -1)
|
||||
perror(PFX "tcsetattr");
|
||||
|
||||
close(g_kbdfd);
|
||||
g_kbdfd = -1;
|
||||
}
|
||||
|
||||
int xenv_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = x11h_init();
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
ret = tty_init();
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
fprintf(stderr, PFX "error: both x11h_init and tty_init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xenv_update(int *is_down)
|
||||
{
|
||||
if (g_xstuff.display)
|
||||
return x11h_update(is_down);
|
||||
|
||||
// TODO: read tty?
|
||||
return -1;
|
||||
}
|
||||
|
||||
void xenv_finish(void)
|
||||
{
|
||||
// TODO: cleanup X?
|
||||
tty_end();
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
int xenv_init(void);
|
||||
int xenv_update(int *is_down);
|
||||
void xenv_finish(void);
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* picorestore - clean up after an omapfb program crash
|
||||
*
|
||||
* Copyright (c) Gražvydas "notaz" Ignotas, 2010
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the organization nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/omapfb.h>
|
||||
#include <linux/kd.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
struct fb_var_screeninfo fbvar;
|
||||
struct omapfb_plane_info pi;
|
||||
struct omapfb_mem_info mi;
|
||||
int ret, fbdev, kbdfd;
|
||||
|
||||
fbdev = open("/dev/fb0", O_RDWR);
|
||||
if (fbdev == -1) {
|
||||
perror("open fb0");
|
||||
goto end_fb0;
|
||||
}
|
||||
|
||||
ret = ioctl(fbdev, FBIOGET_VSCREENINFO, &fbvar);
|
||||
if (ret == -1) {
|
||||
perror("FBIOGET_VSCREENINFO ioctl");
|
||||
goto end_fb0;
|
||||
}
|
||||
|
||||
if (fbvar.yoffset != 0) {
|
||||
printf("fixing yoffset.. ");
|
||||
fbvar.yoffset = 0;
|
||||
ret = ioctl(fbdev, FBIOPAN_DISPLAY, &fbvar);
|
||||
if (ret < 0)
|
||||
perror("ioctl FBIOPAN_DISPLAY");
|
||||
else
|
||||
printf("ok\n");
|
||||
}
|
||||
|
||||
end_fb0:
|
||||
if (fbdev >= 0)
|
||||
close(fbdev);
|
||||
|
||||
fbdev = open("/dev/fb1", O_RDWR);
|
||||
if (fbdev == -1) {
|
||||
perror("open fb1");
|
||||
goto end_fb1;
|
||||
}
|
||||
|
||||
ret = ioctl(fbdev, OMAPFB_QUERY_PLANE, &pi);
|
||||
ret |= ioctl(fbdev, OMAPFB_QUERY_MEM, &mi);
|
||||
if (ret != 0)
|
||||
perror("QUERY_*");
|
||||
|
||||
pi.enabled = 0;
|
||||
ret = ioctl(fbdev, OMAPFB_SETUP_PLANE, &pi);
|
||||
if (ret != 0)
|
||||
perror("SETUP_PLANE");
|
||||
|
||||
mi.size = 0;
|
||||
ret = ioctl(fbdev, OMAPFB_SETUP_MEM, &mi);
|
||||
if (ret != 0)
|
||||
perror("SETUP_MEM");
|
||||
|
||||
end_fb1:
|
||||
if (fbdev >= 0)
|
||||
close(fbdev);
|
||||
|
||||
kbdfd = open("/dev/tty", O_RDWR);
|
||||
if (kbdfd == -1) {
|
||||
perror("open /dev/tty");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ioctl(kbdfd, KDSETMODE, KD_TEXT) == -1)
|
||||
perror("KDSETMODE KD_TEXT");
|
||||
|
||||
close(kbdfd);
|
||||
|
||||
return 0;
|
||||
}
|
381
pandora/pnd.c
381
pandora/pnd.c
|
@ -1,381 +0,0 @@
|
|||
/* gameplaySP - pandora backend
|
||||
*
|
||||
* Copyright (C) 2011 notaz <notasas@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
||||
#include <X11/keysym.h>
|
||||
#include "linux/omapfb.h" //
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "../arm/neon_scale2x.h"
|
||||
#include "../arm/neon_scale3x.h"
|
||||
#include "../arm/neon_eagle2x.h"
|
||||
#include "linux/fbdev.h"
|
||||
#include "linux/xenv.h"
|
||||
|
||||
enum gpsp_key {
|
||||
GKEY_UP = 1 << 0,
|
||||
GKEY_LEFT = 1 << 1,
|
||||
GKEY_DOWN = 1 << 2,
|
||||
GKEY_RIGHT = 1 << 3,
|
||||
GKEY_START = 1 << 4,
|
||||
GKEY_SELECT = 1 << 5,
|
||||
GKEY_L = 1 << 6,
|
||||
GKEY_R = 1 << 7,
|
||||
GKEY_A = 1 << 8,
|
||||
GKEY_B = 1 << 9,
|
||||
GKEY_X = 1 << 10,
|
||||
GKEY_Y = 1 << 11,
|
||||
GKEY_1 = 1 << 12,
|
||||
GKEY_2 = 1 << 13,
|
||||
GKEY_3 = 1 << 14,
|
||||
GKEY_4 = 1 << 15,
|
||||
GKEY_MENU = 1 << 16,
|
||||
};
|
||||
|
||||
u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT] =
|
||||
{
|
||||
GKEY_UP,
|
||||
GKEY_LEFT,
|
||||
GKEY_DOWN,
|
||||
GKEY_RIGHT,
|
||||
GKEY_START,
|
||||
GKEY_SELECT,
|
||||
GKEY_L,
|
||||
GKEY_R,
|
||||
GKEY_A,
|
||||
GKEY_B,
|
||||
GKEY_X,
|
||||
GKEY_Y,
|
||||
GKEY_1,
|
||||
GKEY_2,
|
||||
GKEY_3,
|
||||
GKEY_4,
|
||||
GKEY_MENU,
|
||||
};
|
||||
|
||||
u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
|
||||
{
|
||||
BUTTON_ID_UP, // Up
|
||||
BUTTON_ID_LEFT, // Left
|
||||
BUTTON_ID_DOWN, // Down
|
||||
BUTTON_ID_RIGHT, // Right
|
||||
BUTTON_ID_START, // Start
|
||||
BUTTON_ID_SELECT, // Select
|
||||
BUTTON_ID_L, // Ltrigger
|
||||
BUTTON_ID_R, // Rtrigger
|
||||
BUTTON_ID_FPS, // A
|
||||
BUTTON_ID_A, // B
|
||||
BUTTON_ID_B, // X
|
||||
BUTTON_ID_MENU, // Y
|
||||
BUTTON_ID_SAVESTATE, // 1
|
||||
BUTTON_ID_LOADSTATE, // 2
|
||||
BUTTON_ID_FASTFORWARD, // 3
|
||||
BUTTON_ID_NONE, // 4
|
||||
BUTTON_ID_MENU // Space
|
||||
};
|
||||
|
||||
static const u32 xk_to_gkey[] = {
|
||||
XK_Up, XK_Left, XK_Down, XK_Right, XK_Alt_L, XK_Control_L,
|
||||
XK_Shift_R, XK_Control_R, XK_Home, XK_End, XK_Page_Down, XK_Page_Up,
|
||||
XK_1, XK_2, XK_3, XK_4, XK_space,
|
||||
};
|
||||
|
||||
static const u8 gkey_to_cursor[32] = {
|
||||
[0 ... 31] = CURSOR_NONE,
|
||||
[0] = CURSOR_UP, CURSOR_LEFT, CURSOR_DOWN, CURSOR_RIGHT, CURSOR_NONE, CURSOR_NONE,
|
||||
CURSOR_L, CURSOR_R, CURSOR_SELECT, CURSOR_SELECT, CURSOR_EXIT, CURSOR_BACK,
|
||||
};
|
||||
|
||||
struct vout_fbdev *fb;
|
||||
static void *fb_current;
|
||||
static int bounce_buf[400 * 272 * 2 / 4];
|
||||
static int src_w = 240, src_h = 160;
|
||||
static enum software_filter {
|
||||
SWFILTER_NONE = 0,
|
||||
SWFILTER_SCALE2X,
|
||||
SWFILTER_SCALE3X,
|
||||
SWFILTER_EAGLE2X,
|
||||
} sw_filter;
|
||||
|
||||
// (240*3 * 160*3 * 2 * 3)
|
||||
#define MAX_VRAM_SIZE (400*2 * 272*2 * 2 * 3)
|
||||
|
||||
|
||||
static int omap_setup_layer(int fd, int enabled, int x, int y, int w, int h)
|
||||
{
|
||||
struct omapfb_plane_info pi = { 0, };
|
||||
struct omapfb_mem_info mi = { 0, };
|
||||
int ret;
|
||||
|
||||
ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
|
||||
if (ret != 0) {
|
||||
perror("QUERY_PLANE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
|
||||
if (ret != 0) {
|
||||
perror("QUERY_MEM");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* must disable when changing stuff */
|
||||
if (pi.enabled) {
|
||||
pi.enabled = 0;
|
||||
ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
|
||||
if (ret != 0)
|
||||
perror("SETUP_PLANE");
|
||||
}
|
||||
|
||||
/* alloc enough for 3x scaled tripple buffering */
|
||||
if (mi.size < MAX_VRAM_SIZE) {
|
||||
mi.size = MAX_VRAM_SIZE;
|
||||
ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
|
||||
if (ret != 0) {
|
||||
perror("SETUP_MEM");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
pi.pos_x = x;
|
||||
pi.pos_y = y;
|
||||
pi.out_width = w;
|
||||
pi.out_height = h;
|
||||
pi.enabled = enabled;
|
||||
|
||||
ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
|
||||
if (ret != 0) {
|
||||
perror("SETUP_PLANE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpsp_plat_init(void)
|
||||
{
|
||||
int ret, w, h, fd;
|
||||
const char *layer_fb_name;
|
||||
|
||||
ret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
layer_fb_name = getenv("FBDEV_LAYER");
|
||||
if (layer_fb_name == NULL)
|
||||
layer_fb_name = "/dev/fb1";
|
||||
|
||||
ret = xenv_init();
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "xenv_init failed with %d\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// must set the layer up first to be able to use it
|
||||
fd = open(layer_fb_name, O_RDWR);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "%s: ", layer_fb_name);
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = omap_setup_layer(fd, 0, 0, 0, 400, 272);
|
||||
close(fd);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "failed to set up layer, exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// double of original menu size
|
||||
w = 400*2;
|
||||
h = 272*2;
|
||||
fb = vout_fbdev_init("/dev/fb1", &w, &h, 16, 3);
|
||||
if (fb == NULL) {
|
||||
fprintf(stderr, "vout_fbdev_init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// default to 3x scale
|
||||
screen_scale = 2;
|
||||
}
|
||||
|
||||
void gpsp_plat_quit(void)
|
||||
{
|
||||
xenv_finish();
|
||||
omap_setup_layer(vout_fbdev_get_fd(fb), 0, 0, 0, 0, 0);
|
||||
vout_fbdev_finish(fb);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
u32 gpsp_plat_joystick_read(void)
|
||||
{
|
||||
static int gkeystate;
|
||||
int key, is_down, i;
|
||||
int gkey = -1;
|
||||
|
||||
key = xenv_update(&is_down);
|
||||
for (i = 0; i < sizeof(xk_to_gkey) / sizeof(xk_to_gkey[0]); i++) {
|
||||
if (key == xk_to_gkey[i]) {
|
||||
gkey = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gkey >= 0) {
|
||||
if (is_down)
|
||||
gkeystate |= 1 << gkey;
|
||||
else
|
||||
gkeystate &= ~(1 << gkey);
|
||||
}
|
||||
|
||||
return gkeystate;
|
||||
}
|
||||
|
||||
u32 gpsp_plat_buttons_to_cursor(u32 buttons)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (buttons == 0)
|
||||
return CURSOR_NONE;
|
||||
|
||||
for (i = 0; (buttons & 1) == 0; i++, buttons >>= 1)
|
||||
;
|
||||
|
||||
return gkey_to_cursor[i];
|
||||
}
|
||||
|
||||
static void set_filter(int is_filtered)
|
||||
{
|
||||
static int was_filtered = -1;
|
||||
char buf[128];
|
||||
|
||||
if (is_filtered == was_filtered)
|
||||
return;
|
||||
|
||||
snprintf(buf, sizeof(buf), "sudo -n /usr/pandora/scripts/op_videofir.sh %s",
|
||||
is_filtered ? "default" : "none");
|
||||
system(buf);
|
||||
was_filtered = is_filtered;
|
||||
}
|
||||
|
||||
void *fb_flip_screen(void)
|
||||
{
|
||||
void *ret = bounce_buf;
|
||||
void *s = bounce_buf;
|
||||
|
||||
switch (sw_filter) {
|
||||
case SWFILTER_SCALE2X:
|
||||
neon_scale2x_16_16(s, fb_current, src_w, src_w*2, src_w*2*2, src_h);
|
||||
break;
|
||||
case SWFILTER_SCALE3X:
|
||||
neon_scale3x_16_16(s, fb_current, src_w, src_w*2, src_w*3*2, src_h);
|
||||
break;
|
||||
case SWFILTER_EAGLE2X:
|
||||
neon_eagle2x_16_16(s, fb_current, src_w, src_w*2, src_w*2*2, src_h);
|
||||
break;
|
||||
case SWFILTER_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fb_current = vout_fbdev_flip(fb);
|
||||
if (sw_filter == SWFILTER_NONE)
|
||||
ret = fb_current;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fb_wait_vsync(void)
|
||||
{
|
||||
vout_fbdev_wait_vsync(fb);
|
||||
}
|
||||
|
||||
void fb_set_mode(int w, int h, int buffers, int scale,
|
||||
int filter, int filter2)
|
||||
{
|
||||
int lx, ly, lw = w, lh = h;
|
||||
int multiplier;
|
||||
|
||||
switch (scale) {
|
||||
case 0:
|
||||
lw = w;
|
||||
lh = h;
|
||||
break;
|
||||
case 1:
|
||||
lw = w * 2;
|
||||
lh = h * 2;
|
||||
break;
|
||||
case 2:
|
||||
lw = w * 3;
|
||||
lh = h * 3;
|
||||
break;
|
||||
case 3:
|
||||
lw = 800;
|
||||
lh = 480;
|
||||
break;
|
||||
case 15:
|
||||
lw = 800;
|
||||
lh = 480;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown scale: %d\n", scale);
|
||||
break;
|
||||
}
|
||||
if (lw > 800)
|
||||
lw = 800;
|
||||
if (lh > 480)
|
||||
lh = 480;
|
||||
lx = 800 / 2 - lw / 2;
|
||||
ly = 480 / 2 - lh / 2;
|
||||
|
||||
omap_setup_layer(vout_fbdev_get_fd(fb), 1, lx, ly, lw, lh);
|
||||
set_filter(filter);
|
||||
|
||||
sw_filter = filter2;
|
||||
if (w != 240) // menu
|
||||
sw_filter = SWFILTER_SCALE2X;
|
||||
|
||||
switch (sw_filter) {
|
||||
case SWFILTER_SCALE2X:
|
||||
multiplier = 2;
|
||||
break;
|
||||
case SWFILTER_SCALE3X:
|
||||
multiplier = 3;
|
||||
break;
|
||||
case SWFILTER_EAGLE2X:
|
||||
multiplier = 2;
|
||||
break;
|
||||
case SWFILTER_NONE:
|
||||
default:
|
||||
multiplier = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
fb_current = vout_fbdev_resize(fb, w * multiplier, h * multiplier,
|
||||
16, 0, 0, 0, 0, buffers);
|
||||
src_w = w;
|
||||
src_h = h;
|
||||
}
|
||||
|
||||
// vim:shiftwidth=2:expandtab
|
|
@ -1,14 +0,0 @@
|
|||
void gpsp_plat_init(void);
|
||||
void gpsp_plat_quit(void);
|
||||
|
||||
u32 gpsp_plat_joystick_read(void);
|
||||
u32 gpsp_plat_buttons_to_cursor(u32 buttons);
|
||||
|
||||
#define PLAT_BUTTON_COUNT 17
|
||||
#define PLAT_MENU_BUTTON -1 // have one hardcoded
|
||||
extern u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT];
|
||||
|
||||
void *fb_flip_screen(void);
|
||||
void fb_set_mode(int w, int h, int buffers, int scale,
|
||||
int filter, int filter2);
|
||||
void fb_wait_vsync(void);
|
1223
pandora/readme.txt
1223
pandora/readme.txt
File diff suppressed because it is too large
Load Diff
|
@ -1,45 +0,0 @@
|
|||
# gpSP makefile
|
||||
# Gilead Kutnick - Exophase
|
||||
# pandora port - notaz
|
||||
# respberry pi - DPR
|
||||
|
||||
# Global definitions
|
||||
|
||||
CC = gcc
|
||||
|
||||
OBJS = rpi.o main.o cpu.o memory.o video.o input.o sound.o gui.o \
|
||||
cheats.o zip.o arm_stub.o warm.o cpu_threaded.o\
|
||||
gles_video.o video_blend.o
|
||||
|
||||
BIN = gpsp
|
||||
|
||||
# Platform specific definitions
|
||||
|
||||
VPATH += .. ../arm
|
||||
CFLAGS += -DARM_ARCH -DRPI_BUILD -Wall
|
||||
CFLAGS += -O3 -mfpu=vfp
|
||||
CFLAGS += `sdl-config --cflags`
|
||||
CFLAGS += -I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
|
||||
CFLAGS += -I/opt/vc/include/interface/vmcs_host/linux
|
||||
|
||||
# expecting to have PATH set up to get correct sdl-config first
|
||||
|
||||
LIBS += `sdl-config --libs`
|
||||
LIBS += -ldl -lpthread -lz
|
||||
LIBS += -L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lrt
|
||||
|
||||
# Compilation:
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
%.o: %.S
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
|
||||
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(OBJS) $(LIBS) -o $(BIN)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(BIN)
|
|
@ -1,417 +0,0 @@
|
|||
/*
|
||||
|
||||
This file is based on Portable ZX-Spectrum emulator.
|
||||
Copyright (C) 2001-2012 SMT, Dexus, Alone Coder, deathsoft, djdron, scor
|
||||
|
||||
C++ to C code conversion by Pate
|
||||
|
||||
Modified by DPR for gpsp for Raspberry Pi
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "bcm_host.h"
|
||||
#include "GLES/gl.h"
|
||||
#include "EGL/egl.h"
|
||||
#include "EGL/eglext.h"
|
||||
#include "GLES2/gl2.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
static uint32_t frame_width = 0;
|
||||
static uint32_t frame_height = 0;
|
||||
|
||||
|
||||
#define SHOW_ERROR gles_show_error();
|
||||
|
||||
static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y);
|
||||
|
||||
static const char* vertex_shader =
|
||||
"uniform mat4 u_vp_matrix; \n"
|
||||
"attribute vec4 a_position; \n"
|
||||
"attribute vec2 a_texcoord; \n"
|
||||
"varying mediump vec2 v_texcoord; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" v_texcoord = a_texcoord; \n"
|
||||
" gl_Position = u_vp_matrix * a_position; \n"
|
||||
"} \n";
|
||||
|
||||
static const char* fragment_shader =
|
||||
"varying mediump vec2 v_texcoord; \n"
|
||||
"uniform sampler2D u_texture; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_FragColor = texture2D(u_texture, v_texcoord); \n"
|
||||
"} \n";
|
||||
/*
|
||||
static const GLfloat vertices[] =
|
||||
{
|
||||
-0.5f, -0.5f, 0.0f,
|
||||
+0.5f, -0.5f, 0.0f,
|
||||
+0.5f, +0.5f, 0.0f,
|
||||
-0.5f, +0.5f, 0.0f,
|
||||
};
|
||||
*/
|
||||
static const GLfloat vertices[] =
|
||||
{
|
||||
-0.5f, -0.5f, 0.0f,
|
||||
-0.5f, +0.5f, 0.0f,
|
||||
+0.5f, +0.5f, 0.0f,
|
||||
+0.5f, -0.5f, 0.0f,
|
||||
};
|
||||
|
||||
#define TEX_WIDTH 1024
|
||||
#define TEX_HEIGHT 512
|
||||
|
||||
static const GLfloat uvs[8];
|
||||
|
||||
static const GLushort indices[] =
|
||||
{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
};
|
||||
|
||||
static const int kVertexCount = 4;
|
||||
static const int kIndexCount = 6;
|
||||
|
||||
|
||||
void Create_uvs(GLfloat * matrix, GLfloat max_u, GLfloat max_v) {
|
||||
memset(matrix,0,sizeof(GLfloat)*8);
|
||||
matrix[3]=max_v;
|
||||
matrix[4]=max_u;
|
||||
matrix[5]=max_v;
|
||||
matrix[6]=max_u;
|
||||
|
||||
}
|
||||
|
||||
void gles_show_error()
|
||||
{
|
||||
GLenum error = GL_NO_ERROR;
|
||||
error = glGetError();
|
||||
if (GL_NO_ERROR != error)
|
||||
printf("GL Error %x encountered!\n", error);
|
||||
}
|
||||
|
||||
static GLuint CreateShader(GLenum type, const char *shader_src)
|
||||
{
|
||||
GLuint shader = glCreateShader(type);
|
||||
if(!shader)
|
||||
return 0;
|
||||
|
||||
// Load and compile the shader source
|
||||
glShaderSource(shader, 1, &shader_src, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
// Check the compile status
|
||||
GLint compiled = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
|
||||
if(!compiled)
|
||||
{
|
||||
GLint info_len = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
|
||||
if(info_len > 1)
|
||||
{
|
||||
char* info_log = (char *)malloc(sizeof(char) * info_len);
|
||||
glGetShaderInfoLog(shader, info_len, NULL, info_log);
|
||||
// TODO(dspringer): We could really use a logging API.
|
||||
printf("Error compiling shader:\n%s\n", info_log);
|
||||
free(info_log);
|
||||
}
|
||||
glDeleteShader(shader);
|
||||
return 0;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
static GLuint CreateProgram(const char *vertex_shader_src, const char *fragment_shader_src)
|
||||
{
|
||||
GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_src);
|
||||
if(!vertex_shader)
|
||||
return 0;
|
||||
GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_src);
|
||||
if(!fragment_shader)
|
||||
{
|
||||
glDeleteShader(vertex_shader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint program_object = glCreateProgram();
|
||||
if(!program_object)
|
||||
return 0;
|
||||
glAttachShader(program_object, vertex_shader);
|
||||
glAttachShader(program_object, fragment_shader);
|
||||
|
||||
// Link the program
|
||||
glLinkProgram(program_object);
|
||||
|
||||
// Check the link status
|
||||
GLint linked = 0;
|
||||
glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
|
||||
if(!linked)
|
||||
{
|
||||
GLint info_len = 0;
|
||||
glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
|
||||
if(info_len > 1)
|
||||
{
|
||||
char* info_log = (char *)malloc(info_len);
|
||||
glGetProgramInfoLog(program_object, info_len, NULL, info_log);
|
||||
// TODO(dspringer): We could really use a logging API.
|
||||
printf("Error linking program:\n%s\n", info_log);
|
||||
free(info_log);
|
||||
}
|
||||
glDeleteProgram(program_object);
|
||||
return 0;
|
||||
}
|
||||
// Delete these here because they are attached to the program object.
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
return program_object;
|
||||
}
|
||||
|
||||
typedef struct ShaderInfo {
|
||||
GLuint program;
|
||||
GLint a_position;
|
||||
GLint a_texcoord;
|
||||
GLint u_vp_matrix;
|
||||
GLint u_texture;
|
||||
} ShaderInfo;
|
||||
|
||||
static ShaderInfo shader;
|
||||
static ShaderInfo shader_filtering;
|
||||
static GLuint buffers[3];
|
||||
static GLuint textures[2];
|
||||
|
||||
|
||||
static void gles2_create()
|
||||
{
|
||||
memset(&shader, 0, sizeof(ShaderInfo));
|
||||
shader.program = CreateProgram(vertex_shader, fragment_shader);
|
||||
if(shader.program)
|
||||
{
|
||||
shader.a_position = glGetAttribLocation(shader.program, "a_position");
|
||||
shader.a_texcoord = glGetAttribLocation(shader.program, "a_texcoord");
|
||||
shader.u_vp_matrix = glGetUniformLocation(shader.program, "u_vp_matrix");
|
||||
shader.u_texture = glGetUniformLocation(shader.program, "u_texture");
|
||||
}
|
||||
glGenTextures(1, textures);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
|
||||
|
||||
Create_uvs(uvs, (float)frame_width/TEX_WIDTH, (float)frame_height/TEX_HEIGHT);
|
||||
|
||||
glGenBuffers(3, buffers);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 3, vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 2, uvs, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, kIndexCount * sizeof(GL_UNSIGNED_SHORT), indices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DITHER);
|
||||
}
|
||||
|
||||
static uint32_t screen_width = 0;
|
||||
static uint32_t screen_height = 0;
|
||||
|
||||
static EGLDisplay display = NULL;
|
||||
static EGLSurface surface = NULL;
|
||||
static EGLContext context = NULL;
|
||||
static EGL_DISPMANX_WINDOW_T nativewindow;
|
||||
|
||||
static GLfloat proj[4][4];
|
||||
static GLint filter_min;
|
||||
static GLint filter_mag;
|
||||
|
||||
void video_set_filter(uint32_t filter) {
|
||||
if (filter==0) {
|
||||
filter_min = GL_NEAREST;
|
||||
filter_mag = GL_NEAREST;
|
||||
} else {
|
||||
filter_min = GL_LINEAR;
|
||||
filter_mag = GL_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
void video_init(uint32_t _width, uint32_t _height, uint32_t filter)
|
||||
{
|
||||
if ((_width==0)||(_height==0))
|
||||
return;
|
||||
|
||||
frame_width = _width;
|
||||
frame_height = _height;
|
||||
|
||||
//bcm_host_init();
|
||||
|
||||
// get an EGL display connection
|
||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
assert(display != EGL_NO_DISPLAY);
|
||||
|
||||
// initialize the EGL display connection
|
||||
EGLBoolean result = eglInitialize(display, NULL, NULL);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
// get an appropriate EGL frame buffer configuration
|
||||
EGLint num_config;
|
||||
EGLConfig config;
|
||||
static const EGLint attribute_list[] =
|
||||
{
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
result = eglBindAPI(EGL_OPENGL_ES_API);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
// create an EGL rendering context
|
||||
static const EGLint context_attributes[] =
|
||||
{
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
|
||||
assert(context != EGL_NO_CONTEXT);
|
||||
|
||||
// create an EGL window surface
|
||||
int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
|
||||
assert(success >= 0);
|
||||
|
||||
VC_RECT_T dst_rect;
|
||||
dst_rect.x = 0;
|
||||
dst_rect.y = 0;
|
||||
dst_rect.width = screen_width;
|
||||
dst_rect.height = screen_height;
|
||||
|
||||
VC_RECT_T src_rect;
|
||||
src_rect.x = 0;
|
||||
src_rect.y = 0;
|
||||
src_rect.width = screen_width << 16;
|
||||
src_rect.height = screen_height << 16;
|
||||
|
||||
DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
|
||||
DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
|
||||
DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
|
||||
1, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
|
||||
|
||||
nativewindow.element = dispman_element;
|
||||
nativewindow.width = screen_width;
|
||||
nativewindow.height = screen_height;
|
||||
vc_dispmanx_update_submit_sync(dispman_update);
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
|
||||
assert(surface != EGL_NO_SURFACE);
|
||||
|
||||
// connect the context to the surface
|
||||
result = eglMakeCurrent(display, surface, surface, context);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
gles2_create();
|
||||
|
||||
int r=(screen_height*10/frame_height);
|
||||
int h = (frame_height*r)/10;
|
||||
int w = (frame_width*r)/10;
|
||||
if (w>screen_width) {
|
||||
r = (screen_width*10/frame_width);
|
||||
h = (frame_height*r)/10;
|
||||
w = (frame_width*r)/10;
|
||||
}
|
||||
glViewport((screen_width-w)/2, (screen_height-h)/2, w, h);
|
||||
SetOrtho(proj, -0.5f, +0.5f, +0.5f, -0.5f, -1.0f, 1.0f, 1.0f ,1.0f );
|
||||
video_set_filter(filter);
|
||||
}
|
||||
|
||||
static void gles2_destroy()
|
||||
{
|
||||
if(!shader.program)
|
||||
return;
|
||||
glDeleteBuffers(3, buffers); SHOW_ERROR
|
||||
glDeleteProgram(shader.program); SHOW_ERROR
|
||||
}
|
||||
|
||||
static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y)
|
||||
{
|
||||
memset(m, 0, 4*4*sizeof(GLfloat));
|
||||
m[0][0] = 2.0f/(right - left)*scale_x;
|
||||
m[1][1] = 2.0f/(top - bottom)*scale_y;
|
||||
m[2][2] = -2.0f/(far - near);
|
||||
m[3][0] = -(right + left)/(right - left);
|
||||
m[3][1] = -(top + bottom)/(top - bottom);
|
||||
m[3][2] = -(far + near)/(far - near);
|
||||
m[3][3] = 1;
|
||||
}
|
||||
#define RGB15(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
|
||||
|
||||
static void gles2_Draw( uint16_t *pixels)
|
||||
{
|
||||
if(!shader.program)
|
||||
return;
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glUseProgram(shader.program);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(shader.u_texture, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_min);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
|
||||
glVertexAttribPointer(shader.a_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
|
||||
glEnableVertexAttribArray(shader.a_position);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
|
||||
glVertexAttribPointer(shader.a_texcoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
|
||||
glEnableVertexAttribArray(shader.a_texcoord);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
|
||||
glUniformMatrix4fv(shader.u_vp_matrix, 1, GL_FALSE, (const GLfloat * )&proj);
|
||||
glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
//glFlush();
|
||||
}
|
||||
|
||||
void video_close()
|
||||
{
|
||||
gles2_destroy();
|
||||
// Release OpenGL resources
|
||||
eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
|
||||
eglDestroySurface( display, surface );
|
||||
eglDestroyContext( display, context );
|
||||
eglTerminate( display );
|
||||
}
|
||||
|
||||
void video_draw(uint16_t *pixels)
|
||||
{
|
||||
gles2_Draw (pixels);
|
||||
eglSwapBuffers(display, surface);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
|
||||
This file is based on Portable ZX-Spectrum emulator.
|
||||
Copyright (C) 2001-2012 SMT, Dexus, Alone Coder, deathsoft, djdron, scor
|
||||
|
||||
C++ to C code conversion by Pate
|
||||
|
||||
Modified by DPR for gpsp for Raspberry Pi
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
void video_init(uint32_t width,uint32_t height,uint32_t filter);
|
||||
void video_close();
|
||||
void video_draw(uint16_t *pixels);
|
|
@ -1,33 +0,0 @@
|
|||
gpsp raspberry pi
|
||||
|
||||
CONTROL KEYS
|
||||
============
|
||||
KEYBOARD
|
||||
---------
|
||||
Up Up Arrow
|
||||
Down Down Arrow
|
||||
Left Left Arrow
|
||||
Right Right Arrow
|
||||
A Z
|
||||
B X
|
||||
Start Enter
|
||||
Select Backspace
|
||||
L A
|
||||
R S
|
||||
|
||||
Exit Esc
|
||||
Menu F10
|
||||
|
||||
GAMEPAD
|
||||
-------
|
||||
Up XAsix -
|
||||
Down XAsix +
|
||||
Left YAsix -
|
||||
Right YAsix +
|
||||
A Button 1
|
||||
B Button 2
|
||||
Start Button 3
|
||||
Select Button 4
|
||||
L Button 5
|
||||
R Button 6
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
/* gameplaySP - raspberry backend
|
||||
*
|
||||
* Copyright (C) 2013 DPR <pribyl.email@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "gles_video.h"
|
||||
#include "rpi.h"
|
||||
#include "bcm_host.h"
|
||||
|
||||
u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
|
||||
{
|
||||
BUTTON_ID_UP, // Up
|
||||
BUTTON_ID_LEFT, // Left
|
||||
BUTTON_ID_DOWN, // Down
|
||||
BUTTON_ID_RIGHT, // Right
|
||||
BUTTON_ID_START, // Start
|
||||
BUTTON_ID_SELECT, // Select
|
||||
BUTTON_ID_L, // Ltrigger
|
||||
BUTTON_ID_R, // Rtrigger
|
||||
BUTTON_ID_FPS, // A
|
||||
BUTTON_ID_A, // B
|
||||
BUTTON_ID_B, // X
|
||||
BUTTON_ID_MENU, // Y
|
||||
BUTTON_ID_SAVESTATE, // 1
|
||||
BUTTON_ID_LOADSTATE, // 2
|
||||
BUTTON_ID_FASTFORWARD, // 3
|
||||
BUTTON_ID_NONE, // 4
|
||||
BUTTON_ID_MENU // Space
|
||||
};
|
||||
|
||||
|
||||
#define MAX_VIDEO_MEM (480*270*2)
|
||||
static int video_started=0;
|
||||
static uint16_t * video_buff;
|
||||
|
||||
|
||||
void gpsp_plat_init(void)
|
||||
{
|
||||
int ret, w, h, fd;
|
||||
//const char *layer_fb_name;
|
||||
SDL_Surface* myVideoSurface;
|
||||
|
||||
bcm_host_init();
|
||||
|
||||
ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
myVideoSurface = SDL_SetVideoMode( 0, 0, 16, SDL_SWSURFACE);
|
||||
// Print out some information about the video surface
|
||||
if (myVideoSurface == NULL) {
|
||||
fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
SDL_ShowCursor(0);
|
||||
fb_set_mode(240, 160, 0, 0, 0, 0);
|
||||
screen_scale = 3;
|
||||
}
|
||||
|
||||
void gpsp_plat_quit(void)
|
||||
{
|
||||
if (video_started) {
|
||||
video_close();
|
||||
free(video_buff);
|
||||
video_started=0;
|
||||
}
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
|
||||
void *fb_flip_screen(void)
|
||||
{
|
||||
video_draw(video_buff);
|
||||
return video_buff;
|
||||
}
|
||||
|
||||
void fb_wait_vsync(void)
|
||||
{
|
||||
}
|
||||
|
||||
void fb_set_mode(int w, int h, int buffers, int scale,int filter, int filter2)
|
||||
{
|
||||
if (video_started) {
|
||||
video_close();
|
||||
free(video_buff);
|
||||
}
|
||||
video_buff=malloc(w*h*sizeof(uint16_t));
|
||||
memset(video_buff,0,w*h*sizeof(uint16_t));
|
||||
video_init(w,h,filter);
|
||||
video_started=1;
|
||||
}
|
||||
// vim:shiftwidth=2:expandtab
|
|
@ -1,10 +0,0 @@
|
|||
void gpsp_plat_init(void);
|
||||
void gpsp_plat_quit(void);
|
||||
|
||||
#define PLAT_BUTTON_COUNT 17
|
||||
#define PLAT_MENU_BUTTON -1 // have one hardcoded
|
||||
extern u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT];
|
||||
|
||||
void *fb_flip_screen(void);
|
||||
void fb_set_mode(int w, int h, int buffers, int scale, int filter, int filter2);
|
||||
void fb_wait_vsync(void);
|
|
@ -1,30 +0,0 @@
|
|||
# glestest makefile
|
||||
# Global definitions
|
||||
|
||||
CC = gcc
|
||||
|
||||
OBJS = gles_video.o test.o
|
||||
|
||||
BIN = glestest
|
||||
|
||||
# Platform specific definitions
|
||||
|
||||
CFLAGS+=-D_LINUX
|
||||
|
||||
LIBS +=-L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt
|
||||
|
||||
INCLUDES+=-I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
|
||||
|
||||
# Compilation:
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(OBJS) $(LIBS) -o $(BIN)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(BIN)
|
||||
|
|
@ -1,417 +0,0 @@
|
|||
/*
|
||||
|
||||
This file is based on Portable ZX-Spectrum emulator.
|
||||
Copyright (C) 2001-2012 SMT, Dexus, Alone Coder, deathsoft, djdron, scor
|
||||
|
||||
C++ to C code conversion by Pate
|
||||
|
||||
Modified by DPR for gpsp for Raspberry Pi
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "bcm_host.h"
|
||||
#include "GLES/gl.h"
|
||||
#include "EGL/egl.h"
|
||||
#include "EGL/eglext.h"
|
||||
#include "GLES2/gl2.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
static uint32_t frame_width = 0;
|
||||
static uint32_t frame_height = 0;
|
||||
|
||||
|
||||
#define SHOW_ERROR gles_show_error();
|
||||
|
||||
static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y);
|
||||
|
||||
static const char* vertex_shader =
|
||||
"uniform mat4 u_vp_matrix; \n"
|
||||
"attribute vec4 a_position; \n"
|
||||
"attribute vec2 a_texcoord; \n"
|
||||
"varying mediump vec2 v_texcoord; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" v_texcoord = a_texcoord; \n"
|
||||
" gl_Position = u_vp_matrix * a_position; \n"
|
||||
"} \n";
|
||||
|
||||
static const char* fragment_shader =
|
||||
"varying mediump vec2 v_texcoord; \n"
|
||||
"uniform sampler2D u_texture; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_FragColor = texture2D(u_texture, v_texcoord); \n"
|
||||
"} \n";
|
||||
/*
|
||||
static const GLfloat vertices[] =
|
||||
{
|
||||
-0.5f, -0.5f, 0.0f,
|
||||
+0.5f, -0.5f, 0.0f,
|
||||
+0.5f, +0.5f, 0.0f,
|
||||
-0.5f, +0.5f, 0.0f,
|
||||
};
|
||||
*/
|
||||
static const GLfloat vertices[] =
|
||||
{
|
||||
-0.5f, -0.5f, 0.0f,
|
||||
-0.5f, +0.5f, 0.0f,
|
||||
+0.5f, +0.5f, 0.0f,
|
||||
+0.5f, -0.5f, 0.0f,
|
||||
};
|
||||
|
||||
#define TEX_WIDTH 1024
|
||||
#define TEX_HEIGHT 512
|
||||
|
||||
static const GLfloat uvs[8];
|
||||
|
||||
static const GLushort indices[] =
|
||||
{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
};
|
||||
|
||||
static const int kVertexCount = 4;
|
||||
static const int kIndexCount = 6;
|
||||
|
||||
|
||||
void Create_uvs(GLfloat * matrix, GLfloat max_u, GLfloat max_v) {
|
||||
memset(matrix,0,sizeof(GLfloat)*8);
|
||||
matrix[3]=max_v;
|
||||
matrix[4]=max_u;
|
||||
matrix[5]=max_v;
|
||||
matrix[6]=max_u;
|
||||
|
||||
}
|
||||
|
||||
void gles_show_error()
|
||||
{
|
||||
GLenum error = GL_NO_ERROR;
|
||||
error = glGetError();
|
||||
if (GL_NO_ERROR != error)
|
||||
printf("GL Error %x encountered!\n", error);
|
||||
}
|
||||
|
||||
static GLuint CreateShader(GLenum type, const char *shader_src)
|
||||
{
|
||||
GLuint shader = glCreateShader(type);
|
||||
if(!shader)
|
||||
return 0;
|
||||
|
||||
// Load and compile the shader source
|
||||
glShaderSource(shader, 1, &shader_src, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
// Check the compile status
|
||||
GLint compiled = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
|
||||
if(!compiled)
|
||||
{
|
||||
GLint info_len = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
|
||||
if(info_len > 1)
|
||||
{
|
||||
char* info_log = (char *)malloc(sizeof(char) * info_len);
|
||||
glGetShaderInfoLog(shader, info_len, NULL, info_log);
|
||||
// TODO(dspringer): We could really use a logging API.
|
||||
printf("Error compiling shader:\n%s\n", info_log);
|
||||
free(info_log);
|
||||
}
|
||||
glDeleteShader(shader);
|
||||
return 0;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
static GLuint CreateProgram(const char *vertex_shader_src, const char *fragment_shader_src)
|
||||
{
|
||||
GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_src);
|
||||
if(!vertex_shader)
|
||||
return 0;
|
||||
GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_src);
|
||||
if(!fragment_shader)
|
||||
{
|
||||
glDeleteShader(vertex_shader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint program_object = glCreateProgram();
|
||||
if(!program_object)
|
||||
return 0;
|
||||
glAttachShader(program_object, vertex_shader);
|
||||
glAttachShader(program_object, fragment_shader);
|
||||
|
||||
// Link the program
|
||||
glLinkProgram(program_object);
|
||||
|
||||
// Check the link status
|
||||
GLint linked = 0;
|
||||
glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
|
||||
if(!linked)
|
||||
{
|
||||
GLint info_len = 0;
|
||||
glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
|
||||
if(info_len > 1)
|
||||
{
|
||||
char* info_log = (char *)malloc(info_len);
|
||||
glGetProgramInfoLog(program_object, info_len, NULL, info_log);
|
||||
// TODO(dspringer): We could really use a logging API.
|
||||
printf("Error linking program:\n%s\n", info_log);
|
||||
free(info_log);
|
||||
}
|
||||
glDeleteProgram(program_object);
|
||||
return 0;
|
||||
}
|
||||
// Delete these here because they are attached to the program object.
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
return program_object;
|
||||
}
|
||||
|
||||
typedef struct ShaderInfo {
|
||||
GLuint program;
|
||||
GLint a_position;
|
||||
GLint a_texcoord;
|
||||
GLint u_vp_matrix;
|
||||
GLint u_texture;
|
||||
} ShaderInfo;
|
||||
|
||||
static ShaderInfo shader;
|
||||
static ShaderInfo shader_filtering;
|
||||
static GLuint buffers[3];
|
||||
static GLuint textures[2];
|
||||
|
||||
|
||||
static void gles2_create()
|
||||
{
|
||||
memset(&shader, 0, sizeof(ShaderInfo));
|
||||
shader.program = CreateProgram(vertex_shader, fragment_shader);
|
||||
if(shader.program)
|
||||
{
|
||||
shader.a_position = glGetAttribLocation(shader.program, "a_position");
|
||||
shader.a_texcoord = glGetAttribLocation(shader.program, "a_texcoord");
|
||||
shader.u_vp_matrix = glGetUniformLocation(shader.program, "u_vp_matrix");
|
||||
shader.u_texture = glGetUniformLocation(shader.program, "u_texture");
|
||||
}
|
||||
glGenTextures(1, textures);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
|
||||
|
||||
Create_uvs(uvs, (float)frame_width/TEX_WIDTH, (float)frame_height/TEX_HEIGHT);
|
||||
|
||||
glGenBuffers(3, buffers);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 3, vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 2, uvs, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, kIndexCount * sizeof(GL_UNSIGNED_SHORT), indices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DITHER);
|
||||
}
|
||||
|
||||
static uint32_t screen_width = 0;
|
||||
static uint32_t screen_height = 0;
|
||||
|
||||
static EGLDisplay display = NULL;
|
||||
static EGLSurface surface = NULL;
|
||||
static EGLContext context = NULL;
|
||||
static EGL_DISPMANX_WINDOW_T nativewindow;
|
||||
|
||||
static GLfloat proj[4][4];
|
||||
static GLint filter_min;
|
||||
static GLint filter_mag;
|
||||
|
||||
void video_set_filter(uint32_t filter) {
|
||||
if (filter==0) {
|
||||
filter_min = GL_NEAREST;
|
||||
filter_mag = GL_NEAREST;
|
||||
} else {
|
||||
filter_min = GL_LINEAR;
|
||||
filter_mag = GL_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
void video_init(uint32_t _width, uint32_t _height, uint32_t filter)
|
||||
{
|
||||
if ((_width==0)||(_height==0))
|
||||
return;
|
||||
|
||||
frame_width = _width;
|
||||
frame_height = _height;
|
||||
|
||||
//bcm_host_init();
|
||||
|
||||
// get an EGL display connection
|
||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
assert(display != EGL_NO_DISPLAY);
|
||||
|
||||
// initialize the EGL display connection
|
||||
EGLBoolean result = eglInitialize(display, NULL, NULL);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
// get an appropriate EGL frame buffer configuration
|
||||
EGLint num_config;
|
||||
EGLConfig config;
|
||||
static const EGLint attribute_list[] =
|
||||
{
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
result = eglBindAPI(EGL_OPENGL_ES_API);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
// create an EGL rendering context
|
||||
static const EGLint context_attributes[] =
|
||||
{
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
|
||||
assert(context != EGL_NO_CONTEXT);
|
||||
|
||||
// create an EGL window surface
|
||||
int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
|
||||
assert(success >= 0);
|
||||
|
||||
VC_RECT_T dst_rect;
|
||||
dst_rect.x = 0;
|
||||
dst_rect.y = 0;
|
||||
dst_rect.width = screen_width;
|
||||
dst_rect.height = screen_height;
|
||||
|
||||
VC_RECT_T src_rect;
|
||||
src_rect.x = 0;
|
||||
src_rect.y = 0;
|
||||
src_rect.width = screen_width << 16;
|
||||
src_rect.height = screen_height << 16;
|
||||
|
||||
DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
|
||||
DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
|
||||
DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
|
||||
1, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
|
||||
|
||||
nativewindow.element = dispman_element;
|
||||
nativewindow.width = screen_width;
|
||||
nativewindow.height = screen_height;
|
||||
vc_dispmanx_update_submit_sync(dispman_update);
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
|
||||
assert(surface != EGL_NO_SURFACE);
|
||||
|
||||
// connect the context to the surface
|
||||
result = eglMakeCurrent(display, surface, surface, context);
|
||||
assert(EGL_FALSE != result);
|
||||
|
||||
gles2_create();
|
||||
|
||||
int r=(screen_height*10/frame_height);
|
||||
int h = (frame_height*r)/10;
|
||||
int w = (frame_width*r)/10;
|
||||
if (w>screen_width) {
|
||||
r = (screen_width*10/frame_width);
|
||||
h = (frame_height*r)/10;
|
||||
w = (frame_width*r)/10;
|
||||
}
|
||||
glViewport((screen_width-w)/2, (screen_height-h)/2, w, h);
|
||||
SetOrtho(proj, -0.5f, +0.5f, +0.5f, -0.5f, -1.0f, 1.0f, 1.0f ,1.0f );
|
||||
video_set_filter(filter);
|
||||
}
|
||||
|
||||
static void gles2_destroy()
|
||||
{
|
||||
if(!shader.program)
|
||||
return;
|
||||
glDeleteBuffers(3, buffers); SHOW_ERROR
|
||||
glDeleteProgram(shader.program); SHOW_ERROR
|
||||
}
|
||||
|
||||
static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y)
|
||||
{
|
||||
memset(m, 0, 4*4*sizeof(GLfloat));
|
||||
m[0][0] = 2.0f/(right - left)*scale_x;
|
||||
m[1][1] = 2.0f/(top - bottom)*scale_y;
|
||||
m[2][2] = -2.0f/(far - near);
|
||||
m[3][0] = -(right + left)/(right - left);
|
||||
m[3][1] = -(top + bottom)/(top - bottom);
|
||||
m[3][2] = -(far + near)/(far - near);
|
||||
m[3][3] = 1;
|
||||
}
|
||||
#define RGB15(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
|
||||
|
||||
static void gles2_Draw( uint16_t *pixels)
|
||||
{
|
||||
if(!shader.program)
|
||||
return;
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glUseProgram(shader.program);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(shader.u_texture, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_min);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
|
||||
glVertexAttribPointer(shader.a_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
|
||||
glEnableVertexAttribArray(shader.a_position);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
|
||||
glVertexAttribPointer(shader.a_texcoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
|
||||
glEnableVertexAttribArray(shader.a_texcoord);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
|
||||
glUniformMatrix4fv(shader.u_vp_matrix, 1, GL_FALSE, (const GLfloat * )&proj);
|
||||
glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
//glFlush();
|
||||
}
|
||||
|
||||
void video_close()
|
||||
{
|
||||
gles2_destroy();
|
||||
// Release OpenGL resources
|
||||
eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
|
||||
eglDestroySurface( display, surface );
|
||||
eglDestroyContext( display, context );
|
||||
eglTerminate( display );
|
||||
}
|
||||
|
||||
void video_draw(uint16_t *pixels)
|
||||
{
|
||||
gles2_Draw (pixels);
|
||||
eglSwapBuffers(display, surface);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define RGB15(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
|
||||
|
||||
void video_init(uint32_t width,uint32_t height, uint32_t f);
|
||||
void video_close();
|
||||
void video_draw(uint16_t *pixels);
|
||||
|
||||
|
||||
|
||||
void showbitmap( uint32_t wd, uint32_t ht, uint32_t f) {
|
||||
int index;
|
||||
uint16_t j,k;
|
||||
uint8_t r,g,b;
|
||||
uint16_t * bitmap;
|
||||
|
||||
bitmap=malloc(wd*ht*sizeof(uint16_t));
|
||||
|
||||
b=16;
|
||||
index=0;
|
||||
for (j=0;j<ht;j++) {
|
||||
r=(j*31)/(ht-1);
|
||||
for (k=0; k<wd ; k++) {
|
||||
g=(k*31)/(wd-1);
|
||||
bitmap[index++]=RGB15(r,g,b);
|
||||
}
|
||||
}
|
||||
bitmap[0]=0;
|
||||
|
||||
video_init(wd,ht,f);
|
||||
video_draw(bitmap);
|
||||
sleep(5);
|
||||
video_close();
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
showbitmap( 320, 240,0);
|
||||
showbitmap( 320, 240,1);
|
||||
showbitmap( 320, 240,2);
|
||||
showbitmap( 240, 160,0);
|
||||
showbitmap( 400, 272,0);
|
||||
|
||||
return 0;
|
||||
}
|
6
sound.c
6
sound.c
|
@ -25,19 +25,13 @@ u32 global_enable_audio = 1;
|
|||
direct_sound_struct direct_sound_channel[2];
|
||||
gbc_sound_struct gbc_sound_channel[4];
|
||||
|
||||
#ifdef RPI_BUILD
|
||||
u32 sound_frequency = 22050;
|
||||
#else
|
||||
u32 sound_frequency = 44100;
|
||||
#endif
|
||||
|
||||
SDL_mutex *sound_mutex;
|
||||
static SDL_cond *sound_cv;
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
u32 audio_buffer_size_number = 1;
|
||||
#elif defined(POLLUX_BUILD)
|
||||
u32 audio_buffer_size_number = 7;
|
||||
#else
|
||||
u32 audio_buffer_size_number = 8;
|
||||
#endif
|
||||
|
|
2
sound.h
2
sound.h
|
@ -25,7 +25,7 @@
|
|||
#define GBA_XTAL 16777216.0f
|
||||
#define GBA_60HZ_RATE 16853760.0f /* 228*(272+960)*60 */
|
||||
|
||||
#if !defined(PSP_BUILD) && !defined(POLLUX_BUILD)
|
||||
#if !defined(PSP_BUILD)
|
||||
// run GBA at 60Hz (~0.5% faster) to better match host display
|
||||
#define GBC_BASE_RATE GBA_60HZ_RATE
|
||||
#else
|
||||
|
|
295
video.c
295
video.c
|
@ -86,41 +86,8 @@ static void Ge_Finish_Callback(int id, void *arg)
|
|||
#define get_screen_pitch() \
|
||||
screen_pitch \
|
||||
|
||||
#elif defined(POLLUX_BUILD)
|
||||
|
||||
static u16 rot_buffer[240*4];
|
||||
static u32 rot_lines_total = 4;
|
||||
static u32 rot_line_count = 0;
|
||||
#ifdef WIZ_BUILD
|
||||
static char rot_msg_buff[64];
|
||||
#endif
|
||||
|
||||
static u32 screen_offset = 0;
|
||||
static u16 *screen_pixels = NULL;
|
||||
const u32 screen_pitch = 320;
|
||||
|
||||
#define get_screen_pixels() \
|
||||
screen_pixels \
|
||||
|
||||
#define get_screen_pitch() \
|
||||
screen_pitch \
|
||||
|
||||
#elif defined(PND_BUILD) || defined(RPI_BUILD)
|
||||
|
||||
static u16 *screen_pixels = NULL;
|
||||
|
||||
#define get_screen_pixels() \
|
||||
screen_pixels \
|
||||
|
||||
#define get_screen_pitch() \
|
||||
resolution_width \
|
||||
|
||||
#else
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
#include "SDL_gp2x.h"
|
||||
SDL_Surface *hw_screen;
|
||||
#endif
|
||||
SDL_Surface *screen;
|
||||
const u32 video_scale = 1;
|
||||
|
||||
|
@ -3273,28 +3240,6 @@ void update_scanline()
|
|||
if(skip_next_frame)
|
||||
return;
|
||||
|
||||
#ifdef WIZ_BUILD
|
||||
if (screen_scale == unscaled_rot || screen_scale == scaled_aspect_rot)
|
||||
{
|
||||
if (rot_line_count == rot_lines_total)
|
||||
{
|
||||
rot_line_count = 0;
|
||||
if (vcount - rot_lines_total < FONT_HEIGHT && rot_msg_buff[0])
|
||||
{
|
||||
print_string_ext(rot_msg_buff, 0xFFFF, 0x0000, 0, 0,
|
||||
rot_buffer, 240, 0, vcount - rot_lines_total, rot_lines_total);
|
||||
if (vcount >= FONT_HEIGHT)
|
||||
rot_msg_buff[0] = 0;
|
||||
}
|
||||
if (screen_scale == unscaled_rot)
|
||||
do_rotated_blit(gpsp_gp2x_screen, rot_buffer, vcount);
|
||||
else
|
||||
upscale_aspect_row(gpsp_gp2x_screen, rot_buffer, vcount/3);
|
||||
}
|
||||
screen_offset = &rot_buffer[rot_line_count++ * 240];
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the screen is in in forced blank draw pure white.
|
||||
if(dispcnt & 0x80)
|
||||
{
|
||||
|
@ -3358,43 +3303,6 @@ void flip_screen()
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined(POLLUX_BUILD)
|
||||
|
||||
void flip_screen()
|
||||
{
|
||||
if((resolution_width == small_resolution_width) &&
|
||||
(resolution_height == small_resolution_height))
|
||||
{
|
||||
switch(screen_scale)
|
||||
{
|
||||
case unscaled:
|
||||
break;
|
||||
case scaled_aspect:
|
||||
upscale_aspect(gpsp_gp2x_screen, screen_pixels);
|
||||
break;
|
||||
case unscaled_rot:
|
||||
do_rotated_blit(gpsp_gp2x_screen, rot_buffer, 160);
|
||||
rot_line_count = 0;
|
||||
goto no_clean;
|
||||
case scaled_aspect_rot:
|
||||
rot_line_count = 0;
|
||||
goto no_clean;
|
||||
}
|
||||
}
|
||||
warm_cache_op_all(WOP_D_CLEAN);
|
||||
|
||||
no_clean:
|
||||
pollux_video_flip();
|
||||
screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset;
|
||||
}
|
||||
|
||||
#elif defined(PND_BUILD) || defined(RPI_BUILD)
|
||||
|
||||
void flip_screen()
|
||||
{
|
||||
screen_pixels = fb_flip_screen();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define integer_scale_copy_2() \
|
||||
|
@ -3468,43 +3376,7 @@ void flip_screen()
|
|||
}
|
||||
}
|
||||
}
|
||||
#ifdef GP2X_BUILD
|
||||
{
|
||||
if((resolution_width == small_resolution_width) &&
|
||||
(resolution_height == small_resolution_height))
|
||||
{
|
||||
switch (screen_scale)
|
||||
{
|
||||
case unscaled:
|
||||
{
|
||||
SDL_Rect srect = {0, 0, 240, 160};
|
||||
SDL_Rect drect = {40, 40, 240, 160};
|
||||
warm_cache_op_all(WOP_D_CLEAN);
|
||||
SDL_BlitSurface(screen, &srect, hw_screen, &drect);
|
||||
return;
|
||||
}
|
||||
case scaled_aspect:
|
||||
{
|
||||
SDL_Rect drect = {0, 10, 0, 0};
|
||||
warm_cache_op_all(WOP_D_CLEAN);
|
||||
SDL_BlitSurface(screen, NULL, hw_screen, &drect);
|
||||
return;
|
||||
}
|
||||
case scaled_aspect_sw:
|
||||
{
|
||||
upscale_aspect(hw_screen->pixels, get_screen_pixels());
|
||||
return;
|
||||
}
|
||||
case fullscreen:
|
||||
break;
|
||||
}
|
||||
}
|
||||
warm_cache_op_all(WOP_D_CLEAN);
|
||||
SDL_BlitSurface(screen, NULL, hw_screen, NULL);
|
||||
}
|
||||
#else
|
||||
SDL_Flip(screen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3604,31 +3476,13 @@ void init_video()
|
|||
GE_CMD(NOP, 0);
|
||||
}
|
||||
|
||||
#elif defined(WIZ_BUILD) || defined(PND_BUILD) || defined (RPI_BUILD)
|
||||
|
||||
void init_video()
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void init_video()
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE);
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
SDL_GP2X_AllowGfxMemory(NULL, 0);
|
||||
|
||||
hw_screen = SDL_SetVideoMode(320 * video_scale, 240 * video_scale,
|
||||
16, SDL_HWSURFACE);
|
||||
|
||||
screen = SDL_CreateRGBSurface(SDL_HWSURFACE, 240 * video_scale,
|
||||
160 * video_scale, 16, 0xFFFF, 0xFFFF, 0xFFFF, 0);
|
||||
|
||||
warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1);
|
||||
#else
|
||||
screen = SDL_SetVideoMode(240 * video_scale, 160 * video_scale, 16, 0);
|
||||
#endif
|
||||
SDL_ShowCursor(0);
|
||||
}
|
||||
|
||||
|
@ -3739,163 +3593,23 @@ void clear_screen(u16 color)
|
|||
sceGuSync(0, 0); */
|
||||
}
|
||||
|
||||
#elif defined(POLLUX_BUILD)
|
||||
|
||||
void video_resolution_large()
|
||||
{
|
||||
screen_offset = 0;
|
||||
resolution_width = 320;
|
||||
resolution_height = 240;
|
||||
|
||||
fb_use_buffers(1);
|
||||
flip_screen();
|
||||
clear_screen(0);
|
||||
wiz_lcd_set_portrait(0);
|
||||
}
|
||||
|
||||
void video_resolution_small()
|
||||
{
|
||||
fb_use_buffers(4);
|
||||
|
||||
switch (screen_scale)
|
||||
{
|
||||
case unscaled:
|
||||
screen_offset = 320*40 + 40;
|
||||
wiz_lcd_set_portrait(0);
|
||||
break;
|
||||
case scaled_aspect:
|
||||
screen_offset = 320*(80 - 14) + 80;
|
||||
wiz_lcd_set_portrait(0);
|
||||
break;
|
||||
case unscaled_rot:
|
||||
wiz_lcd_set_portrait(1);
|
||||
rot_lines_total = 4;
|
||||
rot_line_count = 0;
|
||||
break;
|
||||
case scaled_aspect_rot:
|
||||
wiz_lcd_set_portrait(1);
|
||||
rot_lines_total = 3;
|
||||
rot_line_count = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
flip_screen();
|
||||
clear_screen(0);
|
||||
|
||||
resolution_width = 240;
|
||||
resolution_height = 160;
|
||||
}
|
||||
|
||||
void set_gba_resolution(video_scale_type scale)
|
||||
{
|
||||
screen_scale = scale;
|
||||
}
|
||||
|
||||
void clear_screen(u16 color)
|
||||
{
|
||||
u32 col = ((u32)color << 16) | color;
|
||||
u32 *p = gpsp_gp2x_screen;
|
||||
int c = 320*240/2;
|
||||
while (c-- > 0)
|
||||
*p++ = col;
|
||||
}
|
||||
|
||||
#elif defined(PND_BUILD) || defined(RPI_BUILD)
|
||||
|
||||
void video_resolution_large()
|
||||
{
|
||||
#if defined (RPI_BUILD)
|
||||
resolution_width = 480;
|
||||
#else
|
||||
resolution_width = 400;
|
||||
#endif
|
||||
resolution_height = 272;
|
||||
|
||||
fb_set_mode(resolution_width, resolution_height, 1, 15, screen_filter, screen_filter2);
|
||||
flip_screen();
|
||||
clear_screen(0);
|
||||
}
|
||||
|
||||
void video_resolution_small()
|
||||
{
|
||||
resolution_width = 240;
|
||||
resolution_height = 160;
|
||||
|
||||
fb_set_mode(resolution_width, resolution_height, 3, screen_scale, screen_filter, screen_filter2);
|
||||
flip_screen();
|
||||
clear_screen(0);
|
||||
}
|
||||
|
||||
void set_gba_resolution(video_scale_type scale)
|
||||
{
|
||||
screen_scale = scale;
|
||||
}
|
||||
|
||||
void clear_screen(u16 color)
|
||||
{
|
||||
u32 col = ((u32)color << 16) | color;
|
||||
u32 *p = (u32 *)get_screen_pixels();
|
||||
int c = resolution_width * resolution_height / 2;
|
||||
while (c-- > 0)
|
||||
*p++ = col;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void video_resolution_large()
|
||||
{
|
||||
current_scale = unscaled;
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
SDL_FreeSurface(screen);
|
||||
SDL_GP2X_AllowGfxMemory(NULL, 0);
|
||||
hw_screen = SDL_SetVideoMode(320, 240, 16, SDL_HWSURFACE);
|
||||
screen = SDL_CreateRGBSurface(SDL_HWSURFACE, 320, 240, 16, 0xFFFF,
|
||||
0xFFFF, 0xFFFF, 0);
|
||||
resolution_width = 320;
|
||||
resolution_height = 240;
|
||||
SDL_ShowCursor(0);
|
||||
|
||||
warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1);
|
||||
#else
|
||||
screen = SDL_SetVideoMode(480, 272, 16, 0);
|
||||
resolution_width = 480;
|
||||
resolution_height = 272;
|
||||
#endif
|
||||
}
|
||||
|
||||
void video_resolution_small()
|
||||
{
|
||||
current_scale = screen_scale;
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
int w, h;
|
||||
SDL_FreeSurface(screen);
|
||||
SDL_GP2X_AllowGfxMemory(NULL, 0);
|
||||
|
||||
w = 320; h = 240;
|
||||
if (screen_scale == scaled_aspect || screen_scale == fullscreen)
|
||||
{
|
||||
w = small_resolution_width * video_scale;
|
||||
h = small_resolution_height * video_scale;
|
||||
}
|
||||
if (screen_scale == scaled_aspect) h += 20;
|
||||
hw_screen = SDL_SetVideoMode(w, h, 16, SDL_HWSURFACE);
|
||||
|
||||
w = small_resolution_width * video_scale;
|
||||
if (screen_scale == scaled_aspect_sw)
|
||||
w = 320;
|
||||
screen = SDL_CreateRGBSurface(SDL_HWSURFACE,
|
||||
w, small_resolution_height * video_scale,
|
||||
16, 0xFFFF, 0xFFFF, 0xFFFF, 0);
|
||||
|
||||
SDL_ShowCursor(0);
|
||||
|
||||
warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1);
|
||||
#else
|
||||
screen = SDL_SetVideoMode(small_resolution_width * video_scale,
|
||||
small_resolution_height * video_scale, 16, 0);
|
||||
#endif
|
||||
resolution_width = small_resolution_width;
|
||||
resolution_height = small_resolution_height;
|
||||
}
|
||||
|
@ -4024,15 +3738,6 @@ void print_string_ext(const char *str, u16 fg_color, u16 bg_color,
|
|||
void print_string(const char *str, u16 fg_color, u16 bg_color,
|
||||
u32 x, u32 y)
|
||||
{
|
||||
#ifdef WIZ_BUILD
|
||||
if ((screen_scale == unscaled_rot || screen_scale == scaled_aspect_rot) &&
|
||||
(resolution_width == small_resolution_width) &&
|
||||
(resolution_height == small_resolution_height))
|
||||
{
|
||||
snprintf(rot_msg_buff, sizeof(rot_msg_buff), "%s", str);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
print_string_ext(str, fg_color, bg_color, x, y, get_screen_pixels(),
|
||||
get_screen_pitch(), 0, 0, FONT_HEIGHT);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue