Merge pull request #5 from eadmaster/master

added GBC BIOS palettes + some fixes
This commit is contained in:
Hans-Kristian Arntzen 2013-01-13 23:45:16 -08:00
commit c9bd9586e8
2 changed files with 551 additions and 23 deletions

View File

@ -0,0 +1,506 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* sinamas@users.sourceforge.net *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* 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 version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <cstring>
#include <algorithm>
namespace {
#define TO5BIT(c8) (((c8) * 0x1F * 2 + 0xFF) / (0xFF*2))
#define PACK15_1(rgb24) (TO5BIT((rgb24) >> 16 & 0xFF) << 10 | TO5BIT((rgb24) >> 8 & 0xFF) << 5 | TO5BIT((rgb24) & 0xFF))
#define PACK15_4(c0, c1, c2, c3) \
PACK15_1(c0), PACK15_1(c1), PACK15_1(c2), PACK15_1(c3)
static const unsigned short p005[] = {
PACK15_4(0xFFFFFF, 0x52FF00, 0xFF4200, 0x000000),
PACK15_4(0xFFFFFF, 0x52FF00, 0xFF4200, 0x000000),
PACK15_4(0xFFFFFF, 0x52FF00, 0xFF4200, 0x000000)
};
static const unsigned short p006[] = {
PACK15_4(0xFFFFFF, 0xFF9C00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0xFF9C00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0xFF9C00, 0xFF0000, 0x000000)
};
static const unsigned short p007[] = {
PACK15_4(0xFFFFFF, 0xFFFF00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0xFFFF00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0xFFFF00, 0xFF0000, 0x000000)
};
static const unsigned short p008[] = {
PACK15_4(0xA59CFF, 0xFFFF00, 0x006300, 0x000000),
PACK15_4(0xA59CFF, 0xFFFF00, 0x006300, 0x000000),
PACK15_4(0xA59CFF, 0xFFFF00, 0x006300, 0x000000)
};
static const unsigned short p012[] = {
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000)
};
static const unsigned short p013[] = {
PACK15_4(0x000000, 0x008484, 0xFFDE00, 0xFFFFFF),
PACK15_4(0x000000, 0x008484, 0xFFDE00, 0xFFFFFF),
PACK15_4(0x000000, 0x008484, 0xFFDE00, 0xFFFFFF)
};
static const unsigned short p016[] = {
PACK15_4(0xFFFFFF, 0xA5A5A5, 0x525252, 0x000000),
PACK15_4(0xFFFFFF, 0xA5A5A5, 0x525252, 0x000000),
PACK15_4(0xFFFFFF, 0xA5A5A5, 0x525252, 0x000000)
};
static const unsigned short p017[] = {
PACK15_4(0xFFFFA5, 0xFF9494, 0x9494FF, 0x000000),
PACK15_4(0xFFFFA5, 0xFF9494, 0x9494FF, 0x000000),
PACK15_4(0xFFFFA5, 0xFF9494, 0x9494FF, 0x000000)
};
static const unsigned short p01B[] = {
PACK15_4(0xFFFFFF, 0xFFCE00, 0x9C6300, 0x000000),
PACK15_4(0xFFFFFF, 0xFFCE00, 0x9C6300, 0x000000),
PACK15_4(0xFFFFFF, 0xFFCE00, 0x9C6300, 0x000000)
};
static const unsigned short p100[] = {
PACK15_4(0xFFFFFF, 0xADAD84, 0x42737B, 0x000000),
PACK15_4(0xFFFFFF, 0xFF7300, 0x944200, 0x000000),
PACK15_4(0xFFFFFF, 0xADAD84, 0x42737B, 0x000000)
};
static const unsigned short p10B[] = {
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p10D[] = {
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000)
};
static const unsigned short p110[] = {
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p11C[] = {
PACK15_4(0xFFFFFF, 0x7BFF31, 0x0063C5, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x0063C5, 0x000000)
};
static const unsigned short p20B[] = {
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p20C[] = {
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000),
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000),
PACK15_4(0xFFC542, 0xFFD600, 0x943A00, 0x4A0000)
};
static const unsigned short p300[] = {
PACK15_4(0xFFFFFF, 0xADAD84, 0x42737B, 0x000000),
PACK15_4(0xFFFFFF, 0xFF7300, 0x944200, 0x000000),
PACK15_4(0xFFFFFF, 0xFF7300, 0x944200, 0x000000)
};
static const unsigned short p304[] = {
PACK15_4(0xFFFFFF, 0x7BFF00, 0xB57300, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p305[] = {
PACK15_4(0xFFFFFF, 0x52FF00, 0xFF4200, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p306[] = {
PACK15_4(0xFFFFFF, 0xFF9C00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p308[] = {
PACK15_4(0xA59CFF, 0xFFFF00, 0x006300, 0x000000),
PACK15_4(0xFF6352, 0xD60000, 0x630000, 0x000000),
PACK15_4(0xFF6352, 0xD60000, 0x630000, 0x000000)
};
static const unsigned short p30A[] = {
PACK15_4(0xB5B5FF, 0xFFFF94, 0xAD5A42, 0x000000),
PACK15_4(0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A),
PACK15_4(0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A)
};
static const unsigned short p30C[] = {
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000),
PACK15_4(0xFFC542, 0xFFD600, 0x943A00, 0x4A0000),
PACK15_4(0xFFC542, 0xFFD600, 0x943A00, 0x4A0000)
};
static const unsigned short p30D[] = {
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p30E[] = {
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p30F[] = {
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p312[] = {
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000)
};
static const unsigned short p319[] = {
PACK15_4(0xFFE6C5, 0xCE9C84, 0x846B29, 0x5A3108),
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000)
};
static const unsigned short p31C[] = {
PACK15_4(0xFFFFFF, 0x7BFF31, 0x0063C5, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p405[] = {
PACK15_4(0xFFFFFF, 0x52FF00, 0xFF4200, 0x000000),
PACK15_4(0xFFFFFF, 0x52FF00, 0xFF4200, 0x000000),
PACK15_4(0xFFFFFF, 0x5ABDFF, 0xFF0000, 0x0000FF)
};
static const unsigned short p406[] = {
PACK15_4(0xFFFFFF, 0xFF9C00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0xFF9C00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0x5ABDFF, 0xFF0000, 0x0000FF )
};
static const unsigned short p407[] = {
PACK15_4(0xFFFFFF, 0xFFFF00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0xFFFF00, 0xFF0000, 0x000000),
PACK15_4(0xFFFFFF, 0x5ABDFF, 0xFF0000, 0x0000FF)
};
static const unsigned short p500[] = {
PACK15_4(0xFFFFFF, 0xADAD84, 0x42737B, 0x000000),
PACK15_4(0xFFFFFF, 0xFF7300, 0x944200, 0x000000),
PACK15_4(0xFFFFFF, 0x5ABDFF, 0xFF0000, 0x0000FF)
};
static const unsigned short p501[] = {
PACK15_4(0xFFFF9C, 0x94B5FF, 0x639473, 0x003A3A),
PACK15_4(0xFFC542, 0xFFD600, 0x943A00, 0x4A0000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p502[] = {
PACK15_4(0x6BFF00, 0xFFFFFF, 0xFF524A, 0x000000),
PACK15_4(0xFFFFFF, 0xFFFFFF, 0x63A5FF, 0x0000FF),
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000)
};
static const unsigned short p503[] = {
PACK15_4(0x52DE00, 0xFF8400, 0xFFFF00, 0xFFFFFF),
PACK15_4(0xFFFFFF, 0xFFFFFF, 0x63A5FF, 0x0000FF),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000)
};
static const unsigned short p508[] = {
PACK15_4(0xA59CFF, 0xFFFF00, 0x006300, 0x000000),
PACK15_4(0xFF6352, 0xD60000, 0x630000, 0x000000),
PACK15_4(0x0000FF, 0xFFFFFF, 0xFFFF7B, 0x0084FF)
};
static const unsigned short p509[] = {
PACK15_4(0xFFFFCE, 0x63EFEF, 0x9C8431, 0x5A5A5A),
PACK15_4(0xFFFFFF, 0xFF7300, 0x944200, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p50B[] = {
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFFFF7B, 0x0084FF, 0xFF0000)
};
static const unsigned short p50C[] = {
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000),
PACK15_4(0xFFC542, 0xFFD600, 0x943A00, 0x4A0000),
PACK15_4(0xFFFFFF, 0x5ABDFF, 0xFF0000, 0x0000FF)
};
static const unsigned short p50D[] = {
PACK15_4(0xFFFFFF, 0x8C8CDE, 0x52528C, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000)
};
static const unsigned short p50E[] = {
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p50F[] = {
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000)
};
static const unsigned short p510[] = {
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p511[] = {
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x00FF00, 0x318400, 0x004A00),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p512[] = {
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p514[] = {
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFF00, 0xFF0000, 0x630000, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000)
};
static const unsigned short p515[] = {
PACK15_4(0xFFFFFF, 0xADAD84, 0x42737B, 0x000000),
PACK15_4(0xFFFFFF, 0xFFAD63, 0x843100, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
static const unsigned short p518[] = {
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000)
};
static const unsigned short p51A[] = {
PACK15_4(0xFFFFFF, 0xFFFF00, 0x7B4A00, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000),
PACK15_4(0xFFFFFF, 0x7BFF31, 0x008400, 0x000000)
};
static const unsigned short p51C[] = {
PACK15_4(0xFFFFFF, 0x7BFF31, 0x0063C5, 0x000000),
PACK15_4(0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000),
PACK15_4(0xFFFFFF, 0x63A5FF, 0x0000FF, 0x000000)
};
#undef PACK15_4
#undef PACK15_1
#undef TO5BIT
struct GbcPaletteEntry { const char *title; const unsigned short *p; };
static const GbcPaletteEntry gbcDirPalettes[] = {
{ "GBC - Blue", p518 },
{ "GBC - Brown", p012 },
{ "GBC - Dark Blue", p50D },
{ "GBC - Dark Brown", p319 },
{ "GBC - Dark Green", p31C },
{ "GBC - Grayscale", p016 },
{ "GBC - Green", p005 },
{ "GBC - Inverted", p013 },
{ "GBC - Orange", p007 },
{ "GBC - Pastel Mix", p017 },
{ "GBC - Red", p510 },
{ "GBC - Yellow", p51A },
};
static const GbcPaletteEntry gbcTitlePalettes[] = {
{ "ALLEY WAY", p008 },
{ "ASTEROIDS/MISCMD", p30E },
{ "ATOMIC PUNK", p30F }, // unofficial ("DYNABLASTER" alt.)
{ "BA.TOSHINDEN", p50F },
{ "BALLOON KID", p006 },
{ "BASEBALL", p503 },
{ "BOMBERMAN GB", p31C }, // unofficial ("WARIO BLAST" alt.)
{ "BOY AND BLOB GB1", p512 },
{ "BOY AND BLOB GB2", p512 },
{ "BT2RAGNAROKWORLD", p312 },
{ "DEFENDER/JOUST", p50F },
{ "DMG FOOTBALL", p30E },
{ "DONKEY KONG", p306 },
{ "DONKEYKONGLAND", p50C },
{ "DONKEYKONGLAND 2", p50C },
{ "DONKEYKONGLAND 3", p50C },
{ "DONKEYKONGLAND95", p501 },
{ "DR.MARIO", p20B },
{ "DYNABLASTER", p30F },
{ "F1RACE", p012 },
{ "FOOTBALL INT'L", p502 }, // unofficial ("SOCCER" alt.)
{ "G&W GALLERY", p304 },
{ "GALAGA&GALAXIAN", p013 },
{ "GAME&WATCH", p012 },
{ "GAMEBOY GALLERY", p304 },
{ "GAMEBOY GALLERY2", p304 },
{ "GBWARS", p500 },
{ "GBWARST", p500 }, // unofficial ("GBWARS" alt.)
{ "GOLF", p30E },
{ "Game and Watch 2", p304 },
{ "HOSHINOKA-BI", p508 },
{ "JAMES BOND 007", p11C },
{ "KAERUNOTAMENI", p10D },
{ "KEN GRIFFEY JR", p31C },
{ "KID ICARUS", p30D },
{ "KILLERINSTINCT95", p50D },
{ "KINGOFTHEZOO", p30F },
{ "KIRAKIRA KIDS", p012 },
{ "KIRBY BLOCKBALL", p508 },
{ "KIRBY DREAM LAND", p508 },
{ "KIRBY'S PINBALL", p308 },
{ "KIRBY2", p508 },
{ "LOLO2", p50F },
{ "MAGNETIC SOCCER", p50E },
{ "MANSELL", p012 },
{ "MARIO & YOSHI", p305 },
{ "MARIO'S PICROSS", p012 },
{ "MARIOLAND2", p509 },
{ "MEGA MAN 2", p50F },
{ "MEGAMAN", p50F },
{ "MEGAMAN3", p50F },
{ "METROID2", p514 },
{ "MILLI/CENTI/PEDE", p31C },
{ "MOGURANYA", p300 },
{ "MYSTIC QUEST", p50E },
{ "NETTOU KOF 95", p50F },
{ "NEW CHESSMASTER", p30F },
{ "OTHELLO", p50E },
{ "PAC-IN-TIME", p51C },
{ "PENGUIN WARS", p30F }, // unofficial ("KINGOFTHEZOO" alt.)
{ "PENGUINKUNWARSVS", p30F }, // unofficial ("KINGOFTHEZOO" alt.)
{ "PICROSS 2", p012 },
{ "PINOCCHIO", p20C },
{ "POKEBOM", p30C },
{ "POKEMON BLUE", p10B },
{ "POKEMON GREEN", p11C },
{ "POKEMON RED", p110 },
{ "POKEMON YELLOW", p007 },
{ "QIX", p407 },
{ "RADARMISSION", p100 },
{ "ROCKMAN WORLD", p50F },
{ "ROCKMAN WORLD2", p50F },
{ "ROCKMANWORLD3", p50F },
{ "SEIKEN DENSETSU", p50E },
{ "SOCCER", p502 },
{ "SOLARSTRIKER", p013 },
{ "SPACE INVADERS", p013 },
{ "STAR STACKER", p012 },
{ "STAR WARS", p512 },
{ "STAR WARS-NOA", p512 },
{ "STREET FIGHTER 2", p50F },
{ "SUPER BOMBLISS ", p006 }, // unofficial ("TETRIS BLAST" alt.)
{ "SUPER MARIOLAND", p30A },
{ "SUPER RC PRO-AM", p50F },
{ "SUPERDONKEYKONG", p501 },
{ "SUPERMARIOLAND3", p500 },
{ "TENNIS", p502 },
{ "TETRIS", p007 },
{ "TETRIS ATTACK", p405 },
{ "TETRIS BLAST", p006 },
{ "TETRIS FLASH", p407 },
{ "TETRIS PLUS", p31C },
{ "TETRIS2", p407 },
{ "THE CHESSMASTER", p30F },
{ "TOPRANKINGTENNIS", p502 },
{ "TOPRANKTENNIS", p502 },
{ "TOY STORY", p30E },
//{ "TRIP WORLD", p500 }, // unofficial
{ "VEGAS STAKES", p50E },
{ "WARIO BLAST", p31C },
{ "WARIOLAND2", p515 },
{ "WAVERACE", p50B },
{ "WORLD CUP", p30E },
{ "X", p016 },
{ "YAKUMAN", p012 },
{ "YOSHI'S COOKIE", p406 },
{ "YOSSY NO COOKIE", p406 },
{ "YOSSY NO PANEPON", p405 },
{ "YOSSY NO TAMAGO", p305 },
{ "ZELDA", p511 },
};
static inline std::size_t gbcDirPalettesSize() { return (sizeof gbcDirPalettes) / (sizeof gbcDirPalettes[0]); }
static inline const struct GbcPaletteEntry * gbcDirPalettesEnd() { return gbcDirPalettes + gbcDirPalettesSize(); }
static inline std::size_t gbcTitlePalettesSize() { return (sizeof gbcTitlePalettes) / (sizeof gbcTitlePalettes[0]); }
static inline const struct GbcPaletteEntry * gbcTitlePalettesEnd() { return gbcTitlePalettes + gbcTitlePalettesSize(); }
struct GbcPaletteEntryLess {
bool operator()(const GbcPaletteEntry &lhs, const char *const rhstitle) const {
return std::strcmp(lhs.title, rhstitle) < 0;
}
};
static const unsigned short * findGbcDirPal(const char *const title) {
const GbcPaletteEntry *const r = std::lower_bound(gbcDirPalettes, gbcDirPalettesEnd(), title, GbcPaletteEntryLess());
return r < gbcDirPalettesEnd() && !std::strcmp(r->title, title) ? r->p : 0;
}
static const unsigned short * findGbcTitlePal(const char *const title) {
const GbcPaletteEntry *const r = std::lower_bound(gbcTitlePalettes, gbcTitlePalettesEnd(), title, GbcPaletteEntryLess());
return r < gbcTitlePalettesEnd() && !std::strcmp(r->title, title) ? r->p : 0;
}
static const unsigned short * findGbcPal(const char *const title) {
if (const unsigned short *const pal = findGbcDirPal(title))
return pal;
return findGbcTitlePal(title);
}
static unsigned long gbcToRgb32(const unsigned rgb15) {
const unsigned long r = rgb15 >> 10 & 0x1F;
const unsigned long g = rgb15 >> 5 & 0x1F;
const unsigned long b = rgb15 & 0x1F;
return ((r * 13 + g * 2 + b) >> 1) << 16 | (g * 3 + b) << 9 | (r * 3 + g * 2 + b * 11) >> 1;
}
}

View File

@ -1,5 +1,6 @@
#include "libretro.h"
#include "resamplerinfo.h"
#include "gbcpalettes.h"
#include <gambatte.h>
@ -173,27 +174,34 @@ bool retro_load_game(const struct retro_game_info *info)
return false;
}
bool load_fail = gb.load(info->data, info->size);
if (load_fail)
if (gb.load(info->data, info->size))
return false;
if (gb.isCgb())
return true;
// else it is a GB-mono game -> set a color palette
//std::string internal_game_name = gb.romTitle(); // available only in latest Gambatte
std::string internal_game_name = reinterpret_cast<const char *>((char*)info->data + 0x134);
/* ALTERNATIVE:
char title[0x11] = {0};
memcpy(title, info->data + 0x134, 0x10);
std::string internal_game_name = title;
*/
// ALTERNATIVE2: pass via "info->meta"
//std::string internal_game_name = reinterpret_cast<const char *>(info->data + 0x134); // buggy with some games ("YOSSY NO COOKIE", "YOSSY NO PANEPON, etc.)
char internal_game_name[17] = {0};
strncpy(internal_game_name, (const char *)(info->data)+0x134, 16);
// TODO: check GBC BIOS builtin palettes
/*
for (unsigned palnum = 0; palnum < 3; ++palnum)
// load a GBC BIOS builtin palette
unsigned short* gbc_bios_palette = NULL;
gbc_bios_palette = const_cast<unsigned short*>(findGbcTitlePal(internal_game_name));
if(gbc_bios_palette==0)
{
// no custom palette found, load the default (blue)
gbc_bios_palette = const_cast<unsigned short*>(findGbcDirPal("GBC - Blue"));
}
unsigned rgb32 = 0;
for (unsigned palnum = 0; palnum < 3; ++palnum)
for (unsigned colornum = 0; colornum < 4; ++colornum) {
unsigned rgb32 = ...
rgb32 = gbcToRgb32(gbc_bios_palette[palnum * 4 + colornum]);
gb.setDmgPaletteColor(palnum, colornum, rgb32);
}
*/
const char *system_directory_c = NULL;
environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_directory_c);
@ -204,21 +212,21 @@ bool retro_load_game(const struct retro_game_info *info)
}
std::string system_directory(system_directory_c);
const char *input_rom_path = info->path;
std::string custom_palette_path = system_directory + "/palettes/" + basename(input_rom_path) + ".pal";
std::string custom_palette_path = system_directory + "/palettes/" + basename(info->path) + ".pal";
std::ifstream palette_file(custom_palette_path.c_str()); // try to open the palette file in read-only mode
if (!palette_file.is_open())
{
// try again with the internal game name from the ROM header
custom_palette_path = system_directory + "/palettes/" + internal_game_name + ".pal";
custom_palette_path = system_directory + "/palettes/" + std::string(internal_game_name) + ".pal";
palette_file.open(custom_palette_path.c_str());
}
if (!palette_file.is_open())
if (!palette_file.is_open() && !findGbcTitlePal(internal_game_name))
{
// try again with default.pal
// only if no specific title palette from the GBC BIOS is found
custom_palette_path = system_directory + "/palettes/" + "default.pal";
palette_file.open(custom_palette_path.c_str());
}
@ -230,21 +238,35 @@ bool retro_load_game(const struct retro_game_info *info)
}
// fprintf(stderr, "[Gambatte]: using custom palette %s.\n", custom_palette_path.c_str());
unsigned rgb32 = 0;
unsigned line_count = 0;
for (std::string line; getline(palette_file, line); ) // iterate over file lines
{
line_count++;
if (line[0]=='[') // skip ini sections
continue;
if (line[0]==';') // skip ini comments
continue;
if (line[0]=='\n') // skip empty lines
continue;
if (line.find("=") == std::string::npos)
{
fprintf(stderr, "[Gambatte]: error in %s, line %d (color left as default).\n", custom_palette_path.c_str(), line_count);
continue; // current line does not contain a palette color definition, so go to next line
}
if (startswith(line, "slectedScheme="))
continue;
std::string line_value = line.substr(line.find("=") + 1); // extract the color value string
std::stringstream ss(line_value); // convert the color value to int
//rgb32 = ss >> rgb32 ? rgb32 : 0; // if number conversion fail set it to 0
ss >> rgb32;
if (!ss)
{
//fprintf(stderr, "[Gambatte]: unable to read palette color in %s, line %d (color left as default).\n", custom_palette_path.c_str(), line_count);
fprintf(stderr, "[Gambatte]: unable to read palette color in %s, line %d (color left as default).\n", custom_palette_path.c_str(), line_count);
continue;
}
@ -272,8 +294,8 @@ bool retro_load_game(const struct retro_game_info *info)
gb.setDmgPaletteColor(2, 2, rgb32);
else if (startswith(line, "Sprite%2023="))
gb.setDmgPaletteColor(2, 3, rgb32);
// else
// TODO: print warnings on invalid lines?
else
fprintf(stderr, "[Gambatte]: error in %s, line %d (color left as default).\n", custom_palette_path.c_str(), line_count);
} // endfor