1986 · Argus Press Software

The Detective

This minisite was contributed by Nico-van-der-Zijden, air. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/the-detective with me to Gold.

A murder mystery where every suspect follows a script in a little language of its own, against a clock that keeps real time, and the killer is the man the doctor says is dead.

01 · The game

Inspector Snide at the McFungus house

Angus McFungus is dead. The player is Inspector Snide of Scotland Yard, called to his house on a stormy night at ten past nine.

The title screen: The Detective Game, A.P.S. Software 1986 Snide in the hall with the butler

The title introduces the cast one at a time. Play starts in the hall, drawn at an angle across the top of the screen, with a line of scrolling speech under it and a text panel and picture box below.

Nine people are in the house: the Reverend, Bentley the butler, Hilda the cook, Gabriel the maid, Cynthia, Professor Bull, Doctor Mortem, Major Sludgebucket and Mr Dingle the solicitor. They walk from room to room on their own, talk to each other and to Snide, and some of them die as the evening goes on. Snide walks the house with the joystick, and fire opens a menu of icons: examine, take, open, read, question, accuse and more.

To win, Snide must put ten pieces of evidence into the evidence envelopes and accuse the right person before the clock reaches 11:03.

02 · Music

Music: the game's two tunes

The player works in the built site.

The game's own music player ($945E-$984B), run on the site's 6502 with its tunes from the listing, through a model of the C64's sound chip with a 6581's filter. The title tune starts at $9461 as the game starts and plays as long as the title shows. The second tune starts at $945E when Snide first walks into a room where someone has died, and the game stops it once its first voice has read 15 bytes. Every write to the sound chip, frame by frame, matches the game's code run on the kit's 6502 (test_music.js).

The player is a small sequencer. Each voice reads a list of bytes: a byte below $F0 is a note, its low four bits one of twelve frequencies at $97DD and the next three bits how many octaves to drop. Bytes from $F0 are commands: glide to the next note, vibrato on, silence the voice, change the instrument, repeat a stretch ($95AC). The title tune's three voices are at $E680, $E6C0 and $E740, after the room pictures; the second tune's sit among the sprite shapes, at $7AC5.

03 · The cast

Nine characters, nine scripts

Every character's behaviour is a script, stored as bytes for a small interpreter. Pick a character to read theirs.

The scripts are decoded in the built site.

Decoded from the listing's bytes with the interpreter's own table of operand lengths ($A4FE), following every jump. Each instruction's length and handler were checked against the game's own fetch code ($A460) run on the kit's 6502 (test_scripts.js). Words in braces are word tokens; room numbers are the game's own.

The interpreter ($A460) runs once in every pass of the main loop, for one character at a time, so each character gets a turn every ninth pass. It reads the opcode from the low five bits of the next byte, looks up how many operand bytes follow ($A4FE), moves the character's script pointer on and jumps to one of 27 handlers ($A4C8). A handler that has to wait, for a door to unlock or for the message bar to be free, puts the pointer back so the same instruction runs again next turn.

The instructions are about the house: walk to a room, which finds the right door in the door table ($1F00) and walks to it; go through a door, waiting if it is locked; say a line, which shows only if Snide is in the same room; jump if someone else is here, if the player is in a given room, or at random. One instruction, opcode 11, calls ordinary 6502 code. Dingle's second script uses it to kill.

A script asks for a door it has no record of, and the game says so: the screen flashes red and "GUEST ERROR.." appears ($A618). It is a check the author left in for his own scripts.

04 · The solution

What the scripts give away

This section names the murderer and how to win.

Dingle is the murderer. Alone in his room with the door locked, he lies down as if strangled ($B1CF). The Doctor's script then finds Snide, announces "INSPECTOR..MR. DINGLE/S BEEN STRANGLED!", leads him upstairs ("HERE..", "POOR FELLOW..TERRIBLE") and switches Dingle to a second script ($B09C). From then on Dingle waits for Snide to be somewhere else, and kills: Cynthia, found in the hall ($AC96); the Doctor, who certified him dead ($B19E); and Gabriel ($ACEC). He also plants a bomb and takes the ammunition for his gun.

To winWhere the game checks
The ten pieces of evidence in the envelopes: the will, the knife, the note, the small bottle, the cravat, the syringe, the folded document, the wad of notes, the open locket and the bomb$BB17, $BB76
Accuse Dingle, and nobody else$BB76
Before he takes it, swap the bullets where Dingle keeps them for the blank bullets$B1E6
In the cellar, use the gun on him before he escapes$BCAF

At the accusation Snide is led at gunpoint through a dark tunnel to the cellar, and Dingle says "VERY CLEVER, INSPECTOR.. I PAID THE DOCTOR TO CERTIFY ME DEAD, AND THEN TOOK CARE OF HIM.. NOW I JUST HAVE TO TAKE CARE OF YOU!" and fires. With the blanks loaded, "NOTHING HAPPENS" and Snide can arrest him. With the real bullets the game ends.

Each of these outcomes was played in the emulator through the game's own menus, with the stick: the accusation refused without the evidence; and, with the evidence put in the envelopes by hand, the blanks clicking, Dingle escaping when Snide waits, the arrest when Snide uses the gun from his inventory, and the game ending when Dingle has the real bullets. Snide has only a few seconds after the click, because Dingle's escape script walks him out of the cellar at once ($B159).

A winning game, played

The whole game was also won in the emulator from the game's first instruction, with nothing but stick and keyboard input. A script steered Snide and the menu pointer by reading the game's own memory, and logged every input it gave. The promotion came at 09:28 on the game's clock, about 56,000 frames after the start and long before the 11:03 limit. In order:

  1. The padded envelopes from Snide's room; the elephant gun and the blank bullets from the Major's room.
  2. Wait in the upstairs corridor until Dingle lies down. Then, from his "body", the cravat and a small key. The small key opens his briefcase, which holds the note. This has to be done before Snide next walks into room 1 or 15, because Dingle then locks his room for good (see Discoveries).
  3. Into Bentley's room behind him while he has it unlocked; the bunch of keys from the jacket in his clothes cupboard.
  4. Unlock the study. Take the bullets out of the desk and put the blanks in their place.
  5. In the library, take the books and ask for "101 DETECTIVE STORIES": the hardback book holds the folded document.
  6. Take the picture in the drawing room to find the safe, and type McFungus's birthday, 210319: the will.
  7. The Doctor's black bag: the small bottle and the wad of notes.
  8. Walk into the upstairs corridor (room 15) so that Dingle disappears, and wait downstairs until Cynthia is killed. Then the bomb is on Snide's bed.
  9. Wait upstairs for the Doctor's and Gabriel's murders. The knife turns up in the Cook's bed, the syringe and a locket on Gabriel.
  10. Open the secret passage in the kitchen floor, take the screwdriver from the boxes in the cellar, and use it to open the locket.
  11. With all ten pieces in the envelopes, accuse Dingle. In the cellar his gun clicks; use the elephant gun from the inventory, and the game is won ($BCEB).

The murders wait for Snide to be in certain rooms, not for the clock, and the script took him there as soon as it was ready for each one, so the game's clock moved only from 09:10 to 09:28.

The murders, in order

The killings are not tied to the clock. Each step of Dingle's scripts waits for Snide to be somewhere else, so the order is fixed and the timing depends on where the player walks. A script's wait counts down once every 16 rounds of the interpreter ($A519), 144 calls; in the hall the interpreter ran 35,148 times in 3,000 frames, so one unit of wait is about a quarter of a second there. The times below use that rate, which changes with how busy the main loop is.

  1. Dingle fakes his death. He walks to his room (19) and asks anyone there to leave ("WOULD YOU MIND LEAVING MY ROOM PLEASE, SIR.."). Once Snide is not with him, he locks his door, waits 74 (about 18 seconds) and lies down as if strangled ($B08A, $B1CF). That counts the first death.
  2. The Doctor reports it. With a death counted, the Doctor leaves his search for his scalpels at random ($AE90, $AED7), says "GOOD EVENING", goes up to his room and on to Dingle's. From there he walks the house until he is in Snide's room, says "INSPECTOR..MR. DINGLE'S BEEN STRANGLED!", leads him back ("HERE..", "POOR FELLOW..TERRIBLE") and switches Dingle to his second script ($AFA6).
  3. Dingle disappears. He waits for Snide to be in the corridor downstairs (room 1) or the corridor upstairs (room 15), locks his door, leaves every room ($B18D) and waits 260 (about a minute).
  4. Cynthia. When Snide is in the drawing room, the servants' corridor (room 13), or Bentley's, the Cook's or Gabriel's room, her script is stopped and she is killed: her body is put in the hall, and "YOU HEAR A SCREAM.. FOLLOWED.." is printed ($B0CA, $AC96).
  5. The bomb. As soon as Snide is out of his own room (23), Dingle plants the bomb ($B198), then waits 368, about a minute and a half, and 120 more for as long as a coin toss says so.
  6. The Doctor. When Snide is upstairs (the landing or either upstairs corridor), "YOU HEAR A RATHER UNPLEASANT, GASPING SCREAM FROM DOWNSTAIRS!", the Doctor's script is stopped and he is killed in room 27, and the knife is moved to place $1A ($B0EE, $B19E).
  7. Gabriel. After a wait of 122, about half a minute, and once Snide is in one of the upstairs corridors, she is killed in her room ($B13F, $ACEC).
  8. The ammunition. After 632, about two and a half minutes, and 152 more for as long as a coin toss says so, and once Snide is out of the study, Dingle takes the ammunition from its place ($B14F, $B1E6): the real bullets if they are there, the blanks if the player has swapped them. His script then stops for good. The accusation runs the same routine again, so the swap can be made any time before Dingle has taken them.

05 · Time

A clock that keeps real time

The clock is the text "09:10" at $1EBD. An animation job that runs every fourth frame ($2C83) counts to ten and then to 75 before it adds a minute ($2570): 3,000 frames, which is one minute at the 50 frames a second of a European C64. Running the game for 6,100 frames moved the clock on by two minutes.

The time limit is "11:03" ($2158). That is an hour and 53 minutes of real time from the start. When the clock reaches it, the lights go out, Snide is shot by an unseen assassin, and the game starts again from the title ($2592). The pause icon stops the clock by setting the game state's top bit while it waits for fire ($A1E0): from state 10 up, the interrupt skips its animation jobs, the clock's among them ($2C57).

07 · The house

Thirty rooms from seventeen pictures

Each room is drawn from a packed picture into a map 256 columns wide ($0C00), and the screen shows a 40-column window of it that scrolls as Snide walks. The Maps tab draws every room. Doors are drawn over the picture afterwards, from a table of 32 doors ($1F00). Doors of type 8 are secret passages: closed, the game draws the wall back over them, and the border, which flashes when Snide reaches something to investigate, stays still for them ($3E32).

08 · Sprites

Everyone is two sprites

Each person on screen is a pair of sprites, a head above a body. The machine has eight sprites, so a room shows at most four people: the main loop fills four slots with whoever is in Snide's room and in view ($2F91), and the interrupt places the pairs from the slots every frame ($2A0D). Every sprite is multicolour, with white and black shared by all of them ($D025 = 1, $D026 = 0) and a colour of its own, light red for skin. The game changes that colour once: when Snide swallows the bottle of pills, "YUK.. THAT DIDN'T TASTE TOO GOOD..!", he turns green until the next game ($A1B1).

The sprites are drawn in the built site.

Snide and the cast are animated by different code. Snide has twenty shapes, a head and four bodies for each of four directions ($43-$56), and none is ever mirrored. The direction picks the head ($372E), and a step counter that runs down from 8 to 1, one step every third frame, picks the body ($36B4, $3734), so his walk repeats every 24 frames. The direction is taken only when the counter starts again, so a turn can show up to seven steps late.

Each of the nine others has ten shapes, from $6D on: three heads and three bodies facing the viewer, then a head and three bodies facing away. Twice in every four frames ($9241) the cast's animation moves on after every third call, through the eight offsets 1, 0, 1, 2, 1, 0, 1, 2 ($9239), which pick the body. Walking right or towards the viewer uses the shapes facing the viewer, and walking left or away the shapes facing away ($9228, $922C). Towards the viewer and away are drawn mirrored: when a character turns between the two, the game reverses its ten shapes in memory, two shapes a call, through a table that reverses the four pixels of each byte ($9138, $0500). The character speaking steps through the three heads instead, by the offsets 0, 0, 1, 1, 0, 2, 1, 2 ($93C2), so the mouth moves. The Major is an exception in the code: walking right or towards the viewer, his head moves with the steps too ($9391).

The dead are drawn with other shapes, and their pairs are placed in other ways, by a number kept for each person ($1EA6, set by $AD18, used by $250B): 1 puts the two sprites side by side, lying down; 2 keeps them one above the other with the head 2 pixels to the right of the body; 3 shows one sprite alone. Snide lies down the same way when the game ends with him beaten: when the clock runs out, when he drinks from the small bottle ("GASP IN AGONY AND DROP DEAD"), and after the bomb, which first shows him as a BOOM ($C066). All three end in $25D6.

Drawn in the built site.

The title's portraits

While the title waits for fire, it introduces Snide and the nine others one at a time in the picture box, each with a few lines in the panel beside it ($9129, from the list at $8E65). A portrait does not simply appear. The interrupt runs the introduction in phases, one every few frames ($8CC8, $8B31). After two single sprites, the portrait is wiped on in a buffer of two sprite shapes at $58C0, in five steps a little higher each time. Each step keeps what is inside the character's outline and adds one of five pictures, sprite shapes $5E-$62 stretched to twice their height when the title starts ($8DC0). The outline is built from the character's own head and body ($8D13), so the pictures fill the shape of the person who is coming. The buffer then flashes through ten pairs of colours, and the character's real sprites take its place in four more, talk in their play colours for 254 frames, about five seconds, while the panel shows their lines, and fade out through eight. Every character takes 480 frames, eight counts of 60 ($1E69).


    

The title runs in the built site.

The box is drawn as the title screen shows it (reference/title.png): the portrait's sprites go in front of the panel's grey. The port runs the game's three routines in the order the interrupt runs them, at 50 frames a second, and a test holds it against the game's own code for 5,200 frames, all ten characters (test_title.js). The outline's lower half is always taken from the fifth shape after the head ($8D3E, where the X register is always 0): that is Snide's body, but for the nine others it is a walking body, while their portrait shows the standing one.

All 176 sprite shapes, $40 to $EF at $5000-$7BFF, are below in the colours of play. Besides the people and the bodies, they hold the title's sprites and the menu's pointer. Hover over a shape, or tap it, for its number.

Shape numbers are shown on hover.

09 · Speech

Thirty-two words in one byte each

The cast's lines are stored in capitals, with single bytes standing in for common words. A byte of $60 or more is a token: its low five bits pick a word from a list at $4A90, and the print routine prints the word instead ($21D8). The first ten words are the names, so a script can say "[8]" to mean "DINGLE".

TokenWordTokenWord