raspberry pi port
This commit is contained in:
parent
6a298de481
commit
ffa573f880
4
common.h
4
common.h
|
@ -270,4 +270,8 @@ typedef u32 fixed8_24;
|
||||||
#include "pandora/pnd.h"
|
#include "pandora/pnd.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RPI_BUILD
|
||||||
|
#include "raspberrypi/rpi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
35
gui.c
35
gui.c
|
@ -552,7 +552,7 @@ typedef enum
|
||||||
NUMBER_SELECTION_OPTION = 0x01,
|
NUMBER_SELECTION_OPTION = 0x01,
|
||||||
STRING_SELECTION_OPTION = 0x02,
|
STRING_SELECTION_OPTION = 0x02,
|
||||||
SUBMENU_OPTION = 0x04,
|
SUBMENU_OPTION = 0x04,
|
||||||
ACTION_OPTION = 0x08
|
ACTION_OPTION = 0x08,
|
||||||
} menu_option_type_enum;
|
} menu_option_type_enum;
|
||||||
|
|
||||||
struct _menu_type
|
struct _menu_type
|
||||||
|
@ -746,6 +746,13 @@ u32 gamepad_config_line_to_button[] =
|
||||||
|
|
||||||
#endif
|
#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[] =
|
static const char *scale_options[] =
|
||||||
{
|
{
|
||||||
#ifdef PSP_BUILD
|
#ifdef PSP_BUILD
|
||||||
|
@ -759,6 +766,8 @@ static const char *scale_options[] =
|
||||||
"unscaled", "2x", "3x", "fullscreen"
|
"unscaled", "2x", "3x", "fullscreen"
|
||||||
#elif defined(GP2X_BUILD)
|
#elif defined(GP2X_BUILD)
|
||||||
"unscaled 3:2", "scaled 3:2", "fullscreen", "scaled 3:2 (software)"
|
"unscaled 3:2", "scaled 3:2", "fullscreen", "scaled 3:2 (software)"
|
||||||
|
#elif defined(RPI_BUILD)
|
||||||
|
"fullscreen"
|
||||||
#else
|
#else
|
||||||
"unscaled 3:2"
|
"unscaled 3:2"
|
||||||
#endif
|
#endif
|
||||||
|
@ -843,10 +852,15 @@ s32 load_game_config_file()
|
||||||
if(file_loaded)
|
if(file_loaded)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#ifdef RPI_BUILD
|
||||||
|
current_frameskip_type = manual_frameskip;
|
||||||
|
frameskip_value = 1;
|
||||||
|
#else
|
||||||
current_frameskip_type = auto_frameskip;
|
current_frameskip_type = auto_frameskip;
|
||||||
frameskip_value = 4;
|
frameskip_value = 4;
|
||||||
#ifdef POLLUX_BUILD
|
#ifdef POLLUX_BUILD
|
||||||
frameskip_value = 1;
|
frameskip_value = 1;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
random_skip = 0;
|
random_skip = 0;
|
||||||
clock_speed = default_clock_speed;
|
clock_speed = default_clock_speed;
|
||||||
|
@ -1213,10 +1227,6 @@ u32 menu(u16 *original_screen)
|
||||||
reg[CHANGED_PC_STATUS] = 1;
|
reg[CHANGED_PC_STATUS] = 1;
|
||||||
menu_update_clock();
|
menu_update_clock();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
choose_menu(current_menu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_restart()
|
void menu_restart()
|
||||||
|
@ -1329,8 +1339,9 @@ u32 menu(u16 *original_screen)
|
||||||
static const char *update_backup_options[] = { "Exit only", "Automatic" };
|
static const char *update_backup_options[] = { "Exit only", "Automatic" };
|
||||||
|
|
||||||
// Marker for help information, don't go past this mark (except \n)------*
|
// Marker for help information, don't go past this mark (except \n)------*
|
||||||
menu_option_type graphics_sound_options[] =
|
menu_option_type graphics_sound_options[] =
|
||||||
{
|
{
|
||||||
|
#ifndef RPI_BUILD
|
||||||
string_selection_option(NULL, "Display scaling", scale_options,
|
string_selection_option(NULL, "Display scaling", scale_options,
|
||||||
(u32 *)(&screen_scale),
|
(u32 *)(&screen_scale),
|
||||||
sizeof(scale_options) / sizeof(scale_options[0]),
|
sizeof(scale_options) / sizeof(scale_options[0]),
|
||||||
|
@ -1344,6 +1355,8 @@ u32 menu(u16 *original_screen)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
"", 2),
|
"", 2),
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef GP2X_BUILD
|
#ifndef GP2X_BUILD
|
||||||
string_selection_option(NULL, "Screen filtering", yes_no_options,
|
string_selection_option(NULL, "Screen filtering", yes_no_options,
|
||||||
(u32 *)(&screen_filter), 2,
|
(u32 *)(&screen_filter), 2,
|
||||||
|
@ -1352,7 +1365,7 @@ u32 menu(u16 *original_screen)
|
||||||
"smooth image, at the cost of being blurry and having less vibrant\n"
|
"smooth image, at the cost of being blurry and having less vibrant\n"
|
||||||
"colors.", 3),
|
"colors.", 3),
|
||||||
#endif
|
#endif
|
||||||
#ifdef PND_BUILD
|
#if defined (PND_BUILD)
|
||||||
string_selection_option(NULL, "Scaling filter", filter2_options,
|
string_selection_option(NULL, "Scaling filter", filter2_options,
|
||||||
(u32 *)(&screen_filter2),
|
(u32 *)(&screen_filter2),
|
||||||
sizeof(filter2_options) / sizeof(filter2_options[0]),
|
sizeof(filter2_options) / sizeof(filter2_options[0]),
|
||||||
|
@ -1572,7 +1585,7 @@ u32 menu(u16 *original_screen)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PC_BUILD
|
#if defined(PC_BUILD) || defined(RPI_BUILD)
|
||||||
|
|
||||||
menu_option_type gamepad_config_options[] =
|
menu_option_type gamepad_config_options[] =
|
||||||
{
|
{
|
||||||
|
@ -1801,6 +1814,10 @@ u32 menu(u16 *original_screen)
|
||||||
|
|
||||||
if(current_option->option_type & SUBMENU_OPTION)
|
if(current_option->option_type & SUBMENU_OPTION)
|
||||||
choose_menu(current_option->sub_menu);
|
choose_menu(current_option->sub_menu);
|
||||||
|
|
||||||
|
if(current_menu == &main_menu)
|
||||||
|
choose_menu(&main_menu);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
126
input.c
126
input.c
|
@ -555,8 +555,49 @@ void init_input()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(RPI_BUILD)
|
||||||
|
|
||||||
#ifdef PC_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)
|
u32 key_map(SDLKey key_sym)
|
||||||
{
|
{
|
||||||
|
@ -596,6 +637,8 @@ u32 key_map(SDLKey key_sym)
|
||||||
return BUTTON_NONE;
|
return BUTTON_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(PC_BUILD) || defined(RPI_BUILD)
|
||||||
|
|
||||||
u32 joy_map(u32 button)
|
u32 joy_map(u32 button)
|
||||||
{
|
{
|
||||||
|
@ -607,16 +650,16 @@ u32 joy_map(u32 button)
|
||||||
case 5:
|
case 5:
|
||||||
return BUTTON_R;
|
return BUTTON_R;
|
||||||
|
|
||||||
case 9:
|
case 2:
|
||||||
return BUTTON_START;
|
return BUTTON_START;
|
||||||
|
|
||||||
case 8:
|
case 3:
|
||||||
return BUTTON_SELECT;
|
return BUTTON_SELECT;
|
||||||
|
|
||||||
case 0:
|
case 1:
|
||||||
return BUTTON_B;
|
return BUTTON_B;
|
||||||
|
|
||||||
case 1:
|
case 0:
|
||||||
return BUTTON_A;
|
return BUTTON_A;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -632,7 +675,7 @@ gui_action_type get_gui_input()
|
||||||
delay_us(30000);
|
delay_us(30000);
|
||||||
|
|
||||||
while(SDL_PollEvent(&event))
|
while(SDL_PollEvent(&event))
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event.type)
|
||||||
{
|
{
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
|
@ -669,15 +712,49 @@ gui_action_type get_gui_input()
|
||||||
case SDLK_BACKSPACE:
|
case SDLK_BACKSPACE:
|
||||||
gui_action = CURSOR_BACK;
|
gui_action = CURSOR_BACK;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
default:
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
return gui_action;
|
return gui_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,8 +775,11 @@ u32 update_input()
|
||||||
{
|
{
|
||||||
quit();
|
quit();
|
||||||
}
|
}
|
||||||
|
#ifdef PC_BUILD
|
||||||
if(event.key.keysym.sym == SDLK_BACKSPACE)
|
if(event.key.keysym.sym == SDLK_BACKSPACE)
|
||||||
|
#else
|
||||||
|
if(event.key.keysym.sym == SDLK_F10)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
u16 *screen_copy = copy_screen();
|
u16 *screen_copy = copy_screen();
|
||||||
u32 ret_val = menu(screen_copy);
|
u32 ret_val = menu(screen_copy);
|
||||||
|
@ -708,7 +788,7 @@ u32 update_input()
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#ifdef PC_BUILD
|
||||||
if(event.key.keysym.sym == SDLK_F1)
|
if(event.key.keysym.sym == SDLK_F1)
|
||||||
{
|
{
|
||||||
debug_on();
|
debug_on();
|
||||||
|
@ -741,7 +821,7 @@ u32 update_input()
|
||||||
dump_translation_cache();
|
dump_translation_cache();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
if(event.key.keysym.sym == SDLK_F5)
|
if(event.key.keysym.sym == SDLK_F5)
|
||||||
{
|
{
|
||||||
char current_savestate_filename[512];
|
char current_savestate_filename[512];
|
||||||
|
@ -795,6 +875,22 @@ u32 update_input()
|
||||||
key &= ~(joy_map(event.jbutton.button));
|
key &= ~(joy_map(event.jbutton.button));
|
||||||
break;
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
main.c
10
main.c
|
@ -38,8 +38,14 @@ debug_state current_debug_state = RUN;
|
||||||
|
|
||||||
//u32 breakpoint_value = 0;
|
//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;
|
frameskip_type current_frameskip_type = auto_frameskip;
|
||||||
u32 global_cycles_per_instruction = 1;
|
u32 global_cycles_per_instruction = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 random_skip = 0;
|
u32 random_skip = 0;
|
||||||
u32 fps_debug = 0;
|
u32 fps_debug = 0;
|
||||||
|
|
||||||
|
@ -821,7 +827,7 @@ void synchronize()
|
||||||
}
|
}
|
||||||
else if (synchronize_flag)
|
else if (synchronize_flag)
|
||||||
{
|
{
|
||||||
#if defined(PND_BUILD)
|
#if defined(PND_BUILD) || defined(RPI_BUILD)
|
||||||
fb_wait_vsync();
|
fb_wait_vsync();
|
||||||
#elif !defined(GP2X_BUILD) // sleeping on GP2X is a bad idea
|
#elif !defined(GP2X_BUILD) // sleeping on GP2X is a bad idea
|
||||||
delay_us((u64)virtual_frame_count * 50000 / 3 - new_ticks + 2);
|
delay_us((u64)virtual_frame_count * 50000 / 3 - new_ticks + 2);
|
||||||
|
@ -867,7 +873,7 @@ void synchronize()
|
||||||
|
|
||||||
interval_skipped_frames += skip_next_frame;
|
interval_skipped_frames += skip_next_frame;
|
||||||
|
|
||||||
#if !defined(GP2X_BUILD) && !defined(PND_BUILD)
|
#if !defined(GP2X_BUILD) && !defined(PND_BUILD) && !defined(RPI_BUILD)
|
||||||
char char_buffer[64];
|
char char_buffer[64];
|
||||||
sprintf(char_buffer, "gpSP: %2d (%2d) fps", fps, frames_drawn);
|
sprintf(char_buffer, "gpSP: %2d (%2d) fps", fps, frames_drawn);
|
||||||
SDL_WM_SetCaption(char_buffer, "gpSP");
|
SDL_WM_SetCaption(char_buffer, "gpSP");
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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)
|
|
@ -0,0 +1,393 @@
|
||||||
|
#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);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
void video_init(uint32_t width,uint32_t height,uint32_t filter);
|
||||||
|
void video_close();
|
||||||
|
void video_draw(uint16_t *pixels);
|
|
@ -0,0 +1,33 @@
|
||||||
|
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
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* 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
|
|
@ -0,0 +1,9 @@
|
||||||
|
void gpsp_plat_init(void);
|
||||||
|
void gpsp_plat_quit(void);
|
||||||
|
|
||||||
|
#define PLAT_BUTTON_COUNT 17
|
||||||
|
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);
|
|
@ -0,0 +1,30 @@
|
||||||
|
# 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)
|
||||||
|
|
|
@ -0,0 +1,383 @@
|
||||||
|
#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,
|
||||||
|
};
|
||||||
|
|
||||||
|
#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_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,
|
||||||
|
0, &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;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
if (filter==0) {
|
||||||
|
filter_min = GL_NEAREST;
|
||||||
|
filter_mag = GL_NEAREST;
|
||||||
|
} else if (filter==1) {
|
||||||
|
filter_min = GL_LINEAR_MIPMAP_LINEAR;
|
||||||
|
filter_mag = GL_LINEAR;
|
||||||
|
} else if (filter==2) {
|
||||||
|
filter_min = GL_LINEAR_MIPMAP_NEAREST;
|
||||||
|
filter_mag = GL_LINEAR;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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_MIN_FILTER, filter_min);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
|
||||||
|
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);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#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;
|
||||||
|
}
|
4
sound.c
4
sound.c
|
@ -25,7 +25,11 @@ u32 global_enable_audio = 1;
|
||||||
direct_sound_struct direct_sound_channel[2];
|
direct_sound_struct direct_sound_channel[2];
|
||||||
gbc_sound_struct gbc_sound_channel[4];
|
gbc_sound_struct gbc_sound_channel[4];
|
||||||
|
|
||||||
|
#ifdef RPI_BUILD
|
||||||
|
u32 sound_frequency = 22050;
|
||||||
|
#else
|
||||||
u32 sound_frequency = 44100;
|
u32 sound_frequency = 44100;
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_mutex *sound_mutex;
|
SDL_mutex *sound_mutex;
|
||||||
static SDL_cond *sound_cv;
|
static SDL_cond *sound_cv;
|
||||||
|
|
16
video.c
16
video.c
|
@ -105,7 +105,7 @@ const u32 screen_pitch = 320;
|
||||||
#define get_screen_pitch() \
|
#define get_screen_pitch() \
|
||||||
screen_pitch \
|
screen_pitch \
|
||||||
|
|
||||||
#elif defined(PND_BUILD)
|
#elif defined(PND_BUILD) || defined(RPI_BUILD)
|
||||||
|
|
||||||
static u16 *screen_pixels = NULL;
|
static u16 *screen_pixels = NULL;
|
||||||
|
|
||||||
|
@ -3388,7 +3388,7 @@ no_clean:
|
||||||
screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset;
|
screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(PND_BUILD)
|
#elif defined(PND_BUILD) || defined(RPI_BUILD)
|
||||||
|
|
||||||
void flip_screen()
|
void flip_screen()
|
||||||
{
|
{
|
||||||
|
@ -3604,7 +3604,7 @@ void init_video()
|
||||||
GE_CMD(NOP, 0);
|
GE_CMD(NOP, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(POLLUX_BUILD) || defined(PND_BUILD)
|
#elif defined(WIZ_BUILD) || defined(PND_BUILD) || defined (RPI_BUILD)
|
||||||
|
|
||||||
void init_video()
|
void init_video()
|
||||||
{
|
{
|
||||||
|
@ -3800,14 +3800,18 @@ void clear_screen(u16 color)
|
||||||
*p++ = col;
|
*p++ = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(PND_BUILD)
|
#elif defined(PND_BUILD) || defined(RPI_BUILD)
|
||||||
|
|
||||||
void video_resolution_large()
|
void video_resolution_large()
|
||||||
{
|
{
|
||||||
|
#if defined (RPI_BUILD)
|
||||||
|
resolution_width = 480;
|
||||||
|
#else
|
||||||
resolution_width = 400;
|
resolution_width = 400;
|
||||||
|
#endif
|
||||||
resolution_height = 272;
|
resolution_height = 272;
|
||||||
|
|
||||||
fb_set_mode(400, 272, 1, 15, screen_filter, screen_filter2);
|
fb_set_mode(resolution_width, resolution_height, 1, 15, screen_filter, screen_filter2);
|
||||||
flip_screen();
|
flip_screen();
|
||||||
clear_screen(0);
|
clear_screen(0);
|
||||||
}
|
}
|
||||||
|
@ -3817,7 +3821,7 @@ void video_resolution_small()
|
||||||
resolution_width = 240;
|
resolution_width = 240;
|
||||||
resolution_height = 160;
|
resolution_height = 160;
|
||||||
|
|
||||||
fb_set_mode(240, 160, 3, screen_scale, screen_filter, screen_filter2);
|
fb_set_mode(resolution_width, resolution_height, 3, screen_scale, screen_filter, screen_filter2);
|
||||||
flip_screen();
|
flip_screen();
|
||||||
clear_screen(0);
|
clear_screen(0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue