Layout Dynamic Publisher schermen Versie : 1.0 Datum : 11-mei-1991 Auteur : Hans Otten BBS: Risoft 01804-15958 De layout van een schermbestand (.PCT) van Dynamic Publisher is niet door de makers gepubliceerd. Om zelf met dit soort bestanden om te gaan heb ik door experimenten -- een test scherm aanmaken en dan met een diskmonitor het bestand bestuderen -- de layout ontrafeld. Met behulp van deze specificatie ben ik er in geslaagd mijn conversie programma CNVS (PCX naar MSX schermen en omgekeerd) uit te breiden met invoer uit Dynamic Publisher schermen. Deze specificatie bevat voldoende informatie om zelf programma's te schrijven die Dynamic Publisher schermen inlezen of aanmaken. Alle gebruikte getallen in deze specificatie zijn hexadecimaal. Het eerste gedeelte van deze specificatie beschrijft de layout in algemene termen. In het tweede deel heb ik een aantal code fragmenten uit mijn CNVS programma opgenomen waarmee een Dynamic Publisher scherm wordt ingelezen. 1. Bestand Een Dynamic Publisher bestand heeft meestal de extensie .PCT. Door gebruik te maken van simpele compressie is de grootte van het bestand niet vast, hoe meer details, des te groter wordt het bestand. Het scherm bestand is binair van aard, een programma zal het byte voor byte moeten benaderen. De beeldinformatie heeft de vaste afmetingen van 512 bij 702 punten. De breedte van 512 sluit aan bij het gebruikte MSX scherm 6. Het beeld is monochroom (alleen zwart-wit informatie). Een punt heeft dus de waarde 0 (wit op Dynamic Publisher scherm) of 1 (zwart). 2. Layout Een scherm bestand bestaat uit drie delen: Header Kader-informatie Beelddata 3. Header De header dient ter identificatie van het type bestand. De lengte bedraagt 24 bytes en de inhoud is de tekst 'DYNAMIC PUBLISHER SCREEN' 0000 44 59 4E 41 4D 49 43 20 50 55 42 4C 49 53 48 45 0000 D Y N A M I C P U B L I S H E 0010 52 20 53 43 52 45 45 4E 0010 R S C R E E N Er is een duitstalige versie van Dynamic Publisher met de naam Euro Publisher. De header bevat dan : 0000 45 20 55 20 52 20 4F 20 50 55 42 4C 49 53 48 45 0010 52 20 53 43 52 45 45 4E 0000 E U R O P U B L I S H E 0010 52 20 53 43 52 45 45 4E 0010 R S C R E E N 4. Kader De kader informatie wordt opgeslagen van lokatie 0018 tot 017F. De inhoud kan worden genegeerd bij lezen of bij schrijven worden gevuld met 00. 5. Data De beeldpunten worden met een eenvoudige compressiemethode opgeslagen. Er zijn 702 lijnen met elk 512 punten op te slaan, elke lijn wordt apart opgeslagen. Een lijn loopt van links naar rechts, de data begint bij de bovenste lijn. De gebruikte compressie is van het type runlength encoding. Daarbij wordt een herhalend patroon opgeslagen als een teller die het aantal herhalingen aangeeft gevolgd door het patroon. Omdat een plaatje veel herhalende patronen bevat (veel lege plekken) kunnen hier flinke besparingen mee worden bereikt. Bij Dynamic Publisher is de teller 1 byte groot en het patroon een of meer bytes waarin meerdere punten worden opgeborgen. Er zijn twee mogelijkheden voor de tellerbyte: a. Van het tellerbyte is het MSB (meest significante bit) gezet. Dan is de herhalingsteller gelijk aan het tellerbyte met het MSB weggelaten plus 1. En er volgt 1 databyte na het tellerbyte dat 'herhalingsteller' maal herhaald moet worden. b. Het MSB van het tellerbyte is niet gezet. Dan is de herhalingsteller de tellerbyte plus 1 . Na het tellerbyte volgen 'herhalingsteller' maal databytes. Databyte Een databyte bevat acht punten. Eerst moeten we het byte in twee nibbles (4 bits) verdelen : eerst het minst significante en daarna het meest significante. Van een nibble nemen we nu eerst het meest significante bit en werken door tot het minst significante om de punten op de lijn te vinden. Een bit met de waarde 1 betekent een gezet (bij Dynamic Publisher dus zwart) punt. Voorbeelden: a. Een aantal lege eerste lijnen op het scherm: 0180 BF 00 BF 00 BF 00 BF 00 BF 00 BF 00 BF 00 BF 00 Het byte op lokatie 0180 heeft de waarde BF. Het MSB is gezet en de herhalingsteller heeft de waarde 3F. Er worden dus 64 databytes herhaald, met 8 punten per byte zijn dit 512 punten oftewel een gehele regel. Omdat het databyte de waarde 0 heeft is het een lege regel. b. Een punt op positie 145,108 (decimaal) (lijn 108, kolom 145). 0250 BF 00 BF 00 BF 00 BF 00 91 00 00 04 AC 00 BF 00 ^ De lijn 108 begint bij de tellerbyte 91: MSB gezet dus er volgen (91 and 80) + 1 = 12 databytes met de waarde nul: 144 (decimaal) niet gezette punten. Daarna komt tellerbyte 00, dus 1 databyte met de waarde 04. Het minst significante nibble heeft de waarde 4, dus het eerste punt is gezet en de daarna volgende drie niet. Positie 145 (decimaal) op de lijn is dus gezet. Het meest significante nibble heeft de waarde 0, dus de volgende vier punten zijn niet gezet. We zijn nu 152 posities op de lijn gevorderd. En de lijn wordt volgemaakt door het volgende tellerbyte met de waarde AC: herhalingsteller is (AC and 80) + 1 = 2D. En dat levert 360 (decimaal) punten niet gezet op, in totaal (152 + 360) = 512 (decimaal) punten. Uit mijn CNVS programma volgen nu een aantal code fragmenten waarmee een Dynamic Publisher scherm bestand wordt gelezen. Het programma is geschreven in Turbo Pascal. Het is geen volledig programma, alleen de interessante delen zijn opgenomen. Een '$' voor een getal beteknt dat dit een hexadecimale notatie is. Gebruikte routines: Function GetNextByte : char ; levert volgende byte van invoer bestand op Display_pixel(x,y, kleur) Verwerk (toon op scherm of converteer) punt op positie x,y met de aangegeven kleur (0 = zwart, 1 = wit ) Header lezen procedure LeesPCTHeader ; var publisher_string : string[24] ; count : integer ; begin { lees PCT header } count := 0 ; publisher_string := '' ; { lees 23 bytes } repeat publisher_string := publisher_string + GetNextByte ; count := count + 1 ; until count = 24 ; if (publisher_string <> 'DYNAMIC PUBLISHER SCREEN') and (publisher_string <> 'E U R O PUBLISHER SCREEN') then begin report_error('Geen PCT bestand') ; end ; end ; Kader lezen procedure LeesKader ; { kader informatie wordt overgeslagen } var b, count : integer ; begin for count := 24 to $17F do b := ord(GetNextByte) ; end ; procedure Lees_PCT_pixels { eerst LeesHeader en LeesKader uitvoeren om op de juiste positie in het bestand te beginnen } var count, row_count, col_byte_count, col_count, rep_count : integer ; pixel_line : array[1..512] of byte ; b : byte ; procedure Add_pixel_nibble(nibble : byte) ; { pak punten in nibble uit om toe te voegen aan pixel_line buffer } var count : integer ; begin { werk vanaf het meest significante bit af } for count := 1 to 4 do begin if ((nibble and 8) = 8) then pixel_line[col_count] := 1 else pixel_line[col_count] := 0 ; inc(col_count) ; { schuif volgende bit naar meest significante positie } nibble := nibble shl 1 ; end ; end ; { Add_packed_nibble } begin for row_count := 1 to 702 do begin col_byte_count := 0 ; col_count := 1 ; repeat { Get repeat count } b := ord(GetNextByte) ; { hoogste bit gezet ?} if ((b and $80) = $80) then begin { herhaal het data byte b and 80 maal } rep_count := (b and $7F) ; { Get databyte } b := ord(GetNextByte) ; for count := 0 to rep_count do begin add_pixel_nibble(b and $0F) ; add_pixel_nibble(b shr 4) ; inc(col_byte_count) ; end ; end else begin { er volgen b databytes } rep_count := b ; for count := 0 to rep_count do begin b := ord(GetNextByte) ; ( eerst het minst significante nibble } add_pixel_nibble(b and $0F) ; add_pixel_nibble(b shr 4) ; inc(col_byte_count) ; end ; end ; until col_byte_count >= 512 ; for col_count := 1 to 512 do Display_pixel(col_count,row_count,pixel_line[col_count]) ; end ; end ;