Technical appendix · Home · Français
How the player acts on the game, and what decides which sentence
appears. Most of the game's content is data in G3.CON
record 0x2A, so the lists are generated into logic/ by tools/game_logic.py.
| File | Contents |
|---|---|
logic/dialogue.md |
Every answer for each character and question, with what changes it |
logic/actions.md |
Per room and zone: each verb's reply, objects, containers |
logic/unlocks.md |
What unlocks each conversation topic |
logic/events.md |
Messages and scene changes by time |
logic/schedule.tsv |
Where each character is, every half-hour |
logic/rooms.md |
Room exits and travel costs |
logic/quiz.md |
The final questionnaire, with its answers |
logic/documents.md |
Every readable object with its pages, the newspapers, and the piano's tunes |
Coverage. The tables are extracted exactly as the
code reads them. Reactions written directly in code are only partly
listed (see "Scripted reactions"), so a sentence missing from logic/ isn't proof that it never
appears. Room names are matched from exit labels and string order, and
aren't stored in a table.
Game_Turn EA 0x1E220 waits for a choice,
then Cmd_Dispatch EA 0x1D9D8 runs it.
Menu (DS:40) |
Label | Choices |
|---|---|---|
| 0 | Fic (inferred label) |
9 characters: if present, Accoster (talk) or
Suivre (follow). Item 10 opens another screen
(0x119B8), not yet read |
| 1 | Dep |
up to 6 exits for the room, from tables 6, 7 and 8 |
| 2 | Invent |
select a carried object (up to 5 slots at DS:7A0, in
hand at DS:7AA) |
| 3 | Action |
appuyer, attendre, dormir, fermer, fouiller, lire, manger, mettre, observer, ouvrir, prendre, regarder, sentir, sonder, soulever, tourner |
| 4 | Self |
se cacher, déposer, se fouiller, lire |
After choosing a verb that needs a target, the player clicks the
scene. Ui_PickPoint EA 0x19660 converts the
click to 8×8 cells and looks up two zone sets, per room: tables
0x111 (scene zones, DS:78) and
0x112 (detail zones, DS:7A). A zone with an
entry in Flag_ZoneIndex EA 0x1FCC8 exists only
while its flag is set. The cell is ((x - 4) / 8, (y - 12) / 8) on the
320 × 200 screen. Each table gives, per room, a record 0x2A
entry with the number of rectangles per zone (first byte: zones - 1),
and the next entry holds, zone by zone, the rectangles' x0, x1 pairs
then their y0, y1 pairs, in cells (Zone_Find EA
0x206ED).
Fixed behaviour of some verbs:
DS:68, set from the time by EA 0x1F924) is 9,
13 or 20, otherwise a refusal. Breakfast at 9 adds 7 condition and one
half-hour; lunch at 13 and dinner at 20 add 14 and take an hour (EA
0x1A58C).DS:16E by 1 if
DS:7C is set, and by 3 if DS:137 is set; see
"State".138 where the zone
allows it. While it is set, the owner of the room doesn't confront
you.Game_AdvanceTime EA 0x138DE advances the
clock and runs what depends on it. Time starts at 20 (10:00 on the
31st), and the character tables run for 74 half-hours from there.
Characters follow logic/schedule.tsv
exactly: table 0, room = T0[(time - 20) * 9 + character].
The player can only talk to those in the current room.
Travel adds table 8's value to
DS:6C. The code adjusts it by
(condition / 20 - 2) * 25 / 100, but that integer division
gives 0 for every condition value, so the adjustment has no
effect.
Exits: values from 100 trigger a special event.
"Pick on screen" exits (255) lead through a door zone (tables
0x113, 0x114, 0x116, listed at
the end of logic/rooms.md).
Exits shown: the word at DS:A79 + 2
× (room - 1) is how many of the room's exits the Dep menu
shows (Game_Turn EA 0x1E258). Scripts raise
it: the rope put on the well (room 10, zone 17) sets 6 and adds
dans le puits; opening Maguy's trapdoor sets 4 and adds the
passage; in the well (room 16), appuyer on detail zone 6
("Signes des temps") switches 1 and 2, adding
dans le passage, but only while the stone #23 sits in the
well's rock (room 10, zone 15, flag DS:7F0). Climbing back
out sets it to 1 again.
Locks: Tbl_LockCheck EA
0x152A2 refuses a door (table 0x1B2) or a zone
that opens (table 0x1B8) between two times unless one of
the five carried objects matches. Lucie's room (door 4 in front of
Maguy's house) is always locked without key
All are listed in logic/rooms.md.
Timed messages, scene changes
and objects moved by the clock are in logic/events.md, such as the
well flooding at 16:30, the wig in Juste's stove at 18:30, the médaillon
in the fish trap at 01:30 and the decoded sheet in Roy's cabin at 02:00.
Each object move runs once (flag DS:924+i). A removal that
finds nothing in the container means you carry the object, and kills
you.
Dlg_Talk EA 0x1ADD4 offers a topic list.
Characters are numbered 0-8: Maguy, Sue, Anita, Bruce, Roy, Chris, Bob,
Anton, Juste. Marie and Lucie can be asked about but aren't in the
schedule.
| Question | Table | Lookup, c = character |
Change key (type) |
|---|---|---|---|
| Votre emploi du temps... | 1 | T[slot * 9 + c] |
c * 40 + slot (1) |
| Qu'avez-vous remarqué... | 2 | T[slot * 9 + c] |
c * 40 + slot (2) |
| Que faites-vous là? | 3 | T[(time - 20) * 9 + c] |
c * 74 + time - 20 (3) |
| opinion of a person, 0-8 | 4 | T[c * 9 + person] |
c * 9 + person (4) |
| Marie, Lucie, or one of 20 topics | 5 | T[row * 9 + c] |
c * 22 + row (5) |
Values are 1-based class 5 strings (storage bank 7). A value of 0 gives a random evasive line: one of class 5 strings 141-143 for "Que faites-vous là?", and three others for "Qu'avez-vous remarqué".
An answer changed earlier takes priority:
Dlg_GetOverride EA 0x18784 looks in the saved
array at DS:2D2.
The three lists are gated by flags in the state block. Showing
certain strings or taking certain objects sets them, as listed in logic/unlocks.md.
| Topics | Flags | Names |
|---|---|---|
| people and the four standard questions | DS:842+i |
table 0x105 |
| 20 subjects | DS:851+i |
table 0x106 |
| time slots | DS:864+i-1; the first two are always on |
table 0x107 |
A time slot appears once it is over. At each time
step, Time_UnlockSlots EA 0x1F924 sets
DS:864+i for i = 1 to day × 24 + hour - 10, so "6 à 7 h PM"
can be asked about from 19:00. The menu reads slot k (k ≥ 2) at
DS:864+k-1.
Topics are unlocked in four ways, all listed in logic/unlocks.md and run by
Tbl_UnlockTopic EA 0x103B4: an answer (table
0x1BE), a message (0x1C6), reading or taking
an object (0x1C2), and clicking a scene
zone with any verb (0x1CB, from
Ui_PickPoint). The last one is how "La chambre fermée à
clef" appears: click the locked door in front of Maguy's house. The
bassin's statue, the sealed crate and Marie's forced bookcase work the
same way.
Dlg_Answer EA 0x18A43 shows an answer with
seven buttons (table 0xFE):
| Button | Effect |
|---|---|
| Mémoriser | stores the answer: who, question and string, at
DS:170-1A6 |
| opposer | confronts the character with a stored answer: 8 points if it's the statement this level expects |
| se souvenir | shows a stored answer |
| donner | gives the object in hand; if the character wants it (tables
0x130/0x131), +4 pressure |
| montrer | shows the object in hand: reply from table 0x87,
T[object * 9 + c]; costs 2 of DS:16E |
| soudoyer | offers money: accepted if the amount exceeds table 10's price by 3 per refusal, +2 pressure |
| tabasser | lowers DS:16E by 10 or 40. Won if condition is at least
the character's strength (30,20,40,60,60,90,90,80,40) plus
the attempt number: +1 pressure, -10 condition. Losing costs condition
by the gap, at least 15 |
Dlg_Pressure EA 0x163A3 applies the change,
using tables F = 0xCA, 0xCE, 0xD6, 0xDC, 0xE4
by question type and G =
0x1EA, 0x1EB, 0x1EE, 0x1F0, 0x1F3. A question listed in
F+1 has up to three levels, and each level says which
answer comes next (table F+3+2×level). To advance:
F+2+2×level, F+3+2×level). A string of
600 in the data can never match, so those levels advance only by
pressure. Otherwise it adds 8 points.88), which then falls by 1.216+2i) plus this attempt's amount reach its threshold
(G+level). Only then are the points kept, the level byte
(DS:1B8+i) raised and the new answer stored at
DS:2D2. A failed attempt leaves no points,
and the thresholds count from the points already kept.opposer with the expected statement (amount 8, EA
0x19047) works at the first try whenever the earlier levels
were also passed by opposing: no threshold in the game is above 8 ×
(level + 1). Opposing with anything else never helps. The "pressure
>= N" in logic/dialogue.md is this
threshold: pressure (DS:88) is the amount for a plain
question, and it only matters for the levels marked 600, which can't be
opposed.logic/dialogue.md
shows these under each answer, as → condition: new answer.
Reaching a given sentence means meeting all of: the
character is present at that time, the topic is unlocked, and any
→ condition on it is met. Sentences that aren't in a
character's grid come from → lines or code.
Following (Dlg_Follow EA 0x1C5CD) tracks
the character's schedule, and can fail with "Vous l'avez perdu de
vue!".
Each verb has a reply table family, listed in logic/actions.md:
T zones per room, T+1 zone ids,
T+2 the default, T+3 the strings
(Tbl_ZoneLookup EA 0x1FF5C).
| Reply used | When |
|---|---|
| table reply | the zone is listed for this verb |
| default | no entry; for Tbl_ZoneReply EA 0x1294C,
also when the zone is already open |
| "not open yet" reply | Tbl_StateReply EA 0x12C58, for fermer,
fouiller, ouvrir, mettre |
Other mechanisms:
ouvrir,
fermer, soulever, tourner and
appuyer toggle state at DS:92F +
11 × (room - 1) + zone, redrawing the zone. Table
0x1B8 can block them by time or carried object.0x185-0x1A9, one per verb, set and clear scene
flags on success (Tbl_ApplyFlags EA
0x11584).prendre uses tables
0xC0-0xC3. Containers hold up to 5 objects, in
the saved arrays at DS:368 and DS:5FC;
fouiller shows them. Object names are table
0xC6.88E (tables
0x1D0-0x1D5), the basis of "Vous devriez avoir
remarqué x pour cent des indices".| DS: | Meaning |
|---|---|
166 |
room |
168 |
time, in half-hours |
16C |
condition, 0-99; below 0 triggers an event |
16E |
hidden sympathy score, starts at 50; see "Sympathy" |
7A0, 7AA |
carried objects, object in hand |
7B5 |
scene and story flags; includes topic flags at 842,
851, 864 |
88C |
money |
88E |
clue points |
8AE |
zone and object state words |
DS:16E is a hidden score, starting at 50. "Sympathy" is
the name an online source gives it; the game's text never names it. Only
three instructions touch it: the add and store in
Game_AddSympathy EA 0x1F9B1, and the test in
Game_AdvanceTime. It has 18 call sites, all with fixed
negative amounts, so it can only fall. It isn't
displayed and changes nothing else, including dialogue.
At the next time step after it goes below 0 (51 points lost), the game ends with one of two failure texts, class 6 strings 62 or 63: Maguy has you taken to Mahé, or the men lock you in your cabin.
| Action | Loss | Condition | Site |
|---|---|---|---|
| tabasser | 40 | anyone else is in the room | 0x1939B |
| tabasser | 10 | only the two of you (DS:7C = 1) |
0x19390 |
| fouiller | 3 | the room's owner is there (DS:137) |
0x1A1A8 |
| fouiller | 1 | someone else is there | 0x1A19D |
| montrer | 2 | each time | 0x191C9 |
| soudoyer | 1 | each offer, accepted or not | 0x19236 |
| suivre | 2 | the person notices you, and turns on you | 0x1CE55 |
| suivre | 2 | you tail the same person again ("Encore vous?") | 0x1AFAE |
| being in someone's own room with them | 1 | "Vous vouliez me voir?" | 0x1B00B |
| the same | 2 | if it's the last person you tailed ("Toujours dans mes pattes!") | 0x1AFF6 |
| the same, from 23:00 to 08:00 | 1 or 2 | "Ce n'est pas une heure pour déranger." | 0x1AF5C, 0x1AF47 |
| leaving something open | 2 per item | someone has been in the room since you left; they close it | 0x19CCD |
| taking money from an object list | 1 | 0x160D8 |
|
| taking an object with your hands full | 2 | from a close-up | 0x160B5 |
| dropping an object | 1 | away from its own place | 0x1D64B |
Owners' rooms come from the array in Dlg_Talk: Maguy 3,
Sue 5, Anita 7, Bruce 20, Roy 19, Chris 21, Bob 25, Anton 27, Juste 8.
The room check runs from the turn loop, so staying can cost more than
once (how often wasn't counted). Hiding avoids the confrontation, but
not the fouiller penalty.
The losses are applied before the outcome, so a beating costs the
same whether you win or lose. Plain accosting, questions,
opposer, donner and Mémoriser
cost nothing.
Two more call sites, 0x1AFCD (3) and
0x1B038 (2), need Dlg_Talk to be called for a
room's owner with DS:137 clear. The only such call site
checks that it is set, so they look unreachable.
Tolerance, for reference: one beating with a witness leaves 10, and a second one ends the game. Beating people alone, you can do it five times and sit at 0; the sixth ends it.
Tourner on zone 31 of room 30 starts the check in
Script_Hook EA 0x1767F. It needs the 5
bénitier on the first plate and the 3 bénitier on the second, each
holding 2 volumes (DS:AF7 = 0xA6,
DS:AF9 = 0xA8, DS:AF1 = 2,
DS:AF3 = 2). Zone 31 exists once the opened médaillon is in
the ring.
Quiz_Run EA 0x15450 then asks 7 chains of
questions from table 0x1F9. Questions in 0x1FB
go on to 0x1FC if right. Any wrong answer clears
the success flag, so the percentage in class 7 string 126 is
only shown on failure, and play continues. Success plays class 6 string
102 and sets DS:132. The winning path is worth exactly 100
points. See Walkthrough.
Script_Hook receives
(event, room, zone, item), with these events:
| Event | From | Event | From |
|---|---|---|---|
| 1 | ouvrir | 9 | appuyer, scene zone |
| 2, 3 | tourner, detail and scene zones | 0xA |
lire |
| 4 | fermer | 0xB |
time passing during travel |
| 5, 6, 7 | mettre: success, attempt, special | 0xC |
an exit |
| 8 | appuyer, detail zone | 0xD, 0xE, 0xF |
déposer, sonder, prendre |
Cases read so far:
Room 30 puzzle: a water-jug puzzle with
bénitiers of 5, 3 and 8 volumes, which start full; sonder
reads a level, tourner empties, mettre
pours.
The piano (room 2). tourner on its
detail zone 14 once the ashtray is in place sets DS:139 and
opens the compartment (container 24). Putting a one-cent coin in the
slot (zone 16, event 6 with object kind 14 from table 0xC4)
shows the 15 tunes of table 0xF1 (logic/documents.md). If
DS:139 is set, the chosen tune leaves a sheet in the
compartment (DS:456 is its fifth slot) and
DS:139 is cleared (EA 0x17D37):
from 12:00 to 17:00 on the 31st, tune 13 ("Requiem") leaves the real message, sheet #139; tunes 0-12 and 14 leave
88A, ending at about 15:00); when it
runs out, if you are alone in the salon you arekilled, otherwise it waits.
from 07:00 on the 1st, tune 4 ("Ham and eggs") leaves the second message, sheet #162; the others leave #188-#201. Marie's hidden list (sheet #158) starts with "Requiem: Kyrie eleison", then "Ham and eggs". At 17:30 on the 31st the clock puts #139 in the compartment anyway, and takes it away at 23:00.
Inscriptions: lire on the bassin's
zone 5 (with the binoculars, at low tide) shows record 0x21
sub 7, and lire on detail zone 1 of the passage under
Maguy's trapdoor (room 17) shows sub 6. Each is half of a mirrored
Spanish text; see Walkthrough.
Touch puzzles: Item_TouchPuzzle EA
0x14D04 turns an object into another when its stones are
clicked in order. Header T: byte 2 is the last stone index, byte 3 the
last step index, byte 4 the new object; T+1 and T+2 are the stones' x
and y, T+3 the order. The écrin #40 (T = 0x1E0) has 5
stones and needs 4, 5, 3, 3, 5, 2, and becomes #163, whose lid shows
zodiac signs. The médaillon #49 (T = 0x1E5) has 7 stones
and needs 3, 4, 6, 5, 2, and becomes #153 with its key.
Hidden caches: appuyer on the
painting in Maguy's room (zone 1, table 0x12D) opens the
cache with key #15 and 10 dollars. tourner on zone 14 there
opens the drawer with key #17 (zone 30), and soulever on
zone 15 shows the trapdoor (zone 21). In Roy's cabin,
tourner on zone 31 ("Un déclic") opens the cache, zone 33,
where the decoded sheet
Room 11, zone 5 (event 10): readable only at times 32-33, 56-57 and 80-81, while carrying object 42 (the binoculars). Otherwise "Vous êtes trop loin...".
Well, room 10 to 16 (event 12): outside those
same times, leaving triggers special event 0x40.
Sounds and small flag changes in rooms 1, 3, 10, 12, 16, 20, 26 and 28.
Item_Read EA 0x12E52 looks the object up in
three families, listed in logic/documents.md: single
pages (tables 0x137-0x13A), books
(0x13B-0x13E) and newspapers
(0x13F-0x145). For a single page it passes the
string number to service 9 with table 0x13A's value in the
high word. Txt_DrawIndexed in maup.exe (EA
0x157C3) keeps that value at DS:CE, and
Vid_DrawStringEx (EA 0x1188C) uses it to
highlight some letters in another colour:
maup.exe DS:k-1 (each byte is an offset to a
list of gaps, ending with 0xFF). In the file,
DS:0 holds the C runtime's copyright, and the game does
read it: in the game, #174 (k = -1) darkens the first four characters
and then one on the third row, and #175 (k = -2) the first three and
then one a place earlier, as the bytes 0, 0, 0, 0 and "T" (84) predict.
The decoys show noise.The five readable grids as the game shows them, read in the game from a test start state (the pointer is the mouse):
| Sheet | Screen |
|---|---|
| #139, the real message ("Requiem") | ![]() |
| #25, Roy's copy | ![]() |
| #162, the second message ("Ham and eggs") | ![]() |
| #48, the paper in the garden | ![]() |
| #174, a decoy ("Sweet Emily") | ![]() |
Decoding. The 64 highlighted letters are a chessboard, a1 first then rank by rank. Reading the destination square of each move of a game in 'Les échecs', white and black in turn, gives the message: game n°4 (pages 4 and 90 of bank 4) on #139 or #25 gives "we wait the boat", and game n°5 (pages 40 and 96) on #162 gives "tribes need guns! the Wind!". No game decodes #48. The method was first found by the Adventurers' Guild blog for the first message.
Not yet read in full: parts of
Script_Hook, Act_Regarder's close-ups
(including the médaillon), Act_Observer,
0x119B8, and what happens when you're caught.
Previous: The two programs · Next: File formats, scenes and palettes · Technical appendix · Home