🎄 Merry Christmas, TCRF! 🎄
The Adventures of Captain Comic (DOS)
The Adventures of Captain Comic |
---|
Developer: Michael A. Denio This game has unused code. This game has a prerelease article This game has a notes page This game has a bugs page |
The Adventures of Captain Comic is an EGA sidescroller.
You can play the game in a browser at the Internet Archive.
Contents
Sub-Pages
Prerelease Info |
Notes |
Bugs |
Code Changes |
Revisional Differences
The file COMIC.DOC describes five revisions of the game.
- Revision 1 ( 5/01/88)
- Original Software Release.
- Revision 2 (11/28/88)
- Added definable keyboard option.
- Keyboard definitions can be saved (KEYS.DEF) for future play.
- High score file (COMIC.HGH) by can be deleted to "clear" highscores.
- Several minor bug fixes.
- Revision 3 ( 2/20/89)
- Revised player control. Jumping in cramped areas is now more consistent with the "feel" of jumping in open areas.
- Major bug fixes. This version contains no known bugs.
- Revision 4 (10/20/89)
- Limited revisions. Added joystick feature to get feedback on the "feel" of the joystick control for use in future games.
- Joystick option not yet available on PC XT class machines.
- Revision 5 (7/10/91)
- Limited revisions again. Fixed the joystick to work with all PCs. I also modified the scoring system to remove 'bonus' points awarded when the player falls. This made beginner's score unnaturally high.
Revision 1 was reverse-engineered and modded into Prigodi Pìonerki Ksenì.
Maps
The map file format marks each tile as being either passable or solid. 6 of the 24 level maps changed their structure in a way that was not merely graphical. 5 of the 6 cases changed only once, in Revision 3. The remaining case, COMP2.PT, changed twice, in Revision 2 and Revision 3.
■ Revision 1 ■ Revision 2 ■ Revision 3
Map Tiles
All levels except the castle saw changes to their map tiles. Not all map tiles are used, not even all of those that were newly redrawn in a revision.
Graphics
In Revision 4, Comic traded his overalls (presumably a leftover from these sprites' not too subtle inspiration) for a V-neck more befitting a spaceman.
Revisions 1–3 | Revisions 4–5 |
---|---|
Fullscreen Graphics
The fullscreen graphics are stored in .EGA files. In Revision 1, the file format was just 32000 bytes of uncompressed EGA data. In Revision 2 and later revisions, the graphics are compressed with an RLE scheme.
SYS000.EGA | ||
---|---|---|
Revision 1 | Revisions 2–4 | Revision 5 |
Revision 2 slightly shifted the text against the background starfield. | Revision 5 substantially reworked the lettering. |
SYS001.EGA | |
---|---|
Revision 1 | Revisions 2–5 |
Revision 2 slightly shifted the text against the background starfield. |
SYS002.EGA | |
---|---|
Revision 1 | Revisions 2–5 |
Revision 2 slightly shifted the text against the background starfield. |
SYS003.EGA |
---|
Revisions 1–5 |
The interface graphic remained unchanged through all revisions, down to the copyright date. |
Sound
To do: Identify the R5 title theme. Wikipedia claims it is "George Frideric Handel Harpsichord Suite In D Minor, HWV 428, Air" (here is the edit that added the claim), but that appears to be a conflation with the music of the NES port; and a misinterpretation of the cited paper by Gibbons (about the NES port), which says rather "Handel, Aria from Aria with Variations movement of Suite in D minor (no HWV)" (Table 1). |
In Revisions 1–4, the main title theme, screen transition jingle, and game over sound were all riffs on the Marines' Hymn. These three sound effects changed to something else in Revision 5. Revision 5 omits a slow recapitulation of the title theme just before Captain Comic materializes. All other sound effects are the same in every revision.
Revisions 1–4 | Revision 5 | |
---|---|---|
Title | ||
Game start | absent | |
Screen transition | ||
Game over |
Revision 5 is more in tune than earlier revisions. Captain Comic uses the PC speaker and so cannot set precise frequencies; it can only use frequencies of the form 1193182 / d, where d is a 16-bit integer. Revision 5 chooses d to get a close approximation of twelve-tone equal temperament, while earlier revisions only get close to the nearest integer frequency.
note | true frequency | R1–R4 | R5 | ||
---|---|---|---|---|---|
divisor | frequency (error) | divisor | frequency (error) | ||
C3 | 130.813 Hz | 2394 | 131.004 Hz (+2.53 cents) | 23a1 | 130.817 Hz (+0.06 cents) |
D3 | 146.832 Hz | 1fb5 | 146.998 Hz (+1.95 cents) | 1fbe | 146.835 Hz (+0.03 cents) |
E3 | 164.814 Hz | 1c3f | 165.009 Hz (+2.05 cents) | 1c48 | 164.804 Hz (−0.10 cents) |
F3 | 174.614 Hz | 1aa2 | 175.005 Hz (+3.87 cents) | 1ab1 | 174.621 Hz (+0.06 cents) |
G3 | 195.998 Hz | 17c8 | 195.989 Hz (−0.08 cents) | 17c8 | 195.989 Hz (−0.08 cents) |
A3 | 220.000 Hz | 1530 | 219.982 Hz (−0.14 cents) | 1530 | 219.982 Hz (−0.14 cents) |
B3 | 246.942 Hz | 12df | 246.984 Hz (+0.30 cents) | 12e0 | 246.933 Hz (−0.06 cents) |
C4 | 261.626 Hz | 11ca | 262.007 Hz (+2.53 cents) | 11d1 | 261.605 Hz (−0.13 cents) |
D4 | 293.665 Hz | 0fdf | 293.670 Hz (+0.03 cents) | ||
E4 | 329.628 Hz | 0e24 | 329.608 Hz (−0.10 cents) | ||
F4 | 349.228 Hz | 0d59 | 349.190 Hz (−0.19 cents) | ||
F♯4 | 369.994 Hz | 0c99 | 369.979 Hz (−0.07 cents) | ||
G4 | 391.995 Hz | 0be4 | 391.978 Hz (−0.08 cents) | ||
A4 | 440.000 Hz | 0a98 | 439.964 Hz (−0.14 cents) | ||
B4 | 493.883 Hz | 0974 | 493.050 Hz (−2.92 cents) | 0974 | 493.050 Hz (−2.92 cents) |
C5 | 523.251 Hz | 08e9 | 523.096 Hz (−0.51 cents) | 08e9 | 523.096 Hz (−0.51 cents) |
D5 | 587.330 Hz | 07f1 | 586.907 Hz (−1.25 cents) | 07f1 | 586.907 Hz (−1.25 cents) |
E5 | 659.255 Hz | 0713 | 658.853 Hz (−1.06 cents) | ||
F5 | 698.456 Hz | 06ad | 698.176 Hz (−0.70 cents) | ||
G5 | 783.991 Hz | 05f2 | 783.957 Hz (−0.08 cents) | ||
A5 | 880.000 Hz | 054b | 880.577 Hz (+1.14 cents) |
Code
Code Changes in Revision 2
Moves some variables to before the program entry point.
The variables are preceded by a stub jmp main
, which is unused
because the EXE header already points at main
.ref
Adds a check that the game's custom interrupt handlers were properly installed. It does this by adding a special function to INT 3 (which otherwise controls the sound) to tweak a global variable. The game invokes INT 3 and checks that the global variable is tweaked as expected. However the failure branch of the check seems to be in error in this revision. Intead of exiting the program, it jump directly to the title screen, skipping the startup notice.ref
Fleshes out the startup notice and pauses to let you read it.ref
Adds a definable keymap and an interface for configuring it. The keymap is loaded from the file KEYS.DEF if present; otherwise it defaults to the Revision 1 keys.ref
Fullscreen graphics are now RLE-compressed, and their loading moved into a subroutine instead of being inlined where needed.ref Loads the high scores background from the FILE SYS005.EGA instead of storing it in the executable.ref
Preserves the sound mute status through the landing sequence. In Revision 1, if you pressed F2 to mute the sound during the title, it would be unconditionally unmuted after awarding the player their initial stock of lives.ref
Adds a check on the initial number of lives that leads to the unused instant-win mode.ref
Removes a check for an unused −1 value of an internal sound-control variable.ref
If the COMIC.HGH file cannot be opened, loads a default empty high scores table instead of terminating.ref
Code Changes in Revision 3
The startup notice changes Revision 2
to Revision 3
; Copyright 1988
to Copyright 1988, 1989
; and begin.
to begin
.ref
You can now press Esc to quit from the startup screen. Previously, Esc acted as an "any other key" to start the game.ref
The code that reads a keypress during keyboard setup moves into a subroutine, which also clears the BIOS keyboard buffer after every input, instead of doing it once at the end. Disables interrupts in some, but not all, places where the BIOS keyboard buffer is cleared after reading a keypress.ref
You can now map the Del key (scancode 53) during keyboard setup. In Revision 2, an off-by-one bug meant you could only map up to Ins (scancode 52).ref
The interrupt handler for IRQ 1 (keyboard events) sets a global variable to the scancode of the most recent key event. In Revision 2, the variable represents the most recent key release, but in Revision 3, it represents the most recent key press.ref You can see the difference easily in the keyboard setup menu by pressing and holding a key. In Revision 2, the key is not assigned until you release the key. In Revision 3, it is assigned as soon as you press it. The press/release change also allowed removing a hack that called the key-mapping subroutine once, before even showing the keyboard setup menu, simply to eat the K key event that would otherwise be immediately assigned to "Move Left".ref You can see an artifact of this hack in Revision 2 using the fact that the key-mapping subroutine does not return until you have released a key that is not currently mapped to one of the game actions. At the startup screen, press and hold K. While it is being held, press and release another key. Any key will advance the screen except for those that are mapped by default (Left, Right, Space, Ins, Alt) and other keys that the key-mapping subroutine handles as special cases (Esc and any scancode above Ins). Caps Lock works to advance the screen, even though it is by default mapped to "Teleport", because the subroutine doesn't check that particular mapping. The keyboard-mapping subroutine has the side effect of printing "K " to the screen, but it is not noticeable because the screen is cleared immediately after.
After being paused with Esc, the game no longer unpauses until Esc is released.ref In Revision 2, holding Esc would cause the game to flicker paused and unpaused, and could get in an inverted state where pressing Esc would unpause and releasing it would pause.
Fixes the hover glitch. There is a variable (call it comic_jump_counter
) that tracks the height of a player's jump. The variable is set to 4 (if you don't have the Boots) or 5 (if you do) whenever the player stands on solid ground, in preparation for a jump. comic_jump_counter
counts down during every game tick that the player is jumping, and when it reaches 1, the player stops accelerating upward. In Revision 2, comic_jump_counter
gets initialized to 0 when the player spawns at the start of the game or after dying. If you jump on the first possible frame, it skips past the sentinel value of 1 and underflows to ff, allowing you to keep the jump going for 255 ticks. Revision 3 fixes the bug by initializing comic_jump_counter
to 4 instead.ref The fix still leaves a minor bug: a first-frame jump will be as high as if you did not have the Boots, even if you do have them.
Jumps work differently under low ceilings. The following graphic compares identical jumps in Revision 2 (left) and Revision 3 (right). Formerly, Captain Comic couldn't jump at all in two-tile-high corridors; now, he can push a half a tile into the ceiling, just as in taller corridors. Comic also sticks to the ceiling longer, instead of quickly bouncing off.ref The top of the screen is not considered an actual ceiling, and jumps that clip to the top of the screen haven't changed.
Code Changes in Revision 4
The startup notice changes Revision 3
to Revision 4
, removes the promise to send registered users the question hotline phone number, changes the mailing address, and adds a prompt to press J to configure the joystick.ref
Adds joystick play using the BIOS's native joystick support.ref
Code Changes in Revision 5
Replaces the unused jmp main
stub with
an unused copyright notice.ref
Makes the program exit if the game's custom interrupt handlers cannot be installed, instead of jumping to the title screen.ref
The startup notice announces the availability of
Captain Comic Episode II: Fractured Reality
and registration details are moved to a separate screen.
Inlines the display_xor_decrypt
subroutine.ref
Shifts the text in the keymap configuration one space to the left.ref
Overhauls how joystick handling works. Installs a custom INT 21 handler to replace the BIOS's native joystick support.ref Does a CPU speed test on startup to determine how many times to poll the joystick on each tick.ref
Changes the joystick axis thresholds, seemingly with a bug in the left and up directions.ref In Revision 4, the thresholds were 50% of the way between the zero and extreme values for left and right, and 75% of the way for up and down:
joystick_x_low = 1/2 * joystick_x_zero + 1/2 * extreme_left joystick_x_high = 1/2 * joystick_x_zero + 1/2 * extreme_right joystick_y_low = 1/4 * joystick_y_zero + 3/4 * extreme_up joystick_y_high = 1/4 * joystick_y_zero + 3/4 * extreme_down
In Revision 5, the threshold is changed to 50% in the up and down directions, but also a sign is flipped in the left and up directions, making them no longer represent a weighted average of the zero and extreme values:
joystick_x_low = 1/2 * joystick_x_zero - 1/2 * extreme_left joystick_x_high = 1/2 * joystick_x_zero + 1/2 * extreme_right joystick_y_low = 1/2 * joystick_y_zero - 1/2 * extreme_up joystick_y_high = 1/2 * joystick_y_zero + 1/2 * extreme_down
Joystick inputs now count as keypresses for the purpose of advancing through the title cards.ref
Saves the video mode on startup and restores it on exit, instead of unconditionally restoring mode 2.ref
Saves the es
register in the wait_for_keypress
subroutine.ref
Reorders how the title sequence graphics are loaded and displayed.ref
The time the title screen is displayed is increased from 10 ticks to 14 ticks.ref
Clears the BIOS keyboard buffer in fewer places.ref
Uses an auxiliary global variable to pass the size argument into the RLE decoding subroutine. Doubles the size of the RLE decoding buffer.ref
Revises the double buffer handling to wait for vsync, and swap only the high byte of the video start offset pointer.ref
No longer plays a recapitulation of the title music before beaming in.ref
Zeroes Comic's health before respawning him and filling up his health again. In earlier revisions, the game would fill Comic's health and overcharge the health meter if it did not begin empty. This would award points, the same as if you had collected a Shield while at more than zero health.ref
No longer decrypts and displays an empty string when exiting.ref
Removes a block of unused bytes that may be an unused sound,
and adds the unused strings sys006.ega
and sys007.ega
.ref
Unused Map Tiles
Unused Text
- Unused in every revision:
File error
- The program simply terminates whenever it detects a file error and does not display this string.
- Unused in Revision 1:
sys005.ega
- This would be the filename of the high scores graphic, but in Revision 1, the graphic is stored in the executable, not in a separate file.
- Unused in Revision 5:
sys006.ega
,sys007.ega
- These strings follow the naming convention of fullscreen graphics, but are never referenced.
- Unused in Revision 5:
\n\r\n\rCaptain Comic I - Planet of Death, Version SH1.0\n\rCopyright 1990 by Michael A. Denio\n\r
- This string appears at offset 0000 in the executable, before the address where execution begins. It is never used or displayed. The year 1990 lies between the release dates of Revision 4 (October 20, 1989) and Revision 5 (July 10, 1991).
Revisions 2 and later display a copyright screen in text mode, before switching to graphics mode for the game. The text of the screen is XOR-obfuscated in the executable. Revision 1 also has such a screen, but the program doesn't wait for a keypress before entering graphics mode, so you never get to see it. Its unobfuscated contents are:
The Adventures of Captain Comic\r\n Copyright (c) 1988 by Michael Denio\r\n
Unused Sound
In Revisions 1 through 4, there is a block of 24 unused bytes just after the title recapitulation sound effect. The unused bytes vaguely resemble a sound effect, except that they use a frequency divisor of 0001 instead of 0028 to indicate a rest. If it is a sound effect, this is what it would sound like. It's a 1193.182 Hz tone played three times.
Unused Graphics Masks
The icons at the bottom of the screen that indicate the number of lives remaining have transparency masks, but the subroutine that draws them does not use the masks, instead rendering them as fully opaque. The difference is imperceptible in the game, because the would-be transparent pixels are the same color as the background over which they are drawn.
Graphics with masks | Graphics without masks |
---|---|
Unused Instant-Win Mode
Just after counting up the player's initial stock of lives, the game checks whether the number of lives is exactly 4. If so, gameplay continues as normal; but if not, the game starts a timer to warp to the ending sequence after approximately 200 game ticks. It's the same timer that gets set after the player collects the last of the three treasures to win the game, but in that case, the timer is set to 20, not 200. There does not appear to be any way to change the initial number of lives short of hacking the game executable, so the code goes unused. The instant-win check is missing in Revision 1, but present in all later revisions.
Video of the effect in action in Revision 5.
; Disassembly of the relevant code in Revision 5. Starts at offset ; 0x4f0 in the unpacked executable (exclusive of the MZ header). 2ea05e00 mov al, byte cs:[sound_is_enabled] 50 push ax ; save sound mute status b80200 mov ax, SOUND_MUTE cc int3 ; call sound control subroutine b90500 mov cx, MAX_NUM_LIVES ; loop 5 times .loop: b80100 mov ax, 1 e8c800 call wait_n_frames ; wait 1 tick between each life awarded 51 push cx ; gain_a_life uses cx e8291c call gain_a_life 59 pop cx e2f3 loop .loop b80300 mov ax, SOUND_STOP ; stop the extra life sound that is playing but muted cc int3 58 pop ax 2ea25e00 mov byte cs:[sound_is_enabled], al ; restore the saved sound mute status b80300 mov ax, 3 e8b200 call wait_n_frames ; wait 3 ticks before subtracting the initial life e8571c call lose_a_life 803e460004 cmp byte [comic_num_lives], MAX_NUM_LIVES - 1 ; player has 4 lives? 7405 je .num_lives_ok ; always true c606fdd3c8 mov byte [win_timer], 200 ; win after 200 frames .num_lives_ok: e9a205 jmp load_new_level
Unused F3 and F4 Keys
The F1 and F2 keys enable and disable sound. The game also checks F3 and F4, and even has variables devoted to tracking their stateref, but does not use these two keys for anything. In Revision 1, it works somewhat differently, and there is a flat array tracking the state of all keys from LAlt (scancode 38) to Ins (scancode 52) inclusive, which encompasses many unused keys including F3–F10.
- Pages missing developer references
- Games developed by Michael A. Denio
- DOS games
- Pages missing date references
- Games released in 1988
- Games released in May
- Games released on May 1
- Games with unused code
- Games with hidden developer credits
- Games with unused graphics
- Games with unused sounds
- Games with unused text
- Games with revisional differences
- Pages missing publisher info
- To do
Cleanup > Pages missing date references
Cleanup > Pages missing developer references
Cleanup > Pages missing publisher info
Cleanup > To do
Games > Games by content > Games with hidden developer credits
Games > Games by content > Games with revisional differences
Games > Games by content > Games with unused code
Games > Games by content > Games with unused graphics
Games > Games by content > Games with unused sounds
Games > Games by content > Games with unused text
Games > Games by developer > Games developed by Michael A. Denio
Games > Games by platform > DOS games
Games > Games by release date > Games released in 1988
Games > Games by release date > Games released in May
Games > Games by release date > Games released in May > Games released on May 1