1985 · Mastertronic

Mr Puniverse

This minisite was contributed by air. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c16/mr-puniverse with me to Gold.

What the code holds that the game never shows. A second title, WIMPO, waits beside MR PUNIVERSE for a routine that never reads it, one room spells REST ROOM in its walls, and five exits lead somewhere other than the room next door.

01 · Secret

Secret: an unused title spells WIMPO

The routine that draws MR PUNIVERSE in dots on the title has a second path beside its own. Pointed at it, the title spells WIMPO.

title_path ($340D), 233 dots
wimpo_path ($1B77), 220 dots

The title as new_game leaves it. Then the game's own routine title_dot_step, at $1C46 in memory (a $ marks a number written in hexadecimal, base 16), runs once for each dot, with its wait left out. It runs on the page's copy of the C16's processor, a 6502. On the right, the four instructions that read title_path read wimpo_path instead. With the same change made in the plus4emu emulator, the title drew WIMPO.

While the title waits for RETURN, new_game calls title_dot_step over and over. Every 255th call draws one dot, a vitamin, and moves on along a path of strokes. Each stroke is one byte, eight bits. Its low four bits count the dots, and its high four bits give the direction. A byte of 0 starts a new stroke somewhere else on the screen. A byte of 1 starts the path again in the background colour, so the letters are drawn and then rubbed out, dot by dot.

The routine reads its path at $340D. A second path in the same format lies at $1B77, between the PAUSED message and the title's text, and the game never reads it. It draws the same box round the play area and then WIMPO in tall thin letters, where MR PUNIVERSE goes. The inlay calls the weaklings Mr Puniverse is one of "Wimps".

02 · Secret

Secret: room 18 spells REST ROOM

The walls of room 18 are letters five rows high, REST along the top and ROOM below, and the room is an easy one.

Room 18 as the game's draw_room ($2868) draws it from its record, run on the page's 6502.

A room's walls are a bitmap of 45 bytes, one bit for two cells (How it works), so a room can be drawn as freely as a picture. Room 18 is on the fourth row of the map, in the fourth column. It fills the EGY bar a step every pass, as fast as any room, and its only objects are three crushers. Its floor has nine gaps that lead out to room 0, each under a block of wall (Five exits).

03 · Secret

Secret: five exits lead off the map

The rooms are a map five by five, and most exits lead to the room next door. Five lead elsewhere: four of them to room 0, at the top left, and one up two rows at once.

Both rooms drawn by the game's draw_room on the kit's 6502. On the left, the exit's cells: the blank cells on that edge, which draw_room_objects turns into exits. On the right, the cells on the opposite edge, where leave_room moves his block: 15 rows up or down, or 38 columns across, in the same column or row. In plus4emu, room 2's pit and room 24's corridor and ladder each took him to the room shown.

Each room's record names four rooms, one for each edge, and any gap the walls leave on an edge is an exit to that room (How it works). An exit byte of 0 is room 0 like any other number. Room 2's pit drops him into room 0, at the top left of the map, not into room 7 below it. In room 24, at the bottom right, the corridor along the foot of the screen leads left into room 0, and the ladder at the right climbs into room 14, two rows up.

The gaps in the floors of rooms 18 and 19 also lead to room 0. Each of room 18's nine gaps lies under a block of wall, and room 19's lies under the foot of a ladder, which holds him when he lands on it.

04 · Bug

Bug: a room that fills the EGY bar never fills its last cell

In a room that fills the bar, the filling stops when it reaches the rightmost cell, before it fills it. Whatever that cell lost stays lost until the next turn.

After draining

After filling, as long as it will

The game's own energy_tick ($33AB), run on the page's 6502. It is called with a rate of 1, first in a room that drains (mode 1), as many times as the slider says, and then in a room that fills (mode 0), until the bar stops changing. The bar is drawn as the panel draws it. In plus4emu, in room 6, cells 30 to 33 at full, full, one step down and empty went to full, full, full and empty.

The bar is 34 cells in a row along the foot of the panel, numbered 0 to 33, and each cell holds four steps. A variable, bar_pos, says which cell is being worked on. A turn starts with bar_pos at 33, the right end. Draining takes a step at a time from that cell, and moves bar_pos left when the cell is empty. Filling puts a step back into the cell at bar_pos, and moves bar_pos right when the cell is full.

Before it fills, though, energy_tick checks whether bar_pos is 33. If it is, energy_tick does nothing, so cell 33 is never filled. After any drain, the bar can come back to at most 33 full cells, plus whatever cell 33 still held. The first four steps drained in a turn come out of cell 33, and filling never puts them back, in any room. Only the start of the next turn fills the whole bar (refill_energy).

05 · Secret

Secret: the code has a working lift, and none of the rooms uses it

A lift is coded from end to end: a character that moves, a way to draw it, and a rule that carries Mr Puniverse up when he stands on it. There is none in any of the 25 rooms.

A column of character $BC beside itself, four rows high, as draw_column would draw it, moved by the game's animate_chars ($1D13) on the page's 6502 twenty times a second, as often as the main loop calls it. Drawn in the colours of room 24's ladder.

Three routines know about the lift. animate_chars scrolls the picture of character $BC up a line every third pass, as it scrolls the force field, so a lift would seem to rise. draw_column, which draws the ladders and the force fields, puts a second character beside each one for its right half. For the lift, as for the blank, that second character is the same one again, and every other column gets a different character beside it. Last, player_move, finding $BC under his feet, moves him up two lines a pass with move_up, the routine a jump uses.

A room would place a lift as a piece of scenery (How it works). Scenery is made by make_decor, which draws a row of floor for the characters $A0 to $BB and from $C8 up, and a column for any other. So $BC would be a column. The records place 18 pieces of scenery, and every one of them is something other than a lift.

06 · Secret

Secret: a second tune player plays the room data

Beside the title tune's player is another of the same shape, which the game never calls. Its tables lie where the rooms are.

old_music_tick ($317F), run on the page's 6502 once a frame (about 50 times a second) from the start of its tables, as irq runs the title tune. Its writes play through the site's model of TED, the chip that makes the C16's picture and sound. The other button plays the title tune, for comparison.

old_music_tick works as music_tick does, with seven frames to a step instead of six and 96 steps instead of 128. It takes voice 1's notes from $1800, voice 2's from $1860, and their pitches from tables at $18C0 and $18D8. It plays only while the byte at $03BB is 0, and the rest of the game never reads or writes that byte.

Those addresses lie in the records of rooms 19, 20, 22 and 23, so this second tune player would read walls and objects as notes. irq, the game's interrupt routine, calls only music_tick, and the game never reaches $317F.

07 · Bug

Bug: the title tune reads past its own tables

The tune starts on a step 255, which reads bytes beyond both of the tune's tables. Three of its notes also take their pitches from beyond the table of pitches.

From the listing: tune_voice1 at $196E, tune_voice2 at $1A27, 128 steps each; note_freq_lo at $19EE and note_freq_hi at $1A0A, read at the note's number. The pitch is TED's: 110,840 ÷ (1023 − the value) Hz, vibrations a second, on a PAL machine, the kind sold in Britain and Europe.

setup_machine sets the tune's frame and step counters to $FF, which is 255. music_tick plays the step its step counter holds, so for the tune's first six frames it plays step 255. Voice 1 reads byte 255 of its table, which lies inside tune_voice2. Voice 2 reads byte 255 of its own table, which is a byte of music_tick's code. Both bytes are taken as notes, so the tune opens with a chord that is not in it. Then the counter wraps round to 0 and the tune proper begins.

The pitch table has 28 entries, for notes 0 to 27. Near the end of the tune, voice 2 plays notes 84, 85 and 87, and their pitches come from bytes of tune_voice2 itself, read as if they were the table. Notes 20 and 21 also repeat the pitches of 16 and 17.

08 · Bug

Bug: cannons that are always on read another table as their switch

Every cannon and crusher has a switch number in its record. Those without a switch of their own give switch 8, and there are only eight switches, 0 to 7.

object_timer looks the switch up in switch_state ($0FE8), a table of eight bytes, one for each switch. Switch 8 would be the byte after them, which is the first byte of the next table, obj_type: the type of the room's first moving object. In a room with a cannon or a crusher, that byte is never 0, so switch 8 is always on. The game works, by way of a byte that belongs to another table.

09 · Bug

Bug: the title's colours are whatever the tape left behind

Nothing in the game sets the title screen's colours. Once a frame, the game's interrupt routine copies three bytes into TED, the chip that draws the picture, as the colours for the top of the screen. On the title, those bytes still hold what loading the tape left in them.

The top of the screen takes its colours from room_colours ($0339-$033B), which draw_room fills each time it draws a room (How it works). Those three bytes lie in the cassette buffer, a part of memory that the C16's built-in program, the KERNAL, uses when it reads a tape. Until the first room is drawn, they hold what the tape's loader left there: $4C, $4A and $F0, a blue-green, a yellow-green and black. A loader that left other bytes behind would give the title other colours.