Skip to content
This repository has been archived by the owner on Jan 27, 2019. It is now read-only.

Commit

Permalink
SDL: Add support for loading PNG images
Browse files Browse the repository at this point in the history
  • Loading branch information
bgK committed Sep 29, 2013
1 parent fd11e3a commit 1ba81a4
Show file tree
Hide file tree
Showing 16 changed files with 124 additions and 23 deletions.
11 changes: 7 additions & 4 deletions CMakeLists.txt
Expand Up @@ -21,6 +21,7 @@ ENDIF( NOT VERSION )

# Look for some dependencies using builtin CMake scripts
FIND_PACKAGE ( ZLIB REQUIRED )
FIND_PACKAGE ( PNG REQUIRED )
FIND_PACKAGE ( SDL2 REQUIRED )
FIND_PACKAGE ( SDL2TTF REQUIRED )
FIND_PACKAGE ( LibArchive REQUIRED )
Expand Down Expand Up @@ -99,6 +100,7 @@ SET(SRC_SDL
INCLUDE_DIRECTORIES(
${LibArchive_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
${PNG_INCLUDE_DIRS}
${SDL2_INCLUDE_DIR}
${SDL2TTF_INCLUDE_DIR}
${Glib_INCLUDE_DIRS}
Expand All @@ -122,6 +124,7 @@ TARGET_LINK_LIBRARIES (
vba
vbacore
${LibArchive_LIBRARIES}
${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
${SDL2_LIBRARY}
${SDL2TTF_LIBRARY}
Expand All @@ -130,7 +133,7 @@ TARGET_LINK_LIBRARIES (

# Installation
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vba DESTINATION bin)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/game-db.xml DESTINATION ${DATA_INSTALL_DIR})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/game-db.xsd DESTINATION ${DATA_INSTALL_DIR})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/DroidSans-Bold.ttf DESTINATION ${DATA_INSTALL_DIR})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/DroidSans-Bold.txt DESTINATION ${DATA_INSTALL_DIR})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/db/game-db.xml DESTINATION ${DATA_INSTALL_DIR}/db)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/db/game-db.xsd DESTINATION ${DATA_INSTALL_DIR}/db)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/fonts/DroidSans-Bold.ttf DESTINATION ${DATA_INSTALL_DIR}/fonts)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/fonts/DroidSans-Bold.txt DESTINATION ${DATA_INSTALL_DIR}/fonts)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
32 changes: 31 additions & 1 deletion src/common/GameDB.c
Expand Up @@ -26,6 +26,8 @@ typedef struct {

gboolean isInGameTag;
gboolean isInTitleTag;
gboolean isInRegionTag;
gboolean isInPublisherTag;
gboolean isInCodeTag;
gboolean foundCode;
gboolean gameLoaded;
Expand Down Expand Up @@ -72,6 +74,14 @@ static void on_start_element(GMarkupParseContext *context,
{
db->isInCodeTag = TRUE;
}
else if (g_strcmp0(element_name, "region") == 0)
{
db->isInRegionTag = TRUE;
}
else if (g_strcmp0(element_name, "publisher") == 0)
{
db->isInPublisherTag = TRUE;
}
else if (g_strcmp0(element_name, "sram") == 0)
{
db->game->hasSRAM = TRUE;
Expand Down Expand Up @@ -123,6 +133,14 @@ static void on_end_element(GMarkupParseContext *context,
{
db->isInCodeTag = FALSE;
}
else if (g_strcmp0(element_name, "region") == 0)
{
db->isInRegionTag = FALSE;
}
else if (g_strcmp0(element_name, "publisher") == 0)
{
db->isInPublisherTag = FALSE;
}
}

static void on_text(GMarkupParseContext *context,
Expand All @@ -142,6 +160,16 @@ static void on_text(GMarkupParseContext *context,
g_free(db->game->title);
db->game->title = g_strdup(text);
}
else if (db->isInGameTag && db->isInRegionTag)
{
g_free(db->game->region);
db->game->region = g_strdup(text);
}
else if (db->isInGameTag && db->isInPublisherTag)
{
g_free(db->game->publisher);
db->game->publisher = g_strdup(text);
}
else if (db->isInGameTag && db->isInCodeTag)
{
if (g_strcmp0(text, db->lookupCode) == 0) {
Expand All @@ -157,7 +185,7 @@ GameInfos *game_db_lookup_code(const gchar *code, GError **err)
{
g_return_val_if_fail(err == NULL || *err == NULL, NULL);

gchar *dbFilePath = data_get_file_path("game-db.xml");
gchar *dbFilePath = data_get_file_path("db", "game-db.xml");
gchar *xmlData = NULL;
gsize length = 0;

Expand All @@ -175,6 +203,8 @@ GameInfos *game_db_lookup_code(const gchar *code, GError **err)
db->isInGameTag = FALSE;
db->isInTitleTag = FALSE;
db->isInCodeTag = FALSE;
db->isInRegionTag = FALSE;
db->isInPublisherTag = FALSE;

GMarkupParser parser;
parser.start_element = &on_start_element;
Expand Down
4 changes: 4 additions & 0 deletions src/common/GameInfos.c
Expand Up @@ -30,6 +30,8 @@ GameInfos *game_infos_new() {
game->flashSize = 0x10000;
game->title = NULL;
game->code = NULL;
game->region = NULL;
game->publisher = NULL;

return game;
}
Expand All @@ -41,5 +43,7 @@ void game_infos_free(GameInfos *game)

g_free(game->code);
g_free(game->title);
g_free(game->region);
g_free(game->publisher);
g_free(game);
}
2 changes: 2 additions & 0 deletions src/common/GameInfos.h
Expand Up @@ -35,6 +35,8 @@ typedef struct
int flashSize;

gchar *title;
gchar *region;
gchar *publisher;
gchar *code;
} GameInfos;

Expand Down
11 changes: 3 additions & 8 deletions src/common/Util.c
Expand Up @@ -18,19 +18,14 @@

#include "Util.h"

gchar *data_get_file_path(const gchar *filename) {
gchar *data_get_file_path(const gchar *folder, const gchar *filename) {
// Use the data file from the source folder if it exists
// to make vbam runnable without installation
gchar *dataFilePath = g_build_filename("data", filename, NULL);
gchar *dataFilePath = g_build_filename("data", folder, filename, NULL);
if (!g_file_test(dataFilePath, G_FILE_TEST_EXISTS))
{
g_free(dataFilePath);
dataFilePath = g_build_filename("data", "sdl", filename, NULL);
}
if (!g_file_test(dataFilePath, G_FILE_TEST_EXISTS))
{
g_free(dataFilePath);
dataFilePath = g_build_filename(PKGDATADIR, filename, NULL);
dataFilePath = g_build_filename(PKGDATADIR, folder, filename, NULL);
}

return dataFilePath;
Expand Down
2 changes: 1 addition & 1 deletion src/common/Util.h
Expand Up @@ -35,7 +35,7 @@ extern "C" {
* @param filename Name of the file to find
* @return newly allocated string containint the path to the file
*/
gchar *data_get_file_path(const gchar *filename);
gchar *data_get_file_path(const gchar *folder, const gchar *filename);

// save game
typedef struct {
Expand Down
16 changes: 16 additions & 0 deletions src/gba/Cartridge.c
Expand Up @@ -69,6 +69,22 @@ const gchar *cartridge_get_game_title() {
return game->title;
}

const gchar *cartridge_get_game_region() {
if (!cartridge_is_present()) {
return NULL;
}

return game->region;
}

const gchar *cartridge_get_game_publisher() {
if (!cartridge_is_present()) {
return NULL;
}

return game->publisher;
}

gboolean cartridge_is_present() {
return game != NULL;
}
Expand Down
2 changes: 2 additions & 0 deletions src/gba/Cartridge.h
Expand Up @@ -34,6 +34,8 @@ gboolean cartridge_load_rom(const gchar *filename, GError **err);
void cartridge_unload();
void cartridge_get_game_name(u8 *romname);
const gchar *cartridge_get_game_title();
const gchar *cartridge_get_game_region();
const gchar *cartridge_get_game_publisher();
gboolean cartridge_is_present();

gboolean cartridge_read_battery(GError **err);
Expand Down
42 changes: 41 additions & 1 deletion src/sdl/DisplaySDL.cpp
Expand Up @@ -23,6 +23,7 @@

#include <SDL.h>
#include <SDL_ttf.h>
#include <png.h>

static const int screenWidth = 240;
static const int screenHeigth = 160;
Expand Down Expand Up @@ -239,7 +240,6 @@ Renderable *display_sdl_renderable_create(DisplayDriver *driver, gpointer entity
renderable->entity = entity;
renderable->driver = driver;
renderable->renderer = data->renderer;
renderable->window = data->window;
renderable->render = NULL;

data->renderables = g_slist_append(data->renderables, renderable);
Expand All @@ -257,3 +257,43 @@ void display_sdl_renderable_free(Renderable *renderable) {

g_free(renderable);
}

SDL_Texture *display_sdl_load_png(DisplayDriver *driver, const gchar *filename, GError **err) {
g_return_val_if_fail(err == NULL || *err == NULL, NULL);
g_assert(driver != NULL);
DriverData *data = (DriverData *) driver->driverData;

png_image image;
memset(&image, 0, sizeof(image));
image.version = PNG_IMAGE_VERSION;

if (!png_image_begin_read_from_file(&image, filename)) {
g_set_error(err, DISPLAY_ERROR, G_DISPLAY_ERROR_FAILED,
"Failed to load png: %s", image.message);
return NULL;
}

png_bytep buffer = (png_bytep) g_malloc(PNG_IMAGE_SIZE(image));
image.format = PNG_FORMAT_RGBA;

if (!png_image_finish_read(&image, NULL, buffer, 0, NULL)) {
g_free(buffer);
g_set_error(err, DISPLAY_ERROR, G_DISPLAY_ERROR_FAILED,
"Failed to load png: %s", image.message);
return NULL;
}

SDL_Texture *texture = SDL_CreateTexture(data->renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, image.width, image.height);
if (texture == NULL) {
g_free(buffer);
g_set_error(err, DISPLAY_ERROR, G_DISPLAY_ERROR_FAILED,
"Failed create texture : %s", SDL_GetError());
return NULL;
}

SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_UpdateTexture(texture, NULL, buffer, image.width * sizeof(guint32));

g_free(buffer);
return texture;
}
15 changes: 12 additions & 3 deletions src/sdl/DisplaySDL.h
Expand Up @@ -88,9 +88,6 @@ struct Renderable {
/** Display driver to be used for rendering */
DisplayDriver *driver;

/** Window to draw on */
SDL_Window *window;

/** Renderer to use for rendering */
SDL_Renderer *renderer;
};
Expand All @@ -114,6 +111,18 @@ Renderable *display_sdl_renderable_create(DisplayDriver *driver, gpointer entity
*/
void display_sdl_renderable_free(Renderable *renderable);

/**
* Loads a given PNG file pointed to by filename into an SDL_Texture.
*
* Call SDL_DestroyTexture on the result to release.
*
* @param driver The driver the texture belongs to
* @param filename Filename of the PNG image
* @param err return location for a GError, or NULL
* @return a pointer to the texture on success, NULL on failure.
*/
SDL_Texture *display_sdl_load_png(DisplayDriver *driver, const gchar *filename, GError **err);

/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion src/sdl/GameScreen.c
Expand Up @@ -40,7 +40,7 @@ void gamescreen_render(gpointer entity) {

// Do letterboxing to preserve aspect ratio regardless of the window size
int windowWidth, windowHeight;
SDL_GetWindowSize(screen->renderable->window, &windowWidth, &windowHeight);
SDL_GetRendererOutputSize(screen->renderable->renderer, &windowWidth, &windowHeight);

double scale = MIN(windowHeight / (double)screenHeigth, windowWidth / (double)screenWidth);
SDL_Rect screenRect;
Expand Down
8 changes: 4 additions & 4 deletions src/sdl/OSD.c
Expand Up @@ -41,8 +41,8 @@ static gboolean text_update_texture(TextOSD *text, GError **err) {

SDL_DestroyTexture(text->texture);

gchar *fontFile = data_get_file_path("DroidSans-Bold.ttf");
TTF_Font *font = TTF_OpenFont(fontFile, 10);
gchar *fontFile = data_get_file_path("fonts", "DroidSans-Bold.ttf");
TTF_Font *font = TTF_OpenFont(fontFile, text->size);
g_free(fontFile);

if (font == NULL) {
Expand All @@ -61,7 +61,7 @@ static gboolean text_update_texture(TextOSD *text, GError **err) {
text->texture = SDL_CreateTextureFromSurface(text->renderable->renderer, surface);
if (text->texture == NULL) {
g_set_error(err, DISPLAY_ERROR, G_DISPLAY_ERROR_FAILED,
"Failed create texture : %s", TTF_GetError());
"Failed create texture : %s", SDL_GetError());
return FALSE;
}

Expand All @@ -86,7 +86,7 @@ static void text_osd_render(gpointer entity) {
SDL_QueryTexture(text->texture, NULL, NULL, &textWidth, &textHeight);

int windowWidth, windowHeight;
SDL_GetWindowSize(text->renderable->window, &windowWidth, &windowHeight);
SDL_GetRendererOutputSize(text->renderable->renderer, &windowWidth, &windowHeight);

SDL_Rect screenRect;
screenRect.w = textWidth;
Expand Down

0 comments on commit 1ba81a4

Please sign in to comment.