Start page: ARABART home
← All fifteen programs

Arabic Commercial

1991 · C:\ARABIC\DEMO.COM

C:\ARABIC\DEMO.COM
Arabic Commercial running in DOS

Loading DEMO.COM, 5 KB

Click the screen to type into the program.

A 15-slide Arabic advert for a computer services center in Port Said, played by a 152-byte player he wrote.

The story

This slide show is the step before ARABART. Every line of Arabic travels as short vertical pen strokes, 9,023 of them for 15 slides. A player of just 152 bytes paints them back one pixel at a time. Before each line, the player rewrites five bytes of its own code to pick the direction, the shadow and both colors. Player and pictures together fit in 4,864 bytes on disk. His signature rides inside, scrambled, and comes back only when the program runs.

Fifteen slides, painted stroke by stroke

In 1991 Yasser made a slide show for the Port Said Center for Computer Services: fifteen slides of Arabic in color, with 3-D shadows. A player of 152 bytes shows all of it.

Here the Arabic travels as pixels. Every line of text is a list of short vertical strokes, and his player paints them back one pixel at a time. For a 3-D line it paints each pixel twice: once in the letters’ color, then two pixels right and two down in the shadow’s. Press Run to play the whole show from his own bytes, or step slide by slide.

C:\ARABIC\DEMO.COM
A slide of his commercial: مركز بورسعيد لخدمات الكمبيوتر, Port Said Center for Computer Services, in white letters with a red 3-D shadow.
بسم الله الرحمن الرحيمIn the name of God, the Most Gracious, the Most Merciful
HIS CODE, live
0149 4B dec bx x: one column to the left
0151 43 inc bx w: one column to the right
016C B8070C mov ax,0C07h the letters’ color
0173 EB00 jmp +0 draw the shadow
0175 B8040C mov ax,0C04h the shadow’s color
Line 1 of 1 · 368 strokes · 3,712 pixel calls

Watch the window beside the screen. Before each line of text, the player reads five bytes and writes them straight into its own code: which way “x” moves, whether to draw the shadow, and both colors. One loop, rewritten on the fly, draws all 23 lines of the show. This is self-modifying code.

The commercial is the step before ARABART. Its letters stand 34 pixels tall, the height of ARABART’s font 3, with the same two-pixel shadow. In ARABART that look became a single call: one line of code draws 3-D Arabic from any letters you type.

Inside the player

78 instructions, 152 bytes, draw the whole show. Step through the first strokes of slide 1 and watch his script bytes turn into pixels.

THE SCRIPT bytes it reads
4B430007048700E8011F06781E08781D0A2C02781D0A2B04781E0424042A06781F0224042A067824042B0478
header: 5 code bytes, row, columnstrokes: row, lengthx: next column
VGA close up
DEMO.COM his player
  1. 0113mov si,01ECh; the script
  2. 0116mov ax,0010h; 640 x 350
  3. 0119int 10h; and a clean screen
  4. 011Emov [0149h],al; write: step for x
  5. 0124mov [0151h],al; write: step for w
  6. 012Amov [0174h],al; write: shadow jump
  7. 0130mov [016Dh],al; write: letter color
  8. 0136mov [0176h],al; write: shadow color
  9. 0139mov di,[si]; start row
  10. 013Dmov bx,[si]; start column
  11. 0141next:mov dl,[si]; one script byte
  12. 0144cmp dl,78h; x?
  13. 0149inc bx; rewritten: dec bx
  14. 014Ccmp dl,77h; w?
  15. 0154cmp dl,79h; y: next line
  16. 0159cmp dl,7Ah; z: the end
  17. 015Ecmp dl,88h; next slide
  18. 0165add dx,di; the row
  19. 0167mov cl,[si]; how many pixels
  20. 016Cpx:mov ax,0C00h; rewritten: color
  21. 016Fxchg bx,cx
  22. 0171int 10h; one pixel
  23. 0173jmp +0; rewritten: 0 or 0Dh
  24. 0175mov ax,0C00h; rewritten: shadow
  25. 0178inc cx / inc cx; x + 2
  26. 017Ainc dx / inc dx; y + 2
  27. 017Cint 10h; its shadow
  28. 017Edec cx / dec cx; back again
  29. 0182inc dx; one row down
  30. 0185loop px; the rest
  31. 0187jmp next
The same in C
  1. byte *s = script;
  2. set_mode(0x10);// and clears
  3. code[0x149] = *s++;// his code
  4. code[0x151] = *s++;
  5. code[0x174] = *s++;
  6. code[0x16D] = *s++;
  7. code[0x176] = *s++;
  8. row0 = word(s); s += 2;
  9. col = word(s); s += 2;
  10. for (;;) {
  11. b = *s++;
  12. if (b == 'x') { col--; continue; }
  13. if (b == 'w') { col++; continue; }
  14. if (b == 'y' || b == 'z' || b == 0x88)
  15. break;
  16. row = row0 + b; n = *s++;
  17. while (n--) {
  18. plot(col, row, color);
  19. if (shadow)
  20. plot(col + 2, row + 2, shade);
  21. row++;
  22. }
  23. }
Watches
SI
01ECh where it is reading
BX
0 the column
DX
0 the row
Help

His read pointer starts at the script: 25,653 bytes that hold all fifteen slides.

His player, and the same ideas today
1991 to 19932026Why it is the same idea
Five bytes written into his own loop before each line Setting shader uniforms before a GPU draw call One drawing program, with new settings for every draw.
A jump of 0 or 13 bytes decides whether the shadow is drawn A boolean flag passed to the shader One switch turns a whole step on or off.
Strokes stored as a row and a length Run-length encoding, as in fax images and sprite formats Store where the ink is, not every empty pixel.
For engineers: the whole player
ARABIC/DEMO.COM · player (CS:0113 to 01AA)
0116 mov ax,0010h / int 10h ; EGA 640×350, 16 colors; a clean screen
011B mov al,[si] / inc si / mov [0149h],al ; five times: 0149, 0151, 0174, 016D, 0176
0139 mov di,[si] / mov bx,[si+2] ; start row, start column
0141 mov dl,[si] / inc si ; the next script byte
0144 cmp dl,"x" / jne / inc bx ; the step he rewrote
0154 cmp dl,"y" / "z" / 88h ; next line, the end, next slide
0163 mov dh,0 / add dx,di / mov cl,[si] ; row, stroke length
016F xchg bx,cx / int 10h ; CX = column, and BH = 0, the page
0178 inc cx / inc cx / inc dx / inc dx / int 10h ; the shadow at +2, +2
0185 loop 016Ch ; down the stroke
0189 mov cx,1000h / mov ah,0Bh / int 21h / loop ; a pause between slides
019D mov ax,3 / int 10h / mov ah,9 / int 21h ; text mode, print the credit
CS offsets; the file starts at CS:0100. The script starts at 01ECh and ends with its first z at 6620h.

One small trick shows how carefully he packed it. xchg bx,cx moves the stroke counter into BX. The counter is always below 256, so BH is 0, which is exactly the video page number the BIOS pixel call needs. One instruction does two jobs. The pause between slides asks DOS 4,096 times whether a key was pressed, then setting the graphics mode again wipes the screen for the next slide. See the player in Every Byte.

4,864 bytes for fifteen slides

The whole commercial, player and pictures, is 4,864 bytes on disk. One plain screenshot of a single slide would take 112,000.

The secret is to store only the ink. A plain 16-color picture spends half a byte on every pixel, black or not. His script spends two bytes on each stroke, where it starts and how long it runs, plus one byte to move to the next column. Scan one word and watch the two counts.

ONE WORD, as his script stores it
Column 1 of 74
His script so far
0 bytes
The same pixels as a plain picture
0 bytes
BYTES, to scale

Sizes in units of his player, the whole drawing program. Tap any bar to make it the unit.

In memory the program is 25,899 bytes. He shipped it packed with DIET, a compressor of the day, and it unpacks itself when it starts, like a self-extracting zip. That leaves 4,864 bytes on the floppy disk for fifteen slides of animated Arabic.

His name, hidden in the bytes

Open DEMO.COM in a file viewer and his name is nowhere to be found. It is there, scrambled, and the first 19 bytes of the program put it back together.

Each byte of the credit is stored a little higher than it should be. The first is 4 too high, the next 5, the next 6, and so on. His loop subtracts the same keys, one by one, and when the show ends the program prints the result. Step through it, then try it on your own name.

HIS CREDIT 65 bytes, as a file viewer shows them
O4F%25K4B'27U55)29c63+2BM4D-2D[5B/2F030131e65·82z7A·89·8Dx78·8A~7E:3A;3B_5F·8C·90·8FN4EM4D/2F-2D131/2FF46c63·8Bg67[5Bd64e65^5EN4E·88q71·84·85x78·86U55·83·86·80z7A·87·80·80]5D·7F·8B·89o6FO4FM4Dh68
Decoded so far
DEMO.COM the first 19 bytes
  1. 0100mov si,01ABh; the 65 bytes
  2. 0103mov al,4; the first key
  3. 0105mov cx,41h; 65 times
  4. 0108next:mov ah,[si]; one byte
  5. 010Asub ah,al; minus the key
  6. 010Cmov [si],ah; written back
  7. 010Einc si; the next byte
  8. 010Finc al; the next key
  9. 0111loop next
The same in C
  1. byte *s = credit;// 01ABh
  2. byte key = 4;
  3. for (n = 65; n > 0; n--) {
  4. *s = *s - key;// unscramble
  5. s++;
  6. key++;
  7. }
Watches
SI
01ABh byte 1 of 65
AL
0 the key
CX
0 bytes still to go
Help

His read pointer starts at the 65 scrambled bytes. In a file viewer they read as nonsense.

TRY IT scramble your own name his way
In the file After his loop

The last slide signs the show in Arabic for every viewer: برمجة ياسر محمد على, “Programmed by Yasser Mohamed Ali”. The scrambled lines are the signature inside the code: KEMYAM Software Corp., <c>1991 YASSER MOHAMED ALI.

In paid work he hid his name this way so that nobody could remove it easily. Today we call this obfuscation. A search of the file finds nothing, and a byte editor cannot change the name without knowing his rule.

Every Byte of DEMO.COM

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:\ARABIC\DEMO.COM

4,864 bytes on the disk, packed by DIET

25,899 bytes in memory, 25,899 of them his own code

  • Picture99%
  • Code0.7%
  • Text0.3%
  • Empty space<0.1%

The biggest parts, his first

  1. Slide script25,653 bytesYasser
  2. Slide player152 bytesYasser
  3. Scrambled credit65 bytesYasser
  4. Credit decoder19 bytesYasser
  5. Tail10 bytesYasser

Mapped by hand from the program’s own bytes.

Open in the byte mapSee the packed file