Refactor CG loaders

Now they return a newly introduced CG object instead of writing directly
to VRAM. The palette is still written directly in the load functions.
This commit is contained in:
kichikuou
2025-11-09 10:41:00 +09:00
parent 75e99d3fbc
commit 49cf5d55ed
8 changed files with 181 additions and 203 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ SDL_Texture* create_scanline_texture(SDL_Renderer* renderer, int width, int heig
{
SDL_Surface* sf = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_ARGB8888);
for (int y = 0; y < height; y++) {
uint32* p = surface_line(sf, y);
uint32* p = reinterpret_cast<uint32*>(surface_line(sf, y));
uint32 v = y % 2 ? (SCANLINE_ALPHA << 24) : 0;
for (int x = 0; x < width; x++) {
p[x] = v;
+23 -7
View File
@@ -17,14 +17,30 @@
#include "dri.h"
#include <SDL_ttf.h>
inline uint32* surface_line(SDL_Surface* surface, int y)
inline uint8_t* surface_line(SDL_Surface* surface, int y)
{
return (uint32*)((uint8*)surface->pixels + surface->pitch * y);
return static_cast<uint8*>(surface->pixels) + surface->pitch * y;
}
struct Config;
class FILEIO;
struct SurfaceDeleter {
void operator()(SDL_Surface* s) const noexcept {
if (s) SDL_FreeSurface(s);
}
};
struct CG {
std::unique_ptr<SDL_Surface, SurfaceDeleter> surface_;
int x;
int y;
explicit CG(SDL_Surface* surface = nullptr, int x = 0, int y = 0)
: surface_(surface), x(x), y(y) {}
SDL_Surface* surface() const { return surface_.get(); }
};
class AGS
{
protected:
@@ -52,12 +68,12 @@ private:
SDL_Cursor* hCursor[10];
// AGS
void load_gm3(const std::vector<uint8_t>& data, int transparent); // Intruder -桜屋敷の探索-
void load_vsp2l(const std::vector<uint8_t>& data, int transparent); // Little Vampire
void load_gl3(const std::vector<uint8_t>& data, bool set_palette, int transparent);
void load_pms(int page, const std::vector<uint8_t>& data, bool set_palette, int transparent);
CG load_gm3(const std::vector<uint8_t>& data, int transparent); // Intruder -桜屋敷の探索-
CG load_vsp2l(const std::vector<uint8_t>& data, int transparent); // Little Vampire
CG load_gl3(const std::vector<uint8_t>& data, bool set_palette, int transparent);
CG load_pms(int page, const std::vector<uint8_t>& data, bool set_palette, int transparent);
void load_bmp(const char* file_name); // あゆみちゃん物語 フルカラー実写版
void load_vsp(const std::vector<uint8_t>& data, bool set_palette, int transparent);
CG load_vsp(const std::vector<uint8_t>& data, bool set_palette, int transparent);
void draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color);
void draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color, uint8 cache[]);
+21 -13
View File
@@ -27,41 +27,41 @@ void AGS::load_cg(int page, int transparent)
return;
bool set_palette = extract_palette && !ignore_palette.count(page);
CG cg;
switch (game_id.sys_ver) {
case 1:
switch (game_id.game) {
case GameId::BUNKASAI:
case GameId::GAKUEN:
load_vsp(data, set_palette, transparent);
cg = load_vsp(data, set_palette, transparent);
break;
case GameId::INTRUDER:
// load_gm3(data, transparent);
load_vsp(data, set_palette, transparent); // 暫定
// cg = load_gm3(data, transparent);
cg = load_vsp(data, set_palette, transparent); // 暫定
break;
case GameId::LITTLE_VAMPIRE:
load_vsp2l(data, transparent);
cg = load_vsp2l(data, transparent);
break;
default:
load_gl3(data, set_palette, transparent);
cg = load_gl3(data, set_palette, transparent);
break;
}
break;
case 2:
if (game_id.is(GameId::AYUMI_PROTO)) {
// あゆみちゃん物語 PROTO
load_gl3(data, set_palette, transparent);
cg = load_gl3(data, set_palette, transparent);
} else if (game_id.is(GameId::AYUMI_FD) || game_id.is(GameId::AYUMI_HINT)) {
// あゆみちゃん物語
load_vsp(data, set_palette, transparent);
cg = load_vsp(data, set_palette, transparent);
} else if (game_id.is_sdps()) {
// Super D.P.S
load_pms(page, data, set_palette, transparent);
cg = load_pms(page, data, set_palette, transparent);
} else {
if(data[0x8] == 0) {
load_vsp(data, set_palette, transparent);
cg = load_vsp(data, set_palette, transparent);
} else {
load_pms(page, data, set_palette, transparent);
cg = load_pms(page, data, set_palette, transparent);
}
}
break;
@@ -69,13 +69,21 @@ void AGS::load_cg(int page, int transparent)
if(data[0x8] == 0) {
if (game_id.is(GameId::FUNNYBEE_FD) || game_id.is(GameId::FUNNYBEE_CD))
set_palette = !ignore_palette.count(page);
load_vsp(data, set_palette, transparent);
cg = load_vsp(data, set_palette, transparent);
} else {
set_palette = set_palette || game_id.is(GameId::FUNNYBEE_CD);
load_pms(page, data, set_palette, transparent);
cg = load_pms(page, data, set_palette, transparent);
}
break;
}
if (extract_cg && cg.surface()) {
SDL_SetSurfacePalette(cg.surface(), screen_palette);
SDL_Rect dstrect = { cg.x, cg.y, cg.surface()->w, cg.surface()->h };
SDL_BlitSurface(cg.surface(), NULL, hBmpScreen[dest_screen], &dstrect);
if (dest_screen == 0) {
draw_screen(dstrect.x, dstrect.y, dstrect.w, dstrect.h);
}
}
if (set_palette) {
dirty_rect = {0, 0, screen_width, screen_height};
#ifdef ENABLE_DEBUGGER
+25 -38
View File
@@ -7,7 +7,7 @@
#include "ags.h"
#include <string.h>
void AGS::load_gl3(const std::vector<uint8_t>& data, bool set_palette, int transparent)
CG AGS::load_gl3(const std::vector<uint8_t>& data, bool set_palette, int transparent)
{
// ヘッダ取得
uint16 tmp = (data[0x30] | (data[0x31] << 8)) - 0x8000;
@@ -47,6 +47,10 @@ void AGS::load_gl3(const std::vector<uint8_t>& data, bool set_palette, int trans
}
// GL3展開
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width * 8, height, 8, SDL_PIXELFORMAT_INDEX8);
if (transparent >= 0) {
SDL_SetColorKey(surface, SDL_TRUE, transparent | base);
}
uint8 cgdata[4][80][3];
int p = 0x36;
memset(cgdata, 0, sizeof(cgdata));
@@ -106,46 +110,29 @@ void AGS::load_gl3(const std::vector<uint8_t>& data, bool set_palette, int trans
}
}
// VRAMに転送
if(extract_cg) {
for(int x = 0; x < width; x++) {
for(int pl = 0; pl < 4; pl++) {
cgdata[pl][x][2] = cgdata[pl][x][1];
cgdata[pl][x][1] = cgdata[pl][x][0];
}
uint8 b0, b1, b2, b3, c[8];
b0 = cgdata[0][x][0];
b1 = cgdata[1][x][0];
b2 = cgdata[2][x][0];
b3 = cgdata[3][x][0];
c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8);
c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8);
c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8);
c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8);
c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8);
c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8);
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8);
uint8_t* dest = &vram[dest_screen][y + sy][(x + sx) * 8];
if(transparent == -1) {
for(int i = 0; i < 8; i++) {
dest[i] = c[i] | base;
}
} else {
for(int i = 0; i < 8; i++) {
if(c[i] != transparent) {
dest[i] = c[i] | base;
}
}
}
// Transfer to the surface
for (int x = 0; x < width; x++) {
for (int pl = 0; pl < 4; pl++) {
cgdata[pl][x][2] = cgdata[pl][x][1];
cgdata[pl][x][1] = cgdata[pl][x][0];
}
uint8 b0, b1, b2, b3;
b0 = cgdata[0][x][0];
b1 = cgdata[1][x][0];
b2 = cgdata[2][x][0];
b3 = cgdata[3][x][0];
uint8_t* dest = surface_line(surface, y) + x * 8;
dest[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8) | base;
dest[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8) | base;
dest[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8) | base;
dest[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8) | base;
dest[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8) | base;
dest[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8) | base;
dest[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8) | base;
dest[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8) | base;
}
}
// 画面更新
if(dest_screen == 0 && extract_cg) {
draw_screen(sx * 8, sy, width * 8, height);
}
return CG(surface, sx * 8, sy);
}
+28 -37
View File
@@ -7,7 +7,7 @@
#include "ags.h"
#include <string.h>
void AGS::load_gm3(const std::vector<uint8_t>& data, int transparent)
CG AGS::load_gm3(const std::vector<uint8_t>& data, int transparent)
{
// ヘッダ取得
uint16 tmp = (data[0x30] | (data[0x31] << 8)) - 0x8000;
@@ -30,6 +30,10 @@ void AGS::load_gm3(const std::vector<uint8_t>& data, int transparent)
}
// GM3展開
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width * 8, height * 2, 8, SDL_PIXELFORMAT_INDEX8);
if (transparent >= 0) {
SDL_SetColorKey(surface, SDL_TRUE, transparent | base);
}
uint8 cgdata[3][80][3];
int p = 0x36;
memset(cgdata, 0, sizeof(cgdata));
@@ -89,46 +93,33 @@ void AGS::load_gm3(const std::vector<uint8_t>& data, int transparent)
}
}
// VRAMに転送
if(extract_cg) {
for(int x = 0; x < width; x++) {
for(int pl = 0; pl < 3; pl++) {
cgdata[pl][x][2] = cgdata[pl][x][1];
cgdata[pl][x][1] = cgdata[pl][x][0];
}
uint8 b0, b1, b2, c[8];
b0 = cgdata[0][x][0];
b1 = cgdata[1][x][0];
b2 = cgdata[2][x][0];
c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4);
c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4);
c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4);
c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4);
c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4);
c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4);
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4);
// Transfer to the surface
for (int x = 0; x < width; x++) {
for (int pl = 0; pl < 3; pl++) {
cgdata[pl][x][2] = cgdata[pl][x][1];
cgdata[pl][x][1] = cgdata[pl][x][0];
}
uint8 b0, b1, b2, c[8];
b0 = cgdata[0][x][0];
b1 = cgdata[1][x][0];
b2 = cgdata[2][x][0];
c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4);
c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4);
c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4);
c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4);
c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4);
c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4);
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4);
uint8_t* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8];
uint8_t* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8];
if(transparent == -1) {
for(int i = 0; i < 8; i++) {
dest0[i] = dest1[i] = c[i] | base;
}
} else {
for(int i = 0; i < 8; i++) {
if(c[i] != transparent) {
dest0[i] = dest1[i] = c[i] | base;
}
}
}
uint8_t* dest0 = surface_line(surface, y * 2) + x * 8;
uint8_t* dest1 = dest0 + surface->pitch;
for (int i = 0; i < 8; i++) {
dest0[i] = dest1[i] = c[i] | base;
}
}
}
// 画面更新
if(dest_screen == 0 && extract_cg) {
draw_screen(sx * 8, sy * 2, width * 8, height * 2);
}
return CG(surface, sx * 8, sy * 2);
}
+9 -20
View File
@@ -8,7 +8,7 @@
#include "game_id.h"
#include <string.h>
void AGS::load_pms(int page, const std::vector<uint8_t>& data, bool set_palette, int transparent)
CG AGS::load_pms(int page, const std::vector<uint8_t>& data, bool set_palette, int transparent)
{
// ヘッダ取得
int sx = data[0x0] | (data[0x1] << 8);
@@ -87,10 +87,11 @@ void AGS::load_pms(int page, const std::vector<uint8_t>& data, bool set_palette,
}
}
if (!extract_cg) {
return;
}
// Extract pixel data
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 8, SDL_PIXELFORMAT_INDEX8);
if (transparent >= 0) {
SDL_SetColorKey(surface, SDL_TRUE, transparent);
}
std::vector<uint8_t> buf[3];
buf[0].resize(width);
buf[1].resize(width);
@@ -104,7 +105,7 @@ void AGS::load_pms(int page, const std::vector<uint8_t>& data, bool set_palette,
// enough pixels for the image size.
if (p >= data.size()) {
WARNING("CG #%d: PMS data is incomplete or corrupted.", page);
goto finish;
return CG(surface, sx, sy);
}
uint8_t d1 = data[p++];
@@ -136,23 +137,11 @@ void AGS::load_pms(int page, const std::vector<uint8_t>& data, bool set_palette,
}
}
// Transfer the row to VRAM
uint8_t* dest = &vram[dest_screen][y + sy][sx];
if (transparent == -1) {
memcpy(dest, buf[0].data(), width);
} else {
for (int x = 0; x < width; x++) {
if (buf[0][x] != transparent) {
dest[x] = buf[0][x];
}
}
}
// Transfer the row to the surface
memcpy(surface_line(surface, y), buf[0].data(), width);
buf[2].swap(buf[1]);
buf[1].swap(buf[0]);
}
finish:
if (dest_screen == 0) {
draw_screen(sx, sy, width, height);
}
return CG(surface, sx, sy);
}
+50 -53
View File
@@ -8,7 +8,25 @@
#include "game_id.h"
#include <string.h>
void AGS::load_vsp(const std::vector<uint8_t>& data, bool set_palette, int transparent)
namespace {
void trim(CG& cg, int w, int h)
{
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, w, h, 8, SDL_PIXELFORMAT_INDEX8);
SDL_SetSurfacePalette(sf, cg.surface()->format->palette);
if (SDL_HasColorKey(cg.surface())) {
Uint32 key;
SDL_GetColorKey(cg.surface(), &key);
SDL_SetColorKey(sf, SDL_TRUE, key);
}
SDL_Rect srcrect = { 0, 0, w, h };
SDL_BlitSurface(cg.surface(), &srcrect, sf, NULL);
cg.surface_.reset(sf);
}
} // namespace
CG AGS::load_vsp(const std::vector<uint8_t>& data, bool set_palette, int transparent)
{
// ヘッダ取得
int sx = data[0] | (data[1] << 8);
@@ -56,6 +74,10 @@ void AGS::load_vsp(const std::vector<uint8_t>& data, bool set_palette, int trans
}
// VSP展開
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width * 8, height, 8, SDL_PIXELFORMAT_INDEX8);
if (transparent >= 0) {
SDL_SetColorKey(surface, SDL_TRUE, transparent | base);
}
uint8 cgdata[4][2][480], mask = 0;
int p = 0x3a;
memset(cgdata, 0, sizeof(cgdata));
@@ -116,61 +138,36 @@ void AGS::load_vsp(const std::vector<uint8_t>& data, bool set_palette, int trans
}
}
// VRAMに転送
if(extract_cg) {
for(int y = 0; y < height; y++) {
uint8 b0, b1, b2, b3, c[8];
b0 = cgdata[0][1][y] = cgdata[0][0][y];
b1 = cgdata[1][1][y] = cgdata[1][0][y];
b2 = cgdata[2][1][y] = cgdata[2][0][y];
b3 = cgdata[3][1][y] = cgdata[3][0][y];
c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8);
c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8);
c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8);
c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8);
c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8);
c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8);
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8);
uint8_t* dest;
// Gakuen Senki uses exact sx values rather than 8x.
if (game_id.is(GameId::GAKUEN))
dest = &vram[dest_screen][y + sy][(x * 8) + sx];
else
dest = &vram[dest_screen][y + sy][(x + sx) * 8];
if(transparent == -1) {
for(int i = 0; i < 8; i++) {
dest[i] = c[i] | base;
}
} else {
for(int i = 0; i < 8; i++) {
if(c[i] != transparent) {
dest[i] = c[i] | base;
}
}
}
}
// Transfer to the surface
for (int y = 0; y < height; y++) {
uint8 b0, b1, b2, b3;
b0 = cgdata[0][1][y] = cgdata[0][0][y];
b1 = cgdata[1][1][y] = cgdata[1][0][y];
b2 = cgdata[2][1][y] = cgdata[2][0][y];
b3 = cgdata[3][1][y] = cgdata[3][0][y];
uint8_t* dest = surface_line(surface, y) + x * 8;
dest[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8) | base;
dest[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8) | base;
dest[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8) | base;
dest[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8) | base;
dest[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8) | base;
dest[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8) | base;
dest[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8) | base;
dest[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8) | base;
}
}
// 画面更新
if(dest_screen == 0 && extract_cg) {
if (game_id.is(GameId::GAKUEN)) {
// Gakuen Senki's images were converted to VSP for the modern port, but don't always adhere to VSP's width restrictions, which demand
// every image width be a factor of 8. Thankfully, the exceptions are designed to fit into specific parts of the GUI, and so have
// consistent widths for each output position.
//
// As above, GS also uses exact sx values rather than values that are meant to be multiplied by 8.
if (sx == 289 && sy == 26) draw_screen(sx, sy, 188, height);
else if (sx == 289 && sy == 92) draw_screen(sx, sy, 190, height);
else if (sx == 278 && sy == 208) draw_screen(sx, sy, 212, height);
else draw_screen(sx, sy, width * 8, height);
}
else {
draw_screen(sx * 8, sy, width * 8, height);
}
if (game_id.is(GameId::GAKUEN)) {
// Gakuen Senki uses exact sx values rather than 8x.
CG cg(surface, sx, sy);
// Gakuen Senki's images were converted to VSP for the modern port, but don't always adhere to VSP's width restrictions, which demand
// every image width be a factor of 8. Thankfully, the exceptions are designed to fit into specific parts of the GUI, and so have
// consistent widths for each output position.
if (sx == 289 && sy == 26) trim(cg, 188, surface->h);
else if (sx == 289 && sy == 92) trim(cg, 190, surface->h);
else if (sx == 278 && sy == 208) trim(cg, 212, surface->h);
return cg;
}
return CG(surface, sx * 8, sy);
}
+24 -34
View File
@@ -7,7 +7,7 @@
#include "ags.h"
#include <string.h>
void AGS::load_vsp2l(const std::vector<uint8_t>& data, int transparent)
CG AGS::load_vsp2l(const std::vector<uint8_t>& data, int transparent)
{
// ヘッダ取得
int sx = data[0] | (data[1] << 8);
@@ -46,6 +46,10 @@ void AGS::load_vsp2l(const std::vector<uint8_t>& data, int transparent)
SDL_SetPaletteColors(screen_palette, colors, base, 8);
// VSP2L展開
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width * 8, height * 2, 8, SDL_PIXELFORMAT_INDEX8);
if (transparent >= 0) {
SDL_SetColorKey(surface, SDL_TRUE, transparent | base);
}
uint8 cgdata[3][2][200], mask = 0;
int p = 0x1a;
memset(cgdata, 0, sizeof(cgdata));
@@ -106,42 +110,28 @@ void AGS::load_vsp2l(const std::vector<uint8_t>& data, int transparent)
}
}
// VRAMに転送
if(extract_cg) {
for(int y = 0; y < height; y++) {
uint8 b0, b1, b2, c[8];
b0 = cgdata[0][1][y] = cgdata[0][0][y];
b1 = cgdata[1][1][y] = cgdata[1][0][y];
b2 = cgdata[2][1][y] = cgdata[2][0][y];
c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4);
c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4);
c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4);
c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4);
c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4);
c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4);
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4);
// Transfer to the surface
for (int y = 0; y < height; y++) {
uint8 b0, b1, b2, c[8];
b0 = cgdata[0][1][y] = cgdata[0][0][y];
b1 = cgdata[1][1][y] = cgdata[1][0][y];
b2 = cgdata[2][1][y] = cgdata[2][0][y];
c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4);
c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4);
c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4);
c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4);
c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4);
c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4);
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4);
uint8_t* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8];
uint8_t* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8];
if(transparent == -1) {
for(int i = 0; i < 8; i++) {
dest0[i] = dest1[i] = c[i] | base;
}
} else {
for(int i = 0; i < 8; i++) {
if(c[i] != transparent) {
dest0[i] = dest1[i] = c[i] | base;
}
}
}
uint8_t* dest0 = surface_line(surface, y * 2) + x * 8;
uint8_t* dest1 = dest0 + surface->pitch;
for (int i = 0; i < 8; i++) {
dest0[i] = dest1[i] = c[i] | base;
}
}
}
// 画面更新
if(dest_screen == 0 && extract_cg) {
draw_screen(sx * 8, sy * 2, width * 8, height * 2);
}
return CG(surface, sx * 8, sy * 2);
}