Extract cutscene scripts, portraits and normalize code (#1686)

More research on how cutscenes work.

I normalized all the various C files as `cutscene.c`, marked all the
isolated function as `static` and renamed the main entity as
`{STAGE}_CutsceneExec` (e.g. `CEN_CutsceneExec`). I am using the
`OVL_EXPORT` to automate the names.

TO-DO:

- [x] Rename entity as `{STAGE}_EntityCutscene` for consistency
- [x] CEN
- [x] DRE
- [x] NO3
- [x] NZ0
- [x] ST0
- [x] MAR
~~SEL~~

The offset of the portrait data seems to be hardcoded. I have no idea
how to resolve these offsets at compilation time. The entire cutscene
script thing is very sketchy and horribly designed by the original
developers. What a nightmare to integrate into our project.

This is how a cutscene script gets decompiled:

```
LOAD_PORTRAIT(0x80188D8C, 0),
SET_PORTRAIT(1, 0),
SCRIPT_UNKNOWN_11(),
PLAY_SOUND(0x37B),
WAIT_FOR_SOUND(),
SET_SPEED(4),
'T','h','a','t',' ','v','o','i','c','e','!',' ',
SET_WAIT(16),
SET_SPEED(3),
'A','l','u','c','a','r','d',',',
LINE_BREAK(),
SET_WAIT(16),
SET_FLAG(2),
'i','t','\'','s',' ','y','o','u','!',
SET_WAIT(48),
NEXT_DIALOG(),
```
This commit is contained in:
Luciano Ciccariello 2024-09-29 03:56:35 +01:00 committed by GitHub
parent 4be6249664
commit f86e111fc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
64 changed files with 1089 additions and 1025 deletions

View File

@ -253,7 +253,7 @@ set(SOURCE_FILES_STAGE_SEL
src/st/sel/33164.c
src/st/sel/3410C.c
src/st/sel/3585C.c
src/st/sel/3642C.c
src/st/sel/cutscene.c
)
set(SOURCE_FILES_STAGE_CEN
@ -269,7 +269,7 @@ set(SOURCE_FILES_STAGE_CEN
src/st/cen/st_debug.c
src/st/cen/e_breakable.c
src/st/cen/DB18.c
src/st/cen/holyglassescutscene.c
src/st/cen/cutscene.c
src/st/cen/F890.c
src/st/cen/st_update.c
src/st/cen/collision.c
@ -286,7 +286,7 @@ set(SOURCE_FILES_STAGE_CEN
src/st/cen/prim_helpers.c
src/st/cen/header.c
src/st/cen/create_entity.c
src/st/cen/holyglassescutscene.c
src/st/cen/cutscene.c
src/st/cen/e_collect.c
)

View File

@ -92,6 +92,7 @@ define list_st_src_files
$(foreach dir,$(ASM_DIR)/$(1)/data,$(wildcard $(dir)/**.s))
$(foreach dir,$(SRC_DIR)/$(1),$(wildcard $(dir)/**.c))
$(foreach dir,$(ASSETS_DIR)/$(1),$(wildcard $(dir)/D_8018*.bin))
$(foreach dir,$(ASSETS_DIR)/$(1),$(wildcard $(dir)/cutscene_*.bin))
endef
define list_o_files

View File

@ -8,6 +8,51 @@ files:
assets:
- [0x13F0, cutscene, cutscene_data]
- [0x1658, skip]
- target: disks/us/ST/DRE/DRE.BIN
asset_path: assets/st/dre
src_path: src/st/dre
segments:
- start: 0
vram: 0x80180000
assets:
- [0x16C8, cutscene, cutscene_data]
- [0x1D05, skip]
- target: disks/us/ST/NO3/NO3.BIN
asset_path: assets/st/no3
src_path: src/st/no3
segments:
- start: 0
vram: 0x80180000
assets:
- [0x4CE0, cutscene, cutscene_data]
- [0x4E60, skip]
- target: disks/us/ST/NZ0/NZ0.BIN
asset_path: assets/st/nz0
src_path: src/st/nz0
segments:
- start: 0
vram: 0x80180000
assets:
- [0x3B0C, cutscene, cutscene_data]
- [0x3CB8, skip]
- target: disks/us/ST/ST0/ST0.BIN
asset_path: assets/st/st0
src_path: src/st/st0
segments:
- start: 0
vram: 0x80180000
assets:
- [0x29D8, cutscene, cutscene_data]
- [0x2C4C, skip]
- target: disks/us/BOSS/MAR/MAR.BIN
asset_path: assets/boss/mar
src_path: src/boss/mar
segments:
- start: 0
vram: 0x80180000
assets:
- [0x1424, cutscene, cutscene_data]
- [0x15DC, skip]
- target: disks/us/BIN/WEAPON0.BIN
asset_path: assets/weapon
src_path: src/weapon

View File

@ -18,6 +18,7 @@ options:
use_legacy_include_asm: false
migrate_rodata_to_functions: true
asm_jtbl_label_macro: jlabel
extensions_path: tools/splat_ext
symbol_name_format: us_$VRAM
disassemble_all: True
section_order:
@ -45,7 +46,7 @@ segments:
- [0x310, .data, e_init]
- [0x4E8, .data, st_debug]
- [0x568, .data, e_breakable]
- [0x5D4, data] # AFC4
- [0x5D4, data, cutscene]
- [0x764, .data, st_update]
- [0x790, .data, collision]
- [0xB50, .data, e_red_door]
@ -58,12 +59,16 @@ segments:
- [0x12EC, .data, rooms]
- [0x1308, .data, e_life_up]
- [0x135C, .data, e_layout] # layout entries data
- [0x1424, data]
- [0x1424, .data, cutscene_data]
- [0x15DC, data]
- [0x15F0, raw, cutscene_alucard]
- [0x2370, raw, cutscene_maria]
- [0x30F0, data]
- [0x5300, .data, tile_data] # tile data
- [0x5700, .data, tile_data] # tile definitions
- [0x9710, .data, sprites]
- [0xA9D4, data]
- [0xA9EC, .rodata, AFC4]
- [0xA9EC, .rodata, cutscene]
- [0xAA70, .rodata, CA94]
- [0xAAB0, .rodata, e_red_door]
- [0xAAC8, .rodata, e_collect]
@ -74,7 +79,7 @@ segments:
- [0xABF0, .rodata, e_life_up]
- [0xAC0C, c, st_debug]
- [0xAE90, c, e_breakable]
- [0xAFC4, c]
- [0xAFC4, c, cutscene]
- [0xCA94, c]
- [0xCF70, c, st_update]
- [0xD3A4, c, collision]

View File

@ -42,7 +42,7 @@ segments:
- [0x394, .data, e_init]
- [0x4D4, .data, st_debug]
- [0x554, .data, e_breakable]
- [0x5D8, .data, holyglassescutscene]
- [0x5D8, .data, cutscene]
- [0x68C, .data, F890]
- [0x7B8, .data, st_update]
- [0x7E4, .data, collision]
@ -58,6 +58,8 @@ segments:
- [0x13F0, .data, cutscene_data]
- [0x1658, cmp, D_80181658]
- [0x199C, cmp, D_8018199C]
- [0x1F40, raw, cutscene_alucard]
- [0x2CC0, raw, cutscene_maria]
- [0x3A40, cmp, D_80183A40]
- [0x4B70, cmp, D_80184B70]
- [0x5830, cmp, D_80185830]
@ -69,7 +71,7 @@ segments:
- [0x81EC, .data, tile_data] # tile definitions
- [0xC60C, .data, sprites]
- [0xD414, .rodata, e_init]
- [0xD42C, .rodata, holyglassescutscene]
- [0xD42C, .rodata, cutscene]
- [0xD4B0, .rodata, F890]
- [0xD4D8, .rodata, e_red_door] # EntityRedDoor
- [0xD540, .rodata, e_collect] # EntityPrizeDrop
@ -81,7 +83,7 @@ segments:
- [0xD600, c, st_debug]
- [0xD89C, c, e_breakable]
- [0xDB18, c]
- [0xDF0C, c, holyglassescutscene]
- [0xDF0C, c, cutscene]
- [0xF890, c]
- [0x10E4C, c, st_update]
- [0x11280, c, collision]
@ -98,6 +100,6 @@ segments:
- [0x1BED4, c, prim_helpers]
- [0x1C704, .bss, header]
- [0x1C764, .bss, create_entity]
- [0x1C774, .bss, holyglassescutscene]
- [0x1C774, .bss, cutscene]
- [0x1C7C0, .bss, e_collect]
- [0x1D46C]

View File

@ -47,7 +47,7 @@ segments:
- [0x650, data]
- [0x660, data]
- [0x770, data]
- [0x938, .data, succubuscutscene]
- [0x938, .data, cutscene]
- [0x944, data]
- [0x97C, .data, st_update]
- [0x9A8, .data, collision]
@ -61,14 +61,20 @@ segments:
- [0x14AC, data]
- [0x1608, .data, e_layout] # layout entries data
- [0x16C0, data]
- [0x16C8, .data, cutscene_data]
- [0x1D08, data]
- [0x800C, raw, cutscene_alucard]
- [0x8D8C, raw, cutscene_mother]
- [0x9B0C, raw, cutscene_succubus]
- [0xA88C, data]
- [0xB548, .data, tile_data] # tile data
- [0xBD48, .data, tile_data] # tile definitions
- [0x10168, .data, sprites]
- [0x1171C, .rodata, 11A64]
- [0x11728, .rodata, succubus] # EntitySuccubus
- [0x11808, .rodata, succubuscutscene]
- [0x1181C, .rodata, succubuscutscene] #D_80180938, names
- [0x1183C, .rodata, succubuscutscene] #EntitySuccubusCutscene
- [0x11808, .rodata, cutscene]
- [0x1181C, .rodata, cutscene] #D_80180938, names
- [0x1183C, .rodata, cutscene] #DRE_EntityCutscene
- [0x118C0, .rodata, 161DC] #EntityCSMoveAlucard, string and jumps
- [0x118F8, .rodata, 161DC] # EntityUnkId23
- [0x11910, .rodata, 1697C] # EntityFadeToWhite
@ -80,7 +86,7 @@ segments:
- [0x11A5C, .rodata, prim_helpers]
- [0x11A64, c]
- [0x11A64, c, succubus]
- [0x14774, c, succubuscutscene]
- [0x14774, c, cutscene]
- [0x161DC, c]
- [0x1697C, c]
- [0x16F90, c, st_update]

View File

@ -67,7 +67,11 @@ segments:
- [0x3C44, data]
- [0x3CC4, .data, rooms]
- [0x3DC8, .data, e_layout] # layout entries data
- [0x4CE0, data]
- [0x4CE0, .data, cutscene_data]
- [0x4E60, data]
- [0x11B88, raw, cutscene_alucard]
- [0x12908, raw, cutscene_death]
- [0x13688, data]
- [0x18838, .data, tile_data] # tile data
- [0x26638, .data, tile_data] # tile definitions
- [0x2EA68, .data, sprites]
@ -77,7 +81,7 @@ segments:
- [0x37414, .rodata, 3C4EC]
- [0x3742C, .rodata, 3E134] #EntityFlyingOwlAndLeaves
- [0x37440, rodata]
- [0x37458, .rodata, deathcutscene] # EntityDeathCutscene
- [0x37458, .rodata, cutscene] # NO3_EntityCutscene
- [0x374DC, .rodata, 3FF00] # EntityRoomTransition2
- [0x374F4, .rodata, 3FF00] # EntityDeathStolenItems
- [0x37514, .rodata, 3FF00] # EntityDeath
@ -103,7 +107,7 @@ segments:
- [0x377D4, c]
- [0x3C4EC, c]
- [0x3E134, c]
- [0x3E544, c, deathcutscene]
- [0x3E544, c, cutscene]
- [0x3FF00, c]
- [0x4184C, c, st_update]
- [0x41C80, c, collision]

View File

@ -62,7 +62,11 @@ segments:
- [0x272C, .data, rooms]
- [0x2830, .data, e_life_up]
- [0x2884, .data, e_layout] # layout entries data
- [0x3B0C, data]
- [0x3B0C, .data, cutscene_data]
- [0x3CB8, data]
- [0x13BA4, raw, cutscene_maria]
- [0x14924, raw, cutscene_alucard]
- [0x156A4, data]
- [0x16A5C, .data, tile_data] # tile data
- [0x20A5C, .data, tile_data] # tile definitions
- [0x26E8C, .data, sprites]
@ -74,7 +78,7 @@ segments:
- [0x30618, .rodata, gaibon] # EntityGaibon .rodata, 33FCC
- [0x3063C, .rodata, e_elevator] # func_801B7034
- [0x3064C, rodata]
- [0x30664, .rodata, mariacutscene]
- [0x30664, .rodata, cutscene]
- [0x306E8, .rodata, maria]
- [0x30728, .rodata, e_red_door]
- [0x30740, .rodata, e_collect] # CollectGold text
@ -101,7 +105,7 @@ segments:
- [0x35778, c, gaibon]
- [0x36DE4, c]
- [0x37034, c, e_elevator]
- [0x374CC, c, mariacutscene]
- [0x374CC, c, cutscene]
- [0x38E0C, c, maria]
- [0x394D4, c, st_update]
- [0x39908, c, collision]

View File

@ -42,7 +42,7 @@ segments:
- [0x4D0, .data, 3410C]
- [0x4E0, .data, banks]
- [0x728, data]
- [0x824, .data, 3642C]
- [0x824, .data, cutscene]
- [0x8DC, .data, save_mgr_pre]
- [0x8E4, palette, memcard_0]
- [0x904, palette, memcard_1]
@ -109,8 +109,8 @@ segments:
- [0x27B98, .rodata, 3410C] # TestCollision
- [0x27BD8, .rodata, 3410C] # func_801B55C8
- [0x27BF8, .rodata, 3585C]
- [0x27CD4, .rodata, 3642C] # g_DiagActors strings
- [0x27CF4, .rodata, 3642C] # func_801B69F8 jtbl
- [0x27CD4, .rodata, cutscene] # g_DiagActors strings
- [0x27CF4, .rodata, cutscene] # SEL_EntityCutscene jtbl
- [0x27D78, .rodata, save_mgr]
- [0x28040, .rodata, config_us] # equip strings
- [0x29B18, .rodata, config_us] # accessories strings
@ -124,7 +124,7 @@ segments:
- [0x33164, c, 33164]
- [0x3410C, c, 3410C]
- [0x3585C, c, 3585C]
- [0x3642C, c, 3642C]
- [0x3642C, c, cutscene]
- [0x380F0, c, save_mgr]
- [0x39744, c, stream]
- [0x3AB70, asm, handwritten/func_801BAB70]

View File

@ -41,7 +41,7 @@ segments:
- [0x4BC, data]
- [0x580, data]
- [0x770, data]
- [0x828, .data, draculacutscene] # "Richter, Dracula"
- [0x828, .data, cutscene] # "Richter, Dracula"
- [0x830, data]
- [0x990, data]
- [0xAB0, data]
@ -56,9 +56,13 @@ segments:
- [0x2060, .data, rooms]
- [0x2084, data]
- [0x26B8, .data, e_layout] # layout entries data
- [0x29D8, data]
- [0x29D8, .data, cutscene_data]
- [0x2C4C, data]
#- [0x3D1C, cmp]
- [0x487C, data]
- [0xF130, raw, cutscene_richter]
- [0xFEB0, raw, cutscene_dracula]
- [0x10C30, data]
#- [0x17F80, cmp]
- [0x187BC, data]
#- [0x1A40C, cmp]
@ -67,7 +71,7 @@ segments:
- [0x1E6D0, .data, tile_data] # tile definitions
- [0x226E0, .data, sprites]
- [0x27984, .rodata, 27D64]
- [0x279E8, .rodata, draculacutscene] # EntityDraculaCutscene
- [0x279E8, .rodata, cutscene] # ST0_EntityCutscene
- [0x27A74, .rodata, 2A218] # EntityCutscene
- [0x27AB4, .rodata, 2A8DC] # EntitySecretButton
- [0x27ACC, .rodata, 2A8DC] # EntitySecretStairs
@ -89,7 +93,7 @@ segments:
- [0x27D3C, .rodata, prim_helpers]
- [0x27D44, .rodata, 3D8F0]
- [0x27D64, c]
- [0x28984, c, draculacutscene]
- [0x28984, c, cutscene]
- [0x2A218, c]
- [0x2A8DC, c]
- [0x2B0C8, c]

View File

@ -28,7 +28,7 @@ EntitySuccubusClone = 0x80193E18;
EntityPinkBallProjectile = 0x80194214;
EntitySuccubusWingSpike = 0x80194488;
EntitySuccubusWingSpikeTip = 0x801946C4;
EntitySuccubusCutscene = 0x801950F8;
DRE_EntityCutscene = 0x801950F8;
EntityCSMoveAlucard = 0x80196238;
EntityUnkId23 = 0x80196678;
EntityFadeToWhite1 = 0x8019697C;

View File

@ -64,7 +64,7 @@ EntityBackgroundTrees = 0x801BDEB0;
EntityBackgroundCastleWall = 0x801BE080;
EntityFlyingOwlAndLeaves = 0x801BE134;
EntityFallingLeaf = 0x801BE444;
EntityDeathCutscene = 0x801BEEB0;
NO3_EntityCutscene = 0x801BEEB0;
EntityRoomTransition2 = 0x801BFF00;
EntityDeathStolenItem = 0x801C033C;
EntityDeath = 0x801C083C;

View File

@ -1,6 +1,6 @@
SEL_g_EntityGfxs = 0x80180760;
g_Streams = 0x8018B2EC;
func_801B69F8 = 0x801B69F8;
SEL_EntityCutscene = 0x801B69F8;
StreamDiskIsReady = 0x801B9744;
StreamNextVlc = 0x801B988C;
func_801BAB70 = 0x801BAB70;

View File

@ -19,7 +19,7 @@ D_80197F80 = 0x80197F80;
D_8019A40C = 0x8019A40C;
c_HeartPrizes = 0x801A7C84;
EntityLockCamera = 0x801A7EB0;
EntityDraculaCutscene = 0x801A9210;
ST0_EntityCutscene = 0x801A9210;
EntityCutscene = 0x801AA290;
EntitySecretButton = 0x801AA8DC;
EntitySecretStairsCeiling = 0x801AABA4;

View File

@ -5,31 +5,48 @@ typedef enum {
CSOP_LINE_BREAK,
CSOP_SET_SPEED,
CSOP_SET_WAIT,
CSOP_SET_PORTRAIT = 5,
CSOP_SCRIPT_UNKNOWN_4,
CSOP_SET_PORTRAIT,
CSOP_NEXT_DIALOG,
CSOP_SET_POS,
CSOP_CLOSE_DIALOG,
CSOP_PLAY_SOUND,
CSOP_WAIT_FOR_SOUND,
CSOP_UNK_11,
CSOP_WAIT_FOR_FLAG = 16,
CSOP_SET_END,
CSOP_SCRIPT_UNKNOWN_13,
CSOP_SCRIPT_UNKNOWN_14,
CSOP_SCRIPT_UNKNOWN_15,
CSOP_WAIT_FOR_FLAG,
CSOP_SET_FLAG,
CSOP_LOAD_PORTRAIT = 19,
CSOP_SCRIPT_UNKNOWN_18,
CSOP_LOAD_PORTRAIT,
CSOP_SCRIPT_UNKNOWN_20,
CSOP_SCRIPT_UNKNOWN_21,
CSOP_SCRIPT_UNKNOWN_22,
CSOP_SCRIPT_UNKNOWN_23,
CSOP_SCRIPT_UNKNOWN_24,
} CutsceneOpcode;
#define script_half(x) (((x) & 0xFF0) >> 4), ((x) & 0xFF)
#define script_word(x) (x & 0xFF000) >> 12, (x & 0xFF00) >> 8, script_half(x)
#define END_CUTSCENE() CSOP_END_CUTSCENE
#define LINE_BREAK() CSOP_LINE_BREAK
#define SET_SPEED(x) CSOP_SET_SPEED, x
#define SET_WAIT(x) CSOP_SET_WAIT, x
#define SET_PORTRAIT(clut, side) CSOP_SET_PORTRAIT, clut, !!side
#define SET_PORTRAIT(clut, side) CSOP_SET_PORTRAIT, clut, side
#define NEXT_DIALOG() CSOP_NEXT_DIALOG
#define SET_POS(x, y) CSOP_SET_POS, x, y
#define CLOSE_DIALOG() CSOP_CLOSE_DIALOG
#define PLAY_SOUND(x, y) CSOP_PLAY_SOUND, x, y
#define PLAY_SOUND(id) CSOP_PLAY_SOUND, script_half(id)
#define WAIT_FOR_SOUND() CSOP_WAIT_FOR_SOUND
#define SCRIPT_UNKNOWN_11() CSOP_UNK_11
#define SET_END(x) CSOP_SET_END, script_word(x)
#define SCRIPT_UNKNOWN_14(x, y, z) \
CSOP_SCRIPT_UNKNOWN_14, script_word(x), script_word(y), script_word(z)
#define SCRIPT_UNKNOWN_15(x) CSOP_SCRIPT_UNKNOWN_15, script_word(x)
#define WAIT_FOR_FLAG(x) CSOP_WAIT_FOR_FLAG, x
#define SET_FLAG(x) CSOP_SET_FLAG, x
#define LOAD_PORTRAIT(a, b, c, d, e) CSOP_LOAD_PORTRAIT, a, b, c, d, e
#define SCRIPT_UNKNOWN_20(x, y) CSOP_SCRIPT_UNKNOWN_20, x, y
#define LOAD_PORTRAIT(addr, id) CSOP_LOAD_PORTRAIT, script_word(addr), id
#define SCRIPT_UNKNOWN_20(x) CSOP_SCRIPT_UNKNOWN_20, script_half(x)

View File

@ -1449,7 +1449,7 @@ typedef struct {
} RelicOrb; /* size=0x10 */
typedef struct {
/* 0x00 */ const char* nextCharDialogue; // ptr to dialogue next character
/* 0x00 */ u8* scriptCur; // ptr to dialogue next character
/* 0x04 */ s16 startX; // starting x coord
/* 0x06 */ s16 nextLineY; // next line y coord
/* 0x08 */ s16 startY; // starting y coord
@ -1465,7 +1465,7 @@ typedef struct {
/* 0x30 */ s32 primIndex[3]; // primIndices: unk, actorName, unk
/* 0x3C */ u16 unk3C; // maybe it is a begin flag?
/* 0x3E */ u16 timer; // global timer
/* 0x40 */ const char* unk40; // dialogue settings, maybe?
/* 0x40 */ u8* scriptEnd; // pointer to the end of the script
} Dialogue; // size = 0x44
typedef struct {

1
src/boss/.gitignore vendored
View File

@ -6,3 +6,4 @@ layers.h
sprite_banks.h
tilemap_*.h
tiledef_*.h
cutscene_data.h

View File

@ -13,7 +13,7 @@ extern u8 D_us_80180718[];
extern u8 D_us_80180724[];
extern u8 D_us_80180738[];
extern u32 g_CutsceneFlags;
extern s32 D_us_8019AE70;
extern s32 skip_cutscene;
void func_us_8018CA94(Entity* self) {
Entity* player;
@ -24,7 +24,7 @@ void func_us_8018CA94(Entity* self) {
tilemap = &g_Tilemap;
player = &PLAYER;
if (D_us_8019AE70 && self->step < 12) {
if (skip_cutscene && self->step < 12) {
SetStep(12);
}

View File

@ -4,7 +4,7 @@
STATIC_PAD_BSS(3072);
s32 D_us_8019AE70;
s32 skip_cutscene;
Dialogue g_Dialogue;
s32 D_us_8019AEB8[26];
s32 g_CutsceneFlags;

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include <stage.h>
#include <cutscene.h>
#include "mar.h"
@ -15,13 +16,13 @@ extern Dialogue g_Dialogue;
#include "../../st/cutscene_avatar.h"
#include "../../st/cutscene_unk6.h"
#include "../../st/set_cutscene_end.h"
#include "../../st/cutscene.h"
#include "../../st/cutscene_run.h"
#include "../../st/cutscene_scale_avatar.h"
extern s32 D_us_8019AE70;
extern s32 skip_cutscene;
extern s32 D_us_8019AF2C;
extern s32 D_8003CB04;
extern u8 D_us_801805D4[];
@ -30,9 +31,9 @@ extern u16 D_us_801805DC[];
extern u16 D_us_801805E4[];
extern u16 D_us_801805E8[];
extern s16 D_us_801805F0[];
extern const char D_us_80181424[];
void EntityMariaCutscene(Entity* self) {
extern u8 OVL_EXPORT(cutscene_data)[];
void OVL_EXPORT(EntityCutscene)(Entity* self) {
const int PrimCount = 72;
Primitive* prim;
#if defined(VERSION_PC) || defined(VERSION_PSP)
@ -48,13 +49,13 @@ void EntityMariaCutscene(Entity* self) {
s16 y;
u16 nextChar;
s32 nextChar2;
s32 bit_shifty;
u_long ptr;
if (self->step != 0) {
if ((D_us_8019AF2C != 0) && (D_us_8019AE70 == 0) &&
if (self->step) {
if ((D_us_8019AF2C != 0) && !skip_cutscene &&
((D_8003CB04 & 0x80) || (g_IsTimeAttackUnlocked != 0)) &&
(g_pads[0].tapped & PAD_START)) {
D_us_8019AE70 = 1;
skip_cutscene = 1;
g_api.FreePrimitives(self->primIndex);
self->flags ^= FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
@ -67,7 +68,7 @@ void EntityMariaCutscene(Entity* self) {
self->step = 1;
self->step_s = 0;
}
if ((self->step) && (g_Dialogue.unk3C != 0)) {
if (self->step && (g_Dialogue.unk3C != 0)) {
CutsceneRun();
}
}
@ -77,11 +78,11 @@ void EntityMariaCutscene(Entity* self) {
DestroyEntity(self);
return;
}
if (SetCutsceneScript(D_us_80181424) & 0xFF) {
if (SetCutsceneScript(OVL_EXPORT(cutscene_data)) & 0xFF) {
self->flags |= FLAG_HAS_PRIMS | FLAG_UNK_2000;
g_CutsceneFlags = 0;
D_us_8019AF2C = 0;
D_us_8019AE70 = 0;
skip_cutscene = 0;
D_8003C704 = 1;
self->primIndex = g_Dialogue.primIndex[2];
self->step++;
@ -91,19 +92,19 @@ void EntityMariaCutscene(Entity* self) {
case 1:
// this is a huge While-loop! Don't miss it!
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_us_8019AE70 == 0)) {
if ((g_Dialogue.nextCharTimer != 0) && !skip_cutscene) {
g_Dialogue.nextCharTimer--;
return;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
switch (nextChar) {
case 0:
self->step = 7;
return;
case 1:
if (D_us_8019AE70 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
@ -131,18 +132,18 @@ void EntityMariaCutscene(Entity* self) {
return;
case 2:
g_Dialogue.unk17 = *g_Dialogue.nextCharDialogue++;
g_Dialogue.unk17 = *g_Dialogue.scriptCur++;
continue;
case 3:
g_Dialogue.nextCharTimer = *g_Dialogue.nextCharDialogue++;
if (D_us_8019AE70 != 0) {
g_Dialogue.nextCharTimer = *g_Dialogue.scriptCur++;
if (skip_cutscene) {
continue;
}
return;
case 4:
if (D_us_8019AE70 != 0) {
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -153,14 +154,14 @@ void EntityMariaCutscene(Entity* self) {
return;
case 5:
if (D_us_8019AE70 != 0) {
g_Dialogue.nextCharDialogue += 2;
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
// fake reuse of i?
i = *g_Dialogue.nextCharDialogue++;
nextChar2 = *g_Dialogue.nextCharDialogue++;
i = *g_Dialogue.scriptCur++;
nextChar2 = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
x = D_us_801805D4[nextChar2 & 1];
y = D_us_801805D8[nextChar2 & 1];
@ -190,7 +191,7 @@ void EntityMariaCutscene(Entity* self) {
return;
case 6:
if (D_us_8019AE70 != 0) {
if (skip_cutscene) {
continue;
}
for (prim = g_Dialogue.prim[0], i = 0; i < 5; i++) {
@ -204,13 +205,13 @@ void EntityMariaCutscene(Entity* self) {
return;
case 7:
if (D_us_8019AE70 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
g_Dialogue.startX = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startY = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startX = *g_Dialogue.scriptCur++;
g_Dialogue.startY = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = g_Dialogue.startY;
@ -224,7 +225,7 @@ void EntityMariaCutscene(Entity* self) {
return;
case 8:
if (D_us_8019AE70 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
@ -232,97 +233,95 @@ void EntityMariaCutscene(Entity* self) {
return;
case 9:
if (D_us_8019AE70 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 10:
if (D_us_8019AE70 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != false) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 11:
if (D_us_8019AE70 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != true) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 12:
bit_shifty = *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
CutsceneUnk6(bit_shifty);
ptr = *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
SetCutsceneEnd(ptr);
continue;
case 13:
continue;
case 14:
bit_shifty = *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
ptr = *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
// This needs help. Casting the const to short is good.
bit_shifty += (u16)0x100000;
g_Dialogue.nextCharDialogue += *(u16*)bit_shifty << 2;
ptr += (u16)0x100000;
g_Dialogue.scriptCur += *(u16*)ptr << 2;
bit_shifty = *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue =
(const char*)bit_shifty + 0x100000;
ptr = *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (const char*)ptr + 0x100000;
continue;
case 15:
bit_shifty = *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue =
(const char*)bit_shifty + 0x100000;
ptr = *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (const char*)ptr + 0x100000;
continue;
case 16:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
g_Dialogue.nextCharDialogue--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
g_Dialogue.scriptCur--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue);
*g_Dialogue.nextCharDialogue++;
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur);
*g_Dialogue.scriptCur++;
continue;
case 17:
g_CutsceneFlags |= 1 << *g_Dialogue.nextCharDialogue++;
g_CutsceneFlags |= 1 << *g_Dialogue.scriptCur++;
continue;
case 18:
@ -330,54 +329,54 @@ void EntityMariaCutscene(Entity* self) {
continue;
case 19:
if (D_us_8019AE70 != 0) {
g_Dialogue.nextCharDialogue += 5;
if (skip_cutscene) {
g_Dialogue.scriptCur += 5;
} else {
bit_shifty = *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= *g_Dialogue.nextCharDialogue++;
bit_shifty += 0x100000;
nextChar2 = g_Dialogue.nextCharDialogue++[0];
LoadTPage((u_long*)bit_shifty, 1, 0,
D_us_801805E4[nextChar2], 0x100, 0x30, 0x48);
ptr = *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= *g_Dialogue.scriptCur++;
ptr += 0x100000;
nextChar2 = g_Dialogue.scriptCur++[0];
LoadTPage((u_long*)ptr, 1, 0, D_us_801805E4[nextChar2],
0x100, 0x30, 0x48);
}
continue;
case 20:
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 21:
g_CutsceneFlags = 0;
D_us_8019AE70 = 0;
skip_cutscene = 0;
D_us_8019AF2C = 0;
continue;
case 22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue++);
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur++);
continue;
case 23:
return;
case 24:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
*g_Dialogue.nextCharDialogue--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
*g_Dialogue.scriptCur--;
return;
}
*g_Dialogue.nextCharDialogue++;
*g_Dialogue.scriptCur++;
continue;
}
if (D_us_8019AE70) {
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "mar.h"
#include <cutscene.h>
u8 OVL_EXPORT(cutscene_data)[] = {
#include "cutscene_data.h"
};

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include <stage.h>
#include "mar.h"
void EntityBreakable(Entity* self);
void EntityExplosion(Entity* self);
@ -30,7 +30,7 @@ void EntityStatueGear(Entity* self);
void EntityStoneDoor(Entity* self);
void func_us_80199114(Entity* self);
void EntityDummy(Entity* self);
void EntityMariaCutscene(Entity* self);
void OVL_EXPORT(EntityCutscene)(Entity* self);
void func_us_8018C90C(Entity* self);
void func_us_8018CA94(Entity* self);
@ -49,7 +49,7 @@ PfnEntityUpdate PfnEntityUpdates[] = {
EntityClockHands, EntityBirdcageDoor,
EntityStatue, EntityStatueGear,
EntityStoneDoor, func_us_80199114,
EntityDummy, EntityMariaCutscene,
EntityDummy, OVL_EXPORT(EntityCutscene),
func_us_8018C90C, func_us_8018CA94,
};

View File

@ -4,8 +4,9 @@
#include <stdlib.h>
#include <string.h>
#include "stage_loader.h"
#include "cen.h"
extern Overlay CEN_Overlay;
extern Overlay OVL_EXPORT(Overlay);
u16 D_8018658C[0x80];
u16 D_8018678C[0x80];
@ -28,5 +29,5 @@ void InitStageCEN(Overlay* o) {
LOAD_ASSET("assets/st/cen/D_80181658.bin", D_80181658);
LOAD_ASSET("assets/st/cen/D_8018199C.bin", D_8018199C);
LOAD_ASSET("assets/st/cen/D_80185830.bin", D_80185830);
memcpy(o, &CEN_Overlay, sizeof(Overlay));
memcpy(o, &OVL_EXPORT(Overlay), sizeof(Overlay));
}

View File

@ -87,7 +87,7 @@ s32 D_801BC340;
s32 g_StreamDiscStatus;
s32 D_801BC348;
s32 D_801BC34C;
s32 D_801BC350;
s32 skip_cutscene;
Dialogue g_Dialogue;
u32 D_801BC398[16];
s32 g_MemCardSelectorX;
@ -135,5 +135,5 @@ void func_801B9C80(void) {
// reset D_8003C728 to signal the end of video playback
D_8003C728 = 0;
}
void func_801B69F8(Entity* e) { NOT_IMPLEMENTED; }
void SEL_EntityCutscene(Entity* e) { NOT_IMPLEMENTED; }
void func_801B79D4(Entity* e) { NOT_IMPLEMENTED; }

2
src/st/.gitignore vendored
View File

@ -6,4 +6,4 @@ layers.h
sprite_banks.h
tilemap_*.h
tiledef_*.h
cutscene_*.h
cutscene_data.h

View File

@ -73,6 +73,5 @@ extern u16 g_ESoulStealOrbAngles[];
extern s16 g_ESoulStealOrbSprt[];
extern u8 g_ESoulStealOrbAnim[];
extern ObjInit D_8018125C[];
extern u8 g_CutsceneScript[];
#endif

View File

@ -3,7 +3,7 @@
#include <cutscene.h>
static u8 __unused[0xC00];
static s32 D_8019D374;
static s32 skip_cutscene;
static Dialogue g_Dialogue;
static u32 __unused0[26];
u32 g_CutsceneFlags;
@ -58,9 +58,9 @@ static const char _pad[4] = "";
#include "../cutscene_avatar.h"
#include "../cutscene_unk6.h"
#include "../set_cutscene_end.h"
void CutsceneRun(void) {
static void CutsceneRun(void) {
Entity* entity;
u16 startTimer;
@ -72,41 +72,41 @@ void CutsceneRun(void) {
}
while (true) {
// Start the dialogue script only if the start timer has passed
startTimer = *g_Dialogue.unk40++ << 8;
startTimer |= *g_Dialogue.unk40++;
startTimer = *g_Dialogue.scriptEnd++ << 8;
startTimer |= *g_Dialogue.scriptEnd++;
if (g_Dialogue.timer < startTimer) {
// Re-evaluate the condition at the next frame
g_Dialogue.unk40 -= 2;
g_Dialogue.scriptEnd -= 2;
return;
}
switch (*g_Dialogue.unk40++) {
switch (*g_Dialogue.scriptEnd++) {
case 0:
entity =
&g_Entities[*g_Dialogue.unk40++ & 0xFF] + STAGE_ENTITY_START;
entity = &g_Entities[*g_Dialogue.scriptEnd++ & 0xFF] +
STAGE_ENTITY_START;
DestroyEntity(entity);
entity->entityId = *g_Dialogue.unk40++;
entity->entityId = *g_Dialogue.scriptEnd++;
entity->pfnUpdate = PfnEntityUpdates[entity->entityId - 1];
entity->posX.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posX.i.hi |= *g_Dialogue.unk40++;
entity->posY.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posY.i.hi |= *g_Dialogue.unk40++;
entity->posX.i.hi = *g_Dialogue.scriptEnd++ * 0x10;
entity->posX.i.hi |= *g_Dialogue.scriptEnd++;
entity->posY.i.hi = *g_Dialogue.scriptEnd++ * 0x10;
entity->posY.i.hi |= *g_Dialogue.scriptEnd++;
entity->posX.i.hi -= g_Tilemap.scrollX.i.hi;
entity->posY.i.hi -= g_Tilemap.scrollY.i.hi;
break;
case 1:
entity =
&g_Entities[*g_Dialogue.unk40++ & 0xFF] + STAGE_ENTITY_START;
entity = &g_Entities[*g_Dialogue.scriptEnd++ & 0xFF] +
STAGE_ENTITY_START;
DestroyEntity(entity);
break;
case 2:
if (!((g_CutsceneFlags >> *g_Dialogue.unk40) & 1)) {
g_Dialogue.unk40--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptEnd) & 1)) {
g_Dialogue.scriptEnd--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.unk40++);
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptEnd++);
break;
case 3:
g_CutsceneFlags |= 1 << *g_Dialogue.unk40++;
g_CutsceneFlags |= 1 << *g_Dialogue.scriptEnd++;
break;
}
}
@ -114,7 +114,8 @@ void CutsceneRun(void) {
#include "../cutscene_scale_avatar.h"
void EntityHolyGlassesCutscene(Entity* self) {
extern u8 OVL_EXPORT(cutscene_data)[];
void OVL_EXPORT(EntityCutscene)(Entity* self) {
RECT rect;
Primitive* prim;
s32 primIndex;
@ -124,14 +125,13 @@ void EntityHolyGlassesCutscene(Entity* self) {
s16 vCoord;
u16 nextChar;
s32 nextChar2;
u32 bit_shifty;
u_long ptr;
if (self->step != 0) {
if ((D_8019D428 != 0) && (D_8019D374 == 0) &&
((g_Settings.D_8003CB04 & 0x800) ||
(g_IsTimeAttackUnlocked != 0)) &&
if (self->step) {
if (D_8019D428 && !skip_cutscene &&
((g_Settings.D_8003CB04 & 0x800) || g_IsTimeAttackUnlocked) &&
(g_pads[0].tapped & PAD_START)) {
D_8019D374 = 1;
skip_cutscene = 1;
g_api.FreePrimitives(self->primIndex);
self->flags ^= FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
@ -144,7 +144,7 @@ void EntityHolyGlassesCutscene(Entity* self) {
self->step = 1;
self->step_s = 0;
}
if ((self->step) && (g_Dialogue.unk3C != 0)) {
if (self->step && (g_Dialogue.unk3C != 0)) {
CutsceneRun();
}
}
@ -154,12 +154,12 @@ void EntityHolyGlassesCutscene(Entity* self) {
DestroyEntity(self);
return;
}
if (SetCutsceneScript(g_CutsceneScript)) {
if (SetCutsceneScript(OVL_EXPORT(cutscene_data))) {
self->flags |= FLAG_HAS_PRIMS | FLAG_UNK_2000;
D_8003C704 = 1;
g_CutsceneFlags = 0;
D_8019D428 = 0;
D_8019D374 = 0;
skip_cutscene = 0;
self->primIndex = g_Dialogue.primIndex[2];
self->step++;
}
@ -167,17 +167,17 @@ void EntityHolyGlassesCutscene(Entity* self) {
case 1:
// this is a huge While-loop! Don't miss it!
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_8019D374 == 0)) {
if ((g_Dialogue.nextCharTimer != 0) && !skip_cutscene) {
g_Dialogue.nextCharTimer--;
return;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
switch (nextChar) {
case CSOP_END_CUTSCENE:
self->step = 7;
return;
case CSOP_LINE_BREAK:
if (D_8019D374 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
@ -204,16 +204,16 @@ void EntityHolyGlassesCutscene(Entity* self) {
self->step++;
return;
case CSOP_SET_SPEED:
g_Dialogue.unk17 = *g_Dialogue.nextCharDialogue++;
g_Dialogue.unk17 = *g_Dialogue.scriptCur++;
continue;
case CSOP_SET_WAIT:
g_Dialogue.nextCharTimer = *g_Dialogue.nextCharDialogue++;
if (D_8019D374 != 0) {
g_Dialogue.nextCharTimer = *g_Dialogue.scriptCur++;
if (skip_cutscene) {
continue;
}
return;
case 4:
if (D_8019D374 != 0) {
case CSOP_SCRIPT_UNKNOWN_4:
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -223,13 +223,13 @@ void EntityHolyGlassesCutscene(Entity* self) {
}
return;
case CSOP_SET_PORTRAIT:
if (D_8019D374 != 0) {
g_Dialogue.nextCharDialogue += 2;
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
// fake reuse of i?
i = *g_Dialogue.nextCharDialogue++;
nextChar2 = *g_Dialogue.nextCharDialogue++;
i = *g_Dialogue.scriptCur++;
nextChar2 = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
uCoord = g_HeartDropArray[nextChar2 & 1];
vCoord = D_801805DC[nextChar2 & 1];
@ -258,7 +258,7 @@ void EntityHolyGlassesCutscene(Entity* self) {
self->step = 3;
return;
case CSOP_NEXT_DIALOG:
if (D_8019D374 != 0) {
if (skip_cutscene) {
continue;
}
for (prim = g_Dialogue.prim[0], i = 0; i < 5; i++) {
@ -271,13 +271,13 @@ void EntityHolyGlassesCutscene(Entity* self) {
self->step = 4;
return;
case CSOP_SET_POS:
if (D_8019D374 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
g_Dialogue.startX = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startY = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startX = *g_Dialogue.scriptCur++;
g_Dialogue.startY = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = g_Dialogue.startY;
@ -290,139 +290,139 @@ void EntityHolyGlassesCutscene(Entity* self) {
self->step_s = 0;
return;
case CSOP_CLOSE_DIALOG:
if (D_8019D374 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
self->step = 6;
return;
case CSOP_PLAY_SOUND:
if (D_8019D374 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case CSOP_WAIT_FOR_SOUND:
if (D_8019D374 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != false) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case CSOP_UNK_11:
if (D_8019D374 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != true) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 12:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
CutsceneUnk6((u8*)bit_shifty);
case CSOP_SET_END:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
SetCutsceneEnd((u8*)ptr);
continue;
case 13:
case CSOP_SCRIPT_UNKNOWN_13:
continue;
case 14:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += (u16)0x100000;
g_Dialogue.nextCharDialogue += *(u16*)bit_shifty << 2;
case CSOP_SCRIPT_UNKNOWN_14:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += (u16)0x100000;
g_Dialogue.scriptCur += *(u16*)ptr << 2;
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 15:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
case CSOP_SCRIPT_UNKNOWN_15:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case CSOP_WAIT_FOR_FLAG:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
g_Dialogue.nextCharDialogue--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
g_Dialogue.scriptCur--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue);
*g_Dialogue.nextCharDialogue++;
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur);
*g_Dialogue.scriptCur++;
continue;
case 17:
g_CutsceneFlags |= 1 << *g_Dialogue.nextCharDialogue++;
case CSOP_SET_FLAG:
g_CutsceneFlags |= 1 << *g_Dialogue.scriptCur++;
continue;
case 18:
case CSOP_SCRIPT_UNKNOWN_18:
g_Dialogue.unk3C = 0;
continue;
case CSOP_LOAD_PORTRAIT:
if (D_8019D374 != 0) {
g_Dialogue.nextCharDialogue += 5;
if (skip_cutscene) {
g_Dialogue.scriptCur += 5;
} else {
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += 0x100000;
nextChar2 = g_Dialogue.nextCharDialogue++[0];
LoadTPage((u_long*)bit_shifty, 1, 0, D_801805E8[nextChar2],
0x100, 0x30, 0x48);
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += 0x100000;
nextChar2 = g_Dialogue.scriptCur++[0];
LoadTPage((u_long*)ptr, 1, 0, D_801805E8[nextChar2], 0x100,
48, 72);
}
continue;
case CSOP_SCRIPT_UNKNOWN_20:
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 21:
case CSOP_SCRIPT_UNKNOWN_21:
g_CutsceneFlags = 0;
D_8019D374 = 0;
skip_cutscene = 0;
D_8019D428 = 0;
continue;
case 22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue++);
case CSOP_SCRIPT_UNKNOWN_22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur++);
continue;
case 23:
case CSOP_SCRIPT_UNKNOWN_23:
return;
case 24:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
*g_Dialogue.nextCharDialogue--;
case CSOP_SCRIPT_UNKNOWN_24:
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
*g_Dialogue.scriptCur--;
return;
}
*g_Dialogue.nextCharDialogue++;
*g_Dialogue.scriptCur++;
continue;
default:
if (D_8019D374 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "cen.h"
#include <cutscene.h>
u8 g_CutsceneScript[] = {
u8 OVL_EXPORT(cutscene_data)[] = {
#include "cutscene_data.h"
};

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "game.h"
#include "stage.h"
#define OVL_EXPORT(x) CEN_##x
void EntityBreakable(Entity*);
void EntityExplosion(Entity*);
@ -22,7 +23,7 @@ void EntityUnkId12(Entity*);
void EntityUnkId13(Entity*);
void EntityUnkId14(Entity*);
void EntityUnkId15(Entity*);
void EntityHolyGlassesCutscene(Entity*);
void OVL_EXPORT(EntityCutscene)(Entity*);
void EntityPlatform(Entity*);
void EntityMaria(Entity*);
void EntityRoomDarkness(Entity*);
@ -41,7 +42,7 @@ PfnEntityUpdate PfnEntityUpdates[] = {
EntityDummy, EntityDummy,
EntityBackgroundBlock, EntityUnkId12,
EntityUnkId13, EntityUnkId14,
EntityUnkId15, EntityHolyGlassesCutscene,
EntityUnkId15, OVL_EXPORT(EntityCutscene),
EntityPlatform, EntityMaria,
EntityRoomDarkness, EntityElevatorStationary,
EntityUnkId1B, EntityMovingElevator,

View File

@ -16,39 +16,39 @@ void CutsceneRun(void) {
}
while (true) {
// Start the dialogue script only if the start timer has passed
startTimer = *g_Dialogue.unk40++ << 8;
startTimer |= *g_Dialogue.unk40++;
startTimer = *g_Dialogue.scriptEnd++ << 8;
startTimer |= *g_Dialogue.scriptEnd++;
if (g_Dialogue.timer < startTimer) {
// Re-evaluate the condition at the next frame
g_Dialogue.unk40 -= 2;
g_Dialogue.scriptEnd -= 2;
return;
}
switch (*g_Dialogue.unk40++) {
switch (*g_Dialogue.scriptEnd++) {
case 0:
entity =
&g_Entities[*g_Dialogue.unk40++ & 0xFF] + STAGE_ENTITY_START;
entity = &g_Entities[*g_Dialogue.scriptEnd++ & 0xFF] +
STAGE_ENTITY_START;
DestroyEntity(entity);
entity->entityId = *g_Dialogue.unk40++;
entity->entityId = *g_Dialogue.scriptEnd++;
entity->pfnUpdate = PfnEntityUpdates[entity->entityId - 1];
entity->posX.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posX.i.hi |= *g_Dialogue.unk40++;
entity->posY.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posY.i.hi |= *g_Dialogue.unk40++;
entity->posX.i.hi = *g_Dialogue.scriptEnd++ * 0x10;
entity->posX.i.hi |= *g_Dialogue.scriptEnd++;
entity->posY.i.hi = *g_Dialogue.scriptEnd++ * 0x10;
entity->posY.i.hi |= *g_Dialogue.scriptEnd++;
break;
case 1:
entity =
&g_Entities[*g_Dialogue.unk40++ & 0xFF] + STAGE_ENTITY_START;
entity = &g_Entities[*g_Dialogue.scriptEnd++ & 0xFF] +
STAGE_ENTITY_START;
DestroyEntity(entity);
break;
case 2:
if (!((g_CutsceneFlags >> *g_Dialogue.unk40) & 1)) {
g_Dialogue.unk40--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptEnd) & 1)) {
g_Dialogue.scriptEnd--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.unk40++);
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptEnd++);
break;
case 3:
g_CutsceneFlags |= 1 << *g_Dialogue.unk40++;
g_CutsceneFlags |= 1 << *g_Dialogue.scriptEnd++;
break;
}
}

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
void CutsceneUnk1(void) {
static void CutsceneUnk1(void) {
g_Dialogue.nextLineX = 2;
g_Dialogue.nextCharX = 2;
g_Dialogue.nextCharY = 0;

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
void CutsceneUnk3(s16 arg0) {
static void CutsceneUnk3(s16 arg0) {
RECT rect;
rect.y = (arg0 * 12) + 384;

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
void CutsceneUnk4(void) {
static void CutsceneUnk4(void) {
Primitive* prim;
CutsceneUnk3(g_Dialogue.nextCharY);

View File

@ -19,7 +19,7 @@ void EntityCSMoveAlucard(Entity* self) {
s16 posX;
FntPrint("step %x\n", self->step);
if ((D_801A3ED4 != 0) && (self->step < 8)) {
if (skip_cutscene && (self->step < 8)) {
SetStep(8);
}

View File

@ -2,7 +2,7 @@
#include <common.h>
STATIC_PAD_BSS(3072);
u32 D_801A3ED4;
u32 skip_cutscene;
u32 g_Dialogue;
u16 D_801A3EDC;
u16 D_801A3EDE;

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "dre.h"
#include <cutscene.h>
#include "../cutscene_unk1.h"
@ -16,9 +17,9 @@ static const char* g_ActorNames[] = {_S("Alucard"), _S("Lisa"), _S("Succubus")};
#include "../cutscene_avatar.h"
#include "../cutscene_unk6.h"
#include "../set_cutscene_end.h"
void CutsceneRun(void) {
static void CutsceneRun(void) {
Entity* entity;
u16 startTimer;
@ -30,40 +31,40 @@ void CutsceneRun(void) {
}
while (true) {
// Start the dialogue script only if the start timer has passed
startTimer = *g_Dialogue.unk40++ << 8;
startTimer |= *g_Dialogue.unk40++;
startTimer = *g_Dialogue.scriptEnd++ << 8;
startTimer |= *g_Dialogue.scriptEnd++;
if (g_Dialogue.timer < startTimer) {
// Re-evaluate the condition at the next frame
g_Dialogue.unk40 -= 2;
g_Dialogue.scriptEnd -= 2;
return;
}
switch (*g_Dialogue.unk40++) {
switch (*g_Dialogue.scriptEnd++) {
case 0:
entity =
&g_Entities[*g_Dialogue.unk40++ & 0xFF] + STAGE_ENTITY_START;
entity = &g_Entities[*g_Dialogue.scriptEnd++ & 0xFF] +
STAGE_ENTITY_START;
DestroyEntity(entity);
entity->entityId = *g_Dialogue.unk40++;
entity->entityId = *g_Dialogue.scriptEnd++;
entity->pfnUpdate = PfnEntityUpdates[entity->entityId - 1];
entity->posX.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posX.i.hi |= *g_Dialogue.unk40++;
entity->posY.i.hi = *g_Dialogue.unk40++ * 0x10;
entity->posY.i.hi |= *g_Dialogue.unk40++;
entity->posX.i.hi = *g_Dialogue.scriptEnd++ * 0x10;
entity->posX.i.hi |= *g_Dialogue.scriptEnd++;
entity->posY.i.hi = *g_Dialogue.scriptEnd++ * 0x10;
entity->posY.i.hi |= *g_Dialogue.scriptEnd++;
break;
case 1:
entity =
&g_Entities[*g_Dialogue.unk40++ & 0xFF] + STAGE_ENTITY_START;
entity = &g_Entities[*g_Dialogue.scriptEnd++ & 0xFF] +
STAGE_ENTITY_START;
DestroyEntity(entity);
break;
case 2:
if (!((g_CutsceneFlags >> *g_Dialogue.unk40) & 1)) {
g_Dialogue.unk40 -= 3;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptEnd) & 1)) {
g_Dialogue.scriptEnd -= 3;
g_Dialogue.timer--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.unk40++);
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptEnd++);
break;
case 3:
g_CutsceneFlags |= 1 << *g_Dialogue.unk40++;
g_CutsceneFlags |= 1 << *g_Dialogue.scriptEnd++;
break;
}
}
@ -71,7 +72,7 @@ void CutsceneRun(void) {
void func_80194F14(Entity* self) {
if (g_pads[0].tapped == PAD_START) {
D_801A3ED4 = 1;
skip_cutscene = 1;
g_api.FreePrimitives(self->primIndex);
self->flags ^= FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
@ -91,7 +92,8 @@ void func_80194F14(Entity* self) {
// dialogue with mother opens as alucard walks right ID 20
// Same pattern as a lot of other cutscenes, main differences
// are related to the self->params if-else statements.
void EntitySuccubusCutscene(Entity* self) {
extern u8 OVL_EXPORT(cutscene_data)[];
void OVL_EXPORT(EntityCutscene)(Entity* self) {
RECT rect;
Primitive* prim;
s32 primIndex;
@ -101,11 +103,11 @@ void EntitySuccubusCutscene(Entity* self) {
s16 vCoord;
u16 nextChar;
s32 nextChar2;
s32 bit_shifty;
u_long ptr;
if (self->step != 0) {
if ((D_801A3F88 != 0) && (D_801A3ED4 == 0)) {
if (g_IsTimeAttackUnlocked != 0) {
if ((D_801A3F88 != 0) && !skip_cutscene) {
if (g_IsTimeAttackUnlocked) {
func_80194F14(self);
} else {
if (self->params) {
@ -132,15 +134,15 @@ void EntitySuccubusCutscene(Entity* self) {
}
}
if (self->params) {
bit_shifty = SetCutsceneScript(D_80181B65);
ptr = SetCutsceneScript(OVL_EXPORT(cutscene_data) + 0x49D);
} else {
bit_shifty = SetCutsceneScript(D_801816C8);
ptr = SetCutsceneScript(OVL_EXPORT(cutscene_data));
}
if (bit_shifty) {
if (ptr) {
self->flags |= FLAG_HAS_PRIMS | FLAG_UNK_2000;
g_CutsceneFlags = 0;
D_801A3F88 = 0;
D_801A3ED4 = 0;
skip_cutscene = 0;
D_8003C704 = 1;
self->primIndex = g_Dialogue.primIndex[2];
self->step++;
@ -148,23 +150,23 @@ void EntitySuccubusCutscene(Entity* self) {
if ((g_CastleFlags[SUCC_CS_DONE] != 0) ||
(g_PlayableCharacter != PLAYER_ALUCARD) ||
(g_DemoMode != Demo_None)) {
D_801A3ED4 = 1;
skip_cutscene = 1;
}
break;
case 1:
// this is a huge While-loop! Don't miss it!
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_801A3ED4 == 0)) {
if ((g_Dialogue.nextCharTimer != 0) && !skip_cutscene) {
g_Dialogue.nextCharTimer--;
return;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
switch (nextChar) {
case 0:
case CSOP_END_CUTSCENE:
self->step = 7;
return;
case 1:
if (D_801A3ED4 != 0) {
case CSOP_LINE_BREAK:
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
@ -190,17 +192,17 @@ void EntitySuccubusCutscene(Entity* self) {
self->step_s = 0;
self->step++;
return;
case 2:
g_Dialogue.unk17 = *g_Dialogue.nextCharDialogue++;
case CSOP_SET_SPEED:
g_Dialogue.unk17 = *g_Dialogue.scriptCur++;
continue;
case 3:
g_Dialogue.nextCharTimer = *g_Dialogue.nextCharDialogue++;
if (D_801A3ED4 != 0) {
case CSOP_SET_WAIT:
g_Dialogue.nextCharTimer = *g_Dialogue.scriptCur++;
if (skip_cutscene) {
continue;
}
return;
case 4:
if (D_801A3ED4 != 0) {
case CSOP_SCRIPT_UNKNOWN_4:
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -209,14 +211,14 @@ void EntitySuccubusCutscene(Entity* self) {
prim = prim->next;
}
return;
case 5:
if (D_801A3ED4 != 0) {
g_Dialogue.nextCharDialogue += 2;
case CSOP_SET_PORTRAIT:
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
// fake reuse of i?
i = *g_Dialogue.nextCharDialogue++;
nextChar2 = *g_Dialogue.nextCharDialogue++;
i = *g_Dialogue.scriptCur++;
nextChar2 = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
uCoord = D_8018088C[nextChar2 & 1];
vCoord = D_80180890[nextChar2 & 1];
@ -244,8 +246,8 @@ void EntitySuccubusCutscene(Entity* self) {
g_Dialogue.portraitAnimTimer = 6;
self->step = 3;
return;
case 6:
if (D_801A3ED4 != 0) {
case CSOP_NEXT_DIALOG:
if (skip_cutscene) {
continue;
}
for (prim = g_Dialogue.prim[0], i = 0; i < 5; i++) {
@ -257,14 +259,14 @@ void EntitySuccubusCutscene(Entity* self) {
g_Dialogue.portraitAnimTimer = 6;
self->step = 4;
return;
case 7:
if (D_801A3ED4 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
case CSOP_SET_POS:
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
g_Dialogue.startX = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startY = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startX = *g_Dialogue.scriptCur++;
g_Dialogue.startY = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = g_Dialogue.startY;
@ -276,143 +278,140 @@ void EntitySuccubusCutscene(Entity* self) {
self->step = 5;
self->step_s = 0;
return;
case 8:
if (D_801A3ED4 != 0) {
case CSOP_CLOSE_DIALOG:
if (skip_cutscene) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
self->step = 6;
return;
case 9:
if (D_801A3ED4 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
case CSOP_PLAY_SOUND:
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 10:
if (D_801A3ED4 != 0) {
case CSOP_WAIT_FOR_SOUND:
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != false) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 11:
if (D_801A3ED4 != 0) {
case CSOP_UNK_11:
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != true) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 12:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
CutsceneUnk6((u8*)bit_shifty);
case CSOP_SET_END:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
SetCutsceneEnd((u8*)ptr);
continue;
case 13:
case CSOP_SCRIPT_UNKNOWN_13:
continue;
case 14:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += 0x100000;
g_Dialogue.nextCharDialogue += *(u8*)bit_shifty << 2;
case CSOP_SCRIPT_UNKNOWN_14:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += 0x100000;
g_Dialogue.scriptCur += *(u8*)ptr << 2;
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 15:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
case CSOP_SCRIPT_UNKNOWN_15:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 16:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
g_Dialogue.nextCharDialogue--;
case CSOP_WAIT_FOR_FLAG:
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
g_Dialogue.scriptCur--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue);
*g_Dialogue.nextCharDialogue++;
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur);
*g_Dialogue.scriptCur++;
continue;
case 17:
g_CutsceneFlags |= 1 << *g_Dialogue.nextCharDialogue++;
case CSOP_SET_FLAG:
g_CutsceneFlags |= 1 << *g_Dialogue.scriptCur++;
continue;
case 18:
case CSOP_SCRIPT_UNKNOWN_18:
g_Dialogue.unk3C = 0;
continue;
case 19:
if (D_801A3ED4 != 0) {
g_Dialogue.nextCharDialogue += 5;
case CSOP_LOAD_PORTRAIT:
if (skip_cutscene) {
g_Dialogue.scriptCur += 5;
} else {
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += 0x100000;
nextChar2 = g_Dialogue.nextCharDialogue++[0];
LoadTPage((u32*)bit_shifty, 1, 0, D_8018089C[nextChar2],
0x100, 0x30, 0x48);
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += 0x100000;
nextChar2 = g_Dialogue.scriptCur++[0];
LoadTPage((u32*)ptr, 1, 0, D_8018089C[nextChar2], 0x100,
0x30, 0x48);
}
continue;
case 20:
nextChar = *g_Dialogue.nextCharDialogue++;
case CSOP_SCRIPT_UNKNOWN_20:
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 21:
case CSOP_SCRIPT_UNKNOWN_21:
g_CutsceneFlags = 0;
D_801A3ED4 = 0;
skip_cutscene = 0;
D_801A3F88 = 0;
continue;
case 22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue++);
case CSOP_SCRIPT_UNKNOWN_22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur++);
continue;
case 23:
case CSOP_SCRIPT_UNKNOWN_23:
return;
case 24:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
*g_Dialogue.nextCharDialogue--;
case CSOP_SCRIPT_UNKNOWN_24:
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
*g_Dialogue.scriptCur--;
return;
}
*g_Dialogue.nextCharDialogue++;
*g_Dialogue.scriptCur++;
continue;
default:
if (D_801A3ED4 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "dre.h"
#include <cutscene.h>
u8 OVL_EXPORT(cutscene_data)[] = {
#include "cutscene_data.h"
};

View File

@ -131,7 +131,7 @@ extern u8 g_ESoulStealOrbAnim[];
// *** EntitySoulStealOrb properties END ***
extern s32 D_801A3ED4;
extern s32 skip_cutscene;
extern Primitive* D_801A3EF0[];
extern s32 D_801A3F08;
extern s32 D_801A3F0C;
@ -145,9 +145,7 @@ extern u16 D_80180894[];
extern u16 D_8018089C[];
extern u16 D_801808A0[];
extern s16 D_801808A8[];
extern const char D_80181B65[];
extern const char D_801816C8[];
extern s32 D_801A3ED4;
extern s32 skip_cutscene;
extern u32 g_CutsceneFlags;
extern s32 D_801A3F88;

View File

@ -126,7 +126,7 @@ void EntitySuccubus(Entity* self) {
break;
case SUCCUBUS_CS_2: // Disguised as Lisa
if (D_801A3ED4 != 0) {
if (skip_cutscene) {
SetSubStep(4);
}
switch (self->step_s) {
@ -169,7 +169,7 @@ void EntitySuccubus(Entity* self) {
// Sets Succubus in position
case SUCCUBUS_CS_3:
if ((D_801A3ED4 == 0) || (self->step_s == 0)) {
if (!skip_cutscene || (self->step_s == 0)) {
switch (self->step_s) {
case 0:
self->facingLeft = 0;

View File

@ -3,7 +3,7 @@
STATIC_PAD_BSS(3072);
u32 D_801D7D20;
u32 skip_cutscene;
u32 g_Dialogue;
u16 D_801D7D28;
u16 D_801D7D2A;

View File

@ -1,8 +1,9 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "no3.h"
#include <cutscene.h>
// similar but not an exact duplicate
void CutsceneUnk1(void) {
static void CutsceneUnk1(void) {
g_Dialogue.nextLineX = 0x182; // Note that these two lines are "= 2"
g_Dialogue.nextCharX = 0x182; // for all other cutscenes (so far)!
g_Dialogue.nextCharY = 0;
@ -14,7 +15,7 @@ void CutsceneUnk1(void) {
#include "../set_cutscene_script.h"
void CutsceneUnk3(s16 yOffset) {
static void CutsceneUnk3(s16 yOffset) {
RECT rect;
rect.x = 384;
@ -24,7 +25,7 @@ void CutsceneUnk3(s16 yOffset) {
ClearImage(&rect, 0, 0, 0);
}
void CutsceneUnk4(void) {
static void CutsceneUnk4(void) {
Primitive* prim;
CutsceneUnk3(g_Dialogue.nextCharY);
@ -44,13 +45,13 @@ void CutsceneUnk4(void) {
#include "../cutscene_avatar.h"
#include "../cutscene_unk6.h"
#include "../set_cutscene_end.h"
#include "../cutscene.h"
#include "../cutscene_run.h"
void func_801BECCC(Entity* self) {
static void func_801BECCC(Entity* self) {
if (g_pads[0].tapped == PAD_START) {
D_801D7D20 = 1;
skip_cutscene = 1;
g_api.FreePrimitives(self->primIndex);
self->flags ^= FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
@ -67,7 +68,8 @@ void func_801BECCC(Entity* self) {
#include "../cutscene_scale_avatar.h"
void EntityDeathCutscene(Entity* self) {
extern u8 OVL_EXPORT(cutscene_data)[];
void OVL_EXPORT(EntityCutscene)(Entity* self) {
RECT rect;
Primitive* prim;
s32 primIndex;
@ -77,10 +79,10 @@ void EntityDeathCutscene(Entity* self) {
s16 vCoord;
u16 nextChar;
s32 nextChar2;
s32 bit_shifty;
u_long ptr;
if (self->step != 0) {
if ((D_801D7DD4 != 0) && (D_801D7D20 == 0) &&
if (self->step) {
if ((D_801D7DD4 != 0) && !skip_cutscene &&
((g_IsTimeAttackUnlocked) || (g_Settings.D_8003CB04 & 4))) {
func_801BECCC(self);
}
@ -98,11 +100,11 @@ void EntityDeathCutscene(Entity* self) {
return;
}
g_Entities[192].params = 0x100;
if (SetCutsceneScript(D_80184CE0)) {
if (SetCutsceneScript(OVL_EXPORT(cutscene_data))) {
self->flags |= FLAG_HAS_PRIMS | FLAG_UNK_2000;
g_CutsceneFlags = 0;
D_801D7DD4 = 0;
D_801D7D20 = 0;
skip_cutscene = 0;
D_8003C704 = 1;
self->primIndex = g_Dialogue.primIndex[2];
self->step++;
@ -111,17 +113,17 @@ void EntityDeathCutscene(Entity* self) {
case 1:
// this is a huge While-loop! Don't miss it!
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_801D7D20 == 0)) {
if ((g_Dialogue.nextCharTimer != 0) && !skip_cutscene) {
g_Dialogue.nextCharTimer--;
return;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
switch (nextChar) {
case 0:
case CSOP_END_CUTSCENE:
self->step = 7;
return;
case 1:
if (D_801D7D20 != 0) {
case CSOP_LINE_BREAK:
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
@ -147,17 +149,17 @@ void EntityDeathCutscene(Entity* self) {
self->step_s = 0;
self->step++;
return;
case 2:
g_Dialogue.unk17 = *g_Dialogue.nextCharDialogue++;
case CSOP_SET_SPEED:
g_Dialogue.unk17 = *g_Dialogue.scriptCur++;
continue;
case 3:
g_Dialogue.nextCharTimer = *g_Dialogue.nextCharDialogue++;
if (D_801D7D20 != 0) {
case CSOP_SET_WAIT:
g_Dialogue.nextCharTimer = *g_Dialogue.scriptCur++;
if (skip_cutscene) {
continue;
}
return;
case 4:
if (D_801D7D20 != 0) {
case CSOP_SCRIPT_UNKNOWN_4:
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -166,14 +168,14 @@ void EntityDeathCutscene(Entity* self) {
prim = prim->next;
}
return;
case 5:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue += 2;
case CSOP_SET_PORTRAIT:
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
// fake reuse of i?
i = *g_Dialogue.nextCharDialogue++;
nextChar2 = *g_Dialogue.nextCharDialogue++;
i = *g_Dialogue.scriptCur++;
nextChar2 = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
uCoord = D_80181A28[nextChar2 & 1];
vCoord = D_80181A2C[nextChar2 & 1];
@ -201,8 +203,8 @@ void EntityDeathCutscene(Entity* self) {
g_Dialogue.portraitAnimTimer = 6;
self->step = 3;
return;
case 6:
if (D_801D7D20 != 0) {
case CSOP_NEXT_DIALOG:
if (skip_cutscene) {
continue;
}
for (prim = g_Dialogue.prim[0], i = 0; i < 5; i++) {
@ -214,14 +216,14 @@ void EntityDeathCutscene(Entity* self) {
g_Dialogue.portraitAnimTimer = 6;
self->step = 4;
return;
case 7:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
case CSOP_SET_POS:
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
g_Dialogue.startX = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startY = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startX = *g_Dialogue.scriptCur++;
g_Dialogue.startY = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = g_Dialogue.startY;
@ -233,143 +235,140 @@ void EntityDeathCutscene(Entity* self) {
self->step = 5;
self->step_s = 0;
return;
case 8:
if (D_801D7D20 != 0) {
case CSOP_CLOSE_DIALOG:
if (skip_cutscene) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
self->step = 6;
return;
case 9:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
case CSOP_PLAY_SOUND:
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 10:
if (D_801D7D20 != 0) {
case CSOP_WAIT_FOR_SOUND:
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != false) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 11:
if (D_801D7D20 != 0) {
case CSOP_UNK_11:
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != true) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 12:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
CutsceneUnk6((u8*)bit_shifty);
case CSOP_SET_END:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
SetCutsceneEnd((u8*)ptr);
continue;
case 13:
case CSOP_SCRIPT_UNKNOWN_13:
continue;
case 14:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += (u16)0x100000;
g_Dialogue.nextCharDialogue += *(u16*)bit_shifty << 2;
case CSOP_SCRIPT_UNKNOWN_14:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += (u16)0x100000;
g_Dialogue.scriptCur += *(u16*)ptr << 2;
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 15:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
case CSOP_SCRIPT_UNKNOWN_15:
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 16:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
g_Dialogue.nextCharDialogue--;
case CSOP_WAIT_FOR_FLAG:
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
g_Dialogue.scriptCur--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue);
*g_Dialogue.nextCharDialogue++;
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur);
*g_Dialogue.scriptCur++;
continue;
case 17:
g_CutsceneFlags |= 1 << *g_Dialogue.nextCharDialogue++;
case CSOP_SET_FLAG:
g_CutsceneFlags |= 1 << *g_Dialogue.scriptCur++;
continue;
case 18:
case CSOP_SCRIPT_UNKNOWN_18:
g_Dialogue.unk3C = 0;
continue;
case 19:
if (D_801D7D20 != 0) {
g_Dialogue.nextCharDialogue += 5;
case CSOP_LOAD_PORTRAIT:
if (skip_cutscene) {
g_Dialogue.scriptCur += 5;
} else {
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += 0x100000;
nextChar2 = g_Dialogue.nextCharDialogue++[0];
LoadTPage((u32*)bit_shifty, 1, 0, D_80181A34[nextChar2],
0x100, 0x30, 0x48);
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += 0x100000;
nextChar2 = g_Dialogue.scriptCur++[0];
LoadTPage((u32*)ptr, 1, 0, D_80181A34[nextChar2], 0x100,
0x30, 0x48);
}
continue;
case 20:
nextChar = *g_Dialogue.nextCharDialogue++;
case CSOP_SCRIPT_UNKNOWN_20:
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 21:
case CSOP_SCRIPT_UNKNOWN_21:
g_CutsceneFlags = 0;
D_801D7D20 = 0;
skip_cutscene = 0;
D_801D7DD4 = 0;
continue;
case 22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue++);
case CSOP_SCRIPT_UNKNOWN_22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur++);
continue;
case 23:
case CSOP_SCRIPT_UNKNOWN_23:
return;
case 24:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
*g_Dialogue.nextCharDialogue--;
case CSOP_SCRIPT_UNKNOWN_24:
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
*g_Dialogue.scriptCur--;
return;
}
*g_Dialogue.nextCharDialogue++;
*g_Dialogue.scriptCur++;
continue;
default:
if (D_801D7D20 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "no3.h"
#include <cutscene.h>
u8 OVL_EXPORT(cutscene_data)[] = {
#include "cutscene_data.h"
};

View File

@ -236,7 +236,7 @@ extern u8 D_80183C84[];
extern u8 D_80183C98[];
extern s32 D_80183CAC;
extern s32 D_80183CBC;
extern s32 D_801D7D20;
extern s32 skip_cutscene;
extern s32 D_801D7D54;
extern s32 D_801D7D58;
extern u32 g_CutsceneFlags;
@ -288,7 +288,7 @@ extern u8 g_ESoulStealOrbAnim[];
extern SVECTOR D_801B73E0;
// For EntityDeathCutscene
// For NO3_EntityCutscene
extern u8 D_80181A28[];
extern u8 D_80181A2C[];
extern u16 D_80181A30[];
@ -296,11 +296,10 @@ extern u16 D_80181A34[];
extern u16 D_80181A38[];
extern s16 D_80181A3C[];
extern const char D_801813F0[];
extern s32 D_801D7D20;
extern s32 skip_cutscene;
extern u32 g_CutsceneFlags;
extern s32 D_801D7DD4;
extern u16 D_801D7D60;
extern const char D_80184CE0[];
extern s32 D_801D7D5C;
extern u16 D_80180B3C[];
extern s16 D_80181808[];

View File

@ -2,7 +2,7 @@
#include <common.h>
STATIC_PAD_BSS(3072);
u32 D_801CB684;
u32 skip_cutscene;
u32 g_Dialogue;
u16 D_801CB68C;
u16 D_801CB68E;

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "nz0.h"
// This file consists of EntityMariaCutscene, and all the functions it calls.
// This file consists of NZ0_EntityCutscene, and all the functions it calls.
// No function in NZ0 calls anything in there, nor does anything in here call
// any NZ0 functions, besides the ones in this file.
@ -15,14 +15,15 @@
#include "../cutscene_avatar.h"
#include "../cutscene_unk6.h"
#include "../set_cutscene_end.h"
#include "../cutscene.h"
#include "../cutscene_run.h"
#include "../cutscene_scale_avatar.h"
// cutscene where alucard and maria discuss castle changing
void EntityMariaCutscene(Entity* self) {
extern u8 OVL_EXPORT(cutscene_data)[];
void OVL_EXPORT(EntityCutscene)(Entity* self) {
RECT rect;
Primitive* prim;
s32 primIndex;
@ -32,14 +33,14 @@ void EntityMariaCutscene(Entity* self) {
s16 vCoord;
u16 nextChar;
s32 nextChar2;
s32 bit_shifty;
u_long ptr;
if (self->step != 0) {
if ((D_801CB73C != 0) && (D_801CB684 == 0) &&
if ((D_801CB73C != 0) && !skip_cutscene &&
((g_Settings.D_8003CB04 & 0x100) ||
(g_IsTimeAttackUnlocked != 0)) &&
(g_pads[0].tapped == PAD_START)) {
D_801CB684 = 1;
skip_cutscene = 1;
g_api.FreePrimitives(self->primIndex);
self->flags ^= FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
@ -52,7 +53,7 @@ void EntityMariaCutscene(Entity* self) {
self->step = 1;
self->step_s = 0;
}
if ((self->step) && (g_Dialogue.unk3C != 0)) {
if (self->step && (g_Dialogue.unk3C != 0)) {
CutsceneRun();
}
}
@ -63,11 +64,11 @@ void EntityMariaCutscene(Entity* self) {
DestroyEntity(self);
return;
}
if (SetCutsceneScript(D_80183B0C)) {
if (SetCutsceneScript(OVL_EXPORT(cutscene_data))) {
self->flags |= FLAG_HAS_PRIMS | FLAG_UNK_2000;
g_CutsceneFlags = 0;
D_801CB73C = 0;
D_801CB684 = 0;
skip_cutscene = 0;
D_8003C704 = 1;
self->primIndex = g_Dialogue.primIndex[2];
self->step++;
@ -76,17 +77,17 @@ void EntityMariaCutscene(Entity* self) {
case 1:
// this is a huge While-loop! Don't miss it!
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_801CB684 == 0)) {
if ((g_Dialogue.nextCharTimer != 0) && !skip_cutscene) {
g_Dialogue.nextCharTimer--;
return;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
switch (nextChar) {
case 0:
self->step = 7;
return;
case 1:
if (D_801CB684 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
@ -113,16 +114,16 @@ void EntityMariaCutscene(Entity* self) {
self->step++;
return;
case 2:
g_Dialogue.unk17 = *g_Dialogue.nextCharDialogue++;
g_Dialogue.unk17 = *g_Dialogue.scriptCur++;
continue;
case 3:
g_Dialogue.nextCharTimer = *g_Dialogue.nextCharDialogue++;
if (D_801CB684 != 0) {
g_Dialogue.nextCharTimer = *g_Dialogue.scriptCur++;
if (skip_cutscene) {
continue;
}
return;
case 4:
if (D_801CB684 != 0) {
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -132,13 +133,13 @@ void EntityMariaCutscene(Entity* self) {
}
return;
case 5:
if (D_801CB684 != 0) {
g_Dialogue.nextCharDialogue += 2;
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
// fake reuse of i?
i = *g_Dialogue.nextCharDialogue++;
nextChar2 = *g_Dialogue.nextCharDialogue++;
i = *g_Dialogue.scriptCur++;
nextChar2 = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
uCoord = D_801813C8[nextChar2 & 1];
vCoord = D_801813CC[nextChar2 & 1];
@ -167,7 +168,7 @@ void EntityMariaCutscene(Entity* self) {
self->step = 3;
return;
case 6:
if (D_801CB684 != 0) {
if (skip_cutscene) {
continue;
}
for (prim = g_Dialogue.prim[0], i = 0; i < 5; i++) {
@ -180,13 +181,13 @@ void EntityMariaCutscene(Entity* self) {
self->step = 4;
return;
case 7:
if (D_801CB684 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
g_Dialogue.startX = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startY = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startX = *g_Dialogue.scriptCur++;
g_Dialogue.startY = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = g_Dialogue.startY;
@ -200,141 +201,141 @@ void EntityMariaCutscene(Entity* self) {
return;
case 8:
if (D_801CB684 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
self->step = 6;
return;
case 9:
if (D_801CB684 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 10:
if (D_801CB684 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != false) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 11:
if (D_801CB684 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != true) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 12:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
CutsceneUnk6((u8*)bit_shifty);
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
SetCutsceneEnd((u8*)ptr);
continue;
case 13:
continue;
case 14:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += (u16)0x100000;
g_Dialogue.nextCharDialogue += *(u16*)bit_shifty << 2;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += (u16)0x100000;
g_Dialogue.scriptCur += *(u16*)ptr << 2;
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 15:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 16:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
g_Dialogue.nextCharDialogue--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
g_Dialogue.scriptCur--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue);
*g_Dialogue.nextCharDialogue++;
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur);
*g_Dialogue.scriptCur++;
continue;
case 17:
g_CutsceneFlags |= 1 << *g_Dialogue.nextCharDialogue++;
g_CutsceneFlags |= 1 << *g_Dialogue.scriptCur++;
continue;
case 18:
g_Dialogue.unk3C = 0;
continue;
case 19:
if (D_801CB684 != 0) {
g_Dialogue.nextCharDialogue += 5;
if (skip_cutscene) {
g_Dialogue.scriptCur += 5;
} else {
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty += 0x100000;
nextChar2 = g_Dialogue.nextCharDialogue++[0];
LoadTPage((u32*)bit_shifty, 1, 0, D_801813D4[nextChar2],
0x100, 0x30, 0x48);
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr += 0x100000;
nextChar2 = g_Dialogue.scriptCur++[0];
LoadTPage((u32*)ptr, 1, 0, D_801813D4[nextChar2], 0x100,
0x30, 0x48);
}
continue;
case 20:
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 21:
g_CutsceneFlags = 0;
D_801CB684 = 0;
skip_cutscene = 0;
D_801CB73C = 0;
continue;
case 22:
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue++);
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur++);
continue;
case 23:
return;
case 24:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
*g_Dialogue.nextCharDialogue--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
*g_Dialogue.scriptCur--;
return;
}
*g_Dialogue.nextCharDialogue++;
*g_Dialogue.scriptCur++;
continue;
default:
if (D_801CB684 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "nz0.h"
#include <cutscene.h>
u8 OVL_EXPORT(cutscene_data)[] = {
#include "cutscene_data.h"
};

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include <stage.h>
#include "nz0.h"
void EntityBreakableNZ0(Entity*);
void EntityExplosion(Entity*);
@ -75,7 +75,7 @@ void EntityElevator(Entity*);
void func_801B6DE4(Entity*);
void EntityLifeUpSpawn(Entity*);
void EntityMagicallySealedDoor(Entity*);
void EntityMariaCutscene(Entity*);
void NZ0_EntityCutscene(Entity*);
void EntityMaria(Entity*);
void func_801B8E0C(Entity*);
@ -154,110 +154,44 @@ PfnEntityUpdate PfnEntityUpdates[] = {
func_801B6DE4,
EntityLifeUpSpawn,
EntityMagicallySealedDoor,
EntityMariaCutscene,
OVL_EXPORT(EntityCutscene),
EntityMaria,
func_801B8E0C,
};
u16 g_eBreakableInit[] = {
0x0003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
u16 g_InitializeData0[] = {
0x0003, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000,
};
u16 g_InitializeEntityData0[] = {
0x0003, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000,
};
u16 g_MariaInit[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000,
};
u16 g_EInitGeneric[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0005, 0x0000,
};
u16 g_InitDataEnt13[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000,
};
u16 D_80180C10[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000,
};
u16 g_eInitGeneric2[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0003, 0x0000,
};
u16 g_eDamageDisplayInit[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0003, 0x0000,
};
u16 D_80180C34[] = {
0x8001, 0x0000, 0x0000, 0x0000, 0x0003, 0x0000,
};
u16 D_80180C40[] = {
0x8002, 0x0000, 0x004C, 0x0200, 0x0046, 0x0000,
};
u16 g_BoneScimitarInit[] = {
0x8003, 0x0001, 0x004D, 0x0204, 0x0069, 0x0000,
};
u16 g_ScimitarPartsInit[] = {
0x8003, 0x0000, 0x004D, 0x0204, 0x0002, 0x0000,
};
u16 g_EAxeKnightInit[] = {
0x8004, 0x0001, 0x0048, 0x0207, 0x00F6, 0x0000,
};
u16 D_80180C70[] = {
0x8004, 0x002F, 0x0048, 0x0205, 0x018F, 0x0000,
};
u16 g_EBloodyZombieInit[] = {
0x8005, 0x0001, 0x004A, 0x0209, 0x000D, 0x0000,
};
u16 D_80180C88[] = {
0x8006, 0x0001, 0x004E, 0x020C, 0x004B, 0x0000,
};
u16 D_80180C94[] = {
0x8006, 0x0000, 0x004E, 0x020C, 0x0002, 0x0000,
};
u16 D_80180CA0[] = {
0x8006, 0x0015, 0x004E, 0x020C, 0x004C, 0x0000,
};
u16 D_80180CAC[] = {
0x8007, 0x0034, 0x0050, 0x020D, 0x0051, 0x0000,
};
u16 D_80180CB8[] = {
0x8007, 0x0040, 0x0050, 0x020D, 0x0052, 0x0000,
};
u16 D_80180CC4[] = {
0x8008, 0x0000, 0x004B, 0x0219, 0x0005, 0x0000,
};
u16 D_80180CD0[] = {
0x8009, 0x0000, 0x004F, 0x0211, 0x0005, 0x0000,
};
u16 D_80180CDC[] = {
0x800A, 0x0000, 0x0053, 0x0215, 0x0005, 0x0000,
};
u16 D_80180CE8[] = {
0x800C, 0x0000, 0x004C, 0x021D, 0x0005, 0x0000,
};
u16 D_80180CF4[] = {
0x800C, 0x0000, 0x004C, 0x021D, 0x0002, 0x0000,
};
u16 D_80180D00[] = {
0x8001, 0x0008, 0x0000, 0x0000, 0x0005, 0x0000,
};
u16 D_80180D0C[] = {
0x800D, 0x0000, 0x0048, 0x0227, 0x00F3, 0x0000,
};
u16 D_80180D18[] = {
0x800D, 0x0000, 0x0048, 0x0227, 0x00F4, 0x0000,
};
u16 D_80180D24[] = {
0x800D, 0x0000, 0x0048, 0x0227, 0x00F5, 0x0000,
};
u16 D_80180D30[] = {
0x800E, 0x0000, 0x004C, 0x022A, 0x00FE, 0x0000,
};
u16 D_80180D3C[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x00FF, 0x0000,
};
u16 D_80180D48[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000,
};
u16 g_eBreakableInit[] = {0x0003, 0x0000, 0x0000, 0x0000, 0x0000};
u16 g_InitializeData0[] = {0x0003, 0x0000, 0x0000, 0x0000, 0x0001};
u16 g_InitializeEntityData0[] = {0x0003, 0x0000, 0x0000, 0x0000, 0x0002};
u16 g_MariaInit[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0004};
u16 g_EInitGeneric[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0005};
u16 g_InitDataEnt13[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0002};
u16 D_80180C10[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0001};
u16 g_eInitGeneric2[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0003};
u16 g_eDamageDisplayInit[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0003};
u16 D_80180C34[] = {0x8001, 0x0000, 0x0000, 0x0000, 0x0003};
u16 D_80180C40[] = {0x8002, 0x0000, 0x004C, 0x0200, 0x0046};
u16 g_BoneScimitarInit[] = {0x8003, 0x0001, 0x004D, 0x0204, 0x0069};
u16 g_ScimitarPartsInit[] = {0x8003, 0x0000, 0x004D, 0x0204, 0x0002};
u16 g_EAxeKnightInit[] = {0x8004, 0x0001, 0x0048, 0x0207, 0x00F6};
u16 D_80180C70[] = {0x8004, 0x002F, 0x0048, 0x0205, 0x018F};
u16 g_EBloodyZombieInit[] = {0x8005, 0x0001, 0x004A, 0x0209, 0x000D};
u16 D_80180C88[] = {0x8006, 0x0001, 0x004E, 0x020C, 0x004B};
u16 D_80180C94[] = {0x8006, 0x0000, 0x004E, 0x020C, 0x0002};
u16 D_80180CA0[] = {0x8006, 0x0015, 0x004E, 0x020C, 0x004C};
u16 D_80180CAC[] = {0x8007, 0x0034, 0x0050, 0x020D, 0x0051};
u16 D_80180CB8[] = {0x8007, 0x0040, 0x0050, 0x020D, 0x0052};
u16 D_80180CC4[] = {0x8008, 0x0000, 0x004B, 0x0219, 0x0005};
u16 D_80180CD0[] = {0x8009, 0x0000, 0x004F, 0x0211, 0x0005};
u16 D_80180CDC[] = {0x800A, 0x0000, 0x0053, 0x0215, 0x0005};
u16 D_80180CE8[] = {0x800C, 0x0000, 0x004C, 0x021D, 0x0005};
u16 D_80180CF4[] = {0x800C, 0x0000, 0x004C, 0x021D, 0x0002};
u16 D_80180D00[] = {0x8001, 0x0008, 0x0000, 0x0000, 0x0005};
u16 D_80180D0C[] = {0x800D, 0x0000, 0x0048, 0x0227, 0x00F3};
u16 D_80180D18[] = {0x800D, 0x0000, 0x0048, 0x0227, 0x00F4};
u16 D_80180D24[] = {0x800D, 0x0000, 0x0048, 0x0227, 0x00F5};
u16 D_80180D30[] = {0x800E, 0x0000, 0x004C, 0x022A, 0x00FE};
u16 D_80180D3C[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x00FF};
u16 D_80180D48[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0100};
static u32 D_80180D54[] = {0x00000B10};
static u32 D_80180D58[] = {0x0D080C08, 0x0F080E08, 0x00001008};

View File

@ -80,7 +80,7 @@ void EntityGaibon(Entity* self) {
s32 yVar;
s32 xVar;
if ((self->step) && (!self->ext.GS_Props.nearDeath) &&
if (self->step && (!self->ext.GS_Props.nearDeath) &&
self->hitPoints < g_api.enemyDefs[0xFE].hitPoints / 2) {
self->ext.GS_Props.grabedAscending = 0;
self->ext.GS_Props.nearDeath = 1;

View File

@ -53,7 +53,7 @@ void EntityMaria(Entity* self) {
Primitive* prim;
s32 i;
if ((D_801CB684 != 0) && (self->step < 12)) {
if (skip_cutscene && (self->step < 12)) {
if (!(g_CutsceneFlags & 1)) {
g_CutsceneFlags |= 1;
}

View File

@ -120,7 +120,7 @@ extern s32 D_801826AC;
extern u16 D_80180C88[];
extern u16 D_80180CAC[];
extern u16 D_80180CC4[];
extern s16 D_80180CE8[];
extern u16 D_80180CE8[];
extern u16 D_80180D00[];
// *** EntitySlogra properties START ***
@ -227,7 +227,7 @@ extern s16 D_801824DC[];
extern u8 D_801824E2[];
extern u16 D_801824E4[];
extern u8 D_80181F30[];
extern u8 D_80180CF4[];
extern u16 D_80180CF4[];
extern s32 D_80182600[];
extern u16 g_InitializeData0[];
extern u16 D_80180BC8[];
@ -323,8 +323,8 @@ extern SVECTOR D_80182838;
extern SVECTOR D_80182840;
extern SVECTOR D_80182848;
// For EntityMariaCutscene
extern s32 D_801CB684;
// For NZ0_EntityCutscene
extern s32 skip_cutscene;
extern s32 D_801CB73C;
extern u8 D_801813C8[];
extern u8 D_801813CC[];
@ -332,7 +332,6 @@ extern u16 D_801813D0[];
extern u16 D_801813D4[];
extern u16 D_801813D8[];
extern s16 D_801813DC[];
extern const char D_80183B0C[];
extern u32 g_CutsceneFlags;
// EntityMaria, mostly animations
@ -358,7 +357,7 @@ extern u16 g_eBlueDoorTiles[2][8];
extern char D_80182710[];
// for func_801B0AA4
extern u16 D_80180C10;
extern u16 D_80180C10[];
extern u8 D_80180DBC[];
extern u8 D_80180DC0[];
extern u16 D_80180DC4[];

View File

@ -383,7 +383,7 @@ void func_801B60D4(void) {
case 3:
ent4 = &g_Entities[4];
func_801B5A7C();
func_801B69F8(ent4);
SEL_EntityCutscene(ent4);
func_801B4C68();
func_801B519C();
func_801B4D78();

View File

@ -53,7 +53,7 @@ u32 D_801BC340;
u32 g_StreamDiskIsReady;
u32 D_801BC348;
u32 D_801BC34C;
u32 D_801BC350;
u32 skip_cutscene;
u32 g_Dialogue;
u16 D_801BC358;
u16 D_801BC35A;

View File

@ -3,7 +3,7 @@
#include "../cutscene_unk1.h"
u8 SetCutsceneScript(const char* textDialogue) {
u8 SetCutsceneScript(u8* script) {
Primitive* prim;
s16 firstPrimIndex;
@ -13,7 +13,7 @@ u8 SetCutsceneScript(const char* textDialogue) {
g_Dialogue.primIndex[2] = 0;
return false;
}
g_Dialogue.nextCharDialogue = textDialogue;
g_Dialogue.scriptCur = script;
g_Dialogue.unk3C = 0;
g_Dialogue.primIndex[1] = -1;
g_Dialogue.primIndex[0] = -1;
@ -114,7 +114,7 @@ const char* g_ActorNames[] = {
#include "../cutscene_avatar.h"
#include "../cutscene_unk6.h"
#include "../set_cutscene_end.h"
// n.b.! unlike the stage version of this function, a `self`
// parameter is used to store the substep instead of
@ -148,8 +148,7 @@ static void ScaleCutsceneAvatar(u8 ySteps, Entity* self) {
g_Dialogue.portraitAnimTimer++;
}
// Strong resemblence to NZ0 EntityMariaCutscene and others
void func_801B69F8(Entity* entity) {
void SEL_EntityCutscene(Entity* entity) {
Primitive* prim;
s32 i;
s32 j;
@ -161,7 +160,7 @@ void func_801B69F8(Entity* entity) {
switch (entity->step) {
case 0:
if (SetCutsceneScript(D_8018B304)) {
D_801BC350 = D_801D6B00 = D_801BC3E8 = 0;
skip_cutscene = D_801D6B00 = D_801BC3E8 = 0;
D_8003C704 = 1;
entity->flags |= FLAG_HAS_PRIMS | FLAG_UNK_2000;
entity->primIndex = g_Dialogue.primIndex[2];
@ -170,17 +169,17 @@ void func_801B69F8(Entity* entity) {
break;
case 1:
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_801BC350 == 0)) {
if ((g_Dialogue.nextCharTimer != 0) && !skip_cutscene) {
--g_Dialogue.nextCharTimer;
return;
}
nextChar = g_Dialogue.nextCharDialogue++[0];
nextChar = g_Dialogue.scriptCur++[0];
switch (nextChar) {
case 0:
entity->step = 7;
return;
case 1:
if (D_801BC350 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
@ -202,16 +201,16 @@ void func_801B69F8(Entity* entity) {
++entity->step;
return;
case 2:
g_Dialogue.unk17 = g_Dialogue.nextCharDialogue++[0];
g_Dialogue.unk17 = g_Dialogue.scriptCur++[0];
continue;
case 3:
g_Dialogue.nextCharTimer = g_Dialogue.nextCharDialogue++[0];
if (D_801BC350 != 0) {
g_Dialogue.nextCharTimer = g_Dialogue.scriptCur++[0];
if (skip_cutscene) {
continue;
}
return;
case 4: {
if (D_801BC350 != 0) {
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -224,12 +223,12 @@ void func_801B69F8(Entity* entity) {
case 5: {
s16 temp_a0;
s16 temp_a1;
if (D_801BC350 != 0) {
g_Dialogue.nextCharDialogue += 2;
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
j = g_Dialogue.nextCharDialogue++[0];
nextChar2 = g_Dialogue.nextCharDialogue++[0];
j = g_Dialogue.scriptCur++[0];
nextChar2 = g_Dialogue.scriptCur++[0];
prim = g_Dialogue.prim[5];
temp_a0 = D_80180824[nextChar2 & 1];
temp_a1 = D_80180828[nextChar2 & 1];
@ -259,7 +258,7 @@ void func_801B69F8(Entity* entity) {
return;
}
case 6:
if (D_801BC350 != 0) {
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -273,12 +272,12 @@ void func_801B69F8(Entity* entity) {
entity->step = 4;
return;
case 7:
if (D_801BC350 != 0) {
g_Dialogue.nextCharDialogue += 2;
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
g_Dialogue.startX = g_Dialogue.nextCharDialogue++[0];
g_Dialogue.startY = g_Dialogue.nextCharDialogue++[0];
g_Dialogue.startX = g_Dialogue.scriptCur++[0];
g_Dialogue.startY = g_Dialogue.scriptCur++[0];
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = prim->y2 = prim->y3 = g_Dialogue.startY;
@ -292,128 +291,125 @@ void func_801B69F8(Entity* entity) {
entity->step_s = 0;
return;
case 8:
if (D_801BC350 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
entity->step = 6;
return;
case 9:
if (D_801BC350 != 0) {
g_Dialogue.nextCharDialogue += 2;
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
nextChar = g_Dialogue.nextCharDialogue++[0];
g_api.PlaySfx(
g_Dialogue.nextCharDialogue++[0] | (nextChar << 4));
nextChar = g_Dialogue.scriptCur++[0];
g_api.PlaySfx(g_Dialogue.scriptCur++[0] | (nextChar << 4));
continue;
case 10:
if (D_801BC350 != 0 || g_api.func_80131F68() != false) {
if (skip_cutscene != 0 || g_api.func_80131F68() != false) {
continue;
}
--g_Dialogue.nextCharDialogue;
--g_Dialogue.scriptCur;
return;
case 11:
if (D_801BC350 != 0 || g_api.func_80131F68() != true) {
if (skip_cutscene != 0 || g_api.func_80131F68() != true) {
continue;
}
--g_Dialogue.nextCharDialogue;
--g_Dialogue.scriptCur;
return;
case 12:
i = g_Dialogue.nextCharDialogue++[0];
i = g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
CutsceneUnk6(i);
i |= g_Dialogue.scriptCur++[0];
SetCutsceneEnd(i);
continue;
case 13:
continue;
case 14:
i = g_Dialogue.nextCharDialogue++[0];
i = g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
g_Dialogue.nextCharDialogue +=
((const char*)i + 0x100000)[0] * 4;
i = g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
g_Dialogue.scriptCur += ((const char*)i + 0x100000)[0] * 4;
i = g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue[0];
g_Dialogue.nextCharDialogue = (const char*)(i + 0x100000);
i |= g_Dialogue.scriptCur[0];
g_Dialogue.scriptCur = (const char*)(i + 0x100000);
continue;
case 15:
i = g_Dialogue.nextCharDialogue++[0];
i = g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue[0];
g_Dialogue.nextCharDialogue = (const char*)(i + 0x100000);
i |= g_Dialogue.scriptCur[0];
g_Dialogue.scriptCur = (const char*)(i + 0x100000);
continue;
case 16:
if (!((D_801BC3E8 >> g_Dialogue.nextCharDialogue[0]) & 1)) {
--g_Dialogue.nextCharDialogue;
if (!((D_801BC3E8 >> g_Dialogue.scriptCur[0]) & 1)) {
--g_Dialogue.scriptCur;
return;
}
D_801BC3E8 &= ~(1 << g_Dialogue.nextCharDialogue[0]);
++g_Dialogue.nextCharDialogue;
D_801BC3E8 &= ~(1 << g_Dialogue.scriptCur[0]);
++g_Dialogue.scriptCur;
continue;
case 17:
D_801BC3E8 |= 1 << g_Dialogue.nextCharDialogue++[0];
D_801BC3E8 |= 1 << g_Dialogue.scriptCur++[0];
continue;
case 18:
g_Dialogue.unk3C = 0;
continue;
case 19:
if (D_801BC350 != 0) {
g_Dialogue.nextCharDialogue += 5;
if (skip_cutscene) {
g_Dialogue.scriptCur += 5;
} else {
i = g_Dialogue.nextCharDialogue++[0];
i = g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i <<= 4;
i |= g_Dialogue.nextCharDialogue++[0];
i |= g_Dialogue.scriptCur++[0];
i += 0x100000;
nextChar2 = g_Dialogue.nextCharDialogue++[0];
nextChar2 = g_Dialogue.scriptCur++[0];
LoadTPage((u_long*)i, 1, 0, D_80180834[nextChar2], 0x100,
0x30, 0x48);
}
continue;
case 20:
nextChar = g_Dialogue.nextCharDialogue++[0];
g_api.PlaySfx(
g_Dialogue.nextCharDialogue++[0] | (nextChar << 4));
nextChar = g_Dialogue.scriptCur++[0];
g_api.PlaySfx(g_Dialogue.scriptCur++[0] | (nextChar << 4));
continue;
case 21:
D_801D6B00 = D_801BC350 = D_801BC3E8 = 0;
D_801D6B00 = skip_cutscene = D_801BC3E8 = 0;
continue;
case 22:
D_801BC3E8 &= ~(1 << g_Dialogue.nextCharDialogue++[0]);
D_801BC3E8 &= ~(1 << g_Dialogue.scriptCur++[0]);
continue;
case 23:
return;
case 24:
if (!((D_801BC3E8 >> g_Dialogue.nextCharDialogue[0]) & 1)) {
--g_Dialogue.nextCharDialogue;
if (!((D_801BC3E8 >> g_Dialogue.scriptCur[0]) & 1)) {
--g_Dialogue.scriptCur;
return;
}
++g_Dialogue.nextCharDialogue;
++g_Dialogue.scriptCur;
continue;
default:
if (D_801BC350 != 0) {
++g_Dialogue.nextCharDialogue;
if (skip_cutscene) {
++g_Dialogue.scriptCur;
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;
@ -520,7 +516,7 @@ u8 func_801B76F0(const char* msg) {
g_Dialogue.primIndex[PRIM] = g_api.AllocPrimitives(PRIM_SPRT, 0x20);
if (g_Dialogue.primIndex[PRIM] != -1) {
g_Dialogue.nextCharX = 0x200;
g_Dialogue.nextCharDialogue = msg;
g_Dialogue.scriptCur = msg;
g_Dialogue.startY = 0x20B;
g_Dialogue.nextLineX = 0;
g_Dialogue.nextCharY = 0;
@ -627,10 +623,10 @@ s32 func_801B79D4(Entity* entity) {
func_801B786C(0);
glyphIndex = 0;
while (1) {
nextChar = g_Dialogue.nextCharDialogue++[0];
nextChar = g_Dialogue.scriptCur++[0];
if (nextChar == 1) {
g_Dialogue.startY =
g_Dialogue.nextCharDialogue++[0] + g_Dialogue.nextCharX;
g_Dialogue.scriptCur++[0] + g_Dialogue.nextCharX;
++g_Dialogue.nextLineX;
break;
}
@ -664,7 +660,7 @@ s32 func_801B79D4(Entity* entity) {
if (g_Dialogue.nextCharY == 0u) {
break;
}
temp_a0_5 = g_Dialogue.nextCharDialogue++;
temp_a0_5 = g_Dialogue.scriptCur++;
nextChar = temp_a0_5[0];
bitDepth = 0;
@ -674,7 +670,7 @@ s32 func_801B79D4(Entity* entity) {
g_Dialogue.unk12 = 0x400;
return 0;
case 1:
g_Dialogue.nextCharDialogue = temp_a0_5 + 2;
g_Dialogue.scriptCur = temp_a0_5 + 2;
g_Dialogue.startY = temp_a0_5[1] + g_Dialogue.nextCharX;
if (++g_Dialogue.nextLineX >= 0x10) {
g_Dialogue.nextLineX = 0;
@ -682,7 +678,7 @@ s32 func_801B79D4(Entity* entity) {
g_Dialogue.nextCharY = 0;
return 0;
case 2:
g_Dialogue.nextCharDialogue = temp_a0_5 + 2;
g_Dialogue.scriptCur = temp_a0_5 + 2;
g_Dialogue.startY = temp_a0_5[1] + g_Dialogue.nextCharX;
if (++g_Dialogue.nextLineX >= 0x10) {
g_Dialogue.nextLineX = 0;
@ -708,7 +704,7 @@ s32 func_801B79D4(Entity* entity) {
g_Dialogue.portraitAnimTimer += 6;
return 0;
case 3:
g_Dialogue.nextCharDialogue = temp_a0_5 + 2;
g_Dialogue.scriptCur = temp_a0_5 + 2;
g_Dialogue.startY = temp_a0_5[1] + g_Dialogue.nextCharX;
if (++g_Dialogue.nextLineX >= 0x10) {
g_Dialogue.nextLineX = 0;
@ -735,7 +731,7 @@ s32 func_801B79D4(Entity* entity) {
return 0;
}
if (nextChar & 0x80) {
nextChar = g_Dialogue.nextCharDialogue++[0] | (nextChar << 8);
nextChar = g_Dialogue.scriptCur++[0] | (nextChar << 8);
glyph = g_api.func_80106A28(nextChar, 0);
} else {
glyph = func_801B78BC(nextChar & 0xFF);

View File

@ -189,7 +189,7 @@ extern s32 D_801BC340;
extern s32 g_StreamDiskIsReady;
extern s32 D_801BC348;
extern s32 D_801BC34C;
extern s32 D_801BC350;
extern s32 skip_cutscene;
extern Dialogue g_Dialogue;
extern u32 D_801BC398[16];
extern s32 g_MemCardSelectorX;

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
void CutsceneUnk6(s32 arg0) {
g_Dialogue.unk40 = arg0 + 0x100000;
static void SetCutsceneEnd(u8* ptr) {
g_Dialogue.scriptEnd = ptr + 0x100000;
g_Dialogue.timer = 0;
g_Dialogue.unk3C = 1;
}

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
u8 SetCutsceneScript(const char* script) {
static u8 SetCutsceneScript(u8* script) {
Primitive* prim;
s16 firstPrimIndex;
@ -15,7 +15,7 @@ u8 SetCutsceneScript(const char* script) {
g_Dialogue.primIndex[2] = 0;
return 0;
}
g_Dialogue.nextCharDialogue = script;
g_Dialogue.scriptCur = script;
g_Dialogue.unk3C = 0;
g_Dialogue.primIndex[1] = -1;
g_Dialogue.primIndex[0] = -1;

View File

@ -22,7 +22,7 @@ void EntityCutscene(Entity* self) {
self->posX.i.hi = player->posX.i.hi;
self->posY.i.hi = player->posY.i.hi - 1;
if ((self->step != 14) && (D_801C24C8 != 0) && (D_801C2580 != 0) &&
if ((self->step != 14) && skip_cutscene && (D_801C2580 != 0) &&
(self->step >= 5)) {
self->step = 15;
self->animSet = ANIMSET_DRA(0);

View File

@ -468,14 +468,14 @@ void PrologueScroll(void) {
}
}
u8 func_801B101C(const char* msg) {
u8 func_801B101C(u8* script) {
Primitive* prim;
s16 i;
D_801C24E4[0] = g_api.AllocPrimitives(PRIM_SPRT, 0x20);
if (D_801C24E4[0] != -1) {
g_Dialogue.nextCharX = 0x200;
g_Dialogue.nextCharDialogue = msg;
g_Dialogue.scriptCur = script;
g_Dialogue.startY = 0x216;
g_Dialogue.nextLineX = 0;
g_Dialogue.nextCharY = 0;

View File

@ -8,7 +8,7 @@ u16 D_801C1BC8;
u16 D_801C1BCA;
u16 D_801C1BCC[1022];
u32 D_801C23C8[64];
u32 D_801C24C8;
u32 skip_cutscene;
u32 g_Dialogue;
u16 D_801C24D0;
u16 D_801C24D2;

View File

@ -1,15 +1,10 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/*
* Overlay: ST0
* Description: Cutscene of Richter talking to Dracula
*/
#include "st0.h"
#include <cutscene.h>
#include "../cutscene_unk1.h"
// not an exact duplicate
u8 SetCutsceneScript(const char* textDialogue) {
static u8 SetCutsceneScript(u8* script) {
Primitive* prim;
s16 firstPrimIndex;
@ -19,7 +14,7 @@ u8 SetCutsceneScript(const char* textDialogue) {
g_Dialogue.primIndex[2] = 0;
return 0;
}
g_Dialogue.nextCharDialogue = textDialogue;
g_Dialogue.scriptCur = script;
g_Dialogue.unk3C = 0;
g_Dialogue.primIndex[1] = -1;
g_Dialogue.primIndex[0] = -1;
@ -77,13 +72,14 @@ const char* g_ActorNames[] = {_S("Richter"), _S("Dracula")};
#include "../cutscene_avatar.h"
#include "../cutscene_unk6.h"
#include "../set_cutscene_end.h"
#include "../cutscene.h"
#include "../cutscene_run.h"
#include "../cutscene_scale_avatar.h"
void EntityDraculaCutscene(Entity* self) {
extern u8 OVL_EXPORT(cutscene_data)[];
void OVL_EXPORT(EntityCutscene)(Entity* self) {
RECT rect;
Primitive* prim;
s32 primIndex;
@ -93,12 +89,12 @@ void EntityDraculaCutscene(Entity* self) {
s16 vCoord;
u16 nextChar;
s32 nextChar2;
s32 bit_shifty;
u_long ptr;
if ((D_801C2580 != 0) && (D_801C24C8 == 0) &&
if ((D_801C2580 != 0) && !skip_cutscene &&
((g_Settings.D_8003CB04 & 1) || (g_IsTimeAttackUnlocked != 0)) &&
(g_pads[0].tapped == PAD_START)) {
D_801C24C8 = 1;
skip_cutscene = 1;
g_api.FreePrimitives(self->primIndex);
self->flags &= ~FLAG_HAS_PRIMS;
if (g_Dialogue.primIndex[1] != -1) {
@ -111,22 +107,22 @@ void EntityDraculaCutscene(Entity* self) {
self->step = 1;
self->step_s = 0;
}
if ((self->step) && (g_Dialogue.unk3C != 0)) {
if (self->step && (g_Dialogue.unk3C != 0)) {
CutsceneRun();
}
switch (self->step) {
case 0:
if (SetCutsceneScript(D_801829D8)) {
if (SetCutsceneScript(OVL_EXPORT(cutscene_data))) {
self->flags |= FLAG_HAS_PRIMS;
g_CutsceneFlags = 0;
D_801C2580 = 0;
D_801C24C8 = 0;
skip_cutscene = 0;
D_8003C704 = 1;
self->primIndex = g_Dialogue.primIndex[2];
self->step += 1;
if (g_DemoMode != Demo_None) {
D_801C24C8 = 1;
skip_cutscene = 1;
D_801C2580 = 1;
g_api.FreePrimitives(self->primIndex);
self->flags &= ~FLAG_HAS_PRIMS;
@ -136,17 +132,17 @@ void EntityDraculaCutscene(Entity* self) {
case 1:
// this is a huge While-loop! Don't miss it!
while (1) {
if ((g_Dialogue.nextCharTimer != 0) && (D_801C24C8 == 0)) {
if ((g_Dialogue.nextCharTimer != 0) && !skip_cutscene) {
g_Dialogue.nextCharTimer--;
return;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
switch (nextChar) {
case 0:
self->step = 7;
return;
case 1:
if (D_801C24C8 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharX = g_Dialogue.nextLineX;
@ -173,16 +169,16 @@ void EntityDraculaCutscene(Entity* self) {
self->step++;
return;
case 2:
g_Dialogue.unk17 = *g_Dialogue.nextCharDialogue++;
g_Dialogue.unk17 = *g_Dialogue.scriptCur++;
continue;
case 3:
g_Dialogue.nextCharTimer = *g_Dialogue.nextCharDialogue++;
if (D_801C24C8 != 0) {
g_Dialogue.nextCharTimer = *g_Dialogue.scriptCur++;
if (skip_cutscene) {
continue;
}
return;
case 4:
if (D_801C24C8 != 0) {
if (skip_cutscene) {
continue;
}
prim = g_Dialogue.prim[0];
@ -192,13 +188,13 @@ void EntityDraculaCutscene(Entity* self) {
}
return;
case 5:
if (D_801C24C8 != 0) {
g_Dialogue.nextCharDialogue += 2;
if (skip_cutscene) {
g_Dialogue.scriptCur += 2;
continue;
}
// fake reuse of i?
i = *g_Dialogue.nextCharDialogue++;
nextChar2 = *g_Dialogue.nextCharDialogue++;
i = *g_Dialogue.scriptCur++;
nextChar2 = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
uCoord = D_80180784[nextChar2 & 1]; // a1
vCoord = D_80180788[nextChar2 & 1]; // a2
@ -227,7 +223,7 @@ void EntityDraculaCutscene(Entity* self) {
self->step = 3;
return;
case 6:
if (D_801C24C8 != 0) {
if (skip_cutscene) {
continue;
}
for (prim = g_Dialogue.prim[0], i = 0; i < 5; i++) {
@ -240,13 +236,13 @@ void EntityDraculaCutscene(Entity* self) {
self->step = 4;
return;
case 7:
if (D_801C24C8 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
g_Dialogue.startX = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startY = *g_Dialogue.nextCharDialogue++;
g_Dialogue.startX = *g_Dialogue.scriptCur++;
g_Dialogue.startY = *g_Dialogue.scriptCur++;
prim = g_Dialogue.prim[5];
prim = prim->next;
prim->y0 = prim->y1 = g_Dialogue.startY;
@ -260,127 +256,127 @@ void EntityDraculaCutscene(Entity* self) {
return;
case 8:
if (D_801C24C8 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.portraitAnimTimer = 0x18;
self->step = 6;
return;
case 9:
if (D_801C24C8 != 0) {
g_Dialogue.nextCharDialogue++;
g_Dialogue.nextCharDialogue++;
if (skip_cutscene) {
g_Dialogue.scriptCur++;
g_Dialogue.scriptCur++;
continue;
}
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
case 10:
if (D_801C24C8 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != false) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 11:
if (D_801C24C8 != 0) {
if (skip_cutscene) {
continue;
}
if (g_api.func_80131F68() != true) {
continue;
}
*g_Dialogue.nextCharDialogue--;
*g_Dialogue.scriptCur--;
return;
case 12:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
CutsceneUnk6((u8*)bit_shifty);
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
SetCutsceneEnd((u8*)ptr);
continue;
case 13:
continue;
case 14:
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
// This needs help. Casting the const to short is good.
bit_shifty += (u16)0x100000;
g_Dialogue.nextCharDialogue += *(u16*)bit_shifty << 2;
ptr += (u16)0x100000;
g_Dialogue.scriptCur += *(u16*)ptr << 2;
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 15: // c64
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++;
bit_shifty <<= 4;
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue;
g_Dialogue.nextCharDialogue = (u8*)bit_shifty + 0x100000;
ptr = (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur++;
ptr <<= 4;
ptr |= (u_long)*g_Dialogue.scriptCur;
g_Dialogue.scriptCur = (u8*)ptr + 0x100000;
continue;
case 16:
if (!((g_CutsceneFlags >> *g_Dialogue.nextCharDialogue) & 1)) {
g_Dialogue.nextCharDialogue--;
if (!((g_CutsceneFlags >> *g_Dialogue.scriptCur) & 1)) {
g_Dialogue.scriptCur--;
return;
}
g_CutsceneFlags &= ~(1 << *g_Dialogue.nextCharDialogue);
*g_Dialogue.nextCharDialogue++;
g_CutsceneFlags &= ~(1 << *g_Dialogue.scriptCur);
*g_Dialogue.scriptCur++;
continue;
case 17:
g_CutsceneFlags |= 1 << *g_Dialogue.nextCharDialogue++;
g_CutsceneFlags |= 1 << *g_Dialogue.scriptCur++;
continue;
case 18:
g_Dialogue.unk3C = 0;
continue;
case 19:
if (D_801C24C8 != 0) {
g_Dialogue.nextCharDialogue += 5;
if (skip_cutscene) {
g_Dialogue.scriptCur += 5;
} else {
bit_shifty = (s32)*g_Dialogue.nextCharDialogue++; // 8e4
bit_shifty <<= 4; // 918
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++; // 91c
bit_shifty <<= 4; // 920
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++; // 924
bit_shifty <<= 4; // 928
bit_shifty |= (s32)*g_Dialogue.nextCharDialogue++; // 92c
bit_shifty += 0x100000; //
nextChar2 = g_Dialogue.nextCharDialogue++[0];
LoadTPage((u32*)bit_shifty, 1, 0, D_80180790[nextChar2],
0x100, 0x30, 0x48);
ptr = (u_long)*g_Dialogue.scriptCur++; // 8e4
ptr <<= 4; // 918
ptr |= (u_long)*g_Dialogue.scriptCur++; // 91c
ptr <<= 4; // 920
ptr |= (u_long)*g_Dialogue.scriptCur++; // 924
ptr <<= 4; // 928
ptr |= (u_long)*g_Dialogue.scriptCur++; // 92c
ptr += 0x100000; //
nextChar2 = g_Dialogue.scriptCur++[0];
LoadTPage((u32*)ptr, 1, 0, D_80180790[nextChar2], 0x100,
0x30, 0x48);
}
continue;
case 20:
nextChar = *g_Dialogue.nextCharDialogue++;
nextChar = *g_Dialogue.scriptCur++;
nextChar <<= 4;
nextChar |= *g_Dialogue.nextCharDialogue++;
nextChar |= *g_Dialogue.scriptCur++;
g_api.PlaySfx(nextChar);
continue;
// Note: Other cutscenes have Case 21-24 here, this one is missing
// it.
default:
if (D_801C24C8 != 0) {
if (skip_cutscene) {
continue;
}
g_Dialogue.nextCharTimer = g_Dialogue.unk17;

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "st0.h"
#include <cutscene.h>
u8 OVL_EXPORT(cutscene_data)[] = {
#include "cutscene_data.h"
};

View File

@ -178,7 +178,7 @@ extern u8 D_801824CC[];
extern s8 D_801A7BDC;
extern Point32 D_801BEB64[];
extern s32 D_801C24C8;
extern s32 skip_cutscene;
extern s16 D_801C24D4;
extern s16 D_801C24D6;
extern s16 D_801C24D8;
@ -199,15 +199,14 @@ extern u8 g_ESoulStealOrbAnim[];
// *** EntitySoulStealOrb properties END ***
// For EntityDraculaCutscene
// For ST0_EntityCutscene
extern u8 D_80180784[];
extern u8 D_80180788[];
extern u16 D_8018078C[];
extern u16 D_80180790[];
extern u16 D_80180794[];
extern s16 D_80180798[];
extern const char D_801829D8[];
extern s32 D_801C24C8;
extern s32 skip_cutscene;
extern s32 D_801C2504;
extern u32 g_CutsceneFlags;
extern s32 D_801C2580;

View File

@ -78,7 +78,7 @@ var extractHandlers = map[string]func(assetEntry) error{
return fmt.Errorf("cutscene cannot be 0 bytes")
}
r := bytes.NewReader(e.data)
script, err := parseCutsceneAsC(r, e.ramBase, e.ramBase.Sum(e.start))
script, err := parseCutsceneAsC(r, e.ramBase, e.ramBase.Sum(e.start), e.end - e.start)
if err != nil {
return err
}

View File

@ -7,7 +7,7 @@ import (
"strings"
)
func readCutscene(r io.ReadSeeker, baseAddr, addr psx.Addr) ([]string, error) {
func readCutscene(r io.ReadSeeker, baseAddr, addr psx.Addr, length int) ([]string, error) {
if err := addr.MoveFile(r, baseAddr); err != nil {
return []string{}, fmt.Errorf("unable to read cutscene: %w", err)
}
@ -15,18 +15,27 @@ func readCutscene(r io.ReadSeeker, baseAddr, addr psx.Addr) ([]string, error) {
read1 := func(r io.ReadSeeker) byte {
b := make([]byte, 1)
_, _ = r.Read(b)
length -= 1
return b[0]
}
read2 := func(r io.ReadSeeker) int {
b := make([]byte, 2)
_, _ = r.Read(b)
length -= 2
return int(b[1]) | (int(b[0]) << 4)
}
read4 := func(r io.ReadSeeker) int {
b := make([]byte, 4)
_, _ = r.Read(b)
length -= 4
return int(b[3]) | (int(b[2]) << 4) | (int(b[1]) << 8) | (int(b[0]) << 12) | 0x80100000
}
script := make([]string, 0)
loop := true
for loop {
for length > 0 {
op := read1(r)
switch op {
case 0:
script = append(script, "END_CUTSCENE()")
script = append(script, "0xFF")
script = append(script, "0xFF")
loop = false
case 1:
script = append(script, "LINE_BREAK()")
case 2:
@ -44,13 +53,22 @@ func readCutscene(r io.ReadSeeker, baseAddr, addr psx.Addr) ([]string, error) {
case 8:
script = append(script, "CLOSE_DIALOG()")
case 9:
script = append(script, fmt.Sprintf("PLAY_SOUND(0x%02X, 0x%02X)", read1(r), read1(r)))
script = append(script, fmt.Sprintf("PLAY_SOUND(0x%X)", read2(r)))
case 10:
script = append(script, "WAIT_FOR_SOUND()")
case 11:
script = append(script, "SCRIPT_UNKNOWN_11()")
case 12:
script = append(script, fmt.Sprintf(
"SET_END(0x%08X)", read4(r)))
case 13:
script = append(script, "SCRIPT_UNKNOWN_13()")
case 14:
script = append(script, fmt.Sprintf(
"SCRIPT_UNKNOWN_14(0x%08X, 0x%08X, 0x%08X)", read4(r), read4(r), read4(r)))
case 15:
script = append(script, fmt.Sprintf(
"SCRIPT_UNKNOWN_15(0x%08X)", read4(r)))
case 16:
script = append(script, fmt.Sprintf("WAIT_FOR_FLAG(%d)", read1(r)))
case 17:
@ -59,27 +77,28 @@ func readCutscene(r io.ReadSeeker, baseAddr, addr psx.Addr) ([]string, error) {
script = append(script, "SCRIPT_UNKOWN_18()")
case 19:
script = append(script, fmt.Sprintf(
"LOAD_PORTRAIT(0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X)",
read1(r), read1(r), read1(r), read1(r), read1(r)))
"LOAD_PORTRAIT(0x%08X, %d)", read4(r), read1(r)))
case 20:
script = append(script, fmt.Sprintf("SCRIPT_UNKNOWN_20(0x%02X, 0x%02X)", read1(r), read1(r)))
script = append(script, fmt.Sprintf("SCRIPT_UNKNOWN_20(0x%X)", read2(r)))
case 0x27:
script = append(script, "'\\''")
case 0xFF:
script = append(script, "0xFF")
default:
if op >= 0x20 && op <= 0x7e {
if op >= 0x20 && op <= 0x7E {
script = append(script, fmt.Sprintf("'%s'", string([]byte{op})))
} else {
return script, fmt.Errorf("unknown op 0x%02X", op)
script = append(script, fmt.Sprintf("0x%02X", op))
}
}
}
return script, nil
}
func parseCutsceneAsC(r io.ReadSeeker, baseAddr, addr psx.Addr) (string, error) {
script, err := readCutscene(r, baseAddr, addr)
func parseCutsceneAsC(r io.ReadSeeker, baseAddr, addr psx.Addr, length int) (string, error) {
script, err := readCutscene(r, baseAddr, addr, length)
if err != nil {
return "", err
}
return strings.ReplaceAll(strings.Join(script, ",\n"), "',\n'", "','"), nil
return "// clang-format off\n" + strings.ReplaceAll(strings.Join(script, ",\n"), "',\n'", "','"), nil
}