Merge some changes from SysEng 0.7 (for Gakuen Senki port)

This commit is contained in:
kichikuou
2023-04-09 15:17:33 +09:00
parent 32f4c0f945
commit 24224e0d2b
10 changed files with 192 additions and 26 deletions
+37 -11
View File
@@ -38,8 +38,19 @@ static SDL_Surface* display_surface;
AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false)
{
SDL_RenderSetLogicalSize(g_renderer, 640, 400);
sdlTexture = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 640, 400); // TOOD: pixelformat?
// 画面サイズ
if (nact->crc32_a == CRC32_GAKUEN || nact->crc32_a == CRC32_GAKUEN_ENG) {
screen_width = 512;
screen_height = 424;
} else {
screen_width = 640;
screen_height = 400;
}
scroll = screen_height;
SDL_SetWindowSize(g_window, screen_width, screen_height);
SDL_RenderSetLogicalSize(g_renderer, screen_width, screen_height);
sdlTexture = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, screen_width, screen_height); // TOOD: pixelformat?
// DIBSection 8bpp * 3 (表, 裏, メニュー)
for(int i = 0; i < 3; i++) {
@@ -232,9 +243,11 @@ AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false)
SET_MENU(i, 452, 14, 627, 214, true);
break;
case CRC32_VAMPIRE:
case CRC32_VAMPIRE_ENG:
SET_TEXT(i, 8, 255, 615, 383, false);
SET_MENU(i, 448, 11, 615, 224, false);
case CRC32_VAMPIRE_ENG:
SET_TEXT(i, 8, 255, 615, 383, false);
SET_MENU(i, 448, 11, 615, 234, false);
break;
case CRC32_YAKATA:
SET_TEXT(i, 48, 288, 594, 393, false);
@@ -252,6 +265,15 @@ AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false)
SET_TEXT(i, 104, 304, 620, 382, false);
SET_MENU(i, 420, 28, 620, 244, true);
break;
case CRC32_GAKUEN:
case CRC32_GAKUEN_ENG:
SET_TEXT(i, 8, 260, 505, 384, false);
if (i == 1) {
SET_MENU(i, 128, 32, 337, 178, true);
} else {
SET_MENU(i, 288, 30, 433, 210, true);
}
break;
default:
SET_TEXT(i, 8, 311, 623, 391, true);
SET_MENU(i, 464, 80, 623, 240, true);
@@ -290,10 +312,6 @@ AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false)
// 画面選択
src_screen = dest_screen = 0;
// 画面サイズ
screen_height = 400;
scroll = 400;
// メッセージ表示
text_dest_x = text_w[0].sx;
text_dest_y = text_w[0].sy + 2;
@@ -447,7 +465,7 @@ void AGS::flush_screen(bool update)
for(int y = 0; y < screen_height; y++) {
uint32* src = vram[0][y];
uint32* dest = surface_line(hBmpDest, y);
for(int x = 0; x < 640; x++) {
for(int x = 0; x < screen_width; x++) {
if (nact->sys_ver == 3 && src[x] & 0x80000000) {
// あゆみちゃん物語 フルカラー実写版
dest[x] = src[x] & 0xffffff;
@@ -457,7 +475,7 @@ void AGS::flush_screen(bool update)
}
}
}
invalidate_screen(0, 0, 640, screen_height);
invalidate_screen(0, 0, screen_width, screen_height);
}
void AGS::draw_screen(int sx, int sy, int width, int height)
@@ -514,8 +532,8 @@ void AGS::update_screen()
void AGS::save_screenshot(const char* path)
{
SDL_Surface* sf = SDL_CreateRGBSurface(0, 640, screen_height, 32, 0, 0, 0, 0);
SDL_Rect r = {0, 0, 640, screen_height};
SDL_Surface* sf = SDL_CreateRGBSurface(0, screen_width, screen_height, 32, 0, 0, 0, 0);
SDL_Rect r = {0, 0, screen_width, screen_height};
SDL_UnlockSurface(hBmpDest);
SDL_BlitSurface(hBmpDest, &r, sf, NULL);
SDL_LockSurface(hBmpDest);
@@ -529,6 +547,14 @@ void AGS::save_screenshot(const char* path)
SDL_FreeSurface(sf);
}
int AGS::calculate_menu_max(int window) {
if (nact->crc32_a == CRC32_INTRUDER)
return 6;
if (nact->crc32_a == CRC32_GAKUEN || nact->crc32_a == CRC32_GAKUEN_ENG)
return (menu_w[window - 1].ey - menu_w[window - 1].sy) / (menu_font_size + 4);
return 11;
}
#ifdef __EMSCRIPTEN__
extern "C" {
+2 -1
View File
@@ -129,6 +129,7 @@ public:
void translate_mouse_coords(int* x, int* y);
void save_screenshot(const char* path);
int calculate_menu_max(int window);
bool dirty;
@@ -140,7 +141,7 @@ public:
int dest_screen;
int scroll;
int screen_height;
int screen_width, screen_height;
// メッセージ表示
int text_dest_x;
+2
View File
@@ -37,6 +37,8 @@ void AGS::load_cg(int page, int transparent)
case 1:
switch (nact->crc32_a) {
case CRC32_BUNKASAI:
case CRC32_GAKUEN:
case CRC32_GAKUEN_ENG:
load_vsp(data, page, transparent);
break;
case CRC32_INTRUDER:
+21 -2
View File
@@ -141,7 +141,13 @@ 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 = &vram[dest_screen][y + sy][(x + sx) * 8];
uint32* dest;
// Gakuen Senki uses exact sx values rather than 8x.
if (nact->crc32_a == CRC32_GAKUEN || nact->crc32_a == CRC32_GAKUEN_ENG)
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;
@@ -159,7 +165,20 @@ void AGS::load_vsp(uint8* data, int page, int transparent)
// 画面更新
if(dest_screen == 0 && extract_cg) {
draw_screen(sx * 8, sy, width * 8, height);
if (nact->crc32_a == CRC32_GAKUEN || nact->crc32_a == CRC32_GAKUEN_ENG) {
// 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);
}
}
}
+2
View File
@@ -32,6 +32,8 @@
#define CRC32_VAMPIRE 0x957bcfbf // Little Vampire
#define CRC32_VAMPIRE_ENG 0x61985a7f // Little Vampire (English) Patch 1.5
#define CRC32_YAKATA 0x8cef6fa6 // ALICEの館
#define CRC32_GAKUEN 0xe4d6ec66 // 学園戦記 (unofficial system1 port) 1.0JP
#define CRC32_GAKUEN_ENG 0x6ba8c102 // Gakuen Senki (English) 1.0
// SYSTEM2
+3
View File
@@ -183,6 +183,9 @@ protected:
// DPS
bool text_refresh;
// GAKUEN
bool enable_graphics = true;
bool column; // 座標モード
bool wait_keydown; // ウェイト時のキー受付
int text_wait_time; // テキスト表示のウェイト
+2
View File
@@ -39,6 +39,8 @@ const struct CRCTable {
{"little_vampire", 1, "Little Vampire", JAPANESE, CRC32_VAMPIRE},
{"little_vampire_eng", 1, "Little Vampire", ENGLISH, CRC32_VAMPIRE_ENG},
{"yakata", 1, "ALICEの館", JAPANESE, CRC32_YAKATA},
{"gakuen", 1, "学園戦記", JAPANESE, CRC32_GAKUEN},
{"gakuen_eng", 1, "Gakuen Senki", ENGLISH, CRC32_GAKUEN_ENG},
{"ayumi_fd", 2, "あゆみちゃん物語", JAPANESE, CRC32_AYUMI_FD},
{"ayumi_hint", 2, "あゆみちゃん物語 ヒントディスク", JAPANESE, CRC32_AYUMI_HINT},
+1 -1
View File
@@ -52,7 +52,7 @@ void NACT::pump_events()
case SDL_FINGERDOWN:
case SDL_FINGERUP:
case SDL_FINGERMOTION:
mousex = e.tfinger.x * 640;
mousex = e.tfinger.x * ags->screen_width;
mousey = e.tfinger.y * ags->screen_height;
switch (SDL_GetNumTouchFingers(e.tfinger.touchId)) {
case 0:
+122 -9
View File
@@ -20,9 +20,6 @@
#include "encoding.h"
#include "texthook.h"
// メニューの改ページ
#define MENU_MAX (crc32_a == CRC32_INTRUDER ? 6 : 11)
#define WAIT(tm) \
{ \
Uint32 dwTime = SDL_GetTicks() + (tm); \
@@ -112,6 +109,17 @@ void NACT_Sys1::opening()
cmd_a();
ags->draw_box(0);
break;
case CRC32_GAKUEN:
case CRC32_GAKUEN_ENG:
mako->set_cd_track(1, 1);
ags->load_cg(302, -1);
WAIT(3000);
ags->load_cg(303, -1);
WAIT(3000);
mako->play_music(1);
ags->load_cg(304, -1);
WAIT(4000);
break;
}
}
@@ -303,6 +311,9 @@ void NACT_Sys1::cmd_set_menu()
ags->menu_dest_y += 2;
ags->draw_menu = true;
if (crc32_a == CRC32_GAKUEN || crc32_a == CRC32_GAKUEN_ENG)
menu_window = 2;
output_console("\n$%x,", menu_addr[menu_index - 1]);
}
}
@@ -372,6 +383,10 @@ void NACT_Sys1::cmd_open_verb()
// 表示する動詞のチェック
int chk[MAX_VERB], page = 0, cnt = 0;
if (crc32_a == CRC32_GAKUEN || crc32_a == CRC32_GAKUEN_ENG)
menu_window = 1;
int menu_max = ags->calculate_menu_max(menu_window);
memset(chk, 0, sizeof(chk));
for(int i = 0; i < menu_index; i++) {
chk[menu_verb[i]] = 1;
@@ -390,7 +405,7 @@ top:
ags->menu_dest_y = 0;
ags->draw_menu = true;
if(cnt <= MENU_MAX) {
if(cnt <= menu_max) {
// 1ページ内に全て表示できる
for(int i = 0; i < MAX_VERB; i++) {
if(chk[i]) {
@@ -412,7 +427,7 @@ top2:
ags->menu_dest_y += ags->menu_font_size + 2;
}
page = i + 1;
if(index == MENU_MAX - 1) {
if(index == menu_max - 1) {
break;
}
}
@@ -446,6 +461,8 @@ top2:
void NACT_Sys1::cmd_open_obj(int verb)
{
int menu_max = ags->calculate_menu_max(menu_window);
// 目的語メニューの表示
verb_obj = false;
@@ -481,7 +498,7 @@ top:
ags->menu_dest_y = 0;
ags->draw_menu = true;
if(cnt <= MENU_MAX - 1) {
if(cnt <= menu_max - 1) {
// 1ページ内に全て表示できる
for(int i = 0; i < MAX_OBJ; i++) {
if(chk[i]) {
@@ -509,7 +526,7 @@ top2:
ags->menu_dest_y += ags->menu_font_size + 2;
}
page = i + 1;
if(index == MENU_MAX - 2) {
if(index == menu_max - 2) {
break;
}
}
@@ -620,11 +637,14 @@ void NACT_Sys1::cmd_g()
output_console("\nG %d:", page);
if(crc32_a == CRC32_INTRUDER) {
if (crc32_a == CRC32_INTRUDER) {
page = (page == 97) ? 96 : (page == 98) ? 97 : page;
} else if (crc32_a == CRC32_GAKUEN || crc32_a == CRC32_GAKUEN_ENG) {
page = (page == 3) ? 94 : page;
}
ags->load_cg(page, -1);
if (enable_graphics)
ags->load_cg(page, -1);
if(crc32_a == CRC32_INTRUDER) {
if(page == 94) {
@@ -1011,6 +1031,41 @@ void NACT_Sys1::cmd_y()
fatal_error = true;
break;
}
} else if (crc32_a == CRC32_GAKUEN || crc32_a == CRC32_GAKUEN_ENG) {
switch (cmd) {
case 1:
RND = (param == 0 || param == 1) ? 0 : random(param);
break;
case 2:
// Clear variables up to param, though in practice param is always 21.
for (int i = 0; i <= param; i++) {
var[i] = 0;
}
break;
case 3:
{
char buf[16];
sprintf(buf, "%d", param);
ags->draw_text(buf);
}
break;
case 4:
if (param == 0) {
mako->play_music(1);
} else {
mako->stop_music();
}
break;
case 5:
enable_graphics = (param == 0);
break;
case 6:
// Dummied. 0 - "Display text slowly," 1 - disable.
break;
case 7:
// Dummied. 0 - "Switch to interlace mode," 1 - disable.
break;
}
} else {
switch(cmd) {
case 0:
@@ -1190,6 +1245,64 @@ void NACT_Sys1::cmd_z()
}
}
break;
case CRC32_GAKUEN:
case CRC32_GAKUEN_ENG:
if (param != 30 && (param < 34 || param > 46)) {
if (enable_graphics) {
ags->load_cg(param + 250, -1);
}
}
// Display the Gakuen Senki party status bar for party members. The Z commands make the slots appear in reverse, so 39 and 45 draw
// the box for character 1, 38 and 44 draw for character 2, and so on. Z 1, 30: draws the first character slot, which is always occupied.
//
// One the actual MSX, this bar was constructed in an irregular fashion. This code constructs a more consistent version, where each square
// is 35px wide with 2px borders on each side. Since the borders are overlapped, this means each sub-sprite is placed 37px apart.
else if (param == 46) {
// Originally this would have loaded Image 296, the party status bar, to screen 1 for future reference. However, due to trouble with
// the palette, I decided to load it before using each subcommand, instead.
/*ags->dest_screen = 1;
ags->load_cg(296, -1);
ags->dest_screen = 0;*/
}
else if (param == 30) {
// Load party status bar to screen 1.
ags->dest_screen = 1;
ags->load_cg(296, -1);
ags->dest_screen = 0;
// Draw Wataru's icon.
ags->src_screen = 1;
ags->copy(10, 182, 48, 224, 7, 210);
ags->src_screen = 0;
}
else if (param >= 34 && param <= 39) {
int x = (39 - param) * 37 + 45;
// Load party status bar to screen 1.
ags->dest_screen = 1;
ags->load_cg(296, -1);
ags->dest_screen = 0;
// Draw a blank party icon to init or clear the party box.
ags->src_screen = 1;
ags->copy(269, 182, 307, 224, x, 210);
ags->src_screen = 0;
}
else {
int x = (45 - param) * 37 + 45;
// Load party status bar to screen 1.
ags->dest_screen = 1;
ags->load_cg(296, -1);
ags->dest_screen = 0;
// Draw a party member's icon to the party bar.
ags->src_screen = 1;
ags->copy(x + 2, 182, x + 38, 224, x, 210);
ags->src_screen = 0;
}
}
}
-2
View File
@@ -26,8 +26,6 @@ void init_menu(bool mouse_move_enabled)
HINSTANCE hinst = (HINSTANCE)GetModuleHandle(NULL);
HMENU hmenu = LoadMenu(hinst, MAKEINTRESOURCE(IDR_MENU1));
SetMenu(get_hwnd(g_window), hmenu);
// Let SDL recalc the window size, taking menu height into account.
SDL_SetWindowSize(g_window, 640, 400);
if (mouse_move_enabled)
CheckMenuItem(hmenu, ID_OPTION_MOUSE_MOVE, MF_BYCOMMAND | MFS_CHECKED);
}