Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wonderswan map format #75

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
wonderswan map format
loading and saving the wonderswan/wonderswan color map
  • Loading branch information
joffb committed Oct 12, 2022
commit 38461ba92cdaf8529ef0e28844da559f32d20dfc
64 changes: 48 additions & 16 deletions src/tilemap-format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ static const int tileset_sizes[NUM_FORMATS] = {
0x40, // PC_TOWN_MAP - High two bits are reserved for X/Y flip
0x100, // SW_TOWN_MAP - 8-bit tile IDs (but $00 is reserved for the end marker)
0xFF, // POKEGEAR_CARD - $FF is reserved for the end marker
0x200, // WONDERSWAN - 9 bit tile IDs
0x400, // WONDERSWAN_COLOR - 9 bit tile IDs + bank bit
};

int format_tileset_size(Tilemap_Format fmt) {
Expand All @@ -44,6 +46,8 @@ int format_palettes_size(Tilemap_Format fmt) {
case Tilemap_Format::NDS_4BPP:
case Tilemap_Format::GENESIS:
case Tilemap_Format::TG16:
case Tilemap_Format::WONDERSWAN:
case Tilemap_Format::WONDERSWAN_COLOR:
return 16;
case Tilemap_Format::SGB_BORDER:
return 4;
Expand All @@ -69,6 +73,8 @@ int format_palette_size(Tilemap_Format fmt) {
case Tilemap_Format::NDS_4BPP:
case Tilemap_Format::SNES_ATTRS:
case Tilemap_Format::TG16:
case Tilemap_Format::WONDERSWAN:
case Tilemap_Format::WONDERSWAN_COLOR:
return 16;
case Tilemap_Format::GBC_ATTRS:
case Tilemap_Format::GBC_ATTRMAP:
Expand Down Expand Up @@ -96,6 +102,8 @@ int format_color_depth(Tilemap_Format fmt) {
case Tilemap_Format::SNES_ATTRS:
case Tilemap_Format::GENESIS:
case Tilemap_Format::TG16:
case Tilemap_Format::WONDERSWAN:
case Tilemap_Format::WONDERSWAN_COLOR:
return 4;
case Tilemap_Format::GBC_ATTRS:
case Tilemap_Format::GBC_ATTRMAP:
Expand All @@ -112,22 +120,24 @@ int format_color_depth(Tilemap_Format fmt) {
}

static const char *format_names[NUM_FORMATS] = {
"Plain tiles", // PLAIN
"GBC tiles + attributes", // GBC_ATTRS
"GBC tilemap + attrmap", // GBC_ATTRMAP
"GBA tiles + 4bpp palettes", // GBA_4BPP
"GBA tiles + 8bpp palette", // GBA_8BPP
"NDS tiles + 4bpp palettes", // NDS_4BPP
"NDS tiles + 8bpp palette", // NDS_8BPP
"SGB border", // SGB_BORDER
"SNES tiles + attributes", // SNES_ATTRS
"Genesis tiles + attributes", // GENESIS
"TG16 tiles + palettes", // TG16
"RBY Town Map", // RBY_TOWN_MAP
"GSC Town Map", // GSC_TOWN_MAP
"PC Town Map", // PC_TOWN_MAP
"SW Town Map", // SW_TOWN_MAP
"Pok\xc3\xa9gear card", // POKEGEAR_CARD
"Plain tiles", // PLAIN
"GBC tiles + attributes", // GBC_ATTRS
"GBC tilemap + attrmap", // GBC_ATTRMAP
"GBA tiles + 4bpp palettes", // GBA_4BPP
"GBA tiles + 8bpp palette", // GBA_8BPP
"NDS tiles + 4bpp palettes", // NDS_4BPP
"NDS tiles + 8bpp palette", // NDS_8BPP
"SGB border", // SGB_BORDER
"SNES tiles + attributes", // SNES_ATTRS
"Genesis tiles + attributes", // GENESIS
"TG16 tiles + palettes", // TG16
"RBY Town Map", // RBY_TOWN_MAP
"GSC Town Map", // GSC_TOWN_MAP
"PC Town Map", // PC_TOWN_MAP
"SW Town Map", // SW_TOWN_MAP
"Pok\xc3\xa9gear card", // POKEGEAR_CARD
"Wonderswan tiles", // WONDERSWAN
"Wonderswan Color tiles", // WONDERSWAN_COLOR
};

const char *format_name(Tilemap_Format fmt) {
Expand Down Expand Up @@ -159,6 +169,8 @@ static const char *format_extensions[NUM_FORMATS] = {
".bin", // PC_TOWN_MAP - e.g. polishedcrystal/gfx/town_map/*.bin
".tilemap.rle", // SW_TOWN_MAP - e.g. pokegold-spaceworld/gfx/trainer_gear/town_map.tilemap.rle
".tilemap.rle", // POKEGEAR_CARD - e.g. pokecrystal/gfx/pokegear/*.tilemap.rle
".bin", // WONDERSWAN
".bin", // WONDERSWAN COLOR
};

const char *format_extension(Tilemap_Format fmt) {
Expand All @@ -181,6 +193,8 @@ int format_bytes_per_tile(Tilemap_Format fmt) {
case Tilemap_Format::SNES_ATTRS:
case Tilemap_Format::GENESIS:
case Tilemap_Format::TG16:
case Tilemap_Format::WONDERSWAN:
case Tilemap_Format::WONDERSWAN_COLOR:
return 2;
case Tilemap_Format::RBY_TOWN_MAP:
case Tilemap_Format::SW_TOWN_MAP:
Expand Down Expand Up @@ -393,6 +407,24 @@ std::vector<uchar> make_tilemap_bytes(const std::vector<Tile_Tessera *> &tiles,
bytes.push_back(r);
}
}
else if (fmt == Tilemap_Format::WONDERSWAN || fmt == Tilemap_Format::WONDERSWAN_COLOR) {
bytes.reserve(n * 2);
for (Tile_Tessera* tt : tiles) {

// lower 8 bits of the tile number
uchar v = (uchar)(tt->id() & 0xFF);
bytes.push_back(v);
uchar a = 0;
// top 9th bit of the tile number
if (tt->id() & 0x100) { a |= 0x01; }
// tile numbers >= $200 use the next tile bank (color only)
if (tt->id() & 0x200 && fmt == Tilemap_Format::WONDERSWAN_COLOR) { a |= 0x020; }
if (tt->x_flip()) { a |= 0x40; }
if (tt->y_flip()) { a |= 0x80; }
if (tt->palette() > -1) { a |= (tt->palette() & 0xf) << 1; }
bytes.push_back(a);
}
}

if (fmt == Tilemap_Format::RBY_TOWN_MAP || fmt == Tilemap_Format::SW_TOWN_MAP) {
bytes.push_back(0x00);
Expand Down
8 changes: 4 additions & 4 deletions src/tilemap-format.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@

#define TILEPAL_EXT ".asm"

#define NUM_FORMATS 16
#define NUM_FORMATS 18

enum class Tilemap_Format { PLAIN, GBC_ATTRS, GBC_ATTRMAP, GBA_4BPP, GBA_8BPP, NDS_4BPP, NDS_8BPP, SGB_BORDER, SNES_ATTRS,
GENESIS, TG16, RBY_TOWN_MAP, GSC_TOWN_MAP, PC_TOWN_MAP, SW_TOWN_MAP, POKEGEAR_CARD };
GENESIS, TG16, RBY_TOWN_MAP, GSC_TOWN_MAP, PC_TOWN_MAP, SW_TOWN_MAP, POKEGEAR_CARD, WONDERSWAN, WONDERSWAN_COLOR };

inline constexpr bool format_has_landmarks(Tilemap_Format fmt) {
return fmt == Tilemap_Format::GSC_TOWN_MAP || fmt == Tilemap_Format::PC_TOWN_MAP;
Expand All @@ -49,7 +49,7 @@ inline constexpr bool format_can_make_palettes(Tilemap_Format fmt) {
inline constexpr bool format_can_edit_palettes(Tilemap_Format fmt) {
return fmt == Tilemap_Format::GBC_ATTRS || fmt == Tilemap_Format::GBC_ATTRMAP || fmt == Tilemap_Format::GBA_4BPP ||
fmt == Tilemap_Format::NDS_4BPP || fmt == Tilemap_Format::SGB_BORDER || fmt == Tilemap_Format::SNES_ATTRS ||
fmt == Tilemap_Format::GENESIS || fmt == Tilemap_Format::TG16;
fmt == Tilemap_Format::GENESIS || fmt == Tilemap_Format::TG16 || fmt == Tilemap_Format::WONDERSWAN || fmt == Tilemap_Format::WONDERSWAN_COLOR;
}

inline constexpr bool format_has_per_tile_palettes(Tilemap_Format fmt) {
Expand All @@ -60,7 +60,7 @@ inline constexpr bool format_can_flip(Tilemap_Format fmt) {
return fmt == Tilemap_Format::GBC_ATTRS || fmt == Tilemap_Format::GBC_ATTRMAP || fmt == Tilemap_Format::GBA_4BPP ||
fmt == Tilemap_Format::GBA_8BPP || fmt == Tilemap_Format::NDS_4BPP || fmt == Tilemap_Format::NDS_8BPP ||
fmt == Tilemap_Format::GENESIS || fmt == Tilemap_Format::SGB_BORDER || fmt == Tilemap_Format::SNES_ATTRS ||
fmt == Tilemap_Format::PC_TOWN_MAP;
fmt == Tilemap_Format::PC_TOWN_MAP || fmt == Tilemap_Format::WONDERSWAN || fmt == Tilemap_Format::WONDERSWAN_COLOR;
}

inline constexpr bool format_has_priority(Tilemap_Format fmt) {
Expand Down
18 changes: 18 additions & 0 deletions src/tilemap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,24 @@ Tilemap::Result Tilemap::make_tiles(const std::vector<uchar> &tbytes, const std:
width = GAME_BOY_WIDTH;
}

else if (fmt == Tilemap_Format::WONDERSWAN || fmt == Tilemap_Format::WONDERSWAN_COLOR) {
if (c % 2) { return (_result = Result::TILEMAP_TOO_SHORT_ATTRS); }
tiles.reserve(c / 2);
for (size_t i = 0; i < c; i += 2) {
// lower 8 bits of tile number
uint16_t v = tbytes[i];
// attributes
uchar a = tbytes[i + 1];
// 9th bit of tile number
if (!!(a & 0x01)) { v |= 0x100; }
// tile bank (color only)
if (!!(a & 0x20) && fmt == Tilemap_Format::WONDERSWAN_COLOR) { v |= 0x200; }
bool x_flip = !!(a & 0x40), y_flip = !!(a & 0x80), priority = false, obp1 = false;
int palette = (a >> 1) & 0x0f;
tiles.emplace_back(new Tile_Tessera(0, 0, 0, 0, v, x_flip, y_flip, priority, obp1, palette));
}
}

if (tiles.empty()) { return (_result = Result::TILEMAP_EMPTY); }

_tiles.swap(tiles);
Expand Down