4x4 Off-Road Racing Full Screen Graphic Format
Format type | Image |
---|---|
Hardware | CGA, EGA |
Colour depth | 2-bit (CGA) |
Minimum size (pixels) | 320×200 |
Maximum size (pixels) | 320×200 |
Palette | None |
Plane count | 1 |
Transparent pixels? | No |
Hitmap pixels? | No |
Games |
This format is used by 4x4 Off-Road Racing to store full-screen (320 × 200) images. The extension is *.pck, however the game has different graphic formats that use the same extension.
Image
The format has no header. The size of the image and color palette are stored in the EXE, so modification is limited. The format is encoded with a basic run-length encoding. Since the format only supports 2-bit color, each byte of graphic data accounts for 4 pixels.
When decoding the graphic, you read from the beginning, loading one byte for pixel data, and another for the length of the run. Each pixel byte is 4 pixels of data, 2-bits per pixel. The format is interlaced storing all the even lines then the odd lines. There is always 1,408 bytes of padding data between the even and odd lines data to accommodate the memory structure of the CGA standard.
Data type | Name | Description |
---|---|---|
BYTE | pixels | Binary representation of 4 pixels (2 bits per pixel) |
UINT8 | length | Number of times to repeat this pixel pattern. |
Source Code
Viewer
The following FreeBASIC code will read and display each of the graphic formats in the game with their correct EGA or CGA palette which you can specify.
' This program can decode and view the sprites, backgrounds, and full-screen
' images from the 1988 DOS game, 4x4 Off-Road Racing. It still needs a little
' work to display the sprites properly.
' Images are stored in two formats:
'
' Interlaced Format - Used only in full screen background images.
' Draws every even line until it reaches the bottom and then loops back to the
' top and draws every odd line. Has some redundant data at the end of the even
' lines.
'
' Flat Format - Used in all other images. Reads from left to right, top to
' bottom.
'
' None of the formats have headers. All image dimensions and palettes are
' stored in the EXE.
Declare Function GetColor(Bit1 As Byte, Bit2 As Byte) As UByte
Dim bPixels As UByte, bLength As UByte, bRepeat As UShort
Dim X As Short, Y As Short, Z As Short, W As Short, lLoc As ULong
Dim sWidth As UShort, bHeightJump As UByte
Dim bColor As UByte
Dim sName As String, sPath As String
Dim Shared sPalette As String, bColors As UByte
Dim aPalette(0 To 3) As UByte
Screen 12
' Available palettes include: CGA, EGA.
sPalette = "EGA"
' The file to load and the path to load from.
' Take a look at Street.pck to see an Easter Egg!
sName = "TITLE.PCK"
sPath = "D:\\Games\\4x4\\" ' <-- Remove double slashes.
Select Case UCase(sName)
' Full screen images. - Interlaced format.
Case "HALLFAME.PCK", "MART.PCK", "ROAD.PCK", "RSCREEN.PCK", "SELECT.PCK",_
"SHOP.PCK", "STORES.PCK", "STREET.PCK", "TITLE.PCK", "TRUCKSCR.PCK"
sWidth = 320
bHeightJump = 2
If sPalette = "CGA" Then bColors = 1 Else bColors = 0
' The track maps. - Flat Format.
Case "MAPS.PCK"
sWidth = 320
bHeightJump = 1
If sPalette = "CGA" Then bColors = 1 Else bColors = 0
' The side view of the Trucks with their masks. - Flat Format.
Case "TRUCKS.PCK"
sWidth = 176
bHeightJump = 1
If sPalette = "CGA" Then bColors = 1 Else bColors = 0
' Truck driving sprites. - Flat Format.
Case "HIGHLSPR.PCK", "KATACSPR.PCK", "KATANSPR.PCK", "STORMSPR.PCK",_
"TARACSPR.PCK", "TARANSPR.PCK"
Select Case UCase(sName)
Case "HIGHLSPR.PCK"
sWidth = 44
Case "KATANSPR.PCK", "KATACSPR.PCK"
sWidth = 40
Case "STORMSPR.PCK"
sWidth = 48
Case "TARANSPR.PCK", "TARACSPR.PCK"
sWidth = 44
End Select
bHeightJump = 1
If sPalette = "CGA" Then bColors = 1 Else bColors = 2
' Track background images. - Flat Format.
Case "BAJABCK.PCK", "DVALBCK.PCK", "GEORBCK.PCK", "MICHBCK.PCK"
sWidth = 576
bHeightJump = 1
' Figure out what palette to use.
Select Case UCase(sName)
Case "BAJABCK.PCK"
If sPalette = "CGA" Then bColors = 1 Else bColors = 2
Case "DVALBCK.PCK", "GEORBCK.PCK"
If sPalette = "CGA" Then bColors = 4 Else bColors = 3
Case "MICHBCK.PCK"
If sPalette = "CGA" Then bColors = 1 Else bColors = 2
End Select
' Road objects and masks. - Flat Format.
Case "BAJAOBS.PCK", "DVALOBS.PCK", "GEOROBS.PCK", "MICHOBS.PCK"
sWidth = 24
bHeightJump = 1
' Figure out what palette to use.
Select Case UCase(sName)
Case "BAJAOBS.PCK"
If sPalette = "CGA" Then bColors = 1 Else bColors = 2
Case "DVALOBS.PCK", "GEOROBS.PCK"
If sPalette = "CGA" Then bColors = 4 Else bColors = 3
Case "MICHOBS.PCK"
If sPalette = "CGA" Then bColors = 1 Else bColors = 2
End Select
End Select
' This section is the palette lookup.
' Note, 4x4 uses the 3rd CGA color palette so it uses red rather than magenta.
Select Case bColors
Case 0 ' EGA - Default
aPalette(0) = 0 ' Black
aPalette(1) = 4 ' Red
aPalette(2) = 1 ' Blue
aPalette(3) = 7 ' Lt. Gray
Case 1 ' CGA - Default / CGA Michigan / CGA Baja
aPalette(0) = 0 ' Black
aPalette(1) = 12 ' Bright Red
aPalette(2) = 11 ' Bright Cyan
aPalette(3) = 15 ' White
Case 2 ' EGA - Baja / EGA - Michigan
aPalette(0) = 0 ' Black
aPalette(1) = 4 ' Red
aPalette(2) = 3 ' Cyan
aPalette(3) = 15 ' White
Case 3 ' EGA - Death Valley / EGA - Georgia
aPalette(0) = 0 ' Black
aPalette(1) = 4 ' Red
aPalette(2) = 3 ' Cyan
aPalette(3) = 14 ' Yellow
Case 4 ' CGA - Death Valley / CGA - Georgia
aPalette(0) = 0 ' Black
aPalette(1) = 12 ' Bright Red
aPalette(2) = 10 ' Green
aPalette(3) = 14 ' Yellow
End Select
Dim sKey As String
Open sPath + sName For Binary As #1
' Loop through the file until we hit the end.
X = 0
Y = 0
Do Until EOF(1)
' Grab two bytes. The first is the pixel data, the second is the number of
' times to draw the data.
Get #1, , bPixels
Get #1, , bLength
lLoc = lLoc + 2
' Repeat the drawing process as many times as specified.
For bRepeat = 1 To bLength
W = 0
' The binary data is stored backwards, so loop though it back to front.
For Z = 3 To 0 Step -1
' Every 2 bits is a color. Send them to our GetColor function.
bColor = GetColor(Bit(bPixels, (Z * 2) + 1), Bit(bPixels, Z * 2))
' Once the color has been deciphered, plot a pixel.
Pset(X + W, Y), aPalette(bColor)
W = W + 1
Next Z
X = X + 4
' When we hit the right edge, drop back to the left.
If X = sWidth Then
X = 0
' Increment one or two lines based on the format.
Y = Y + bHeightJump
End If
' The full screen graphic format doesn't just store 1 screen worth of
' data. Some of the pixels from the middle of the image are stored at
' the end of the first pass. This data is redundant as the second pass
' will fill in all the blanks.
If bHeightJump = 2 Then
If Y = 204 And X = 128 Then
Y = 1
X = 0
End If
End If
Next bRepeat
Loop
Close #1
Sleep
' This function converts the 2 bits into a single color.
Function GetColor(Bit1 As Byte, Bit2 As Byte) As UByte
Dim bCol As UByte
' First, get the index.
If Bit1 = 0 and Bit2 = 0 Then bCol = 0
If Bit1 = -1 and Bit2 = 0 Then bCol = 1
If Bit1 = 0 and Bit2 = -1 Then bCol = 2
If Bit1 = -1 and Bit2 = -1 Then bCol = 3
' Return the color.
Return bCol
End Function
Credits
This graphic format was reverse engineered by TheAlmightyGuru. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)