17

I have been investigating the MS-DOS port of the C64's Maniac Mansion game. The original MS-DOS port used the C64-specific character map to draw the various backgrounds in the game. I noticed that each background (i.e. room) has 4 colours.

These four values appear to be read as colours within the ScummVM source code:

void GdiV1::roomChanged(byte *roomptr) {
for (int i = 0; i < 4; i++){
    _V1.colors[i] = roomptr[6 + i];
}

For each room in the game, the first 3 colours always fall within the range of 0x00 and 0x15, corresponding to the original C64 colour palette. For most of the other rooms, the fourth colour almost always falls in this range with a few exceptions.

Originally I assumed the C64 game was running in Multicolor Character Mode. This matched other sources:

This is purely done in multicolor character graphics

If the game runs on the C64 in the Multicolor Character Mode I expect the first 3 colours to be used as the common colours across all characters.

I loaded up Maniac Mansion on the Vice emulator to check the memory settings via the built in monitor tool (ALT+M on Windows). I checked the memory at these addresses:

enter image description here

I was expecting these two addresses to show that the game is running in Multicolor Character Mode:

D011: $7C  0111 1100  
D016: $51  0101 0001  

Using the following source it looks like the following is enabled:

  • Extended Background Color Mode (bit 6 set in D011)
  • Standard Bitmap Mode (bit 5 set in D011)
  • Multicolor Bitmap Mode (bit 4 set in D016)

Assuming the bit numbers are counted in this order:

7 6 5 4 3 2 1 0

In the same source this is known as Extended Background Color Multicolor Bitmap Mode. Refer to mode 7 in the table. The following is stated:

Modes 5-7 are technically feasible, but considered illegal. Although the features expected of modes 5-7 are present (such as collision detection), there is no visible screen output for the user. It is for this reason that they are not utilised.

I checked the addresses for the 3 common background colours:

D021: $16  0001 0110 
D022: $26  0010 0110 
D023: $FB  1111 1011

As you can see, these bytes do not fall within 0x00 to 0x15, nor do they actually correspond to the same values I am reading in the DOS port.

According to this article, the screen switches between 2 character sets to display text on screen:

Another thing of note is that the C64 supports two different character sets (2×256 Characters) and that the second character set consists of a common font, including the inventory arrows. This is one of the reasons that there is no text in the main game screen – they use the second (font) character set for the title line, switch to the primary set to draw the screen, then back to the secondary set for the menu at the bottom.


I want to know if I am using the correct method to determine the graphic mode for the game in question.

Ultimately I want to understand how the room's 4th colour is actually applied.


I have used additional sources to map the C64 memory as well as which addresses I need to check.

  • 3
    VICE maybe showing you the RAM that lives "underneath" the device I/O region where the VIC-II chip is mapped. Also it looks from the screen shot the game switches modes, using standard character mode for the top line and one of the multicolour colour modes for the rest. – Ross Ridge Nov 17 '17 at 1:26
  • 3
    It's doing more than just switching fonts, it's also switching modes. The top line uses the C64's standard 8x8 font which only works (unscaled) in either standard character or standard bitmap mode. On the other hand the Manic Mansion logo uses three colours (four if you count the word "START", but that could be a sprite) and double width pixels, which means it's almost certainly using either multicolor character or multicolor bitmap mode. – Ross Ridge Nov 17 '17 at 1:56
  • 1
    In VICE debugger, try using the following command: io $d000. If it wouldn't help, it will at least show VIC config in more readable way than digging hex dumps. – lvd Nov 17 '17 at 6:39
  • 2
    @RossRidge You can mix multicolor characters and hires characters, but then you lose half the possible colours which is a pain (because one colour bit is used to toggle the interpretation of the character). I made a game for 2016 7DRL challenge which did exactly that. (dropbox.com/s/fiqwmy9qzm1oz9n/monsters.png?dl=0) – tylisirn Nov 18 '17 at 17:48
  • 3
    @camelCase, note that gfx mode can be switched during the ray scanning time. It is a routine practice on C64 to have line interrupts and switch all the things including gfx mode. – lvd Nov 18 '17 at 23:51
7

I downloaded the ScummVM source code, and debugged any section of code that read from this "4th colour". It appears that before it reads the 4th colour it is overwritten (in a way that appears to match the block of colour ram used in C64's Multicolor Character Mode):

void GdiV1::drawStripV1Background(byte *dst, int dstPitch, int stripnr, int height) {
    int charIdx;
    height /= 8;
    for (int y = 0; y < height; y++) {
        _V1.colors[3] = (_V1.colorMap[y + stripnr * height] & 7); // overwrite
        // Check for room color change in V1 zak
        if (_roomPalette[0] == 255) {
            _V1.colors[2] = _roomPalette[2];
            _V1.colors[1] = _roomPalette[1];
        }

        charIdx = _V1.picMap[y + stripnr * height] * 8;
        for (int i = 0; i < 8; i++) {
            byte c = _V1.charMap[charIdx + i];
            dst[0] = dst[1] = _V1.colors[(c >> 6) & 3];
            dst[2] = dst[3] = _V1.colors[(c >> 4) & 3];
            dst[4] = dst[5] = _V1.colors[(c >> 2) & 3];
            dst[6] = dst[7] = _V1.colors[(c >> 0) & 3]; // read _V1.colors[3]
            dst += dstPitch;
        }
    }
}

The same occurs here:

void GdiV1::drawStripV1Object(byte *dst, int dstPitch, int stripnr, int width, int height) {
    int charIdx;
    height /= 8;
    width /= 8;
    for (int y = 0; y < height; y++) {
        _V1.colors[3] = (_V1.objectMap[(y + height) * width + stripnr] & 7); // overwrite
        charIdx = _V1.objectMap[y * width + stripnr] * 8;
        for (int i = 0; i < 8; i++) {
            byte c = _V1.charMap[charIdx + i];
            dst[0] = dst[1] = _V1.colors[(c >> 6) & 3];
            dst[2] = dst[3] = _V1.colors[(c >> 4) & 3];
            dst[4] = dst[5] = _V1.colors[(c >> 2) & 3];
            dst[6] = dst[7] = _V1.colors[(c >> 0) & 3]; // read _V1.colors[3]
            dst += dstPitch;
        }
    }
}

In terms of the ScummVM emulator, the 4th colour found in the data files is never actually used.

That answers my original question: Ultimately I want to understand how the room's 4th colour is actually applied.

In regards to I want to know if I am using the correct method to determine the graphic mode for the game in question.:

I have used the suggestions in the comments and managed to get meaningful values by using the io command:

(C:$d040) io $d000
VIC-II:
>C:d000  00 fd 00 fd  00 fd 00 fd  00 fd 00 fd  00 fd 27 45   ..............'E
>C:d010  00 9b 37 00  00 ff c9 00  3f 74 f1 00  7f 00 ff 00   ..7.....?t......
>C:d020  f0 f0 fe fa  f1 fa f0 f1  f2 f3 f4 f5  f6 f7 fc ff   ................
>C:d030  ff ff ff ff  ff ff ff ff  ff ff ff ff  ff ff ff ff   ................

Rasterline:   current: 0 IRQ: 41
Display Mode: Standard Hires Text
Colors:       Border:  0 Background:  0
Scroll X/Y:   1/3
Screen Size:  40 x 25

VIC Memory Bank:   $c000 - $ffff

Video Memory:      $cc00
Character Set:     $f800

Sprites:
           Spr.0  Spr.1  Spr.2  Spr.3  Spr.4  Spr.5  Spr.6  Spr.7
Enabled:     yes    yes    yes    yes    yes    yes    yes    yes
Pointer:     $bc    $bd    $be    $bf    $c0    $00    $c0    $c1
Address:   $ef00  $ef40  $ef80  $efc0  $f000  $c000  $f000  $f040
X-Pos:         0      0      0      0      0      0      0     39
Y-Pos:       253    253    253    253    253    253    253     69
X-Expand:     no     no     no     no     no     no     no     no
Y-Expand:     no     no     no     no     no     no     no     no
Priority:    spr    spr    spr    spr    spr    spr    spr    spr
Mode:       muco   muco   muco   muco   muco   muco   muco    std
Color:         1      2      3      4      5      6      7     12
Multi Color 1: 10  Multi Color 2: 0

I'm not sure why there is a different compared to reading the values directly from the memory compared to using the io command. Regardless, the io command allowed me to confirm that 3 of the 4 colours found in the data files is being applied.


Update

Ross Ridge added the following comment to explain the differences seen when reading the values directly from the memory compared to using the io command:

If you'll look at the memory map you linked you'll see that one of three different things can be mapped into the $D000 to $DFFF address range: "I/O Area (memory mapped chip registers), Character ROM or RAM area (4096 bytes); depends on the value of bits #0-#2 of the processor port at memory address $0001". Rather than showing you what the CPU currently sees mapped into that range, the VICE debugger may simply be showing the RAM that can be mapped into that range.

  • Add the other comments have mentioned, you can't look at the io registers in an 'instant' because, depending on where the scan-line was when the snapshot was taken, may give different results. – Neil Sep 14 '18 at 7:40

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.