Memory

Date: 2019-12-26 01:34:55


Download


Memory is an open source (C source, BASIC source) text based game written in C that compiles for the Color Computer, Linux, macOS, and Windows. It is an adaption of the classic solitaire card game Concentration.

You can find build instructions in the README.md file.


YouTube Video

Memory is played with a standard deck of 52 cards. Cards include thirteen ranks numbered 2-10 (T for 10) jack (J), queen (Q), king (K) and ace (A), in each of the four suites:

clubs (C), diamonds (D), hearts (H), and spades (S).

You flip cards over two at a time. If the rank matches (the suite does not need to) you leave the cards face up and chose another two. If they do no match you turn them over so they are face down again.

You continue flipping cards two at a time, leaving matches face up, and flipping ones that do not match back over until all cards have been matched.

Your score is the number of turns you have made. The lower the score the better.

Use the arrow keys, ENTER to select a card, ESCAPE to quit the game. On Windows/macOS/Linux you can also use wasd and space keys to move and select.

Hi-res 80x24 text mode

My previous games, Minefield and Robot Minefield both used 32x16 mode. This is a great mode, and very fast, but it doesn't let you do lower case letters, and you can't do colors. But really, they were just intermediate steps to build my text routines anyway.

The Color Computer 3 introduced a 80x24 hi-res text mode, which let's you have individual colors for each letter and background, as well as underline and blink modes.

In order to manipulate the text in this mode and not take a hit using the standard routines, is to write directly to the video memory. hi-res text is located at $6C000-$6DFFF. However, the 6809 (the Coco's CPU) can only address memory from $0000-$FFFF. $6C000 is way out of the accessable address space.

GIME MMU

Enter the GIME MMU. It maps 8K blocks of ram from outside of the 64K address space into the 64K address space.

For example, if you mapped $6C000-$6DFFF to $E000-$FDFF, when you write to address $E000, you are actually writing to physical memory at $6C000. You can map more then one block at a time.

To map the video memory at $6C000-$6DFFF (the hi-res text screen ram in the table above), to you update the appropriate MMU register and tell it to point to the memory page you want. So to map $6C000-$6DFFF to $E000-$FDFF, you find the MMU register that is associated wth the block of memory you want. In our example that is MMU register $FFA7. Then we set what page it should be mapped to. In our example, we want $6C000-$6DFFF so that is page $36. To put that into C code, it looks like this:

//Color Computer 3 only
#include "coco.h"

int main()
{
    initCoCoSupport();
    width(80);
    byte* hiresText = 0xE000;           //where text memory will be mapped
    byte* mmuReg = 0xFFA7;              //point to the mmu 
    byte previousPageValue = *mmuReg;   //remember what it was
    *mmuReg = 0x36;                     //point to the text page

    //now address 0xE000 points to 0x6C000
    *hiresText = 'a';                   //put a letter on screen

    //set MMU back to normal
    *mmuReg = previousPageValue;        

    waitkey(TRUE);

    return 0;
}

It's important to remember to put the MMU register back to normal if you plan to use any standard routines. You see me keeping track of what the value was near the top of the program, then put it back to that value at the end of the program. Notice also, I set it back before I call waitkey(TRUE).

To make it a little easier to use, I created a couple functions to do the job for me:

#define PAGE_HIRES_TEXT 0x36
#define MMU_REGISTER    0xFFA7
#define PAGE_ADDR       0xE000

void mapmmu() {
    previousPageValue = *((byte*)MMU_REGISTER);
    *((byte*)MMU_REGISTER) = PAGE_HIRES_TEXT;
}

void unmapmmu() {
    *((byte*)MMU_REGISTER) = previousPageValue;
}

Text and color

The hi-res text mode stores one byte for the character to display, and a second byte for the attribute of that character:

/*
 * Bit map 76543210
 * 7   Blink     (0x80)
 * 6   Underline (0x40)
 * 543 Forground 
 * 210 Background
 */
void setColor(byte fg, byte bg) {
    colorAttr = (colorAttr & 0xC0) + ((fg & 0x07) << 3) + (bg & 0x07);
}

Then I make use of a routine like this to display text. Notice that I write a byte for the character, then the second byte is the colorAttr.

void gotoxy(byte x, byte y) {
    cursorx = x;
    cursory = y;
}

void textout(const char* s) {
    mapmmu();
    byte* addr = (byte*)PAGE_ADDR + (cursory * 160 + cursorx*2);
    int len = strlen(s);
    for (int i = 0; i < len; ++i) {
        *addr = *(s + i);
        *(addr + 1) = colorAttr;
        addr += 2;
        cursorx++;
    }
    unmapmmu();
}



Copyright © 2020, Lee Patterson