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 (0x##) Pattern number if flag set |
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 0xYY Offset for Y using sign-magnitude |
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 0xXY Upper 4-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 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 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## |
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 |
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 (0x##) Pattern number if flag set |
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## Palette Command Number (0x00) Set palette Entry
(0x01) Set Entire Palette
TODO: SCI1 commands differ |
Palette Command
Execute the palette command specified. Note: for SCI1 pictures, this command extends the number of commands to include drawing a bitmap. |
FE 00 10 22 Set palette entry 16 in palette 1 to 0x22 (2,2)
|
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:
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:
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:
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);
}
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 to do this is using the following formula:
if ((x + y) % 2) == 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.
Versions
PIC
P16
P56
References
Also See
- SCI Specifications: Chapter 1 - Introduction#PIC
- SCI Specifications: Chapter 1 - Introduction#P16
- SCI Specifications: Chapter 1 - Introduction#P56