apple2_gumball/README.md

1205 lines
22 KiB
Markdown
Raw Permalink Normal View History

2018-04-19 17:07:14 +00:00
Revised: April 19, 2018
# Gumball Easter Eggs
# Table of Contents
* Introduction
* Pre-requisites
* In-game Hints
* Long Lost Gumball Source Code!
2018-04-19 17:16:21 +00:00
* Fragment GB.1.a
* Fragment GB.1.b
* Fragment GB.1.c
* Fragment GB.1.d
* Fragment GB.1.e
* Fragment GB.1.f
* Dump Listing
* Fragment GB.1.All
* Fragment GB.2
* Dump Symbols
* Fragment GB.2.All
* Fragment GB.3.a
* Fragmnet GB.3.b
2018-04-19 17:37:18 +00:00
* Fragment GB.3.All
2018-04-19 17:07:14 +00:00
* Hints Revisited
* Hall of Fame
2018-04-19 17:16:21 +00:00
* Credits
2018-04-19 17:07:14 +00:00
* Job Titles
* Secret in-game end message
2018-04-19 17:39:02 +00:00
* Conclusion
2018-04-19 17:07:14 +00:00
* Appendix A: Sector Interleave
# Introduction
I don't know what it is about Apple 2 games
but I love using a sector editor viewing
every track and sector for easter eggs. I guess
it is the thrill of (re)discovering something
that hasn't been seen in 20 - 40 years that
has been seen only by the author.
Today we'll discover some easter eggs hidden
in Br0derbund's "Gumball". A regular player
2018-04-19 17:17:16 +00:00
will _never_ see these since they are never shown (aside from the hints.)
2018-04-19 17:07:14 +00:00
They are "remnants" left over from the build process.
And the only way to view them is to either
* view memory
* view the disk contents
We'll be using a "cracked" copy -- specifically
games that have been converted over to a standard
Track/Sector format. We'll also be using a sector
2018-04-19 18:06:04 +00:00
editor -- "Copy ][ Plus" as it is the standard 'go to tool'.
2018-04-19 17:07:14 +00:00
2018-04-19 17:55:17 +00:00
# Pictures
Here is what we'll be looking at:
2018-04-19 17:56:17 +00:00
* ![source_3a.png](source_3a.png)
2018-04-19 17:55:17 +00:00
* ![source_3b.png](source_3b.png)
2018-04-19 17:07:14 +00:00
# Pre-requisites
There are few different cracked versions out there.
We'll use these disks:
* [gumball_fixed](ftp://ftp.apple.asimov.net/pub/apple_II/images/games/action/gumball-fixed.zip)
* [Gumball (4am & san inc crack)](ftp://ftp.apple.asimov.net/pub/apple_II/images/games/)
4am's version is the most "pristine" -- he only
removes the copy protection scheme and keeps
_everything_ else in-tact. We even have his
cracking notes to follow along and verify!
I'll also be using another version since it
will be curious if other crackers kept everything
or not.
# In-game Hints
4am, T02SB
We have a strange 24 character string:
```
1B:_____ ________ __FIG YRJMYR<FF>
```
Instead of C's ASCIIZ we have ASCIIFF where FF is the end sentinel.
This is actually in-game hint #4 (using a subtituion chipher)
```YOU RETIRE```
4am has documented all of those in his notes:
* "Gumball (4am & san inc crack).txt"
The remaining hints have a lookup table on T12/S4/@AA
```
$FB2
$FD4
$FF6
$1014
```
Note: The strings are not null terminated but $FF terminated.
| Hint | Location | Memory |
|:-------------:|:---------:|:------:|
| `RBJRY JSYRR` | T12S4 @B2 | $0FB2 |
| `VRJJRY ZIAR` | T12S4 @D4 | $0FD4 |
| `ESRB` | T12SB @F6 | $0FF6 |
| `FIG YRJMYR` | T12SB @14 | $1014 |
For some reason the last hint is duplicated on T02SB which
is located in memory @ $101B ?
And now for something completely different ...
# Long Lost Gumball Source Code!
No, this isn't the _entire_ source code -- only fragments of it.
Still let's see what treasure we can "mine" by "spelunking."
## Fragment GB.1.a
2018-04-19 21:12:21 +00:00
I'm going to use the nomenclature and call these
source code fragments `GB.#._` -- i.e. GB.1.a, GB.2.b, etc.
2018-04-19 17:07:14 +00:00
Since we have two disk images:
* I'll prefix `4am's` DSK image with `4am`, and
* I'll prefix `Gumball Fixed` DSK image with 'Fix'.
Here is the track/sector infor for the first fragment.
* 4am, T3S0
* Fix, T2S0
The first fragement is an assembler header block!
```asm
;
;
;
;
;
; --------------------------------
; < <
; < "BLOCK2" <
; < <
; < TABLES AND BLOCK SHAPES <
; < <
; < ROBER
```
It is continued on:
4am, T03S7
Fix, T02S7
```asm
; T COOK <
; < <
; --------------------------------
;
;
;
;
;
;
; GUMBALL TITLE BLOCK
;
;
;
;
;
; GUMBALL
d 280000000
d 0000000000000000
d 0000000000000000
d 0000000000000000
d 00000A2800000000
d 0
```
**NOTE:**
* I'm leaving out the control characters,
* It looks like $13 is used to represent a TAB ($09) char?
This is continued on either T03S4, T03SC, or T03SE.
But which is one is correct?
## Fragment GB.1.b
4am, T03S4
Fix, T02S4
Let's padd the front with space(s) to align
the text.
```asm
F7F837F8360FF81 (1) @00
d 000A28703F80E67F (2) @11
d FC0FE0FFF83FFE7F (3) @25
d F37F787F7F0FFE5F (4) @39
d FF077F8360FF8100 (5) @4D
d 0A28703F80667FFC (6) @61
...
d 7F0360FF81000A28
```
Now we're going to "cheat" -- that is: _"Work smarter not harder"_
Searching for `FC 0F E0 FF` the raw bytes on line 3 can be found at:
* 4am, T7S5 @4C
* Fix, T5S1 @4C
2018-04-19 21:15:03 +00:00
From this we can deduce ~three~, ~four,~ nay, five, things:
2018-04-19 17:07:14 +00:00
* We know the first digit should be `7`,
* That rules out Sectors $4 and $E, leaving Sector $C,
* We _must_ verify our assumptions,
* We can start to see the sector interleaving table,
* Even if we _weren't_ able to find the raw hex bytes on disk we
could have assumed that Sector $E followed from Sector $7 by
inspection and noticing the run of zeroes.
## Fragment GB.1.c
Making a table of what we have so far:
| Sector | Mem |
|:-:|:-----:|
| 0 | $1800 |
| 7 | $1900 |
| : | : |
| C | $?000 |
| 4 | $?100 |
2018-04-19 18:12:19 +00:00
We'll continue to inspect sector $C
2018-04-19 17:07:14 +00:00
2018-04-19 18:12:19 +00:00
* 4am, T03SC
* Fix, T02SC
2018-04-19 17:07:14 +00:00
```asm
F7F7F3F603C (1) @00
d FF07307E7F01FF07 (2) @0D
d 70FF01000A28707F (3) @21
d 000000781F607F70 (4) @35
d FF7F7F7F3FF0FC7F (5) @49
...
d 7FF773FB87E7F077 (13) @E9
d 7 (14) @FD
```
Without visually inspecting these HGR bytes
it would look like T03S4 is the contination due
to each row being 16 characters.
Why?
Since S3S7 ends with 1 character that means the next
row will only have 15 characters. At first glance T03S4
would fit the bill.
However, we must always _verify_ our assumptions.
That's why we did the `Hex Search` earlier and found
the _actual_ answer was T03SC and *not* our _expected_ T03S4.
An exercise for the reader: "Rip" the sprites from the
startup demo and re-construct the actuall assembly source.
## Fragment GB.1.d
Sector $E looks like the continuation of S0.
```asm
000000000000000 (1) @00
d 0000000000000000 (2) @11
d 0000000000000000 (3) @25
d 000A280000000000 (4) @39
d 0000000000000000 (5) @4D
d 0000000000000000 (6) @61
d 0000000000000000 (7) @75
d 0A28000000000000 (8) @89
d 0000000000000000 (9) @9D
d 0000000000000000 (10) @B1
d 0000000000000000 (11) @C5
d 2800007E0300000F (12) @D9
d 4007007003007C00 (13) @ED
```
| Sector | Mem |
|:-:|:-----:|
| 0 | $1800 |
| 7 | $1900 |
| E | $1A00 |
| : | : |
| C | $?000 |
| 4 | $?100 |
## Fragment GB.1.e
From the above analysis we have enough to put together
a sector interleaving table.
|Logical|Physical|
|:-----:|:------:|
| 0 | 0 |
| 1 | 7 |
| 2 | E |
| 3 | 6 |
| 4 | D |
| 5 | 5 |
| 6 | C |
| 7 | 4 |
| 8 | B |
| 9 | 3 |
| A | A |
| B | 2 |
| C | 9 |
| D | 1 |
| E | 8 |
| F | F |
Let's inspect Sector $6
2018-04-19 18:12:19 +00:00
* 4am, T03S6
* Fix, T02S6
2018-04-19 17:07:14 +00:00
```asm
d 007F0F0000000000 (1) @01
d 7001000F00000A28 (2) @15
:
d 07787C0300660 (13) @F1
```
## Fragment GB.1.f
2018-04-19 18:12:19 +00:00
Moving along,
* 4am, T03SD
* Fix, T02SD
2018-04-19 17:07:14 +00:00
```asm
730 (1) @00
d 7E00000A2800CF7F (2) @05
:
d 0A2860FF7 (13) @F5
```
## Fragment GB.1.All
Here is the the complete sector and memory list for Fragment 1:
| Sector | Mem |
|:-:|:-----:|
| 0 | $1800 |
| 7 | $1900 |
| E | $1A00 |
| 6 | $1B00 |
| D | $1C00 |
| 5 | $1D00 |
| C | $1E00 |
| 4 | $1F00 |
A complete _half of track's worth of data_ is source code!?
The simplest way to save this non-linear data into a linear format
is too boot the game up and inspect memory at the title sequence.
From AppleWin:
2018-04-19 18:10:02 +00:00
* Mount disk
* Press `F2` to re-boot
* Wait for title screen
* Press `F7` to enter the debugger
2018-04-19 17:07:14 +00:00
* `bsave "gumball.fragment.1.1800",1800:1FFF`
## Dump Listing
Here's a C program, [dump_list.c](dump_list.c), to dump the fragment:
```c
// Includes
#include <stdio.h> // printf()
#include <stdlib.h> // malloc()
// Util
size_t FileSize( FILE *file )
{
if( !file )
return 0;
// Yes, this is insecure
// and we should use stat()
// but that isn't available under Windows
fseek( file, 0, SEEK_END );
size_t size = ftell( file );
fseek( file, 0, SEEK_SET );
return size;
}
// Main
2018-04-19 17:27:39 +00:00
int main( const int nArg, const char *aArg[] )
2018-04-19 17:07:14 +00:00
{
const char *name = "gumball.fragment.1.1800";
2018-04-19 17:27:39 +00:00
if( nArg > 1 )
name = aArg[1];
2018-04-19 17:07:14 +00:00
FILE *in = fopen( name, "rb" );
2018-04-19 17:30:26 +00:00
printf( "Filename: %s\n", name );
2018-04-19 17:07:14 +00:00
if( in )
{
size_t size = FileSize( in );
//printf( "Size: %lld\n", size );
if( size )
{
char *buffer = (char*) malloc( size );
int i;
int n = (int) size;
char c;
size_t read = fread( buffer, 1, size, in );
if( read != size )
printf( "ERROR: Only read %lld / %lld bytes\n", read, size );
for( i = 0; i < n; i++ )
{
c = buffer[ i ] & 0x7F;
if( c == 0x0D )
{
printf( "\n" );
c = buffer[ ++i ];
if( (c == 0x13) || (c == 0x0B) )
printf( "\t" );
else
printf( " " );
}
else
if( c < 0x20 )
;
else
printf( "%c", c );
}
free( buffer );
}
fclose( in );
}
else
printf( "ERROR: Couldn't open: '%s'\n", name );
return 0;
}
```
And finally, our moment of truth!
```asm
;
;
;
;
;
; --------------------------------
; | |
; | "BLOCK2" |
; | |
; | TABLES AND BLOCK SHAPES |
; | |
; | ROBERT COOK |
; | |
; --------------------------------
;
;
;
;
;
;
; GUMBALL TITLE BLOCK
;
;
;
;
;
GUMB :
d 28000000
d 0000000000000000
d 0000000000000000
d 0000000000000000
d 00000A2800000000
d 0000000000000000
d 0000000000000000
d 0000000000000000
d 000A280000000000
d 0000000000000000
d 0000000000000000
d 0000000000000000
d 0A28000000000000
d 0000000000000000
d 0000000000000000
d 000000000000000A
d 2800007E0300000F
d 4007007003007C00
d 007F0F0000000000
d 7001000F00000A28
d 00607F1F00601F60
d 0F807C0F007F0370
d 7F7F00401F00007C
d 03603F00000A2800
d 387E3F00203E301E
d 007E3F607F07787F
d 7F03707F00006407
d 70BF80000A28008E
d 7E6700303E301E80
d 737F307E87FC7F7F
d 07787C0300660730
d 7E00000A2800CF7F
d 6700703FF83F40F3
d 7FB87E0FCC7F7F87
d 787C07007E87307E
d 00000A2840FF7F7F
d 00F83FF83FE07F7F
d 797F1F4C7F7F0F78
d 7F0F007E87707F80
d 000A28407F7F7F00
d 983FF83FE0797FFD
d 7F1FFC7F7F0F787F
d 1F007287707F8000
d 0A2860FF7F3F0098
d 3F703FE0797F7F7F
d 3F7C7F7F0F707F3F
d 007287707F01000A
d 28607F871F00183F
d 707F607C7F7F7F3F
d 789FFE0F407F7F00
d F30770FF01000A28
d 70FF810000781F60
d 7F607C7F7F7F3F40
d 3FFC87607F7F80FF
d 0770FF01000A2870
d FF800000781F607F
d 70FF7F7F7F3F603C
d FF07307E7F01FF07
d 70FF01000A28707F
d 000000781F607F70
d FF7F7F7F3FF0FC7F
d 83187F7F81FF8360
d 7F01000A28703F80
d 7007780FE0FF70FF
d 7E7F773FB07E7F81
d 9C7F7F03FF83607F
d 01000A28703F807C
d 3F780FE0FF707F7E
d 7F773FB87E7F077C
d 7F7F837F8360FF81
d 000A28703F80E67F
d FC0FE0FFF83FFE7F
d F37F787F7F0FFE5F
d FF077F8360FF8100
d 0A28703F80667FFC
d 0F407FF83F7C7F63
d 7F785F7F0FFF1F7F
d 877F0360FF81000A
d 28707F007E7FFC0F
d 407FF83F787F617F
d 781F7C1FFF0FFF0F
d 7F0360FF81000A28
```
## Fragment GB.2
On Track $08 we we find more snippets of assembly source:
Fragment GB.2a, T08S4
```
+,ANDPIC V,BALLINDHW,BALLINDLZ,BMINDH ],BMIND
```
This looks like a symbol table.
If we boot the game and again inspect memory at the title
sequence we see that this is loaded into memory at $8400.
We are interested in the snippet from $849a onwards.
The format of the symbol table is this in C:
```c
struct
{
uint8_t name[8];
uint16_t address;
}
```
The first two letters at $849A and $849B got
over-written with zeroes. We can over-write
these 2 end bytes of graphics data with underscores
(`_`) $5F:
* 849A:5F
* 849B:5F
* `bsave "gumball.fragment.2.849a",849a:87FF`
## Dump Symobls
We can modify our `dump_list` converting it to
[dump_sym.c](dump_sym.c) to dump the symbol table:
```c
// Includes
#include <stdio.h> // printf()
#include <stdlib.h> // malloc()
// Util
size_t FileSize( FILE *file )
{
if( !file )
return 0;
// Yes, this is insecure
// and we should use stat()
// but that isn't available under Windows
fseek( file, 0, SEEK_END );
size_t size = ftell( file );
fseek( file, 0, SEEK_SET );
return size;
}
// Main
int main( const int nArg, const char *aArg[] )
{
const char *name = "gumball.fragment.2.849a";
if( nArg > 1 )
2018-04-19 17:30:26 +00:00
name = aArg[1];
FILE *in = fopen( name, "rb" );
printf( "Filename: %s\n", name );
2018-04-19 17:07:14 +00:00
if( in )
{
size_t size = FileSize( in );
//printf( "Size: %lld\n", size );
if( size )
{
char *buffer = (char*) malloc( size );
int src;
int len = (int) size;
size_t read = fread( buffer, 1, size, in );
char name[ 9 ];
if( read != size )
printf( "ERROR: Only read %lld / %lld bytes\n", read, size );
for( src = 0; src < len; )
{
int dst;
for( dst = 0; dst < 8; dst++ )
name[ dst ] = buffer[ src + dst ];
name[ 8 ] = 0;
printf(
"%s EQU $%02X%02X\n"
, name
, (buffer[ src + 9 ] & 0xFF)
, (buffer[ src + 8 ] & 0xFF)
);
src += 10;
}
free( buffer );
}
fclose( in );
}
else
printf( "ERROR: Couldn't open: '%s'\n", name );
return 0;
}
```
## Fragment GB.2.All
Lo and behold!
```asm
__OB EQU $084C
DROP1 EQU $087B
DROP2 EQU $0892
BALLDOOR EQU $08CF
RASEPOLE EQU $08E3
MAKECRS1 EQU $0900
SHOWGUMB EQU $0922
COPYRITE EQU $0948
PRELIM EQU $0978
MAKECRS2 EQU $09A8
SHOWROB EQU $09CE
SHOWDOUG EQU $09F4
GUMBDR EQU $0A30
CROSSDR EQU $0A6B
PLOT EQU $0AB2
POLEUP EQU $0AFC
OPENBALL EQU $0B1B
BALLDRP1 EQU $0B5D
CHUNKPLT EQU $0BA5
BALLSET EQU $0BC5
BALLDRP2 EQU $0BEC
BBPLOT EQU $0C3D
EEPLOT EQU $0C63
ANPLOT EQU $0C89
PRPLOT EQU $0CBD
BBUNPLOT EQU $0CE3
EEUNPLOT EQU $0D07
ANUNPLOT EQU $0D2D
PRUNPLOT EQU $0D58
ROTKNOB EQU $0D7E
PAUSE EQU $0DD5
LPAUSE EQU $0E15
SCRFLIP EQU $0E1F
SCRCLR EQU $0E33
SCRTRANS EQU $0E4C
TRANSOUT EQU $0E6E
TRANSIN EQU $0E90
BLOCK1 EQU $0EB2
BLOCK2 EQU $0EE6
BLOCK3 EQU $0F52
B3LOOP EQU $0F54
MAIN EQU $0F9D
STARTUP EQU $0FD3
YLO EQU $6000
YHI EQU $60C8
KNOBIND EQU $6190
KNOB1 EQU $619A
KNOB2 EQU $62AE
KNOB3 EQU $63C2
KNOB4 EQU $64D6
KNOB5 EQU $65EA
BB EQU $66FE
BRODB EQU $68C5
EE EQU $68C6
ELTE EQU $6A2D
PRE EQU $6A2E
PRES EQU $6B0D
NEWY1 EQU $6B0E
NEWY2 EQU $6B6B
NEWY3 EQU $6BCB
NEWY4 EQU $6C0B
AND EQU $6C2B
ANDPIC EQU $6C56
BALLINDH EQU $6C57
BALLINDL EQU $6C5A
BMINDH EQU $6C5D
BMINDL EQU $6C60
BALL1 EQU $6C63
BALLM EQU $6C99
OBALLIND EQU $6CCF
OBALL1 EQU $6CD9
OBALL2 EQU $6D60
OBALL3 EQU $6DE7
OBALL4 EQU $6E6E
OBALL5 EQU $6EF5
PATH1 EQU $6F7C
PATH2 EQU $6F9A
GUMCHUNK EQU $6FDF
BALL2 EQU $7033
BALL3 EQU $7069
WHTMASK EQU $709F
BYTET EQU $70D5
BLOCKPOS EQU $71D9
DOTS1 EQU $730A
DOTS2 EQU $7311
GUMB EQU $7318
GUMBR EQU $006B
```
4am, Track $8
| Sector | Mem |
|:-:|:-----:|
| D | $8400 |
| 5 | $8500 |
| C | $8600 |
| 4 | $8700 |
Fragment GB.2.a, T08S4
Fragment GB.2.b, T08S5
Fragment GB.2.c, T08SC
Fragment GB.2.d, T08SD
## Fragment GB.3a
There is 3rd fragment on disk!
* 4am, T13S0
* Fix, T11S0
```
;
;
;
;
; -----------------------------
; < <
; < "BLOCK3" <
; < <
; < TABLES AND BLOCK SHAPES <
; < <
; < ROBE
```
## Fragment GB.3.b
It is continued on 4am, T13S7
```
RT COOK <
; < <
; -----------------------------
```
Using our sector interleave table:
2018-04-19 17:33:40 +00:00
|Sector|Fragment|
|:-:|:-:|
| 0 | 1 |
| 7 | 2 |
| E | 3 |
| 6 | 4 |
| D | 5 |
| 5 | 6 |
| C | 7 |
| 4 | 8 |
2018-04-19 17:07:14 +00:00
I still need to track down where this is loaded into memory.
To save this we have three choices:
* Play the game, and inspect memory where this is loaded which is time consuming,
* Manually save this "piece-meal" from `Copy ][+` which is still time consuming, or
* We make a "temp copy" of the game and and over-write the previous fragment 1 with fragment 3.
Let's do the latter:
* Read: T13S0, Write: T3S0
* Read: T13S4, Write: T3S4
* Read: T13S5, Write: T3S5
* Read: T13S6, Write: T3S6
* Read: T13S7, Write: T3S7
* Read: T13SC, Write: T3SC
* Read: T13SD, Write: T3SD
* Read: T13SE, Write: T3SE
Back in AppleWin
* `bsave "Gumball.fragment.3.1800",1800:1FFF`
## Fragment GB.3.All
Using our [dump_list.c](dump_list.c) program:
```asm
;
;
;
;
;
; --------------------------------
; | |
; | "BLOCK3" |
; | |
; | TABLES AND BLOCK SHAPES |
; | |
; | ROBERT COOK |
; | |
; --------------------------------
;
;
[ $5800
;
;
;
;
;
; CROWN PICTURE
;
;
;
;
;
CROWNS :
d 624E624D624C644B
d 644C644D644E664D
d 664C664B664A684A
d 684B684C6A4C6A4B
d 6A4A6A496C496C4A
d 6C4B6E4B6E4A6E49
d 7049704A704B724B
d 724A72497449744A
d 744B764B764A7649
d 7849784A784B784C
d 7A4C7A4B7A4A7C4A
d 7C4B7C4C7C4D7E4E
d 7E4D7E4C7E4B804C
d 804D804E824F824E
d 844E824D824C844D
d 824B844C864C864B
d 844B844A864A8649
d 8449824982488448
d 8447824782468446
d 8445824580458044
d 8244824380438042
d 8242824180417E41
d 7E408040803F7E3F
d 7E3E803E803D7E3D
d 7C3D7C3C7C3B7E3C
d 7E3B7E3A7E398038
d 8039803A823A8239
d 8238823784378438
d 8439863986388637
d 8636883688378838
d 8A388A378A368C36
d 8C378C388E388E37
d 8E36903690379038
d 9239923892379236
d 943794389439963A
d 9639963896379838
d 9839983A9A399A3A
d 9C3B9A3B9C3C9C3D
d 9A3C9A3D983D983E
d 9A3E9A3F983F9840
d 9A409A4198419641
d 9642984298439643
d 9644984498459645
d 9445944696469647
d 9447944896489649
d 94499249924A944A
d 924B924C944B964B
d 944C964C944D944E
d 964F964E964D984C
d 984D984E9A4E9A4D
d 9A4C9A4B9C4A9C4B
d 9C4C9C4D9E4C9E4B
d 9E4AA049A04AA04B
d A04CA24BA24AA249
d A449A44AA44BA64B
d A64AA649A849A84A
d A84BAA4BAA4AAA49
d AC49AC4AAC4BAE4C
d AE4BAE4AAE49B04A
d B04BB04CB24AB24B
d B24CB24DB44EB44D
d B44CB44BB64EB64D
d B84FB84EB64CB84D
d BA4EBA4DB84CBA4C
d BC4CBC4BBA4BB84B
d BA4ABC4ABC49BA49
d B849B848BA48BA47
d B847B846BA46BA45
d B845B645B644B844
d B843B643B642B842
d B841B641B441B440
d B640B63FB43FB43E
d B63EB63DB43DB23D
d B23CB43CB43BB23B
d B23AB43AB439B239
d B238B039B237B236
d B036B037B038AE38
d AE37AE36AC36AC37
d AC38AA38AA37AA36
d A836A837A838A638
d A637A636A436A437
d A4
```
# Hints revisted
4am ,T0DS3 has this message:
```
PRESS CTRL-Z DURING THE CARTOONS
```
# Hall of Fame
T11S2 has the High Score headers
```
----------------------------------------
ALL TIME CHAMPSIONS OF GUMBALL
# INITIALS SCORE LEVEL
--- ---------- ------- -------
```
## Credits
The end of the credits is:
4am, T11S3, @ 00
```
. STAUB
JIM KASSENBROCK U.C.B.C.
AND ALL OF THE AMAZING PEOPLE AT
BR0DERBUND
```
The first half of the credits is the following sector:
4am, T11S4, @BE
```
>>>>>>>> CREDITS <<<<<<<<
THE FOLLOWING PEOPLE HAD SOMETH
```
4am, T11SB @00
```
THING TO DO WITH
```
# Job Titles
T11SC
```
WORKER
FOREMAN
SUPERVISOR
MANAGER
VICE PRESIDEN
```
# Secret in-game end message
We see another hint:
4am, T12S7 @87
```
DOUBLE HELIX
```
Here we see the congratulations screen T12S7 @DD ...
```
AHA! YOU MADE IT!
EITHER YOU AR
```
... continued on T12SE ...
```
E AN EXCELLENT GAME-PLAYER
OR (GAH!) PROGRAM-BREAKER!
YOU ARE CERTAINLY ONE OF THE PEOPLE
THAT WILL EVER SEE THIS SCREEN.
THIS IS NOT THE END, THOUGH.
IN ANOTHER BR0DERBUND PRODUCT
TYPE 'Z0DWARE' FOR MORE PUZZLES.
HAVE FUN! BYE!!
________________
```
(I've displayed the spaces with underscores for the last line.)
... and concluded on T12S6
```
R.A.C.
```
I discovered this back in the mid 80's. I never documented
since I figured that if _I_ had used a sector editor to
see it, **surely** someone else would have.
Who knew that it was never publically announced.
DOH!
Oh well, it's been 20 years of fun knowing about these hidden treasures!
2018-04-19 17:39:02 +00:00
# Conclusion
Who knew that a WHOLE Track+ (20 sectors) of source was on disk!
2018-04-19 17:43:09 +00:00
Now if only we could figure out where that `Z0DWARE` easter egg is ...
2018-04-19 17:39:02 +00:00
2018-04-19 17:07:14 +00:00
# Appendix A: Sector Interleave
Here is a translation table to map logical sectors to physical sectors and vice versa.
NOTE: Copy ][+ reads physical sectors.
|Logical|Physical|
|:-----:|:------:|
| 0 | 0 |
| 1 | 7 |
| 2 | E |
| 3 | 6 |
| 4 | D |
| 5 | 5 |
| 6 | C |
| 7 | 4 |
| 8 | B |
| 9 | 3 |
| A | A |
| B | 2 |
| C | 9 |
| D | 1 |
| E | 8 |
| F | F |
Revisions
* Sept 24, 2017
* April 18, 2018
* April 19, 2018