home *** CD-ROM | disk | FTP | other *** search
/ PC/CD FUN 24 / cdimage.iso / dos / GFX2 / TECH_ENG.TXT < prev    next >
Encoding:
Text File  |  1996-12-12  |  28.8 KB  |  694 lines

  1. ┌────────────────────────────────────────────────────────────────────────────┐
  2. │░▒▓█ Technical documentation for GrafX 2.00 - Version 1.03 (12/12/1996) █▓▒░│
  3. └────────────────────────────────────────────────────────────────────────────┘
  4.  
  5. This file deals with:
  6.  
  7.   - the PKM picture format
  8.   - the values to send to the CRTC to access all the amazing video modes
  9.     available in GrafX 2.00
  10.  
  11.  
  12.  
  13. ┌────────────────────────────────────────────────────────────────────────────┐
  14. │            ░▒▓█ The PKM picture format - by Karl Maritaud █▓▒░             │
  15. └────────────────────────────────────────────────────────────────────────────┘
  16.  
  17.  
  18.     First of all, I'd like to say that I made this file format some years ago
  19.   when I didn't knew how to load any good format (eg. GIF) and wanted to have
  20.   my own format.
  21.     PKM format was designed to be very simple, easy to encode and decode. Its
  22.   header is very simple (short) and evolutive.
  23.     The only real default I can find in this format is that you can only save
  24.   256-color pictures.
  25.     I know that you will think:
  26.       "Oh no just another fucking format! I'll never use it! Its compression
  27.       is too poor and I prefer GIF!".
  28.     And I'll answer:
  29.       "Yeah! You're right. But if you dunno how to load GIF and want a simple
  30.       format with a quite good compression rate (on simple pictures at least),
  31.       it could be useful."
  32.  
  33.   So, here comes the format documentation...
  34.  
  35.  
  36.  
  37. The HEADER:
  38. ═══════════
  39.  
  40.   The header is the following 780-byte-structure. (Don't worry about the size.
  41.   That's just because the palette is considered as a part of the header).
  42.  
  43.  
  44.   ┌─────┬───────────┬──────┬──────┬──────────────────────────────────────────┐
  45.   │ Pos │ Field     │ Type │ Size │ Description                              │
  46.   ╞═════╪═══════════╪══════╪══════╪══════════════════════════════════════════╡
  47.   │   0 │ Signature │ char │   3  │ Constant string "PKM" (with NO size      │
  48.   │     │           │      │      │ delimitation '\0' or so...)              │
  49.   ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
  50.   │   3 │ Version   │ byte │   1  │ For the moment, it can take only the     │
  51.   │     │           │      │      │ value 0.                                 │
  52.   │     │           │      │      │ Other packing methods may change this    │
  53.   │     │           │      │      │ field but there is only one for now...   │
  54.   ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
  55.   │   4 │ Pack_byte │ byte │   1  │ Value of the recognition byte for color  │
  56.   │     │           │      │      │ repetitions that are coded on 1 byte.    │
  57.   │     │           │      │      │ (See the picture packing section for a   │
  58.   │     │           │      │      │ better explanation)                      │
  59.   ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
  60.   │   5 │ Pack_word │ byte │   1  │ Value of the recognition byte for color  │
  61.   │     │           │      │      │ repetitions that are coded on 2 bytes.   │
  62.   │     │           │      │      │ (See the picture packing section...)     │
  63.   ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
  64.   │   6 │ Width     │ word │   2  │ Picture width  (in pixels)               │
  65.   ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
  66.   │   8 │ Height    │ word │   2  │ Picture height (in pixels)               │
  67.   ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
  68.   │  10 │ Palette   │ byte │ 768  │ RGB palette (RGB RGB ... 256 times) with │
  69.   │     │           │      │      │ values from 0 to 63. I know the standard │
  70.   │     │           │      │      │ in picture files is 0 to 255 but I find  │
  71.   │     │           │      │      │ it stupid! It is really easier to send   │
  72.   │     │           │      │      │ the whole palette in port 3C9h with a    │
  73.   │     │           │      │      │ REP OUTSB without palette convertion.    │
  74.   ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
  75.   │ 778 │ PH_size   │ word │   2  │ Post-header size. This is the number of  │
  76.   │     │           │      │      │ bytes between the header and the picture │
  77.   │     │           │      │      │ data. This value can be equal to 0.      │
  78.   └─────┴───────────┴──────┴──────┴──────────────────────────────────────────┘
  79.  
  80.   Data of type "word" are stored with Intel conventions: lower byte first.
  81.  
  82.  
  83.  
  84. The POST-HEADER:
  85. ════════════════
  86.  
  87.   The post-header has a variable size. It was designed to support new features
  88. for this file format without changing the whole format.
  89.  
  90.   It consists in field identifiers followed by their size and their value.
  91.   A field identifier is coded with 1 byte and a field size also.
  92.  
  93.  
  94.   These field identifiers are:  (this list may be updated...)
  95.   ────────────────────────────
  96.  
  97.     0 : Comment on the picture
  98.     1 : Original screen dimensions
  99.  
  100.   If you encounter a field that you don't know just jump over it. But if a
  101.   field tells you to jump to a position that is over the beginning of the
  102.   picture data, there is an error in the file.
  103.  
  104.  
  105.   The fields:
  106.   ───────────
  107.  
  108.     * Comment:
  109.  
  110.       With this field, artists will be able to comment their pictures.
  111.       Note that GrafX 2 has a comment size limit of 32 chars. But you can
  112.       comment a picture with up to 255 chars if you make your own viewer
  113.       since GrafX 2 will just ignore extra characters.
  114.  
  115.       Example: [0],[16],[Picture by X-Man]
  116.       This sequence means:
  117.         - the field is a comment
  118.         - the comment takes 16 characters (there is no end-of-string character
  119.           since you know its size)
  120.         - the comment is "Picture by X-Man"
  121.  
  122.     * Original screen dimensions:
  123.  
  124.       Since GrafX 2 supplies a huge range of resolutions, it seemed convenient
  125.       to add a field that indicates what were the original screen dimensions.
  126.  
  127.       Example: [1],[4],[320],[256]
  128.       This sequence means:
  129.         - the field is a screen dimensions descriptor
  130.         - the dimensions are 2 words (so this value must be always equal to 4)
  131.         - the original screen width was 320 pixels
  132.         - the original screen height was 256 pixels
  133.  
  134.       Note that words stored in fields are written Intel-like. The 90% BETA
  135.       version did not respect this norm. I'm really sorry about this. This is
  136.       not very serious but pictures saved with version 90% and loaded with a
  137.       latest version (91% and more) won't set the right resolution.
  138.  
  139.  
  140. The PICTURE PACKING METHOD:
  141. ═══════════════════════════
  142.  
  143.   The PKM compression method is some sort of Run-Length-Compression which is
  144. very efficient on pictures with long horizontal color repetitions.
  145.   Actually, the compression is efficient if there are often more than 3 times
  146. the same color consecutively.
  147.  
  148.   I think that it would be better to give you the algorithm instead of swim-
  149. ming in incomprehensible explanations.
  150.  
  151.  
  152.   BEGIN
  153.     /*
  154.       functions:
  155.         Read_byte(File)       reads and returns 1 byte from File
  156.         Draw_pixel(X,Y,Color) draws a pixel of a certain Color at pos. (X,Y)
  157.         File_length(File)     returns the total length in bytes of File
  158.  
  159.       variables:
  160.         type of Image_size          is dword
  161.         type of Data_size           is dword
  162.         type of Packed_data_counter is dword
  163.         type of Pixels_counter      is dword
  164.         type of Color               is byte
  165.         type of Byte_read           is byte
  166.         type of Word_read           is word
  167.         type of Counter             is word
  168.         type of File                is <file> (depends on the language)
  169.     */
  170.  
  171.     /* At this point you've already read the header and post-header. */
  172.  
  173.     Image_size          <- Header.Width * Header.Height
  174.     Data_size           <- File_length(File) - (780+Header.PH_size)
  175.  
  176.     Packed_data_counter <- 0
  177.     Pixels_counter      <- 0
  178.  
  179.     Byte_read           <- Read_byte(File)
  180.  
  181.     /* Depacking loop: */
  182.     WHILE ((Pixels_counter<Image_size) AND (Packed_data_counter<Data_size)) DO
  183.     {
  184.  
  185.       /* If it is not a packet recognizer, it's a raw pixel */
  186.       IF ((Byte_read<>Header.Pack_byte) AND (Byte_read<>Header.Pack_word))
  187.       THEN
  188.       {
  189.         Draw_pixel(Pixels_counter MOD Header.Width,
  190.                    Pixels_counter DIV Header.Width,
  191.                    Byte_read)
  192.  
  193.         Pixels_counter      <- Pixels_counter + 1
  194.         Packed_data_counter <- Packed_data_counter + 1
  195.         Byte_read           <- Read_byte(File)
  196.       }
  197.       ELSE /* Is the number of pixels to repeat coded... */
  198.       {    /* ... with 1 byte */
  199.         IF (Byte_read = Header.Pack_byte) THEN
  200.         {
  201.           Color     <- Read_byte(File)
  202.           Byte_read <- Read_byte(File)
  203.  
  204.           FOR Counter FROM 0 TO (Byte_read-1) STEP +1
  205.             Draw_pixel((Pixels_counter+Counter) MOD Header.Width,
  206.                        (Pixels_counter+Counter) DIV Header.Width,
  207.                        Color)
  208.  
  209.           Pixels_counter      <- Pixels_counter + Byte_read
  210.           Packed_data_counter <- Packed_data_counter + 3
  211.           Byte_read           <- Read_byte(File)
  212.         }
  213.         ELSE /* ... with 2 bytes */
  214.         {
  215.           Color     <- Read_byte(File)
  216.           Word_read <- (word value) (Read_byte(File) SHL 8)+Read_byte(File)
  217.  
  218.           FOR Counter FROM 0 TO (Word_read-1) STEP +1
  219.             Draw_pixel((Pixels_counter+Counter) MOD Header.Width,
  220.                        (Pixels_counter+Counter) DIV Header.Width,
  221.                        Color)
  222.  
  223.           Pixels_counter      <- Pixels_counter + Word_read
  224.           Packed_data_counter <- Packed_data_counter + 4
  225.           Byte_read           <- Read_byte(File)
  226.         }
  227.       }
  228.  
  229.     }
  230.   END
  231.  
  232.  
  233.   For example, the following sequence:
  234.     (we suppose that Pack_byte=01 and Pack_word=02)
  235.     04 03 01 05 06 03 02 00 01 2C
  236.   will be decoded as:
  237.     04 03 05 05 05 05 05 05 03 00 00 00 ... (repeat 0 300 times (012Ch=300))
  238.  
  239.   Repetitions that fit in a word must be written with their higher byte first.
  240.   I know that it goes against Intel standard but since I read bytes from the
  241.   file thru a buffer (really faster), I don't care about the order (Sorry :)).
  242.   But words in the header and post-header must be written and read Intel-like!
  243.  
  244.  
  245.   Packing advices:
  246.   ────────────────
  247.  
  248.   * As you can see, there could be a problem when you'd want to pack a raw
  249.   pixel with a color equal to Pack_byte or Pack_word. These pixels should
  250.   always be coded as a packet even if there is only one pixel.
  251.  
  252.     Example: (we suppose that Pack_byte=9)
  253.       9   will be encoded 9,9,1     (The 1st 9 in the encoded...
  254.       9,9 will be encoded 9,9,2     ... sequence is Pack_byte)
  255.       etc...
  256.  
  257.   * It seems obvious to find values for Pack_byte and Pack_word that are
  258.   (almost) never used. So a small routine that finds the 2 less used colors
  259.   in the image should be called before starting to pack the picture. This can
  260.   be done almost instantaneously in Assembler.
  261.  
  262.   * When you want to pack a 2-color-sequence, just write these 2 colors one
  263.   after the other (Color,Color) because it only takes 2 bytes instead of 3 if
  264.   you had to write a packet (Pack_byte,Color,2).
  265.  
  266.   * If you pack a very simple picture which has a sequence of more than 65535
  267.   same consecutive bytes, you must break the sequence and continue with a new
  268.   packet.
  269.  
  270.     Example: you have to pack 65635 same consecutive bytes (eg. color 0)
  271.       (we suppose that Pack_byte=01 and Pack_word=02)
  272.       You'll write: 02 00 FF FF 01 00 64        (FFFFh=65535, 64h=100)
  273.  
  274.  
  275.  
  276. ┌────────────────────────────────────────────────────────────────────────────┐
  277. │                  ░▒▓█ Setting GrafX 2.00 video modes █▓▒░                  │
  278. └────────────────────────────────────────────────────────────────────────────┘
  279.  
  280.  
  281.     All set-mode procs are in 386 ASM. Anyway, if you can't understand any
  282.   line of ASM, I really can't see the use you'll have of these procedures.
  283.  
  284.     They are designed to be used in FLAT memory model. Anyway, it wouldn't
  285.   take too much time for you to adapt them to the model you use since only
  286.   memory indexations can be affected by this (so use DS:SI instead of ESI,
  287.   ES:DI instead of EDI, and beware to the address 0A0000h that will become
  288.   0A000h:00000h).
  289.  
  290.  
  291. MCGA: (Standard VGA mode)
  292. ═════
  293.  
  294.     Is there anybody in this world who still don't now how to set the MCGA
  295.   320x200 256 colors mode ??!?
  296.     Well... I hope you are a novice if you read the 2 following lines :)
  297.  
  298.  
  299.     mov  ax,0013h
  300.     int  10h
  301.  
  302.  
  303.  
  304. X-Modes: (Extended VGA modes)
  305. ════════
  306.  
  307.     Well... I think the original Mode X was 320x240 but now, many people call
  308.   "X-Modes" (or Modes X) all the VGA modes that use more that 64Kb of video
  309.   memory with the "Chain-4" structure.
  310.     Setting a pixel in any X-Mode can be done by the one same function (but
  311.   I won't explain to you how to do that. You just have to tell the function
  312.   what the plane width (screen_width/4) is).
  313.     If you can't understand anything about what I say (chain-4, planes...),
  314.   just read any good documentation about Mode X.
  315.  
  316.     We'd like to thank the authors of XLIB2 for saving our time by having made
  317.   this useful function. We slightly optimized it for our needs but the most
  318.   important parts are here.
  319.  
  320.  
  321.     mov  ax,13h      ; Yeah! The MCGA mode again! All X-Modes must start from
  322.     int  10h         ; the standard VGA mode, but many things change after.
  323.  
  324.     mov  dx,3C4h     ; We will inform the TIMING SEQUENCER register to switch
  325.     mov  ax,0604h    ; in unchained mode (X-mode), without odd/even management
  326.     out  dx,ax       ; and with an access to the 256Kb of the video card.
  327.     mov  ax,0100h    ; Now we will engage the synchronous reset of the TS
  328.     out  dx,ax       ; register because we're about to play with registers.
  329.  
  330.     mov  esi,X_ptr   ; Pointer on the list of constants to send to the CRTC.
  331.     cld
  332.  
  333.     lodsb            ; This loads in AL a value that will tell what to do
  334.                      ; with the MISCELLANEOUS register, and increases ESI.
  335.                      ; The value is equal to ZERO => Nothing to do
  336.                      ;                    or ELSE => Send AL to MISCELLANEOUS
  337.  
  338.     or   al,al       ; Shall we modify the basic video mode?
  339.     jz   NoThankYou  ; No?─┐ Actually the answer is always "Yes".
  340.     mov  dx,3C2h     ;     │ Except for a few modes such as
  341.     out  dx,al       ;     │ 320x200 in Mode X
  342.     NoThankYou:      ; <───┘ (but our 320x200 is MCGA...)
  343.  
  344.     mov  dx,3C4h     ; Manipulations with MISCELLANEOUS register are over, we
  345.     mov  ax,0300h    ; can now disengage the synchronous register of the TS.
  346.     out  dx,ax
  347.  
  348.     ; Now, what about teasing the CRTC?
  349.  
  350.     mov  dx,3D4h     ; In the 18th register of the CRTC, we will disengage the
  351.     mov  al,11h      ; protection bit. Without this, the values we would have
  352.     out  dx,al       ; sent to the CRTC registers would have been ignored.
  353.     inc  dx
  354.     in   al,dx
  355.     and  al,7Fh
  356.     out  dx,al
  357.  
  358.     dec  dx          ; DX points back to the CRTC register entry
  359.     lodsb            ; This loads in AL the number of CRTC registers to modify
  360.     xor  ecx,ecx     ; You must clear ECX before...
  361.     mov  cl,al       ; ... starting to repeat AL (CL) times OUTSW
  362.     rep  outsw       ; Let's send all the CRTC parameters!
  363.  
  364.     ; Just in case the 20th CRTC register would have been forgotten in the
  365.     ; initialisation table, we can compute it by ourselves (Yeah, we are good
  366.     ; guys).
  367.  
  368.     mov  ax,Screen_width ; You must tell the routine what is the Screen width
  369.     shr  ax,3
  370.     mov  ah,al
  371.     mov  al,13h
  372.     out  dx,ax
  373.  
  374.     mov  dx,3C4h     ; Now you have the good resolution but there can be
  375.     mov  ax,0F02h    ; shitty pixels on the screen coming from the uncleared
  376.     out  dx,ax       ; memory areas.
  377.     mov  edi,0A0000h ; So we will clean memory starting from 0A0000h with the
  378.     xor  eax,eax     ; value 0 (whitch is the standard black) and on a range
  379.     mov  ecx,4000h   ; of 4000h dwords (256Kb).
  380.     rep  stosd       ; Let's wipe all this out.
  381.  
  382.  
  383.  
  384.   The constants table you must send is one of these:
  385.   (These are tables for C but they can be easily used in other languages)
  386.  
  387.   word X320Y224[] =
  388.     { 0x10E3, 0x6F06, 0xBA07, 0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0x0014,
  389.       0xC715, 0x0416, 0xE317, 0xE317 };
  390.   word X320Y240[] =
  391.     { 0x0AE3, 0x0D06, 0x3E07, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0x0014, 0xE715,
  392.       0x0616, 0xE317 };
  393.   word X320Y256[] =
  394.     { 0x0CE3, 0x2306, 0xB207, 0x0008, 0x6109, 0x0A10, 0xAC11, 0xFF12, 0x2013,
  395.       0x0014, 0x0715, 0x1A16, 0xE317 };
  396.   word X320Y270[] =
  397.     { 0x0BE7, 0x3006, 0xF007, 0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x0014,
  398.       0x1F15, 0x2F16, 0xE317 };
  399.   word X320Y282[] =
  400.     { 0x0CE3, 0x6206, 0xF007, 0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x2F13,
  401.       0x0014, 0x3C15, 0x5C16, 0xE317 };
  402.   word X320Y300[] =
  403.     { 0x0DE3, 0x4606, 0x1F07, 0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x2013,
  404.       0x0014, 0x2F15, 0x4416, 0xE317 };
  405.   word X320Y360[] =
  406.     { 0x09E3, 0x4009, 0x8810, 0x8511, 0x6712, 0x2013, 0x0014, 0x6D15, 0xBA16,
  407.       0xE317 };
  408.   word X320Y400[] =
  409.     { 0x03E3, 0x4009, 0x0014, 0xE317 };
  410.   word X320Y448[] =
  411.     { 0x0BE3, 0x6F06, 0xBA07, 0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0x0014,
  412.       0xC715, 0x0416, 0xE317 };
  413.   word X320Y480[] =
  414.     { 0x0AE3, 0x0D06, 0x3E07, 0x4009, 0xEA10, 0xAC11, 0xDF12, 0x0014, 0xE715,
  415.       0x0616 , 0xE317};
  416.   word X320Y512[] =
  417.     { 0x0CE3, 0x2306, 0xB207, 0x0008, 0x6009, 0x0A10, 0xAC11, 0xFF12, 0x2013,
  418.       0x0014, 0x0715, 0x1A16, 0xE317 };
  419.   word X320Y540[] =
  420.     { 0x0BE7, 0x3006, 0xF007, 0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x0014,
  421.       0x1F15, 0x2F16, 0xE317 };
  422.   word X320Y564[] =
  423.     { 0x0CE7, 0x6206, 0xF007, 0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x2013,
  424.       0x0014, 0x3C15, 0x5C16, 0xE317 };
  425.   word X320Y600[] =
  426.     { 0x0BE7, 0xBE06, 0xF007, 0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x0014,
  427.       0x5815, 0x7016, 0xE317 };
  428.   word X360Y200[] =
  429.     { 0x08E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x0014, 0xE317 };
  430.   word X360Y224[] =
  431.     { 0x10E3, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6F06, 0xBA07,
  432.       0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
  433.   word X360Y240[] =
  434.     { 0x11E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x0D06, 0x3E07,
  435.       0x4109, 0xEA10, 0xAC11, 0xDF12, 0x2D13, 0x0014, 0xE715, 0x0616, 0xE317 };
  436.   word X360Y256[] =
  437.     { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x2B06, 0xB207,
  438.       0x0008, 0x6109, 0x0E10, 0xAC11, 0xFF12, 0x2D13, 0x0014, 0x0715, 0x1A16,
  439.       0xE317 };
  440.   word X360Y270[] =
  441.     { 0x10E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x3006, 0xF007,
  442.       0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
  443.   word X360Y282[] =
  444.     { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6206, 0xF007,
  445.       0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x2F13, 0x0014, 0x3C15, 0x5C16,
  446.       0xE317 };
  447.   word X360Y300[] =
  448.     { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4606, 0x1F07,
  449.       0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x2D13, 0x0014, 0x2F15, 0xE317,
  450.       0x4416 };
  451.   word X360Y360[] =
  452.     { 0x0FE7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4009, 0x8810,
  453.       0x8511, 0x6712, 0x2D13, 0x0014, 0x6D15, 0xBA16, 0xE317 };
  454.   word X360Y400[] =
  455.     { 0x09E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4009, 0x0014,
  456.       0xE317 };
  457.   word X360Y448[] =
  458.     { 0x10E3, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6F06, 0xBA07,
  459.       0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
  460.   word X360Y480[] =
  461.     { 0x11E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x0D06, 0x3E07,
  462.       0x4009, 0xEA10, 0xAC11, 0xDF12, 0x2D13, 0x0014, 0xE715, 0x0616, 0xE317 };
  463.   word X360Y512[] =
  464.     { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x2B06, 0xB207,
  465.       0x0008, 0x6009, 0x0E10, 0xAC11, 0xff12, 0x2D13, 0x0014, 0x0715, 0x1A16,
  466.       0xE317 };
  467.   word X360Y540[] =
  468.     { 0x10E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x3006, 0xF007,
  469.       0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
  470.   word X360Y564[] =
  471.     { 0x12EB, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6206, 0xF007,
  472.       0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x2D13, 0x0014, 0x3C15, 0x5C16,
  473.       0xE317 };
  474.   word X360Y600[] =
  475.     { 0x10E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0xBE06, 0xF007,
  476.       0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x5815, 0x7016, 0xE317 };
  477.   word X400Y200[] =
  478.     { 0x08E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x0014, 0xE317 };
  479.   word X400Y224[] =
  480.     { 0x10E3, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6F06, 0xBA07,
  481.       0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
  482.   word X400Y240[] =
  483.     { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x0D06, 0x3E07,
  484.       0x0008, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0x3213, 0x0014, 0xE715, 0x0616,
  485.       0xE317 };
  486.   word X400Y256[] =
  487.     { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x2B06, 0xB207,
  488.       0x0008, 0x6109, 0x1310, 0xAC11, 0xFF12, 0x3213, 0x0014, 0x0715, 0x1A16,
  489.       0xE317 };
  490.   word X400Y270[] =
  491.     { 0x10E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x3006, 0xF007,
  492.       0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
  493.   word X400Y282[] =
  494.     { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6206, 0xF007,
  495.       0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x2F13, 0x0014, 0x3C15, 0x5C16,
  496.       0xE317 };
  497.   word X400Y300[] =
  498.     { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x4606, 0x1F07,
  499.       0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x3213, 0x0014, 0x2F15, 0x4416,
  500.       0xE317 };
  501.   word X400Y360[] =
  502.     { 0x0FE7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x4009, 0x8810,
  503.       0x8511, 0x6712, 0x3213, 0x0014, 0x6D15, 0xBA16, 0xE317 };
  504.   word X400Y400[] =
  505.     { 0x09E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x4009, 0x0014,
  506.       0xE317 };
  507.   word X400Y448[] =
  508.     { 0x10E3, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6F06, 0xBA07,
  509.       0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
  510.   word X400Y480[] =
  511.     { 0x11E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x0D06, 0x3E07,
  512.       0x4009, 0xEA10, 0xAC11, 0xDF12, 0x3213, 0x0014, 0xE715, 0x0616, 0xE317 };
  513.   word X400Y512[] =
  514.     { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x2B06, 0xB207,
  515.       0x0008, 0x6009, 0x1310, 0xAC11, 0xFF12, 0x3213, 0x0014, 0x0715, 0x1A16,
  516.       0xE317 };
  517.   word X400Y540[] =
  518.     { 0x10E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x3006, 0xF007,
  519.       0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
  520.   word X400Y564[] =
  521.     { 0x12EB, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6206, 0xF007,
  522.       0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x3213, 0x0014, 0x3C15, 0x5C16,
  523.       0xE317 };
  524.   word X400Y600[] =
  525.     { 0x10E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0xBE06, 0xF007,
  526.       0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x5815, 0x7016, 0xE317 };
  527.  
  528.  
  529.   The structure: (example)
  530.  
  531.        ┌────This is the number of values to send to the CRTC registers. This
  532.        │    is actually the number of words in the tables minus 1 (because the
  533.        │    1st word of the table is not sent to the CRTC but contains a value
  534.        │    to send to the MISCELLANEOUS register and the number of values to
  535.        │    send to the CRTC registers ;) ).
  536.        │
  537.        │ ┌──This is the value to send to the MISCEALLANEOUS register (or ZERO
  538.        │ │  if no value must be send to it).
  539.        │ │
  540.        │ │     ┌───This is a value to send to a register of the CRTC.
  541.        │ │     │
  542.        │ │     │ ┌─This is the index of the CRTC register which will recieve
  543.        │ │     │ │ the value.
  544.        ├┐├┐    ├┐├┐
  545.    { 0x0AE3, 0x0D06, 0x3E07, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0x0014, 0xE715,
  546.      0x0616, 0xE317 };
  547.  
  548.     You can notice that CRTC registers 0 to 5 (and 13h) define the screen
  549.   width while registers 6 to 17h (except 13h) define the screen height.
  550.  
  551.  
  552.     We have more modes in our pocket than the "few" :) ones we included in
  553.   GrafX 2.00, but they aren't really useful or stable. But we may decice to
  554.   include them anyway in a next version if we modify the Set-resolution-window
  555.   (a list of modes just like the file selector would be the best choice if we
  556.   add more video modes).
  557.     If some of your favourite modes are missing, just send us the list of
  558.   constants we must shoot into the CRTC just following the structure we use
  559.   above.
  560.  
  561.   IMPORTANT! The constant values listed above are not supported by every
  562.              monitor or video card.
  563.              We have tested GrafX2 with several different configurations and
  564.              we constated that some modes don't work at all with some video
  565.              cards while some others can be overscanned, out of center, dark,
  566.              too bright, or shrunk.
  567.              But they all work fine with our poor little Tseng Labs ET4000...
  568.  
  569.   If you already have a good knowledge about X-Modes and have different values
  570.   than ours for certain modes, please let us know. We'll use them if they work
  571.   better with a majority of computers.
  572.  
  573.  
  574.  
  575. VESA: (A "pseudo-standard" for Super-VGA modes)
  576. ═════
  577.  
  578.     We use VESA for modes that require a width of 640, 800 or 1024 pixels.
  579.   But there is a way to combine X-Modes height with VESA so it's possible to
  580.   have modes as weird as in X-Mode.
  581.  
  582.  
  583.   mov  ax,4F02h
  584.   mov  bx,Video_mode
  585.   int  10h
  586.  
  587.  
  588.   256-color-VESA video modes are:
  589.     100h :  640x400
  590.     101h :  640x480
  591.     103h :  800x600
  592.     105h : 1024x768
  593.     107h : 1280x1024 (not available in GrafX2 because only supported with
  594.                      video cards with 2 or more Megabytes of video memory)
  595.  
  596.  
  597.   As with X-Modes, you can modify CRTC registers to access "Xtd-VESA" modes!
  598.   (Note that some video cards don't support the modification of the VGA CRTC
  599.   registers in VESA modes.)
  600.  
  601.  
  602.   To enter these extended VESA modes, set a standard VESA mode with the right
  603.   width, and then call Modify_CRTC_registers with the proper Height table.
  604.  
  605.   Example (640x512) :
  606.     VESA_Set_mode(101h)          /* Set a video mode with the same width */
  607.     Modify_CRTC_registers(Y512)  /* Modify height */
  608.  
  609.  
  610.   * Height tables:
  611.  
  612.   word Y224[] =
  613.     { 0x09E3, 0x6F06, 0xBA07, 0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0xC715,
  614.       0x0416 };
  615.   word Y240[] =
  616.     { 0x09E3, 0x0D06, 0x3E07, 0x0008, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0xE715,
  617.       0x0616 };
  618.   word Y256[] =
  619.     { 0x0900, 0x2B06, 0xB207, 0x0008, 0x6109, 0x0A10, 0xAC11, 0xFF12, 0x0715,
  620.       0x1A16 };
  621.   word Y270[] =
  622.     { 0x09E7, 0x3006, 0xF007, 0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x1F15,
  623.       0x2F16 };
  624.   word Y282[] =
  625.     { 0x0CE3, 0x6206, 0xF007, 0x0008, 0x6109, 0x310F, 0x3710, 0x8911, 0x3312,
  626.       0x2F13, 0x0014, 0x3C15, 0x5C16 };
  627.   word Y300[] =
  628.     { 0x09E3, 0x4606, 0x1F07, 0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x2F15,
  629.       0x4416 };
  630.   word Y350[] =
  631.     { 0x09A3, 0xBF06, 0x1F07, 0x0008, 0x4009, 0x8310, 0x8511, 0x5D12, 0x6315,
  632.       0xBA16 };
  633.   word Y360[] =
  634.     { 0x09E3, 0x0008, 0x4009, 0x8810, 0x8511, 0x6712, 0x2013, 0x0014, 0x6D15,
  635.       0xBA16 };
  636.   word Y400[] =
  637.     { 0x02E3, 0x4009, 0x0014 };
  638.   word Y448[] =
  639.     { 0x09E3, 0x6F06, 0xBA07, 0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0xC715,
  640.       0x0416 };
  641.   word Y480[] =
  642.     { 0x09E3, 0x0D06, 0x3E07, 0x0008, 0x4009, 0xEA10, 0xAC11, 0xDF12, 0xE715,
  643.       0x0616 };
  644.   word Y512[] =
  645.     { 0x0900, 0x2B06, 0xB207, 0x0008, 0x6009, 0x0A10, 0xAC11, 0xFF12, 0x0715,
  646.       0x1A16 };
  647.   word Y540[] =
  648.     { 0x09E7, 0x3006, 0xF007, 0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x1F15,
  649.       0x2F16 };
  650.   word Y564[] =
  651.     { 0x09E7, 0x6206, 0xF007, 0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x3C15,
  652.       0x5C16 };
  653.   word Y600[] =
  654.     { 0x09E7, 0xBE06, 0xF007, 0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x5815,
  655.       0x7016 };
  656.  
  657.  
  658.  
  659.   Modifying CRTC registers: (inspired by X-Modes init... See above for more
  660.   ─────────────────────────  details or comments)
  661.  
  662.   mov  esi,XVESA_Ptr
  663.   cld
  664.  
  665.   lodsb
  666.   or   al,al       ; Shall we modify the basic video mode?
  667.   jz   NoThankYou  ; No?─┐ The answer can be "No" because initialisations
  668.   mov  dx,3C2h     ;     │ of certain VESA modes directly set the right
  669.   out  dx,al       ;     │ value for the Miscellaneous register.
  670.   NoThankYou:      ; <───┘
  671.  
  672.   mov  dx,3D4h
  673.   mov  al,11h
  674.   out  dx,al
  675.   inc  dx
  676.   in   al,dx
  677.   and  al,7Fh
  678.   out  dx,al
  679.  
  680.   dec  dx
  681.   lodsb
  682.   xor  ecx,ecx
  683.   mov  cl,al
  684.   rep  outsw
  685.  
  686.  
  687.  
  688.     If you are cunning enough, you'll be able to combine constants used in
  689.   X-Modes to get more "Xtd-VESA" modes such as 640x200, 800x480, etc...
  690.   (but I don't think this will work with 1024x??? because this mode is
  691.   generally interlaced... But who knows?...)
  692.     The most difficult is to find the right value for the MISCELLANEOUS
  693.   register.
  694.