Skip to content

Commit

Permalink
Add support for Sega Master System and Game Gear (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
lidnariq authored Dec 4, 2024
1 parent d56c292 commit d8cdb19
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
7 changes: 7 additions & 0 deletions src/Map.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ inline byte_vec_t pack_native_mapentry(const Mapentry& entry, Mode mode) {
v.push_back(entry.tile_index & 0xff);
break;

case Mode::sms:
case Mode::gg:
v.push_back(entry.tile_index & 0xff);
v.push_back(((entry.tile_index >> 8) & 0x01) | (entry.flip_h << 1) | (entry.flip_v << 2) | ((entry.palette_index << 3) & 0x8));
// SMS and GG support depth information per tile in tilemap, instead of per sprite. But superfamiconv doesn't provide that rope?
break;

case Mode::gbc:
v.push_back(entry.tile_index & 0xff);
v.push_back(((entry.palette_index) & 0x07) | ((entry.tile_index >> 5) & 0x08) | (entry.flip_h << 5) | (entry.flip_v << 6));
Expand Down
64 changes: 60 additions & 4 deletions src/Mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ enum class Mode {
pce_sprite,
ws,
wsc,
wsc_packed
wsc_packed,
sms,
gg
};

inline Mode mode(const std::string& str) {
Expand Down Expand Up @@ -50,6 +52,10 @@ inline Mode mode(const std::string& str) {
return Mode::wsc;
} else if (str == "wsc_packed") {
return Mode::wsc_packed;
} else if (str == "sms") {
return Mode::sms;
} else if (str == "gg") {
return Mode::gg;
}
return Mode::none;
}
Expand Down Expand Up @@ -80,6 +86,10 @@ inline std::string mode(Mode mode) {
return std::string("wsc");
case Mode::wsc_packed:
return std::string("wsc_packed");
case Mode::sms:
return std::string("sms");
case Mode::gg:
return std::string("gg");
default:
return std::string("none");
}
Expand All @@ -98,6 +108,8 @@ constexpr unsigned default_bpp_for_mode(Mode mode) {
case Mode::pce_sprite:
case Mode::wsc:
case Mode::wsc_packed:
case Mode::sms:
case Mode::gg:
case Mode::none:
return 4;
case Mode::snes_mode7:
Expand Down Expand Up @@ -128,6 +140,8 @@ constexpr bool bpp_allowed_for_mode(unsigned bpp, Mode mode) {
case Mode::pce:
case Mode::pce_sprite:
case Mode::wsc_packed:
case Mode::sms:
case Mode::gg:
return bpp == 4;
case Mode::none:
return false;
Expand All @@ -151,6 +165,8 @@ constexpr unsigned max_tile_count_for_mode(Mode mode) {
return 256;
case Mode::gbc:
case Mode::ws:
case Mode::sms:
case Mode::gg:
return 512;
case Mode::snes:
case Mode::gba:
Expand Down Expand Up @@ -201,6 +217,8 @@ constexpr bool tile_height_allowed_for_mode(unsigned height, Mode mode) {
case Mode::ws:
case Mode::wsc:
case Mode::wsc_packed:
case Mode::sms:
case Mode::gg:
return height == 8;
case Mode::pce_sprite:
return height == 16;
Expand Down Expand Up @@ -250,6 +268,8 @@ constexpr unsigned default_palette_count_for_mode(Mode mode) {
case Mode::gb:
case Mode::gba_affine:
return 1;
case Mode::sms:
return 2;
case Mode::md:
return 4;
case Mode::snes:
Expand All @@ -271,6 +291,8 @@ constexpr bool col0_is_shared_for_mode(Mode mode) {
switch (mode) {
case Mode::gb:
case Mode::gbc:
case Mode::sms:
case Mode::gg:
return false;
default:
return true;
Expand All @@ -288,6 +310,8 @@ constexpr bool col0_is_shared_for_sprite_mode(Mode mode) {
case Mode::md:
case Mode::pce:
case Mode::pce_sprite:
case Mode::sms:
case Mode::gg:
return true;
default:
return false;
Expand Down Expand Up @@ -355,8 +379,18 @@ inline rgba_t reduce_color(const rgba_t color, Mode to_mode) {
return (scaled & 0x00ffffff) + 0xff000000;
}
break;
case Mode::sms: {
rgba_color c(color);
c.r >>= 6;
c.g >>= 6;
c.b >>= 6;
rgba_t scaled = c;
return (scaled & 0x00ffffff) + 0xff000000;
}
break;
case Mode::wsc:
case Mode::wsc_packed:
case Mode::gg:
if (((color & 0xff000000) >> 24) < 0x80) {
return transparent_color;
} else {
Expand Down Expand Up @@ -403,13 +437,15 @@ inline rgba_t normalize_color(const rgba_t color, Mode from_mode) {
c.a = scale_up(c.a, 3);
return c;
case Mode::gb:
case Mode::sms:
c.r = scale_up(c.r, 6);
c.g = scale_up(c.g, 6);
c.b = scale_up(c.b, 6);
c.a = scale_up(c.a, 6);
return c;
case Mode::wsc:
case Mode::wsc_packed:
case Mode::gg:
c.r = scale_up(c.r, 4);
c.g = scale_up(c.g, 4);
c.b = scale_up(c.b, 4);
Expand Down Expand Up @@ -471,10 +507,14 @@ inline byte_vec_t pack_native_color(const rgba_t color, Mode mode) {
v.push_back(color ^ 0x07);
break;
case Mode::wsc:
case Mode::gg:
case Mode::wsc_packed:
v.push_back(((color >> 16) & 0x0F) | ((color >> 4) & 0xF0));
v.push_back((color & 0x0F));
break;
case Mode::sms:
v.push_back(((color >> 12) & 0x30) | ((color >> 6) & 0x0C) | (color & 3));
break;
case Mode::none:
break;
}
Expand Down Expand Up @@ -533,6 +573,12 @@ inline rgba_vec_t unpack_native_colors(const byte_vec_t& colors, Mode mode) {
v.push_back(nc);
}
break;
case Mode::sms:
for (unsigned i = 0; i < colors.size(); i++) {
rgba_t nc = (colors[i] & 3) | ((colors[i] & 0xC) << 6) | ((colors[i] & 0x30) << 12) | 0xff000000;
v.push_back(nc);
}
break;
case Mode::gb:
if (colors.size() != 1) {
throw std::runtime_error("native palette size not one byte");
Expand All @@ -550,6 +596,16 @@ inline rgba_vec_t unpack_native_colors(const byte_vec_t& colors, Mode mode) {
v.push_back(rgba);
}
break;
case Mode::gg:
if (colors.size() % 2 != 0) {
throw std::runtime_error("native palette size not a multiple of 2");
}
for (unsigned i = 0; i < colors.size(); i += 2) {
uint16_t cw = (colors[i + 1] << 8) + colors[i];
rgba_t nc = (cw & 0x00f) | ((cw & 0x00f0) << 4) | ((cw & 0x0f00) << 8) | 0xff000000;
v.push_back(nc);
}
break;
case Mode::md:
if (colors.size() % 2 != 0) {
throw std::runtime_error("native palette size not a multiple of 2");
Expand Down Expand Up @@ -607,7 +663,7 @@ inline rgba_vec_t unpack_native_colors(const byte_vec_t& colors, Mode mode) {

inline byte_vec_t pack_native_tile(const index_vec_t& data, Mode mode, unsigned bpp, unsigned width, unsigned height) {

// wsc planar style bit planes
// wsc/sms/gg planar style bit planes
auto make_4bit_planes = [](const index_vec_t& in_data, unsigned plane_index) {
byte_vec_t p(32);
if (in_data.empty())
Expand Down Expand Up @@ -723,7 +779,7 @@ inline byte_vec_t pack_native_tile(const index_vec_t& data, Mode mode, unsigned
nd.insert(nd.end(), plane.begin(), plane.end());
}

} else if (mode == Mode::ws || mode == Mode::wsc) {
} else if (mode == Mode::ws || mode == Mode::wsc || mode == Mode::gg || mode == Mode::sms) {
if (width != 8 || height != 8)
throw std::runtime_error(
fmt::format("programmer error (tile size not 8x8 in pack_native_tile() for mode \"{}\")", sfc::mode(mode)));
Expand Down Expand Up @@ -783,7 +839,7 @@ inline index_vec_t unpack_native_tile(const byte_vec_t& data, Mode mode, unsigne
for (unsigned i = 0; i < bpp; ++i)
add_1bit_plane(ud, data, i);

} else if (mode == Mode::ws || mode == Mode::wsc) {
} else if (mode == Mode::ws || mode == Mode::wsc || mode == Mode::gg || mode == Mode::sms) {
if (bpp == 4) {
for (unsigned i = 0; i < bpp; ++i)
add_1bit_plane_4bpp(ud, data, i);
Expand Down

0 comments on commit d8cdb19

Please sign in to comment.