Skip to content

Commit

Permalink
Added preliminary Mega Drive support (--mode md)
Browse files Browse the repository at this point in the history
  • Loading branch information
Optiroc committed Mar 29, 2020
1 parent 7da74f3 commit fda0660
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ The `mode` option, which is common for all commands, affects the color space han
* `gbc`
* `gba`
* `gba_affine`
* `md`
* `pce`
* `pce_sprite`

Expand Down Expand Up @@ -150,7 +151,6 @@ For more flexibility use the sub commands, which have the following options resp


## future work
* Mode: Mega Drive
* Better error diagnostics
* Better documentation and example usage

Expand Down
2 changes: 1 addition & 1 deletion src/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ typedef std::vector<rgba_set_t> rgba_set_vec_t;

namespace sfc {

constexpr const char* VERSION = "0.9.1";
constexpr const char* VERSION = "0.9.2";

constexpr const char* COPYRIGHT = "Copyright (c) 2017-2020 David Lindecrantz";

Expand Down
8 changes: 7 additions & 1 deletion src/Map.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,18 @@ inline byte_vec_t pack_native_mapentry(const Mapentry& entry, Mode mode) {
v.push_back(entry.tile_index & 0xff);
break;

case Mode::md:
v.push_back(entry.tile_index & 0xff);
v.push_back(((entry.tile_index >> 8) & 0x07) | (entry.flip_h << 3) | (entry.flip_v << 4) | ((entry.palette_index << 5) & 0x60));
break;

case Mode::pce:
v.push_back(entry.tile_index & 0xff);
v.push_back(((entry.tile_index >> 8) & 0x0f) | ((entry.palette_index << 4) & 0xf0));
break;

default:
case Mode::pce_sprite:
case Mode::none:
break;
}
return v;
Expand Down
70 changes: 51 additions & 19 deletions src/Mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum class Mode {
gbc,
gba,
gba_affine,
md,
pce,
pce_sprite
};
Expand All @@ -33,6 +34,8 @@ inline Mode mode(const std::string& str) {
return Mode::gba;
} else if (str == "gba_affine") {
return Mode::gba_affine;
} else if (str == "md") {
return Mode::md;
} else if (str == "pce") {
return Mode::pce;
} else if (str == "pce_sprite") {
Expand All @@ -55,11 +58,13 @@ inline std::string mode(Mode mode) {
return std::string("gba");
case Mode::gba_affine:
return std::string("gba_affine");
case Mode::md:
return std::string("md");
case Mode::pce:
return std::string("pce");
case Mode::pce_sprite:
return std::string("pce_sprite");
default:
case Mode::none:
return std::string("none");
}
}
Expand All @@ -77,10 +82,11 @@ constexpr unsigned default_bpp_for_mode(Mode mode) {
return 4;
case Mode::gba_affine:
return 8;
case Mode::md:
case Mode::pce:
case Mode::pce_sprite:
return 4;
default:
case Mode::none:
return 4;
}
}
Expand All @@ -98,6 +104,7 @@ constexpr bool bpp_allowed_for_mode(unsigned bpp, Mode mode) {
return bpp == 4 || bpp == 8;
case Mode::gba_affine:
return bpp == 8;
case Mode::md:
case Mode::pce:
case Mode::pce_sprite:
return bpp == 4;
Expand Down Expand Up @@ -129,11 +136,12 @@ constexpr unsigned max_tile_count_for_mode(Mode mode) {
return 1024;
case Mode::gba_affine:
return 256;
case Mode::md:
case Mode::pce:
return 2048;
case Mode::pce_sprite:
return 0;
default:
case Mode::none:
return 0;
}
}
Expand All @@ -147,11 +155,12 @@ constexpr bool tile_width_allowed_for_mode(unsigned width, Mode mode) {
case Mode::gbc:
case Mode::gba:
case Mode::gba_affine:
case Mode::md:
case Mode::pce:
return width == 8;
case Mode::pce_sprite:
return width == 16;
default:
case Mode::none:
return false;
}
}
Expand All @@ -165,11 +174,12 @@ constexpr bool tile_height_allowed_for_mode(unsigned height, Mode mode) {
case Mode::gbc:
case Mode::gba:
case Mode::gba_affine:
case Mode::md:
case Mode::pce:
return height == 8;
case Mode::pce_sprite:
return height == 16;
default:
case Mode::none:
return false;
}
}
Expand All @@ -179,14 +189,15 @@ constexpr bool tile_flipping_allowed_for_mode(Mode mode) {
case Mode::snes:
case Mode::gbc:
case Mode::gba:
case Mode::md:
return true;
case Mode::snes_mode7:
case Mode::gb:
case Mode::gba_affine:
case Mode::pce:
case Mode::pce_sprite:
return false;
default:
case Mode::none:
return false;
}
}
Expand All @@ -198,14 +209,15 @@ constexpr unsigned default_map_size_for_mode(Mode mode) {
case Mode::gbc:
case Mode::gba:
case Mode::gba_affine:
case Mode::md:
case Mode::pce:
return 32;
case Mode::snes_mode7:
return 128;
case Mode::pce_sprite:
return 0;
default:
return 32;
case Mode::none:
return 0;
}
}

Expand All @@ -223,11 +235,13 @@ constexpr unsigned default_palette_count_for_mode(Mode mode) {
return 16;
case Mode::gba_affine:
return 1;
case Mode::md:
return 4;
case Mode::pce:
case Mode::pce_sprite:
return 16;
default:
return 8;
case Mode::none:
return 0;
}
}

Expand All @@ -237,14 +251,15 @@ constexpr bool col0_is_shared_for_mode(Mode mode) {
case Mode::snes_mode7:
case Mode::gba:
case Mode::gba_affine:
case Mode::md:
case Mode::pce_sprite:
return true;
case Mode::gb:
case Mode::gbc:
return false;
case Mode::pce:
return true;
default:
case Mode::none:
return true;
}
}
Expand All @@ -257,11 +272,12 @@ constexpr bool col0_is_shared_for_sprite_mode(Mode mode) {
case Mode::gbc:
case Mode::gba:
case Mode::gba_affine:
case Mode::md:
case Mode::pce:
case Mode::pce_sprite:
return true;
default:
return true;
case Mode::none:
return false;
}
}

Expand Down Expand Up @@ -301,6 +317,7 @@ inline rgba_t reduce_color(const rgba_t color, Mode to_mode) {
return (scaled & 0x00ffffff) + 0xff000000;
break;
}
case Mode::md:
case Mode::pce:
case Mode::pce_sprite:
if (((color & 0xff000000) >> 24) < 0x80) {
Expand Down Expand Up @@ -354,6 +371,7 @@ inline rgba_t normalize_color(const rgba_t color, Mode from_mode) {
c.b = scale_up(c.b, 6);
c.a = scale_up(c.a, 6);
return c;
case Mode::md:
case Mode::pce:
case Mode::pce_sprite:
c.r = scale_up(c.r, 5);
Expand Down Expand Up @@ -393,12 +411,16 @@ inline byte_vec_t pack_native_color(const rgba_t color, Mode mode) {
case Mode::gb:
v.push_back((0xff - (color & 0x3)) & 0x3);
break;
case Mode::md:
v.push_back(((color << 1) & 0x0e) | ((color >> 3) & 0xe0));
v.push_back(((color >> 15) & 0x0e));
break;
case Mode::pce:
case Mode::pce_sprite:
v.push_back(((color >> 16) & 0x07) | (color << 3 & 0x38) | ((color >> 2) & 0xc0));
v.push_back((color >> 10) & 0x01);
break;
default:
case Mode::none:
break;
}
return v;
Expand Down Expand Up @@ -462,18 +484,28 @@ inline rgba_vec_t unpack_native_colors(const byte_vec_t& colors, Mode mode) {
v.push_back(rgba);
}
break;
case Mode::md:
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 & 0x00e) >> 1) | ((cw & 0x00e0) << 3) | ((cw & 0x0e00) << 7) | 0xff000000;
v.push_back(nc);
}
break;
case Mode::pce:
case Mode::pce_sprite:
if (colors.size() % 2 != 0) {
throw std::runtime_error("pce native palette size not a multiple of 2");
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 & 0x0038) >> 3) | ((cw & 0x0007) << 8) | ((cw & 0x1c00) << 10) | 0xff000000;
v.push_back(nc);
}
break;
default:
case Mode::none:
break;
}
return v;
Expand Down Expand Up @@ -532,7 +564,7 @@ inline byte_vec_t pack_native_tile(const index_vec_t& data, Mode mode, unsigned
return p;
};

// gba style 2 pixels per byte data
// gba/md style 2 pixels per byte data
auto make_4bpp_bitpack = [](const index_vec_t& in_data) {
if (in_data.size() % 2)
throw std::runtime_error("programmer error (in_data not multiple of 2 in make_4bpp_bitpack)");
Expand Down Expand Up @@ -560,7 +592,7 @@ inline byte_vec_t pack_native_tile(const index_vec_t& data, Mode mode, unsigned
} else if (mode == Mode::snes_mode7) {
nd = data;

} else if (mode == Mode::gba || mode == Mode::gba_affine) {
} else if (mode == Mode::gba || mode == Mode::gba_affine || mode == Mode::md) {
if (bpp == 8) {
nd = data;
} else if (bpp == 4) {
Expand Down Expand Up @@ -597,7 +629,7 @@ inline index_vec_t unpack_native_tile(const byte_vec_t& data, Mode mode, unsigne
} else if (mode == Mode::snes_mode7) {
ud = data;

} else if (mode == Mode::gba || mode == Mode::gba_affine) {
} else if (mode == Mode::gba || mode == Mode::gba_affine || mode == Mode::md) {
if (bpp == 4) {
for (unsigned i = 0; i < data.size(); ++i) {
ud[(i << 1) + 0] = data[i] & 0x0f;
Expand Down

0 comments on commit fda0660

Please sign in to comment.