Picture Resource

From SCI Wiki
Revision as of 21:19, 14 October 2020 by Rainer De Temple (talk | contribs) (formatting)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search
The SCI Picture Resource

 

 



Description

Place holder for the SCI Picture Resource

Format/Specifications

The picture resource is a vector image format defined by unsigned bytes in the file.

A Picture Resource File always begins with a two-byte header identifier of 0x8100, followed by the first drawing instruction.

Below is a summary of each drawing instruction:

Number Hex Parameters Description Example
0 0xF0 0x## (1 byte) Set Visual Color

Sets the visual color index to the value specified

F0 0C Sets the visual palette index to 0x0C (color 12, bright red)
1 0xF1 Disable Visual

Disables drawing on visual canvas

F1 Disable visual drawing
2 0xF2 0x## (lower 4-bits only) Set Priority Color

Sets the priority color index to the value specified

F0 05 Sets the priority color to 0x05 (color 5, Magenta)
3 0xF3 Disable Priority

Disables drawing on priority canvas

F3 Disable priority drawing
4 0xF4

(0x##) Pattern number if flag set

0xXY Upper 4-bits for starting X and Y coordinates
0xXX 0xYY Lower 8 bits for starting X and Y coordinates

(0x##) Pattern number if flag set
0xXY offset (signed 4 bit words)

Short Relative Patterns

Plots patterns from the coordinates specified to the offset coordinates until next command.

F4 10 22 AC D9 Plot current pattern type at coordinates 0x122,0x0AC(290,172) and then (-5,-1) at (285,171)
5 0xF5

0xXY Upper 4-bits for starting X and Y coordinates
0xXX 0xYY Lower 8 bits for starting X and Y coordinates

0xYY Offset for Y using sign-magnitude
0xXX Offset for X using 2's Compliment

Medium Relative Lines

Plots short lines from starting coordinates, to offset coordinates until next command.

F5 10 22 AC 85 FB Draw a line starting at 0x122,0x0AC(290,172) to offset 0xFB,0x85(-5,-5) at (285,167)
6 0xF6

0xXY Upper 4-bits for starting X and Y coordinates
0xXX 0xYY Lower 8 bits for starting X and Y coordinates

0xXY Upper 4-bits for next X and Y coordinates
0xXX 0xYY Lower 8 bits for next X and Y coordinates

Long Lines

Plots lines from starting coordinates, to next coordinates until next command.

F5 10 22 AC 00 05 0F Draw a line starting at 0x122,0x0AC(290,172) to 0x005,0x00F(5,14)
7 0xF7

0xXY Upper 4-bits for starting X and Y coordinates
0xXX 0xYY Lower 8 bits for starting X and Y coordinates

0xXY offset (signed 4 bit words)

Short Relative Lines

Plots lines from starting coordinates, to next coordinates until next command.

F5 10 22 AC 00 5D Draw a line starting at 0x122,0x0AC(290,172) to offset 0x5,0xD(5,-5) at (295, 167)
8 0xF8

0xXY Upper 4-bits for starting X and Y coordinates
0xXX 0xYY Lower 8 bits for starting X and Y coordinates

0xXY offset (signed 4 bit words)

Flood fill

Plots lines from starting coordinates, to next coordinates until next command.

F5 10 22 AC 00 5D Draw a line starting at 0x122,0x0AC(290,172) to offset 0x5,0xD(5,-5) at (295, 167)
9 0xF9

0x##
Bit 4 - Use Solid/Pattern Flag
Bit 5 - Use Circle/Rectangle
Bits 0-3 - Pattern Size (0-7)

Set Pattern

Sets Pattern style flags and Pattern size.

F9 23 Sets pattern brush to size 3 and type to random pattern.
10 0xFA

(0x##) Pattern number if use pattern flag set

0xXY Upper 4-bits for next X and Y coordinates
0xXX 0xYY Lower 8 bits for next X and Y coordinates

Long Patterns

Plots a pattern using the set flags, size and number to coordinates specified. Command is repeated until next command.

FA 10 22 AC Plot a pattern at coordinates 0x122,0x0AC(290,172)
11 0xFB 0x## (lower 4-bits only) Set Control Color

Sets the control color index to the value specified

FB 02 Sets the control color to 0x02 (color 2, Green)
12 0xFC Disable Control

Disables drawing on control canvas

FC Disable control drawing
13 0xFD

(0x##) Pattern number if use pattern flag set

0xXY Upper 4-bits for starting X and Y coordinates
0xXX 0xYY Lower 8 bits for starting X and Y coordinates

(0x##) Pattern number if flag set
0xYY Offset for Y using sign-magnitude
0xXX Offset for X using 2's Compliment

Medium Relative Patterns

Plots short lines from starting coordinates, to offset coordinates until next command.

F5 10 22 AC 85 FB Plot a pattern starting at 0x122,0x0AC(290,172) then to offset 0xFB,0x85(-5,-5) at (285,167)
14 0xFE

0x## Extended Command Number

(0x00) Set palette Entry

0x## Palette Index(across all 4 palettes)
0xXY Set first color to X and second to Y

(0x01) Set Entire Palette

0x## Palette Number
0xXY Set first color to X and second to Y (for 40 iterations)

(0x02) Set Mono0 Set Monochrome Palette

0x## Palette Number
0xXY Set first color to X and second to Y (for 40 iterations)

(0x03) Set Mono1 Set Visual (using monochrome palette)

0x## Color

(0x04) Set Mono2 Disable Visual

(0x05) Set Mono3 Set direct Visual (without going through the mono palette)

0x## Color

(0x06) Set Mono4 Disable direct Visual

(0x07) Embed Cel (bitmap) (SCI01 Onwards Only)

0xXY Upper 4-bits for X and Y coordinates

0xXX 0xYY Lower 8 bits for X and Y coordinates
0x## 0x## Size of the data to follow in bytes (little endian)

0x## (for size amount of bytes) Refer to View documentation for Cel format

(0x08) Set Priority Bands (SCI01 Onwards Only)

0x## Y locations for priority bands (14 num)??

Command extensions

Execute the extended command specified. Note these differ for SCI1.1 (VGA).

FE 00 10 22Set palette entry 16 in palette 1 to 0x22 (2,2)
15 0xFF Picture End

Signals the end of the picture commands.

FF End of Drawing Commands.

Short, Medium, Long?

The different types is likely to help in reducing file size for the pictures. You can see that a "Long" line uses 6 bytes, however a Medium uses 5 bytes, and a short 4 bytes. There is a trade-off on line length - for example a "Short" line can only be up to 7 pixels long. This could be automatically determined by the picture editor software. An image with 100 short lines would only be 400 bytes on disk, whereas using long lines is 50% larger at 600 bytes. When you're designing a game to be shipped on 720k disks, every byte counts.

Palette

Each drawing can contain up to 4 palettes of 40 colors. Each entry in the palette consists of a first and second color. Where both are the same value the color appears solid. When the values are different then the color is "dithered" between those two colors.

The default palette (ie palette 1) is set as follows:

INSERT IMAGE HERE

In hexadecimal format:

Code:
std::array<std::pair<uint8_t,uint8_t>, 40> default_palette =
{{
     {0x0,0x0}, {0x1,0x1}, {0x2,0x2}, {0x3,0x3}, {0x4,0x4}, {0x5,0x5}, {0x6,0x6}, {0x7,0x7},
     {0x8,0x8}, {0x9,0x9}, {0xa,0xa}, {0xb,0xb}, {0xc,0xc}, {0xd,0xd}, {0xe,0xe}, {0x8,0x8},
     {0x8,0x8}, {0x0,0x1}, {0x0,0x2}, {0x0,0x3}, {0x0,0x4}, {0x0,0x5}, {0x0,0x6}, {0x8,0x8},
     {0x8,0x8}, {0xf,0x9}, {0xf,0xa}, {0xf,0xb}, {0xf,0xc}, {0xf,0xd}, {0xf,0xe}, {0xf,0xf},
     {0x0,0x8}, {0x9,0x1}, {0x2,0xa}, {0x3,0xb}, {0x4,0xc}, {0x5,0xd}, {0x6,0xe}, {0x8,0x8}
}};

The default palette is duplicated across all 4 palettes at the start of a picture.

Line and Flood-fill algorithms

Typically, the Bresenham line-algorithm is used for line drawing.

Below is an example of what the routine might look like:

Code:
void dither_line(int x0, int y0, int x1, int y1, std::pair<uint8_t, uint8_t> col, uint8_t priority, uint8_t control, uint8_t draw_enable)
{
    int dx =  std::abs(x1-x0);
    int sx = x0<x1 ? 1 : -1;
    int dy = -std::abs(y1-y0);
    int sy = y0<y1 ? 1 : -1;
    int err = dx+dy;  
    while(true)
    {
        uint8_t line_col = ((x0 + y0) % 2) ? col.first : col.second;
        if (draw_enable & DRAW_ENABLE_VISUAL) plot_pixel(x0, y0, visual_pixels, line_col);
        if (draw_enable & DRAW_ENABLE_PRIORITY) plot_pixel(x0, y0, priority_pixels, priority);
        if (draw_enable & DRAW_ENABLE_CONTROL) plot_pixel(x0, y0, control_pixels, control);
        if (x0==x1 && y0==y1) break;
        int e2 = 2*err;
        if (e2 >= dy) 
        {
            err += dy;
            x0 += sx;
        }
        if (e2 <= dx) 
        {
            err += dx;
            y0 += sy;
        }
    }
}

Similarly, a basic 4-way recursive flood fill algorithm is used for the fill function.

An example of how the flood fill procedure may work:

Code:
void dither_fill(int x, int y, std::pair<uint8_t, uint8_t> col, uint8_t priority, uint8_t control, uint8_t draw_enable)
{
    int legal_color = 0xf;
    static std::array<uint8_t, 320*200> bound_pixels; // a temporary working area
    if (draw_enable & DRAW_ENABLE_VISUAL) { bound_pixels = visual_pixels; legal_color = 0xf;}
    else if (draw_enable & DRAW_ENABLE_PRIORITY) { bound_pixels = priority_pixels; legal_color = 0;}
    else if (draw_enable & DRAW_ENABLE_CONTROL) { bound_pixels = control_pixels; legal_color = 0;}
    else return; // no draw flags set

    if (x<0 || x>319 || y<0 || y>189) return; // don't fill outside canvas

    if (bound_pixels[x + (y * 320)] != legal_color) return; // don't fill non-white/black areas
    
    // plot the pixel
    if (draw_enable & DRAW_ENABLE_VISUAL)   plot_pixel(x, y, visual_pixels, ((x + y) % 2) ? col.first : col.second);
    if (draw_enable & DRAW_ENABLE_PRIORITY) plot_pixel(x, y, priority_pixels, priority);
    if (draw_enable & DRAW_ENABLE_CONTROL)  plot_pixel(x, y, control_pixels, control);
    
    // recursively call for neighbours
    dither_fill(x, y+1, col, priority, control, draw_enable);
    dither_fill(x, y-1, col, priority, control, draw_enable);
    dither_fill(x-1, y, col, priority, control, draw_enable);
    dither_fill(x+1, y, col, priority, control, draw_enable);
}


NOTE:

The recursive fill above may not work on larger fill areas and cause a stack overflow. A better way to to keep an organised list (ie a queue) of points to fill, popping them off the list as each is filled.


Dithering

One of the identifying qualities of an SCI EGA Picture is it's dithering. This is done by alternating between color 1 and color 2 from the palette.

A practical way (easy to understand) to do this is using the following formula:

if ((x + y) % 2) color = col.first else color = col.second

or (for older computers):

if ((x + y) & 1) color = col.first else color = col.second

Patterns

Pictures keep two flags for whether to draw a circle or square, and solid or random pattern (spray-paint style).

USE_RECTANGLE_FLAG
0x10 (bit 4)
USE_PATTERN_FLAG
0x20 (bit 5)

At the start of a picture these flags are both set to zero (ie use circles, and use solids).

INSERT PATTERN TYPES IMAGE HERE

There are 120 different styles of "random" pattern available.

A texture bitmap is sampled from different offsets to generate each style. The texture is defined as a 256-bit array:

0x20, 0x94, 0x02, 0x24, 0x90, 0x82, 0xa4, 0xa2,
0x82, 0x09, 0x0a, 0x22, 0x12, 0x10, 0x42, 0x14,
0x91, 0x4a, 0x91, 0x11, 0x08, 0x12, 0x25, 0x10,
0x22, 0xa8, 0x14, 0x24, 0x00, 0x50, 0x24, 0x04

The Pattern number is an index to the following table, which in turn is an offset into the texture defined above.

    
0x00, 0x18, 0x30, 0xc4, 0xdc, 0x65, 0xeb, 0x48,
0x60, 0xbd, 0x89, 0x04, 0x0a, 0xf4, 0x7d, 0x6d,
0x85, 0xb0, 0x8e, 0x95, 0x1f, 0x22, 0x0d, 0xdf,
0x2a, 0x78, 0xd5, 0x73, 0x1c, 0xb4, 0x40, 0xa1,
0xb9, 0x3c, 0xca, 0x58, 0x92, 0x34, 0xcc, 0xce,
0xd7, 0x42, 0x90, 0x0f, 0x8b, 0x7f, 0x32, 0xed,
0x5c, 0x9d, 0xc8, 0x99, 0xad, 0x4e, 0x56, 0xa6,
0xf7, 0x68, 0xb7, 0x25, 0x82, 0x37, 0x3a, 0x51,
0x69, 0x26, 0x38, 0x52, 0x9e, 0x9a, 0x4f, 0xa7,
0x43, 0x10, 0x80, 0xee, 0x3d, 0x59, 0x35, 0xcf,
0x79, 0x74, 0xb5, 0xa2, 0xb1, 0x96, 0x23, 0xe0,
0xbe, 0x05, 0xf5, 0x6e, 0x19, 0xc5, 0x66, 0x49,
0xf0, 0xd1, 0x54, 0xa9, 0x70, 0x4b, 0xa4, 0xe2,
0xe6, 0xe5, 0xab, 0xe4, 0xd2, 0xaa, 0x4c, 0xe3,
0x06, 0x6f, 0xc6, 0x4a, 0x75, 0xa3, 0x97, 0xe1

If the pattern size forces the sample point past the length of the texture, then it wraps back around to zero. With modern computers the texture could be repeated twice to avoid having to write code to wrap around (SCUMMVM does this).


Versions


PIC


P16


P56


References


Also See