Get rid of PND_BUILD/RPI_BUILD/POLLUX_BUILD/GIZ_BUILD

This commit is contained in:
twinaphex 2014-07-14 04:50:52 +02:00
parent 862e940b8c
commit 093a70482f
43 changed files with 4 additions and 6797 deletions

View File

@ -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

View File

@ -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 *

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -1,4 +0,0 @@
[info]
name="gpSP Caanoo"
path="/gpsp_caanoo/gpsp_caanoo.gpe"
group="GAMES"

View File

@ -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

View File

@ -1,10 +0,0 @@
#ifdef __cplusplus
extern "C"
{
#endif
int pollux_dpc_set(volatile unsigned short *memregs, const char *str);
#ifdef __cplusplus
}
#endif

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
View File

@ -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 *)(&current_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
View File

@ -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
View File

@ -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
View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -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();
}

View File

@ -1,5 +0,0 @@
int xenv_init(void);
int xenv_update(int *is_down);
void xenv_finish(void);

View File

@ -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;
}

View File

@ -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

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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
View File

@ -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);
}

View File

@ -79,15 +79,7 @@ typedef enum
{
unscaled,
scaled_aspect,
#ifdef POLLUX_BUILD
unscaled_rot,
scaled_aspect_rot,
#elif defined(GP2X_BUILD)
fullscreen,
scaled_aspect_sw,
#else
fullscreen,
#endif
} video_scale_type;
typedef enum