mirror of
https://github.com/kichikuou/system3-sdl2.git
synced 2026-09-22 22:58:12 +03:00
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:
+1
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user