use new phosg::Image class
This commit is contained in:
@@ -14,6 +14,7 @@ CTestTestfile.cmake
|
|||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
Makefile
|
Makefile
|
||||||
Testing
|
Testing
|
||||||
|
build
|
||||||
|
|
||||||
# Files modified by the user and/or server that don't have defaults
|
# Files modified by the user and/or server that don't have defaults
|
||||||
system/config.json
|
system/config.json
|
||||||
@@ -35,6 +36,7 @@ system/patch-bb/.metadata-cache.json
|
|||||||
# repository
|
# repository
|
||||||
files
|
files
|
||||||
make_release.py
|
make_release.py
|
||||||
|
notes-private
|
||||||
old-khyller
|
old-khyller
|
||||||
old-newserv
|
old-newserv
|
||||||
release
|
release
|
||||||
|
|||||||
+10
-11
@@ -35,7 +35,7 @@ struct GVRHeader {
|
|||||||
be_uint16_t height;
|
be_uint16_t height;
|
||||||
} __packed_ws__(GVRHeader, 0x10);
|
} __packed_ws__(GVRHeader, 0x10);
|
||||||
|
|
||||||
string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const string& internal_name, uint32_t global_index) {
|
string encode_gvm(const phosg::ImageRGBA8888& img, GVRDataFormat data_format, const string& internal_name, uint32_t global_index) {
|
||||||
int8_t dimensions_field = -2;
|
int8_t dimensions_field = -2;
|
||||||
{
|
{
|
||||||
size_t h = img.get_height();
|
size_t h = img.get_height();
|
||||||
@@ -90,17 +90,16 @@ string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const stri
|
|||||||
for (size_t x = 0; x < img.get_width(); x += 4) {
|
for (size_t x = 0; x < img.get_width(); x += 4) {
|
||||||
for (size_t yy = 0; yy < 4; yy++) {
|
for (size_t yy = 0; yy < 4; yy++) {
|
||||||
for (size_t xx = 0; xx < 4; xx++) {
|
for (size_t xx = 0; xx < 4; xx++) {
|
||||||
uint64_t a, r, g, b;
|
uint32_t c = img.read(x + xx, y + yy);
|
||||||
img.read_pixel(x + xx, y + yy, &r, &g, &b, &a);
|
|
||||||
switch (data_format) {
|
switch (data_format) {
|
||||||
case GVRDataFormat::RGB565:
|
case GVRDataFormat::RGB565:
|
||||||
w.put_u16b(encode_rgb565(r, g, b));
|
w.put_u16b(phosg::rgb565_for_rgba8888(c));
|
||||||
break;
|
break;
|
||||||
case GVRDataFormat::RGB5A3:
|
case GVRDataFormat::RGB5A3:
|
||||||
w.put_u16b(encode_rgb5a3(r, g, b, a));
|
w.put_u16b(encode_rgb5a3(c));
|
||||||
break;
|
break;
|
||||||
case GVRDataFormat::ARGB8888:
|
case GVRDataFormat::ARGB8888:
|
||||||
w.put_u32b(encode_argb8888(r, g, b, a));
|
w.put_u32b(phosg::argb8888_for_rgba8888(c));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw logic_error("cannot encode pixel format");
|
throw logic_error("cannot encode pixel format");
|
||||||
@@ -115,15 +114,15 @@ string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const stri
|
|||||||
|
|
||||||
static const array<uint32_t, 4> fon_colors = {0x000000FF, 0x555555FF, 0xAAAAAAFF, 0xFFFFFFFF};
|
static const array<uint32_t, 4> fon_colors = {0x000000FF, 0x555555FF, 0xAAAAAAFF, 0xFFFFFFFF};
|
||||||
|
|
||||||
phosg::Image decode_fon(const string& data, size_t width) {
|
phosg::ImageRGB888 decode_fon(const string& data, size_t width) {
|
||||||
size_t num_pixels = data.size() * 4;
|
size_t num_pixels = data.size() * 4;
|
||||||
size_t height = num_pixels / width;
|
size_t height = num_pixels / width;
|
||||||
phosg::Image ret(width, height);
|
phosg::ImageRGB888 ret(width, height);
|
||||||
|
|
||||||
phosg::BitReader r(data);
|
phosg::BitReader r(data);
|
||||||
for (size_t y = 0; y < height; y++) {
|
for (size_t y = 0; y < height; y++) {
|
||||||
for (size_t x = 0; x < width; x++) {
|
for (size_t x = 0; x < width; x++) {
|
||||||
ret.write_pixel(x, y, fon_colors[r.read(2)]);
|
ret.write(x, y, fon_colors[r.read(2)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -133,11 +132,11 @@ constexpr size_t uabs(size_t a, size_t b) {
|
|||||||
return (a > b) ? (a - b) : (b - a);
|
return (a > b) ? (a - b) : (b - a);
|
||||||
}
|
}
|
||||||
|
|
||||||
string encode_fon(const phosg::Image& img) {
|
string encode_fon(const phosg::ImageRGB888& img) {
|
||||||
phosg::BitWriter w;
|
phosg::BitWriter w;
|
||||||
for (size_t y = 0; y < img.get_height(); y++) {
|
for (size_t y = 0; y < img.get_height(); y++) {
|
||||||
for (size_t x = 0; x < img.get_width(); x++) {
|
for (size_t x = 0; x < img.get_width(); x++) {
|
||||||
uint32_t color = img.read_pixel(x, y);
|
uint32_t color = img.read(x, y);
|
||||||
|
|
||||||
size_t result_delta = 0x400;
|
size_t result_delta = 0x400;
|
||||||
size_t result_index = 0;
|
size_t result_index = 0;
|
||||||
|
|||||||
+17
-31
@@ -19,43 +19,29 @@ enum class GVRDataFormat : uint8_t {
|
|||||||
DXT1 = 0x0E,
|
DXT1 = 0x0E,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index);
|
std::string encode_gvm(
|
||||||
phosg::Image decode_fon(const std::string& data, size_t width);
|
const phosg::ImageRGBA8888& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index);
|
||||||
std::string encode_fon(const phosg::Image& img);
|
phosg::ImageRGB888 decode_fon(const std::string& data, size_t width);
|
||||||
|
std::string encode_fon(const phosg::ImageRGB888& img);
|
||||||
|
|
||||||
constexpr uint16_t encode_rgb565(uint8_t r, uint8_t g, uint8_t b) {
|
constexpr uint16_t encode_rgb5a3(uint32_t c) {
|
||||||
return ((r << 8) & 0xF800) | ((g << 3) & 0x07E0) | ((b >> 3) & 0x001F);
|
if ((phosg::get_a(c) & 0xE0) == 0xE0) {
|
||||||
}
|
return 0x8000 | ((phosg::get_r(c) << 7) & 0x7C00) | ((phosg::get_g(c) << 2) & 0x03E0) | ((phosg::get_b(c) >> 3) & 0x001F);
|
||||||
|
|
||||||
constexpr uint16_t encode_rgb5a3(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
|
||||||
if ((a & 0xE0) == 0xE0) {
|
|
||||||
return 0x8000 | ((r << 7) & 0x7C00) | ((g << 2) & 0x03E0) | ((b >> 3) & 0x001F);
|
|
||||||
} else {
|
} else {
|
||||||
return ((a << 7) & 0x7000) | ((r << 4) & 0x0F00) | (g & 0x00F0) | ((b >> 4) & 0x000F);
|
return ((phosg::get_a(c) << 7) & 0x7000) | ((phosg::get_r(c) << 4) & 0x0F00) | (phosg::get_g(c) & 0x00F0) | ((phosg::get_b(c) >> 4) & 0x000F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint32_t encode_argb8888(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
template <phosg::PixelFormat Format>
|
||||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
bool has_any_transparent_pixels(const phosg::Image<Format>& img) {
|
||||||
|
if constexpr (phosg::Image<Format>::HAS_ALPHA) {
|
||||||
|
for (size_t y = 0; y < img.get_height(); y++) {
|
||||||
|
for (size_t x = 0; x < img.get_height(); x++) {
|
||||||
|
if (phosg::get_a(img.read(x, y)) != 0xFF) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint16_t encode_argb8888_to_argb1555(uint32_t argb8888) {
|
|
||||||
// In: aaaaaaaarrrrrrrrggggggggbbbbbbbb
|
|
||||||
// Out: arrrrrgggggbbbbb
|
|
||||||
return ((argb8888 >> 9) & 0x7C00) | ((argb8888 >> 6) & 0x03E0) | ((argb8888 >> 3) & 0x001F) | ((argb8888 >> 16) & 0x8000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint16_t encode_rgba8888_to_argb1555(uint32_t rgba8888) {
|
|
||||||
// In: rrrrrrrrggggggggbbbbbbbbaaaaaaaa
|
|
||||||
// Out: arrrrrgggggbbbbb
|
|
||||||
return ((rgba8888 >> 17) & 0x7C00) | ((rgba8888 >> 14) & 0x03E0) | ((rgba8888 >> 11) & 0x001F) | ((rgba8888 << 8) & 0x8000);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
constexpr uint32_t decode_argb1555_to_rgba8888(uint16_t argb1555) {
|
return false;
|
||||||
// In: arrrrrgggggbbbbb
|
|
||||||
// Out: rrrrrrrrggggggggbbbbbbbbaaaaaaaa
|
|
||||||
return ((argb1555 << 17) & 0xF8000000) | ((argb1555 << 12) & 0x07000000) |
|
|
||||||
((argb1555 << 14) & 0x00F80000) | ((argb1555 << 9) & 0x00070000) |
|
|
||||||
((argb1555 << 11) & 0x0000F800) | ((argb1555 << 6) & 0x00000700) |
|
|
||||||
((argb1555 & 0x8000) ? 0x000000FF : 0x00000000);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-21
@@ -1166,7 +1166,7 @@ Action a_decode_gci_snapshot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto img = file.decode_image();
|
auto img = file.decode_image();
|
||||||
string saved = img.save(phosg::Image::Format::WINDOWS_BITMAP);
|
string saved = img.serialize(phosg::ImageFormat::WINDOWS_BITMAP);
|
||||||
write_output_data(args, saved.data(), saved.size(), "bmp");
|
write_output_data(args, saved.data(), saved.size(), "bmp");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1177,13 +1177,16 @@ Action a_encode_gvm(
|
|||||||
GVM file can be used as an Episode 3 lobby banner.\n",
|
GVM file can be used as an Episode 3 lobby banner.\n",
|
||||||
+[](phosg::Arguments& args) {
|
+[](phosg::Arguments& args) {
|
||||||
const string& input_filename = args.get<string>(1, false);
|
const string& input_filename = args.get<string>(1, false);
|
||||||
phosg::Image img;
|
string data;
|
||||||
if (!input_filename.empty() && (input_filename != "-")) {
|
if (!input_filename.empty() && (input_filename != "-")) {
|
||||||
img = phosg::Image(input_filename);
|
data = phosg::load_file(input_filename);
|
||||||
} else {
|
} else {
|
||||||
img = phosg::Image(stdin);
|
data = phosg::read_all(stdin);
|
||||||
}
|
}
|
||||||
string encoded = encode_gvm(img, img.get_has_alpha() ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565, "image.gvr", 0);
|
auto img = phosg::ImageRGBA8888::from_file_data(data);
|
||||||
|
// If the image has any transparent pixels at all, use RGB5A3
|
||||||
|
string encoded = encode_gvm(
|
||||||
|
img, has_any_transparent_pixels(img) ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565, "image.gvr", 0);
|
||||||
write_output_data(args, encoded.data(), encoded.size(), "gvm");
|
write_output_data(args, encoded.data(), encoded.size(), "gvm");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1196,7 +1199,7 @@ Action a_decode_bitmap_font(
|
|||||||
+[](phosg::Arguments& args) {
|
+[](phosg::Arguments& args) {
|
||||||
std::string data = read_input_data(args);
|
std::string data = read_input_data(args);
|
||||||
size_t width = args.get<size_t>("width");
|
size_t width = args.get<size_t>("width");
|
||||||
std::string bmp_data = decode_fon(data, width).save(phosg::Image::Format::WINDOWS_BITMAP);
|
std::string bmp_data = decode_fon(data, width).serialize(phosg::ImageFormat::WINDOWS_BITMAP);
|
||||||
write_output_data(args, bmp_data.data(), bmp_data.size(), "bmp");
|
write_output_data(args, bmp_data.data(), bmp_data.size(), "bmp");
|
||||||
});
|
});
|
||||||
Action a_encode_bitmap_font(
|
Action a_encode_bitmap_font(
|
||||||
@@ -1207,12 +1210,13 @@ Action a_encode_bitmap_font(
|
|||||||
original fon\'s dimensions.\n",
|
original fon\'s dimensions.\n",
|
||||||
+[](phosg::Arguments& args) {
|
+[](phosg::Arguments& args) {
|
||||||
const string& input_filename = args.get<string>(1, false);
|
const string& input_filename = args.get<string>(1, false);
|
||||||
phosg::Image img;
|
string data;
|
||||||
if (!input_filename.empty() && (input_filename != "-")) {
|
if (!input_filename.empty() && (input_filename != "-")) {
|
||||||
img = phosg::Image(input_filename);
|
data = phosg::load_file(input_filename);
|
||||||
} else {
|
} else {
|
||||||
img = phosg::Image(stdin);
|
data = phosg::read_all(stdin);
|
||||||
}
|
}
|
||||||
|
auto img = phosg::ImageRGB888::from_file_data(data);
|
||||||
string encoded = encode_fon(img);
|
string encoded = encode_fon(img);
|
||||||
write_output_data(args, encoded.data(), encoded.size(), "fon");
|
write_output_data(args, encoded.data(), encoded.size(), "fon");
|
||||||
});
|
});
|
||||||
@@ -2591,22 +2595,19 @@ Action a_generate_ep3_cards_html(
|
|||||||
phosg::parallel_range<uint32_t>([&](uint32_t index, size_t) -> bool {
|
phosg::parallel_range<uint32_t>([&](uint32_t index, size_t) -> bool {
|
||||||
auto& info = this->card_infos[index];
|
auto& info = this->card_infos[index];
|
||||||
if (!info.large_filename.empty()) {
|
if (!info.large_filename.empty()) {
|
||||||
phosg::Image img(info.large_filename);
|
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(info.large_filename));
|
||||||
phosg::Image cropped(512, 399);
|
img.resize(512, 399);
|
||||||
cropped.blit(img, 0, 0, 512, 399, 0, 0);
|
info.large_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||||
info.large_data_url = cropped.png_data_url();
|
|
||||||
}
|
}
|
||||||
if (!info.medium_filename.empty()) {
|
if (!info.medium_filename.empty()) {
|
||||||
phosg::Image img(info.medium_filename);
|
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(info.medium_filename));
|
||||||
phosg::Image cropped(184, 144);
|
img.resize(184, 144);
|
||||||
cropped.blit(img, 0, 0, 184, 144, 0, 0);
|
info.medium_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||||
info.medium_data_url = cropped.png_data_url();
|
|
||||||
}
|
}
|
||||||
if (!info.small_filename.empty()) {
|
if (!info.small_filename.empty()) {
|
||||||
phosg::Image img(info.small_filename);
|
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(info.small_filename));
|
||||||
phosg::Image cropped(58, 43);
|
img.resize(58, 43);
|
||||||
cropped.blit(img, 0, 0, 58, 43, 0, 0);
|
info.small_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||||
info.small_data_url = cropped.png_data_url();
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|||||||
+3
-13
@@ -218,16 +218,7 @@ bool PSOGCSnapshotFile::checksum_correct() const {
|
|||||||
return (crc == this->checksum);
|
return (crc == this->checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t decode_rgb565(uint16_t c) {
|
phosg::ImageRGB888 PSOGCSnapshotFile::decode_image() const {
|
||||||
// Input bits: rrrrrggg gggbbbbb
|
|
||||||
// Output bits: rrrrrrrr gggggggg bbbbbbbb aaaaaaaa
|
|
||||||
return ((c << 16) & 0xF8000000) | ((c << 11) & 0x07000000) | // R
|
|
||||||
((c << 13) & 0x00FC0000) | ((c << 7) & 0x00030000) | // G
|
|
||||||
((c << 11) & 0x0000F800) | ((c << 6) & 0x00000700) | // B
|
|
||||||
0x000000FF; // A
|
|
||||||
}
|
|
||||||
|
|
||||||
phosg::Image PSOGCSnapshotFile::decode_image() const {
|
|
||||||
size_t width = this->width ? this->width.load() : 256;
|
size_t width = this->width ? this->width.load() : 256;
|
||||||
size_t height = this->height ? this->height.load() : 192;
|
size_t height = this->height ? this->height.load() : 192;
|
||||||
if (width != 256) {
|
if (width != 256) {
|
||||||
@@ -238,14 +229,13 @@ phosg::Image PSOGCSnapshotFile::decode_image() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4x4 blocks of pixels
|
// 4x4 blocks of pixels
|
||||||
phosg::Image ret(width, height, false);
|
phosg::ImageRGB888 ret(width, height);
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for (size_t y = 0; y < this->height; y += 4) {
|
for (size_t y = 0; y < this->height; y += 4) {
|
||||||
for (size_t x = 0; x < this->width; x += 4) {
|
for (size_t x = 0; x < this->width; x += 4) {
|
||||||
for (size_t yy = 0; yy < 4; yy++) {
|
for (size_t yy = 0; yy < 4; yy++) {
|
||||||
for (size_t xx = 0; xx < 4; xx++) {
|
for (size_t xx = 0; xx < 4; xx++) {
|
||||||
uint32_t color = decode_rgb565(this->pixels[offset++]);
|
ret.write(x + xx, y + yy, phosg::rgba8888_for_rgb565(this->pixels[offset++]));
|
||||||
ret.write_pixel(x + xx, y + yy, color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1066,7 +1066,7 @@ struct PSOGCSnapshotFile {
|
|||||||
/* 1818C */
|
/* 1818C */
|
||||||
|
|
||||||
bool checksum_correct() const;
|
bool checksum_correct() const;
|
||||||
phosg::Image decode_image() const;
|
phosg::ImageRGB888 decode_image() const;
|
||||||
} __packed_ws__(PSOGCSnapshotFile, 0x1818C);
|
} __packed_ws__(PSOGCSnapshotFile, 0x1818C);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
+2
-2
@@ -966,10 +966,10 @@ void ServerState::load_config_early() {
|
|||||||
} else if (lower_path.ends_with(".gvm")) {
|
} else if (lower_path.ends_with(".gvm")) {
|
||||||
decompressed_gvm_data = phosg::load_file(path);
|
decompressed_gvm_data = phosg::load_file(path);
|
||||||
} else if (lower_path.ends_with(".bmp")) {
|
} else if (lower_path.ends_with(".bmp")) {
|
||||||
phosg::Image img(path);
|
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(path));
|
||||||
decompressed_gvm_data = encode_gvm(
|
decompressed_gvm_data = encode_gvm(
|
||||||
img,
|
img,
|
||||||
img.get_has_alpha() ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565,
|
has_any_transparent_pixels(img) ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565,
|
||||||
std::format("bnr{}", banner_index),
|
std::format("bnr{}", banner_index),
|
||||||
0x80 | banner_index);
|
0x80 | banner_index);
|
||||||
banner_index++;
|
banner_index++;
|
||||||
|
|||||||
+5
-5
@@ -98,14 +98,14 @@ void TeamIndex::Team::save_config() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TeamIndex::Team::load_flag() {
|
void TeamIndex::Team::load_flag() {
|
||||||
phosg::Image img(this->flag_filename());
|
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(this->flag_filename()));
|
||||||
if (img.get_width() != 32 || img.get_height() != 32) {
|
if (img.get_width() != 32 || img.get_height() != 32) {
|
||||||
throw runtime_error("incorrect flag image dimensions");
|
throw runtime_error("incorrect flag image dimensions");
|
||||||
}
|
}
|
||||||
this->flag_data.reset(new parray<le_uint16_t, 0x20 * 0x20>());
|
this->flag_data.reset(new parray<le_uint16_t, 0x20 * 0x20>());
|
||||||
for (size_t y = 0; y < 32; y++) {
|
for (size_t y = 0; y < 32; y++) {
|
||||||
for (size_t x = 0; x < 32; x++) {
|
for (size_t x = 0; x < 32; x++) {
|
||||||
this->flag_data->at(y * 0x20 + x) = encode_rgba8888_to_argb1555(img.read_pixel(x, y));
|
this->flag_data->at(y * 0x20 + x) = phosg::argb1555_for_rgba8888(img.read(x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,13 +114,13 @@ void TeamIndex::Team::save_flag() const {
|
|||||||
if (!this->flag_data) {
|
if (!this->flag_data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
phosg::Image img(32, 32, true);
|
phosg::ImageRGBA8888 img(32, 32);
|
||||||
for (size_t y = 0; y < 32; y++) {
|
for (size_t y = 0; y < 32; y++) {
|
||||||
for (size_t x = 0; x < 32; x++) {
|
for (size_t x = 0; x < 32; x++) {
|
||||||
img.write_pixel(x, y, decode_argb1555_to_rgba8888(this->flag_data->at(y * 0x20 + x)));
|
img.write(x, y, phosg::rgba8888_for_argb1555(this->flag_data->at(y * 0x20 + x)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
img.save(this->flag_filename(), phosg::Image::Format::WINDOWS_BITMAP);
|
phosg::save_file(this->flag_filename(), img.serialize(phosg::ImageFormat::WINDOWS_BITMAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeamIndex::Team::delete_files() const {
|
void TeamIndex::Team::delete_files() const {
|
||||||
|
|||||||
Reference in New Issue
Block a user