YACE64 Logo

The Commodore 64 Emulator with the extra dimension

Home Introduction Features Screenshots Download Links Help About
Commodore 64
www.icons8.com

Tutorials

Tutorial 15 - Color-maps

This script shows how to change and extend the 16 default colors of the VIC. Each character or sprite can have complete new colors.
Also colors can be animated or changed at runtime.

This is the "Tutorial15" included in the Tutorial-Download.

Instructions

The OnLoad() set and defines three color-maps with the APP.SetColorMap method. In the callback function for characters and sprites the index of the new color-maps are set.

The default color-map with index 0 are the original C64/VIC colors, which can not be changed.

In the OnFrameEnd() function one color of the color-map colors1 is animated, so the color changes always.

The InitColorMaps() function just defines 16 colors for each of the 3 color-maps. Each color is a true RGB (red, green, blue) color, so it's not limited to the C64 color palette.

const int startProgramTimerId = 1;

int spriteColorMap = 0;

// Define three color-maps with 16 colors each
array<array<float>> colors1(16);
array<array<float>> colors2(16);
array<array<float>> colors3(16);

void InitColorMaps()
{
    // Set the 16 colors for the three color-maps colors1, colors2 and colors3.
    // Each color is defined by its red, green and blue part between 0.0 and 1.0
    colors1[0] = { 0.1, 0.0, 0.0 };
    colors1[1] = { 0.2, 0.0, 0.0 };
    colors1[2] = { 0.3, 0.0, 0.0 };
    colors1[3] = { 0.4, 0.0, 0.0 };
    colors1[4] = { 0.5, 0.0, 0.0 };
    colors1[5] = { 0.6, 0.0, 0.0 };
    colors1[6] = { 0.0, 0.0, 170.0 / 255.0 }; // original blue
    colors1[7] = { 0.7, 0.0, 0.0 };
    colors1[8] = { 0.8, 0.0, 0.0 };
    colors1[9] = { 0.9, 0.0, 0.0 };
    colors1[10] = { 1.0, 0.1, 0.2 };
    colors1[11] = { 1.0, 0.3, 0.4 };
    colors1[12] = { 1.0, 0.4, 0.5 };
    colors1[13] = { 1.0, 0.6, 0.7 };
    colors1[14] = { 1.0, 0.8, 0.9 };
    colors1[15] = { 1.0, 1.0, 1.0 };

    colors2[0] = { 0.0, 0.0, 0.1 };
    colors2[1] = { 0.0, 0.0, 0.2 };
    colors2[2] = { 0.0, 0.0, 0.3 };
    colors2[3] = { 0.0, 0.0, 0.4 };
    colors2[4] = { 0.0, 0.0, 0.5 };
    colors2[5] = { 0.0, 0.0, 0.6 };
    colors2[6] = { 0.0, 0.0, 0.7 };
    colors2[7] = { 0.0, 0.0, 0.8 };
    colors2[8] = { 0.0, 0.0, 0.9 };
    colors2[9] = { 0.0, 0.0, 1.0 };
    colors2[10] = { 0.1, 0.1, 1.0 };
    colors2[11] = { 0.3, 0.3, 1.0 };
    colors2[12] = { 0.5, 0.5, 1.0 };
    colors2[13] = { 0.6, 0.6, 1.0 };
    colors2[14] = { 0.9, 0.9, 1.0 };
    colors2[15] = { 1.0, 1.0, 1.0 };

    colors3[0] = { 0.1, 0.1, 0.4 };
    colors3[1] = { 1.0, 1.0, 1.0 };
    colors3[2] = { 252.0 / 255.0, 15.0 / 255.0, 192.0 / 255.0 }; // pink
    colors3[3] = { 0.0, 0.0, 0.0 };
    colors3[4] = { 0.0, 0.0, 0.0 };
    colors3[5] = { 0.0, 0.0, 0.0 };
    colors3[6] = { 0.0, 0.0, 0.0 };
    colors3[7] = { 0.0, 0.0, 0.0 };
    colors3[8] = { 0.0, 0.0, 0.0 };
    colors3[9] = { 0.0, 0.0, 0.0 };
    colors3[10] = { 0.0, 0.0, 0.0 };
    colors3[11] = { 0.0, 0.0, 0.0 };
    colors3[12] = { 0.0, 0.0, 0.0 };
    colors3[13] = { 0.0, 0.0, 0.0 };
    colors3[14] = { 0.0, 0.0, 0.0 };
    colors3[15] = { 0.0, 0.0, 0.0 };
}

int OnChar(int mode, CharInfo& charInfo, BlockManipulation& charManipulationBack, BlockManipulation& charManipulationFore)
{
    if (charInfo.row == 1)
        charManipulationFore.colorMap = 1; // use color-map 1 for the 2nd line
    else if (charInfo.row == 3)
        charManipulationFore.colorMap = 2; // use color-map 2 for the 4th line

    // all other row use the default C64 colors from color-map 0

    return Draw::DrawCombined;
}

bool OnSprite(int mode, SpriteInfo& spriteInfo, BlockManipulation& spriteManipulation)
{
    spriteManipulation.zTranslation -= 0.08;

    // set another color-map for our 2nd sprite
    if (spriteInfo.index == 1)
        spriteManipulation.colorMap = spriteColorMap;

    return true;
}

void OnLoad(bool reloaded)
{
    // Get the path of our script
    string scriptPath = APP.GetScriptPath();

    APP.ClearDepthMaps();
    APP.ClearModels();
    APP.ViewMode = ViewMode::Ext3D;

    if (!reloaded)
    {
        // Load a program, which is the same path as our script
        APP.Load(scriptPath + "Sprites.prg", 0);
        // Set a timer with 120 frame delay, which will send "RUN" to the keyboard
        SetTimer(startProgramTimerId, 120, false);
    }

    GUI.SetButtonTitle(1, "Normal Colors");
    GUI.SetButtonTitle(2, "User defined solors");

    GUI.ShowInfoMessage("Tutorial 15");

    InitColorMaps();

    // Set our three color maps
    APP.SetColorMap(1, colors1);
    APP.SetColorMap(2, colors2);
    APP.SetColorMap(3, colors3);


    // Write something to color memory for 2nd and 4th line
    for (int a = 0; a < 40; ++a)
        C64.Write(0xD800 + 40 + a, a % 16);
    for (int a = 0; a < 40; ++a)
        C64.Write(0xD800 + 120 + a, a % 16);
}

void OnFrameEnd()
{
    const int animateColor = 7;

    // simple animation of the color 7 of our color-map 1
    colors1[animateColor] = { colors1[animateColor][0] + 0.009, colors1[animateColor][1] + 0.016, colors1[animateColor][2] + 0.012 };

    if (colors1[animateColor][0] > 1.0)
        colors1[animateColor][0] = 0.0;
    if (colors1[animateColor][1] > 1.0)
        colors1[animateColor][1] = 0.0;
    if (colors1[animateColor][2] > 1.0)
        colors1[animateColor][2] = 0.0;

    APP.SetColorMap(1, colors1);
}

void OnUser(int buttonIndex)
{
    if (buttonIndex == 1)
    {
        spriteColorMap = 0;
    }
    else if (buttonIndex == 2)
    {
        spriteColorMap = 3;
    }
}

void OnTimer(int timerId)
{
    if (timerId == startProgramTimerId)
    {
        APP.SendASCII("RUN\n"); // send "RUN" to the keyboard and also press 'Enter'
    }
}