diff --git a/src/sys/ags.cpp b/src/sys/ags.cpp index 7f15f14..58c123d 100644 --- a/src/sys/ags.cpp +++ b/src/sys/ags.cpp @@ -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(surface_line(sf, y)); uint32 v = y % 2 ? (SCANLINE_ALPHA << 24) : 0; for (int x = 0; x < width; x++) { p[x] = v; diff --git a/src/sys/ags.h b/src/sys/ags.h index 16eb648..e98cecc 100644 --- a/src/sys/ags.h +++ b/src/sys/ags.h @@ -17,14 +17,30 @@ #include "dri.h" #include -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(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 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& data, int transparent); // Intruder -桜屋敷の探索- - void load_vsp2l(const std::vector& data, int transparent); // Little Vampire - void load_gl3(const std::vector& data, bool set_palette, int transparent); - void load_pms(int page, const std::vector& data, bool set_palette, int transparent); + CG load_gm3(const std::vector& data, int transparent); // Intruder -桜屋敷の探索- + CG load_vsp2l(const std::vector& data, int transparent); // Little Vampire + CG load_gl3(const std::vector& data, bool set_palette, int transparent); + CG load_pms(int page, const std::vector& data, bool set_palette, int transparent); void load_bmp(const char* file_name); // あゆみちゃん物語 フルカラー実写版 - void load_vsp(const std::vector& data, bool set_palette, int transparent); + CG load_vsp(const std::vector& 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[]); diff --git a/src/sys/ags_draw.cpp b/src/sys/ags_draw.cpp index 7c01230..2d025c3 100644 --- a/src/sys/ags_draw.cpp +++ b/src/sys/ags_draw.cpp @@ -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 diff --git a/src/sys/ags_gl3.cpp b/src/sys/ags_gl3.cpp index 30ca342..551ebc4 100644 --- a/src/sys/ags_gl3.cpp +++ b/src/sys/ags_gl3.cpp @@ -7,7 +7,7 @@ #include "ags.h" #include -void AGS::load_gl3(const std::vector& data, bool set_palette, int transparent) +CG AGS::load_gl3(const std::vector& 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& 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& 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); } diff --git a/src/sys/ags_gm3.cpp b/src/sys/ags_gm3.cpp index 9a8cd16..58c6e20 100644 --- a/src/sys/ags_gm3.cpp +++ b/src/sys/ags_gm3.cpp @@ -7,7 +7,7 @@ #include "ags.h" #include -void AGS::load_gm3(const std::vector& data, int transparent) +CG AGS::load_gm3(const std::vector& data, int transparent) { // ヘッダ取得 uint16 tmp = (data[0x30] | (data[0x31] << 8)) - 0x8000; @@ -30,6 +30,10 @@ void AGS::load_gm3(const std::vector& 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& 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); } diff --git a/src/sys/ags_pms.cpp b/src/sys/ags_pms.cpp index bb5d68f..cff23ad 100644 --- a/src/sys/ags_pms.cpp +++ b/src/sys/ags_pms.cpp @@ -8,7 +8,7 @@ #include "game_id.h" #include -void AGS::load_pms(int page, const std::vector& data, bool set_palette, int transparent) +CG AGS::load_pms(int page, const std::vector& 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& 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 buf[3]; buf[0].resize(width); buf[1].resize(width); @@ -104,7 +105,7 @@ void AGS::load_pms(int page, const std::vector& 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& 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); } diff --git a/src/sys/ags_vsp.cpp b/src/sys/ags_vsp.cpp index acd5dda..be52499 100644 --- a/src/sys/ags_vsp.cpp +++ b/src/sys/ags_vsp.cpp @@ -8,7 +8,25 @@ #include "game_id.h" #include -void AGS::load_vsp(const std::vector& 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& data, bool set_palette, int transparent) { // ヘッダ取得 int sx = data[0] | (data[1] << 8); @@ -56,6 +74,10 @@ void AGS::load_vsp(const std::vector& 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& 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); } diff --git a/src/sys/ags_vsp2l.cpp b/src/sys/ags_vsp2l.cpp index 203f287..48bd721 100644 --- a/src/sys/ags_vsp2l.cpp +++ b/src/sys/ags_vsp2l.cpp @@ -7,7 +7,7 @@ #include "ags.h" #include -void AGS::load_vsp2l(const std::vector& data, int transparent) +CG AGS::load_vsp2l(const std::vector& data, int transparent) { // ヘッダ取得 int sx = data[0] | (data[1] << 8); @@ -46,6 +46,10 @@ void AGS::load_vsp2l(const std::vector& 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& 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); } -