Start page: ARABART home
← All fifteen programs

Port Said Computer Systems

1993 · C:\PORTSAID\PORTSAID.EXE

C:\PORTSAID\PORTSAID.EXE
Port Said Computer Systems running in DOS

Loading PORTSAID.EXE, 19 KB

Click the screen to type into the program.

The start-up screen on every PC that Port Said Computer Systems sold. They paid him with his first mouse.

The story

Yasser made this boot screen as a gift for Port Said Computer Systems, and every computer the company sold showed it when it started. The company thanked him with his very first mouse, a rare thing in Egypt in 1993. He built it on the picture code from his KemYam splash, carried into C.

The screen every PC showed

Every computer that Port Said Computer Systems sold greeted its owner with this screen. It is a small film, and his own code draws every frame.

PORTSAID.EXE 640 x 350, 16 colors
The Port Said Computer Systems boot screen: the red PCS logo with a computer drawn in white lines, the Arabic name بورسعيد للحاسبات in green outline letters, and PORT-SAID COMPUTER SYSTEMS in yellow, on black.

Draw 659 of 659: the boot screen is complete.

The four pieces of the red PCS logo fly in from the right. The company's Arabic name, بورسعيد للحاسبات, opens like a curtain, falls and bounces into place. Then the English name appears beneath it.

He wrote it in Turbo C++, with the drawing done in inline assembly: 2,318 bytes of his code and 24,993 bytes of pictures, all in one file. Drag the bar to any of its 659 draws, or pick a part and watch it again.

Four tiles, four straight lines

The logo is four tiles, 64 by 79 pixels each. Each one flies on a straight line in 100 steps: two from the top right corner, two from below the bottom edge.

The line is plain school math. Divide the distance by the number of steps, then add that much to x and y at every step. The steps are decimals, 5.12 pixels across for each row down, so the path stays perfectly straight. It is the way a CSS transition moves an element from one point to another.

Each step, x is cut to a whole pixel and then to a whole byte, x ÷ 8, because the screen stores eight pixels in a byte. So the tiles glide down a row at a time and across in hops of eight pixels. Nothing is erased between steps. The first tile paints a red ribbon across the screen, and the tile that follows the same path rolls it back up behind it. Step through his loop below and watch the numbers.

THE SCREEN 640 x 350
x, a decimal576.0 whole x576 ÷ 8: the byte72 y0
PORTSAID.EXE fly a tile
  1. 0595sub sp,24h; room for x, y, dx and dy
  2. 05A0sub ax,[bp+0Ah]; x1 - x0
  3. 05BAfdivr qword [bp-18h]; dx = (x1 - x0) / n
  4. 05C7sub ax,di; y1 - y0
  5. 05E0fdivr qword [bp-20h]; dy = (y1 - y0) / n
  6. 05F4fstp qword [bp-08h]; x = x0
  7. 0601fstp qword [bp-10h]; y = y0
  8. 0605xor si,si; i = 0
  9. 060Bstep:fld qword [bp-08h]; x, then _ftol cuts it to a whole number
  10. 0615fld qword [bp-10h]; y, cut the same way
  11. 0621imul dx; y × 80 bytes a row
  12. 062Bidiv bx; x ÷ 8: the byte
  13. 062Eadd dx,ax; where the tile lands
  14. 0643call 04FA; copy the tile, four layers
  15. 064Dfadd qword [bp-18h]; x += dx
  16. 0659fadd qword [bp-20h]; y += dy
  17. 0666call 0311; wait
  18. 066Ainc si; i++
  19. 066Ejle step; until i passes n
His C
  1. void fly(word pic, int x0, int y0, int x1, int y1,
  2. int w, int h, int n, int wait) {
  3. double dx = (double)(x1 - x0) / n;
  4. double dy = (double)(y1 - y0) / n;
  5. double x = x0, y = y0;
  6. for (int i = 0; i <= n; i++) {
  7. int at = (int)y * 80 + (int)x / 8;
  8. copy(pic, at, w, h);// all four layers
  9. x += dx;
  10. y += dy;
  11. delay(wait);
  12. }
  13. }
Watches
i
- the step, 0 to 100
x
576.0 a decimal, in the math unit
y
0.0 a decimal
dx
-5.12 added every step
AX
0 the last whole number
Help

Logo tile 4 flies from the top right corner, (576, 0), toward (64, 100), in 100 steps. The function is C; Turbo C++ wrote this start.

For engineers: decimals in a tiny program

The decimals are C doubles. Turbo C++ compiles each math instruction as a call to Borland's floating-point emulator, which uses the math chip when the PC has one and does the work in software when it does not, so the logo flies on every PC. The emulator needs ten addresses that DOS fills in when the program loads, a relocation table, so this tiny-model program ships as an EXE that starts like a .COM, at offset 100h.

A curtain, a drop, a bounce

The Arabic name enters in three acts. It opens at the top of the screen, falls to its place, and bounces four times, each bounce smaller than the last.

THE BOUNCE the name's top row
The Arabic name's top row over its entrance: 80 draws of the curtain at row 0, then a fall to row 123 and bounces up to 110, 117, 119 and 122, settling at 123. row 0 123 curtain 13641
PORTSAID.EXE the top of the screen
The PCS logo and the Arabic name بورسعيد للحاسبات, settled at row 123.

The name has settled at row 123, after bounces of 13, 6, 4 and 1 rows.

The curtain takes 80 draws, one more byte of every row each time. Even rows slide in from the left, odd rows from the right, and they meet as a whole name. It is the comb effect from his KemYam splash, now a C function.

The bounce has no physics engine. It is nine straight moves, each with numbers he chose: down to row 123, up 13 rows, down, up 6, down, up 4, down, up 1, down. Each bounce is lower and quicker than the one before, so the name slows as it settles, like an ease-out curve drawn by hand.

Pictures inside the code

There are no picture files. All six pictures sit inside the program, between its functions, and the code points at each one by its own address.

PORTSAID.EXE in memory 47,152 bytes
his codehis picturesBorland's start-up and math library

His code points at six pictures. Scan it to find them.

FOUND

His code says mov ax,6375h / xor dx,dx / mov bx,10h / div bx: divide the picture’s place by 16.

6375h ÷ 16 = 637h, remainder 5. He moves his starting point in memory forward by 637h and keeps 5 as the step inside it. That leaves the decoder a whole 64 KB window to read the picture from.

Its first two words say 8 bytes (64 pixels) by 79 rows. 2,417 packed bytes become 2,528: four color layers of 632.

A PC address of the time has two parts, like a street and a house number: a segment and an offset. His code asks which street it is running on, then splits each picture's place in two. 6375h becomes the street plus 637h, and house number 5. The house number stays small, so the decoder has room to read the whole picture. This pair is a far pointer.

Each picture starts with its width and height, then his packed layers. The Arabic name packs from 18,560 bytes to 9,400. With the pictures inside, the program is one file: copy it to a new PC and nothing can go missing.

Then and now
1991 to 19932026Why it is the same idea
Pictures stored inside the program, between its functions Images inlined in a JavaScript bundle as data: URLs One file to ship, and nothing to lose on the way.
A straight line with a decimal step added every frame A CSS transition or a gsap.to tween with linear easing Start, end and a number of steps; the math fills in the rest.
Nine moves, smaller and smaller, to make a bounce A keyframe animation with an ease-out bounce Smaller and smaller rebounds read as weight settling.

Code that moved house

The heart of this boot screen came from his KemYam splash. He carried his assembly into C functions, and 153 bytes arrived exactly as he first wrote them.

NAMES.COM his assembly
090533FF8B360305AC3C377403AAEBF8AC3C00740932ED8AC8ACF3AAEBEAAD0E1FA311058936
PORTSAID.EXE inside C
760683C6048B7E0AAC3C377403AAEBF8AC3C00740932ED8AC8ACF3AAEBEA8976FE071F8B46FE

Picture decoder, 22 identical bytes. The heart of his run-length decoder: read a byte, copy it, or repeat the next one.

lodsb · cmp al,37h · je · stosb · jmp · lodsb · cmp al,0 · je · xor ch,ch · mov cl,al · lodsb · rep stosb · jmp

In the KemYam splash the decoder finds its input in fixed memory cells. Here it is a C function. Turbo C++ writes the entry and the exit, and his inline assembly reads its four arguments from the stack frame. The middle, 22 bytes, is the same loop. It is what you do today when you move tested code into a shared package with a new interface.

The layer copy, the refresh wait, the key wait and his signature with its spark came along the same way. To see how the decoder, the color layers and the spark work, step through them on the KemYam splash page.

Every Byte of PORTSAID.EXE

Each square is one byte of the program in memory, colored by what it is. Tap a part to open it in the full map, down to the single instruction.

C:\PORTSAID\PORTSAID.EXE