├── .gitignore ├── COPYING ├── asm ├── Makefile ├── card.h ├── card_strings.c ├── card_table.c ├── entry.asm ├── player_info.h ├── players.c ├── rich4.asm ├── rich4_clib.asm ├── rich4_config.c ├── rich4_config.h ├── rich4_crt_mthread.asm ├── rich4_time.c ├── rich4_time.h ├── stocks.h ├── stocks_data.c ├── tool.h ├── tool_strings.c ├── tool_table.c ├── window_util.c └── window_util.h ├── csrc ├── bit_functions.c ├── card.h ├── cards.c ├── cards_ui.c ├── drawing.c ├── drawing.h ├── fcn_4021f8.c ├── fcn_417d65.c ├── font.c ├── fortune.c ├── game_init.c ├── global.h ├── land.h ├── loadsave.c ├── main.c ├── media_init.c ├── misc.c ├── misc.h ├── mkf │ ├── Makefile │ ├── graph_struct.c │ ├── graph_struct.h │ ├── mkf.c │ ├── mkf.h │ ├── mkf_decompress.c │ └── test │ │ ├── Data.mkf.sha1 │ │ ├── data1.sha1 │ │ ├── data1_graph_info.txt │ │ ├── dump1.c │ │ ├── dump_data.c │ │ ├── mkfdata.sha1 │ │ ├── parse_mkf.c │ │ └── runtest.sh ├── news.c ├── player_action.c ├── sound_struct.h ├── tools_ui.c └── util.c ├── docs ├── characters.txt ├── global_vars.txt ├── libwine │ ├── ddraw.h │ ├── winuser.h │ └── winuser.rh ├── radare2_tips.txt ├── rich4_cfg.txt ├── saveload.txt └── special_place.txt ├── r2 └── rich4_dump.py └── readme.rst /.gitignore: -------------------------------------------------------------------------------- 1 | r2 2 | *.o 3 | csrc/mkf/test/*.data 4 | *.obj 5 | *.exe 6 | -------------------------------------------------------------------------------- /asm/Makefile: -------------------------------------------------------------------------------- 1 | CROSS=i686-w64-mingw32- 2 | CC=$(CROSS)gcc 3 | LD=$(CROSS)ld 4 | LDFLAGS=-e entry 5 | LIBS=-lgdi32 -luser32 -lkernel32 -lwinmm -ldsound -lddraw 6 | LIBS+=-lmsvcrt 7 | 8 | OBJS = entry.obj \ 9 | rich4.obj rich4_time.obj card_strings.obj stocks_data.obj card_table.obj tool_strings.obj tool_table.obj \ 10 | rich4_config.obj \ 11 | players.obj \ 12 | window_util.obj \ 13 | rich4_crt_mthread.obj rich4_clib.obj 14 | 15 | rich4.exe: $(OBJS) 16 | $(LD) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) 17 | 18 | %.obj: %.asm 19 | nasm -f win32 $< 20 | 21 | %.obj: %.c 22 | $(CC) $(CFLAGS) -c -o $@ $< 23 | 24 | .PHONY: clean 25 | 26 | clean: 27 | rm -f rich4.exe $(OBJS) 28 | -------------------------------------------------------------------------------- /asm/card.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | const char *name_ptr; 6 | uint8_t init_amount; 7 | uint8_t price; 8 | uint8_t f6; 9 | uint8_t f7; 10 | } rich4_card; 11 | extern rich4_card card_table[]; 12 | -------------------------------------------------------------------------------- /asm/card_table.c: -------------------------------------------------------------------------------- 1 | #include "card.h" 2 | 3 | rich4_card card_table[] = { 4 | { "\xa7\xa1\xb4\x49\xa5\x64", 1, 200, 2, 2 }, /* 均富卡 */ 5 | { "\xa7\xa1\xb3\x68\xa5\x64", 2, 200, 2, 2 }, /* 均贫卡 */ 6 | { "\xc1\xca\xa6\x61\xa5\x64", 4, 35, 0, 1 }, /* 购地卡 */ 7 | { "\xb4\xab\xa6\x61\xa5\x64", 4, 25, 0, 0 }, /* 换地卡 */ 8 | { "\xb4\xab\xab\xce\xa5\x64", 4, 20, 0, 0 }, /* 换屋卡 */ 9 | { "\xc2\xe0\xa6\x56\xa5\x64", 3, 20, 0, 0 }, /* 转向卡 */ 10 | { "\xa7\xef\xab\xd8\xa5\x64", 8, 15, 0, 0 }, /* 改建卡 */ 11 | { "\xa9\xe7\xbd\xe6\xa5\x64", 3, 20, 0, 1 }, /* 拍卖卡 */ 12 | { "\xa4\xd1\xa8\xcf\xa5\x64", 2, 160, 2, 0 }, /* 天使卡 */ 13 | { "\xb4\x63\xc5\x5d\xa5\x64", 1, 180, 2, 2 }, /* 恶魔卡 */ 14 | { "\xa9\xc7\xc3\x7e\xa5\x64", 2, 60, 0, 2 }, /* 怪兽卡 */ 15 | { "\xa9\xee\xb0\xa3\xa5\x64", 5, 15, 0, 1 }, /* 拆除卡 */ 16 | { "\xb7\x6d\xb9\xdc\xa5\x64", 4, 25, 0, 2 }, /* 抢夺卡 */ 17 | { "\xb0\xb1\xaf\x64\xa5\x64", 4, 20, 0, 0 }, /* 停留卡 */ 18 | { "\xa5\x56\xaf\x76\xa5\x64", 2, 100, 2, 2 }, /* 冬眠卡 */ 19 | { "\xb9\xda\xb9\x43\xa5\x64", 4, 25, 0, 1 }, /* 梦游卡 */ 20 | { "\xb3\xb4\xae\x60\xa5\x64", 4, 20, 0, 2 }, /* 陷害卡 */ 21 | { "\xb4\x5f\xa4\xb3\xa5\x64", 4, 20, 0, 0 }, /* 复仇卡 */ 22 | { "\xb6\xf9\xba\xd7\xa5\x64", 4, 40, 0, 0 }, /* 嫁祸卡 */ 23 | { "\xa7\x4b\xb6\x4f\xa5\x64", 4, 25, 0, 0 }, /* 免费卡 */ 24 | { "\xa7\x4b\xb8\x6f\xa5\x64", 4, 25, 0, 0 }, /* 免罪卡 */ 25 | { "\xb0\x65\xaf\xab\xb2\xc5", 3, 10, 0, 0 }, /* 送神符 */ 26 | { "\xbd\xd0\xaf\xab\xb2\xc5", 3, 20, 0, 0 }, /* 请神符 */ 27 | { "\xac\xf5\xa5\x64", 3, 50, 0, 0 }, /* 红卡 */ 28 | { "\xb6\xc2\xa5\x64", 3, 30, 0, 1 }, /* 黑卡 */ 29 | { "\xac\x64\xb5\x7c\xa5\x64", 4, 35, 0, 1 }, /* 查税卡 */ 30 | { "\xba\xa6\xbb\xf9\xa5\x64", 3, 35, 0, 0 }, /* 涨价卡 */ 31 | { "\xac\x64\xab\xca\xa5\x64", 3, 35, 0, 1 }, /* 查封卡 */ 32 | { "\xa6\x50\xb7\xf9\xa5\x64", 2, 40, 0, 0 }, /* 同盟卡 */ 33 | { "\xaf\x51\xc0\x74\xa5\x64", 3, 70, 0, 0 }, /* 乌龟卡 */ 34 | }; 35 | -------------------------------------------------------------------------------- /asm/entry.asm: -------------------------------------------------------------------------------- 1 | global entry 2 | 3 | extern loc_004588b0 4 | extern __imp__GetModuleHandleA@4 5 | extern _LpCmdLine 6 | extern memset 7 | extern rich4_main 8 | extern __ThreadDataSize 9 | extern fcn_0045abc6 10 | extern _GetThreadPtr 11 | extern __init_stack_limits 12 | extern __NewExceptionFilter 13 | extern __NTInit 14 | extern ref_00488f8c 15 | extern ref_00489330 16 | extern ref_004898ca 17 | extern ref_00489900 18 | extern ref_004991c0 19 | extern fcn_0045ac2a 20 | 21 | section .text 22 | 23 | entry: 24 | push ebx 25 | push ebp 26 | mov ebp, esp 27 | sub esp, 8 28 | mov eax, 1 ; INIT_PRIORITY_THREAD 29 | call __InitRtns ; call 0x45abd6 30 | mov eax, dword [__ThreadDataSize] ; mov eax, dword [0x4894b0] 31 | add eax, 3 32 | and al, 0xfc 33 | sub esp, eax 34 | mov ebx, esp 35 | mov edx, dword [__ThreadDataSize] ; mov edx, dword [0x4894b0] 36 | push edx 37 | push 0 38 | push ebx 39 | call memset ; call 0x456f60 40 | add esp, 0xc 41 | mov eax, dword [__ThreadDataSize] ; mov eax, dword [0x4894b0] 42 | push ebx 43 | mov dword [ebx + 0xf0], eax 44 | lea eax, [ebp - 8] 45 | push eax 46 | call __NTMainInit ; call 0x458859 47 | mov ebx, dword [ref_00489334] ; mov ebx, dword [0x489334] 48 | add ebx, 3 49 | add esp, 8 50 | and bl, 0xfc 51 | call fcn_0045ada0 ; call 0x45ada0 52 | cmp ebx, eax 53 | jae short loc_00458d61 ; jae 0x458d61 54 | push ebx 55 | call __GRO ; call 0x45aded 56 | mov eax, dword [ref_00489334] ; mov eax, dword [0x489334] 57 | add eax, 3 58 | and al, 0xfc 59 | sub esp, eax 60 | mov eax, esp 61 | jmp short loc_00458d63 ; jmp 0x458d63 62 | 63 | loc_00458d61: 64 | xor eax, eax 65 | 66 | loc_00458d63: 67 | mov ebx, dword [ref_00489334] ; mov ebx, dword [0x489334] 68 | add eax, ebx 69 | mov dword [ref_00489338], eax ; mov dword [0x489338], eax 70 | push 0xa 71 | mov ebx, dword [_LpCmdLine] ; mov ebx, dword [0x489310] 72 | push ebx 73 | push 0 74 | push 0 75 | call dword [cs:__imp__GetModuleHandleA@4] ; ucall: call dword cs:[0x4623bc] 76 | push eax 77 | call rich4_main ; call 0x401b9c 78 | push eax 79 | call fcn_0045ae23 ; call 0x45ae23 80 | add esp, 4 81 | mov esp, ebp 82 | pop ebp 83 | pop ebx 84 | ret 85 | 86 | __GRO: 87 | push eax 88 | push ebx 89 | mov eax, dword [esp + 0xc] 90 | mov ebx, 0xfffffffc 91 | 92 | loc_0045adf8: 93 | mov dword [esp + ebx], ebx 94 | sub ebx, 0x1000 95 | sub eax, 0x1000 96 | jg short loc_0045adf8 ; jg 0x45adf8 97 | pop ebx 98 | pop eax 99 | ret 4 100 | 101 | ; __NTMainInit(REGISTRATION_RECORD *rr, thread_data *tdata) 102 | __NTMainInit: 103 | push ebx 104 | push 0 105 | call dword [cs:__imp__GetModuleHandleA@4] ; ucall: call dword cs:[0x4623bc] 106 | push eax 107 | mov edx, dword [esp + 0x10] 108 | push edx 109 | push 0 110 | call __NTInit ; call 0x4585ef 111 | add esp, 0xc 112 | push ref_00489330 ; push 0x489330 113 | call dword [_GetThreadPtr] ; ucall: call dword [0x488f4c] 114 | push eax 115 | call __init_stack_limits ; call 0x45a666 116 | add esp, 8 117 | mov ebx, dword [esp + 8] 118 | push ebx 119 | call __NewExceptionFilter ; call 0x45ab58 120 | add esp, 4 121 | mov eax, 0x21 122 | call __InitRtns ; call 0x45abd6 123 | call dword [ref_00488f8c] ; ucall: call dword [0x488f8c] 124 | mov eax, 0xff 125 | call __InitRtns ; call 0x45abd6 126 | pop ebx 127 | ret 128 | 129 | __InitRtns: 130 | push ebx 131 | push esi 132 | push es 133 | sub esp, 4 134 | mov esi, ref_00489900 ; mov esi, 0x489900 135 | mov byte [esp], al 136 | 137 | loc_0045abe4: 138 | mov eax, ref_004898ca ; mov eax, 0x4898ca 139 | mov dl, byte [esp] 140 | mov ebx, esi 141 | 142 | loc_0045abee: 143 | cmp eax, ref_00489900 ; cmp eax, 0x489900 144 | jae short loc_0045ac0a ; jae 0x45ac0a 145 | cmp byte [eax], 2 146 | je short loc_0045ac05 ; je 0x45ac05 147 | mov cl, byte [eax + 1] 148 | cmp dl, cl 149 | jb short loc_0045ac05 ; jb 0x45ac05 150 | mov ebx, eax 151 | mov dl, cl 152 | 153 | loc_0045ac05: 154 | add eax, 6 155 | jmp short loc_0045abee ; jmp 0x45abee 156 | 157 | loc_0045ac0a: 158 | cmp ebx, ref_00489900 ; cmp ebx, 0x489900 159 | je short loc_0045ac23 ; je 0x45ac23 160 | lea eax, [ebx + 2] 161 | push eax 162 | call fcn_0045abc6 ; call 0x45abc6 163 | add esp, 4 164 | mov byte [ebx], 2 165 | jmp short loc_0045abe4 ; jmp 0x45abe4 166 | 167 | loc_0045ac23: 168 | add esp, 4 169 | pop es 170 | pop esi 171 | pop ebx 172 | ret 173 | 174 | fcn_0045ada0: 175 | push ebx 176 | call dword [_GetThreadPtr] ; ucall: call dword [0x488f4c] 177 | mov ebx, eax 178 | mov eax, esp 179 | sub eax, dword [ebx] 180 | pop ebx 181 | ret 182 | 183 | fcn_0045ae22: 184 | ret 185 | 186 | fcn_0045ae23: 187 | call dword [ref_004894c8] ; ucall: call dword [0x4894c8] 188 | cmp byte [ref_004991c0], 0 ; cmp byte [0x4991c0], 0 189 | jne short loc_0045ae41 ; jne 0x45ae41 190 | mov edx, 0xff 191 | mov eax, 0x10 192 | call fcn_0045ac2a ; call 0x45ac2a 193 | 194 | loc_0045ae41: 195 | mov edx, dword [esp + 4] 196 | push edx 197 | call fcn_0045ae4f ; call 0x45ae4f 198 | add esp, 4 199 | ret 200 | 201 | fcn_0045ae4f: 202 | push ebx 203 | call dword [ref_004894c8] ; ucall: call dword [0x4894c8] 204 | call dword [ref_004894cc] ; ucall: call dword [0x4894cc] 205 | cmp dword [ref_004891ec], 0 ; cmp dword [0x4891ec], 0 206 | je short loc_0045ae6b ; je 0x45ae6b 207 | call dword [ref_004891ec] ; ucall: call dword [0x4891ec] 208 | 209 | loc_0045ae6b: 210 | mov ebx, dword [esp + 8] 211 | push ebx 212 | jmp near loc_004588b0 ; jmp 0x4588b0 213 | 214 | section .data 215 | 216 | ref_004891ec: 217 | dd 0x00000000 218 | 219 | ref_00489334: 220 | dd 0x00000000 221 | 222 | ref_00489338: 223 | dd 0x00000000 224 | 225 | ref_004894c8: ; may contain a jump table 226 | dd fcn_0045ae22 227 | 228 | ref_004894cc: ; may contain a jump table 229 | dd fcn_0045ae22 230 | 231 | -------------------------------------------------------------------------------- /asm/player_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | 8 | typedef struct 9 | { 10 | const char *name_ptr; 11 | uint32_t f4; 12 | uint16_t xpos; /* 0x496b70 */ 13 | uint16_t ypos; /* 0x496b72 */ 14 | uint16_t f12; 15 | uint16_t f14; 16 | /* 0x10 */ 17 | uint8_t f16; 18 | uint8_t traffic_method; /* 0x496b79 */ 19 | uint8_t ndices; /* 0x496b7a */ 20 | uint8_t character; 21 | uint8_t sex; /* 0: female, 1: male */ 22 | uint8_t who_plays; /* 0: not alive, 1: human, 2: computer @0x496b7d */ 23 | uint8_t f22; 24 | uint8_t f23; 25 | uint8_t f24; 26 | uint8_t init_cash_ratio; 27 | uint8_t f26; 28 | uint8_t f27; 29 | int32_t cash; 30 | /* 0x20 */ 31 | int32_t money_in_bank; /* including special financing */ 32 | int32_t loan; 33 | int32_t special_finance; 34 | uint32_t f44; 35 | /* 0x30 */ 36 | uint16_t points; 37 | uint8_t days_in_hotel; /* 0x496b9a */ 38 | uint8_t days_disappearing; 39 | uint8_t days_in_prison; 40 | uint8_t days_in_hospital; 41 | uint8_t days_sleeping; 42 | uint8_t days_sleep_walking; 43 | uint8_t days_stopping; /* 0x496ba0 */ 44 | uint8_t days_tortoise_walking; 45 | uint8_t f58; 46 | uint8_t days_rejected_by_bank; 47 | uint8_t days_bank_no_loans; 48 | uint8_t f61; 49 | uint8_t days_assurance; 50 | uint8_t god_info; 51 | /* 0x40 */ 52 | uint8_t f64; 53 | uint8_t f65; 54 | uint8_t total_winter_sleep_days; 55 | uint8_t f67; 56 | uint16_t f68; 57 | uint16_t f70; 58 | uint16_t f72; 59 | uint16_t f74; 60 | uint32_t f76[6]; 61 | uint8_t f100; /* 0x496bcc */ 62 | uint8_t f101; 63 | uint8_t f102; 64 | uint8_t f103; 65 | } player_info; 66 | 67 | extern player_info players[]; /* 0x496b68 */ 68 | extern player_info rich4_players[]; /* 0x47e80c */ 69 | 70 | extern int nplayers; /* 0x499114 */ 71 | extern int current_player; /* 0x49910c */ 72 | 73 | extern uint8_t player_cards[60]; /* 0x499120 */ 74 | extern uint8_t tool_amount[60]; /* 0x49915c */ 75 | 76 | /* still don't know what this means, 77 | * assume it's special players */ 78 | typedef struct 79 | { 80 | uint16_t f0; 81 | uint16_t f2; 82 | uint16_t f4; 83 | uint16_t f6; 84 | uint8_t f8[2]; 85 | uint8_t f10; // 0x498df2 86 | uint8_t f11; 87 | uint8_t days_winter_sleep; // 0x498df4 88 | uint8_t days_sleep_walking; // 0x498df5 89 | uint8_t days_stopping; 90 | uint8_t days_tortoise_walking; 91 | } special_player_info; 92 | 93 | extern special_player_info special_players[5]; // 0x498e28 94 | -------------------------------------------------------------------------------- /asm/players.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include "player_info.h" 7 | 8 | player_info players[4]; 9 | 10 | int nplayers; 11 | int current_player; 12 | 13 | player_info rich4_players[12] = { 14 | { 15 | .name_ptr = "\xac\xf9 \xbf\xab \xb3\xec", /* 约翰乔 */ 16 | .f4 = 0x00946126, 17 | .traffic_method = 0, 18 | .ndices = 1, 19 | .character = 0, 20 | .sex = 1, 21 | .f22 = 3, 22 | .f23 = 2, 23 | .f24 = 60, 24 | .init_cash_ratio = 50, 25 | .f26 = 30, 26 | }, 27 | { 28 | .name_ptr = "\xa8\x46\xb6\xa9\xa4\xda\xb4\xb5", /* 沙隆巴斯 */ 29 | .f4 = 0x00bdc3c6, 30 | .traffic_method = 0, 31 | .ndices = 1, 32 | .character = 1, 33 | .sex = 1, 34 | .f22 = 3, 35 | .f23 = 1, 36 | .f24 = 100, 37 | .init_cash_ratio = 40, 38 | .f26 = 45, 39 | }, 40 | { 41 | .name_ptr = "\xa7\xd4 \xa4\xd3 \xad\xa6", /* 忍太郎 */ 42 | .f4 = 0x0041323b, 43 | .traffic_method = 0, 44 | .ndices = 1, 45 | .character = 2, 46 | .sex = 1, 47 | .f22 = 3, 48 | .f23 = 2, 49 | .f24 = 0, 50 | .init_cash_ratio = 70, 51 | .f26 = 0, 52 | }, 53 | { 54 | .name_ptr = "\xbf\xfa \xa4\xd2 \xa4H", /* 钱夫人 */ 55 | .f4 = 0x00c626c3, 56 | .traffic_method = 0, 57 | .ndices = 1, 58 | .character = 3, 59 | .sex = 0, 60 | .f22 = 3, 61 | .f23 = 2, 62 | .f24 = 100, 63 | .init_cash_ratio = 60, 64 | .f26 = 30, 65 | }, 66 | { 67 | .name_ptr = "\xaa\xfc \xa4g \xa7\x42", /* 阿土伯 */ 68 | .f4 = 0x00c5b830, 69 | .traffic_method = 0, 70 | .ndices = 1, 71 | .character = 4, 72 | .sex = 1, 73 | .f22 = 3, 74 | .f23 = 1, 75 | .f24 = 50, 76 | .init_cash_ratio = 40, 77 | .f26 = 25, 78 | }, 79 | { 80 | .name_ptr = "\xb2\xef\xa9\xd4\xa4\xbd\xa5\x44", /* 莎拉公主 */ 81 | .f4 = 0x00ed9d9d, 82 | .traffic_method = 0, 83 | .ndices = 1, 84 | .character = 5, 85 | .sex = 0, 86 | .f22 = 3, 87 | .f23 = 1, 88 | .f24 = 75, 89 | .init_cash_ratio = 70, 90 | .f26 = 30, 91 | }, 92 | { 93 | .name_ptr = "\xae\x63\xa5\xbb\xc4_\xc2\xc3", /* 宫本宝藏 */ 94 | .f4 = 0x0000f038, 95 | .traffic_method = 0, 96 | .ndices = 1, 97 | .character = 6, 98 | .sex = 1, 99 | .f22 = 3, 100 | .f23 = 1, 101 | .f24 = 100, 102 | .init_cash_ratio = 50, 103 | .f26 = 20, 104 | }, 105 | { 106 | .name_ptr = "\xbf} \xbf}", /* 糖糖 */ 107 | .f4 = 0x00ffffa0, 108 | .traffic_method = 0, 109 | .ndices = 1, 110 | .character = 7, 111 | .sex = 0, 112 | .f22 = 3, 113 | .f23 = 0, 114 | .f24 = 0, 115 | .init_cash_ratio = 40, 116 | .f26 = 35, 117 | }, 118 | { 119 | .name_ptr = "\xafQ \xab}", /* 乌咪 */ 120 | .f4 = 0x00e77c08, 121 | .traffic_method = 0, 122 | .ndices = 1, 123 | .character = 8, 124 | .sex = 0, 125 | .f22 = 3, 126 | .f23 = 0, 127 | .f24 = 0, 128 | .init_cash_ratio = 60, 129 | .f26 = 20, 130 | }, 131 | { 132 | .name_ptr = "\xae] \xa4p \xac\xfc", /* 孙小美 */ 133 | .f4 = 0x00cc1a20, 134 | .traffic_method = 0, 135 | .ndices = 1, 136 | .character = 9, 137 | .sex = 0, 138 | .f22 = 3, 139 | .f23 = 0, 140 | .f24 = 50, 141 | .init_cash_ratio = 50, 142 | .f26 = 0, 143 | }, 144 | { 145 | .name_ptr = "\xa4p \xa4\xa6 \xa5\xa7", /* 小丹尼 */ 146 | .f4 = 0x002017fe, 147 | .traffic_method = 0, 148 | .ndices = 1, 149 | .character = 10, 150 | .sex = 1, 151 | .f22 = 3, 152 | .f23 = 1, 153 | .f24 = 30, 154 | .init_cash_ratio = 55, 155 | .f26 = 15, 156 | }, 157 | { 158 | .name_ptr = "\xaa\xf7 \xa8\xa9 \xa8\xa9", /* 金贝贝 */ 159 | .f4 = 0x000ebdbd, 160 | .traffic_method = 0, 161 | .ndices = 1, 162 | .character = 11, 163 | .sex = 0, 164 | .f22 = 3, 165 | .f23 = 2, 166 | .f24 = 80, 167 | .init_cash_ratio = 80, 168 | .f26 = 0, 169 | } 170 | }; 171 | -------------------------------------------------------------------------------- /asm/rich4_clib.asm: -------------------------------------------------------------------------------- 1 | global _clib_fopen 2 | global _clib_fclose 3 | global clib_fseek 4 | global _clib_fread 5 | global _clib_fwrite 6 | extern fcn_00457135 7 | extern fcn_004590b9 8 | extern fcn_00457254 9 | extern fcn_00457902 10 | extern ref_00488f60 11 | extern ref_00488f64 12 | extern ref_004991d4 13 | 14 | global clib_rand 15 | global clib_srand 16 | extern _GetThreadPtr 17 | 18 | section .text 19 | 20 | fcn_00457366: 21 | push ebx 22 | push esi 23 | push edi 24 | sub esp, 4 25 | mov eax, esp 26 | push eax 27 | mov edx, dword [esp + 0x1c] 28 | push edx 29 | call fcn_00457135 ; call 0x457135 30 | mov ebx, eax 31 | add esp, 8 32 | test eax, eax 33 | je short loc_004573b8 ; je 0x4573b8 34 | push 0 35 | call fcn_004590b9 ; call 0x4590b9 36 | add esp, 4 37 | mov edx, eax 38 | test eax, eax 39 | je short loc_004573b6 ; je 0x4573b6 40 | push eax 41 | mov ecx, dword [esp + 0x20] 42 | push ecx 43 | mov esi, dword [esp + 8] 44 | push esi 45 | mov edx, dword [esp + 0x24] 46 | xor eax, eax 47 | push ebx 48 | mov al, byte [edx] 49 | push eax 50 | mov edi, dword [esp + 0x28] 51 | push edi 52 | call fcn_00457254 ; call 0x457254 53 | add esp, 0x18 54 | mov edx, eax 55 | 56 | loc_004573b6: 57 | mov eax, edx 58 | 59 | loc_004573b8: 60 | add esp, 4 61 | pop edi 62 | pop esi 63 | pop ebx 64 | ret 65 | 66 | _clib_fopen: 67 | push ebx 68 | push 0 69 | mov edx, dword [esp + 0x10] 70 | push edx 71 | mov ebx, dword [esp + 0x10] 72 | push ebx 73 | call fcn_00457366 ; call 0x457366 74 | add esp, 0xc 75 | pop ebx 76 | ret 77 | 78 | _clib_fclose: 79 | push ebx 80 | mov ebx, dword [esp + 8] 81 | call dword [ref_00488f60] ; ucall: call dword [0x488f60] 82 | mov eax, dword [ref_004991d4] ; mov eax, dword [0x4991d4] 83 | 84 | loc_004578d5: 85 | test eax, eax 86 | jne short loc_004578e6 ; jne 0x4578e6 87 | call dword [ref_00488f64] ; ucall: call dword [0x488f64] 88 | mov eax, 0xffffffff 89 | pop ebx 90 | ret 91 | 92 | loc_004578e6: 93 | cmp ebx, dword [eax + 4] 94 | je short loc_004578ef ; je 0x4578ef 95 | mov eax, dword [eax] 96 | jmp short loc_004578d5 ; jmp 0x4578d5 97 | 98 | loc_004578ef: 99 | call dword [ref_00488f64] ; ucall: call dword [0x488f64] 100 | push 1 101 | push ebx 102 | call fcn_00457902 ; call 0x457902 103 | add esp, 8 104 | pop ebx 105 | ret 106 | 107 | ; ======================== fseek =============================== 108 | extern fcn_00458de7 109 | extern fcn_004591f9 110 | extern fcn_0045931e 111 | extern fcn_004593a9 112 | extern ref_00488f50 113 | extern ref_00488f54 114 | 115 | fcn_004574de: 116 | push ebx 117 | push esi 118 | push edi 119 | mov ebx, dword [esp + 0x10] 120 | mov eax, dword [esp + 0x14] 121 | cmp ebx, dword [eax + 4] 122 | jg short loc_00457519 ; jg 0x457519 123 | mov edx, dword [eax + 8] 124 | mov ecx, dword [eax] 125 | mov edx, dword [edx + 8] 126 | sub edx, ecx 127 | cmp ebx, edx 128 | jl short loc_00457519 ; jl 0x457519 129 | mov dl, byte [eax + 0xc] 130 | mov esi, dword [eax] 131 | mov edi, dword [eax + 4] 132 | and dl, 0xef 133 | add esi, ebx 134 | mov byte [eax + 0xc], dl 135 | sub edi, ebx 136 | mov dword [eax], esi 137 | mov dword [eax + 4], edi 138 | xor eax, eax 139 | pop edi 140 | pop esi 141 | pop ebx 142 | ret 143 | 144 | loc_00457519: 145 | mov eax, 1 146 | pop edi 147 | pop esi 148 | pop ebx 149 | ret 150 | 151 | fcn_00457522: 152 | mov eax, dword [esp + 4] 153 | and byte [eax + 0xc], 0xef 154 | mov edx, dword [eax + 8] 155 | mov edx, dword [edx + 8] 156 | mov dword [eax + 4], 0 157 | mov dword [eax], edx 158 | ret 159 | 160 | clib_fseek: 161 | push ebx 162 | push esi 163 | push edi 164 | push ebp 165 | mov ebx, dword [esp + 0x14] 166 | mov esi, dword [esp + 0x18] 167 | mov edi, dword [esp + 0x1c] 168 | mov edx, dword [ebx + 0x10] 169 | push edx 170 | call dword [ref_00488f50] ; ucall: call dword [0x488f50] 171 | mov ah, byte [ebx + 0xc] 172 | add esp, 4 173 | test ah, 6 174 | je near loc_004575dc ; je 0x4575dc 175 | test byte [ebx + 0xd], 0x10 176 | je short loc_0045759f ; je 0x45759f 177 | push ebx 178 | call fcn_004591f9 ; call 0x4591f9 179 | add esp, 4 180 | test eax, eax 181 | je short loc_004575b6 ; je 0x4575b6 182 | test edi, edi 183 | jne short loc_00457588 ; jne 0x457588 184 | test esi, esi 185 | jge short loc_00457588 ; jge 0x457588 186 | push 9 187 | call fcn_00458de7 ; call 0x458de7 188 | add esp, 4 189 | 190 | loc_00457588: 191 | mov esi, dword [ebx + 0x10] 192 | push esi 193 | 194 | loc_0045758c: 195 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 196 | mov eax, 0xffffffff 197 | add esp, 4 198 | pop ebp 199 | pop edi 200 | pop esi 201 | pop ebx 202 | ret 203 | 204 | loc_0045759f: 205 | cmp edi, 1 206 | jne short loc_004575a7 ; jne 0x4575a7 207 | sub esi, dword [ebx + 4] 208 | 209 | loc_004575a7: 210 | mov eax, dword [ebx + 8] 211 | mov eax, dword [eax + 8] 212 | mov dword [ebx + 4], 0 213 | mov dword [ebx], eax 214 | 215 | loc_004575b6: 216 | push edi 217 | mov cl, byte [ebx + 0xc] 218 | push esi 219 | mov eax, dword [ebx + 0x10] 220 | and cl, 0xeb 221 | push eax 222 | mov byte [ebx + 0xc], cl 223 | call fcn_0045931e ; call 0x45931e 224 | add esp, 0xc 225 | cmp eax, 0xffffffff 226 | jne near loc_004576bc ; jne 0x4576bc 227 | mov ecx, dword [ebx + 0x10] 228 | push ecx 229 | jmp short loc_0045758c ; jmp 0x45758c 230 | 231 | loc_004575dc: 232 | cmp edi, 1 233 | jb short loc_004575f1 ; jb 0x4575f1 234 | jbe short loc_004575fa ; jbe 0x4575fa 235 | cmp edi, 2 236 | je near loc_0045767a ; je 0x45767a 237 | jmp near loc_004576a9 ; jmp 0x4576a9 238 | 239 | loc_004575f1: 240 | test edi, edi 241 | je short loc_0045763b ; je 0x45763b 242 | jmp near loc_004576a9 ; jmp 0x4576a9 243 | 244 | loc_004575fa: 245 | push ebx 246 | push esi 247 | mov ebp, dword [ebx + 4] 248 | call fcn_004574de ; call 0x4574de 249 | add esp, 8 250 | test eax, eax 251 | je near loc_004576bc ; je 0x4576bc 252 | push edi 253 | sub esi, ebp 254 | push esi 255 | mov edi, dword [ebx + 0x10] 256 | push edi 257 | call fcn_0045931e ; call 0x45931e 258 | add esp, 0xc 259 | cmp eax, 0xffffffff 260 | jne short loc_0045762d ; jne 0x45762d 261 | mov ebp, dword [ebx + 0x10] 262 | push ebp 263 | jmp near loc_0045758c ; jmp 0x45758c 264 | 265 | loc_0045762d: 266 | push ebx 267 | call fcn_00457522 ; call 0x457522 268 | add esp, 4 269 | jmp near loc_004576bc ; jmp 0x4576bc 270 | 271 | loc_0045763b: 272 | mov edx, dword [ebx + 0x10] 273 | push edx 274 | call fcn_004593a9 ; call 0x4593a9 275 | add esp, 4 276 | mov ecx, dword [ebx + 4] 277 | mov ebp, esi 278 | sub eax, ecx 279 | push ebx 280 | sub ebp, eax 281 | push ebp 282 | call fcn_004574de ; call 0x4574de 283 | add esp, 8 284 | test eax, eax 285 | je short loc_004576bc ; je 0x4576bc 286 | push edi 287 | push esi 288 | mov esi, dword [ebx + 0x10] 289 | push esi 290 | call fcn_0045931e ; call 0x45931e 291 | add esp, 0xc 292 | cmp eax, 0xffffffff 293 | jne short loc_0045762d ; jne 0x45762d 294 | mov edi, dword [ebx + 0x10] 295 | push edi 296 | jmp near loc_0045758c ; jmp 0x45758c 297 | 298 | loc_0045767a: 299 | mov dl, ah 300 | push edi 301 | mov ecx, dword [ebx + 0x10] 302 | and dl, 0xef 303 | mov eax, dword [ebx + 8] 304 | mov byte [ebx + 0xc], dl 305 | push esi 306 | mov eax, dword [eax + 8] 307 | mov dword [ebx + 4], 0 308 | push ecx 309 | mov dword [ebx], eax 310 | call fcn_0045931e ; call 0x45931e 311 | add esp, 0xc 312 | cmp eax, 0xffffffff 313 | jne short loc_004576bc ; jne 0x4576bc 314 | jmp near loc_00457588 ; jmp 0x457588 315 | 316 | loc_004576a9: 317 | push 9 318 | call fcn_00458de7 ; call 0x458de7 319 | add esp, 4 320 | mov eax, dword [ebx + 0x10] 321 | push eax 322 | jmp near loc_0045758c ; jmp 0x45758c 323 | 324 | loc_004576bc: 325 | mov edx, dword [ebx + 0x10] 326 | push edx 327 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 328 | add esp, 4 329 | xor eax, eax 330 | pop ebp 331 | pop edi 332 | pop esi 333 | pop ebx 334 | ret 335 | 336 | ; ========================== end of fseek =============================== 337 | 338 | ; =========================== fread ===================================== 339 | extern fcn_0045940b 340 | extern fcn_0045949c 341 | extern fcn_00459657 342 | 343 | _clib_fread: 344 | push ebx 345 | push esi 346 | push edi 347 | push ebp 348 | sub esp, 4 349 | mov esi, dword [esp + 0x20] 350 | mov ebx, dword [esp + 0x24] 351 | mov edx, dword [ebx + 0x10] 352 | push edx 353 | call dword [ref_00488f50] ; ucall: call dword [0x488f50] 354 | mov ah, byte [ebx + 0xc] 355 | add esp, 4 356 | test ah, 1 357 | jne short loc_00457716 ; jne 0x457716 358 | push 4 359 | call fcn_00458de7 ; call 0x458de7 360 | or byte [ebx + 0xc], 0x20 361 | add esp, 4 362 | mov edx, dword [ebx + 0x10] 363 | push edx 364 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 365 | add esp, 4 366 | xor eax, eax 367 | jmp near loc_004578bd ; jmp 0x4578bd 368 | 369 | loc_00457716: 370 | imul esi, dword [esp + 0x1c] 371 | test esi, esi 372 | jne short loc_00457733 ; jne 0x457733 373 | mov eax, dword [ebx + 0x10] 374 | push eax 375 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 376 | add esp, 4 377 | mov eax, esi 378 | jmp near loc_004578bd ; jmp 0x4578bd 379 | 380 | loc_00457733: 381 | mov eax, dword [ebx + 8] 382 | cmp dword [eax + 8], 0 383 | jne short loc_00457745 ; jne 0x457745 384 | push ebx 385 | call fcn_0045940b ; call 0x45940b 386 | add esp, 4 387 | 388 | loc_00457745: 389 | xor ebp, ebp 390 | mov dl, byte [ebx + 0xc] 391 | mov dword [esp], ebp 392 | test dl, 0x40 393 | je near loc_00457838 ; je 0x457838 394 | mov ebp, esi 395 | 396 | loc_00457758: 397 | mov eax, dword [ebx + 4] 398 | test eax, eax 399 | je short loc_004577a4 ; je 0x4577a4 400 | mov edx, eax 401 | cmp eax, ebp 402 | jbe short loc_00457767 ; jbe 0x457767 403 | mov edx, ebp 404 | 405 | loc_00457767: 406 | mov edi, dword [esp + 0x18] 407 | mov ecx, edx 408 | mov esi, dword [ebx] 409 | push es 410 | mov eax, ds 411 | mov es, eax 412 | push edi 413 | mov eax, ecx 414 | shr ecx, 2 415 | repne movsd 416 | mov cl, al 417 | and cl, 3 418 | repne movsb ; repne movsb byte es:[edi], byte ptr [esi] 419 | pop edi 420 | pop es 421 | sub ebp, edx 422 | mov eax, dword [esp] 423 | lea esi, [edi + edx] 424 | mov ecx, dword [ebx] 425 | mov dword [esp + 0x18], esi 426 | mov edi, dword [ebx + 4] 427 | add ecx, edx 428 | add eax, edx 429 | sub edi, edx 430 | mov dword [ebx], ecx 431 | mov dword [esp], eax 432 | mov dword [ebx + 4], edi 433 | 434 | loc_004577a4: 435 | test ebp, ebp 436 | je near loc_004578a7 ; je 0x4578a7 437 | cmp ebp, dword [ebx + 0x14] 438 | jae short loc_004577b7 ; jae 0x4577b7 439 | test byte [ebx + 0xd], 4 440 | je short loc_00457822 ; je 0x457822 441 | 442 | loc_004577b7: 443 | mov eax, dword [ebx + 8] 444 | mov eax, dword [eax + 8] 445 | mov dword [ebx], eax 446 | mov edx, ebp 447 | mov al, byte [ebx + 0xd] 448 | mov dword [ebx + 4], 0 449 | test al, 4 450 | jne short loc_004577dc ; jne 0x4577dc 451 | cmp ebp, 0x200 452 | jbe short loc_004577dc ; jbe 0x4577dc 453 | xor dl, dl 454 | and dh, 0xfe 455 | 456 | loc_004577dc: 457 | push edx 458 | mov ecx, dword [esp + 0x1c] 459 | push ecx 460 | mov esi, dword [ebx + 0x10] 461 | push esi 462 | call fcn_0045949c ; call 0x45949c 463 | add esp, 0xc 464 | cmp eax, 0xffffffff 465 | jne short loc_004577fc ; jne 0x4577fc 466 | or byte [ebx + 0xc], 0x20 467 | jmp near loc_004578a7 ; jmp 0x4578a7 468 | 469 | loc_004577fc: 470 | test eax, eax 471 | jne short loc_00457809 ; jne 0x457809 472 | 473 | loc_00457800: 474 | or byte [ebx + 0xc], 0x10 475 | jmp near loc_004578a7 ; jmp 0x4578a7 476 | 477 | loc_00457809: 478 | mov edi, dword [esp + 0x18] 479 | mov edx, dword [esp] 480 | sub ebp, eax 481 | add edi, eax 482 | add edx, eax 483 | mov dword [esp + 0x18], edi 484 | mov dword [esp], edx 485 | jmp near loc_00457758 ; jmp 0x457758 486 | 487 | loc_00457822: 488 | push ebx 489 | call fcn_00459657 ; call 0x459657 490 | add esp, 4 491 | test eax, eax 492 | je near loc_004578a7 ; je 0x4578a7 493 | jmp near loc_00457758 ; jmp 0x457758 494 | 495 | loc_00457838: 496 | mov ebp, dword [esp + 0x18] 497 | add esi, ebp 498 | 499 | loc_0045783e: 500 | cmp dword [ebx + 4], 0 501 | jne short loc_00457851 ; jne 0x457851 502 | push ebx 503 | call fcn_00459657 ; call 0x459657 504 | add esp, 4 505 | test eax, eax 506 | je short loc_004578a7 ; je 0x4578a7 507 | 508 | loc_00457851: 509 | dec dword [ebx + 4] 510 | mov eax, dword [ebx] 511 | lea edx, [eax + 1] 512 | mov dword [ebx], edx 513 | mov al, byte [eax] 514 | and eax, 0xff 515 | cmp eax, 0xd 516 | jne short loc_0045788f ; jne 0x45788f 517 | cmp dword [ebx + 4], 0 518 | jne short loc_0045787a ; jne 0x45787a 519 | push ebx 520 | call fcn_00459657 ; call 0x459657 521 | add esp, 4 522 | test eax, eax 523 | je short loc_004578a7 ; je 0x4578a7 524 | 525 | loc_0045787a: 526 | mov ecx, dword [ebx + 4] 527 | mov eax, dword [ebx] 528 | dec ecx 529 | lea edx, [eax + 1] 530 | mov dword [ebx + 4], ecx 531 | mov dword [ebx], edx 532 | mov al, byte [eax] 533 | and eax, 0xff 534 | 535 | loc_0045788f: 536 | cmp eax, 0x1a 537 | je near loc_00457800 ; je 0x457800 538 | mov edi, dword [esp] 539 | mov byte [ebp], al 540 | inc edi 541 | inc ebp 542 | mov dword [esp], edi 543 | cmp ebp, esi 544 | jne short loc_0045783e ; jne 0x45783e 545 | 546 | loc_004578a7: 547 | mov ecx, dword [ebx + 0x10] 548 | push ecx 549 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 550 | add esp, 4 551 | xor edx, edx 552 | mov eax, dword [esp] 553 | div dword [esp + 0x1c] 554 | 555 | loc_004578bd: 556 | add esp, 4 557 | pop ebp 558 | pop edi 559 | pop esi 560 | pop ebx 561 | ret 562 | ; ===================================== end of fread ====================== 563 | 564 | ; ===================================== fwrite ============================ 565 | extern fcn_004599bb 566 | extern fcn_00459aab 567 | 568 | _clib_fwrite: 569 | push ebx 570 | push esi 571 | push edi 572 | push ebp 573 | sub esp, 0x10 574 | mov edi, dword [esp + 0x2c] 575 | mov ebx, dword [esp + 0x30] 576 | mov edx, dword [ebx + 0x10] 577 | push edx 578 | call dword [ref_00488f50] ; ucall: call dword [0x488f50] 579 | mov ah, byte [ebx + 0xc] 580 | add esp, 4 581 | test ah, 2 582 | jne short loc_00457b25 ; jne 0x457b25 583 | push 4 584 | call fcn_00458de7 ; call 0x458de7 585 | add esp, 4 586 | mov ah, byte [ebx + 0xc] 587 | mov edx, dword [ebx + 0x10] 588 | or ah, 0x20 589 | push edx 590 | mov byte [ebx + 0xc], ah 591 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 592 | add esp, 4 593 | xor eax, eax 594 | jmp near loc_00457d08 ; jmp 0x457d08 595 | 596 | loc_00457b25: 597 | imul edi, dword [esp + 0x28] 598 | test edi, edi 599 | jne short loc_00457b42 ; jne 0x457b42 600 | mov eax, dword [ebx + 0x10] 601 | push eax 602 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 603 | add esp, 4 604 | mov eax, edi 605 | jmp near loc_00457d08 ; jmp 0x457d08 606 | 607 | loc_00457b42: 608 | mov eax, dword [ebx + 8] 609 | cmp dword [eax + 8], 0 610 | jne short loc_00457b54 ; jne 0x457b54 611 | push ebx 612 | call fcn_0045940b ; call 0x45940b 613 | add esp, 4 614 | 615 | loc_00457b54: 616 | mov eax, dword [ebx + 0xc] 617 | mov dl, byte [ebx + 0xc] 618 | xor ebp, ebp 619 | and eax, 0x30 620 | and dl, 0xcf 621 | mov dword [esp + 8], ebp 622 | mov dword [esp], eax 623 | mov byte [ebx + 0xc], dl 624 | test dl, 0x40 625 | je near loc_00457c5a ; je 0x457c5a 626 | mov dword [esp + 0xc], edi 627 | 628 | loc_00457b79: 629 | cmp dword [ebx + 4], 0 630 | jne short loc_00457bc9 ; jne 0x457bc9 631 | mov eax, dword [esp + 0xc] 632 | cmp eax, dword [ebx + 0x14] 633 | jb short loc_00457bc9 ; jb 0x457bc9 634 | xor al, al 635 | and ah, 0xfe 636 | test eax, eax 637 | jne short loc_00457b95 ; jne 0x457b95 638 | mov eax, dword [esp + 0xc] 639 | 640 | loc_00457b95: 641 | push eax 642 | mov esi, dword [esp + 0x28] 643 | push esi 644 | mov edi, dword [ebx + 0x10] 645 | push edi 646 | call fcn_004599bb ; call 0x4599bb 647 | add esp, 0xc 648 | mov ebp, eax 649 | cmp eax, 0xffffffff 650 | je short loc_00457bc3 ; je 0x457bc3 651 | test eax, eax 652 | jne near loc_00457c27 ; jne 0x457c27 653 | call dword [_GetThreadPtr] ; ucall: call dword [0x488f4c] 654 | mov dword [eax + 4], 0xc 655 | 656 | loc_00457bc3: 657 | or byte [ebx + 0xc], 0x20 658 | jmp short loc_00457c27 ; jmp 0x457c27 659 | 660 | loc_00457bc9: 661 | mov ebp, dword [ebx + 0x14] 662 | mov esi, dword [ebx + 4] 663 | mov edi, dword [esp + 0xc] 664 | sub ebp, esi 665 | cmp ebp, edi 666 | jbe short loc_00457bdb ; jbe 0x457bdb 667 | mov ebp, edi 668 | 669 | loc_00457bdb: 670 | mov esi, dword [esp + 0x24] 671 | mov ecx, ebp 672 | mov edi, dword [ebx] 673 | push es 674 | mov eax, ds 675 | mov es, eax 676 | push edi 677 | mov eax, ecx 678 | shr ecx, 2 679 | repne movsd 680 | mov cl, al 681 | and cl, 3 682 | repne movsb ; repne movsb byte es:[edi], byte ptr [esi] 683 | pop edi 684 | pop es 685 | mov eax, dword [ebx] 686 | mov edx, dword [ebx + 4] 687 | mov ch, byte [ebx + 0xd] 688 | add eax, ebp 689 | add edx, ebp 690 | mov dword [ebx], eax 691 | or ch, 0x10 692 | mov dword [ebx + 4], edx 693 | mov byte [ebx + 0xd], ch 694 | mov eax, dword [ebx + 4] 695 | cmp eax, dword [ebx + 0x14] 696 | je short loc_00457c1e ; je 0x457c1e 697 | test byte [ebx + 0xd], 4 698 | je short loc_00457c27 ; je 0x457c27 699 | 700 | loc_00457c1e: 701 | push ebx 702 | call fcn_004591f9 ; call 0x4591f9 703 | add esp, 4 704 | 705 | loc_00457c27: 706 | mov eax, dword [esp + 0x24] 707 | mov edx, dword [esp + 8] 708 | mov ecx, dword [esp + 0xc] 709 | add eax, ebp 710 | add edx, ebp 711 | mov dword [esp + 0x24], eax 712 | mov dword [esp + 8], edx 713 | sub ecx, ebp 714 | mov dword [esp + 0xc], ecx 715 | je near loc_00457cda ; je 0x457cda 716 | test byte [ebx + 0xc], 0x20 717 | je near loc_00457b79 ; je 0x457b79 718 | jmp near loc_00457cda ; jmp 0x457cda 719 | 720 | loc_00457c5a: 721 | mov cl, byte [ebx + 0xd] 722 | xor esi, esi 723 | test cl, 4 724 | je short loc_00457c78 ; je 0x457c78 725 | mov ch, cl 726 | and ch, 0xfa 727 | mov al, ch 728 | mov byte [ebx + 0xd], ch 729 | or al, 1 730 | mov esi, 1 731 | mov byte [ebx + 0xd], al 732 | 733 | loc_00457c78: 734 | mov eax, dword [ebx + 8] 735 | mov ebp, dword [eax + 0xc] 736 | mov dword [esp + 4], ebp 737 | mov dword [eax + 0xc], 1 738 | mov ebp, dword [esp + 0x24] 739 | 740 | loc_00457c8d: 741 | xor eax, eax 742 | push ebx 743 | mov al, byte [ebp] 744 | push eax 745 | inc ebp 746 | call fcn_00459aab ; call 0x459aab 747 | mov dl, byte [ebx + 0xc] 748 | add esp, 8 749 | test dl, 0x30 750 | jne short loc_00457cb2 ; jne 0x457cb2 751 | mov ecx, dword [esp + 8] 752 | inc ecx 753 | mov dword [esp + 8], ecx 754 | cmp edi, ecx 755 | jne short loc_00457c8d ; jne 0x457c8d 756 | 757 | loc_00457cb2: 758 | mov eax, dword [ebx + 8] 759 | mov edi, dword [esp + 4] 760 | mov dword [eax + 0xc], edi 761 | test esi, esi 762 | je short loc_00457cda ; je 0x457cda 763 | mov dh, byte [ebx + 0xd] 764 | and dh, 0xfa 765 | mov cl, dh 766 | mov byte [ebx + 0xd], dh 767 | or cl, 4 768 | push ebx 769 | mov byte [ebx + 0xd], cl 770 | call fcn_004591f9 ; call 0x4591f9 771 | add esp, 4 772 | 773 | loc_00457cda: 774 | test byte [ebx + 0xc], 0x20 775 | je short loc_00457ce6 ; je 0x457ce6 776 | xor edi, edi 777 | mov dword [esp + 8], edi 778 | 779 | loc_00457ce6: 780 | mov eax, dword [esp] 781 | mov ebp, dword [ebx + 0xc] 782 | or ebp, eax 783 | mov eax, dword [ebx + 0x10] 784 | push eax 785 | mov dword [ebx + 0xc], ebp 786 | call dword [ref_00488f54] ; ucall: call dword [0x488f54] 787 | add esp, 4 788 | xor edx, edx 789 | mov eax, dword [esp + 8] 790 | div dword [esp + 0x28] 791 | 792 | loc_00457d08: 793 | add esp, 0x10 794 | pop ebp 795 | pop edi 796 | pop esi 797 | pop ebx 798 | ret 799 | 800 | ; ===================================== end of fwrite ===================== 801 | 802 | fcn_00456f23: 803 | call dword [_GetThreadPtr] ; ucall: call dword [0x488f4c] 804 | add eax, 0xc 805 | ret 806 | 807 | clib_rand: 808 | call fcn_00456f23 ; call 0x456f23 809 | test eax, eax 810 | jne short loc_00456f37 ; jne 0x456f37 811 | ret 812 | 813 | loc_00456f37: 814 | imul edx, dword [eax], 0x41c64e6d 815 | add edx, 0x3039 816 | mov dword [eax], edx 817 | mov eax, edx 818 | shr eax, 0x10 819 | and eax, 0x7fff 820 | ret 821 | 822 | clib_srand: 823 | call fcn_00456f23 ; call 0x456f23 824 | test eax, eax 825 | je short loc_00456f5f ; je 0x456f5f 826 | mov edx, dword [esp + 4] 827 | mov dword [eax], edx 828 | 829 | loc_00456f5f: 830 | ret 831 | 832 | section .data 833 | -------------------------------------------------------------------------------- /asm/rich4_config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #define fopen clib_fopen 7 | #define fclose clib_fclose 8 | #define fread clib_fread 9 | #define fwrite clib_fwrite 10 | 11 | #include 12 | #include 13 | #include "rich4_config.h" 14 | #include "rich4_time.h" 15 | 16 | static const rich4_key_t default_hotkeys[28] = 17 | { 18 | {0x26, 0}, {0x27, 0}, {0x28, 0}, {0x25, 0}, {0x0d, 0}, {0x1b, 0}, {0x09, 0}, {0x09, 0}, 19 | {0x59, 0}, {0x4e, 0}, {0x20, 0}, {0x44, 0}, {0x57, 0}, {0x58, 0}, {0x43, 0}, {0x45, 0}, 20 | {0x46, 0}, {0x4d, 0}, {0xbc, 0}, {0xbe, 0}, {0x41, 0}, {0x56, 0}, {0x53, 0}, {0x4c, 0}, 21 | {0x48, 0}, {0x21, 0}, {0x22, 0}, {0x51, 0x11} 22 | }; 23 | 24 | rich4_cfg global_rich4_cfg; // 0x497158 25 | 26 | void rich4_read_config(void) 27 | { 28 | FILE *fp = clib_fopen("RICH4.CFG", "rb"); 29 | if (fp != NULL) { 30 | clib_fread(&global_rich4_cfg, sizeof(global_rich4_cfg), 1, fp); 31 | clib_fclose(fp); 32 | } else { 33 | global_rich4_cfg.game_speed = 1; 34 | global_rich4_cfg.animation = 1; 35 | global_rich4_cfg.music = 4; 36 | global_rich4_cfg.sound_effect = 4; 37 | global_rich4_cfg.auto_save = 1; 38 | global_rich4_cfg.view = 1; 39 | global_rich4_cfg.dummy2[0] = 0; 40 | memcpy(&global_rich4_cfg.hotkeys, default_hotkeys, 41 | sizeof(global_rich4_cfg.hotkeys)); 42 | } 43 | rich4_time t; 44 | get_local_time(&t); 45 | #if USE_RICH4_DATE_DEFAULT 46 | if (t.year < 1998) { 47 | t.year = 1998; 48 | t.month = 1; 49 | t.day = 1; 50 | } else if (t.year > 2010) { 51 | t.year = 2010; 52 | t.month = 1; 53 | t.day = 1; 54 | } 55 | #endif 56 | global_rich4_cfg.year = t.year; 57 | global_rich4_cfg.month = t.month; 58 | global_rich4_cfg.day = t.day; 59 | } 60 | 61 | void rich4_write_config(void) 62 | { 63 | FILE *fp = clib_fopen("RICH4.CFG", "wb"); 64 | if (fp == NULL) 65 | return; 66 | clib_fwrite(&global_rich4_cfg, sizeof(global_rich4_cfg), 1, fp); 67 | } 68 | -------------------------------------------------------------------------------- /asm/rich4_config.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | uint8_t key; 6 | uint8_t mod; 7 | } rich4_key_t; 8 | 9 | typedef struct 10 | { 11 | uint8_t game_speed; 12 | uint8_t animation; 13 | uint8_t music; 14 | uint8_t sound_effect; 15 | uint8_t auto_save; 16 | uint8_t view; 17 | uint8_t dummy1[2]; 18 | uint8_t day; /* offset 8 */ 19 | uint8_t month; 20 | uint16_t year; 21 | uint8_t dummy2[4]; 22 | rich4_key_t hotkeys[28]; /* offset 0x10 */ 23 | } rich4_cfg; 24 | 25 | extern rich4_cfg global_rich4_cfg; 26 | void rich4_read_config(void); 27 | void rich4_write_config(void); 28 | -------------------------------------------------------------------------------- /asm/rich4_crt_mthread.asm: -------------------------------------------------------------------------------- 1 | global __AllocInitThreadData 2 | global __NTAddThread 3 | global __NTRemoveThread 4 | global __NTThreadFini 5 | 6 | extern __imp__GetLastError@0 7 | extern __imp__CloseHandle@4 8 | extern __imp__SetLastError@4 9 | extern __imp__TlsAlloc@0 10 | extern __imp__TlsFree@4 11 | extern __imp__TlsGetValue@4 12 | extern __imp__TlsSetValue@8 13 | extern __imp__GetCurrentThreadId@0 14 | extern clib_free 15 | extern fcn_0045c836 16 | extern fcn_0045e8ca 17 | extern lib_calloc 18 | extern ref_00488f78 19 | extern ref_00488f7c 20 | extern ref_00499954 21 | extern _RWD_osbuild 22 | extern _RWD_osmajor 23 | extern __ThreadDataSize 24 | extern __TlsIndex 25 | extern __fatal_runtime_error 26 | extern fcn_0045c585 27 | extern ref_0046c97c 28 | extern ref_0046c9a1 29 | extern ref_0046c9c9 30 | extern __init_stack_limits 31 | 32 | section .text 33 | 34 | __MultipleThread: 35 | push ebx 36 | push esi 37 | call dword [cs:__imp__GetLastError@0] ; ucall: call dword cs:[0x4623ac] 38 | mov edx, dword [__TlsIndex] ; mov edx, dword [0x488f48] 39 | push edx 40 | mov esi, eax 41 | call dword [cs:__imp__TlsGetValue@4] ; ucall: call dword cs:[0x46241c] 42 | mov ebx, eax 43 | test eax, eax 44 | jne short loc_0045a223 ; jne 0x45a223 45 | call __GetThreadData ; call 0x45c6be 46 | jmp short loc_0045a22e ; jmp 0x45a22e 47 | 48 | loc_0045a223: 49 | cmp byte [eax + 0x53], 0 50 | je short loc_0045a230 ; je 0x45a230 51 | call __ReallocThreadData ; call 0x45c6f5 52 | 53 | loc_0045a22e: 54 | mov ebx, eax 55 | 56 | loc_0045a230: 57 | push esi 58 | call dword [cs:__imp__SetLastError@4] ; ucall: call dword cs:[0x462408] 59 | mov eax, ebx 60 | pop esi 61 | pop ebx 62 | ret 63 | 64 | __AllocInitThreadData: 65 | push ebx 66 | mov ebx, dword [esp + 8] 67 | test ebx, ebx 68 | jne short loc_0045a26d ; jne 0x45a26d 69 | mov edx, dword [__ThreadDataSize] ; mov edx, dword [0x4894b0] 70 | push edx 71 | push 1 72 | call lib_calloc ; call 0x45c62e 73 | add esp, 8 74 | mov ebx, eax 75 | test eax, eax 76 | je short loc_0045a26d ; je 0x45a26d 77 | mov edx, dword [__ThreadDataSize] ; mov edx, dword [0x4894b0] 78 | mov byte [eax + 0x52], 1 79 | mov dword [eax + 0xf0], edx 80 | 81 | loc_0045a26d: 82 | push ebx 83 | call __InitThreadData ; call 0x45c8d7 84 | add esp, 4 85 | mov eax, ebx 86 | pop ebx 87 | ret 88 | 89 | __NTThreadInit: 90 | call dword [cs:__imp__TlsAlloc@0] ; ucall: call dword cs:[0x462414] 91 | mov dx, word [_RWD_osbuild] ; mov dx, word [0x489355] 92 | mov dword [__TlsIndex], eax ; mov dword [0x488f48], eax 93 | cmp dx, 0x8000 94 | jb short loc_0045a2bb ; jb 0x45a2bb 95 | cmp byte [_RWD_osmajor], 4 ; cmp byte [0x489353], 4 96 | jae short loc_0045a2bb ; jae 0x45a2bb 97 | 98 | loc_0045a29d: 99 | mov edx, dword [__TlsIndex] ; mov edx, dword [0x488f48] 100 | cmp edx, 0xffffffff 101 | je short loc_0045a2bb ; je 0x45a2bb 102 | cmp edx, 2 103 | ja short loc_0045a2bb ; ja 0x45a2bb 104 | call dword [cs:__imp__TlsAlloc@0] ; ucall: call dword cs:[0x462414] 105 | mov dword [__TlsIndex], eax ; mov dword [0x488f48], eax 106 | jmp short loc_0045a29d ; jmp 0x45a29d 107 | 108 | loc_0045a2bb: 109 | cmp dword [__TlsIndex], 0xffffffff ; cmp dword [0x488f48], 0xffffffff 110 | setne al 111 | and eax, 0xff 112 | ret 113 | 114 | __NTAddThread: 115 | push ebx 116 | push esi 117 | cmp dword [__TlsIndex], 0xffffffff ; cmp dword [0x488f48], 0xffffffff 118 | jne short loc_0045a2db ; jne 0x45a2db 119 | 120 | loc_0045a2d6: 121 | xor eax, eax 122 | pop esi 123 | pop ebx 124 | ret 125 | 126 | loc_0045a2db: 127 | mov ebx, dword [esp + 0xc] 128 | push ebx 129 | call __AllocInitThreadData ; call 0x45a23d 130 | mov ebx, eax 131 | add esp, 4 132 | test eax, eax 133 | je short loc_0045a321 ; je 0x45a321 134 | push eax 135 | mov ecx, dword [eax + 0xda] 136 | push ecx 137 | call __AddThreadData ; call 0x45c7ca 138 | add esp, 8 139 | test eax, eax 140 | jne short loc_0045a30d ; jne 0x45a30d 141 | push ebx 142 | call clib_free ; call 0x456e11 143 | add esp, 4 144 | jmp short loc_0045a2d6 ; jmp 0x45a2d6 145 | 146 | loc_0045a30d: 147 | push ebx 148 | mov esi, dword [__TlsIndex] ; mov esi, dword [0x488f48] 149 | push esi 150 | call dword [cs:__imp__TlsSetValue@8] ; ucall: call dword cs:[0x462420] 151 | mov eax, 1 152 | 153 | loc_0045a321: 154 | pop esi 155 | pop ebx 156 | ret 157 | 158 | __NTRemoveThread: 159 | push ebx 160 | push esi 161 | mov edx, dword [__TlsIndex] ; mov edx, dword [0x488f48] 162 | cmp edx, 0xffffffff 163 | je short loc_0045a375 ; je 0x45a375 164 | push edx 165 | call dword [cs:__imp__TlsGetValue@4] ; ucall: call dword cs:[0x46241c] 166 | test eax, eax 167 | je short loc_0045a375 ; je 0x45a375 168 | mov ecx, dword [eax + 0xda] 169 | push ecx 170 | mov ebx, dword [eax + 0xde] 171 | call fcn_0045c836 ; call 0x45c836 172 | add esp, 4 173 | push 0 174 | mov esi, dword [__TlsIndex] ; mov esi, dword [0x488f48] 175 | push esi 176 | call dword [cs:__imp__TlsSetValue@8] ; ucall: call dword cs:[0x462420] 177 | test ebx, ebx 178 | je short loc_0045a375 ; je 0x45a375 179 | cmp dword [esp + 0xc], 0 180 | je short loc_0045a375 ; je 0x45a375 181 | push ebx 182 | call dword [cs:__imp__CloseHandle@4] ; ucall: call dword cs:[0x462348] 183 | 184 | loc_0045a375: 185 | pop esi 186 | pop ebx 187 | ret 188 | 189 | __ThreadExit: 190 | push 1 191 | call __NTRemoveThread ; call 0x45a324 192 | add esp, 4 193 | 194 | __NTThreadFini: 195 | mov edx, dword [__TlsIndex] ; mov edx, dword [0x488f48] 196 | cmp edx, 0xffffffff 197 | je short loc_0045a39f ; je 0x45a39f 198 | push edx 199 | call dword [cs:__imp__TlsFree@4] ; ucall: call dword cs:[0x462418] 200 | mov dword [__TlsIndex], 0xffffffff ; mov dword [0x488f48], 0xffffffff 201 | 202 | loc_0045a39f: 203 | ret 204 | 205 | ;; trdlist.c 206 | 207 | __GetThreadData: 208 | push ebx 209 | xor ebx, ebx 210 | push ebx 211 | call __NTAddThread ; call 0x45a2cb 212 | add esp, 4 213 | test eax, eax 214 | je short loc_0045c6de ; je 0x45c6de 215 | mov edx, dword [__TlsIndex] ; mov edx, dword [0x488f48] 216 | push edx 217 | call dword [cs:__imp__TlsGetValue@4] ; ucall: call dword cs:[0x46241c] 218 | mov ebx, eax 219 | 220 | loc_0045c6de: 221 | test ebx, ebx 222 | jne short loc_0045c6f1 ; jne 0x45c6f1 223 | push 1 224 | push ref_0046c97c ; push 0x46c97c 225 | call __fatal_runtime_error ; call 0x45c690 226 | add esp, 8 227 | 228 | loc_0045c6f1: 229 | mov eax, ebx 230 | pop ebx 231 | ret 232 | 233 | __ReallocThreadData: 234 | push ebx 235 | push esi 236 | push edi 237 | push ebp 238 | call dword [ref_00488f78] ; ucall: call dword [0x488f78] 239 | call dword [cs:__imp__GetCurrentThreadId@0] ; ucall: call dword cs:[0x46238c] 240 | mov ebx, dword [ref_00499954] ; mov ebx, dword [0x499954] 241 | mov ebp, eax 242 | jmp short loc_0045c717 ; jmp 0x45c717 243 | 244 | loc_0045c710: 245 | cmp ebp, dword [ebx + 4] 246 | je short loc_0045c71b ; je 0x45c71b 247 | mov ebx, dword [ebx] 248 | 249 | loc_0045c717: 250 | test ebx, ebx 251 | jne short loc_0045c710 ; jne 0x45c710 252 | 253 | loc_0045c71b: 254 | cmp dword [ebx + 0xc], 0 255 | je short loc_0045c74b ; je 0x45c74b 256 | mov edi, dword [__ThreadDataSize] ; mov edi, dword [0x4894b0] 257 | push edi 258 | mov ebp, dword [ebx + 8] 259 | push ebp 260 | call fcn_0045c585 ; call 0x45c585 261 | add esp, 8 262 | mov ebp, eax 263 | test eax, eax 264 | jne short loc_0045c799 ; jne 0x45c799 265 | push 1 266 | push ref_0046c9a1 ; push 0x46c9a1 267 | call __fatal_runtime_error ; call 0x45c690 268 | add esp, 8 269 | jmp short loc_0045c799 ; jmp 0x45c799 270 | 271 | loc_0045c74b: 272 | mov esi, dword [__ThreadDataSize] ; mov esi, dword [0x4894b0] 273 | push esi 274 | push 1 275 | call lib_calloc ; call 0x45c62e 276 | add esp, 8 277 | mov ebp, eax 278 | test eax, eax 279 | jne short loc_0045c771 ; jne 0x45c771 280 | push 1 281 | push ref_0046c9c9 ; push 0x46c9c9 282 | call __fatal_runtime_error ; call 0x45c690 283 | add esp, 8 284 | 285 | loc_0045c771: 286 | mov esi, dword [ebx + 8] 287 | mov edi, ebp 288 | mov ecx, dword [esi + 0xf0] 289 | push es 290 | mov eax, ds 291 | mov es, eax 292 | push edi 293 | mov eax, ecx 294 | shr ecx, 2 295 | repne movsd 296 | mov cl, al 297 | and cl, 3 298 | repne movsb ; repne movsb byte es:[edi], byte ptr [esi] 299 | pop edi 300 | pop es 301 | mov dword [ebx + 0xc], 1 302 | 303 | loc_0045c799: 304 | mov dword [ebx + 8], ebp 305 | mov eax, dword [__ThreadDataSize] ; mov eax, dword [0x4894b0] 306 | push ebp 307 | mov dword [ebp + 0xf0], eax 308 | mov eax, dword [__TlsIndex] ; mov eax, dword [0x488f48] 309 | mov byte [ebp + 0x52], 1 310 | push eax 311 | mov byte [ebp + 0x53], 0 312 | call dword [cs:__imp__TlsSetValue@8] ; ucall: call dword cs:[0x462420] 313 | call dword [ref_00488f7c] ; ucall: call dword [0x488f7c] 314 | mov eax, ebp 315 | pop ebp 316 | pop edi 317 | pop esi 318 | pop ebx 319 | ret 320 | 321 | __AddThreadData: 322 | push ebx 323 | push esi 324 | push edi 325 | mov edi, dword [esp + 0x14] 326 | call dword [ref_00488f78] ; ucall: call dword [0x488f78] 327 | push 0x10 328 | mov esi, 1 329 | push esi 330 | call lib_calloc ; call 0x45c62e 331 | mov ebx, eax 332 | add esp, 8 333 | test eax, eax 334 | je short loc_0045c828 ; je 0x45c828 335 | push edi 336 | call fcn_0045e8ca ; call 0x45e8ca 337 | add esp, 4 338 | test eax, eax 339 | je short loc_0045c807 ; je 0x45c807 340 | push ebx 341 | call clib_free ; call 0x456e11 342 | xor esi, esi 343 | add esp, 4 344 | jmp short loc_0045c82a ; jmp 0x45c82a 345 | 346 | loc_0045c807: 347 | mov eax, dword [esp + 0x10] 348 | mov dword [ebx + 8], edi 349 | mov dword [ebx + 4], eax 350 | xor eax, eax 351 | mov al, byte [edi + 0x52] 352 | mov dword [ebx + 0xc], eax 353 | mov eax, dword [ref_00499954] ; mov eax, dword [0x499954] 354 | mov dword [ref_00499954], ebx ; mov dword [0x499954], ebx 355 | mov dword [ebx], eax 356 | jmp short loc_0045c82a ; jmp 0x45c82a 357 | 358 | loc_0045c828: 359 | xor esi, esi 360 | 361 | loc_0045c82a: 362 | call dword [ref_00488f7c] ; ucall: call dword [0x488f7c] 363 | mov eax, esi 364 | pop edi 365 | pop esi 366 | pop ebx 367 | ret 368 | 369 | ;; mthrdini.c 370 | 371 | __InitThreadData: 372 | push ebx 373 | mov ebx, dword [esp + 8] 374 | test ebx, ebx 375 | je short loc_0045c8ff ; je 0x45c8ff 376 | push 0 377 | push ebx 378 | mov dword [ebx + 0xc], 1 379 | call __init_stack_limits ; call 0x45a666 380 | add esp, 8 381 | call dword [cs:__imp__GetCurrentThreadId@0] ; ucall: call dword cs:[0x46238c] 382 | mov dword [ebx + 0xda], eax 383 | 384 | loc_0045c8ff: 385 | pop ebx 386 | ret 387 | 388 | section .data 389 | 390 | __TlsIndex: 391 | dd 0xffffffff 392 | -------------------------------------------------------------------------------- /asm/rich4_time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include "rich4_time.h" 8 | 9 | void get_local_time(rich4_time *t) 10 | { 11 | SYSTEMTIME st; 12 | GetLocalTime(&st); 13 | t->day = st.wDay; 14 | t->month = st.wMonth; 15 | t->year = st.wYear; 16 | t->dayofweek = st.wDayOfWeek; 17 | } 18 | -------------------------------------------------------------------------------- /asm/rich4_time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | 8 | typedef struct 9 | { 10 | uint8_t day; 11 | uint8_t month; 12 | uint16_t year; 13 | uint16_t dayofweek; 14 | } rich4_time; 15 | 16 | void get_local_time(rich4_time *t); 17 | -------------------------------------------------------------------------------- /asm/stocks.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | const char * name_ptr; 6 | uint16_t f4; 7 | uint8_t f6; 8 | uint8_t f7; 9 | uint16_t f8; 10 | uint16_t f10; 11 | float f12; 12 | float f16; 13 | float f20; 14 | float f24; 15 | float f28; 16 | uint32_t f32; 17 | } stock_info; 18 | 19 | extern stock_info stocks_on_map[]; /* 0x496980 */ 20 | extern stock_info game_stocks[]; /* 0x47f072 */ 21 | 22 | typedef struct 23 | { 24 | int amount; 25 | int _; 26 | } player_stock_info; 27 | 28 | extern player_stock_info player_stocks[]; // 0x4971a0 29 | -------------------------------------------------------------------------------- /asm/stocks_data.c: -------------------------------------------------------------------------------- 1 | #include "stocks.h" 2 | 3 | stock_info game_stocks[96] = { 4 | { "\xa4\xa4\xb0\xea\xab\x48\xb0\x55", 1, 0, 0, 10000, 0, 100.0, 100.0, 100.0, 1.000000, 0.0, 0 }, /* 中国信托 */ 5 | { "\xbb\x4f\xc6\x57\xa4\x48\xb9\xd8", 1, 0, 0, 5000, 0, 40.0, 40.0, 40.0, 0.600000, 0.0, 0 }, /* 台湾人寿 */ 6 | { "\xa4\x6a\xa6\x74\xa6\xca\xb3\x66", 1, 0, 0, 10000, 0, 25.0, 25.0, 25.0, 1.500000, 0.0, 0 }, /* 大宇百货 */ 7 | { "\xa5\x78\x20\xbf\x6e\x20\xb9\x71", 0, 0, 0, 10000, 0, 180.0, 180.0, 180.0, 1.600000, 0.0, 0 }, /* 台 积 电 */ 8 | { "\xa4\x6a\xa6\x74\xb8\xea\xb0\x54", 0, 0, 0, 10000, 0, 80.0, 80.0, 80.0, 1.200000, 0.0, 0 }, /* 大宇资讯 */ 9 | { "\xa5\x78\xc6\x57\xb6\xec\xbd\xa6", 0, 0, 0, 10000, 0, 60.0, 60.0, 60.0, 1.000000, 0.0, 0 }, /* 台湾塑胶 */ 10 | { "\xb8\xce\xb6\xa9\xa8\x54\xa8\xae", 0, 0, 0, 10000, 0, 60.0, 60.0, 60.0, 1.400000, 0.0, 0 }, /* 裕隆汽车 */ 11 | { "\xbb\xb7\xaa\x46\xaf\xbc\xc2\xb4", 0, 0, 0, 10000, 0, 27.0, 27.0, 27.0, 0.900000, 0.0, 0 }, /* 远东纺织 */ 12 | { "\xb2\xce\xa4\x40\xb6\x57\xb0\xd3", 0, 0, 0, 10000, 0, 310.0, 310.0, 310.0, 0.700000, 0.0, 0 }, /* 统一超商 */ 13 | { "\xbe\x5f\x20\xa5\xb9\x20\xa6\xe6", 0, 0, 0, 10000, 0, 66.0, 66.0, 66.0, 1.000000, 0.0, 0 }, /* 震 旦 行 */ 14 | { "\xb5\xdc\x20\xba\xb8\x20\xb4\x49", 0, 0, 0, 10000, 0, 171.0, 171.0, 171.0, 1.400000, 0.0, 0 }, /* 莱 尔 富 */ 15 | { "\xc1\x70\x20\xa6\x58\x20\xb3\xf8", 0, 0, 0, 10000, 0, 280.0, 280.0, 280.0, 0.800000, 0.0, 0 }, /* 联 合 报 */ 16 | { "\xa4\x57\xae\xfc\xbb\xc8\xa6\xe6", 1, 0, 0, 10000, 0, 70.0, 70.0, 70.0, 1.200000, 0.0, 0 }, /* 上海银行 */ 17 | { "\xa4\xa4\xb0\xea\xa4\x48\xb9\xd8", 1, 0, 0, 5000, 0, 36.0, 36.0, 36.0, 1.000000, 0.0, 0 }, /* 中国人寿 */ 18 | { "\xa4\xfd\xa9\xb2\xa4\xab\xa6\xca\xb3\x66", 1, 0, 0, 10000, 0, 20.0, 20.0, 20.0, 1.600000, 0.0, 0 }, /* 王府井百货 */ 19 | { "\xa4\xa4\xb0\xea\xa5\xdb\xaa\x6f", 1, 0, 0, 0, 0, 15.0, 15.0, 15.0, 1.500000, 0.0, 0 }, /* 中国石油 */ 20 | { "\xc1\x70\xb7\x51\xac\xec\xa7\xde", 0, 0, 0, 10000, 0, 300.0, 300.0, 300.0, 2.000000, 0.0, 0 }, /* 联想科技 */ 21 | { "\xb3\xbb\xb7\x73\xad\xb9\xab\x7e", 0, 0, 0, 10000, 0, 296.0, 296.0, 296.0, 1.800000, 0.0, 0 }, /* 顶新食品 */ 22 | { "\xaa\x46\xa4\xe8\xb9\xea\xb7\x7e", 0, 0, 0, 10000, 0, 133.0, 133.0, 133.0, 1.400000, 0.0, 0 }, /* 东方实业 */ 23 | { "\xb6\xd7\xc2\xd7\xc3\xd2\xa8\xe9", 0, 0, 0, 10000, 0, 170.0, 170.0, 170.0, 1.500000, 0.0, 0 }, /* 汇丰证券 */ 24 | { "\xa4\x6a\xbc\x79\xa5\xdb\xaa\x6f", 0, 0, 0, 10000, 0, 121.0, 121.0, 121.0, 0.800000, 0.0, 0 }, /* 大庆石油 */ 25 | { "\xaa\xf8\xab\xb0\xb9\x71\xbe\xf7", 0, 0, 0, 10000, 0, 60.0, 60.0, 60.0, 0.400000, 0.0, 0 }, /* 长城电机 */ 26 | { "\xaa\xf8\xa6\xbf\xab\xd8\xb3\x5d", 0, 0, 0, 10000, 0, 92.0, 92.0, 92.0, 0.600000, 0.0, 0 }, /* 长江建设 */ 27 | { "\xa4\x6a\xb2\xb3\xb3\x6e\xa5\xf3", 0, 0, 0, 10000, 0, 366.0, 366.0, 366.0, 1.000000, 0.0, 0 }, /* 大众软件 */ 28 | { "\xb4\x49\xa4\x68\xbb\xc8\xa6\xe6", 1, 0, 0, 10000, 0, 160.0, 160.0, 160.0, 0.800000, 0.0, 0 }, /* 富士银行 */ 29 | { "\xa4\x54\xa4\xab\xa5\xcd\xa9\x52", 1, 0, 0, 5000, 0, 99.0, 99.0, 99.0, 1.400000, 0.0, 0 }, /* 三井生命 */ 30 | { "\xa4\x54\xb6\x56\xa6\xca\xb3\x66", 1, 0, 0, 10000, 0, 22.0, 22.0, 22.0, 2.000000, 0.0, 0 }, /* 三越百货 */ 31 | { "\xa4\xe9\xb2\xa3\xab\xd8\xb3\x5d", 1, 0, 0, 5000, 0, 28.0, 28.0, 28.0, 2.000000, 0.0, 0 }, /* 日产建设 */ 32 | { "\xa2\xe1\xa2\xd3\xa2\xd5\xa2\xcf", 1, 0, 0, 5000, 0, 300.0, 300.0, 300.0, 1.000000, 0.0, 0 }, /* SEGA */ 33 | { "\xc2\xd7\xa5\xd0\xa8\x54\xa8\xae", 1, 0, 0, 5000, 0, 35.0, 35.0, 35.0, 1.200000, 0.0, 0 }, /* 丰田汽车 */ 34 | { "\xaa\x51\xa4\x55\xb9\x71\xbe\xf7", 0, 0, 0, 10000, 0, 540.0, 540.0, 540.0, 1.000000, 0.0, 0 }, /* 松下电机 */ 35 | { "\xa4\xe9\xa5\xdf\xbe\xf7\xb9\x71", 0, 0, 0, 10000, 0, 830.0, 830.0, 830.0, 1.000000, 0.0, 0 }, /* 日立机电 */ 36 | { "\xa2\xe1\xa2\xdd\xa2\xdc\xa2\xe7", 0, 0, 0, 10000, 0, 300.0, 300.0, 300.0, 1.200000, 0.0, 0 }, /* SONY */ 37 | { "\xa4\x54\xb5\xd9\xa4\x75\xb7\x7e", 0, 0, 0, 10000, 0, 225.0, 225.0, 225.0, 0.700000, 0.0, 0 }, /* 三菱工业 */ 38 | { "\xa5\xf4\xa4\xd1\xb0\xf3", 0, 0, 0, 10000, 0, 300.0, 300.0, 300.0, 1.000000, 0.0, 0 }, /* 任天堂 */ 39 | { "\xbc\x77\xb6\xa1\xae\xd1\xa9\xb1", 0, 0, 0, 10000, 0, 150.0, 150.0, 150.0, 0.800000, 0.0, 0 }, /* 德间书店 */ 40 | { "\xaa\xe1\xba\x58\xbb\xc8\xa6\xe6", 1, 0, 0, 10000, 0, 200.0, 200.0, 200.0, 1.000000, 0.0, 0 }, /* 花旗银行 */ 41 | { "\xb3\xec\xaa\x76\xa8\xc8\xa4\x48\xb9\xd8", 1, 0, 0, 5000, 0, 55.0, 55.0, 55.0, 0.800000, 0.0, 0 }, /* 乔治亚人寿 */ 42 | { "\xc0\xf4\xb2\x79\xa6\xca\xb3\x66", 1, 0, 0, 10000, 0, 20.0, 20.0, 20.0, 2.000000, 0.0, 0 }, /* 环球百货 */ 43 | { "\xc1\x70\xa6\x58\xaf\xe8\xaa\xc5", 1, 0, 0, 5000, 0, 18.0, 18.0, 18.0, 1.000000, 0.0, 0 }, /* 联合航空 */ 44 | { "\xba\xd6\xaf\x53\xa8\x54\xa8\xae", 1, 0, 0, 5000, 0, 16.0, 16.0, 16.0, 1.400000, 0.0, 0 }, /* 福特汽车 */ 45 | { "\xa2\xd7\xa2\xd0\xa2\xdb", 1, 0, 0, 5000, 0, 550.0, 550.0, 550.0, 2.000000, 0.0, 0 }, /* IBM */ 46 | { "\xbc\x77\xa6\x7b\xbb\xf6\xbe\xb9", 0, 0, 0, 10000, 0, 245.0, 245.0, 245.0, 1.500000, 0.0, 0 }, /* 德州仪器 */ 47 | { "\xbc\xaf\xc9\xec\xc3\xb9\xa9\xd4", 0, 0, 0, 10000, 0, 166.0, 166.0, 166.0, 1.300000, 0.0, 0 }, /* 摩扥罗拉 */ 48 | { "\xad\x7d\xa4\x68\xa5\xa7", 0, 0, 0, 10000, 0, 955.0, 955.0, 955.0, 1.400000, 0.0, 0 }, /* 迪士尼 */ 49 | { "\xa5\x69\xa4\x66\xa5\x69\xbc\xd6", 0, 0, 0, 10000, 0, 1030.0, 1030.0, 1030.0, 0.800000, 0.0, 0 }, /* 可口可乐 */ 50 | { "\xb3\xc1\xb7\xed\xb3\xd2", 0, 0, 0, 10000, 0, 1440.0, 1440.0, 1440.0, 1.000000, 0.0, 0 }, /* 麦当劳 */ 51 | { "\xa6\xca\xa8\xc6\xa5\x69\xbc\xd6", 0, 0, 0, 10000, 0, 310.0, 310.0, 310.0, 1.200000, 0.0, 0 }, /* 百事可乐 */ 52 | { "\xa6\xe6\xac\x50\xbb\xc8\xa6\xe6", 1, 0, 0, 10000, 0, 50.0, 50.0, 50.0, 1.000000, 0.0, 0 }, /* 行星银行 */ 53 | { "\xbb\xc8\xaa\x65\xab\x4f\xc0\x49", 1, 0, 0, 5000, 0, 40.0, 40.0, 40.0, 0.600000, 0.0, 0 }, /* 银河保险 */ 54 | { "\xa6\x74\xa9\x7a\xa6\xca\xb3\x66", 1, 0, 0, 10000, 0, 25.0, 25.0, 25.0, 1.500000, 0.0, 0 }, /* 宇宙百货 */ 55 | { "\xa4\xf5\xac\x50\xb2\xbe\xa5\xc1", 0, 0, 0, 10000, 0, 90.0, 90.0, 90.0, 1.600000, 0.0, 0 }, /* 火星移民 */ 56 | { "\xb9\x6b\xa5\xdb\xc4\x71\xb7\x7e", 0, 0, 0, 10000, 0, 45.0, 45.0, 45.0, 1.200000, 0.0, 0 }, /* 陨石矿业 */ 57 | { "\xac\x50\xb2\x79\xb9\x71\xb5\xf8", 0, 0, 0, 10000, 0, 60.0, 60.0, 60.0, 1.000000, 0.0, 0 }, /* 星球电视 */ 58 | { "\xaa\xf7\xac\x50\xac\xec\xa7\xde", 0, 0, 0, 10000, 0, 60.0, 60.0, 60.0, 1.400000, 0.0, 0 }, /* 金星科技 */ 59 | { "\xac\x50\xae\xfc\xb3\x71\xb0\x54", 0, 0, 0, 10000, 0, 27.0, 27.0, 27.0, 0.900000, 0.0, 0 }, /* 星海通讯 */ 60 | { "\xbb\xc8\xaa\x65\xaf\xe8\xb9\x42", 0, 0, 0, 10000, 0, 110.0, 110.0, 110.0, 0.700000, 0.0, 0 }, /* 银河航运 */ 61 | { "\xa4\xeb\xa5\x40\xac\xc9\xae\xc8\xb9\x43", 0, 0, 0, 10000, 0, 66.0, 66.0, 66.0, 1.000000, 0.0, 0 }, /* 月世界旅游 */ 62 | { "\xa6\x74\xa9\x7a\xa6\x61\xb2\xa3", 0, 0, 0, 10000, 0, 71.0, 71.0, 71.0, 1.400000, 0.0, 0 }, /* 宇宙地产 */ 63 | { "\xa4\xd3\xb6\xa7\xaf\xe0\xb9\x71\xa4\x4f", 0, 0, 0, 10000, 0, 80.0, 80.0, 80.0, 0.800000, 0.0, 0 }, /* 太阳能电力 */ 64 | { "\xbb\x45\xc4\x5f\xbb\xc8\xbc\xd3", 1, 0, 0, 10000, 0, 70.0, 70.0, 70.0, 1.200000, 0.0, 0 }, /* 聚宝银楼 */ 65 | { "\xa8\x67\xae\x7b\xc3\xf0\xa7\xbd", 1, 0, 0, 5000, 0, 70.0, 70.0, 70.0, 1.000000, 0.0, 0 }, /* 狂徒镖局 */ 66 | { "\xab\x6e\xa5\x5f\xb3\x66\xb3\xf5", 1, 0, 0, 10000, 0, 20.0, 20.0, 20.0, 1.600000, 0.0, 0 }, /* 南北货场 */ 67 | { "\xa4\xd6\xaa\x4c\xac\xa3", 1, 0, 0, 3000, 0, 250.0, 250.0, 250.0, 1.500000, 0.0, 0 }, /* 少林派 */ 68 | { "\xaa\x5a\xb7\xed\xac\xa3", 1, 0, 0, 3000, 0, 101.0, 101.0, 101.0, 2.000000, 0.0, 0 }, /* 武当派 */ 69 | { "\xb8\xbe\xa4\x73\xac\xa3", 1, 0, 0, 5000, 0, 96.0, 96.0, 96.0, 1.800000, 0.0, 0 }, /* 蜀山派 */ 70 | { "\xb7\x43\xa4\x73\xac\xa3", 1, 0, 0, 6000, 0, 120.0, 120.0, 120.0, 1.400000, 0.0, 0 }, /* 嵩山派 */ 71 | { "\xab\xed\xa4\x73\xac\xa3", 1, 0, 0, 4000, 0, 47.0, 47.0, 47.0, 1.500000, 0.0, 0 }, /* 恒山派 */ 72 | { "\xae\xf5\xa4\x73\xac\xa3", 1, 0, 0, 5000, 0, 40.0, 40.0, 40.0, 0.800000, 0.0, 0 }, /* 泰山派 */ 73 | { "\xbf\xc5\xa4\x73\xac\xa3", 1, 0, 0, 4000, 0, 30.0, 30.0, 30.0, 0.400000, 0.0, 0 }, /* 衡山派 */ 74 | { "\xb5\xd8\xa4\x73\xac\xa3", 1, 0, 0, 5000, 0, 90.0, 90.0, 90.0, 0.600000, 0.0, 0 }, /* 华山派 */ 75 | { "\xb3\x70\xbb\xbb\xab\xc8\xb4\xcc", 1, 0, 0, 4000, 0, 300.0, 300.0, 300.0, 1.000000, 0.0, 0 }, /* 逍遥客栈 */ 76 | { "\xb6\xc0\xaa\xf7\xbb\xc8\xa6\xe6", 1, 0, 0, 10000, 0, 60.0, 60.0, 60.0, 0.800000, 0.0, 0 }, /* 黄金银行 */ 77 | { "\xaa\xce\xc0\x73\xab\x4f\xc0\x49", 1, 0, 0, 5000, 0, 33.0, 33.0, 33.0, 1.400000, 0.0, 0 }, /* 肥龙保险 */ 78 | { "\xad\xb8\xc0\x73\xa6\xca\xb3\x66", 1, 0, 0, 10000, 0, 22.0, 22.0, 22.0, 2.000000, 0.0, 0 }, /* 飞龙百货 */ 79 | { "\xb9\x70\xc0\x73\xb9\x71\xa4\x6c", 0, 0, 0, 10000, 0, 18.0, 18.0, 18.0, 2.000000, 0.0, 0 }, /* 雷龙电子 */ 80 | { "\xa8\xdc\xc3\xb9\xac\xf6\xbc\x76\xb7\x7e", 0, 0, 0, 10000, 0, 100.0, 100.0, 100.0, 1.000000, 0.0, 0 }, /* 侏罗纪影业 */ 81 | { "\xaa\xf8\xa4\xf2\xb6\x48\xaf\xbc\xc2\xb4", 0, 0, 0, 10000, 0, 15.0, 15.0, 15.0, 1.200000, 0.0, 0 }, /* 长毛象纺织 */ 82 | { "\xa8\xb3\xb2\x72\xa8\x54\xa8\xae", 0, 0, 0, 10000, 0, 40.0, 40.0, 40.0, 1.000000, 0.0, 0 }, /* 迅猛汽车 */ 83 | { "\xae\xa3\xc0\x73\xb3\x4a\xad\xb9\xab\x7e", 0, 0, 0, 10000, 0, 30.0, 30.0, 30.0, 1.000000, 0.0, 0 }, /* 恐龙蛋食品 */ 84 | { "\xa4\xf5\xa4\x73\xa9\xa5\xab\x4f\xc0\x49", 0, 0, 0, 10000, 0, 100.0, 100.0, 100.0, 1.200000, 0.0, 0 }, /* 火山岩保险 */ 85 | { "\xa4\x54\xb8\xad\xc2\xce\xa6\xca\xb3\x66", 0, 0, 0, 10000, 0, 25.0, 25.0, 25.0, 0.700000, 0.0, 0 }, /* 三叶虫百货 */ 86 | { "\xa9\x6c\xaf\xaa\xa4\xc6\xa5\xdb", 0, 0, 0, 10000, 0, 100.0, 100.0, 100.0, 1.000000, 0.0, 0 }, /* 始祖化石 */ 87 | { "\xc1\x6c\xc0\x73\xaf\xe8\xaa\xc5", 0, 0, 0, 10000, 0, 50.0, 50.0, 50.0, 0.800000, 0.0, 0 }, /* 翼龙航空 */ 88 | { "\xb0\xb2\xb4\xc1\xbb\xc8\xa6\xe6", 1, 0, 0, 10000, 0, 100.0, 100.0, 100.0, 1.000000, 0.0, 0 }, /* 假期银行 */ 89 | { "\xb0\xb2\xb4\xc1\xa6\xca\xb3\x66", 1, 0, 0, 10000, 0, 33.0, 33.0, 33.0, 0.800000, 0.0, 0 }, /* 假期百货 */ 90 | { "\xa8\x67\xae\x7b\xa4\x6a\xb6\xba\xa9\xb1", 1, 0, 0, 3000, 0, 500.0, 500.0, 500.0, 2.000000, 0.0, 0 }, /* 狂徒大饭店 */ 91 | { "\xbb\xa8\xb5\xd8\xa4\x6a\xb6\xba\xa9\xb1", 1, 0, 0, 5000, 0, 100.0, 100.0, 100.0, 1.000000, 0.0, 0 }, /* 豪华大饭店 */ 92 | { "\xb2\xc4\xa4\x40\xa4\x6a\xb6\xba\xa9\xb1", 1, 0, 0, 5000, 0, 130.0, 130.0, 130.0, 1.400000, 0.0, 0 }, /* 第一大饭店 */ 93 | { "\xaa\xf7\xaa\xf7\xa4\x6a\xb6\xba\xa9\xb1", 1, 0, 0, 5000, 0, 150.0, 150.0, 150.0, 2.000000, 0.0, 0 }, /* 金金大饭店 */ 94 | { "\xa5\x40\xac\xc9\xa4\x6a\xb6\xba\xa9\xb1", 1, 0, 0, 5000, 0, 70.0, 70.0, 70.0, 1.500000, 0.0, 0 }, /* 世界大饭店 */ 95 | { "\xa6\xca\xa8\xc6\xa5\x69\xbc\xd6", 0, 0, 0, 10000, 0, 66.0, 66.0, 66.0, 1.300000, 0.0, 0 }, /* 百事可乐 */ 96 | { "\xa8\x66\xa4\x68\xa5\xa7", 0, 0, 0, 10000, 0, 55.0, 55.0, 55.0, 1.400000, 0.0, 0 }, /* 狄士尼 */ 97 | { "\xa5\x69\xa4\x66\xa5\x69\xbc\xd6", 0, 0, 0, 10000, 0, 30.0, 30.0, 30.0, 0.800000, 0.0, 0 }, /* 可口可乐 */ 98 | { "\xb3\xc1\xb7\xed\xb3\xd2", 0, 0, 0, 10000, 0, 44.0, 44.0, 44.0, 1.000000, 0.0, 0 }, /* 麦当劳 */ 99 | { "\xb7\x52\xad\x7d\xb9\x46", 0, 0, 0, 10000, 0, 30.0, 30.0, 30.0, 1.200000, 0.0, 0 }, /* 爱迪达 */ 100 | }; 101 | 102 | stock_info stocks_on_map[12]; 103 | player_stock_info player_stocks[48]; 104 | -------------------------------------------------------------------------------- /asm/tool.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | const char *name_ptr; 6 | uint8_t max_amount; 7 | uint8_t price; 8 | uint8_t f6; 9 | uint8_t f7; 10 | } rich4_tool; 11 | extern const rich4_tool tool_table[]; 12 | -------------------------------------------------------------------------------- /asm/tool_strings.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | 8 | const char *tool_strings[12][26] = { 9 | { 10 | "#0236\xb4\xc0\xa7\xda\xb0\xa3\xb1\xbc\x0a\xbb\xd9\xc3\xaa\xaa\xab\xa1\x49", /* #0236替我除掉障碍物! */ 11 | "#0237\xa6\xb9\xb8\xf4\xac\x4f\xa7\xda\xb6}\xa1\x41\x0a\xa6\xb9\xbe\xf0\xac\x4f\xa7\xda\xae\xe2\xa1\xe3", /* #0237此路是我开,此树是我栽∼ */ 12 | "#0238\xa4\x70\xa4\xdf\xa1\x49\x0a\xa8\x42\xa8\x42\xa6\x4d\xbe\xf7\xa1\xe3", /* #0238小心!步步危机∼ */ 13 | "#0239\xb0\x65\xa7\x41\xad\xcc\xa4@\xad\xd3\x0a\xa4\x70\xc2\xa7\xaa\xab\xa1\xe3", /* #0239送你们一个小礼物∼ */ 14 | "#0234\xbd\xc4\xb0\xda\xa1\x49\x0a\xb3\xa5\xa4\xfb\xb8\xb9\xa1\x49", /* #0234冲啊!野牛号! */ 15 | "#0235\xb6\xd9\xa1\x49\xc4_\xa8\xa9\xa1\xe3\x0a\xa4@\xb0_\xa5\x68\xb0\xc2\xad\xb7\xa7\x61\xa1\x49", /* #0235嗨!宝贝∼一起去兜风吧! */ 16 | "#0240\xac\xb5\xb1\x6f\xa7\x41\x0a\xc2\xfb\xad\xb8\xaa\xaf\xb8\xf5\xa1\xe3\xa1\xe3", /* #0240炸得你鸡飞狗跳∼∼ */ 17 | "#0241\xad\x6e\xb4\x58\xc2\x49\xa6\xb3\xb4\x58\xc2\x49\xa1\x49\x0a\xb6}\xa1\xe3", /* #0241要几点有几点!开∼ */ 18 | "#0246\xa5\x53\xa7\xcc\xad\xcc\xa1\x49\x0a\xa4\x57\xa4\x75\xa4\x46\xa1\xe3", /* #0246兄弟们!上工了∼ */ 19 | "#0242\xa6\x70\xaa\x47\xa6\x41\xa6^\xa8\xec\x0a\xb1\x71\xab\x65\xa1\xe3", /* #0242如果再回到从前∼ */ 20 | "#0243\xc0\xfe\xb6\xa1\xb2\xbe\xb0\xca\xa1\x49\xa1\x49", /* #0243瞬间移动!! */ 21 | "#0244\xa9\xee\xb0\xa3\xa4\x6a\xb6\xa4\xa8\xd3\xa4\x46\xa1\x49", /* #0244拆除大队来了! */ 22 | "#0245\xa6\x55\xa1\xe3\xa6\xec\xa1\xe3\xc6[\xa1\xe3\xb2\xb3\x0a\xa1\x44\xa1\x44\xa1\x44\xa1\x44\xa1\x43", /* #0245各∼位∼观∼众....。 */ 23 | NULL, 24 | "#0247\xbd\xd6\xb4\xb1\xbe\xd7\xa7\xda\x0a\xa5\x68\xb8\xf4\xa1\x48\xa1\x49", /* #0247谁敢挡我去路?! */ 25 | "#0248\xbd\xd6\xb3\x6f\xbb\xf2\xaf\xca\xbc\x77\xa1\x48\xa1\x49", /* #0248谁这么缺德?! */ 26 | "#0249\xa7\xda\xa4\xa3\xad\x6e\xa1\xe3\xa1\xe3\xa1\xe3", /* #0249我不要∼∼∼ */ 27 | NULL, 28 | NULL, 29 | NULL, 30 | NULL, 31 | NULL, 32 | NULL, 33 | NULL, 34 | NULL, 35 | NULL, 36 | }, 37 | { 38 | "#0252\xbd\xc4\xb0\xda\xa1\x49\xc4_\xa8\xa9\xa1\x49", /* #0252冲啊!宝贝! */ 39 | "#0253\xb9\x44\xb8\xf4\xac\x49\xa4\x75\xa1\xe3", /* #0253道路施工∼ */ 40 | "#0254\xbc\x48\xbc\x48\xa1\x49", /* #0254嘻嘻! */ 41 | "#0255\xb0\x65\xa7\x41\xa4@\xad\xd3\x0a\xb7\x52\xaa\xba\xc2\xa7\xaa\xab\xa1\xe3", /* #0255送你一个爱的礼物∼ */ 42 | "#0250\xa8\x53\xc0\x64\xbe\x6d\x0a\xb4\x4e\xc3\x4d\xa8\xae\xa7\x61\xa1\x49", /* #0250没骆驼就骑车吧! */ 43 | "#0251\xa7\xda\xac\x4f\xa6\xb3\xa8\xae\xb6\xa5\xaf\xc5\xa1\x49", /* #0251我是有车阶级! */ 44 | "#0256\xba\xcb\xb7\xc7\xa1\x41\xb5\x6f\xae\x67\xa1\x49", /* #0256瞄准,发射! */ 45 | "#0257\xa8\xd3\xad\xd3\xa9\xaf\xb9\x42\x0a\xbc\xc6\xa6\x72\xa7\x61\xa1\x49", /* #0257来个幸运数字吧! */ 46 | "#0262\xb6}\xa4\x75\xa4\x6a\xa6\x4e\xa1\xe3", /* #0262开工大吉∼ */ 47 | "#0258\xa1\x75\xa6^\xa8\xec\xa5\xbc\xa8\xd3\xa1\x76\x0a\xac\xdd\xb9\x4c\xb6\xdc\xa1\x48", /* #0258「回到未来」看过吗? */ 48 | "#0259\xb7\x52\xb7\x68\xa4\xb0\xbb\xf2\x0a\xb4\x4e\xb7\x68\xa4\xb0\xbb\xf2\xa1\x49", /* #0259爱搬什么就搬什么! */ 49 | "#0260\xa7\xda\xc3\x68\xa9\xc0\xbc\x73\xc1\xef\x0a\xaa\xba\xa8\x46\xba\x7a\xa1\xe3", /* #0260我怀念广阔的沙漠∼ */ 50 | "#0261\xac\xdd\xa7\xda\xaa\xba\x0a\xaf\xb5\xb1\x4b\xaa\x5a\xbe\xb9\xa1\xe3", /* #0261看我的秘密武器∼ */ 51 | NULL, 52 | "#0263\xb3\x51\xbe\xd7\xa6\xed\xa4\x46\xa1\xe3", /* #0263被挡住了∼ */ 53 | "#0264\xa7\xb9\xb3\x4a\xa4\x46\xa1\xe3", /* #0264完蛋了∼ */ 54 | "#0265\xa7\xda\xab\xe7\xbb\xf2\xb3\x6f\xbb\xf2\xb0\x49\xa1\xe3", /* #0265我怎么这么衰∼ */ 55 | NULL, 56 | NULL, 57 | NULL, 58 | NULL, 59 | NULL, 60 | NULL, 61 | NULL, 62 | NULL, 63 | NULL, 64 | }, 65 | { 66 | "#0268\xbd\xc4\xb0\xda\xa1\xe3\x0a\xb6}\xb8\xf4\xa5\xfd\xbe\x57\xa1\x49", /* #0268冲啊∼开路先锋! */ 67 | "#0269\xbd\xd6\xb3\xa3\xa7\x4f\xb7\x51\xb9\x4c\xa1\x49", /* #0269谁都别想过! */ 68 | "#0270\xbd\xd6\xbd\xf2\xa8\xec\xbd\xd6\xad\xcb\xb7\xb0\xa1\x49", /* #0270谁踩到谁倒楣! */ 69 | "#0271\xad\x6e\xa9\x52\xaa\xba\x0a\xb4\x4e\xa7\x4f\xb9\x4c\xa8\xd3\xa1\x49", /* #0271要命的就别过来! */ 70 | "#0266\xa8\x53\xac\xdd\xb9\x4c\xa7\xd4\xaa\xcc\x0a\xc3\x4d\xbe\xf7\xa8\xae\xb0\xda\xa1\x48", /* #0266没看过忍者骑机车啊? */ 71 | "#0267\xab\xd3\xa7\x61\xa1\x49", /* #0267帅吧! */ 72 | "#0272\xa4\xa3\xb7\x51\xa6\xba\xaa\xba\x0a\xbe\x61\xc3\xe4\xaf\xb8\xa1\xe3", /* #0272不想死的靠边站∼ */ 73 | "#0273\xa5\xbc\xa8\xd3\xb4\x78\xb4\xa4\xa6\x62\x0a\xa6\xdb\xa4\x76\xa4\xe2\xa4\xa4\xa1\x43", /* #0273未来掌握在自己手中。 */ 74 | "#0278\xb7\xc7\xb3\xc6\xa4\x6a\xbf\xb3\xa4\x67\xa4\xec\xa1\xe3", /* #0278准备大兴土木∼ */ 75 | "#0274\xa7\xda\xaf\x75\xc3\x68\xa9\xc0\x0a\xa5\x48\xab\x65\xaa\xba\xa4\xe9\xa4\x6c\xa1\x43", /* #0274我真怀念以前的日子。 */ 76 | "#0275\xac\xec\xa7\xde\xaa\xba\xb5\xb2\xb4\xb9\xa1\xe3", /* #0275科技的结晶∼ */ 77 | "#0276\xc5\xfd\xa7\xda\xa8\xd3\xb6}\xa9\xdd\x0a\xa4\x48\xa5\xcd\xaa\xba\xa4\x6a\xb9\x44\xa1\xe3", /* #0276让我来开拓人生的大道∼ */ 78 | "#0277\xac\xdd\xa7\xda\xaa\xba\x0a\xb2\xd7\xb7\xa5\xa5\xb2\xb1\xfe\xa7\xde\xa1\xe3\xa1\xe3", /* #0277看我的终极必杀技∼∼ */ 79 | NULL, 80 | "#0279\xa7\x4f\xc4\x64\xa7\xda\xa1\x49", /* #0279别拦我! */ 81 | "#0280\xa7\xda\xba\x47\xa4\x46\xa1\xe3", /* #0280我惨了∼ */ 82 | "#0281\xa7\xd6\xa5\xe1\xb5\xb9\xa7\x4f\xa4\x48\xa1\x49", /* #0281快丢给别人! */ 83 | NULL, 84 | NULL, 85 | NULL, 86 | NULL, 87 | NULL, 88 | NULL, 89 | NULL, 90 | NULL, 91 | NULL, 92 | }, 93 | { 94 | "#0284\xab\xbd\xab\xbd\xa1\x49\x0a\xa5\x68\xc0\xb0\xa7\xda\xb6}\xb8\xf4\xa7\x61\xa1\x49", /* #0284娃娃!去帮我开路吧! */ 95 | "#0285\xac\xdd\xa7\xda\xaa\xba\xa1\x49\xa1\x49", /* #0285看我的!! */ 96 | "#0286\xbc\x4b\xbc\x4b\xbc\x4b\xa1\xe3", /* #0286嘿嘿嘿∼ */ 97 | "#0287\xa7\xda\xa4\x53\xad\x6e\xae`\xa4\x48\xa4\x46\xa1\x41\x0a\xbc\x48\xbc\x48\xa1\xe3", /* #0287我又要害人了,嘻嘻∼ */ 98 | "#0282\xac[\xa6\xa1\xa4\x51\xa8\xac\xa7\x61\xa1\x49", /* #0282架式十足吧! */ 99 | "#0283\xc3\x69\xb1\x6f\xa8\xab\xb8\xf4\xa1\xe3", /* #0283懒得走路∼ */ 100 | "#0288\xac\xdd\xa7\xda\xaa\xba\x0a\xa4\xec\xc4\xf5\xad\xb8\xbc\x75\xa1\x49", /* #0288看我的木兰飞弹! */ 101 | "#0289\xa6\xd1\xae\x51\x0a\xaa\xb1\xaa\xb1\xa4\x51\xa4\x4b\xb0\xd5\xa1\xe3", /* #0289老娘玩玩十八啦∼ */ 102 | "#0294\xb7\x46\xac\xa1\xa7\x61\xa1\x49\x0a\xa7\xda\xaa\xba\xa5\xa3\xc1\xf5\xa1\xe3", /* #0294干活吧!我的奴隶∼ */ 103 | "#0290\xad\xfc\xa1\x49\x0a\xc1\xd9\xac\x4f\xb1\x71\xab\x65\xa6\x6e\xa1\x43", /* #0290唉!还是从前好。 */ 104 | "#0291\xb0\xae\xa9[\xa4\x6a\xae\xbf\xb2\xbe\xa1\x49", /* #0291乾坤大挪移! */ 105 | "#0292\xb9\x48\xb3\xb9\xab\xd8\xbf\x76\x0a\xab\xe7\xbb\xf2\xa8\x53\xa4\x48\xba\xde\xb0\xda\xa1\x48", /* #0292违章建筑怎么没人管啊? */ 106 | "#0293\xa5@\xac\xc9\xa5\xbd\xa4\xe9\xa8\xec\xb9\xc6\xa1\xe3", /* #0293世界末日到喽∼ */ 107 | NULL, 108 | "#0295\xa4\xc4\xaf}\xb5\xb7\xc4\xfb\xa4\x46\xa1\xe3", /* #0295勾破丝袜了∼ */ 109 | "#0296\xb0\xda\xa1\x49\x0a\xa7\xda\xaa\xba\xad\xbb\xa9`\xa8\xe0\xa1\xe3", /* #0296啊!我的香奈儿∼ */ 110 | "#0297\xab\x7a\xa1\xe3\x0a\xa7\xd6\xad\x6e\xc3\x7a\xa4\x46\xa1\x49", /* #0297哇∼快要爆了! */ 111 | NULL, 112 | NULL, 113 | NULL, 114 | NULL, 115 | NULL, 116 | NULL, 117 | NULL, 118 | NULL, 119 | NULL, 120 | }, 121 | { 122 | "#0300\xa9\x49\xa5\xec\xa5\x68\xa1\xe3", /* #0300呼伊去∼ */ 123 | "#0301\xa5\xd2\xa7\xda\xad\xe1\xab\xa8", /* #0301甲我冻咧 */ 124 | "#0302\xa4\x6a\xae\x61\xa5\x64\xaa`\xb7\x4e\xa3\xb0\xa1\x49", /* #0302大家卡注意ㄟ! */ 125 | "#0303\xac\xdd\xbd\xd6\xa4\x48\xa5\x64\xb0\x49\xa1\x48", /* #0303看谁人卡衰? */ 126 | "#0298\xc3\x4d\xbc\x51\xae\x67\xc5\x4b\xb0\xa8\x0a\xa8\xd3\xa5\x68\xa1\x49", /* #0298骑喷射铁马来去! */ 127 | "#0299\xa6\xd1\xa5\xeb\xb0\xda\x0a\xa5\xbc\xb3\xf4\xb5\xdb\xa5\xce\xa6\xe6\xa3\xb0\xa1\x49", /* #0299老伙啊未堪著用行ㄟ! */ 128 | "#0304\xa5\x64\xa6\xb3\xae\xf0\xbe\x7a\xad\x43\xa1\x49", /* #0304卡有气魄耶! */ 129 | "#0305\xb7\x6e\xb4\x58\xc2\x49\xa5\x64\xa6\x6e\xa1\x48", /* #0305摇几点卡好? */ 130 | "#0310\xa5\x53\xa7\xcc\xb0\xda\xa1\xe3\x0a\xa5\x64\xa5\xb4\xab\xf7\xa3\xb0\xa1\x49", /* #0310兄弟啊∼卡打拼ㄟ! */ 131 | "#0306\xe5\x46\xba\xe2\xe5\x46\xba\xe2\xa1\x41\x0a\xad\xab\xa8\xd3\xb0\xd5", /* #0306呒算呒算,重来啦 */ 132 | "#0307\xb3\x6f\xac\x4f\xbd\xbc\xa6\xcc\xa1\x48", /* #0307这是虾米? */ 133 | "#0308\xa4\x48\xa7\xec\xad\xed\xa9\xee\xa1\xe3", /* #0308人抓厝拆∼ */ 134 | "#0309\xa5\x47\xa7\xda\xc3\x7a\xa8\xec\x0a\xb4\x4e\xa6\x59\xa4\x4f\xa4\x46\xb3\xe1\xa1\x49", /* #0309乎我爆到就吃力了喔! */ 135 | NULL, 136 | "#0311\xb3\xc1\xad\xe1\xb8\xf4\xb0\xd5\xa1\x49", /* #0311麦冻路啦! */ 137 | "#0312\xbd\xd6\xa4\x48\xa9\xf1\xaa\xba\xa1\x49\xa1\x49\xa1\x49", /* #0312谁人放的!!! */ 138 | "#0313\xb5\x55\xa6\xba\xa6_\xa5\x4a\xa1\x49", /* #0313猴死囝仔! */ 139 | NULL, 140 | NULL, 141 | NULL, 142 | NULL, 143 | NULL, 144 | NULL, 145 | NULL, 146 | NULL, 147 | NULL, 148 | }, 149 | { 150 | "#0316\xb4\xc0\xa7\xda\xb6}\xb8\xf4\xa7\x61\xa1\x49\x0a\xab\xbd\xab\xbd\xa7\x4c\xa1\x49", /* #0316替我开路吧!娃娃兵! */ 151 | "#0317\xa5\xf4\xa6\xf3\xa4\x48\x0a\xb3\xa3\xa4\xa3\xb3\x5c\xb3\x71\xb9\x4c\xa1\x43", /* #0317任何人都不许通过。 */ 152 | "#0318\xa7\x4f\xa9\xc7\xa7\xda\xa1\x49\xa1\x49", /* #0318别怪我!! */ 153 | "#0319\xad\xcb\xbc\xc6\xad\x70\xae\xc9\xb6}\xa9\x6c\xa1\xe3", /* #0319倒数计时开始∼ */ 154 | "#0314\xad\xbb\xa8\xae\xb0\x74\xac\xfc\xa4\x48\xa1\xe3", /* #0314香车配美人∼ */ 155 | "#0315\xa5\xbb\xa4\xbd\xa5\x44\x0a\xc1\xd9\xa4\xed\xad\xd3\xa5\x71\xbe\xf7\xa1\xe3", /* #0315本公主还欠个司机∼ */ 156 | "#0320\xa7\x41\xad\xcc\x0a\xa4\x6a\xc3\xf8\xc1{\xc0\x59\xa4\x46\xa1\x49", /* #0320你们大难临头了! */ 157 | "#0321\xa7\xda\xaa\xba\x0a\xa9\xaf\xb9\x42\xbc\xc6\xa6\x72\xac\x4f\xa1\x48", /* #0321我的幸运数字是? */ 158 | "#0326\xb6\xd4\xa7\xd6\xc2\x49\xa1\x49\x0a\xa5\xbb\xa4\xbd\xa5\x44\x0a\xb7|\xbf\xcb\xa6\xdb\xc5\xe7\xa6\xac\xa1\x49", /* #0326勤快点!本公主会亲自验收! */ 159 | "#0322\xac\x51\xa4\xe9\xa6\x68\xbb\xf2\xac\xfc\xa6\x6e\xa1\xe3", /* #0322昨日多么美好∼ */ 160 | "#0323\xb7\x51\xa4\xa3\xa8\xec\x0a\xa6\xb3\xb3\x6f\xa4@\xa9\xdb\xa7\x61\xa1\x48", /* #0323想不到有这一招吧? */ 161 | "#0324\xa5\xbb\xa4\xbd\xa5\x44\x0a\xad\x6e\xa4@\xb8\xf4\xa9\xee\xb9\x4c\xa5\x68\xa1\xe3", /* #0324本公主要一路拆过去∼ */ 162 | "#0325\xa4\x48\xa4\xa3\xac\xb0\xa4\x76\xa1\x41\x0a\xa4\xd1\xb8\xdd\xa6\x61\xb7\xc0\xa1\xe3", /* #0325人不为己,天诛地灭∼ */ 163 | NULL, 164 | "#0327\xbd\xd6\xb4\xb1\xbe\xd7\xa5\xbb\xa4\xbd\xa5\x44\xa1\x48", /* #0327谁敢挡本公主? */ 165 | "#0328\xa4\xa3\xb7|\xa7\x61\xa1\x48\xa1\x49", /* #0328不会吧?! */ 166 | "#0329\xbd\xd6\xa8\xd3\xa7\xe2\xa5\xa6\xae\xb3\xa8\xab\xa1\x48", /* #0329谁来把它拿走? */ 167 | NULL, 168 | NULL, 169 | NULL, 170 | NULL, 171 | NULL, 172 | NULL, 173 | NULL, 174 | NULL, 175 | NULL, 176 | }, 177 | { 178 | "#0332\xb9\xcd\xb9\xcd\xb9\xcd\xa1\x41\x0a\xa5\xe6\xb5\xb9\xa7\xda\xa8\xd3\xa1\x49", /* #0332哔哔哔,交给我来! */ 179 | "#0333\xbd\xd0\xba\x43\xa1\xe3\xba\x43\xa1\xe3\x0a\xa6\x61\xab~\xa8\xfd\xa7\x61\xa1\x49", /* #0333请慢∼慢∼地品味吧! */ 180 | "#0334\xbd\xd0\xba\x43\xa1\xe3\xba\x43\xa1\xe3\x0a\xa8\xab\xae@\xa1\x49", /* #0334请慢∼慢∼走哦! */ 181 | "#0335\xa8\xfe\xa8\xfe\xa1\x41\xa6\x6e\xb4\xc1\xab\xdd\xa1\x49", /* #0335呵呵,好期待! */ 182 | "#0330\xa5\x68\xa7\x61\xa1\x41\x0a\xa7\xda\xaa\xba\x48\x4f\x4e\x44\x41\xa1\x49", /* #0330去吧,我的HONDA! */ 183 | "#0331\xa5\x68\xa7\x61\xa1\x41\x0a\xa7\xda\xaa\xba\x54\x4f\x59\x4f\x54\x41\xa1\x49", /* #0331去吧,我的TOYOTA! */ 184 | "#0336\xa5\x68\xa7\x61\xa1\x41\x0a\xa7\xda\xaa\xba\xad\xb8\xbc\x75\xa1\x49", /* #0336去吧,我的飞弹! */ 185 | "#0337\xa6\x6e\xa1\x41\x0a\xa5\xbb\xa4\x6a\xa4\x48\xad\x6e\xa8\xab\xa4\x46\xa1\x49", /* #0337好,本大人要走了! */ 186 | "#0342\xb8\xd3\xa7\xda\xa4\x57\xb3\xf5\xa4\x46\xa1\x49", /* #0342该我上场了! */ 187 | "#0338\xad\xb8\xa7\x72\xad\xb8\xa7\x72\xa1\x41\x0a\xa6^\xa8\xec\xb9\x4c\xa5\x68\xa1\xe3", /* #0338飞呀飞呀,回到过去∼ */ 188 | "#0339\xaf\x75\xa4\xe8\xab\x4b\xaa\xba\xb3\xc3\xa5\xeb", /* #0339真方便的家伙 */ 189 | "#0340\xad\xf3\xa1\x41\xa9\xee\xa4\x46\xa7\x41\xa1\x49", /* #0340哼,拆了你! */ 190 | "#0341\xa5\x68\xa1\x41\xae\xd6\xa4\x6c\xbc\x75\xa1\x49", /* #0341去,核子弹! */ 191 | NULL, 192 | "#0343\xb0\xb1\xa4\x55\xa8\xd3\xa4\x46\xa1\x49", /* #0343停下来了! */ 193 | "#0344\xaf\x62\xa5\xcd\xa1\x49", /* #0344畜生! */ 194 | "#0345\xb6\xe3\xab\x7a\xa1\xe3\xa1\xe3\xa1\x49", /* #0345呜哇∼∼! */ 195 | NULL, 196 | NULL, 197 | NULL, 198 | NULL, 199 | NULL, 200 | NULL, 201 | NULL, 202 | NULL, 203 | NULL, 204 | }, 205 | { 206 | "#0348\xa6\x6e\xa6\x68\xaa\x46\xa6\xe8\x0a\xbe\xd7\xb8\xf4\xb3\xe1\xa1\x49", /* #0348好多东西挡路喔! */ 207 | "#0349\xa6\xb9\xb8\xf4\xa4\xa3\xb3\x71\xa1\x49\xa1\x49\xa1\x49", /* #0349此路不通!!! */ 208 | "#0350\xb0\x65\xa7\x41\xa4@\xa5\xf7\x0a\xb7\x52\xaa\xba\xc2\xa7\xaa\xab\xa1\xe3", /* #0350送你一份爱的礼物∼ */ 209 | "#0351\xa4\x70\xa4\xdf\x0a\xa4\xa3\xad\x6e\xbd\xf2\xa8\xec\xa4\x46\xb3\xe1\xa1\x49", /* #0351小心不要踩到了喔! */ 210 | "#0346\xa7\xda\xb7|\x0a\xb4\xee\xb3\x74\xba\x43\xa6\xe6\xaa\xba\xa1\x49", /* #0346我会减速慢行的! */ 211 | "#0347\xa7\xda\xb7|\x0a\xbf\xed\xa6\x75\xa5\xe6\xb3\x71\xb3\x57\xab\x68\xa1\x49", /* #0347我会遵守交通规则! */ 212 | "#0352\xb3\xf8\xa4\xb3\xaa\xba\xae\xc9\xad\xd4\x0a\xa8\xec\xa4\x46\xa1\x49", /* #0352报仇的时候到了! */ 213 | "#0353\xb2\x71\xb2\x71\xac\xdd\x0a\xa7\xda\xad\x6e\xa8\xab\xb4\x58\xa8\x42\xa1\x48", /* #0353猜猜看我要走几步? */ 214 | "#0358\xbb\x5c\xb1\x6f\xb6\x56\xb0\xaa\xb6\x56\xa6\x6e\xa1\x49", /* #0358盖得越高越好! */ 215 | "#0354\xb9\x42\xae\xf0\xa4\xd3\xae\x74\xa4\x46\xa1\x49", /* #0354运气太差了! */ 216 | "#0355\xb3\x6f\xbe\xf7\xbe\xb9\x0a\xab\xdc\xaf\xab\xa9_\xb3\xe1\xa1\x49", /* #0355这机器很神奇喔! */ 217 | "#0356\xbb\xb0\xa7\xd6\xc2\xf7\xb6}\xb4\x4e\xa4\xa3\xb7|\x0a\xa6\xb3\xa4\x48\xa8\xfc\xb6\xcb\xa1\x49\xa1\x49", /* #0356赶快离开就不会有人受伤!! */ 218 | "#0357\xae`\xb9\x4c\xa7\xda\xaa\xba\xa4\x48\x0a\xb7\xed\xa4\xdf\xa4\x46\xa1\xe3", /* #0357害过我的人当心了∼ */ 219 | NULL, 220 | "#0359\xbd\xd6\xb3\x6f\xbb\xf2\xb5\x4c\xb2\xe1\xa1\x48\xa1\x49", /* #0359谁这么无聊?! */ 221 | "#0360\xa7\xda\xab\xe7\xbb\xf2\x0a\xb3\x6f\xbb\xf2\xa4\xa3\xa4\x70\xa4\xdf\xa1\x48\xa1\x49", /* #0360我怎么这么不小心?! */ 222 | "#0361\xae`\xa4\x48\xba\xeb\xa1\x49\xa1\x49", /* #0361害人精!! */ 223 | NULL, 224 | NULL, 225 | NULL, 226 | NULL, 227 | NULL, 228 | NULL, 229 | NULL, 230 | NULL, 231 | NULL, 232 | }, 233 | { 234 | "#0364\xbd\xc4\xb0\xda\xa1\x49", /* #0364冲啊! */ 235 | "#0365\xa5\xe6\xb3\x71\xba\xde\xa8\xee\xa1\x49", /* #0365交通管制! */ 236 | "#0366\xa7\xda\xa4\xb0\xbb\xf2\xb3\xa3\xa8\x53\xb0\xb5\xa1\xe3", /* #0366我什么都没做∼ */ 237 | "#0367\xa8\x53\xa4\x48\xac\xdd\xa8\xec\xa7\x61\xa1\x48", /* #0367没人看到吧? */ 238 | "#0362\xb3\xe1\xa1\xe3\xa1\xe3\xa1\xe3\x0a\xb3\xe1\xa1\xe3\xa1\xe3\xa1\xe3", /* #0362喔∼∼∼喔∼∼∼ */ 239 | "#0363\xad\x4a\xc5\xcd\xbd\x4d\xb7\x64\x0a\xad\x4a\xc5\xcd\xbd\x4d\xb7\x64\xa1\xe3", /* #0363胡搅瞎搞胡搅瞎搞∼ */ 240 | "#0368\xba\xcb\xb7\xc7\xa5\xd8\xbc\xd0\xa1\x49\xa1\x49", /* #0368瞄准目标!! */ 241 | "#0369\xc0\x48\xa4\xdf\xa9\xd2\xb1\xfd\x0a\xa6\xdb\xa5\xd1\xa6\xdb\xa6\x62\xa1\x49", /* #0369随心所欲自由自在! */ 242 | "#0374\xb0\xca\xa7@\xa7\xd6\xa4@\xc2\x49\xa1\x49\xa1\x49", /* #0374动作快一点!! */ 243 | "#0370\xae\xc9\xa5\xfa\xad\xcb\xac\x79\xb9\xc6\xa1\x49", /* #0370时光倒流喽! */ 244 | "#0371\xb3\x6f\xad\x6e\xab\xe7\xbb\xf2\xa5\xce\xb0\xda\xa1\x48", /* #0371这要怎么用啊? */ 245 | "#0372\xae\xb3\xa7\x41\xad\xcc\xa8\xd3\xb6}\xa4\x4d\xa1\x49", /* #0372拿你们来开刀! */ 246 | "#0373\xa7\xda\xa9\xf1\xb7\xcf\xa4\xf5\x0a\xb5\xb9\xa4\x6a\xae\x61\xac\xdd\xa1\x49", /* #0373我放烟火给大家看! */ 247 | NULL, 248 | "#0375\xa7\xda\xb0\xb1\xa1\xe3", /* #0375我停∼ */ 249 | "#0376\xaf\x51\xab}\xa6\x6e\xa5\x69\xbc\xa6\xb3\xe1\xa1\x49", /* #0376乌咪好可怜喔! */ 250 | "#0377\xa7\xd6\xc3\x7a\xac\xb5\xa4\x46\xb0\xd5\xa1\x49\xa1\x49", /* #0377快爆炸了啦!! */ 251 | NULL, 252 | NULL, 253 | NULL, 254 | NULL, 255 | NULL, 256 | NULL, 257 | NULL, 258 | NULL, 259 | NULL, 260 | }, 261 | { 262 | "#0380\xa4\x70\xa5\x69\xb7\x52\xa1\x41\xa5\x68\xa7\x61", /* #0380小可爱,去吧 */ 263 | "#0381\xb6\xa2\xa4\x48\xa4\xee\xa8\x42\xa1\x49", /* #0381闲人止步! */ 264 | "#0382\xa7\x4f\xa4\x6a\xb7\x4e\xa7\x72", /* #0382别大意呀 */ 265 | "#0383\xa6\x59\xc1\xfb\xb3\x4a\xa7\x61", /* #0383吃颗蛋吧 */ 266 | "#0378\xa5\xe6\xb3\x71\xa6\x77\xa5\xfe\x0a\xad\x6e\xaa`\xb7\x4e\xa1\x49", /* #0378交通安全要注意! */ 267 | "#0379\xa7\xda\xb3\xdf\xc5\x77\x0a\xb0\x6c\xa8\x44\xb3\x74\xab\xd7\xb7\x50\xa1\x49", /* #0379我喜欢追求速度感! */ 268 | "#0384\xbd\xe0\xa7\x41\xa4@\xaa\x54\xad\xb8\xbc\x75\xa1\x49", /* #0384赏你一枚飞弹! */ 269 | "#0385\xa7\xda\xa5\x69\xa5\x48\xa5\x68\x0a\xb7\x51\xa5\x68\xaa\xba\xa6\x61\xa4\xe8\xa4\x46\xa1\x49", /* #0385我可以去想去的地方了! */ 270 | "#0390\xa7\x41\xad\xcc\xbf\xec\xa8\xc6\x0a\xa7\xda\xa9\xf1\xa4\xdf\xa1\xe3", /* #0390你们办事我放心∼ */ 271 | "#0386\xad\xcb\xb0\x68\xa4@\xa6^\xa6\x58\xa1\x49\xa1\x49", /* #0386倒退一回合!! */ 272 | "#0387\xb1\x6f\xa4\xa7\xa4\xa3\xa9\xf6\xa1\x41\x0a\xb7\x51\xb2\x4d\xb7\xa1\xa6\x41\xa5\xce\xa1\x49", /* #0387得之不易,想清楚再用! */ 273 | "#0388\xa7\xda\xa8\xd3\xc0\xcb\xb4\xfa\xa4\x6a\xae\x61\xaa\xba\x0a\xa9\xd0\xa4\x6c\xb0\xed\xa4\xa3\xb0\xed\xa9\x54\xa1\x48", /* #0388我来检测大家的房子坚不坚固? */ 274 | "#0389\xb9\xef\xbc\xc4\xa4\x48\xa4\xaf\xb7\x4f\xa1\x41\x0a\xb4\x4e\xac\x4f\xb9\xef\xa6\xdb\xa4\x76\xb4\xdd\xa7\xd4", /* #0389对敌人仁慈,就是对自己残忍 */ 275 | NULL, 276 | "#0391\xa6\xb3\xb0\xf7\xbe\xf7\xa8\xae\xa1\x49\xa1\x49", /* #0391有够机车!! */ 277 | "#0392\xaf\x75\xad\xcb\xbe`\xa1\x49\xa1\x49", /* #0392真倒霉!! */ 278 | "#0393\xbd\xd6\xa8\xd3\xb1\xb5\xa4\xe2\xa1\xe3\xa1\xe3", /* #0393谁来接手∼∼ */ 279 | NULL, 280 | NULL, 281 | NULL, 282 | NULL, 283 | NULL, 284 | NULL, 285 | NULL, 286 | NULL, 287 | NULL, 288 | }, 289 | { 290 | "#0396\xbd\xc4\xa7\x72\xa1\x49\xbd\xc4\xa7\x72\xa1\x49", /* #0396冲呀!冲呀! */ 291 | "#0397\xb8\x54\xa4\xee\xb3\x71\xa6\xe6\xa1\x49", /* #0397禁止通行! */ 292 | "#0398\xaa`\xb7\x4e\xa1\x49", /* #0398注意! */ 293 | "#0399\xa4\x70\xa4\xdf\xc2\x49\xa1\x49", /* #0399小心点! */ 294 | "#0394\xb6]\xa7\xd6\xa4@\xc2\x49\xa1\x49", /* #0394跑快一点! */ 295 | "#0395\xa4\xf1\xa4\xf5\xbd\x62\xc1\xd9\xa7\xd6\xb3\xe1\xa1\x49", /* #0395比火箭还快喔! */ 296 | "#0400\xb6\xd9\xa1\x49\xa4\x6a\xb9\xd9\xa8\xe0\xad\xcc\xa1\x49", /* #0400嗨!大伙儿们! */ 297 | "#0401\xa4\xdf\xb7\x51\xa8\xc6\xa6\xa8\xa1\x49", /* #0401心想事成! */ 298 | "#0406\xa7\xd6\xa8\xd3\xc0\xb0\xa4\xe2\xa1\x49", /* #0406快来帮手! */ 299 | "#0402\xa6^\xa8\xec\xb9\x4c\xa5\x68\xa1\x49\xa1\x49", /* #0402回到过去!! */ 300 | "#0403\xa6\x6e\xbe\xf7\xbe\xb9\xa1\x49", /* #0403好机器! */ 301 | "#0404\xa7\xda\xac\x4f\x0a\xc5]\xb0\xad\xb2\xd7\xb5\xb2\xaa\xcc\xa1\x49", /* #0404我是魔鬼终结者! */ 302 | "#0405\xa5@\xac\xc9\xa5\xbd\xa4\xe9\xa8\xec\xa4\x46\xa1\xe3", /* #0405世界末日到了∼ */ 303 | NULL, 304 | "#0407\xbe\xbe\xa1\x49", /* #0407噢! */ 305 | "#0408\xa7\xb9\xa4\x46\xa1\x49", /* #0408完了! */ 306 | "#0409\xa4\x6a\xa8\xc6\xa4\xa3\xa7\xae\xa1\xe3", /* #0409大事不妙∼ */ 307 | NULL, 308 | NULL, 309 | NULL, 310 | NULL, 311 | NULL, 312 | NULL, 313 | NULL, 314 | NULL, 315 | NULL, 316 | }, 317 | { 318 | "#0410@20", /* #0410@20 */ 319 | "#0411@19", /* #0411@19 */ 320 | "#0412@19", /* #0412@19 */ 321 | "#0413@19", /* #0413@19 */ 322 | "#0414@20", /* #0414@20 */ 323 | "#0415@20", /* #0415@20 */ 324 | "#0416@19", /* #0416@19 */ 325 | "#0417@20", /* #0417@20 */ 326 | "#0418@20", /* #0418@20 */ 327 | "#0419@20", /* #0419@20 */ 328 | "#0420@20", /* #0420@20 */ 329 | "#0421@20", /* #0421@20 */ 330 | "#0422@19", /* #0422@19 */ 331 | NULL, 332 | "#0423@05", /* #0423@05 */ 333 | "#0424@07", /* #0424@07 */ 334 | "#0425@02", /* #0425@02 */ 335 | NULL, 336 | NULL, 337 | NULL, 338 | NULL, 339 | NULL, 340 | NULL, 341 | NULL, 342 | NULL, 343 | NULL, 344 | }, 345 | }; 346 | -------------------------------------------------------------------------------- /asm/tool_table.c: -------------------------------------------------------------------------------- 1 | #include "tool.h" 2 | 3 | const rich4_tool tool_table[] = { 4 | { "\xbe\xf7\xbe\xb9\xab\xbd\xab\xbd", 10, 15, 0, 0 }, /* 机器娃娃 */ 5 | { "\xb8\xf4\xbb\xd9", 10, 30, 0, 1 }, /* 路障 */ 6 | { "\xa6\x61\xb9\x70", 10, 25, 0, 1 }, /* 地雷 */ 7 | { "\xa9\x77\xae\xc9\xac\xb5\xbc\x75", 10, 25, 0, 1 }, /* 定时炸弹 */ 8 | { "\xbe\xf7\xa8\xae", 10, 80, 0, 0 }, /* 机车 */ 9 | { "\xa8\x54\xa8\xae", 10, 150, 1, 0 }, /* 汽车 */ 10 | { "\xad\xb8\xbc\x75", 10, 100, 1, 2 }, /* 飞弹 */ 11 | { "\xbb\xbb\xb1\xb1\xbb\xeb\xa4\x6c", 10, 30, 1, 0 }, /* 遥控骰子 */ 12 | { "\xbe\xf7\xbe\xb9\xa4\x75\xa4\x48", 0, 30, 2, 1 }, /* 机器工人 */ 13 | { "\xae\xc9\xa5\xfa\xbe\xf7", 0, 40, 2, 2 }, /* 时光机 */ 14 | { "\xb6\xc7\xb0\x65\xbe\xf7", 0, 95, 2, 1 }, /* 传送机 */ 15 | { "\xa4\x75\xb5\x7b\xa8\xae", 0, 150, 2, 2 }, /* 工程车 */ 16 | { "\xae\xd6\xa4\x6c\xad\xb8\xbc\x75", 0, 250, 2, 2 }, /* 核子飞弹 */ 17 | }; 18 | -------------------------------------------------------------------------------- /asm/window_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include "window_util.h" 7 | 8 | wProc windowCallbacks[16]; // 48a010 9 | int callbackSize = 0; // 0x46cad8 10 | 11 | extern HWND gWindowHandle; 12 | 13 | int Wait_0402_Message(wProc cb, int a2) 14 | { 15 | callbackSize++; 16 | windowCallbacks[callbackSize] = cb; 17 | PostMessageA(gWindowHandle, 0x401, 0, a2); 18 | while (1) { 19 | MSG msg; 20 | if (PeekMessageA(&msg, 0, 0, 0, 1) == 0) 21 | continue; 22 | if (msg.message == 0x402) { 23 | callbackSize--; 24 | return msg.lParam; 25 | } 26 | TranslateMessage(&msg); 27 | DispatchMessageA(&msg); 28 | } 29 | } 30 | 31 | void Post_0402_Message(LPARAM lp) 32 | { 33 | PostMessageA(gWindowHandle, 0x402, 0, lp); 34 | } 35 | -------------------------------------------------------------------------------- /asm/window_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | 8 | typedef LRESULT (CALLBACK *wProc)(HWND, UINT, WPARAM, LPARAM); 9 | 10 | extern wProc windowCallbacks[]; 11 | extern int callbackSize; 12 | 13 | int Wait_0402_Message(wProc, int); 14 | void Post_0402_Message(LPARAM lp); 15 | -------------------------------------------------------------------------------- /csrc/bit_functions.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | typedef uint32_t (*bit_f_u32)(uint32_t); 10 | typedef void (*bit_f)(uint16_t*, uint16_t*, uint8_t*, size_t); 11 | extern int pixel_fmt; 12 | 13 | void fcn_455337(uint16_t *edi, uint16_t *esi, uint8_t *ebx, size_t ecx) 14 | { 15 | do { 16 | uint16_t ax = *esi; 17 | esi++; 18 | 19 | uint8_t dl = ebx[ax & 0x1f]; 20 | uint8_t dh = ebx[(ax >> 5) & 0x1f]; 21 | uint8_t al = ebx[(ax >> 10) & 0x1f]; 22 | ax = ((uint16_t)(al & 0x3f) << 10) | ((uint16_t)(dh & 0x1f) << 5) | (dl & 0x1f); 23 | 24 | *edi = ax; 25 | edi++; 26 | } while (--ecx); 27 | } 28 | 29 | void fcn_45536c(uint16_t *edi, uint16_t *esi, uint8_t *ebx, size_t ecx) 30 | { 31 | do { 32 | uint32_t ax = *esi; 33 | esi++; 34 | 35 | uint8_t dl = ebx[ax & 0x1f]; 36 | uint8_t dh = ebx[(ax >> 6) & 0x1f]; 37 | uint16_t dx = ((uint16_t)dh << 8) | dl; 38 | uint8_t al = ebx[(ax >> 11) & 0x1f]; 39 | ax = ((uint16_t)(al & 0x1f) << 11) | (((dx >> 7) & 0x3f) << 5) | (dx & 0x1f); 40 | 41 | *edi = ax; 42 | edi++; 43 | } while (--ecx); 44 | } 45 | 46 | void fcn_4553a1(uint16_t *edi, uint16_t *esi, uint8_t *ebx, size_t ecx) 47 | { 48 | ebx = (uint8_t*)(((long)ebx) >> 1); 49 | do { 50 | uint16_t ax = *esi; 51 | esi++; 52 | 53 | uint8_t dl = ebx[ax & 0xf]; 54 | uint8_t dh = ebx[(ax >> 4) & 0xf]; 55 | uint8_t al = ebx[(ax >> 8) & 0xf]; 56 | ax = ((uint16_t)(dh & 0xf) << 12) | ((uint16_t)al << 4) | (dl & 0xf); 57 | 58 | *edi = ax; 59 | edi++; 60 | } while (--ecx); 61 | } 62 | 63 | uint32_t fcn_45525c(uint32_t eax) 64 | { 65 | // return {16'b0,eax[23:19],eax[15:10],eax[7:3]} 66 | uint32_t t1 = ((eax >> 19) & 0x1f) << 11; 67 | uint32_t t2 = ((eax >> 10) & 0x3f) << 5; 68 | uint32_t t3 = ((eax >> 3) & 0x1f); 69 | return (t1 | t2 | t3); 70 | } 71 | 72 | const bit_f_u32 ftable_485948[4] = { 73 | 0x0045523eU, fcn_45525c, 0x0045527aU, 0x00455299U 74 | }; 75 | 76 | const bit_f ftable_485958[] = { 77 | fcn_455337, fcn_45536c, fcn_45536c, fcn_4553a1 78 | }; 79 | const uint32_t ftable_485968[] = { 80 | 0x00455442U, 0x00455480U, 0x00455480U, 0x004554beU 81 | }; 82 | const uint32_t ftable_485978[] = { 83 | 0x004555ebU, 0x00455628U, 0x0045566eU, 0x004556abU 84 | }; 85 | 86 | void fcn_004552b7(void * dst, void * src, size_t a3, int a4) 87 | { 88 | ftable_485958[pixel_fmt](dst, src, (uint8_t*)(0x485d68 + (a4 << 5)), a3 >> 1); 89 | } 90 | 91 | uint32_t fcn_4551f0(uint32_t a0) 92 | { 93 | return ftable_485948[pixel_fmt](a0); 94 | } 95 | -------------------------------------------------------------------------------- /csrc/card.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | const char *name_ptr; 6 | uint8_t init_amount; 7 | uint8_t price; 8 | uint8_t f6; 9 | uint8_t f7; 10 | } rich4_card; 11 | extern rich4_card cards_table[]; 12 | 13 | typedef int (*card_func)(void); 14 | extern card_func card_functions[]; 15 | -------------------------------------------------------------------------------- /csrc/cards_ui.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include "player_info.h" 7 | #include "global.h" 8 | #include "sound_struct.h" 9 | #include "window_util.h" 10 | 11 | uint8_t player_cards[60]; // 0x499120 12 | int selected_card; // 0x48c544 13 | const char str_use[] = "\xa8\xcf\xa5\xce%s"; // 使用%s 14 | 15 | sound_struct snd0 = {1, NULL}; // 0x00482322 16 | sound_struct snd1 = {3, NULL}; // 0x0048233a 17 | sound_struct snd2; // 0x0048cae0 18 | 19 | void fcn_4540d8(LPDIRECTSOUNDBUFFER sbuf, uint32_t a1, int a2) 20 | { 21 | if (sbuf == NULL || dw_49715b == 0) 22 | return; 23 | 24 | IDirectSoundBuffer_SetCurrentPosition(sbuf, 0); 25 | if (IDirectSoundBuffer_Play(sbuf, 0, 0, a2) == DSERR_BUFFERLOST) { 26 | if (fcn.00453f6c(sbuf, a1) == 1) { 27 | IDirectSoundBuffer_Play(sbuf, 0, 0, a2); 28 | } 29 | } 30 | IDirectSoundBuffer_SetVolume(sbuf, dword [(uint8_t)b_49715b * 4 + 0x47e758]); 31 | snd2.f0 = a1; 32 | snd2.sbuf = sbuf; 33 | } 34 | 35 | void fcn_4542ce(sound_struct * a0, int a1) 36 | { 37 | fcn_4540d8(a0->sbuf, a0->f0, a1); 38 | } 39 | 40 | LRESULT CALLBACK cardProc(HWND hWnd, UINT message, WPARAM wp, LPARAM lp) 41 | { 42 | PAINTSTRUCT ps; 43 | RECT rect2; 44 | 45 | if (message >= 0x202) { 46 | if (message == WM_LBUTTONUP) { 47 | if (selected_card == 0) 48 | return 0; 49 | fcn.00451d4e(); 50 | fcn_00402460(0); 51 | Post_0402_Message(selected_card); 52 | return 0; 53 | } 54 | if (message >= 0x205) { 55 | if (message == WM_RBUTTONUP) { 56 | fcn_00402460(0); 57 | Post_0402_Message(0); 58 | return 0; 59 | } 60 | if (message == 0x401) { 61 | selected_card = 0; 62 | fcn_00402460(1); 63 | InvalidateRect(hWnd, NULL, FALSE); 64 | return 0; 65 | } 66 | return DefWindowProcA(hWnd, message, wp, lp); 67 | } else { 68 | return DefWindowProcA(hWnd, message, wp, lp); 69 | } 70 | } 71 | 72 | if (message >= 0xf) { 73 | if (message == 0xf) { 74 | BeginPaint(hWnd, &ps); 75 | GetCursorPos_35d(&ps.rcPaint); /* fcn_4021f8.c */ 76 | IDirectDrawSurface_BltFast(pddrawsf1, ps.rcPaint.left, ps.rcPaint.top, pddrawsf2, &ps.rcPaint, 0x10); 77 | GetCursorPos_250(&ps.rcPaint); /* fcn_4021f8.c */ 78 | EndPaint(hWnd, &ps); 79 | return 0; 80 | } 81 | if (message == 0x201) { 82 | ebx = (uint16_t)dx; 83 | edx >>= 16; /* unsigned shift */ 84 | if (ebx < 0x13 || ebx >= 0x1a3 || edx < 0x87 || edx >= 0x12f) 85 | return 0; 86 | 87 | esi = ((edx - 0x87) / 56) * 5; 88 | ebx = esi + (ebx - 0x13) / 80; 89 | eax = current_player * 15; 90 | if (player_cards[current_player * 15 + ebx] == 0) 91 | return 0; 92 | 93 | int t1 = (ebx % 5) * 80; 94 | int t2 = (ebx / 5) * 56; 95 | rect2.left = t1 + 0x14; 96 | rect2.right = t1 + 0x62; 97 | rect2.top = t2 + 0x88; 98 | rect2.bottom = t2 + 0xbe; 99 | fcn.00451b9e(&rect2); 100 | 101 | eax = player_cards[current_player * 15 + ebx]; 102 | selected_card = eax; 103 | fcn_4542ce(&snd0, 0); 104 | return 0; 105 | } 106 | return DefWindowProcA(hWnd, message, wp, lp); 107 | } else { 108 | return DefWindowProcA(hWnd, message, wp, lp); 109 | } 110 | } 111 | 112 | void cards_ui() 113 | { 114 | int t[4]; /* esp + 0x80 */ 115 | char s[128]; 116 | uint8_t mem[8]; /* esp + 0x90 */ 117 | 118 | eax = current_player * 0x68; 119 | uint8_t dl = players[current_player].who_plays; 120 | if (dl == 1) { 121 | fcn.0041d546(); 122 | edi = eax = read_mkf(mkf_panel, 11, NULL, NULL); 123 | t[0] = 0; 124 | t[1] = 40; 125 | t[2] = 440; 126 | t[3] = 480; 127 | ebp = fcn.00451e7e(t); 128 | do { 129 | esi = 1; 130 | fcn_00441b0a(0, edi, current_player); 131 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 132 | overlay_fullscreen(sfdesc1.lpSurface, edi+12, 14, 130); 133 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 134 | int cardid = register_wait_callback(cardProc, 0); 135 | fcn_00451edb(ebp, 0, 0x8028); 136 | if (ebx != 0) { 137 | edx = cards_table[cardid - 1].name_ptr; 138 | sprintf(s, str_use, edx); 139 | fcn_00441f73(cardid, s); 140 | esi = eax = card_functions[cardid](); 141 | if (eax) { 142 | fcn_4542ce(&snd1, eax); 143 | } 144 | } 145 | } while (esi != 0); 146 | free (edi); 147 | free (ebp); 148 | return; 149 | } 150 | if ((dl & 6) && (players[current_player].f22 & 1)) { 151 | edi = esi = eax = player_cards_num(current_player); 152 | if (eax == 0) 153 | return; 154 | memset(mem, 0, 8); 155 | if (esi > 8) { 156 | esi = rand() % esi; 157 | } else { 158 | esi = 0; 159 | } 160 | for (ebx = 0; ebx < 8; ebx++) { 161 | eax = current_player * 15; 162 | edx = esi; 163 | esi++; 164 | al = player_cards[edx + eax]; 165 | mem[ebx] = al; 166 | if (edi <= 8 || esi != edi) 167 | continue; 168 | esi ^= edi; 169 | } 170 | } 171 | for (ebx = 0; ebx < 8; ebx++) { 172 | cl = mem[ebx]; 173 | if (cl == 0) 174 | return; 175 | eax = cl; /* zero ext */ 176 | eax = fcn_0041e69e(eax); 177 | if (eax != 1) 178 | continue; 179 | 180 | eax = mem[ebx]; 181 | ecx = cards_table[eax - 1].name_ptr; 182 | sprintf(s, str_use, ecx); 183 | eax = mem[ebx]; 184 | fcn_00441f73(eax, s); 185 | eax = mem[ebx]; 186 | card_functions[eax](); 187 | return; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /csrc/drawing.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include "global.h" 8 | #include "player_info.h" 9 | #include "graph_struct.h" 10 | 11 | struct graph_st st_46caec; 12 | RECT draw_rect; // @ 0x4861b8 13 | 14 | void set_rect(int left, int top, int right, int bottom) 15 | { 16 | draw_rect.left = left; 17 | draw_rect.top = top; 18 | draw_rect.right = right; 19 | draw_rect.bottom = bottom; 20 | } 21 | 22 | int graph_overlay0(int width, int height, uint16_t *pix, struct graph_st *gtop, int xpos, int ypos) 23 | { 24 | int ret = 1; 25 | xpos -= gtop->x; 26 | ypos -= gtop->y; 27 | int startX, startY, width_to_cpy, height_to_cpy; 28 | 29 | if (xpos < width && xpos + gtop->width > 0 30 | && ypos < height && ypos + gtop->height > 0) { 31 | startX = 0; 32 | startY = 0; 33 | width_to_cpy = gtop->width; 34 | height_to_cpy = gtop->height; 35 | 36 | if (xpos < 0) { 37 | startX -= xpos; 38 | width_to_cpy += xpos; 39 | xpos = 0; 40 | } else if (xpos + gtop->width > width) { 41 | width_to_cpy = width - xpos; 42 | } 43 | 44 | if (ypos < 0) { 45 | startY -= ypos; 46 | height_to_cpy += ypos; 47 | ypos = 0; 48 | } else if (ypos + gtop->height > height) { 49 | height_to_cpy = height - ypos; 50 | } 51 | uint16_t *src = >op->gdata[gtop->width * startY + startX]; 52 | uint16_t *dst = &pix[ypos * width + xpos]; 53 | 54 | if (width_to_cpy != 0) { 55 | for (int i = 0; i < height_to_cpy; i++) { 56 | memcpy(dst, src, sizeof(uint16_t) * width_to_cpy); 57 | src += gtop->width; 58 | dst += width; 59 | } 60 | return 0; 61 | } else { 62 | return height_to_cpy; 63 | } 64 | } 65 | return 1; 66 | } 67 | 68 | /* put graph gtop on top of graph with pixels pix size width*height, 69 | * gtop centered at (xpos, ypos) */ 70 | int graph_overlay(uint32_t width, uint32_t height, uint16_t *pix, struct graph_st * gtop, int xpos, int ypos, int a6) 71 | { 72 | /* get left top position */ 73 | xpos -= gtop->x; 74 | ypos -= gtop->y; 75 | 76 | int gtcrop_x, width_to_cpy, gtcrop_y, height_to_cpy; 77 | 78 | if (a6 != 1) { 79 | if (xpos >= width || xpos + gtop->width <= 0 || 80 | ypos >= height || ypos + gtop->height <= 0) 81 | return 1; 82 | 83 | if (xpos < 0) { 84 | gtcrop_x = -xpos; 85 | width_to_cpy = gtop->width + xpos; 86 | xpos = 0; 87 | } else { 88 | gtcrop_x = 0; 89 | int t = gtop->width + xpos - width; 90 | if (t > 0) { 91 | width_to_cpy = width - xpos; 92 | } else { 93 | width_to_cpy = gtop->width; 94 | } 95 | } 96 | 97 | if (ypos < 0) { 98 | gtcrop_y = -ypos; 99 | height_to_cpy = gtop->height + ypos; 100 | ypos = 0; 101 | } else { 102 | gtcrop_y = 0; 103 | int t = gtop->height + ypos - height; 104 | if (t > 0) { 105 | height_to_cpy = height - ypos; 106 | } else { 107 | height_to_cpy = gtop->height; 108 | } 109 | } 110 | } else { 111 | if (xpos >= draw_rect.right || xpos + (uint16_t)gtop->width <= draw_rect.left 112 | || ypos >= draw_rect.bottom || ypos + (uint16_t)gtop->height <= draw_rect.top) 113 | return 1; 114 | 115 | if (xpos < draw_rect.left) { 116 | int delta = draw_rect.left - xpos; 117 | xpos = draw_rect.left; 118 | gtcrop_x = delta; 119 | width_to_cpy = gtop->width - delta; 120 | } else { 121 | gtcrop_x = 0; 122 | if (gtop->width + xpos - draw_rect.right > 0) { 123 | width_to_cpy = draw_rect.right - xpos; 124 | } else { 125 | width_to_cpy = gtop->width; 126 | } 127 | } 128 | 129 | if (ypos < draw_rect.top) { 130 | int delta = draw_rect.top - ypos; 131 | ypos = draw_rect.top; 132 | gtcrop_y = delta; 133 | height_to_cpy = gtop->height - delta; 134 | } else { 135 | gtcrop_y = 0; 136 | if (gtop->height + ypos - draw_rect.bottom > 0) { 137 | height_to_cpy = draw_rect.bottom - ypos; 138 | } else { 139 | height_to_cpy = gtop->height; 140 | } 141 | } 142 | 143 | } 144 | 145 | int crop_start = gtop->width * gtcrop_y + gtcrop_x; 146 | uint16_t *src = >op->gdata[crop_start]; 147 | int gt_width_skip = gtop->width - width_to_cpy; 148 | int pix_width_skip = width - width_to_cpy; 149 | uint16_t *dst = &pix[width * ypos + xpos]; 150 | 151 | for (int i = 0; i < height_to_cpy; i++) { 152 | for (int j = 0; j < width_to_cpy; j++) { 153 | if (*src != 0) 154 | *dst = *src; 155 | src++; 156 | dst++; 157 | } 158 | 159 | src += gt_width_skip; 160 | dst += pix_width_skip; 161 | } 162 | 163 | return 0; 164 | } 165 | 166 | /* put graph a1 over a0 and make a1 centered on (xpos, ypos) of graph a0 */ 167 | void graph_st_overlay(struct graph_st * a0, struct graph_st * a1, int xpos, int ypos) 168 | { 169 | graph_overlay(a0->width, a0->height, a0->gdata, a1, xpos, ypos, 0); 170 | } 171 | 172 | /* put graph a1 over fullscreen sized (640*480) pixel image a0 173 | * and make a1 centered on (xpos, ypos) of graph a0 */ 174 | void fullscreen_overlay(uint16_t *a0, struct graph_st *a1, int xpos, int ypos) 175 | { 176 | graph_overlay(640, 480, a0, a1, xpos, ypos, 0); 177 | } 178 | 179 | void fcn_417191(int a0) 180 | { 181 | RECT r0; 182 | r0.left = dw_48bdec; 183 | r0.top = dw_48bde8; 184 | r0.right = r0.left + dw_48bdd8; 185 | r0.bottom = r0.top + dw_48bddc; 186 | 187 | GetCursorPos_35d(&r0); /* fcn_4021f8.c */ 188 | 189 | if (dw_48bdec != dw_475284 || dw_48bde8 != dw_475288) { 190 | dw_48bdec = dw_475284; 191 | dw_48bde8 = dw_475288; 192 | IDirectDrawSurface_BltFast(pddrawsf1, r0.left, r0.top, pddrawsf2, &r0, 0x10); 193 | } 194 | 195 | if (a0 == 0) { 196 | if (b_46cafd != 0) 197 | return; 198 | 199 | GetCursorPos_250(&r0); 200 | return; 201 | } 202 | 203 | ebx = 0; 204 | if (players[current_player].days_stopping != 0) 205 | ebx = 2; 206 | if (players[current_player].days_tortoise_walking != 0) 207 | ebx = 4; 208 | 209 | IDirectDrawSurface_Lock(pddrawsf1, 0, &sfdesc1, 1, 0); 210 | st_46caec.width = sfdesc1.DUMMYUNIONNAME1.lPitch / 2; 211 | st_46caec.gdata = sfdesc1.lpSurface; 212 | 213 | edx = dw_48bdd4 + ebx; 214 | edx = edx * 12 + dw_48be04 + 12; 215 | 216 | graph_st_overlay(&st_46caec, edx, dw_475284, dw_475288); 217 | 218 | eax = players[current_player].traffic_method & 3; 219 | switch (eax) { 220 | case 0: 221 | eax = dw_475288 + 0x1a; 222 | if (players[current_player].days_stopping == 0) { 223 | graph_st_overlay(&st_46caec, dw_48be04+0x60, dw_475284+7, eax); 224 | } else { 225 | graph_st_overlay(&st_46caec, dw_48be04+0x54, dw_475284+8, eax); 226 | } 227 | break; 228 | case 1: 229 | for (ebx = 0; ebx < 2; ebx++) { 230 | edx = players[current_player].ndices - 1; 231 | if (ebx <= edx && players[current_player].days_stopping == 0) { 232 | eax_1 = ebx * 19 + dw_475288 + 0x10; 233 | edx = (ebx * 2 + 7) * 12; 234 | eax_2 = dw_48be04 + 0xc + edx; 235 | graph_st_overlay(&st_46caec, eax_2, dw_475284 + 7, eax_1); 236 | } else { 237 | eax_1 = ebx*19 + dw_475288 + 0x10; 238 | eax_2 = (ebx * 2 + 6) * 12 + dw_48be04 + 0xc; 239 | graph_st_overlay(&st_46caec, eax_2, dw_475284 + 8, eax_1); 240 | } 241 | } 242 | break; 243 | case 2: 244 | for (ebx = 0; ebx < 3; ebx++) { 245 | edx = players[current_player].ndices - 1; 246 | if (ebx <= edx && players[current_player].days_stopping == 0) { 247 | a4 = ebx * 16 + dw_475288 + 9; 248 | a3 = dw_475284 + 7; 249 | a2 = (ebx * 2 + 7) * 12 + dw_48be04 + 0xc; 250 | graph_st_overlay(&st_46caec, a2, a3, a4); 251 | } else { 252 | a4 = ebx * 16 + dw_475288 + 9; 253 | a3 = dw_475284 + 8; 254 | a2 = (ebx * 2 + 6) * 12 + dw_48be04 + 0xc; 255 | graph_st_overlay(&st_46caec, a2, a3, a4); 256 | } 257 | } 258 | break; 259 | default: 260 | break; 261 | } 262 | IDirectDrawSurface_Unlock(pddrawsf1, NULL); 263 | GetCursorPos_250(&r0); 264 | st_46caec.width = 640; 265 | } 266 | 267 | void IntersectRect_4cd(RECT *r0) 268 | { 269 | RECT result_rect; 270 | RECT o_rect; 271 | if (b_46cafd == 0) 272 | return; 273 | 274 | o_rect.left = dw_475284; 275 | o_rect.top = dw_475288; 276 | o_rect.right = o_rect.left + dw_48bdd8; 277 | o_rect.bottom = o_rect.top + dw_48bddc; 278 | 279 | int ret = IntersectRect(&result_rect, &o_rect, r0); 280 | if (ret == 0) // do not intersect 281 | return; 282 | 283 | fcn_417191(1); 284 | } 285 | 286 | void player_say(int p, int t, const char *s) 287 | { 288 | RECT r0; 289 | 290 | static const char *ss = NULL; // 0x4762c8 291 | 292 | if (s == ss) 293 | return; 294 | ss = s; 295 | if (p & 0x8000) { 296 | edx = 0; 297 | p &= 0x7fff; 298 | } else { 299 | edx = 1; 300 | } 301 | if (players[p].days_disappearing != 0 || players[p].days_sleep_walking != 0 || players[p].days_winter_sleep != 0) 302 | return; 303 | 304 | if (edx != 0) { 305 | player_action_2(players[p].xpos, players[p].ypos, 0); 306 | } 307 | create_some_font(0x10, 0x101010, 0, 2, 1); 308 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 309 | st_46caec.gdata = sfdesc1.lpSurface; 310 | struct graph_st * edi = crop_graph(&st_46caec, NULL, 0, 40, 440, 220); 311 | fullscreen_overlay(sfdesc1.lpSurface, data_0205->chunk_tab[6], 220, 130); 312 | ecx = dword [p * 0x34 + 0x498eb0]; 313 | edx = t + 1; 314 | eax = edx * 12; 315 | ecx += 12; 316 | eax += ecx; 317 | fullscreen_overlay(sfdesc1.lpSurface, eax, 170, 130); 318 | 319 | if (s != NULL) { 320 | if (s[0] == '#') { 321 | esi = 5; 322 | } else { 323 | esi = 0; 324 | } 325 | const char *s2 = s + esi; 326 | if (s2[0] == '@') { 327 | int nn = (s2[1] - '0') * 10 + (s2[2] - '0'); 328 | fullscreen_overlay(sfdesc1.lpSurface, data_0207->chunk_tab[nn - 1], 240, 130); 329 | if (esi == 5) { 330 | eax = (s[1] - '0') * 1000 + (s[2] - '0') * 100 + (s[3] - '0') * 10 + (s[4] - '0'); 331 | speak_words(eax); 332 | } 333 | } else { 334 | draw_some_text(0, s, 200, 130, 5); 335 | } 336 | } 337 | // 0x44f157 338 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 339 | 340 | r0.left = 0; 341 | r0.top = 40; 342 | r0.right = 440; 343 | r0.bottom = 260; 344 | 345 | IDirectDrawSurface_BltFast(pddrawsf1, 0, 40, pddrawsf2, &r0, DDBLTFAST_WAIT); 346 | 347 | sub.WINMM.dll_timeGetTime_4f6(1000); 348 | 349 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 350 | overlay_fullwidth(sfdesc1.lpSurface, edi, r0.left, r0.top, 0, 0, 440, 220); 351 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 352 | 353 | IDirectDrawSurface_BltFast(pddrawsf1, r0.left, r0.top, pddrawsf2, &r0, DDBLTFAST_WAIT); 354 | free(edi); 355 | } 356 | 357 | void move_animation(int obj, int x1, int y1, int x2, int y2, int T) 358 | { 359 | /* push 4 regs, sub esp, 0x68 */ 360 | if (obj != 0) { 361 | eax = (obj - 1) * 3; 362 | ecx = byte [eax*8 + 0x496d09]; 363 | ebp = (8 - dword [0x499088] + ecx) & 7; 364 | edi = byte [eax*8 + 0x496d08]; 365 | edi = dword [edi*4 + 0x49692c]; 366 | eax = ebp * 12; 367 | ebx = edi + 12 + eax; 368 | } else { 369 | ebp = 0; 370 | edi = dword [0x49697c]; 371 | ebx = edi + 12; 372 | } 373 | 374 | int x3, y3, x4, y4; /* sp + 0x30,0x34,0x38,0x3c */ 375 | fcn.00409a23(&x1, &y1, &x3, &y3); 376 | fcn.00409a23(&x2, &y2, &x4, &y4); 377 | int distx = x4 - x3; 378 | int disty = y4 - y3; 379 | 380 | if (edx == 0 && ecx == 0) { 381 | return; 382 | } 383 | 384 | int dist = trunc(1 + sqrtf(disty * disty + distx * distx)); /* @ sp + 0x60 */ 385 | float dx = distx / (float)dist; /* @ sp+0x48 */ 386 | float dy = disty / (float)dist; /* @sp+0x44 */ 387 | float curx = x3 + dx; /* @ sp+0x58 */ 388 | float cury = y3 + dy; /* @ sp+0x5c */ 389 | 390 | RECT r0, r1, r2; /* @ sp, sp+0x10, sp+0x20 */ 391 | r0.left = -1000; 392 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 393 | st_46caec.gdata = sfdesc1.lpSurface; 394 | struct graph_st * st0 = crop_graph(&st_46caec, NULL, 0, 40, 440, 440); /* st0 @ sp+0x4c */ 395 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 396 | 397 | while (dist != 0) { 398 | esi = timeGetTime(); 399 | int icurx = trunc(curx); /* @ sp+0x54 */ 400 | int icury = trunc(cury); /* @ sp+0x50 */ 401 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 402 | if (r0.left != -1000) { 403 | fcn.00456469(sfdesc1.lpSurface, st0, r0.left, r0.top, r0.left, r0.top - 40, r0.right - r0.left, r0.bottom - r0.top); 404 | } 405 | fcn.00456770(sfdesc1.lpSurface, edi, ebp, icurx, icury); 406 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 407 | r2.left = icurx - (s16)word [ebx + 4]; 408 | r2.top = icury - (s16) word [ebx + 6]; 409 | r2.right = r2.left + (s16)word[ebx]; 410 | r2.bottom = r2.top + (s16) word [ebx+2]; 411 | if (r0.left != -1000) { 412 | fcn.00452808(&r2, &r0, &r1); 413 | } else { 414 | memcpy(&r1, &r2, sizeof(RECT)); 415 | } 416 | if (r1.right > 0 && r1.top < 480) { 417 | if (r1.left < 0) { 418 | r1.left = 0; 419 | } 420 | if (r1.bottom > 480) { 421 | r1.bottom = 480; 422 | } 423 | IDirectDrawSurface_BltFast(pddrawsf1, r1.left, r1.top, pddrawsf2, &r1, DDBLTFAST_WAIT); 424 | } 425 | memcpy(&r0, &r2, sizeof(RECT)); 426 | eax = timeGetTime() - esi; 427 | if (eax < 24) { 428 | sub.WINMM.dll_timeGetTime_85e(24 - eax); 429 | } 430 | curx += dx; 431 | cury += dy; 432 | dist--; 433 | } 434 | // 40e9bd 435 | sub.WINMM.dll_timeGetTime_85e(T); 436 | if (obj == 0) { 437 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 438 | fcn.00456469(sfdesc1.lpSurface, st0, r0.left, r0.top, r0.left, r0.top - 40, r0.right - r0.left, r0.bottom - r0.top); 439 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 440 | IDirectDrawSurface_BltFast(pddrawsf1, r0.left, r0.top, pddrawsf2, &r0, DDBLTFAST_WAIT); 441 | } 442 | // 0x40ea4d 443 | free(st0); 444 | } 445 | 446 | int overlay_fullscreen(uint16_t *a0, struct graph_st *a1, int a2, int a3) 447 | { 448 | return graph_overlay0(640, 480, a0, a1, a2, a3); 449 | } 450 | 451 | /* overlay the graph a2 on top of a1, 452 | * a1 has width a0 453 | * (xpos, ypos) is the center of a2 after putting on a1 454 | * a2 has size width*height 455 | */ 456 | void graph_overlay2(int a0, uint16_t *a1, struct graph_st *a2, 457 | int xpos, int ypos, int a2x, int a2y, int width, int height, int a9) 458 | { 459 | /* let (xpos, ypos) be the left-top corner */ 460 | xpos -= a2->x; 461 | ypos -= a2->y; 462 | if ((a9 & 1) == 0) { 463 | if (xpos >= 640 || xpos + width <= 0) 464 | return; 465 | 466 | if (xpos + width > 640) { 467 | width = 640 - xpos; 468 | } else if (xpos < 0) { 469 | width += xpos; 470 | a2x -= xpos; 471 | xpos = 0; 472 | } 473 | 474 | if (ypos >= 480 || ypos + height <= 0) 475 | return; 476 | 477 | if (ypos + height > 480) { 478 | height = 480 - ypos; 479 | } else if (ypos < 0) { 480 | height += ypos; 481 | a2y -= ypos; 482 | ypos = 0; 483 | } 484 | } else { 485 | if (xpos >= draw_rect.right || xpos + width <= draw_rect.left) 486 | return; 487 | 488 | if (xpos + width > draw_rect.right) { 489 | width = draw_rect.right - xpos; 490 | } else if (xpos < draw_rect.left) { 491 | width += xpos - draw_rect.left; 492 | a2x += draw_rect.left - xpos; 493 | xpos = draw_rect.left; 494 | } 495 | 496 | if (ypos >= draw_rect.bottom || ypos + height <= draw_rect.top) 497 | return; 498 | 499 | if (ypos + height > draw_rect.bottom) { 500 | height = draw_rect.bottom - ypos; 501 | } else if (ypos < draw_rect.top) { 502 | height += ypos - draw_rect.top; 503 | a2y += draw_rect.top - ypos; 504 | ypos = draw_rect.top; 505 | } 506 | } 507 | 508 | uint16_t *src = &a2->gdata[a2->width * a2y + a2x]; 509 | uint16_t *dst = &a1[a0 * ypos + xpos]; 510 | 511 | if (width == 0) 512 | return; 513 | 514 | for (int i = 0; i < height; i++) { 515 | memcpy(dst, src, width * 2); 516 | src += a2->width; 517 | dst += a0; 518 | } 519 | } 520 | 521 | void overlay_fullwidth(uint16_t *a0, struct graph_st *a1, 522 | int a2, int a3, int a4, int a5, int a6, int a7) 523 | { 524 | graph_overlay2(640, a0, a1, a2, a3, a4, a5, a6, a7, 0); 525 | } 526 | -------------------------------------------------------------------------------- /csrc/drawing.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include "graph_struct.h" 8 | 9 | extern struct graph_st st_46caec; 10 | extern RECT draw_rect; // @ 0x4861b8 11 | 12 | void set_rect(int left, int top, int right, int bottom); 13 | int graph_overlay0(int width, int height, uint16_t *pix, struct graph_st *gtop, int xpos, int ypos); 14 | int graph_overlay(uint32_t width, uint32_t height, uint16_t *pix, struct graph_st * gtop, int xpos, int ypos, int a6); 15 | void graph_st_overlay(struct graph_st * a0, struct graph_st * a1, int xpos, int ypos); 16 | void fullscreen_overlay(uint16_t *a0, struct graph_st *a1, int xpos, int ypos); 17 | void fcn_417191(int a0); 18 | void IntersectRect_4cd(RECT *r0); 19 | void player_say(int p, int t, const char *s); 20 | void move_animation(int obj, int x1, int y1, int x2, int y2, int T); 21 | int overlay_fullscreen(uint16_t *a0, struct graph_st *a1, int a2, int a3); 22 | void graph_overlay2(int a0, uint16_t *a1, struct graph_st *a2, 23 | int xpos, int ypos, int a2x, int a2y, int width, int height, int a9); 24 | void overlay_fullwidth(uint16_t *a0, struct graph_st *a1, 25 | int a2, int a3, int a4, int a5, int a6, int a7); 26 | -------------------------------------------------------------------------------- /csrc/fcn_4021f8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include "mkf/mkf.h" 8 | 9 | struct graph_st *current_cursors; // 0x48a0f4 10 | 11 | void set_cursor_icon(int data0_idx, int a2, int a3) 12 | { 13 | current_cursors = &data0->chunk_tab[data0_idx]; 14 | w_48a170 = a2; 15 | w_48a174 = a3; 16 | w_48a172 = w_48a176 = 0; 17 | GetCursorPos_35d(NULL); 18 | GetCursorPos_250(NULL); 19 | } 20 | 21 | void fcn_00402460(int a1) 22 | { 23 | if (a1 == 1) { 24 | b_48a178 = (uint8_t)a1; 25 | if ((b_48a179 & 1) != 0) 26 | return; 27 | GetCursorPos_250(NULL); 28 | return; 29 | } 30 | if ((b_48a179 & 1) != 0) { 31 | GetCursorPos_35d(NULL); 32 | } 33 | b_48a178 = (uint8_t)a1; 34 | } 35 | 36 | /* 0x0040235d */ 37 | void GetCursorPos_35d(RECT *rect) 38 | { 39 | POINT p; 40 | 41 | if (b_48a178 != 1) 42 | return; 43 | 44 | if (b_46caf9 != 0) 45 | return; 46 | 47 | if ((b_48a179 & 1) == 0) 48 | return; 49 | 50 | GetCursorPos(&p); 51 | if (rect != NULL) { 52 | struct graph_st *csor = ¤t_cursors[w_48a172]; 53 | edx = p.x - csor->x; 54 | eax = p.y - csor->y; 55 | ecx = edx + 0x20; 56 | esi = eax + 0x20; 57 | if (edx >= rect->right || ecx <= rect->left || eax >= rect->bottom || esi <= rect->top) { 58 | eax = dw_48a0ec; 59 | if (eax >= rect->right) 60 | return; 61 | eax += 0x20; 62 | if (eax <= rect->left) 63 | return; 64 | eax = dw_48a0f0; 65 | if (eax >= rect->bottom) 66 | return; 67 | eax += 0x20; 68 | if (eax <= rect->top) 69 | return; 70 | } 71 | } 72 | b_48a17a = 1; 73 | IDirectDrawSurface_Lock(pddrawsf1, NULL, &sfdesc2, 1, 0); 74 | st_46cb14.gdata = sfdesc2.lpSurface; 75 | fcn_00401f5e(); 76 | IDirectDrawSurface_Unlock(pddrawsf1, NULL); 77 | b_48a17a = 0; 78 | b_48a179 &= ~1; 79 | } 80 | 81 | /* 0x00402250 */ 82 | void GetCursorPos_250(RECT *rect) 83 | { 84 | POINT p; 85 | 86 | if (b_48a178 != 1) 87 | return; 88 | 89 | if (b_46caf9 != 0) 90 | return; 91 | 92 | if ((b_48a179 & 1) == 0) 93 | return; 94 | 95 | GetCursorPos(&p); 96 | if (rect != NULL) { 97 | struct graph_st *csor = ¤t_cursors[w_48a172]; 98 | edx = p.x - csor->x; 99 | eax = p.y - csor->y; 100 | ecx = edx + 0x20; 101 | esi = eax + 0x20; 102 | if (edx >= rect->right || ecx <= rect->left || eax >= rect->bottom || esi <= rect->top) { 103 | eax = dw_48a0ec; 104 | if (eax >= rect->right) 105 | return; 106 | eax += 0x20; 107 | if (eax <= rect->left) 108 | return; 109 | eax = dw_48a0f0; 110 | if (eax >= rect->bottom) 111 | return; 112 | eax += 0x20; 113 | if (eax <= rect->top) 114 | return; 115 | } 116 | } 117 | b_48a17a = 1; 118 | IDirectDrawSurface_Lock(pddrawsf1, NULL, &sfdesc2, 1, 0); 119 | st_46cb14.gdata = sfdesc2.lpSurface; 120 | fcn_00401e59(p.x, p.y); 121 | IDirectDrawSurface_Unlock(pddrawsf1, NULL); 122 | b_48a17a = 0; 123 | b_48a179 |= 1; 124 | } 125 | -------------------------------------------------------------------------------- /csrc/fcn_417d65.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | void fcn_00419703() 7 | { 8 | b_46cafd = 0; 9 | fcn_00417191(0); 10 | } 11 | 12 | void topbar_btn(int v) 13 | { 14 | int res; 15 | 16 | fcn_00402460(0); 17 | fcn_00419703(); 18 | dw_48bde4 = -1; 19 | fcn_00415d31(1); 20 | 21 | switch (v) { 22 | case 0: 23 | help_ui(20, 60); 24 | break; 25 | case 1: 26 | options_ui(1); 27 | break; 28 | case 2: 29 | hosted_ai_ui(); 30 | break; 31 | case 3: 32 | res = load_ui(1); 33 | break; 34 | case 4: 35 | save_ui(); 36 | break; 37 | case 5: 38 | map_ui(); 39 | break; 40 | case 6: 41 | query_user_ui(); 42 | break; 43 | case 7: 44 | tools_ui(); 45 | break; 46 | case 8: 47 | cards_ui(); 48 | break; 49 | case 9: 50 | sales_ui(); 51 | break; 52 | case 10: 53 | stock_ui(0); 54 | default: 55 | break; 56 | } 57 | if (fcn_0040defe() != 1) 58 | return; 59 | if (v == 3) { 60 | if (res != -1) 61 | return; 62 | } 63 | fcn_004196f1(); 64 | fcn_00402460(1); 65 | } 66 | -------------------------------------------------------------------------------- /csrc/font.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include 8 | #include "global.h" 9 | #include "drawing.h" 10 | 11 | HFONT gFont; // 0x4762d0 12 | int gFontHeight; // 0x4762d4 13 | uint32_t gfa[2]; // 0x4762d8, 0x4762dc 14 | COLORREF txt_colors[2]; // 0x4762e0, 0x4762e4 15 | struct graph_st gst_4762e8; 16 | 17 | const char tfname[] = "\xb2\xd3\xa9\xfa\xc5\xe9"; // 0x4660a0, typeface name, BIG5:细明体 18 | 19 | static inline uint32_t swapbytes3(uint32_t x) 20 | { 21 | return (((x & 0xff) << 16) | (x & 0xff00) | ((x & 0xff0000) >> 16)); 22 | } 23 | 24 | /* 0x0044f9d8 */ 25 | HFONT create_some_font(int a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4) 26 | { 27 | txt_colors[0] = swapbytes3(a1); 28 | txt_colors[1] = swapbytes3(a2); 29 | gfa[0] = a3; 30 | gfa[1] = a4; 31 | int weight = (a3==2)?400:700; 32 | if (gFont != 0) { 33 | DeleteObject(gFont); 34 | } 35 | gFontHeight = a0; 36 | gFont = CreateFontA(-a0, 0, 0, 0, weight, 0, 0, 0, 0x88 /* charset */, 0, 0, 0, 0, tfname); 37 | return gFont; 38 | } 39 | 40 | void drawStringY(HDC hdc, int nXStart, int nYStart, LPCSTR str) 41 | { 42 | int h = gFontHeight + gfa[1]; 43 | if (((uint8_t)gfa[0] & 6) != 0) 44 | h++; 45 | 46 | while (*str) { 47 | if ((str[0] & 0x80) != 0) { 48 | TextOutA(hdc, nXStart, nYStart, str, 2); 49 | str += 2; 50 | } else { 51 | TextOutA(hdc, nXStart, nYStart, str, 1); 52 | str += 1; 53 | } 54 | nYStart += h; 55 | } 56 | } 57 | 58 | void surface_bound(uint16_t *lpSurface, RECT *dim1, RECT *dim2) 59 | { 60 | int j_min = 10000; 61 | int i_min = 10000; 62 | int j_max = -10000; 63 | int i_max = -10000; 64 | 65 | 66 | for (int i = 0; i < dim1->bottom; i++) { 67 | int t = 0; 68 | for (int j = dim1->left; j < dim1->right; j++) { 69 | if (lpSurface[t+j] != 0) { 70 | if (j < j_min) 71 | j_min = j; 72 | 73 | if (i < i_min) 74 | i_min = i; 75 | 76 | if (j > j_max) 77 | j_max = j; 78 | 79 | if (i > i_max) 80 | i_max = i; 81 | } 82 | } 83 | t += 0x200; 84 | } 85 | 86 | if (j_min == 10000) { 87 | dim2->top = dim2->left = dim2->right = dim2->bottom = 0; 88 | } else { 89 | dim2->left = j_min; 90 | dim2->top = i_min; 91 | dim2->right = j_max; 92 | dim2->bottom = i_max; 93 | } 94 | } 95 | 96 | /* TODO: very similar to graph_overlay2 except the copying part, 97 | * deduplicate the code 98 | */ 99 | static void graph_overlay_2a(int width, int16_t *sf, struct graph_st *a3, 100 | int xx, int yy, int a6, int a7, int ww, int hh, int a10) 101 | { 102 | xx -= a3->x; 103 | yy -= a3->y; 104 | 105 | if ((a10 & 1) == 0) { 106 | if (xx >= 640 || xx + ww <= 0) { 107 | return; 108 | } 109 | if (xx + ww > 640) { 110 | ww = 640 - xx; 111 | } else if (xx < 0) { 112 | ww = xx + ww; 113 | a6 -= xx; 114 | xx = 0; 115 | } 116 | 117 | if (yy >= 480 || yy + hh <= 0) { 118 | return; 119 | } 120 | if (yy + hh > 480) { 121 | hh = 480 - yy; 122 | } else if (yy < 0) { 123 | hh = yy + hh; 124 | a7 -= yy; 125 | yy = 0; 126 | } 127 | } else { 128 | if (xx >= draw_rect.right) { 129 | return; 130 | } 131 | if (xx + ww <= draw_rect.left) { 132 | return; 133 | } 134 | if (xx + ww > draw_rect.right) { 135 | ww = draw_rect.right - xx; 136 | } else if (xx < draw_rect.left) { 137 | ww -= draw_rect.left - xx; 138 | a6 += draw_rect.left - xx; 139 | xx = draw_rect.left; 140 | } 141 | 142 | if (yy >= draw_rect.bottom) { 143 | return; 144 | } 145 | if (yy + hh <= draw_rect.top) { 146 | return; 147 | } 148 | if (yy + hh > draw_rect.bottom) { 149 | hh = draw_rect.bottom - yy; 150 | } else if (yy < draw_rect.top) { 151 | hh -= draw_rect.top - yy; 152 | a7 += draw_rect.top - yy; 153 | yy = draw_rect.top; 154 | } 155 | } 156 | 157 | int16_t *src = &a3->gdata[a3->width * a7 + a6]; 158 | int16_t *dst = &sf[width * yy + xx]; 159 | 160 | for (int i = 0; i < hh; i++) { 161 | for (int j = 0; j < ww; j++) { 162 | if (src[j] != 0) 163 | dst[j] = src[j]; 164 | } 165 | 166 | src += a3->width; 167 | dst += width; 168 | } 169 | } 170 | 171 | void fcn_4564e6(void *sf, struct graph_st *a1, int a2, int a3, int a4, int a5, int a6, int a7) 172 | { 173 | graph_overlay_2a(640, sf, a1, a2, a3, a4, a5, a6, a7, 1); 174 | } 175 | 176 | void fcn_456495(void *sf, struct graph_st *a1, int a2, int a3, int a4, int a5, int a6, int a7) 177 | { 178 | graph_overlay_2a(640, sf, a1, a2, a3, a4, a5, a6, a7, 0); 179 | } 180 | 181 | void fcn_00456356(struct graph_st *a1, struct graph_st *a2, 182 | int a3, int a4, int a5, int a6, int a7, int a8) 183 | { 184 | graph_overlay_2a(a1->width, a1->gdata, a2, a3, a4, a5, a6, a7, a8, 1); 185 | } 186 | 187 | void fcn_00456328(struct graph_st *a1, struct graph_st *a2, 188 | int a3, int a4, int a5, int a6, int a7, int a8) 189 | { 190 | graph_overlay_2a(a1->width, a1->gdata, a2, a3, a4, a5, a6, a7, a8, 0); 191 | } 192 | 193 | void speak_words(int n) 194 | { 195 | /* TODO */ 196 | } 197 | 198 | void graph_fill(struct graph_st *gg, int left, int top, int width, int height, int v) 199 | { 200 | uint16_t color = fcn_4551f0(v); 201 | uint16_t *fill_line= &gg->gdata[gg->width * top + left]; 202 | 203 | for (int i = 0; i < height; i++) { 204 | for (int j = 0; j < width; j++) { 205 | fill_line[j] = color; 206 | } 207 | fill_line += gg->width; 208 | } 209 | } 210 | 211 | void draw_some_text(struct graph_st *gg, const char *str, int a3, int a4, int a5) 212 | { 213 | DDSURFACEDESC desc; /* esp */ 214 | RECT fmt_dim1; /* esp + 0x6c */ 215 | RECT fmt_dim2; /* esp + 0x7c */ 216 | HDC hDC; /* esp + 0x8c */ 217 | 218 | fmt_dim1 = *(RECT*)0x44f6ec; 219 | fmt_dim2 = *(RECT*)0x44f6fc; 220 | 221 | if (str == NULL || str[0] == 0) 222 | return; 223 | if (str[0] == '#') { 224 | int t = (str[1] - '0') * 1000 + (str[2] - '0') * 100 + 225 | (str[3] - '0') * 10 + (str[4] - '0'); 226 | speak_words(t); 227 | str += 5; 228 | } 229 | IDirectDrawSurface_GetDC(pddrawsf3, &hDC); 230 | SelectObject(hDC, &gFont); 231 | SetBkMode(hDC, 1); 232 | SetTextCharacterExtra(hDC, gfa[1]-1); 233 | DrawTextA(hDC, str, strlen(str), &fmt_dim2, 0x400); 234 | int t1 = fmt_dim2.right + 10; 235 | int t2 = fmt_dim2.bottom + 10; 236 | fmt_dim2.right = t1; 237 | fmt_dim2.bottom = t2; 238 | if (a5 == 3) { 239 | fmt_dim2.right = t2; 240 | fmt_dim2.bottom = t1; 241 | } else if (a5 == 4 || a5 == 7) { 242 | fmt_dim2.left = 256 - fmt_dim2.right / 2; 243 | fmt_dim2.right = 256 + fmt_dim2.right / 2; 244 | } 245 | uint8_t dh = gfa[0]; 246 | if ( (dh & 1) != 0 ) { 247 | SetTextColor(hDC, txt_colors[1]); 248 | fmt_dim1.left = 1; 249 | fmt_dim1.top = 1; 250 | if (a5 >= 4) { 251 | if (a5 == 4 || a5 == 7) { 252 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, 1); 253 | } else { 254 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, 0); 255 | } 256 | } else if (a5 != 3) { 257 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, 0); 258 | } else { 259 | drawStringY(hDC, 1, 1, str); 260 | } 261 | } else if ( (dh & 4) != 0 ) { 262 | SetTextColor(hDC, txt_colors[1]); 263 | if (a5 == 3) { 264 | drawStringY(hDC, 1, 0, str); 265 | drawStringY(hDC, 1, 2, str); 266 | drawStringY(hDC, 0, 1, str); 267 | drawStringY(hDC, 2, 1, str); 268 | } else { 269 | int mode; 270 | if (a5 == 4 || a5 == 7) { 271 | mode = 1; 272 | } else { 273 | mode = 0; 274 | } 275 | 276 | fmt_dim1.left = 1; 277 | fmt_dim1.top = 0; 278 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, mode); 279 | 280 | fmt_dim1.left = 1; 281 | fmt_dim1.top = 2; 282 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, mode); 283 | 284 | fmt_dim1.left = 0; 285 | fmt_dim1.top = 1; 286 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, mode); 287 | 288 | fmt_dim1.left = 2; 289 | fmt_dim1.top = 1; 290 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, mode); 291 | } 292 | } 293 | 294 | SetTextColor(hDC, txt_colors[0]); 295 | if ( ((uint8_t)gfa[0] & 4) != 0 ) { 296 | fmt_dim1.left = 1; 297 | fmt_dim1.top = 1; 298 | } else { 299 | fmt_dim1.left = 0; 300 | fmt_dim1.top = 0; 301 | } 302 | if (a5 >= 4) { 303 | if (a5 == 4 || a5 == 7) { 304 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, 1); 305 | } else { 306 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, 0); 307 | } 308 | } else if (a5 == 3) { 309 | drawStringY(hDC, fmt_dim1.left, fmt_dim1.top, str); 310 | } else { 311 | DrawTextA(hDC, str, strlen(str), &fmt_dim1, 0); 312 | } 313 | 314 | IDirectDrawSurface_ReleaseDC(pddrawsf3, hDC); 315 | 316 | desc.dwSize = 0x6c; 317 | IDirectDrawSurface_Lock(pddrawsf3, NULL, &desc, 1, 0); 318 | 319 | surface_bound(desc.lpSurface, &fmt_dim2, &fmt_dim1); 320 | int width = fmt_dim1.right - fmt_dim1.left + 1; 321 | int height = fmt_dim1.bottom - fmt_dim1.top + 1; 322 | gst_4762e8.gdata = desc.lpSurface; 323 | 324 | switch (a5 - 1) { 325 | case 0: 326 | a3 -= width; 327 | break; 328 | case 1: 329 | case 2: 330 | case 3: 331 | a3 -= width / 2; 332 | /* fall through */ 333 | case 4: 334 | a4 -= height / 2; 335 | break; 336 | case 5: 337 | a3 -= width; 338 | a4 -= height / 2; 339 | break; 340 | case 6: 341 | a3 -= width / 2; 342 | a4 -= height; 343 | break; 344 | default: 345 | break; 346 | } 347 | 348 | if ( ((uint8_t)gfa[0] & 8) != 0) { 349 | if (!gg) { 350 | fcn_4564e6(sfdesc1.lpSurface, &gst_4762e8, 351 | a3, a4, fmt_dim1.left, fmt_dim1.top, width, height); 352 | } else { 353 | fcn_00456356(gg, &gst_4762e8, 354 | a3, a4, fmt_dim1.left, fmt_dim1.top, width, height); 355 | } 356 | } else { 357 | if (!gg) { 358 | fcn_456495(sfdesc1.lpSurface, &gst_4762e8, 359 | a3, a4, fmt_dim1.left, fmt_dim1.top, width, height); 360 | } else { 361 | fcn_00456328(gg, &gst_4762e8, 362 | a3, a4, fmt_dim1.left, fmt_dim1.top, width, height); 363 | } 364 | } 365 | graph_fill(&gst_4762e8, fmt_dim1.left, fmt_dim1.top, width, height, 0); 366 | IDirectDrawSurface_Unlock(pddrawsf3, NULL); 367 | } 368 | 369 | void deinit_font() 370 | { 371 | if (gFont != NULL) 372 | DeleteObject(gFont); 373 | 374 | if (pddrawsf3 != NULL) 375 | IDirectDrawSurface_Release(pddrawsf3); 376 | } 377 | -------------------------------------------------------------------------------- /csrc/fortune.c: -------------------------------------------------------------------------------- 1 | #include "land.h" 2 | #include "mkf/mkf.h" 3 | #include "stock.h" 4 | 5 | struct housing_land *hlands; // @0x498e84 6 | struct business_land *blands; // @0x498e88 7 | 8 | typedef void (*fortune_call(int)); 9 | fortune_call fortune_call_table[]; 10 | 11 | const uint16_t fortune_data_idx[49] = { 12 | 0x01dd, 0x01de, 0x01df, 0x01e0, 0x01e1, 0x01e2, 0x01e3, 0x01e4, 13 | 0x01e5, 0x01e6, 0x01e7, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ec, 14 | 0x01ed, 0x01ee, 0x01ef, 0x01f0, 0x01f1, 0x01f1, 0x01f1, 0x01f2, 15 | 0x01f2, 0x01f3, 0x01f4, 0x01f5, 0x01f5, 0x01f5, 0x01f6, 0x01f7, 16 | 0x01f8, 0x01f9, 0x01fa, 0x01fb, 0x01fc, 0x01f9, 0x01fd, 0x01fe, 17 | 0x01ff, 0x0200, 0x01fa, 0x01fb, 0x0201, 0x0202, 0x0203, 0x01fe, 18 | 0x0204 19 | }; 20 | 21 | int fortune_check(int *v) 22 | { 23 | struct housing_land *lnd; 24 | 25 | switch (*v) { 26 | case 0: 27 | lnd = &hlands[1]; 28 | for (int i = 1; i <= dw_498e98; i++) { 29 | if (lnd->owner == current_player + 1) { 30 | if (lnd->level != 0) 31 | return 1; 32 | } 33 | lnd++; 34 | } 35 | return 0; 36 | case 1: 37 | lnd = &hlands[1]; 38 | for (int i = 1; i <= dw_498e98; i++) { 39 | if (lnd->owner == current_player + 1) { 40 | if (lnd->level == 0) 41 | return 1; 42 | } 43 | lnd++; 44 | } 45 | return 0; 46 | case 5: 47 | int ncards = 0; 48 | for (int i = 0; i < nplayers; i++) { 49 | if (i != current_player) { 50 | ncards += player_cards_num(i); 51 | } 52 | } 53 | if (ncards != 0) { 54 | return 1; 55 | } else { 56 | return 0; 57 | } 58 | case 8: 59 | case 9: 60 | for (int i = 0; i < 12; i++) { 61 | if (player_stocks[current_player * 12 + i].amount != 0) 62 | return 1; 63 | } 64 | return 0; 65 | case 10: 66 | if (players[current_player].traffic_method != 1 && 67 | players[current_player].traffic_method != 2) { 68 | return 0; 69 | } 70 | if (players[current_player].traffic_method == 2) 71 | *v = 11; 72 | 73 | return 1; 74 | case 11: 75 | if (players[current_player].traffic_method != 1) { 76 | if (players[current_player].traffic_method != 2) 77 | return 0; 78 | } 79 | if (players[current_player].traffic_method == 1) 80 | *v = 10; 81 | return 1; 82 | case 12: 83 | if (players[current_player].traffic_method != 0 && 84 | players[current_player].traffic_method != 1) 85 | return 0; 86 | 87 | if (players[current_player].traffic_method == 1) 88 | *v = 13; 89 | 90 | return 1; 91 | case 13: 92 | bh = players[current_player].traffic_method; 93 | if (bh != 0 && bh != 1) 94 | return 0; 95 | 96 | if (players[current_player].traffic_method == 0) 97 | *v = 12; 98 | 99 | return 1; 100 | case 14: 101 | cl = players[current_player].traffic_method; 102 | if (cl > 2) 103 | return 0; 104 | if (cl == 1) { 105 | *v = 15; 106 | } else if (cl == 2) { 107 | *v = 16; 108 | } 109 | return 1; 110 | case 15: 111 | ch = players[current_player].traffic_method; 112 | if (ch > 2) 113 | return 0; 114 | if (ch == 0) { 115 | *v = 15; 116 | } else if (ch == 2) { 117 | *v = 16; 118 | } 119 | return 1; 120 | case 16: 121 | bl = players[current_player].traffic_method; 122 | if (bl > 2) 123 | return 0; 124 | if (bl == 0) { 125 | *v = 14; 126 | } else if (bl == 1) { 127 | *v = 15; 128 | } 129 | return 1; 130 | case 33: 131 | case 34: 132 | case 35: 133 | case 36: 134 | if (game_stage == 0) 135 | return 1; 136 | else 137 | return 0; 138 | default: 139 | return 1; 140 | } 141 | } 142 | 143 | static void *fortune_panel; // @ 0x48c5e0 144 | 145 | void fortune_events(void) 146 | { 147 | int res; 148 | uint32_t edi; 149 | RECT r0; 150 | int t; 151 | 152 | fortune_panel = read_mkf(mkf_panel, 66, NULL, NULL); 153 | struct graph_st *fgraph = allocate_graph_st(388, 251, 0, 0); 154 | 155 | do { 156 | t = byte [dw_4990b4 + 0x496b38]; 157 | res = fortune_check(&t); 158 | create_some_font(28, 0xf0f0f0, 0x101010, 3, 0); 159 | if (res == 1) { 160 | if (t < 33) { 161 | read_mkf(mkf_data, fortune_data_idx[t], fgraph->gdata, NULL); 162 | fcn_00456280(fortune_panel + 0x18, fgraph, 25, 44); 163 | fortune_call_table[t](0); 164 | } else { 165 | read_mkf(mkf_data, fortune_data_idx[game_map * 4 + t], fgraph->gdata, NULL); 166 | fcn_00456280(fortune_panel + 0x18, fgraph, 25, 44); 167 | fortune_call_table[game_map * 4 + t](0); 168 | } 169 | free(fgraph); 170 | } 171 | dw_4990b4++; 172 | if (dw_4990b4 == 37) { 173 | dw_4990b4 = 0; 174 | } 175 | } while (res == 0); 176 | 177 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 178 | overlay_fullscreen(sfdesc1.lpSurface, fortune_panel+0x18, 0, 0); 179 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 180 | r0.left = 0; 181 | r0.top = 0; 182 | r0.right = 440; 183 | r0.bottom = 480; 184 | IDirectDrawSurface_BltFast(pddrawsf1, 0, 0, pddrawsf2, &r0, DDBLTFAST_WAIT); 185 | sub.WINMM.dll_timeGetTime_4f6(1600); 186 | if (t < 33) { 187 | fortune_call_table[t](1); 188 | } else { 189 | fortune_call_table[game_map * 4 + t](1); 190 | } 191 | sub.WINMM.dll_timeGetTime_8b9(800); 192 | free(fortune_panel); 193 | } 194 | 195 | /* all the fortunes */ 196 | 197 | static 198 | void land_house_lost() 199 | { 200 | fcn.00451985(); 201 | player_action_2(0, 0, 1); 202 | sub.WINMM.dll_timeGetTime_8b9(300); 203 | int c = players[current_player].character; 204 | eax = rand() & 1; 205 | edx = dword [c * 108 + eax*4 + 0x480856]; 206 | player_say(current_player, 2, edx); 207 | } 208 | 209 | void break_down_a_house(int a0) 210 | { 211 | static const char *str_break_down_a_house = 212 | "#0185\xb1j\xa8\xee\xa9\xee\xb0\xa3\xa9\xd0\xab\xce\xa4@\xb4\xc9"; 213 | short arr[512]; 214 | 215 | if (a0 == 0) { 216 | int count = 0; 217 | for (int i = 1; i <= dw_498e98; i++) { 218 | struct housing_land *lnd = &hlands[i]; 219 | if (lnd->owner == current_player+1 && lnd->level != 0) { 220 | arr[count] = i; 221 | count++; 222 | } 223 | } 224 | edx = rand() % count; 225 | eax = arr[edx]; 226 | dw_48c5b0 = eax; 227 | draw_some_text(fortune_panel + 0x18, str_break_down_a_house, 24, 330, 0); 228 | graph_st_overlay(fortune_panel + 0x18, dword [current_player * 0x34 + 0x498eb0] + 0x24, 390, 344); 229 | } else { 230 | struct housing_land *lnd = &hlands[dw_48c5b0]; 231 | player_action_2(lnd->x, lnd->y, 2); 232 | fcn.00409b18(1); 233 | fcn.00456c0a(dw_474938, 0x2f440, dw_48c5b0 + 0x7d0, 0xffff); 234 | add_money_to_player(current_player, lnd->level * lnd->house_price, 1); 235 | lnd->level = 0; 236 | lnd->type = 0; 237 | land_house_lost(); 238 | } 239 | } 240 | 241 | void remove_a_land(int a0) 242 | { 243 | short arr[512]; 244 | const char *str_remove_a_land = "#0186\xb1j\xa8\xee\xbcx\xa6\xac\xa4g\xa6\x61\xa4@\xb3\x42"; 245 | 246 | if (a0 == 0) { 247 | int count = 0; 248 | for (int i = 1; i <= dw_498e98; i++) { 249 | struct housing_land *lnd = &hlands[i]; 250 | if (lnd->owner == current_player+1 && lnd->level == 0) { 251 | arr[count] = i; 252 | count++; 253 | } 254 | } 255 | edx = rand() % count; 256 | eax = arr[edx]; 257 | dw_48c5b0 = eax; 258 | draw_some_text(fortune_panel+0x18, str_remove_a_land, 24, 330, 0); 259 | graph_st_overlay(fortune_panel+0x18, dword [current_player * 0x34 + 0x498eb0] + 0x24, 390, 344); 260 | } else { 261 | struct housing_land *lnd = &hlands[dw_48c5b0]; 262 | player_action_2(lnd->x, lnd->y, 2); 263 | fcn.00409b18(1); 264 | fcn.00456c0a(dw_474938, 0x2f440, dw_48c5b0+0x7d0, 0xffff); 265 | add_money_to_player(current_player, lnd->land_price, 1); 266 | lnd->owner = 0; 267 | lnd->flast = 0; 268 | fcn.0040a4e1(0); 269 | land_house_lost(); 270 | } 271 | } 272 | 273 | void fake_loan(int a0) 274 | { 275 | static const char *str_fake_loan = "#0187\xa4H\xc0Y\xb3Q\xb5s\xa5\xce\xab_\xb6U%d\xa4\xb8"; 276 | char buf[128]; 277 | if (a0 == 0) { 278 | dw_48c5b4 = eax = price_index * 10000; 279 | sprintf(buf, str_fake_loan, eax); 280 | draw_some_text(fortune_panel+0x18, buf, 24, 330, 0); 281 | graph_st_overlay(fortune_panel+0x18, dword [current_player * 0x34 + 0x498eb0]+0x30, 390, 344); 282 | } else { 283 | dw_48c5b0 = eax = fcn.0044b896(0, 1); 284 | if (eax == 1) { 285 | player_action_2(0, 0, 3); 286 | fcn.00440cac(0x48c5b8, 1500); 287 | return; 288 | } 289 | if (eax == 2) { 290 | player_action_2(0, 0, 3); 291 | fcn.00440cac(0x48c5b8, 1500); 292 | dw_48c5b4 *= 2; 293 | } 294 | players[current_player].loan = dw_48c5b4; 295 | fcn.00433b7e(current_player); 296 | fcn.0044ba63(current_player, dw_48c5b4, 0); 297 | } 298 | } 299 | 300 | void bank_reject_a_month(int a0) 301 | { 302 | static const char *str_bank_reject = "#0188\xa4\xe4\xb2\xbc\xb8\xf5\xb2\xbc\n" 303 | "\xbb\xc8\xa6\xe6\xa9\xda\xb5\xb4\xa9\xb9\xa8\xd3\xa4@\xad\xd3\xa4\xeb"; 304 | if (a0 == 0) { 305 | draw_some_text(fortune_panel+0x18, str_bank_reject, 24, 330, 0); 306 | graph_st_overlay(fortune_panel+0x18, dword [current_player * 0x34 + 0x498eb0]+0x30, 390, 344); 307 | } else { 308 | dw_48c5b0 = eax = fcn.0044b896(0, 1); 309 | if (eax == 1) { 310 | player_action_2(0, 0, 3); 311 | fcn.00440cac(0x48c5b8, 1500); 312 | } else { 313 | players[current_player].days_rejected_by_bank = 30; 314 | } 315 | } 316 | } 317 | 318 | void invade_bank_computer(int a0) 319 | { 320 | static const char *str_invade = "#0189\xabI\xa4J\xbb\xc8\xa6\xe6\xb9q\xb8\xa3\n" 321 | "\xae\xbf\xa5\xce\xa8\xe4\xa5L\xa4H\xa6s\xb4\xda%d\xa2H"; 322 | 323 | char buf[128]; 324 | 325 | if (a0 == 0) { 326 | dw_48c5b0 = 10; 327 | sprintf(buf, str_invade, 10); 328 | draw_some_text(fortune_panel + 0x18, buf, 24, 330, 0); 329 | graph_st_overlay(fortune_panel + 0x18, [current_player * 0x34 + 0x498eb0] + 0x18, 390, 344); 330 | } else { 331 | float t1 = dw_48c5b0 / 100.0; 332 | for (int i = 0; i < nplayers; i++) { 333 | if (i != current_player 334 | && players[i].who_plays != 0 335 | && players[i].money_in_bank != 0) { 336 | int t2 = trunc(players[i].money_in_bank * t1); 337 | fcn.0041d2c6(i, current_player, t2, 4); 338 | } 339 | } 340 | } 341 | } 342 | 343 | void sell_all_the_stock(int a0) 344 | { 345 | static const char *str_sell = "#0194\xc5\xdc\xbd\xe6\xa9\xd2\xa6\xb3\xaa\xd1\xb2\xbc\xa8\x44\xb2{"; 346 | 347 | if (a0 == 0) { 348 | draw_some_text(fortune_panel + 0x18, str_sell, 24, 330, 0); 349 | graph_st_overlay(fortune_panel + 0x18, dword [current_player * 0x34 + 0x498eb0]+0x24, 390, 344); 350 | } else { 351 | dw_48c5b0 = fcn.0044b896(0, 1); 352 | player_action_2(0, 0, 3); 353 | if (dw_48c5b0 == 1) { 354 | fcn.00440cac(0x48c5b8, 1500); 355 | return; 356 | } else { 357 | for (int i = 0; i < 12; i++) { 358 | int amt = player_stocks[current_player * 12 + i].amount; 359 | if (amt == 0) 360 | continue; 361 | fcn.00428e23(current_player, i, amt, 1); 362 | } 363 | fcn.0041d433(current_player); 364 | int c = players[current_player].character; 365 | ecx = [c * 108 + 0x48085e]; 366 | player_say(current_player, 2, ecx); 367 | fcn.00436b0a(0); 368 | } 369 | } 370 | } 371 | 372 | void sell_all_cards_and_tools(int a0) 373 | { 374 | static const char *str_sell = "#0217\xc5\xdc\xbd\xe6\xa9\xd2\xa6\xb3\xa5\x64\xa4\xf9\xb9\x44\xa8\xe3"; 375 | 376 | if (a0 == 0) { 377 | draw_some_text(fortune_panel + 0x18, str_sell, 24, 330, 0); 378 | graph_st_overlay(fortune_panel + 0x18, dword [current_player * 0x34 + 0x498eb0] + 0x24, 390, 344); 379 | } else { 380 | dw_48c5b0 = fcn.0044b896(1, 1); 381 | player_action_2(0, 0, 3); 382 | if (dw_48c5b0 == 1) { 383 | fcn.00440cac(0x48c5b8, 1500); 384 | } else { 385 | players[current_player].points += fcn.00445b3f(current_player); 386 | players[current_player].points += fcn.00441f21(current_player); 387 | fcn.0041d433(current_player); 388 | int c = players[current_player].character; 389 | player_say(current_player, 2, dword [c * 108 + 0x480856]); 390 | } 391 | } 392 | } 393 | 394 | fortune_call fortune_call_table[] = { 395 | break_down_a_house, 396 | remove_a_land, 397 | fake_loan, 398 | bank_reject_a_month, 399 | invade_bank_computer, 400 | get_one_card_from_each_player, 401 | travel_abroad, 402 | kidnapped_by_alien, 403 | lose_stock, 404 | sell_all_the_stock, 405 | moto_stolen, 406 | car_destroyed, 407 | drowned_to_hospital, 408 | fall_off_moto, 409 | fined_when_crossing_road, 410 | moto_overspeed, 411 | car_overspeed, 412 | invite_others_meal, 413 | fined_for_throwing_trash, 414 | fined_for_your_dog, 415 | pick_money_on_road, 416 | pick_money_on_road2, 417 | pick_money_on_road3, 418 | lose_wallet, 419 | lose_wallet2, 420 | get_heritage, 421 | scammed_money, 422 | win_lottery, 423 | win_lottery2, 424 | win_lottery3, 425 | pay_assurance, 426 | get_assurance, 427 | sell_all_cards_and_tools, 428 | goto_prison_for_drunk, 429 | goto_prison_for_taste, 430 | goto_prison_for_drug, 431 | goto_prison_for_drug2, 432 | goto_prison_for_drunk2, 433 | goto_prison_for_parade, 434 | goto_prison_for_catching_animal, 435 | goto_prison_for_selling_treasure, 436 | goto_prison_for_seducing, 437 | goto_prison_for_taste2, 438 | goto_prison_for_drug3, 439 | goto_prison_for_poisoning, 440 | goto_prison_for_guns, 441 | goto_prison_for_hitting_police, 442 | goto_prison_for_catching_animal2, 443 | goto_prison_for_selling_secret 444 | }; 445 | -------------------------------------------------------------------------------- /csrc/game_init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include "player_info.h" 7 | #include "window_util.h" 8 | #include "stock.h" 9 | #include "graph_struct.h" 10 | 11 | int mkf_jump; // 0x48a3b0 12 | 13 | int initial_fund[6] = { 300000, 200000, 100000, 50000, 30000, 10000 }; // 0x46cb94 14 | int days[6] = { 0, 730, 365, 182, 91, 30 }; // 0x46cbe8 15 | /* wins when total_fund = winning_condition * initial_fund */ 16 | int winning_condition[6] = { 0, 100, 50, 10, 5, 3 }; // 0x46cc00 17 | 18 | int game_initial_fund; // 0x49908c 19 | int traffic_initial; // 0x46cb44 20 | 21 | struct special_player_info default_special_players[5] = { 22 | { .f10 = 1 }, { .f10 = 1 }, { .f10 = 2 }, { .f10 = 2 }, { .f10 = 3 } 23 | }; // 0x47ecec 24 | 25 | void fcn_00445a4d(int a1, int a2) 26 | { 27 | int t = a1 * 15; 28 | 29 | if (byte [a2 + t + 0x49915b] >= 9) 30 | return; 31 | 32 | if (a2 <= 8) { 33 | bh = byte [a2 + 0x49731f]; 34 | if (bh == 0) 35 | return; 36 | cl = bh - 1; 37 | byte [a2 + 0x49731f] = cl; 38 | } 39 | 40 | byte [a2 + t + 0x49915b]++; 41 | } 42 | 43 | int init_new_game(int a0) 44 | { 45 | load_sound_from_mkf(0x46ccd0); 46 | dw_48a354 = malloc(0x96000); 47 | dw_48a358 = malloc(0x96000); 48 | mkf_jump = load_mkf("JUMP.MKF"); 49 | read_mkf(mkf_jump, game_stage * 4 + game_map, dw_48a358, NULL); 50 | fcn_004552b7(dw_48a354, dw_48a358, 0x96000, -16); /* @ bit_functions.c */ 51 | dw_48a3a4 = allocate_graph_st(440, 155, 0, 0); 52 | dw_48a3a0 = allocate_graph_st(192, 461, 0, 0); 53 | dw_48a3b8 = read_mkf(dw_48a3b0, 8, NULL, NULL); 54 | dw_48a3c0 = read_mkf(mkf_data, 2, NULL, NULL); 55 | dw_48a3ac = ebp = 0; 56 | 57 | if (a0 == 0) { 58 | game_map = 0; 59 | memset(0x4990f4, 0, 12); 60 | memset(0x46cb3c, 0, 28); 61 | dw_46cb3c = 2; 62 | dw_46cb40 = 1; 63 | memset(0x48a35c, 0, 48); 64 | } else { 65 | dw_46cb3c = nplayers - 2; 66 | for (int i = 0; i < 6; i++) { 67 | if (game_initial_fund != initial_fund[i]) 68 | continue; 69 | dw_46cb40 = i; 70 | break; 71 | } 72 | traffic_initial = dw_499118; 73 | dw_46cb48 = dw_499110; 74 | edi = dw_49911c; 75 | for (int i = 0; i < 6; i++) { 76 | if (edi != days[i]) 77 | continue; 78 | dw_46cb4c = i; 79 | break; 80 | } 81 | 82 | edx = dw_499108 / game_initial_fund; 83 | 84 | for (int i = 0; i < 6; i++) { 85 | if (edx != winning_condition[i]) 86 | continue; 87 | dw_46cb50 = i; 88 | break; 89 | } 90 | memset(0x48a35c, 0, 48); 91 | eax = players[0].character; 92 | byte [0x4990f4+eax] = 1; 93 | fcn_00404d0a(0, eax); 94 | } 95 | 96 | dw_46cb54 = game_map; /* sign ext */ 97 | 98 | edx = game_stage; /* sign ext */ 99 | eax = edx*20; 100 | edx = eax+1; 101 | eax = edx * 3; 102 | edx = eax * 4; 103 | eax = dw_48a3b8 + 12 + edx; 104 | dw_48a390 = crop_graph(eax, 0, 0x8a, 15, 41, 133); 105 | 106 | edx = game_stage; /* sign ext */ 107 | eax = edx * 20; 108 | edx = eax + 1; 109 | eax = edx * 12; 110 | edx = dw_48a3b8 + 12; 111 | eax += edx; 112 | dw_48a398 = crop_graph(eax, 0, 11, 166, 79, 39); 113 | 114 | edx = game_stage; /* sign ext */ 115 | eax = edx * 20; 116 | edx = eax + 1; 117 | eax = edx * 12; 118 | edx = dw_48a3b8 + 12; 119 | eax += edx; 120 | dw_48a394 = crop_graph(eax, 0, 99, 166, 79, 39); 121 | 122 | edx = game_stage; /* sign ext */ 123 | eax = edx * 20; 124 | edx = eax + 1; 125 | eax = edx * 3; 126 | edx = eax * 4; 127 | eax = dw_48a3b8 + 12 + edx; 128 | dw_48a39c = crop_graph(eax, 0, 157, 216, 23, 24); 129 | 130 | playmid_4549cf(0x8001); /* TODO: 0x4549cf */ 131 | 132 | int res = register_wait_callback(0x404e44, a0); 133 | *(int*)(esp + 4) = res; 134 | unload_mkf(mkf_jump); 135 | 136 | if (res == 1) { 137 | nplayers = dw_46cb3c + 2; 138 | dw_499104 = current_player = 0; 139 | game_initial_fund = initial_fund[dw_46cb40]; 140 | memset(player_cards, 0, 60); 141 | memset(tool_amount, 0, 60); 142 | for (int i = 0; i < 30; i++) { 143 | card_amount[i] = cards_table[i].init_amount; 144 | } 145 | for (ebx = 0; ebx < 8; ebx++) { 146 | al = byte [ebx*8 + 0x47fee6]; 147 | byte [ebx + 0x497320] = al; 148 | } 149 | 150 | for (int i = 0; i < 4; i++) { 151 | int money_in_bank; 152 | if (i >= nplayers) { 153 | memset(&players[i], 0, sizeof(player_info)); 154 | continue; 155 | } 156 | fcn.00445a4d(i, 1); 157 | fcn.00445a4d(i, 2); 158 | fcn.00445a4d(i, 3); 159 | fcn.00445a4d(i, 4); 160 | fcn.00445a4d(i, 8); 161 | fcn.00445a4d(i, 9); 162 | uint32_t character = dword [i * 12 + 0x48a35c]; 163 | memcpy(&players[i], &rich4_players[character & 0xff], sizeof(player_info)); 164 | players[i].f100 = (character >> 31) + 1; 165 | if ((al & 1) == 0) { /* AI players */ 166 | players[i].cash = trunc(players[i].init_cash_ratio * (game_initial_fund / 100.0)); 167 | money_in_bank = game_initial_fund - players[i].cash; 168 | } else { 169 | players[i].cash = money_in_bank = game_initial_fund / 2; 170 | } 171 | players[i].money_in_bank = money_in_bank; 172 | players[i].traffic_method = traffic_initial; 173 | if (traffic_initial != 0) { 174 | eax = traffic_initial; 175 | byte [eax + 0x497323] --; 176 | } 177 | players[i].ndices = traffic_initial + 1; 178 | if (players[i].f100 & 1) { 179 | dw_499104++; 180 | } 181 | } 182 | 183 | memcpy(special_players, default_special_players, sizeof(special_players)); 184 | memset(0x496b30, 0, 8); 185 | memset(0x496b60, 0, 8); 186 | b_496b34 = b_496b35 = b_496b66 = b_496b67 = 1; 187 | dw_499118 = traffic_initial; 188 | dw_499110 = dw_46cb48; 189 | dw_49911c = days[dw_46cb4c]; 190 | dw_499108 = winning_condition[dw_46cb50] * game_initial_fund; 191 | game_map = w_46cb54; 192 | price_index = 1; 193 | dw_4990e4 = dw_499084 = dw_4990dc = dw_4990ec = dw_499100 = esi = 0; 194 | 195 | for (ebx = 0; ebx < 12; ebx++) { 196 | for (edx = 0; edx < 0x90; edx++) { 197 | ecx = ebx * 576; 198 | eax = edx; 199 | esi = 0; 200 | dword [ecx + eax*4 + 0x497328] = 0; 201 | } 202 | } 203 | int _m = game_stage * 4 + game_map; // sign ext 204 | memcpy(stocks, &game_stocks[_m * 12], sizeof(stock_info) * 12); 205 | 206 | float sum = 0; /* esp + 8 */ 207 | 208 | for (int i = 0; i < 12; i++) 209 | sum += stocks[i].f12; 210 | 211 | dw_49907c = trunc(sum * 10.0); 212 | memset(0x4967e0, 0, 336); 213 | memset(player_stocks, 0, 384); 214 | memset(0x4990b8, 0, 36); 215 | dw_499080 = ebp = 0; 216 | fcn.00448b81(); 217 | fcn.0044baea(); 218 | } 219 | 220 | // 4074c9 221 | fcn.00454240(0x46ccd0); 222 | free(dw_48a390); 223 | free(dw_48a398); 224 | free(dw_48a394); 225 | free(dw_48a39c); 226 | for (ebx = 0; ebx < 4; ebx++) { 227 | eax = ebx * 12; 228 | esi = dword [eax + 0x48a364]; 229 | if (esi == 0) 230 | continue; 231 | free(esi); 232 | } 233 | al = 2; 234 | 235 | for (ebx = 0; ebx < 12; ebx++) { 236 | if (byte [ebx + 0x4990f4] == 4) { 237 | byte [ebx + 0x4990f4] = al; 238 | continue; 239 | } 240 | byte [ebx + 0x4990f4] = 0; 241 | } 242 | 243 | free(dw_48a3a0); 244 | free(dw_48a3a4); 245 | free(dw_48a3c0); 246 | free(dw_48a3b8); 247 | free(dw_48a358); 248 | free(dw_48a354); 249 | eax = *(int*)(esp + 4); 250 | return eax; 251 | } 252 | -------------------------------------------------------------------------------- /csrc/global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | /* media_init.c */ 11 | extern IDirectDraw *pddraw; // 0x0048a0d8 12 | 13 | extern DDSURFACEDESC sfdesc1; // 0x0048a068 14 | extern IDirectDrawSurface *pddrawsf1; // 0x0048a0dc 15 | extern IDirectDrawSurface *pddrawsf2; // 0x0048a0e0 16 | extern IDirectDrawSurface *pddrawsf3; // 0x004762cc 17 | 18 | extern int mkf_data; // 0x48a0e4 19 | extern int mkf_speaking; // 0x48a054 20 | extern int mkf_panel; // 0x48a05c 21 | extern int mkf_effect; // 0x48a058 22 | 23 | extern HHOOK ghook; // 0x48a050 24 | 25 | extern int pixel_fmt; 26 | 27 | char * read_mkf(int mkf_idx, int a1, char *buf, int *bufsize); 28 | 29 | /* main.c */ 30 | extern HINSTANCE ghInstance; // 48a064 31 | extern HWND gwindowHandle; // 48a0d4 32 | extern RECT g_rect; /* struct tagRECT { left, top, right, bottom } @ 0x46cadc */ 33 | extern int16_t game_stage; 34 | extern int16_t game_map; 35 | extern int price_index; 36 | extern char mid_status[7]; // 0x46cb00 37 | 38 | /* card.c */ 39 | extern uint8_t card_amount[30]; 40 | 41 | /* misc.c */ 42 | extern char b_46caf8; 43 | extern char b_46caf9; 44 | extern char b_46cafa; 45 | extern char b_46cafb; 46 | extern char b_46cafc; 47 | extern char b_46cafd; 48 | -------------------------------------------------------------------------------- /csrc/land.h: -------------------------------------------------------------------------------- 1 | struct housing_land 2 | { 3 | int16_t x, y; 4 | char name[]; // 0x04 5 | uint8_t price_status; // 0x17 6 | uint8_t type; // 0x18: chained store or house 7 | uint8_t owner; // 0x19 8 | uint8_t level; // 0x1a 9 | uint16_t land_price; // 0x1c 10 | uint16_t house_price; // 0x1e 11 | uint32_t flast; // 0x30 12 | }; /* size is 0x34=52 */ 13 | 14 | struct business_land 15 | { 16 | char name[]; // 0x04 17 | uint8_t type; // 0x18 18 | uint8_t owner; // 0x19 19 | uint8_t level; // 0x1a 20 | uint8_t price_status; // 0x1c 21 | uint16_t land_price; // 0x22 22 | uint16_t house_price; // 0x24 23 | uint32_t _; // 0x34 24 | }; /* size is 0x38=56 */ 25 | 26 | extern struct housing_land *hlands; // @0x498e84 27 | extern struct business_land *blands; // @0x498e88 28 | -------------------------------------------------------------------------------- /csrc/loadsave.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include 8 | #include "global.h" 9 | #include "player_info.h" 10 | #include "mkf/mkf.h" 11 | #include "stock.h" 12 | #include "land.h" 13 | 14 | char *dw_47493c; 15 | char *dw_474945; 16 | char *dw_474949; 17 | char *dw_47494d; 18 | char *dw_48ae60; 19 | char *dw_48ae64[16]; 20 | char *dw_48aea8; 21 | char *dw_48bad0; 22 | char *dw_48badc; 23 | char *dw_496930[20]; 24 | 25 | void show_loading_scene() 26 | { 27 | char *ebx = read_mkf(mkf_data, 0x259, NULL, NULL); 28 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, NULL); 29 | memcpy(sfdesc1.lpSurface, ebx, 0x96000 /* 640*480*2 */); 30 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 31 | IDirectDrawSurface_BltFast(pddrawsf1, g_rect.left, g_rect.top, 32 | pddrawsf2, &g_rect, 16); 33 | free(ebx); 34 | /* TODO: fcn.00454edc() */ 35 | } 36 | 37 | void fcn_0040e033(int a1, int a2, a3, a4) 38 | { 39 | switch (a1 - 0xf) { 40 | case 0: 41 | ebx = 14; 42 | ecx = 16; 43 | break; 44 | case 1: 45 | ebx = 16; 46 | ecx = 26; 47 | break; 48 | case 2: 49 | ebx = 26; 50 | ecx = 36; 51 | break; 52 | case 3: 53 | ebx = 36; 54 | ecx = 46; 55 | break; 56 | default: 57 | ebx = a1 - 1; 58 | ecx = a1; 59 | } 60 | label_40e082: 61 | if (ebx >= ecx) { 62 | return ebx + 1; 63 | } 64 | eax = ebx * 24; 65 | edx = ebx + 1; 66 | if (*(int16_t*)(0x496d0a+eax) != 0) { 67 | ebx = edx; 68 | goto label_40e082; 69 | } 70 | *(int16_t*)(0x496d0a + eax) = a2; 71 | *(int8_t*)(0x496d0c + eax) = a3; 72 | *(int8_t*)(0x496d0d + eax) = a4; 73 | if (a4 != 0 && a1 == 0xf) { 74 | fcn_0040ead7(ecx - 1, 0, edx); 75 | } 76 | if (a2 == 0) { 77 | return ebx + 1; 78 | } 79 | for (edx = 0; edx < 4; edx++) { 80 | eax = dw_498e80 + a2 * 40; 81 | ecx = edx; 82 | eax = *(int16_t*)(eax + ecx * 2 + 0x18); 83 | if (eax != 0) 84 | break; 85 | } 86 | edx = fcn_00407a8c(eax, a2); 87 | eax = ebx * 3; 88 | *(char*)(0x496d09+eax*8) = edx; 89 | eax = a2 * 40 + dw_498e80; 90 | edx = ebx + 1; 91 | edx <<= 16; 92 | *(int32_t*)(eax + 0x24) |= edx; 93 | return ebx + 1; 94 | } 95 | 96 | struct spr_smp *data_0205; // @ 0x48bad8 97 | struct spr_smp *data_0207; // @ 0x48bad4 98 | 99 | void fcn_00407ad2() 100 | { 101 | fcn_004080f5(); 102 | int mkf_map_ = load_mkf("MAP.MKF"); 103 | int gmap = game_stage * 4 + game_map; 104 | dw_474945 = read_mkf(mkf_map_, gmap * 2, NULL, NULL); 105 | dw_48badc = read_mkf(mkf_map_, gmap + 16, NULL, NULL); 106 | dw_48bad0 = read_mkf(mkf_map_, gmap + 16, NULL, NULL); 107 | memcpy(0x48b6b4, dw_474945 + 0x10, 512); 108 | dw_48bac4 = *(int*)dw_474945 + 0x210; 109 | dw_48bacc = *(int*)dw_474945 + 10896; /* 0x2a90 = 10896 */ 110 | dw_474949 = read_mkf(mkf_map_, 24, NULL, NULL); 111 | dw_47494d = read_mkf(mkf_map_, 26, NULL, NULL); 112 | 113 | if (dw_47493c == 0) { 114 | int mkf_map_dat = load_mkf("MAPDAT.MKF"); 115 | if (mkf_map_dat != -1) { 116 | dw_47493c = read_mkf(mkf_map_dat, gmap, NULL, NULL); 117 | unload_mkf(mkf_map_dat); 118 | } else { 119 | dw_47493c = read_mkf(mkf_map_, gmap * 2 + 1, NULL, NULL); 120 | } 121 | /* 0x407c3f */ 122 | int *eax = dw_47493c; 123 | dw_498e9c = eax[0]; 124 | dw_498e80 = &eax[eax[1]]; 125 | dw_498e98 = eax[2]; 126 | hlands = &eax[eax[3]]; 127 | dw_498e8c = eax[4]; 128 | blands = &eax[eax[5]]; 129 | dw_498e90 = eax[6]; 130 | dw_498e7c = &eax[eax[7]]; 131 | dw_499074 = eax[8]; 132 | dw_498e78 = &eax[eax[9]]; 133 | edx = dw_499074 * 4; 134 | ebx = edx; 135 | edx *= 8; 136 | edx -= ebx; 137 | ebx = dw_498e78; 138 | edx += ebx; 139 | edx += 0x1c; 140 | edx -= eax; 141 | dw_498e94 = edx; 142 | 143 | for (ebx = 0; ebx < nplayers; ebx++) { 144 | esi = ebx * 10008; 145 | eax = 0x48cb80 + esi; 146 | memset(eax, 0, 0x2718); 147 | *(int*)(0x48f294 + esi) = malloc(dw_498e94); 148 | memset(0x48f294 + esi, 0, dw_498e94); 149 | } 150 | /* 407d3a */ 151 | memset(0x496d08, 0, 0x450); 152 | 153 | for (ebx = 0; ebx < 0x2e; ebx++) { 154 | eax = ebx * 3; 155 | dl = *(char*)(0x47ed3c + ebx); 156 | *(char*)(0x496d08 + eax * 8) = dl; 157 | } 158 | 159 | for (ebx = 1; ebx <= 11; ebx += 2) { 160 | fcn_0040e033(ebx, fcn_0040aa6c(0), 0, 0); 161 | } 162 | 163 | fcn_0040e033(13, fcn_0040aa6c(0), 0, 0); 164 | fcn_0040e033(14, fcn_0040aa6c(0), 0, 0); 165 | 166 | for (ebx = 1; ebx < dw_498e90; ebx++) { 167 | esi = ebx * 0x34; 168 | eax = dw_498e7c; 169 | esi += eax; 170 | edx = *(char*)(esi + 25); 171 | edx = 0x2710 - stocks[edx].f8; 172 | *(int*)(esi + 0x30) = edx; 173 | } 174 | fcn_0042915a(); 175 | dw_499088 = 0; 176 | } 177 | /* 0x407e0b */ 178 | for (int i = 0; i < 5; i++) { 179 | *(int*)(0x48ae4c + i*4) = read_mkf(mkf_map_, gmap * 5 + 39 + i, NULL, NULL); 180 | } 181 | dw_48ae60 = read_mkf(mkf_map_, gmap + 79, NULL, NULL); 182 | if (game_stage == 0) { 183 | for (int i = 0; i < 17; i++) { 184 | dw_48ae64[i] = read_mkf(mkf_map_, 87 + i, NULL, NULL); 185 | } 186 | } else { 187 | int b = game_map * 17 + 104; 188 | for (int i = 0; i < 17; i++) { 189 | dw_48ae64[i] = read_mkf(mkf_map_, b + i, NULL, NULL); 190 | } 191 | } 192 | for (ebx = 1; ebx <= dw_498e90; ebx++) { 193 | eax = ebx * 0x34; 194 | edx = dw_498e7c; 195 | eax = *(uint16_t*)(edx + eax + 0x20); 196 | if (eax == 0) 197 | continue; 198 | esi = eax * 4; 199 | ebp = *(int32_t*)(0x48ae4c + esi); 200 | if (ebp != 0) 201 | continue; 202 | eax += 0x26; 203 | *(int32_t*)(0x48ae4c+esi) = read_mkf(mkf_map_, eax, NULL, NULL); 204 | } 205 | for (ebx = 1; ebx <= dw_499074; ebx++) { 206 | edx = eax * 28; 207 | eax = dw_498e78; 208 | eax = *(uint16_t*)(edx + eax + 0x1a); 209 | if (eax == 0) 210 | continue; 211 | esi = eax * 4; 212 | edx = *(int32_t*)(0x48ae4c + esi); 213 | if (edx != 0) 214 | continue; 215 | eax += 0x26; 216 | *(int32_t*)(0x48ae4c+esi) = read_mkf(mkf_map_, eax, NULL, NULL); 217 | } 218 | dw_48aea8 = read_mkf(mkf_map_, 0x19, 0, 0); 219 | 220 | #if 0 221 | /* structure with size 0x34 @ 0x498ea0 is */ 222 | struct { 223 | int8_t b0, b1, b2, b3, b4, b5; 224 | int8_t padding[10]; 225 | char *f16; // 0x498eb0 226 | int32_t f20; // 0x498eb4 227 | int32_t f24; // 0x498eb8 228 | int32_t f28; // 0x498ebc 229 | int32_t f32; // 0x498ec0 230 | int32_t f36; // 0x498ec4 231 | int32_t f40; // 0x498ec8 232 | int32_t f44; // 0x498ecc 233 | int32_t padding; 234 | }; 235 | #endif 236 | memset(0x498ea0, 0, 0x34 * 9); 237 | for (int i = 0; i < 9; i++) { 238 | if (i >= nplayers) { 239 | if (i >= 4) { 240 | fcn_0040b93b(i); 241 | } 242 | continue; 243 | } 244 | 245 | edx = read_mkf(mkf_map_, players[i].character + 0x1b, NULL, NULL); 246 | eax = i * 0x34; 247 | *(int32_t*)(0x498eb0+eax) = edx; 248 | 249 | if (players[i].who_plays == 0 && player[i].f100 == 0) { 250 | eax = *(int32_t*)(0x498eb0+eax); 251 | edx = *(int16_t*)(eax + 0xe); /* sign ext */ 252 | eax += 0xc; 253 | fcn_004553fe(eax, 0, 0, *(int16_t*)eax, edx); 254 | } 255 | if (i >= nplayers) { 256 | if (edx < 4) 257 | continue; 258 | fcn_0040b93b(i); 259 | } 260 | } 261 | 262 | unload_mkf(mkf_map_); 263 | edi = dw_498e9c; 264 | for (ebx = 1; ebx <= edi; ebx++) { 265 | eax = ebx * 5; 266 | edx = dw_498e80; 267 | if (*(int16_t*)(edx + eax * 8 + 0x20) == 0x1f41) 268 | *(int16_t*)0x48bae2 = (int16_t)ebx; 269 | edx = ebx * 40; 270 | eax = dw_498e80; 271 | if (*(int16_t*)(edx + eax + 0x20) == 0x1f42) 272 | *(int16_t*)0x48bae0 = (int16_t)ebx; 273 | } 274 | fcn_00428caf(); 275 | data_0205 = read_mkf(mkf_data, 0x205, NULL, NULL); 276 | data_0207 = read_mkf(mkf_data, 0x207, NULL, NULL); 277 | for (int i = 0; i < 20; i++) { 278 | dw_496930[i] = read_mkf(mkf_data, 396 + i, NULL, NULL); 279 | } 280 | fcn_00454176(0x48234a); 281 | fcn_0040a4e1(0); 282 | } 283 | 284 | void fcn_004080f5() 285 | { 286 | } 287 | 288 | int load_checkpoint(int n) 289 | { 290 | char filename[16]; 291 | 292 | sprintf(filename, "SAVE%d.DAT", n); 293 | FILE *fp = fopen(filename, "rb"); 294 | if (fp == NULL) { 295 | return 0; 296 | } 297 | show_loading_scene(); 298 | ebp = timeGetTime(); /* esi = 0 */ 299 | fcn_004080f5(); 300 | 301 | fseek(fp, 4, SEEK_SET); 302 | fread(&global_rich4_cfg.day, 4, 1, fp); // read day,month,year 303 | fread(&game_map, 2, 1, fp); 304 | fread(&game_stage, 2, 1, fp); 305 | fread(&nplayers, 4, 1, fp); 306 | fread(players, sizeof(player_info), 4, fp); 307 | fread(0x499104, 4, 1, fp); 308 | 309 | for (int i = 0; i < nplayers; i++) { 310 | uint8_t j = players[i].character; 311 | players[i].name_ptr = rich4_players[j].name_ptr; 312 | } 313 | 314 | fread(special_players, 0x10, 5, fp); 315 | fread(0x496d08, 0x18, 0x2e, fp); 316 | fread(player_cards, 1, 0x3c, fp); 317 | fread(tool_amount, 1, 0x3c, fp); 318 | fread(card_amount, 1, 30, fp); 319 | fread(0x497320, 1, 8, fp); 320 | fread(0x499100, 4, 1, fp); 321 | fread(0x497328, 4, 0x6c0, fp); 322 | fread(player_stocks, sizeof(player_stock_info), 48, fp); 323 | 324 | /* 12 stocks */ 325 | fread(stocks, sizeof(stock_info), 12, fp); 326 | for (int i = 0; i < 12; i++) { 327 | int m = game_stage * 4 + game_map; 328 | int idx = m * 12 + i; 329 | stocks[i].name_ptr = game_stocks[idx].name_ptr; 330 | } 331 | 332 | fread(0x4967e0, 0xc, 0x1c, fp); 333 | fread(¤t_player, 4, 1, fp); 334 | fread(0x499118, 4, 1, fp); 335 | fread(0x499110, 4, 1, fp); 336 | fread(0x49911c, 4, 1, fp); 337 | fread(0x499108, 4, 1, fp); 338 | fread(0x49908c, 4, 1, fp); 339 | fread(&price_index, 4, 1, fp); 340 | fread(0x4990e4, 4, 1, fp); 341 | fread(0x499084, 4, 1, fp); 342 | fread(0x4990dc, 4, 1, fp); 343 | fread(0x49907c, 4, 1, fp); 344 | fread(0x499078, 4, 1, fp); 345 | fread(0x4990ec, 4, 1, fp); 346 | fread(0x4990f0, 1, 4, fp); 347 | fread(0x4990f4, 1, 0xc, fp); 348 | fread(0x499080, 4, 1, fp); 349 | fread(0x4990b8, 1, 0x24, fp); 350 | fread(0x496b30, 1, 8, fp); 351 | fread(0x496b60, 1, 8, fp); 352 | fread(0x4990e0, 4, 1, fp); 353 | fread(0x4990b4, 4, 1, fp); 354 | fread(0x499090, 1, 0x24, fp); 355 | fread(0x496b38, 1, 0x25, fp); 356 | fread(0x499088, 4, 1, fp); 357 | fread(0x498e94, 4, 1, fp); 358 | 359 | dw_0x47493c = malloc(*(int*)0x498e94); 360 | fread(dw_0x47493c, 1, *(int*)0x498e94, fp); 361 | 362 | eax = *(int*)0x47493c; 363 | edx = *(int*)eax; 364 | *(int*)0x498e9c = edx; 365 | edx = *(int*)(eax + 4); 366 | ebx = eax + edx; 367 | *(int*)0x498e80 = ebx; 368 | edx = *(int*)(eax + 8); 369 | *(int*)0x498e98 = edx; 370 | edx = *(int*)(eax + 12); 371 | ebx = eax + edx; 372 | hlands = ebx; 373 | edx = *(int*)(eax + 16); 374 | *(int*)0x498e8c = edx; 375 | edx = *(int*)(eax + 20); 376 | ebx = eax + edx; 377 | blands = ebx; 378 | edx = *(int*)(eax + 24); 379 | *(int*)0x498e90 = edx; 380 | edx = *(int*)(eax + 28); 381 | ebx = eax + edx; 382 | *(int*)0x498e7c = ebx; 383 | edx = *(int*)(eax + 32); 384 | *(int*)0x499074 = edx; 385 | edx = *(int*)(eax + 36); 386 | eax += edx; 387 | *(int*)0x498e78 = eax; 388 | 389 | for (int i = 0; i < nplayers; i++) { 390 | esi = i * 0x2718; 391 | fread(0x48cb80 + esi, 0x2718, 1, fp); 392 | *(int*)(0x48f294 + esi) = malloc(*(int*)0x498e94); 393 | fread(*(int*)(0x48f294+esi), 1, *(int*)0x498e94, fp); 394 | } 395 | fcn_00407ad2(); 396 | eax = current_player * 0x34; 397 | *(char*)(0x498ea0 + eax) |= 0x80; 398 | srand(GetTickCount()); 399 | 400 | while (timeGetTime()-ebp < 1000) 401 | ; 402 | fclose(fp); 403 | return 1; 404 | } 405 | -------------------------------------------------------------------------------- /csrc/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include 8 | #include "global.h" 9 | #include "window_util.h" 10 | #include "mkf.h" 11 | #include "drawing.h" 12 | #include "misc.h" 13 | 14 | HINSTANCE ghInstance; // 48a064 15 | HWND gwindowHandle; // 48a0d4 16 | RECT g_rect; 17 | 18 | char mid_status[7]; // 0x46cb00 19 | 20 | typedef struct { int16_t x; int16_t y; } pos_t; 21 | static pos_t mpos[5] = { // central position of the buttons @0x46cb28 22 | {190, 380}, // start 23 | {328, 380}, // load 24 | {468, 378}, // options 25 | {328, 450}, // exit 26 | {62, 380} // new stage 27 | }; 28 | 29 | int16_t game_stage; 30 | int16_t game_map; 31 | int price_index; 32 | 33 | static struct spr_smp *data1; // 0x48a180 34 | 35 | void deinit_game(void); 36 | 37 | static void fcn_0045174a(void) 38 | { 39 | mid_status[2] = 0; 40 | Post_0402_Message(0); 41 | } 42 | 43 | static LRESULT CALLBACK windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 44 | { 45 | static int initiated = 0; 46 | 47 | if (message < 0x1c) { 48 | if (message == WM_DESTROY) { 49 | deinit_game(); 50 | PostQuitMessage(0); 51 | return 0; 52 | } 53 | if (windowCallbacks[cb_top] == NULL) { 54 | return DefWindowProcA(hWnd, message, wParam, lParam); 55 | } else { 56 | return (windowCallbacks[cb_top](hWnd, message, wParam, lParam)); 57 | } 58 | } 59 | if (message == WM_ACTIVATEAPP) { 60 | if (wParam != 0) { 61 | if (initiated != 0) { 62 | if (pddrawsf1 != NULL) { 63 | IDirectDrawSurface_Restore(pddrawsf1); 64 | } 65 | if (mid_status[2] != 0) { 66 | mciSendStringA("resume vfw", 0, 0, 0); 67 | } 68 | if (mid_status[3] != 0) { 69 | mciSendStringA("resume mid", 0, 0, 0); 70 | } 71 | if (mid_status[4] != 0) { 72 | mciSendStringA("play cdtrack notify", 0, 0, gwindowHandle); 73 | } 74 | } 75 | SetFocus(hWnd); 76 | mid_status[1] = 1; 77 | return 0; 78 | } 79 | initiated = 1; 80 | mid_status[1] = 0; 81 | if (mid_status[2] != 0) { 82 | mciSendStringA("pause vfw", 0,0,0); 83 | } 84 | if (mid_status[3] != 0) { 85 | mciSendStringA("pause mid", 0, 0, 0); 86 | } 87 | if (mid_status[4] != 0) { 88 | mciSendStringA("stop cdtrack", 0, 0, 0); 89 | } 90 | return 0; 91 | } 92 | if (message == MM_MCINOTIFY) { 93 | if (wParam != 1) 94 | return 0; 95 | if (mid_status[2] != 0) { 96 | fcn_0045174a(); 97 | return 0; 98 | } 99 | playmid_454d2c(); 100 | return 0; 101 | } 102 | if (windowCallbacks[cb_top] == NULL) { 103 | return DefWindowProcA(hWnd, message, wParam, lParam); 104 | } else { 105 | return (windowCallbacks[cb_top](hWnd, message, wParam, lParam)); 106 | } 107 | } 108 | 109 | static LRESULT CALLBACK entryCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 110 | { 111 | static int status; 112 | 113 | if (message >= 0x200) { 114 | if (message == WM_MOUSEMOVE) { 115 | int xPos = LOWORD(lParam); 116 | int yPos = HIWORD(lParam); 117 | int tmp = status; 118 | RECT r0; // @ esp + 0x40 119 | 120 | int i; 121 | for (i = 0; i < 5; i++) { 122 | int idx = i * 2 + 2; 123 | r0.left = mpos[i].x - data1->chunk_tab[idx].x; 124 | r0.top = mpos[i].y - data1->chunk_tab[idx].y; 125 | r0.right = r0.left + data1->chunk_tab[idx].width; 126 | r0.bottom = r0.top + data1->chunk_tab[idx].height; 127 | if (xPos < r0.left) 128 | continue; 129 | if (yPos < r0.top) 130 | continue; 131 | if (xPos >= r0.right) 132 | continue; 133 | if (yPos >= r0.bottom) 134 | continue; 135 | if (i == status) 136 | break; 137 | status = i; 138 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 139 | fullscreen_overlay(sfdesc1.lpSurface, &data1->chunk_tab[idx], mpos[i].x, mpos[i].y); 140 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 141 | InvalidateRect(hWnd, &r0, FALSE); 142 | fcn_4542ce(0x48231a, 0); 143 | break; 144 | } 145 | if (i == 5) 146 | status = -1; 147 | if (tmp == status) 148 | return 0; 149 | if (tmp == -1) 150 | return 0; 151 | 152 | int idx = tmp * 2 + 2; 153 | r0.left = mpos[tmp].x - data1->chunk_tab[idx].x; 154 | r0.top = mpos[tmp].y - data1->chunk_tab[idx].y; 155 | r0.right = r0.left + data1->chunk_tab[idx].width; 156 | r0.bottom = r0.top + data1->chunk_tab[idx].height; 157 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 158 | overlay_fullwidth(sfdesc1.lpSurface, &data1->chunk_tab[0], 159 | r0.left, r0.top, r0.left, r0.top, 160 | r0.right - r0.left, r0.bottom - r0.top); 161 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 162 | InvalidateRect(hWnd, &r0, FALSE); 163 | return 0; 164 | } 165 | if (message == WM_LBUTTONDOWN) { 166 | if (status != -1) { 167 | fcn_4542ce(0x482322, 0); 168 | } 169 | // 0x402638 170 | switch (status) { 171 | case 1: 172 | fcn_00402460(0); 173 | if (load_ui(0) != -1) { 174 | Post_0402_Message(status); 175 | break; 176 | } 177 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 178 | overlay_fullscreen(sfdesc1.lpSurface, &data1->chunk_tab[0], 0, 0); 179 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 180 | fcn_00402460(1); 181 | InvalidateRect(hWnd, NULL, FALSE); 182 | break; 183 | case 2: 184 | fcn_00402460(0); 185 | close_mid_454acb(); 186 | options_ui(0); 187 | playmid_4549cf(0); 188 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 189 | overlay_fullscreen(sfdesc1.lpSurface, &data1->chunk_tab[0], 0, 0); 190 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 191 | fcn_00402460(1); 192 | return 0; 193 | case 0: 194 | case 3: 195 | case 4: 196 | fcn_00402460(0); 197 | Post_0402_Message(status); 198 | break; 199 | default: 200 | break; 201 | } 202 | return 0; 203 | } 204 | if (message == 0x401) { 205 | status = -1; 206 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 207 | overlay_fullscreen(sfdesc1.lpSurface, &data1->chunk_tab[0], 0, 0); 208 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 209 | InvalidateRect(hWnd, NULL, FALSE); 210 | fcn_00402460(1); 211 | return 0; 212 | } 213 | return DefWindowProcA(hWnd, message, wParam, lParam); 214 | } 215 | if (message == WM_PAINT) { 216 | PAINTSTRUCT ps; 217 | BeginPaint(hWnd, &ps); 218 | GetCursorPos_35d(&ps.rcPaint); 219 | IDirectDrawSurface_BltFast(pddrawsf1, ps.rcPaint.left, ps.rcPaint.top, pddrawsf2, &ps.rcPaint, DDBLTFAST_WAIT); 220 | GetCursorPos_250(&ps.rcPaint); 221 | EndPaint(hWnd, &ps); 222 | return 0; 223 | } 224 | return DefWindowProcA(hWnd, message, wParam, lParam); 225 | } 226 | 227 | static int ui_entry() 228 | { 229 | data1 = (struct spr_smp*)read_mkf(mkf_data, 1, NULL, NULL); 230 | 231 | for (int i = 0; i < 5; i++) { 232 | graph_st_overlay(&data1->chunk_tab[0], &data1->chunk_tab[i * 2 + 1], 233 | mpos[i].x, mpos[i].y); 234 | } 235 | 236 | create_some_font(0x10, 0xf0f0f0, 0x101010, 3, 1); 237 | draw_some_text(&data1->chunk_tab[0], "V3.11", 638, 470, 6); 238 | playmid_4549cf(0); 239 | int ret = register_wait_callback(entryCallback, 0); 240 | close_mid_454acb(); 241 | free(data1); 242 | return ret; 243 | } 244 | 245 | void deinit_game() 246 | { 247 | if (mid_status[5] == 0) { 248 | sub.WINMM.dll_timeGetTime_3c4(); 249 | free(dw_474938); 250 | deinit_data_and_timer(); 251 | sub.WINMM.dll_mciSendStringA_8ef(); 252 | unload_mkf(mkf_effect); 253 | unload_mkf(mkf_panel); 254 | unload_mkf(mkf_speaking); 255 | unload_mkf(mkf_data); 256 | sub.USER32.dll_KillTimer_228(); 257 | deinit_font(); 258 | UnhookWindowsHookEx(&ghook); 259 | fcn.00454240(0x48231a); 260 | fcn.00453d28(); 261 | if (pddrawsf2 != NULL) { 262 | IDirectDrawSurface_Release(pddrawsf2); 263 | } 264 | if (pddrawsf1 != NULL) { 265 | IDirectDrawSurface_Release(pddrawsf1); 266 | } 267 | if (pddraw != NULL) { 268 | IDirectDraw_Release(pddraw); 269 | } 270 | mid_status[5] = 1; 271 | } 272 | } 273 | 274 | static void start_game_loop(int a0) 275 | { 276 | cb_top++; 277 | windowCallbacks[cb_top] = some_game_loop_func; 278 | PostMessageA(gwindowHandle, 0x401, 0, 0); 279 | 280 | byte [current_player * 0x34 + 0x498ea0] |= 0x80; 281 | if (a0 != 0) { 282 | sub.WINMM.dll_mciSendStringA_d91(0); 283 | } 284 | } 285 | 286 | char *panel_0; // @ 0x48be0c 287 | char *panel_1; // @ 0x475118 288 | char *panel_2; // @ 0x48be10 289 | char *panel_3; // @ 0x48be14 290 | char *panel_7; // @ 0x48be04 291 | char *panel_8; // @ 0x48be08 292 | char *panel_456[3]; // @ 0x48bdf8 293 | 294 | struct graph_st *gst_48bdcc; 295 | struct graph_st *gst_48bde0; 296 | RECT rect_48bdb8; 297 | 298 | static void fcn_004190cf() 299 | { 300 | if (panel_1 != NULL) 301 | return; 302 | 303 | panel_0 = read_mkf(mkf_panel, 0, NULL, NULL); 304 | panel_1 = read_mkf(mkf_panel, 1, NULL, NULL); 305 | panel_2 = read_mkf(mkf_panel, 2, NULL, NULL); 306 | panel_3 = read_mkf(mkf_panel, 3, NULL, NULL); 307 | panel_7 = read_mkf(mkf_panel, 7, NULL, NULL); 308 | panel_8 = read_mkf(mkf_panel, 8, NULL, NULL); 309 | 310 | for (int i = 0; i < 3; i++) { 311 | panel_456[i] = read_mkf(mkf_panel, i + 4, NULL, NULL); 312 | } 313 | 314 | gst_48bdcc = allocate_graph_st(200, 200, 0, 0); 315 | gst_48bde0 = allocate_graph_st(data_0205->chunk_tab[0].width, 316 | data_0205->chunk_tab[0].height, 0, 0); 317 | rect_48bdb8.left = 220 - data_0205->chunk_tab[5].x; 318 | rect_48bdb8.top = 140 - data_0205->chunk_tab[5].y; 319 | rect_48bdb8.right = rect_48bdb8.left + data_0205->chunk_tab[5].width; 320 | rect_48bdb8.bottom = rect_48bdb8.top + data_0205->chunk_tab[5].height; 321 | } 322 | 323 | int WINAPI WinMain(HINSTANCE hInstance, 324 | HINSTANCE hPrevInstance, 325 | LPSTR lpCmdLine, 326 | int nCmdShow) 327 | { 328 | ghInstance = hInstance; 329 | WNDCLASS wc = { 330 | .style = 0, 331 | .lpfnWndProc = windowProc, 332 | .cbClsExtra = 0, 333 | .cbWndExtra = 0, 334 | .hInstance = hInstance, 335 | .hIcon = LoadIconA(hInstance, "RICH4_ICON"), // esp+0x14 336 | .hCursor = LoadCursorA(0, IDC_ARROW), // esp+0x18 337 | .hbrBackground = GetStockObject(4), // esp + 0x1c 338 | .lpszMenuName = NULL, 339 | .lpszClassName = "Rich4" 340 | }; // @ esp 341 | 342 | if (RegisterClassA(&wc) == 0) { 343 | return -1; 344 | } 345 | int height = GetSystemMetrics(1); 346 | int width = GetSystemMetrics(0); 347 | gwindowHandle = CreateWindowExA(0, "Rich4", "Rich4", WS_POPUP, 0, 0, width, height, NULL, NULL, ghInstance, NULL); 348 | int ret = initialize(); 349 | if (ret == 0) { 350 | return 0; 351 | } 352 | ShowWindow(gwindowHandle, SW_SHOW); 353 | UpdateWindow(gwindowHandle); 354 | play_avi("START.AVI", &g_rect, 1); 355 | 356 | case_401de8_0: 357 | game_stage = 0; 358 | game_map = 0; 359 | dw_4990f0 = 0; 360 | b_46cafc = 0; 361 | ret = ui_entry(); 362 | 363 | L401cb3: 364 | switch (ret) { 365 | case 4: 366 | game_stage = 1; 367 | // fallthrough 368 | case 0: 369 | if (init_new_game((int)b_46cafc)==0) 370 | goto case_401de8_0; 371 | show_loading_scene(); 372 | fcn_00407ad2(); 373 | fcn_004190cf(); 374 | fcn_004291d6(); 375 | fcn_00415872(); 376 | b_46cafc = 1; 377 | start_game_loop(0); 378 | break; 379 | case 1: 380 | switch_401cb8_case_1: 381 | fcn_004190cf(); 382 | b_46cafc = 1; 383 | start_game_loop(1); 384 | break; 385 | case 3: 386 | deinit_game(); 387 | DestroyWindow(gwindowHandle); 388 | break; 389 | default: /* also case 2 */ 390 | break; 391 | } 392 | 393 | start_msg_loop: 394 | 395 | do { 396 | MSG msg; 397 | while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { 398 | if (msg.message == WM_QUIT) 399 | return msg.wParam; 400 | TranslateMessage(&msg); 401 | DispatchMessage(&msg); 402 | } 403 | } while (mid_status[1] == 0); 404 | 405 | if (dw_475110 != 0) 406 | fcn_004192f7(); 407 | if (b_46cafa != 0) 408 | fcn_0040d7c4(); 409 | eax = current_player * 0x34; 410 | if (b_498ea2[eax] == 0) { 411 | if (b_498ea0[eax] != 0x80) { 412 | dl = b_498ea0[eax] & 0x7f; 413 | b_498ea0[eax] = dl; 414 | sub_SetCursorPos_c55(); 415 | } 416 | } 417 | if (b_46caf8 == 0) 418 | goto loop_end; 419 | mid_status[6] = 0; 420 | bl = b_46caf8; 421 | sub_KillTimer_228(); 422 | fcn_004019d2(); 423 | b_46caf8 = 0; 424 | eax = (int)bl - 1; 425 | switch (eax) { 426 | case 0: 427 | goto case_401de8_0; 428 | case 1: 429 | ret = 0; 430 | fcn_004075c1(); 431 | if (b_46caf9 == 0) 432 | goto L401cb3; 433 | break; 434 | case 2: 435 | fcn_004075c1(); 436 | goto case_401de8_0; 437 | case 3: 438 | if (load_ui(0) == -1) 439 | goto case_401de8_0; 440 | goto switch_401cb8_case_1; 441 | default: 442 | break; 443 | } 444 | 445 | loop_end: 446 | 447 | if (b_46caf9 == 0) 448 | goto start_msg_loop; 449 | fcn_00451b36(); 450 | deinit_game(); 451 | DestroyWindow(gwindowHandle); 452 | goto start_msg_loop; 453 | } 454 | -------------------------------------------------------------------------------- /csrc/misc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include "global.h" 8 | 9 | char b_47e772; 10 | 11 | void playmid_4549cf(int x) 12 | { 13 | /* TODO */ 14 | } 15 | 16 | void close_mid_454acb(void) 17 | { 18 | if (mid_status[3] != 0) { 19 | mciSendStringA("close mid wait", 0, 0, 0); 20 | } 21 | mid_status[3] = 0; 22 | b_47e772 = 0; 23 | } 24 | 25 | void play_avi(const char *fn, RECT *r, int x) 26 | { 27 | /* TODO */ 28 | } 29 | 30 | char b_46caf8; 31 | char b_46caf9; 32 | char b_46cafa; 33 | char b_46cafb; 34 | char b_46cafc; 35 | char b_46cafd; 36 | 37 | void playmid_454d2c(void) 38 | { 39 | /* TODO */ 40 | } 41 | -------------------------------------------------------------------------------- /csrc/misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | void playmid_4549cf(int x); 7 | void close_mid_454acb(void); 8 | void play_avi(const char *fn, RECT *r, int x); 9 | void playmid_454d2c(void); 10 | -------------------------------------------------------------------------------- /csrc/mkf/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-m32 -g -Wall 2 | MKFOBJ=mkf.o mkf_decompress.o 3 | 4 | libmkf.a: $(MKFOBJ) 5 | ar r libmkf.a $(MKFOBJ) 6 | -------------------------------------------------------------------------------- /csrc/mkf/graph_struct.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include 8 | #include "graph_struct.h" 9 | 10 | struct graph_st * allocate_graph_st(int w, int h, int x, int y) 11 | { 12 | struct graph_st * newst = (struct graph_st *) 13 | malloc(w * h * 2 + sizeof(struct graph_st)); 14 | newst->width = w; 15 | newst->height = h; 16 | newst->x = x; 17 | newst->y = y; 18 | newst->gdata = newst->data; 19 | return newst; 20 | } 21 | 22 | /* crop graph a1 starting at (x, y) as laft-top coordinate, 23 | * and get graph a2 with size w*h. 24 | * 25 | * this function looks buggy and can crash the game */ 26 | 27 | struct graph_st * crop_graph(struct graph_st *a1, struct graph_st *a2, int x, int y, int w, int h) 28 | { 29 | if (a2 == NULL) { 30 | a2 = allocate_graph_st(w, h, 0, 0); 31 | } 32 | 33 | int16_t *src = &a1->gdata[a1->width * y + x]; 34 | int16_t *dst = a2->gdata; 35 | 36 | for (int i = 0; i < h; i++) { 37 | memcpy(dst, src, w * 2); 38 | dst = dst + w; 39 | src = src + a1->width; 40 | } 41 | return a2; 42 | } 43 | -------------------------------------------------------------------------------- /csrc/mkf/graph_struct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #ifndef RICH4_GRAPH_STRUCT_H_YxnQlWsLYw 7 | #define RICH4_GRAPH_STRUCT_H_YxnQlWsLYw 8 | 9 | #include 10 | 11 | struct graph_st 12 | { 13 | int16_t width; 14 | int16_t height; 15 | int16_t x; 16 | int16_t y; 17 | int16_t * gdata; 18 | int16_t data[0]; 19 | }; 20 | 21 | struct graph_st * allocate_graph_st(int w, int h, int x, int y); 22 | struct graph_st * crop_graph(struct graph_st *a1, struct graph_st *a2, int x, int y, int w, int h); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /csrc/mkf/mkf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "mkf.h" 10 | 11 | #define NULL_HND ((FILE*)(-1)) 12 | 13 | void mkf_decompress(void *arg1, void *arg2); 14 | 15 | struct mkf 16 | { 17 | FILE *handle; 18 | void *data; 19 | }; 20 | struct mkf mkf_stdata[16] = { { NULL_HND, NULL } }; // 0x4762f4 21 | 22 | #ifdef MKF_INFO 23 | static int mkfc[16]; 24 | 25 | int mkf_nchunks(int i) 26 | { 27 | return mkfc[i]; 28 | } 29 | #endif 30 | 31 | int load_mkf(const char *fn) 32 | { 33 | int i; 34 | int32_t x; 35 | 36 | if (mkf_stdata[0].handle == NULL_HND) 37 | memset(mkf_stdata, 0, sizeof(mkf_stdata)); 38 | 39 | FILE *fp = fopen(fn, "rb"); 40 | if (fp == NULL) 41 | return -1; 42 | 43 | for (i = 0; mkf_stdata[i].handle != 0; i++) 44 | ; 45 | 46 | mkf_stdata[i].handle = fp; 47 | fread(&x, 4, 1, fp); 48 | fseek(fp, -1, SEEK_END); 49 | long filesz = ftell(fp) + 1; 50 | size_t t = filesz - x; 51 | fseek(fp, x, SEEK_SET); 52 | mkf_stdata[i].data = malloc(t); 53 | fread(mkf_stdata[i].data, 1, t, fp); 54 | #ifdef MKF_INFO 55 | mkfc[i] = t / 4; 56 | #endif 57 | return i; 58 | } 59 | 60 | void unload_mkf(int mkf_idx) 61 | { 62 | struct mkf *m = &mkf_stdata[mkf_idx]; 63 | if (m->handle == NULL) { 64 | return; 65 | } 66 | fclose(m->handle); 67 | free(m->data); 68 | m->handle = NULL; 69 | m->data = NULL; 70 | } 71 | 72 | static void update_spr_smp_ptr(void *s) 73 | { 74 | struct spr_smp *sst = (struct spr_smp*)s; 75 | size_t lastsz; 76 | 77 | if (strcmp(sst->sig, "SPR") == 0) { 78 | lastsz = (size_t)(sst->chunk_tab[0].gdata); 79 | sst->chunk_tab[0].gdata = (int16_t*)(s + sst->start_offset + 0x200); 80 | } else if (strcmp(sst->sig, "SMP") == 0) { 81 | lastsz = (size_t)(sst->chunk_tab[0].gdata); 82 | sst->chunk_tab[0].gdata = (int16_t*)(s + sst->start_offset); 83 | } else { 84 | return; 85 | } 86 | 87 | for (int i = 1; i < sst->nchunk; i++) { 88 | size_t t = (size_t)(sst->chunk_tab[i].gdata); 89 | sst->chunk_tab[i].gdata = (int16_t*)((void*)(sst->chunk_tab[i-1].gdata) + lastsz); 90 | lastsz = t; 91 | } 92 | } 93 | 94 | static void update_pixels(uint16_t *a, int nbytes) 95 | { 96 | int nw = nbytes >> 1; 97 | 98 | switch (pixel_fmt) { 99 | case 1: 100 | for (int i = 0; i < nw; i++) { 101 | uint16_t t = a[i]; 102 | uint16_t t2 = t * 2; 103 | t &= 0x001f; /* t[0:4] */ 104 | t2 &= 0xffc0; /* t2[6:15] = t[5:14] */ 105 | a[i] = t | t2; /* t[0:4],0,t[5:14] */ 106 | } 107 | return; 108 | case 2: 109 | for (int i = 0; i < nw; i++) { 110 | uint16_t t = a[i]; 111 | uint16_t v1 = (t & 0x7c00) >> 10; /* v1[0:4] = t[10:14] */ 112 | uint16_t v2 = (t & 0x03e0) << 1; /* v2[6:10] = t[5:9] */ 113 | uint16_t v3 = (t & 0x001f) << 11; /* v3[11:15] = t[0:4] */ 114 | a[i] = v1 | v2 | v3; /* t[10:14],0,t[5:9],t[0:4] */ 115 | } 116 | return; 117 | case 3: 118 | for (int i = 0; i < nw; i++) { 119 | uint16_t t = a[i]; 120 | uint16_t v1 = (t & 0x7800) >> 3; /* v1[8:11] = t[11:14] */ 121 | uint16_t v2 = (t & 0x03c0) >> 2; /* v2[4:7] = t[6:9] */ 122 | uint16_t v3 = (t & 0x001e) >> 1; /* v3[0:3] = t[1:4] */ 123 | a[i] = v1 | v2 | v3; /* t[1:4],t[6:9],t[11:14] */ 124 | } 125 | return; 126 | default: 127 | return; 128 | } 129 | } 130 | 131 | char * read_mkf(int mkf_idx, int a1, char *buf, int *bufsize) 132 | { 133 | /* 4-dword mkf info: 134 | * [0]: real data size 135 | * [1]: original size in file 136 | * [2]: graphics data offset 137 | * [3]: graphics data size in bytes 138 | */ 139 | uint32_t data[4]; 140 | 141 | FILE * hdl = mkf_stdata[mkf_idx].handle; 142 | if (hdl == 0) 143 | return 0; 144 | 145 | fseek(hdl, ((uint32_t*)(mkf_stdata[mkf_idx].data))[a1], SEEK_SET); 146 | fread(data, 4, 4, hdl); 147 | 148 | if (buf == NULL) { 149 | buf = malloc(data[0]); 150 | } 151 | 152 | int bufsz = data[0]; 153 | if (data[1] == bufsz) { 154 | fread(buf, 1, bufsz, hdl); 155 | } else { 156 | void *tmpbuf = malloc(data[1]); 157 | fread(tmpbuf, 1, data[1], hdl); 158 | mkf_decompress(buf, tmpbuf); 159 | free(tmpbuf); 160 | } 161 | if (data[3] != 0) { 162 | update_pixels((uint16_t*)(buf + data[2]), data[3]); 163 | } 164 | if (bufsize != NULL) { 165 | *bufsize = data[0]; 166 | } 167 | if (strncmp(buf, "SPR", 3) == 0 168 | || strncmp(buf, "SMP", 3) == 0) { 169 | update_spr_smp_ptr(buf); 170 | } 171 | return buf; 172 | } 173 | -------------------------------------------------------------------------------- /csrc/mkf/mkf.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "graph_struct.h" 3 | 4 | int load_mkf(const char *fn); 5 | void unload_mkf(int mkf_idx); 6 | char * read_mkf(int mkf_idx, int a1, char *buf, int *bufsize); 7 | 8 | extern int pixel_fmt; 9 | 10 | struct spr_smp 11 | { 12 | char sig[4]; /* "SPR" or "SMP" */ 13 | int32_t nchunk; 14 | int32_t start_offset; 15 | struct graph_st chunk_tab[0]; 16 | }; 17 | -------------------------------------------------------------------------------- /csrc/mkf/test/Data.mkf.sha1: -------------------------------------------------------------------------------- 1 | 639dab8f896ea1d18bfda5309a4c7e0d7a990254 Data.mkf 2 | -------------------------------------------------------------------------------- /csrc/mkf/test/data1.sha1: -------------------------------------------------------------------------------- 1 | d0c4b59b19e1f36f164a0a0a97ccae102ee5efe9 data1.00.data 2 | eb232db5bb98434f7a6c5ae3740082df66292913 data1.01.data 3 | 019731df3bf221e0287bf0675ed1ef87ccc072d1 data1.02.data 4 | bb6d61a6665e98060bf2923366448229ed049c9f data1.03.data 5 | 0a9700f7565a8b57c500cdfb427217b1ccfe598c data1.04.data 6 | c1e4f9931ddd0d287a7357b5dd35c0818f55a2c3 data1.05.data 7 | 2279f987fcb0b8156a0c1f7e09b89506df4b2f7c data1.06.data 8 | 4662b97408d03553e99ad43c1897a99d8ef33d94 data1.07.data 9 | 456eb7147784ddf3e2c9afdb9ff9ea36a18b70d7 data1.08.data 10 | 3a96b833397ebfaf30444953a074626c7e39aedc data1.09.data 11 | c6912ae65d6c299b3bb765ef33baf1f5576573ff data1.10.data 12 | -------------------------------------------------------------------------------- /csrc/mkf/test/data1_graph_info.txt: -------------------------------------------------------------------------------- 1 | width = 640, height = 480, x = 0, y = 0 2 | width = 108, height = 105, x = 55, y = 53 3 | width = 116, height = 113, x = 59, y = 57 4 | width = 107, height = 92, x = 51, y = 51 5 | width = 114, height = 99, x = 55, y = 54 6 | width = 98, height = 90, x = 51, y = 42 7 | width = 103, height = 98, x = 53, y = 46 8 | width = 53, height = 18, x = 27, y = 9 9 | width = 58, height = 19, x = 29, y = 10 10 | width = 76, height = 91, x = 37, y = 45 11 | width = 90, height = 107, x = 45, y = 52 12 | -------------------------------------------------------------------------------- /csrc/mkf/test/dump1.c: -------------------------------------------------------------------------------- 1 | /* gcc -m32 -I.. dump1.c ../mkf.c ../mkf_decompress.c -o dump1 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "mkf.h" 7 | 8 | int pixel_fmt = 1; 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | int mkf = load_mkf("Data.mkf"); 13 | struct spr_smp *data1 = (struct spr_smp*)read_mkf(mkf, 1, NULL, NULL); 14 | 15 | for (int i = 0; i < data1->nchunk; i++) { 16 | struct graph_st *gi = &data1->chunk_tab[i]; 17 | printf("width = %hd, height = %hd, x = %hd, y = %hd\n", 18 | gi->width, gi->height, gi->x, gi->y); 19 | 20 | char fn[16]; 21 | sprintf(fn, "data1.%02d.data", i); 22 | FILE *fp = fopen(fn, "wb"); 23 | fwrite(gi->gdata, 1, gi->width * gi->height * 2, fp); 24 | fclose(fp); 25 | } 26 | free(data1); 27 | unload_mkf(mkf); 28 | } 29 | -------------------------------------------------------------------------------- /csrc/mkf/test/dump_data.c: -------------------------------------------------------------------------------- 1 | /* gcc -m32 -DMKF_INFO=1 -I.. dump_data.c ../mkf.c ../mkf_decompress.c -o dump_data */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "mkf.h" 7 | 8 | struct mkf 9 | { 10 | FILE *handle; 11 | void *data; 12 | }; 13 | int pixel_fmt = 1; 14 | extern struct mkf mkf_stdata[]; 15 | int mkf_nchunks(int idx); 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | int mkf = load_mkf("Data.mkf"); 20 | FILE *fp = mkf_stdata[mkf].handle; 21 | int nchunks = mkf_nchunks(mkf); 22 | int dump_smp = 1; 23 | if (argc >= 2 && strcmp(argv[1], "--no-smp-spr") == 0) 24 | dump_smp = 0; 25 | 26 | for (int i = 0; i < nchunks; i++) { 27 | int sz; 28 | char *data = read_mkf(mkf, i, NULL, &sz); 29 | if ((strcmp(data, "SMP") == 0 || strcmp(data, "SPR") == 0) 30 | && !dump_smp) { 31 | free(data); 32 | continue; 33 | } 34 | char fn[16]; 35 | sprintf(fn, "%03d.data", i); 36 | FILE *fp = fopen(fn, "wb"); 37 | fwrite(data, 1, sz, fp); 38 | fclose(fp); 39 | free(data); 40 | } 41 | unload_mkf(mkf); 42 | } 43 | -------------------------------------------------------------------------------- /csrc/mkf/test/mkfdata.sha1: -------------------------------------------------------------------------------- 1 | c35c61899a891853ebb6c0b4879b129fff61655b 004.data 2 | 25dd6d1b0ec6d83a20ea5115ddeca4842e0ee608 005.data 3 | 267642401fc295a91f292d46608815fc857f1133 006.data 4 | 4a7cbfd681dbb43c10f33c36d594b171113f2f0d 007.data 5 | 36cc033d8c04bb896c0818adb51dee568929f2d1 008.data 6 | ccc85ccbd3ed03421de6f9b648026ada4573e7d2 009.data 7 | 69429c6bd3806a1197540a2250ccb430e3ad53ab 010.data 8 | 76f81f7c64d0ec1fd09af279a9edb0a3d388c2b9 011.data 9 | 6fccc68ff6e520c303515364c120d5cc83a91512 012.data 10 | e61cc655dbfbb5afb2fa4c4e6c61dd1ac94b2612 013.data 11 | 4857dd7256a843ed7a1cb750de9f0ea2e15a6656 014.data 12 | fdecf73c040b54c6cd56dbd23ad1843cac39108a 015.data 13 | 5770d5c1a14276dca544a9cabbf5e852545c7fac 016.data 14 | 847e8a250e317658093bb546eaa4c97478e64c93 017.data 15 | eb0c03f7cde4c94669e2a49e105d2ea558f434f4 018.data 16 | 493b57f1c1e9b0ab4787bb7c770c6a13ff73628e 019.data 17 | 6a6ffc48a344fb7cd36f6d8dcd4b8198d60c5764 020.data 18 | 8345c9830063c146914223f923a13c1d35e9ba14 021.data 19 | 8627e02a0149d3898164d6de9a712f8963bcd545 022.data 20 | ffbc613bfdcc4a6ea41c730518a5d533bc8acbb4 023.data 21 | 19c1adaf4bd4e1db7f551d6e068b88fe1a051112 024.data 22 | 0f97034f7d9912f31d113094e9fed3cbc0268061 025.data 23 | fcd8d7e1467015a948ac80c29837e822efb1d406 026.data 24 | b2dd2fdb70298b0ee27d44563b61f538be32b931 027.data 25 | c35c61899a891853ebb6c0b4879b129fff61655b 028.data 26 | 25dd6d1b0ec6d83a20ea5115ddeca4842e0ee608 029.data 27 | 8edc0589ba4b022375cfc1582bfae4f29f73d23b 030.data 28 | ccc85ccbd3ed03421de6f9b648026ada4573e7d2 031.data 29 | 267642401fc295a91f292d46608815fc857f1133 032.data 30 | c3af10f84e140b43eead49d1a7303f66caf2bb5a 033.data 31 | ac631919fa7764df01b104a2ab9a37456e1f1a00 034.data 32 | 3851990d49268b03c4145511c68638d3093f6440 035.data 33 | d5ee0d7dd7c76b0a1f84160a39cb59b0b71f89ab 036.data 34 | 2349b217088db8adeeae9f793226ecd355948034 037.data 35 | 493b57f1c1e9b0ab4787bb7c770c6a13ff73628e 038.data 36 | 6a6ffc48a344fb7cd36f6d8dcd4b8198d60c5764 039.data 37 | 8345c9830063c146914223f923a13c1d35e9ba14 040.data 38 | 8627e02a0149d3898164d6de9a712f8963bcd545 041.data 39 | ffbc613bfdcc4a6ea41c730518a5d533bc8acbb4 042.data 40 | 19c1adaf4bd4e1db7f551d6e068b88fe1a051112 043.data 41 | df466aa5632639f5a37fe2b329acdb5022703788 044.data 42 | fcd8d7e1467015a948ac80c29837e822efb1d406 045.data 43 | 2422ff83f5441298f0acfaa407ae35d058569592 046.data 44 | 4b4ad990bad016d65a4a54dfb5ffbff69214fc72 047.data 45 | 8d46388faa1881eab52e97f80f722408a9b6af0a 048.data 46 | 6377fea28c27dbbc7b4f7ca321dcfbb0e610f0a0 049.data 47 | 0b2771b946e575d5647909e498b689f863ddcd85 050.data 48 | 1f318f27eeb843455a4816f5e1d1b966d29692ca 051.data 49 | 25dd6d1b0ec6d83a20ea5115ddeca4842e0ee608 052.data 50 | 3930b9d692a8ab0f149f734ebcb71509e615b76d 053.data 51 | 344636df9c5de093258d68866206c8b9edcb92eb 054.data 52 | cba0f73cb516e900da7518f19547b161bcecb04f 055.data 53 | 80149619bdec4dcab4b8385e3743a02c268a08cd 056.data 54 | 3d6de0e4955d91cd76cb513ef44aa7cd6f94e4eb 057.data 55 | 8582d03787649e65aecc815921db8162d4a6e2e2 058.data 56 | feaa0cfde2060d6ed65aae77b81531b36b61d7b6 059.data 57 | cc8a8650da63eeab15bb45374aacba44d7cfd0e7 060.data 58 | 84e4b45ae15c08807331f6f388e55e4588626b66 061.data 59 | 9ab5dfd87bf133f1bb66fb2db66da7c3acaab6c0 062.data 60 | 2cb7c98757df01d8c28859c5a8694f204b9106b3 063.data 61 | 0d116c379820b4ccf5805af69a938c810effba98 064.data 62 | cb81a695e8d59217227b0079bd9062bbc3f37828 065.data 63 | a19a943ea75926cf316853f7321baa2def056633 066.data 64 | 0795e54fa61ecedf04db42cd3a401bf3f3e39c2d 067.data 65 | 869eb60fa0ec7d4c1b419b6b218a2be93adfe751 068.data 66 | fe575e06b11406245c97ea3ac41283888450cf96 069.data 67 | 5d51c238554f7e97b03645218e7d42c4d0f12beb 070.data 68 | dd2a249d92edfdf4d87f5bef2512a86479e9ec68 071.data 69 | 20c3f8eb002923995e084299ca434d59a9e1564a 072.data 70 | 1b6c5fc41c873a841b209c6072d8bcd09071347d 073.data 71 | aae08f938e4b8325261fd6cf236d28321408424c 074.data 72 | 966cdced2039b7933095833282718f73ae256309 075.data 73 | 1daa8f3f2e69cbef090022849016106c2f4fabe5 076.data 74 | 8aac705fa6a30fc83536387d992e8874c8c7d811 077.data 75 | ab5e3b68ac761cae784dab64a134fb430847be5a 078.data 76 | e5a4fbf12a9bce7e91b8fcbc2e3d0d60d9d7de9a 079.data 77 | 5f69a608efbfcd95d7046f2fa3c5b3c93917c90e 080.data 78 | 1a6bb0ee2475cdc49f29fbb12673d8d5dc9c3e0b 081.data 79 | 9ab6b3c52bb2af37c594ae9e9d6207e520119d4c 082.data 80 | a3bdbc0e9f462685461918e320a6ae5587f2e0eb 083.data 81 | 33ca51ead6cba7eebabde103cc30ead6b5cf6be5 084.data 82 | 258bb12b5cd12e51ec8de61d9730391024c80553 085.data 83 | 67bb53190a0b798e23ad0a8739cf0d675b84109e 086.data 84 | 539f170703e0691af77520db5675362a1d18e06c 087.data 85 | d5950791b3b1c86afd57868142a15a7ab3da299c 088.data 86 | 16cc09e3510d1acb822d36c471032e392fd18756 089.data 87 | 386bd7364f8b7534af4c7ea8ebe6c6db091361a3 090.data 88 | cb95226bd4d4892289f86fcdca9d075726ae87cc 091.data 89 | 04ea899855fa223721d9a0bc142339b5db64f267 092.data 90 | b4dbff100f6948a87889a7642c29825c437bf7a4 093.data 91 | 8aa050c5ffc699bd164602ffb80b57e4426ce967 094.data 92 | 0a505e7e34293e0027a7360dff1ba53899153b1c 095.data 93 | a990622958441649e021c87be2cfc9ef993a64a0 096.data 94 | 2f18e8b2455fbfbb2b9979ae5e1924389fe271a5 097.data 95 | 8d642c413db004a8aa4551f28e8db4c3aaaafaa3 098.data 96 | 8d642c413db004a8aa4551f28e8db4c3aaaafaa3 099.data 97 | 8d642c413db004a8aa4551f28e8db4c3aaaafaa3 100.data 98 | 8d642c413db004a8aa4551f28e8db4c3aaaafaa3 101.data 99 | 8d642c413db004a8aa4551f28e8db4c3aaaafaa3 102.data 100 | 8d642c413db004a8aa4551f28e8db4c3aaaafaa3 103.data 101 | 8d642c413db004a8aa4551f28e8db4c3aaaafaa3 104.data 102 | 9f868b92077ba48899d7407232c5495b0abeb492 105.data 103 | b04dabef93698befaff753ec13ae943f78223c84 106.data 104 | eb7e85ad62fc6210d9db56d72277a62e0281c330 107.data 105 | 8e063764b5205c8cbeb01d2bc528625180e66b02 108.data 106 | 734cf802bb212946b4243db6c32d1a7d1768c1c5 109.data 107 | ea93de577476188d533058223eb652caedd2814d 110.data 108 | 78016f24ac59374e0544feaef65d209bef7c3501 111.data 109 | fb6e5a4f42cea6fc6561516dfc0f85c011f83783 112.data 110 | 63da7d7f98af5f895493780077862f5fd4fa19fe 113.data 111 | 0821cfd004b955f14f1bb649dc69abb275df2174 114.data 112 | 6f176b82bfdc8818d91d7006c765e39c5ff1a051 115.data 113 | cc13ab589a081b92674e1fdcb65230054c45ae25 116.data 114 | 0396b341e60ccb6b37a0808813eeec1354459aa6 117.data 115 | 0795e54fa61ecedf04db42cd3a401bf3f3e39c2d 118.data 116 | a047ad4e167808fc22978b798d3f4bdf3536b50e 119.data 117 | b4442ba7619a79161df2a71b93d81de4b0b79076 120.data 118 | aae08f938e4b8325261fd6cf236d28321408424c 121.data 119 | 69b00983eec76cc9c52ffdf16ae55a9c868cfae9 122.data 120 | f3a90a6f95aa231145d16e75747b94af334f335a 123.data 121 | d5d801531d52017040b29dc49d1a10569703d04a 124.data 122 | b7bd6eb6a7090eb19a79eef2f8f47ff27c7a16af 125.data 123 | ed3f5c32c56209387c1dc2daf515b344eeb2e1ec 126.data 124 | 5d6fd09e4e83846c2ef0401e6dd66de08decf59e 127.data 125 | 8e96755fe06898b8006e32828590d1c85c3bfbb5 416.data 126 | 9458ba3184dc433d35b332a66a1b9fede8aad8ee 417.data 127 | cd051cc112da67886e0a57a0c4bed6ab4c68b9ac 418.data 128 | cb0d9691c888a718b2717142952fb5be6f1c031d 419.data 129 | d0b13c5e92dabb9728a09788d50c596a684decb4 420.data 130 | 44048a1857328aa0e49a6a5ec3014ff21adda307 421.data 131 | afb67823fb8b53c032f3baa5e50d66ea5e3c93e1 422.data 132 | 9efc2dfb3a8ba5d8c442906dc163daad903ed64c 423.data 133 | 12a95e23383fc765d3964d300dff497a4f760bdb 424.data 134 | def85b3231e3cf6da8bace2c119b13e16a813f44 425.data 135 | 1ae30dbf751349800567a8d3abd41a9009a13cd5 426.data 136 | 0a0c9b863272551ddee0dd97350c79fe46e34401 427.data 137 | 94c349c8a2a4c9ffe8a13cf2b26088264b8a15bd 428.data 138 | c37d96cc91120ff50540d5161b39ae718e975970 429.data 139 | ad61109819a7017a4710a7478f4a013f8196202c 430.data 140 | 535045739a10a63385b390a4f381be76f85194ab 431.data 141 | 67fb15d37a011db6ba980dab69f84194b0c4564c 432.data 142 | 51ad07b31da132d512327789fb79121f1c0b6190 433.data 143 | e579b04a1e223ab6bc9f64ab05e365935c3caf2c 434.data 144 | f639428846d0434fe25ca310166f69a405f0d605 435.data 145 | 5ca244058f6fed742e595fbf5aa5108527b187f6 436.data 146 | 3245daba4c0bcdfd0c75ab4b33a26ffb04200e2a 437.data 147 | d1fa044e9910efa3797145e6d54ebc9a6c2e777b 438.data 148 | c191f4851cdc6ebef48daf5dc7f02a90d133efb8 439.data 149 | 15073cccea27e27baf1787f45fb9d75753e218de 441.data 150 | ed2814aeb35dd39538dee546c0aba81a1eebfbfc 442.data 151 | 7dbedfc9fb950a37a471d28673edc71f36edf6c7 443.data 152 | 026defb436396a7b094f88af20b293bbbbd87165 444.data 153 | bfe8f8973ca17485e6c7bb7d6f75c6766e7c445b 445.data 154 | 2e913f2894ff712c2573432538d3aa2284e4a6d0 446.data 155 | 69e62129540c6fb8953fa2514d6e86219905cc8a 447.data 156 | 52f5476a577807a82e9d821466ca37b34565ba5e 448.data 157 | 8aaadd084c787310898cafa9de99f68830dfd94d 449.data 158 | 46f2172753416b142dff1b6e021e58ea664e18e8 450.data 159 | e94fb8e2b2ced2b3e49dfe775d3460f08c56ed1d 451.data 160 | 662ba7c3cef541f80a8be1702a1bc138e2d7ca4f 452.data 161 | 13d0c437e937340c3d8166faaace02c90b991348 453.data 162 | d59293f36b19432e12e6127f84300e85efb288ae 454.data 163 | e9bf2616597f77d291c42ee62451212531b6ad14 455.data 164 | 918ec7a78492060cc87c2bd748ccae301303f64a 456.data 165 | 3100d2093e2f58d271c3edb6128825595768191a 457.data 166 | 59e7edae0e0f4ba46c5bf1b0589eddc670892193 458.data 167 | f8839fc7062c4ee0f2ec81012c7df901119d020a 459.data 168 | 4378f633244a149c985c9404ed289dd5de3e48af 460.data 169 | d63b6f813c8517066e4ad6c44bf2ec661264b861 461.data 170 | b712a3be6c01a3e761013ded365bcefa213fac54 462.data 171 | 8d959cbc5c469e22daa21ef362ea8cd23671a405 463.data 172 | 18534405062b25ccc5d407b954ce5e68e8305b92 464.data 173 | 55cebf6aa06b56c0ed3490d62a84f287bf45d9ba 465.data 174 | 86d1a65a1049271e75bc6dd1ef94afc30140b173 466.data 175 | f51d7b53601e7b3b7c6caa1f556c96a8052da98d 467.data 176 | f51d7b53601e7b3b7c6caa1f556c96a8052da98d 468.data 177 | 38cf0bda7c29a199e9fcbd4c8dcd72d06696bcec 469.data 178 | eb87a7149a0a1fe4c20519b2ddc42ddb20e93226 470.data 179 | cd8dc28dc275ac771a32f044ad8665200fe1b669 471.data 180 | c63c6f76c1502fbc9c5f773b422b6c772a33e491 472.data 181 | 28a0d658a2094ee8d2c9d6208e85a7a7a00d870f 473.data 182 | e0bd42c36f23d98c5d62e04b6cb94c3955dbf623 474.data 183 | 5b65bdc19c2b20803aedb7b81319d92689cc5fae 475.data 184 | a59fb35797052405b2f12a41d8389a52f60c74f3 476.data 185 | 683464fd60913153b2cc1755ab772ad8245dbeff 477.data 186 | 2de33350155277a28041452ba681665d1fd9328f 478.data 187 | d16d77f1d388052a98a1f32fbf602571e2ae56fe 479.data 188 | 265ba5a158e95b6a1ef11f5cc08e2bb450fa7b10 480.data 189 | 0de35c3658357a871e0afc81012206a3a4da2bba 481.data 190 | e7b4236bfa1669c87687810708db7bfe8184dd75 482.data 191 | 3c81e3d6a5cfea35ebc36e39d6398daf835d5f5a 483.data 192 | 965140a23a0d8920e2283a4f08650702af267969 484.data 193 | 6aa0f197716319dd1da981884bf4392c5840d43b 485.data 194 | db29a06e69459ffb0dcb118a93c4763de292ef19 486.data 195 | 2b5cacac56baaa597f397b82be972b1ca10d400e 487.data 196 | 68a3e49db47842ee0b383951c48ce667e570507b 488.data 197 | 58a3dd47af4e13ec3377f5adc4b7e82b195b9778 489.data 198 | 72c8e746b61a35aa3764172ba731c1871ff91055 490.data 199 | 4657165cc3cc10849e48b8a0a926a8049fbc8311 491.data 200 | b149b9cd2dde7d4a4301fb1e47ad23ca3167aaa7 492.data 201 | b64372bdbef14568e4dc80dd306c4038444fe811 493.data 202 | 2a46d6fa3c8a358c82a5b4413280bcf5c5ae61aa 494.data 203 | c7a87c1b3f67153db26d2a35e0d07fb965d1cee4 495.data 204 | 4f49992f5c893bd596dd8ecab6625a5c416b1f7c 496.data 205 | 1e4b027c9488754f71ee2154b6be6f7c552200f7 497.data 206 | 5009931d736d29e45f9bd0dcdd098fd31c29f31b 498.data 207 | 6d16fd9a8305db5e2ace7088a79e0b18e7829345 499.data 208 | 6c18ddecd99f53577fa55f46d6b4617b863667fa 500.data 209 | 29ff3cd3b02b724c792c9cfbd898c1c43e4c9ee2 501.data 210 | e141923a31e7a7aa513d1c201330002362721e30 502.data 211 | c95678b548356ff15abe76189bc48850737ce1f2 503.data 212 | 7818a94716c82914965f192ab26b4faff4853687 504.data 213 | ee3f623338f0402fb9468ecf78b4f5d4380cf1be 505.data 214 | 8cc7a03e59018013b618005f98a92bd153cc2299 506.data 215 | bdabce9b1096016e67a956b4e3d0468ea92ab58d 507.data 216 | a1d5f17de7d18cfb5192c7c71d3b58e386971fcf 508.data 217 | 2c3db8b1c27e06300cc7c76caf9638195adb996d 509.data 218 | 836c11ebc296de65eee4381e72c9b24c4d0d8a6d 510.data 219 | 20cb6d5c0224de7ebe4d8ed4387a0462e717a02d 511.data 220 | 7e214a1f197695827f2023a8448bb659c662c978 512.data 221 | a1351ad8ba6d3e27e4b0bcbf3d65d77ec19587da 513.data 222 | 97ddc183c7c898f9ea547c3b39016921ca4c4093 514.data 223 | 04c51de123522f307abb9b21e9fc7c765386b924 515.data 224 | 8ece5a0601a97dc44bdc899ab1fa9357c0d3f52b 516.data 225 | a656d23722af37b3f23770c8217939d1d7280e74 523.data 226 | 5eace6573d947d05bec3259a273b21974d0bead3 524.data 227 | 274f4450bd27f0bc69d8509c202d31463f253e7f 525.data 228 | f4bf86489d531345ffc41d94592f507817bbe999 526.data 229 | e15b687f252d0664220be773cb8767315849c21f 527.data 230 | 314f0c095d12759649c702d8142c7c77dd391445 528.data 231 | 4ed1ee8500b0681d392e76e6ca1f929d927385cc 529.data 232 | 7a7ebe70e5e96e04271db753b1723110c0860c99 530.data 233 | ffb17ffa026dfc0778e933700e5c8ecdcf7c8815 531.data 234 | d2444f59f38658630d851c4029fab189f7ae5a9a 532.data 235 | 8b5797d11d6b0f7d6f80cac859243d90f657e351 533.data 236 | 5c8b2b29ef020e188bed632d91b66f9566a26c6b 534.data 237 | 8ed4f99d49edaa5adc2419c6c62b430004cb5409 535.data 238 | d3a11a43fe8fe299fd9148b8c3947e63c7641778 536.data 239 | 87433826647283eacf209170fae61edc46dc520b 537.data 240 | 7b4ebc63b201b37714ea9a203d2fce362cb08f20 538.data 241 | bb017738fe0bec6039e9eae563e441da00013cd9 539.data 242 | 5f47e30d36c300f4c8d9e579dda7c620b2c58782 540.data 243 | 53f6da1309aa500496e21cbbfb845ed40121ee39 541.data 244 | b15eb0142565e6fa224fbc9d1b832d5ff48b6a6c 542.data 245 | 2f098024fe3ef68e259e094c76272ac16040db3b 543.data 246 | 3e2a313f4a056249f5ec05e5f28374eb568327b4 544.data 247 | c5d6d3f773e77ef9d5f9247694cc60e758618431 545.data 248 | 5dfc09ef2be4764f4e66d57f26a38293c851202d 546.data 249 | dccfb1b053a1181940f2f91e30ad7f9e53fed5a2 547.data 250 | 8f2466b3f16816a4849ab30a2829c487da358755 548.data 251 | db6fae4677a93f05583acfdef99ee62905712a76 549.data 252 | ce47134a1d9fe42a7ab6d92c04f2284b6f191177 550.data 253 | 58b3661a88424496463d1fcaf71b796d3e47fe87 551.data 254 | 9eb2a9f3afecc891b3faacf68e0cde3420b61013 552.data 255 | ed35c2de37af93462111d9b1ec75ca255436e0a5 553.data 256 | 6a80d7b5c6b87b43b5ccffdcf81841440c34e3e6 554.data 257 | 938237c8f1b7f0efa7b88bb02c40e67ac85c6fb8 555.data 258 | 30a515a913e499abdf3f1de6898298f44748bb30 556.data 259 | a4495270591aeaaa509c9ab24f556be2b64e2662 557.data 260 | bd80597a7be6cd33ab04c25fffcd200b4e2bf135 558.data 261 | 230a87d54cd16d0f7fbc08aceb15742b4aa50f5c 559.data 262 | 6d57460206ecc859bedb5538aeb0471116946692 560.data 263 | 6afcbcc696216829786e4cf84ca3e07216d1e717 561.data 264 | 0e84132f11a9d496591639e75c9da769702d2f3e 562.data 265 | e09d0eae94ddc4e479cb3eddf4149c5e8783c4b3 563.data 266 | 14250afb90b6d182a048793524766e14c9c53662 564.data 267 | 17b0eb5386ee7c6b29e54e740204c182ca394394 565.data 268 | 3adfcadef8471c28ddaa67303aa05f90a0d299ce 566.data 269 | 231f108d5e0961d9a9efdf370a3795bcb16d9e50 567.data 270 | 40b1d9f5c267923b3a1abeea98f9bd95eb35befe 568.data 271 | a3c784610d43e24b9f282ad11846a718cbe83a1f 569.data 272 | e6d951406323f5d62c27b08b91ddaef7eb11e52e 570.data 273 | b4a2b2d3220ce627b856d950d108ea746395dabc 571.data 274 | d575946de6105fecc8f654766fb87269e38241e1 572.data 275 | 29c41531af52ed44e7d146276f485848949326c3 573.data 276 | 45d1815bd0814735e5af0b7acea5be1d2dedfa17 574.data 277 | 04d2d96c0bcf22a6711a9d3ff5bb3ad516abaaeb 575.data 278 | 5e58fa6523195fb11cd115950a2f39573d61933c 576.data 279 | f275b98d35a81b11e7af9575036b1ddf437954be 577.data 280 | dc4ade073439b02eb1e84ca15a212f6415031d15 578.data 281 | f58258ac7aee50feda17d3c6e91103b8da7ab3d0 579.data 282 | 3c167f302b14e2600ed2b10bf1c315bd6b378400 580.data 283 | 6b004a88d07953599b83a656b1ea4dc6138de0b0 581.data 284 | cd8446c07369371c0f48493b2ed2f8980f7f127b 582.data 285 | 29f5952f39098148e6fd867d5ba544615579b6f7 583.data 286 | 9305f38f8797c30d143dd0dc2037a8449b9f588c 584.data 287 | 348bad2c5aa072a3b20f4ff6d8f22bad10befdb0 585.data 288 | 1af88c57724a21481150fbfb2651b45c6497ab14 586.data 289 | 15a9e87f279aeac0aa5d504dcee8300e3629550b 587.data 290 | cc866bc6a841dcbc9e21b612b7dfb2f474863945 588.data 291 | 1e470ab63c3c849f4474ea0c1606805be64fd67e 589.data 292 | 208bfe50ab4aa40bed335d0096efc228ec7ed561 590.data 293 | 27d0d7388d1c99b4222d940f3efc87bed2d5bdc9 591.data 294 | 6739eba9a0fa91f23cb89dd7eea13f8bcb0021fb 592.data 295 | 9c488b0654ab1db294c3546320d4d43a0f0f3ef0 593.data 296 | c9088652f20fd495b47b2abe07578b36dcd501d1 594.data 297 | 92ecac7a79ef2cf22b393f23bfc35ef8c82af990 595.data 298 | f1c78e211d540da12dffe281f9a0980d6c4bf1b4 596.data 299 | 1ec1d23e01150f52c4ef06ae2bd1dfdc1cca66e3 597.data 300 | 187f7ee1a3418282f7670cef0b510da4fdf33cdd 598.data 301 | 175bd011f9d18a30c7b270f75a75861c8ca66865 599.data 302 | 5f817c2d273b4f8ac1ea017515e70ef2f6abc7bb 600.data 303 | c6d07561ef3975832c527183adf63cc829bbadc7 601.data 304 | -------------------------------------------------------------------------------- /csrc/mkf/test/parse_mkf.c: -------------------------------------------------------------------------------- 1 | /* gcc -m32 -I.. -DMKF_INFO=1 parse_mkf.c ../mkf.c ../mkf_00455040.c -o parse_mkf */ 2 | 3 | #include 4 | #include 5 | #include "mkf.h" 6 | 7 | struct mkf 8 | { 9 | FILE *handle; 10 | void *data; 11 | }; 12 | int pixel_fmt = 1; 13 | extern struct mkf mkf_stdata[]; 14 | int mkf_nchunks(int idx); 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | if (argc < 2) 19 | return 1; 20 | 21 | int mkf = load_mkf(argv[1]); 22 | FILE *fp = mkf_stdata[mkf].handle; 23 | int nchunks = mkf_nchunks(mkf); 24 | uint32_t *data = mkf_stdata[mkf].data; 25 | 26 | for (int i = 0; i < nchunks; i++) { 27 | printf("chunk %d: offset = 0x%08x\n", i, data[i]); 28 | fseek(fp, data[i], SEEK_SET); 29 | uint32_t meta[4]; 30 | fread(meta, 4, 4, fp); 31 | printf("real size = %d, original size = %d, gdata offset = 0x%08x, gsize = %d\n", 32 | meta[0], meta[1], meta[2], meta[3]); 33 | } 34 | 35 | unload_mkf(mkf); 36 | } 37 | -------------------------------------------------------------------------------- /csrc/mkf/test/runtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | TESTDIR=/tmp/rich4.test 5 | mkdir -p ${TESTDIR} 6 | 7 | gcc -m32 -DMKF_INFO=1 -I.. dump_data.c ../mkf.c ../mkf_decompress.c -o "${TESTDIR}/dump_data" 8 | gcc -m32 -I.. dump1.c ../mkf.c ../mkf_decompress.c -o "${TESTDIR}/dump1" 9 | 10 | if sha1sum -c Data.mkf.sha1 11 | then 12 | cp Data.mkf mkfdata.sha1 data1.sha1 data1_graph_info.txt ${TESTDIR} 13 | cd ${TESTDIR} 14 | ./dump_data --no-smp-spr 15 | sha1sum -c mkfdata.sha1 16 | echo "Data.mkf dumping tested." 17 | ./dump1 > info.txt 18 | sha1sum -c data1.sha1 19 | diff info.txt data1_graph_info.txt 20 | echo "First mkf datum of Data.mkf dumping tested." 21 | fi 22 | -------------------------------------------------------------------------------- /csrc/news.c: -------------------------------------------------------------------------------- 1 | #include "mkf/mkf.h" 2 | #include "land.h" 3 | 4 | int check_news(int v) 5 | { 6 | edi = 1; 7 | esi = 0; 8 | 9 | switch (v) { 10 | case 0: 11 | case 1: 12 | if (dw_496b30 == 0) 13 | return 0; 14 | else 15 | return 1; 16 | case 2: 17 | case 3: 18 | if (dw_496b60 == 0) 19 | return 0; 20 | else 21 | return 1; 22 | case 4: 23 | case 5: 24 | case 15: 25 | for (int i = 1; i <= dw_498e98; i++) { 26 | if (hlands[i].level != 0) 27 | return 1; 28 | } 29 | for (int i = 1; i <= dw_498e8c; i++) { 30 | if (blands[i].level != 0) 31 | return 1; 32 | } 33 | return 0; 34 | case 7: 35 | for (int i = 1; i <= dw_498e98; i++) { 36 | if (hlands[i].owner == 0) 37 | return 1; 38 | } 39 | for (int i = 1; i <= dw_498e8c; i++) { 40 | if (blands[i].owner == 0) 41 | return 1; 42 | } 43 | return 0; 44 | case 8: 45 | case 9: 46 | case 12: 47 | for (int i = 1; i <= dw_498e98; i++) { 48 | if (hlands[i].owner != 0) 49 | return 1; 50 | } 51 | for (int i = 1; i <= dw_498e8c; i++) { 52 | if (blands[i].owner != 0) 53 | return 1; 54 | } 55 | return 0; 56 | case 10: 57 | case 13: 58 | for (int i = 0; i < nplayers; i++) { 59 | for (int j = 0; j < 12; j++) { 60 | if (players[i].who_plays == 0) 61 | continue; 62 | if (player_stocks[i * 12 + j].amount != 0) 63 | return 1; 64 | } 65 | } 66 | return 0; 67 | case 16: 68 | for (int i = 0; i < nplayers; i++) { 69 | if (players[i].who_plays == 0) 70 | continue; 71 | if (players[i].traffic_method == 0) 72 | return 1; 73 | } 74 | return 0; 75 | case 17: 76 | for (int i = 0; i < nplayers; i++) { 77 | if (players[i].who_plays == 0) 78 | continue; 79 | if (players[i].traffic_method != 0) 80 | return 1; 81 | } 82 | return 0; 83 | case 28: 84 | for (int i = 0; i < 12; i++) { 85 | if (byte [i * 36 + 0x496986]) != 0 86 | return 1; 87 | } 88 | return 0; 89 | case 29: 90 | for (int i = 1; i <= dw_498e90; i++) { 91 | eax = dw_498e7c + i * 0x34; 92 | dl = byte [eax + 0x18]; 93 | if (dl != 0) { 94 | eax = dl - 1; 95 | if (fcn.0040d73f(eax) == 1) 96 | return 1; 97 | } 98 | } 99 | return 0; 100 | case 35: 101 | for (int i = 1; i <= dw_498e90; i++) { 102 | if (dword [dw_498e7c + i * 0x34 + 0x28] > 10000) 103 | return 1; 104 | } 105 | return 0; 106 | default: 107 | return 1; 108 | } 109 | } 110 | 111 | void news_events(void) 112 | { 113 | RECT r0; 114 | int t; 115 | 116 | dw_48c5ac = read_mkf(mkf_panel, 66, NULL, NULL); 117 | struct graph_st *gn = allocate_graph_st(388, 251, 0, 0); // esi 118 | 119 | do { 120 | ebx = byte [dw_4990e0 + 0x499090]; 121 | edi = ebp = fcn.00448be2(ebx); 122 | create_some_font(28, 0xf0f0f0, 0x101010, 3, 0); 123 | if (edi == 1) { 124 | read_mkf(mkf_data, ebx + 441, gn->gdata, NULL); 125 | fcn_00456280(dw_48c5ac + 12, gn, 25, 44); 126 | free(gn); 127 | draw_some_text(dw_48c5ac + 12, ((int*)0x475ed8)[byte [ebx + 0x475eb4]], 24, 8, 0); 128 | t = ebx; 129 | event_calls_table[ebx](0); 130 | } 131 | // 0x44b7c7 132 | edx = dw_4990e0 + 1; 133 | dw_4990e0 = edx; 134 | if (edx == 36) 135 | dw_4990e0 = 0; 136 | } while (ebp == 0); 137 | 138 | IDirectDrawSurface_Lock(pddrawsf2, NULL, &sfdesc1, 1, 0); 139 | overlay_fullscreen(sfdesc1.lpSurface, dw_48c5ac + 12, 0, 0); 140 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 141 | 142 | r0.left = 0; 143 | r0.top = 0; 144 | r0.right = 440; 145 | r0.bottom = 480; 146 | 147 | IDirectDrawSurface_BltFast(pddrawsf1, 0, 0, pddrawsf2, &r0, DDBLTFAST_WAIT); 148 | sub.WINMM.dll_timeGetTime_4f6(2400); 149 | event_calls_table[t](1); 150 | free(dw_48c5ac); 151 | } 152 | -------------------------------------------------------------------------------- /csrc/player_action.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include "player_info.h" 7 | 8 | void WINAPI some_game_loop_func(HWND hWnd, int, int, int); 9 | 10 | void player_action_1(int a0) 11 | { 12 | /* push 4 registers */ 13 | some_game_loop_func(gwindowHandle, 0xf, 0, 0); 14 | if (a0 == 0) 15 | return; 16 | 17 | GetCursorPos_35d(NULL); /* fcn_4021f8.c */ 18 | IDirectDrawSurface_BltFast(pddrawsf1, g_rect.left, g_rect.top, pddrawsf2, &g_rect, 0x10); 19 | GetCursorPos_250(NULL); /* fcn_4021f8.c */ 20 | dw_475110 = 0; 21 | } 22 | 23 | special_player_info special_players[5]; // 0x498e28 24 | 25 | void player_action_2(int a0, int a1, int a2) 26 | { 27 | int t0, t1; 28 | /* push ebp */ 29 | if ((byte)a2 != 1) { 30 | fcn.0040829d(-1, 0); /* TODO: a very long function */ 31 | dw_475110 |= 2; 32 | } else { 33 | if (current_player < 4) { 34 | t0 = players[current_player].f8; 35 | t1 = players[current_player].f10; 36 | } else { 37 | t0 = special_players[current_player - 4].f0; 38 | t1 = special_players[current_player - 4].f2; 39 | } 40 | if (t0 == a0 && t1 == a1) { 41 | dw_48be18 = 0; 42 | } else { 43 | dw_48be18 = 1; 44 | dw_48be1c = a0; 45 | dw_48be20 = a2; 46 | } 47 | fcn.00416e6d(0); /* TODO: a long function */ 48 | fcn.00415e70(0); 49 | } 50 | if (a2 & 2) { 51 | fcn.00415d31(0); 52 | } 53 | if (a2 & 4) { 54 | some_game_loop_func(gwindowHandle, 15, 0, 0); 55 | } 56 | fcn.004192f7(); 57 | } 58 | 59 | void fcn_41d546() 60 | { 61 | dw_48be18 = 0; 62 | player_action_1(1); 63 | } 64 | -------------------------------------------------------------------------------- /csrc/sound_struct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | typedef struct 7 | { 8 | uint32_t f0; 9 | LPDIRECTSOUNDBUFFER sbuf; 10 | } sound_struct; 11 | 12 | extern sound_struct snd0, snd1, snd2; 13 | -------------------------------------------------------------------------------- /csrc/tools_ui.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include "player_info.h" 7 | #include "window_util.h" 8 | 9 | const char str_cross_sym[] = "\xa1\xd1%d"; // x%d 10 | 11 | char tab_48c548[16]; 12 | int selected_tool; // 0x48c560 13 | uint8_t tool_amount[60]; // 0x49915c 4*15 14 | struct graph_st * dw_48c558; 15 | 16 | void fcn_447c6e(struct graph_st *a1, struct graph_st *a2, int player) 17 | { 18 | char str[40]; 19 | 20 | memset(tab_48c548, 0, 16); 21 | create_some_font(20, 0xffffff, 0x101010, 3, 0); 22 | 23 | if (a1 == NULL) { 24 | a1 = (struct graph_st*)((void*)(a2) + 24); 25 | } else { 26 | fcn_00456280(a1, (struct graph_st*)((void*)(a2) + 24), 0, 0); 27 | } 28 | 29 | int j = 0; 30 | int t = 45; 31 | int k = 0x21; 32 | 33 | for (int i = 0; i < 13; i++) { /* 13 kinds of tools */ 34 | size_t idx = player * 15 + i; 35 | if (tool_amount[idx] == 0) 36 | continue; 37 | graph_st_overlay(a1, ((void*)(a2->data)) + (i+2)*12, t - 16, k); 38 | sprintf(str, str_cross_sym, (int)tool_amount[idx]); 39 | draw_some_text(a1, str, t + 34, k - 10, 1); 40 | tab_48c548[j] = i + 1; 41 | j++; 42 | t += 80; 43 | if (t <= 365) 44 | continue; 45 | t = 45; 46 | k += 56; 47 | } 48 | } 49 | 50 | LRESULT CALLBACK toolsProc(HWND hWnd, UINT message, WPARAM wp, LPARAM lp) 51 | { 52 | PAINTSTRUCT ps; 53 | RECT r1; 54 | 55 | if (message >= 0x202) { 56 | if (message == 0x202) { 57 | if (selected_tool == 0) 58 | return 0; 59 | fcn.00451d4e(); 60 | fcn_00402460(0); 61 | Post_0402_Message(selected_tool); 62 | return 0; 63 | } 64 | if (message < 0x205) { 65 | return DefWindowProcA(hWnd, message, wp, lp); 66 | } else if (message == 0x205) { 67 | fcn_00402460(0); 68 | Post_0402_Message(0); 69 | return 0; 70 | } 71 | 72 | if (message != 0x401) { 73 | return DefWindowProcA(hWnd, message, wp, lp); 74 | } else { 75 | edx = 0; 76 | selected_tool = 0; 77 | fcn_00402460(1); 78 | InvalidateRect(hWnd, NULL, FALSE); 79 | return 0; 80 | } 81 | } 82 | 83 | if (message < 0xf) { 84 | return DefWindowProcA(hWnd, message, wp, lp); 85 | } else if (message == 0xf) { 86 | BeginPaint(hWnd, &ps); 87 | GetCursorPos_35d(&ps.rcPaint); 88 | IDirectDrawSurface_BltFast(pddrawsf1, ps.rcPaint.left, ps.rcPaint.top, pddrawsf2, &ps.rcPaint, 0x10); 89 | GetCursorPos_250(&ps.rcPaint); 90 | EndPaint(hWnd, &ps); 91 | return 0; 92 | } 93 | if (message != 0x201) { 94 | return DefWindowProcA(hWnd, message, wp, lp); 95 | } 96 | 97 | ebx = (uint16_t)lp; 98 | eax = (lp >> 16) & 0xffff; 99 | edx = (uint16_t)eax; 100 | if (ebx < 0x13 || ebx >= 0x1a3 || edx < 0x87 || edx >= 0x12f) 101 | return 0; 102 | 103 | ecx = ((edx - 0x87) / 56) * 5; 104 | eax = (ebx - 0x13) / 80; 105 | ebx = ecx + eax; 106 | if (tab_48c548[ebx] == 0) 107 | return 0; 108 | 109 | eax = (ebx % 5) * 80; 110 | r1.left = eax + 0x14; 111 | r1.right = eax + 0x62; 112 | 113 | eax = (ebx / 5) * 56; 114 | r1.top = eax + 0x88; 115 | r1.bottom = eax + 0xbe; 116 | fcn.00451b9e(&r1); 117 | 118 | selected_tool = tab_48c548[ebx]; 119 | fcn_4542ce(&snd0, 0); 120 | return 0; 121 | } 122 | 123 | void tools_ui() 124 | { 125 | dl = players[current_player].who_plays; 126 | if (dl != 1) 127 | goto 0x447f82; 128 | 129 | fcn_41d546(); 130 | ebx = eax = read_mkf(mkf_panel, 11, NULL, NULL); 131 | edi = eax; 132 | fcn_447c6e(NULL, eax, current_player); 133 | edx = ebx + 0x18; 134 | cl = players[current_player].traffic_method; 135 | if (cl == 1) { 136 | ebx += 0xc0; 137 | fcn_00456280(edx, ebx, 0x145, 0x75); 138 | b_48c556 = 0xe; 139 | } else if (cl == 2) { 140 | ebx += 0xcc; 141 | fcn_00456280(edx, ebx, 0x145, 0x75); 142 | b_48c556 = 0xe; 143 | } 144 | IDirectDrawSurface_Lock(pddrawsf2, 0, &sfdesc1, 1, 0); 145 | st_46caec.f8 = sfdesc1.lpSurface; 146 | dw_48c558 = crop_graph(&st_46caec, NULL, 0, 40, 440, 440); 147 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 148 | 149 | do { 150 | ebx = 1; 151 | 152 | IDirectDrawSurface_Lock(pddrawsf2, 0, &sfdesc1, 1, 0); 153 | overlay_fullscreen(sfdesc1.lpSurface, edi + 0x18, 0xe, 0x82); 154 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 155 | 156 | esi = register_wait_callback(toolsProc, 0); 157 | 158 | IDirectDrawSurface_Lock(pddrawsf2, 0, &sfdesc1, 1, 0); 159 | overlay_fullscreen(sfdesc1.lpSurface, dw_48c558, 0, 40); 160 | IDirectDrawSurface_Unlock(pddrawsf2, NULL); 161 | 162 | RECT r1 = { .left = 0, .top = 40, .right = 440, .bottom = 480 }; 163 | IDirectDrawSurface_BltFast(pddrawsf1, 0, 40, pddrawsf2, &r1, 0x10); 164 | 165 | if (esi != 0) { 166 | ebx = call dword [esi*4 + 0x475dd5]; 167 | } 168 | } while (ebx == 0); 169 | 170 | free(edi); 171 | free(dw_48c558); 172 | return; 173 | 447f82: 174 | if ((dl & 6) == 0) 175 | return; 176 | if (byte [eax+0x496b7e] & 2 == 0) 177 | return; 178 | memset(esp+0x40, 0, 13); 179 | ecx = 0; 180 | 181 | 182 | esi = 0; 183 | for (int i = 0; i < 13; i++) { 184 | if (tool_amount[current_player * 15 + i] == 0) 185 | continue; 186 | if (i == 9) 187 | continue; 188 | byte [esp+esi+0x38] = i+1; 189 | esi++; 190 | } 191 | if (esi == 0) 192 | return; 193 | if (esi > 4) { 194 | ebx = rand() % esi; 195 | } else { 196 | ebx = 0; 197 | } 198 | 199 | edi = 0; 200 | int j = 0; 201 | 202 | while (1) { 203 | dh = byte [esp+ebx+0x38]; 204 | if (dh == 0) 205 | return; 206 | eax = 0; 207 | al = dh; 208 | eax = fcn.00420e9a(eax); 209 | if (eax != 1) { 210 | ebx++; 211 | if (ebx == esi) { 212 | ebx = 0; 213 | } 214 | j++; 215 | if (j >= 4) 216 | return; 217 | continue; 218 | } 219 | break; 220 | } 221 | eax = 0; 222 | al = byte [esp + ebx + 0x38]; 223 | sprintf(esp, str.use, dword [eax*8+0x47feda]); 224 | fcn.00440cac(esp, 1500); 225 | eax = 0; 226 | al = byte [esp + ebx + 0x38]; 227 | call dword [eax*4 + 0x475dd5]; 228 | } 229 | -------------------------------------------------------------------------------- /csrc/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Iru Cai 3 | * SPDX-License-Identifier: GPL-3.0-or-later 4 | */ 5 | 6 | #include 7 | 8 | void strcpy_without_spaces(char * a1, const char * a2) 9 | { 10 | size_t j = 0; 11 | size_t L = strlen(a2); 12 | 13 | for (size_t i = 0; i < L; i++) { 14 | if (a2[i] == ' ') { 15 | continue; 16 | } 17 | a1[j] = a2[i]; 18 | j++; 19 | } 20 | a1[j] = 0; 21 | } 22 | -------------------------------------------------------------------------------- /docs/characters.txt: -------------------------------------------------------------------------------- 1 | 游戏人物 2 | ======== 3 | 4 | 00: 约翰乔 5 | 01: 沙隆巴斯 6 | 02: 忍太郎 7 | 03: 钱夫人 8 | 04: 阿土伯 9 | 05: 莎拉公主 10 | 06: 宫本宝藏 11 | 07: 糖糖 12 | 08: 乌咪 13 | 09: 孙小美 14 | 0a: 小丹尼 15 | 0b: 金贝贝 16 | 17 | 如果只改存档中玩家信息的 0x13 字节,角色发生变化,再存档后角色名称的指针也发生变化,但是读档后(只测试过第一次读档,没测试过再次存档后读档),角色的性别没变(从魔法屋事件可以看出来)。 18 | -------------------------------------------------------------------------------- /docs/global_vars.txt: -------------------------------------------------------------------------------- 1 | 0x4967e0, 0xc*0x1c=0x150 2 | 3 | 0x496980, 0x24*12=0x1b0 4 | 0x496b30, 8 5 | 0x496b38, 0x25 6 | 7 | 0x496b60, 8 8 | 0x496b68, 0x68*4=0x1a0: player info for 4 players 9 | the first player: 10 | 0x496b68, 4: pointer to player name /* 0x00 */ 11 | 0x496b6c, 4 12 | 0x496b70, 2 13 | 0x496b72, 2 14 | 0x496b74, 2 15 | 0x496b76, 2 16 | 0x496b78, 1 /* 0x10 */ 17 | 0x496b79, 1: 0: on foot, 1: moto, 2: car 18 | 0x496b7a, 1: number of dices 19 | 0x496b7b, 1: character (see characters.txt) 20 | 0x496b7c, 1 21 | 0x496b7d, 1 (bank related) 22 | 0x496b7e, 1 23 | 0x496b7f, 1 24 | 0x496b80, 1 25 | 0x496b81, 1 26 | 0x496b82, 1 27 | 0x496b83, 1 28 | 0x496b84, 4: cash 29 | 0x496b88, 4: money, in bank (+ special financing) /* 0x20 */ 30 | 0x496b8c, 4: loan 31 | 0x496b90, 4: special financing 32 | 0x496b94, 4 33 | 0x496b98, 2: points (uint16_t) /* 0x30 */ 34 | 0x496b9a, 1: days in hotel (lowest 7 bits, same as the next fields) 35 | 0x496b9b, 1: days disappearing (MSB: about to appear again) 36 | 0x496b9c, 1: days in prison (what does the MSB mean?) 37 | 0x496b9d, 1: days in hospital (what does the MSB mean?) 38 | 0x496b9e, 1: days in winter sleep 39 | 0x496b9f, 1: days dream walking 40 | 0x496ba0, 1: days stopping /* 0x38 */ 41 | 0x496ba1, 1: days tortoise walking 42 | 0x496ba2, 1: (not used?) 43 | 0x496ba3, 1: number of days rejected by bank 44 | 0x496ba4, 1: number of days bank stop making loans 45 | 0x496ba5, 1 46 | 0x496ba6, 1: days of assurance (uint8_t) 47 | 0x496ba7, 1: god information (cannot find what the bits mean yet) 48 | 0x496ba8, 1 /* 0x40 */ 49 | 0x496ba9, 1 50 | 0x496baa, 1 51 | 0x496bab, 1: not used 52 | 0x496bac, 2 53 | 0x496bae, 2 54 | 0x496bb0, 2 55 | 0x496bb2, 2 56 | 0x496bb4, 4 (dword array?) 57 | 0x496d08, 0x18*0x2e=0x450 58 | 0x497158, 0x48: global rich4 config 59 | 0x497160: 4 byte date (day, month, year) 60 | 0x4971a0, 8*0x30=0x180 61 | 0x497320, 8 62 | 0x497328, 4*0x6c0=0x1b00 63 | 0x498e28, 0x10*5 64 | 65 | 0x498e94, 4 66 | 67 | 0x499078, 4 68 | 0x49907c, 4 69 | 0x499080, 4 70 | 0x499084, 4 71 | 0x499088, 4 72 | 0x49908c, 4 73 | 0x499090, 0x24 74 | 0x4990b4, 4 75 | 0x4990b8, 0x24 76 | 0x4990dc, 4: number of days the stock market rests 77 | 0x4990e0, 4 78 | 0x4990e4, 4 79 | 0x4990e8, 4: price index 80 | 0x4990ec, 4 81 | 0x4990f0, 4 82 | 0x4990f4, 0xc 83 | 0x499100, 4 84 | 0x499104, 4 85 | 0x499108, 4 86 | 0x49910c, 4 87 | 0x499110, 4 88 | 0x499114, 4: number of players, including bankrupt players 89 | 0x499118, 4 90 | 0x49911c, 4 91 | 92 | 0x499120, 0x3c 93 | 0x49915c, 0x3c 94 | 0x144198, 0x1e 95 | 96 | 0x4991b6, 2 97 | 0x4991b8, 2 98 | -------------------------------------------------------------------------------- /docs/radare2_tips.txt: -------------------------------------------------------------------------------- 1 | 对一个地址处的连续多个函数指针进行 af 操作:af @@=`pf 20p @ 0x00475f64 ~=[1]` 2 | -------------------------------------------------------------------------------- /docs/rich4_cfg.txt: -------------------------------------------------------------------------------- 1 | file: RICH4.CFG 2 | 3 | game speed: offset 0, 00,01,02 4 | animation: offset 1, 01 enabled 5 | music: offset 2, 00~04 6 | sound effect: offset 3, 00-04 7 | auto save: offset 4, 01 enabled 8 | view: offset 5, 00 calendar, 01 small map, 02 combined view 9 | day: offset 8 10 | month: offset 9 11 | year: offset 10-11, little endian 12 | 13 | hot keys: 14 | RICH4.CFG uses two bytes to represent one key. 15 | The first byte is the key: use virtual key code 16 | The second byte is the mod key: 0x11 Ctrl 17 | A-Z: same as ascii (0x41-0x5a) 18 | <: 0xbc (VK_OEM_COMMA, '<' + 0x80) 19 | >: 0xbe (VK_OEM_PERIOD, '>' + 0x80) 20 | PGUP: 0x21 (VK_PRIOR) 21 | PGDN: 0x22 (VK_NEXT) 22 | ENTER, ESC, TAB: 0x0d, 0x1b, 0x09 (same as ASCII) 23 | ARROW LEFT, UP, RIGHT, DOWN: 0x25-0x28 (VK_{LEFT,UP,RIGHT,DOWN}) 24 | 25 | offset 0x10: 游标{上移,右移,下移,左移} 确定 取消 切换选项 切换视窗组 26 | offset 0x20: YES NO 前进 选择骰子数 股市 交易 卡片 道具 27 | offset 0x30: 查询 地图 地图向左旋转 地图向右旋转 托管 系统 SAVE LOAD 28 | offset 0x40: 辅助说明 向上换页 向下换页 结束 29 | -------------------------------------------------------------------------------- /docs/saveload.txt: -------------------------------------------------------------------------------- 1 | 大富翁4存档格式 2 | =============== 3 | 4 | 开始是4字节的标识,之后4字节存储日期。 5 | 6 | 在 0xc 处的 4 字节存储玩家数量,包括已倒闭的玩家。 7 | 8 | 0x10 开始的 0x68*4 字节存储玩家信息,每个玩家 0x68 字节,格式见 player_info.h. 9 | 10 | 0x654 开始的 15*4 字节存储每个玩家的卡片。 11 | 12 | 0x690 开始的 15*4 字节存储每个玩家每种道具的数量,道具数量用8位无符号数表示。 13 | -------------------------------------------------------------------------------- /docs/special_place.txt: -------------------------------------------------------------------------------- 1 | 特殊地点 2 | ======== 3 | 4 | 新闻 5 | ---- 6 | 7 | - events_calls_table (0x475e24): 保存所有新闻的回调函数 8 | - 函数 news_events (0x44b6df) 9 | 10 | 命运 11 | ---- 12 | 13 | - fortune_call_table (0x475ef0): 保存所有命运的回调函数 14 | - fortune_events (0x44db81) 15 | 16 | 魔法屋 17 | ------ 18 | 19 | 魔法屋共有12个功能。相关数据结构和函数: 20 | 21 | - magic_house_functions (0x475724): 每项16字节,开头4字节为该功能的 BIG5 字符串 22 | - 函数 magic_house (0x43380a): 魔法屋入口 23 | - 函数 magic_house_actions (0x431caa) 24 | -------------------------------------------------------------------------------- /r2/rich4_dump.py: -------------------------------------------------------------------------------- 1 | # The script to dump rich4.exe to assembly 2 | # SHA256(rich4.exe): 5a90aee28ee5f7a5c3ba5cb935c9e55751a529c25fcd91208748a66293569550 3 | 4 | from dumpbin_pe import R2PEDumper 5 | import r2pipe 6 | import sys 7 | 8 | if __name__ == "__main__": 9 | if len(sys.argv) > 1: 10 | r2dumpbin = R2PEDumper(r2pipe.open(sys.argv[1])) 11 | else: 12 | r2dumpbin = R2PEDumper() 13 | 14 | # call back functions 15 | r2dumpbin.mark_function(0x401010) 16 | r2dumpbin.mark_function(0x4019dd) 17 | r2dumpbin.mark_function(0x401f98) 18 | 19 | # parameter of fcn_004018e7 (register_wait_callback) 20 | callbacks = [0x40257a, 0x40363a, 0x4039c2, 0x404e44, 0x4060e9, 21 | 0x406b14, 0x40a801, 0x4103a3, 0x410ac3, 0x411122, 22 | 0x414858, 0x414bbc, 0x414fcd, 0x41dda9, 0x423cf3, 23 | 0x4258c1, 0x42608f, 0x4267a4, 0x426c2e, 0x42704e, 24 | 0x427c21, 0x429d65, 0x42aaff, 0x42b2ec, 0x42b3eb, 25 | 0x42d37f, 0x42d73f, 0x42f7fc, 0x43010c, 0x4325c2, 26 | 0x433088, 0x434492, 0x435062, 0x436034, 0x436ef8, 27 | 0x437e61, 0x43a2dd, 0x43caab, 0x43da27, 0x43fae4, 28 | 0x43ff56, 0x4402d7, 0x4413ec, 0x4416f0, 0x445e4d, 29 | 0x445c14, 0x446774, 0x44e40b, 0x45156f, 0x452c02, 30 | 0x45367e] 31 | 32 | # fcn_00457e6c callbacks 33 | callbacks += [0x4079f9, 0x42bed0, 0x42d0ef] 34 | 35 | # fcn_0045ae76 callbacks 36 | callbacks += [0x458d9e] 37 | 38 | # SetUnhandledExceptionFilter callbacks 39 | callbacks += [0x45a758] 40 | 41 | callbacks += [0x45a98b] 42 | 43 | for f in callbacks: 44 | r2dumpbin.mark_function(f) 45 | 46 | # jump table functions 47 | # 0x402566 48 | r2dumpbin.mark_function(0x40274c) 49 | r2dumpbin.mark_function(0x40264d) 50 | r2dumpbin.mark_function(0x4026e2) 51 | 52 | # 0x408289 53 | r2dumpbin.mark_function(0x409419) 54 | r2dumpbin.mark_function(0x409426) 55 | r2dumpbin.mark_function(0x409434) 56 | r2dumpbin.mark_function(0x409442) 57 | r2dumpbin.mark_function(0x409449) 58 | 59 | # 0x40e023 60 | r2dumpbin.mark_function(0x40e04d) 61 | r2dumpbin.mark_function(0x40e059) 62 | r2dumpbin.mark_function(0x40e065) 63 | r2dumpbin.mark_function(0x40e071) 64 | 65 | # 0x40ea9b 66 | call_tab = [0x0040ec14, 0x0040ecf1, 0x0040ed8f, 0x0040ee50, 0x0040ef1b, 67 | 0x0040efe4, 0x0040f083, 0x0040f155, 0x0040f205, 0x0040f258, 68 | 0x0040ece6, 0x0040f2a0, 0x0040ece6, 0x0040ece6, 0x0040f2eb] 69 | 70 | # 0x41034b 71 | call_tab += [0x00410537, 0x00410572, 0x004105b9, 0x004105f4, 0x004105f4, 72 | 0x004105f4, 0x00410668, 0x004106c1, 0x004106c1, 0x00410745, 73 | 0x0041076e, 0x0041079c, 0x004107d8, 0x004107f3, 0x004107f3, 74 | 0x004107f3] 75 | 76 | # 0x41038b 77 | call_tab += [0x00410838, 0x00410838, 0x00410838, 0x004104a5, 0x0041095b, 78 | 0x00410969] 79 | 80 | # 0x474d5c 81 | call_tab += [0x4119e3, 0x411a86, 0x411a96] 82 | 83 | # 0x475324 84 | call_tab += [0x0041e6fe, 0x0041e779, 0x0041e9e2, 0x0041eae2, 85 | 0x0041e6e3, 0x0041e6e3, 0x0041ed3e, 0x0041ef26, 86 | 0x0041f037, 0x0041f1b3, 0x0041f400, 0x0041f6a9, 87 | 0x0041f901, 0x0041facc, 0x0041fe4e, 0x0041fe6f, 88 | 0x0041fe6f, 0x0041e6e3, 0x0041e6e3, 0x0041e6e3, 89 | 0x0041e6e3, 0x0041ff77, 0x0041fff8, 0x00420055, 90 | 0x004200ea, 0x004202d2, 0x0042040e, 0x0042062b, 91 | 0x004207cc] 92 | 93 | # 0x475d5c 94 | call_tab += [0x004420d8, 0x004421b4, 0x00442325, 0x00442622, 95 | 0x00442b02, 0x00442f4d, 0x0044309b, 0x00443225, 96 | 0x004434c0, 0x004436e0, 0x00443917, 0x00443b0f, 97 | 0x00443e3d, 0x00443f80, 0x004440ea, 0x004441dc, 98 | 0x004444bf, 0x004420d5, 0x004420d5, 0x004420d5, 99 | 0x004420d5, 0x00444c45, 0x00444e1a, 0x00444f25, 100 | 0x0044503f, 0x004451f0, 0x0044542d, 0x00445593, 101 | 0x00445710, 0x004458df] 102 | 103 | # 0x475dd8 (begins at 0x475dd9) 104 | call_tab += [0x00446afb, 0x00446baa, 0x00446c88, 0x00446d69, 105 | 0x00446e4a, 0x00446f05, 0x00446fbc, 0x004470f8, 106 | 0x00447295, 0x00447387, 0x00447428, 0x004479d2, 107 | 0x00447ace, 0x00447c00 ] 108 | 109 | # 0x4898ca 110 | call_tab += [0x457dda, 0x459c0c, 0x459ce1, 0x45bc21, 0x45c914, 111 | 0x45adb0, 0x45c50b, 0x45ce17, 0x45d00b, 0x457ddb, 112 | 0x45bcb1, 0x45a4c0] 113 | 114 | # 0x489728 115 | r2dumpbin.mark_function(0x45f7e8) 116 | 117 | # endloc: references jump table 0x48998c 118 | r2dumpbin.mark_function(0x45f133) 119 | 120 | # referenced at fcn_0045a3a0 121 | callbacks = [0x45a15e, 0x45a170, 0x45a182, 0x45a190, 0x45a142, 122 | 0x45a150, 0x45a1d5, 0x45a1df, 0x45a0b3, 0x45a11b, 123 | 0x45a087, 0x45a1b6, 0x45a1c4, 0x45a1bd, 0x45a1ce, 124 | 0x45a1f3, 0x45a378, 0x45a1e9, 0x45a1fd] 125 | # referenced at fcn_0045ce17 126 | callbacks += [0x45cdac, 0x45cdf0] 127 | # CreateThread 128 | callbacks += [0x45f738] 129 | # SetConsoleCtrlHandler 130 | callbacks += [0x45cb60] 131 | # fcn_0045cdac 132 | callbacks += [0x45cb3c, 0x45cd2a] 133 | # fcn_00459bd3 134 | callbacks += [0x459bc2, 0x459bcb] 135 | 136 | for f in callbacks: 137 | r2dumpbin.mark_function(f) 138 | 139 | for f in call_tab: 140 | r2dumpbin.mark_function(f) 141 | 142 | r2dumpbin.run_tool() 143 | 144 | -------------------------------------------------------------------------------- /readme.rst: -------------------------------------------------------------------------------- 1 | 大富翁4逆向 2 | =========== 3 | 4 | 本项目为大富翁4的逆向项目。所逆向的大富翁4版本为v3.11版本,rich4.exe 文件大小为 588 KiB. 5 | 6 | 本逆向项目从2018年开始,做了3个月的逆向,发现了大富翁4的数据文件解压算法、存档格式等有用的信息,但是由于时间关系,没能继续此项目。在2021年5月,我采用逐步修改程序的思路进行逆向,用 `r2dumpbin `__ 将 rich4.exe 转为汇编,使得逆向,修改,测试可以同步进行,提高逆向效率。 7 | 8 | 参与项目 9 | ----------- 10 | 11 | 本 GitHub 项目用于接收 issue 和 pull request 和进行项目管理。 12 | 13 | 可以加入 Matrix 聊天室 #rich4re:matrixim.cc 进行讨论。 14 | 15 | 项目文件 16 | -------- 17 | 18 | * csrc: 逆向后的C代码 19 | * asm: rich4.exe 的反汇编,并将部分汇编代码替换为C代码 20 | * docs: 相关文档 21 | 22 | 如果需要阅读 r2dumpbin 转出来的反汇编代码,以及带注释的反汇编,可以见 https://codeberg.org/vimacs/rich4_asm 版本库。 23 | 24 | 构建 25 | ------- 26 | 27 | 本项目在 Arch Linux 下开发,使用 MinGW 工具链和 nasm 汇编器,可以执行 ``pacman -S mingw-w64 nasm`` 安装。 28 | 29 | 构建 rich4.exe:: 30 | 31 | cd asm 32 | make 33 | 34 | 将 rich4.exe 复制到大富翁4的游戏目录,用 wine 运行即可启动游戏。 35 | 36 | radare2 工程文件和辅助脚本 37 | ----------------------------- 38 | 39 | 本项目的 radare2 工程文件和辅助脚本在另一仓库中,用如下方式获取:: 40 | 41 | git clone https://git.wehack.space/rich4.r2 r2 42 | --------------------------------------------------------------------------------