AGS: Make VRAM 8 bits per pixel

Before this, the virtual VRAM was 32 bits per pixel, with each pixel
holding an 8-bit index color or 0x80RRGGBB. The latter was for Ayumi-
chan Monogatari Jisshaban, which has been unsupported since system3-sdl2
was forked from System3 for Win32.

This change removes the 0x80RRGGBB format and makes the virtual VRAM 8
bits per pixel.
This commit is contained in:
kichikuou
2025-01-17 10:58:46 +09:00
parent 7f0bae6f74
commit 33418f8cb5
12 changed files with 40 additions and 96 deletions
+1 -1
View File
@@ -80,7 +80,7 @@ Here is a list of available game IDs and their corresponding titles:
| `ayumi_fd` | あゆみちゃん物語 | |
| `ayumi_hint` | あゆみちゃん物語 ヒントディスク | |
| `ayumi_live_256` | あゆみちゃん物語 実写版 | |
| `ayumi_live_full` | あゆみちゃん物語 フルカラー実写版 | |
| `ayumi_live_full` | あゆみちゃん物語 フルカラー実写版 | Unsupported |
| `ayumi_proto` | あゆみちゃん物語 PROTO | |
| `bunkasai` | あぶない文化祭前夜 | |
| `crescent` | クレセントムーンがぁる | |
+12 -22
View File
@@ -79,14 +79,19 @@ AGS::AGS(const Config& config, const GameId& game_id) : game_id(game_id), dirty(
// DIBSection 8bpp * 3 (表, 裏, メニュー)
for(int i = 0; i < 3; i++) {
hBmpScreen[i] = SDL_CreateRGBSurface(0, 640, 480, 32, 0, 0, 0, 0);
hBmpScreen[i] = SDL_CreateRGBSurfaceWithFormat(0, 640, 480, 8, SDL_PIXELFORMAT_INDEX8);
// all surfaces share the same palette
if (i > 0) {
SDL_SetSurfacePalette(hBmpScreen[i], hBmpScreen[0]->format->palette);
}
// TODO: clear surface
// memset(lpBmpScreen[i], 0, 640 * 480 * sizeof(DWORD));
// 仮想VRAMへのポインタ取得
for(int j = 0; j < 480; j++) {
vram[i][j] = surface_line(hBmpScreen[i], j);
vram[i][j] = (uint8_t*)hBmpScreen[i]->pixels + hBmpScreen[i]->pitch * j;
}
}
@@ -448,11 +453,7 @@ void AGS::set_palette(int index, int r, int g, int b)
uint8 AGS::get_pixel(int dest, int x, int y)
{
if(vram[dest][y][x] & 0x80000000) {
return 0;
} else {
return (uint8)vram[dest][y][x];
}
return vram[dest][y][x];
}
void AGS::set_pixel(int dest, int x, int y, uint8 color)
@@ -496,15 +497,10 @@ void AGS::flush_screen(bool update)
{
if(update) {
for(int y = 0; y < screen_height; y++) {
uint32* src = vram[0][y];
uint8_t* src = vram[0][y];
uint32* dest = surface_line(hBmpDest, y);
for(int x = 0; x < screen_width; x++) {
if (game_id.sys_ver == 3 && src[x] & 0x80000000) {
// あゆみちゃん物語 フルカラー実写版
dest[x] = src[x] & 0xffffff;
} else {
dest[x] = screen_palette[src[x] & 0xff];
}
dest[x] = screen_palette[src[x]];
}
}
}
@@ -519,16 +515,10 @@ void AGS::draw_screen(int sx, int sy, int width, int height)
SDL_IntersectRect(&rect, &screen, &clip);
for (int y = clip.y; y < clip.y + clip.h; y++) {
uint32* src = vram[0][y];
uint8_t* src = vram[0][y];
uint32* dest = surface_line(hBmpDest, y);
for(int x = clip.x; x < clip.x + clip.w; x++) {
uint32 a=src[x];
if (game_id.sys_ver == 3 && src[x] & 0x80000000) {
// あゆみちゃん物語 フルカラー実写版
dest[x] = src[x] & 0xffffff;
} else {
dest[x] = screen_palette[src[x] & 0xff];
}
dest[x] = screen_palette[src[x]];
}
}
invalidate_screen(clip.x, clip.y, clip.w, clip.h);
+3 -3
View File
@@ -82,7 +82,7 @@ private:
uint8 palB(uint8 col) { return screen_palette[col] & 0xff; }
int nearest_color(int r, int g, int b);
uint32* vram[3][480]; // 仮想VRAMへのポインタ
uint8_t* vram[3][480]; // 仮想VRAMへのポインタ
Palette program_palette;
Palette screen_palette;
@@ -181,13 +181,13 @@ public:
int ey;
bool frame;
bool push;
uint32* screen;
uint8_t* screen;
int screen_x;
int screen_y;
int screen_width;
int screen_height;
Palette screen_palette;
uint32* window;
uint8_t* window;
int window_x;
int window_y;
int window_width;
+1 -22
View File
@@ -20,27 +20,6 @@ void AGS::load_bmp(const char* file_name)
}
if(extract_cg) {
assert(false);
#if 0
// BMP読み込み
WCHAR wszFilePath[_MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, FILEIO::GetFilePath(file_name), -1, wszFilePath, _MAX_PATH);
Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromFile(wszFilePath);
for(unsigned int y = 0; y < pBitmap->GetHeight(); y++) {
for(unsigned int x = 0; x < pBitmap->GetWidth(); x++) {
Gdiplus::Color srcColor;
pBitmap->GetPixel(x, y, &srcColor);
vram[dest_screen][y + sy][sx + x] = SETPALETTE256(srcColor.GetR(), srcColor.GetG(), srcColor.GetB()) | 0x80000000;
}
}
// 画面更新
if(dest_screen == 0) {
draw_screen(sx, sy, pBitmap->GetWidth(), pBitmap->GetHeight());
}
// BMP開放
delete pBitmap;
#endif
WARNING("not implemented");
}
}
+1 -20
View File
@@ -78,24 +78,6 @@ void AGS::load_cg(int page, int transparent)
void AGS::copy(int sx, int sy, int ex, int ey, int dx, int dy)
{
#if 0
int width = ex - sx + 1;
int height = ey - sy + 1;
uint32 tmp[640 * 480];
memcpy(tmp, lpBmpScreen[src_screen], sizeof(tmp));
for(int y = 0; y < height && y + sy < 480 && y + dy < 480; y++) {
uint32* src = &tmp[640 * (479 - (y + sy))];
uint32* dest = vram[dest_screen][y + dy];
for(int x = 0; x < width && x + sx < 640 && x + dx < 640; x++) {
dest[x + dx] = src[x + sx];
}
}
if(dest_screen == 0) {
draw_screen(dx, dy, width, height);
}
#else
int width = ex - sx + 1;
int height = ey - sy + 1;
SDL_Rect srcrect = {sx, sy, width, height};
@@ -106,7 +88,6 @@ void AGS::copy(int sx, int sy, int ex, int ey, int dx, int dy)
if(dest_screen == 0) {
draw_screen(dx, dy, ex - sx + 1, ey - sy + 1);
}
#endif
}
void AGS::gcopy(int gsc, int gde, int glx, int gly, int gsw)
@@ -130,7 +111,7 @@ void AGS::gcopy(int gsc, int gde, int glx, int gly, int gsw)
void AGS::paint(int x, int y, uint8 color)
{
int old_color = vram[0][y][x];
uint8_t old_color = vram[0][y][x];
if (old_color == color)
return;
+1 -1
View File
@@ -127,7 +127,7 @@ void AGS::load_gl3(uint8* data, int page, int transparent)
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);
uint32* dest = &vram[dest_screen][y + sy][(x + sx) * 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;
+2 -2
View File
@@ -128,8 +128,8 @@ void AGS::load_gm3(uint8* data, int page, int transparent)
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4);
uint32* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8];
uint32* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8];
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;
+1 -1
View File
@@ -150,7 +150,7 @@ void AGS::load_pms(uint8* data, int page, int transparent)
// VRAMに転送
if(extract_cg) {
uint32* dest = &vram[dest_screen][y + sy][sx];
uint8_t* dest = &vram[dest_screen][y + sy][sx];
if(transparent == -1) {
for(int x = 0; x < width; x++) {
cgdata[2][x] = cgdata[1][x];
+3 -3
View File
@@ -442,7 +442,7 @@ void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* fon
// パターン出力
for (int y = std::max(0, -dest_y); y < fs->h && dest_y + y < 480; y++) {
uint8 *pattern = (uint8*)surface_line(fs, y); // FIXME: do not assume 8bpp
uint8_t* pattern = (uint8_t*)fs->pixels + fs->pitch * y;
for(int x = 0; x < fs->w && dest_x + x < 640; x++) {
if(pattern[x] != 0) {
vram[dest][dest_y + y][dest_x + x] = color;
@@ -477,8 +477,8 @@ void AGS::draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, TTF
// パターン出力
for (int y = std::max(0, -dest_y); y < fs->h && dest_y + y < 480; y++) {
uint8 *pattern = (uint8*)surface_line(fs, y);
uint32 *dp = &vram[dest][dest_y + y][dest_x];
uint8_t* pattern = (uint8_t*)fs->pixels + fs->pitch * y;
uint8_t* dp = &vram[dest][dest_y + y][dest_x];
for(int x = 0; x < fs->w && dest_x + x < 640; x++, dp++) {
uint8 bg = *dp;
int alpha = pattern[x] >> 5;
+1 -1
View File
@@ -141,7 +141,7 @@ void AGS::load_vsp(uint8* data, int page, int transparent)
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);
uint32* dest;
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];
+2 -2
View File
@@ -119,8 +119,8 @@ void AGS::load_vsp2l(uint8* data, int page, int transparent)
c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4);
c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4);
uint32* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8];
uint32* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8];
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;
+12 -18
View File
@@ -88,19 +88,17 @@ void AGS::open_text_window(int index, bool erase)
free(text_w[index - 1].screen);
}
text_w[index - 1].screen = (uint32*)malloc(width * height * sizeof(uint32));
text_w[index - 1].screen = (uint8_t*)malloc(width * height);
text_w[index - 1].screen_x = sx;
text_w[index - 1].screen_y = sy;
text_w[index - 1].screen_width = width;
text_w[index - 1].screen_height = height;
for(int y = 0; y < height && y + sy < 480; y++) {
uint32* scr = surface_line(hBmpDest, y + sy) + sx;
uint32_t* scr = surface_line(hBmpDest, y + sy) + sx;
for(int x = 0; x < width && x + sx < 640; x++) {
uint32 col = vram[0][y + sy][x + sx];
if(!(col & 0x80000000)) {
text_w[index - 1].screen_palette[col & 0xff] = scr[x];
}
uint8_t col = vram[0][y + sy][x + sx];
text_w[index - 1].screen_palette[col] = scr[x];
text_w[index - 1].screen[x + width * y] = col;
}
}
@@ -149,7 +147,7 @@ void AGS::close_text_window(int index, bool update)
free(text_w[index - 1].window);
}
text_w[index - 1].window = (uint32*)malloc(width * height * sizeof(uint32));
text_w[index - 1].window = (uint8_t*)malloc(width * height);
text_w[index - 1].window_x = sx;
text_w[index - 1].window_y = sy;
text_w[index - 1].window_width = width;
@@ -158,10 +156,8 @@ void AGS::close_text_window(int index, bool update)
for(int y = 0; y < height && y + sy < 480; y++) {
uint32* scr = surface_line(hBmpDest, y + sy) + sx;
for(int x = 0; x < width && x + sx < 640; x++) {
uint32 col = vram[0][y + sy][x + sx];
if(!(col & 0x80000000)) {
text_w[index - 1].window_palette[col & 0xff] = scr[x];
}
uint8_t col = vram[0][y + sy][x + sx];
text_w[index - 1].window_palette[col] = scr[x];
text_w[index - 1].window[x + width * y] = col;
}
}
@@ -197,7 +193,7 @@ void AGS::close_text_window(int index, bool update)
void AGS::clear_menu_window()
{
// TODO: use draw function
memset(hBmpScreen[2]->pixels, menu_back_color, 640 * 480 * sizeof(Uint32));
memset(hBmpScreen[2]->pixels, menu_back_color, 640 * 480);
}
void AGS::open_menu_window(int index)
@@ -221,7 +217,7 @@ void AGS::open_menu_window(int index)
free(menu_w[index - 1].screen);
}
menu_w[index - 1].screen = (uint32*)malloc(wwidth * wheight * sizeof(uint32));
menu_w[index - 1].screen = (uint8_t*)malloc(wwidth * wheight);
menu_w[index - 1].screen_x = wsx;
menu_w[index - 1].screen_y = wsy;
menu_w[index - 1].screen_width = wwidth;
@@ -230,10 +226,8 @@ void AGS::open_menu_window(int index)
for(int y = 0; y < wheight && y + wsy < 480; y++) {
uint32* scr = surface_line(hBmpDest, y + wsy) + wsx;
for(int x = 0; x < wwidth && x + wsx < 640; x++) {
uint32 col = vram[0][y + wsy][x + wsx];
if(!(col & 0x80000000)) {
menu_w[index - 1].screen_palette[col & 0xff] = scr[x];
}
uint8_t col = vram[0][y + wsy][x + wsx];
menu_w[index - 1].screen_palette[col] = scr[x];
menu_w[index - 1].screen[x + wwidth * y] = col;
}
}
@@ -294,7 +288,7 @@ void AGS::draw_window(int sx, int sy, int ex, int ey, bool frame, uint8 frame_co
{
// 領域の塗り潰し
for(int y = sy; y <= ey && y < 480; y++) {
uint32* dest = vram[0][y];
uint8_t* dest = vram[0][y];
for(int x = sx; x <= ex && x < 640; x++) {
dest[x] = back_color;
}