home *** CD-ROM | disk | FTP | other *** search
- ┌────────────────────────────────────────────────────────────────────────────┐
- │░▒▓█ Technical documentation for GrafX 2.00 - Version 1.03 (12/12/1996) █▓▒░│
- └────────────────────────────────────────────────────────────────────────────┘
-
- This file deals with:
-
- - the PKM picture format
- - the values to send to the CRTC to access all the amazing video modes
- available in GrafX 2.00
-
-
-
- ┌────────────────────────────────────────────────────────────────────────────┐
- │ ░▒▓█ The PKM picture format - by Karl Maritaud █▓▒░ │
- └────────────────────────────────────────────────────────────────────────────┘
-
-
- First of all, I'd like to say that I made this file format some years ago
- when I didn't knew how to load any good format (eg. GIF) and wanted to have
- my own format.
- PKM format was designed to be very simple, easy to encode and decode. Its
- header is very simple (short) and evolutive.
- The only real default I can find in this format is that you can only save
- 256-color pictures.
- I know that you will think:
- "Oh no just another fucking format! I'll never use it! Its compression
- is too poor and I prefer GIF!".
- And I'll answer:
- "Yeah! You're right. But if you dunno how to load GIF and want a simple
- format with a quite good compression rate (on simple pictures at least),
- it could be useful."
-
- So, here comes the format documentation...
-
-
-
- The HEADER:
- ═══════════
-
- The header is the following 780-byte-structure. (Don't worry about the size.
- That's just because the palette is considered as a part of the header).
-
-
- ┌─────┬───────────┬──────┬──────┬──────────────────────────────────────────┐
- │ Pos │ Field │ Type │ Size │ Description │
- ╞═════╪═══════════╪══════╪══════╪══════════════════════════════════════════╡
- │ 0 │ Signature │ char │ 3 │ Constant string "PKM" (with NO size │
- │ │ │ │ │ delimitation '\0' or so...) │
- ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
- │ 3 │ Version │ byte │ 1 │ For the moment, it can take only the │
- │ │ │ │ │ value 0. │
- │ │ │ │ │ Other packing methods may change this │
- │ │ │ │ │ field but there is only one for now... │
- ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
- │ 4 │ Pack_byte │ byte │ 1 │ Value of the recognition byte for color │
- │ │ │ │ │ repetitions that are coded on 1 byte. │
- │ │ │ │ │ (See the picture packing section for a │
- │ │ │ │ │ better explanation) │
- ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
- │ 5 │ Pack_word │ byte │ 1 │ Value of the recognition byte for color │
- │ │ │ │ │ repetitions that are coded on 2 bytes. │
- │ │ │ │ │ (See the picture packing section...) │
- ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
- │ 6 │ Width │ word │ 2 │ Picture width (in pixels) │
- ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
- │ 8 │ Height │ word │ 2 │ Picture height (in pixels) │
- ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
- │ 10 │ Palette │ byte │ 768 │ RGB palette (RGB RGB ... 256 times) with │
- │ │ │ │ │ values from 0 to 63. I know the standard │
- │ │ │ │ │ in picture files is 0 to 255 but I find │
- │ │ │ │ │ it stupid! It is really easier to send │
- │ │ │ │ │ the whole palette in port 3C9h with a │
- │ │ │ │ │ REP OUTSB without palette convertion. │
- ├─────┼───────────┼──────┼──────┼──────────────────────────────────────────┤
- │ 778 │ PH_size │ word │ 2 │ Post-header size. This is the number of │
- │ │ │ │ │ bytes between the header and the picture │
- │ │ │ │ │ data. This value can be equal to 0. │
- └─────┴───────────┴──────┴──────┴──────────────────────────────────────────┘
-
- Data of type "word" are stored with Intel conventions: lower byte first.
-
-
-
- The POST-HEADER:
- ════════════════
-
- The post-header has a variable size. It was designed to support new features
- for this file format without changing the whole format.
-
- It consists in field identifiers followed by their size and their value.
- A field identifier is coded with 1 byte and a field size also.
-
-
- These field identifiers are: (this list may be updated...)
- ────────────────────────────
-
- 0 : Comment on the picture
- 1 : Original screen dimensions
-
- If you encounter a field that you don't know just jump over it. But if a
- field tells you to jump to a position that is over the beginning of the
- picture data, there is an error in the file.
-
-
- The fields:
- ───────────
-
- * Comment:
-
- With this field, artists will be able to comment their pictures.
- Note that GrafX 2 has a comment size limit of 32 chars. But you can
- comment a picture with up to 255 chars if you make your own viewer
- since GrafX 2 will just ignore extra characters.
-
- Example: [0],[16],[Picture by X-Man]
- This sequence means:
- - the field is a comment
- - the comment takes 16 characters (there is no end-of-string character
- since you know its size)
- - the comment is "Picture by X-Man"
-
- * Original screen dimensions:
-
- Since GrafX 2 supplies a huge range of resolutions, it seemed convenient
- to add a field that indicates what were the original screen dimensions.
-
- Example: [1],[4],[320],[256]
- This sequence means:
- - the field is a screen dimensions descriptor
- - the dimensions are 2 words (so this value must be always equal to 4)
- - the original screen width was 320 pixels
- - the original screen height was 256 pixels
-
- Note that words stored in fields are written Intel-like. The 90% BETA
- version did not respect this norm. I'm really sorry about this. This is
- not very serious but pictures saved with version 90% and loaded with a
- latest version (91% and more) won't set the right resolution.
-
-
- The PICTURE PACKING METHOD:
- ═══════════════════════════
-
- The PKM compression method is some sort of Run-Length-Compression which is
- very efficient on pictures with long horizontal color repetitions.
- Actually, the compression is efficient if there are often more than 3 times
- the same color consecutively.
-
- I think that it would be better to give you the algorithm instead of swim-
- ming in incomprehensible explanations.
-
-
- BEGIN
- /*
- functions:
- Read_byte(File) reads and returns 1 byte from File
- Draw_pixel(X,Y,Color) draws a pixel of a certain Color at pos. (X,Y)
- File_length(File) returns the total length in bytes of File
-
- variables:
- type of Image_size is dword
- type of Data_size is dword
- type of Packed_data_counter is dword
- type of Pixels_counter is dword
- type of Color is byte
- type of Byte_read is byte
- type of Word_read is word
- type of Counter is word
- type of File is <file> (depends on the language)
- */
-
- /* At this point you've already read the header and post-header. */
-
- Image_size <- Header.Width * Header.Height
- Data_size <- File_length(File) - (780+Header.PH_size)
-
- Packed_data_counter <- 0
- Pixels_counter <- 0
-
- Byte_read <- Read_byte(File)
-
- /* Depacking loop: */
- WHILE ((Pixels_counter<Image_size) AND (Packed_data_counter<Data_size)) DO
- {
-
- /* If it is not a packet recognizer, it's a raw pixel */
- IF ((Byte_read<>Header.Pack_byte) AND (Byte_read<>Header.Pack_word))
- THEN
- {
- Draw_pixel(Pixels_counter MOD Header.Width,
- Pixels_counter DIV Header.Width,
- Byte_read)
-
- Pixels_counter <- Pixels_counter + 1
- Packed_data_counter <- Packed_data_counter + 1
- Byte_read <- Read_byte(File)
- }
- ELSE /* Is the number of pixels to repeat coded... */
- { /* ... with 1 byte */
- IF (Byte_read = Header.Pack_byte) THEN
- {
- Color <- Read_byte(File)
- Byte_read <- Read_byte(File)
-
- FOR Counter FROM 0 TO (Byte_read-1) STEP +1
- Draw_pixel((Pixels_counter+Counter) MOD Header.Width,
- (Pixels_counter+Counter) DIV Header.Width,
- Color)
-
- Pixels_counter <- Pixels_counter + Byte_read
- Packed_data_counter <- Packed_data_counter + 3
- Byte_read <- Read_byte(File)
- }
- ELSE /* ... with 2 bytes */
- {
- Color <- Read_byte(File)
- Word_read <- (word value) (Read_byte(File) SHL 8)+Read_byte(File)
-
- FOR Counter FROM 0 TO (Word_read-1) STEP +1
- Draw_pixel((Pixels_counter+Counter) MOD Header.Width,
- (Pixels_counter+Counter) DIV Header.Width,
- Color)
-
- Pixels_counter <- Pixels_counter + Word_read
- Packed_data_counter <- Packed_data_counter + 4
- Byte_read <- Read_byte(File)
- }
- }
-
- }
- END
-
-
- For example, the following sequence:
- (we suppose that Pack_byte=01 and Pack_word=02)
- 04 03 01 05 06 03 02 00 01 2C
- will be decoded as:
- 04 03 05 05 05 05 05 05 03 00 00 00 ... (repeat 0 300 times (012Ch=300))
-
- Repetitions that fit in a word must be written with their higher byte first.
- I know that it goes against Intel standard but since I read bytes from the
- file thru a buffer (really faster), I don't care about the order (Sorry :)).
- But words in the header and post-header must be written and read Intel-like!
-
-
- Packing advices:
- ────────────────
-
- * As you can see, there could be a problem when you'd want to pack a raw
- pixel with a color equal to Pack_byte or Pack_word. These pixels should
- always be coded as a packet even if there is only one pixel.
-
- Example: (we suppose that Pack_byte=9)
- 9 will be encoded 9,9,1 (The 1st 9 in the encoded...
- 9,9 will be encoded 9,9,2 ... sequence is Pack_byte)
- etc...
-
- * It seems obvious to find values for Pack_byte and Pack_word that are
- (almost) never used. So a small routine that finds the 2 less used colors
- in the image should be called before starting to pack the picture. This can
- be done almost instantaneously in Assembler.
-
- * When you want to pack a 2-color-sequence, just write these 2 colors one
- after the other (Color,Color) because it only takes 2 bytes instead of 3 if
- you had to write a packet (Pack_byte,Color,2).
-
- * If you pack a very simple picture which has a sequence of more than 65535
- same consecutive bytes, you must break the sequence and continue with a new
- packet.
-
- Example: you have to pack 65635 same consecutive bytes (eg. color 0)
- (we suppose that Pack_byte=01 and Pack_word=02)
- You'll write: 02 00 FF FF 01 00 64 (FFFFh=65535, 64h=100)
-
-
-
- ┌────────────────────────────────────────────────────────────────────────────┐
- │ ░▒▓█ Setting GrafX 2.00 video modes █▓▒░ │
- └────────────────────────────────────────────────────────────────────────────┘
-
-
- All set-mode procs are in 386 ASM. Anyway, if you can't understand any
- line of ASM, I really can't see the use you'll have of these procedures.
-
- They are designed to be used in FLAT memory model. Anyway, it wouldn't
- take too much time for you to adapt them to the model you use since only
- memory indexations can be affected by this (so use DS:SI instead of ESI,
- ES:DI instead of EDI, and beware to the address 0A0000h that will become
- 0A000h:00000h).
-
-
- MCGA: (Standard VGA mode)
- ═════
-
- Is there anybody in this world who still don't now how to set the MCGA
- 320x200 256 colors mode ??!?
- Well... I hope you are a novice if you read the 2 following lines :)
-
-
- mov ax,0013h
- int 10h
-
-
-
- X-Modes: (Extended VGA modes)
- ════════
-
- Well... I think the original Mode X was 320x240 but now, many people call
- "X-Modes" (or Modes X) all the VGA modes that use more that 64Kb of video
- memory with the "Chain-4" structure.
- Setting a pixel in any X-Mode can be done by the one same function (but
- I won't explain to you how to do that. You just have to tell the function
- what the plane width (screen_width/4) is).
- If you can't understand anything about what I say (chain-4, planes...),
- just read any good documentation about Mode X.
-
- We'd like to thank the authors of XLIB2 for saving our time by having made
- this useful function. We slightly optimized it for our needs but the most
- important parts are here.
-
-
- mov ax,13h ; Yeah! The MCGA mode again! All X-Modes must start from
- int 10h ; the standard VGA mode, but many things change after.
-
- mov dx,3C4h ; We will inform the TIMING SEQUENCER register to switch
- mov ax,0604h ; in unchained mode (X-mode), without odd/even management
- out dx,ax ; and with an access to the 256Kb of the video card.
- mov ax,0100h ; Now we will engage the synchronous reset of the TS
- out dx,ax ; register because we're about to play with registers.
-
- mov esi,X_ptr ; Pointer on the list of constants to send to the CRTC.
- cld
-
- lodsb ; This loads in AL a value that will tell what to do
- ; with the MISCELLANEOUS register, and increases ESI.
- ; The value is equal to ZERO => Nothing to do
- ; or ELSE => Send AL to MISCELLANEOUS
-
- or al,al ; Shall we modify the basic video mode?
- jz NoThankYou ; No?─┐ Actually the answer is always "Yes".
- mov dx,3C2h ; │ Except for a few modes such as
- out dx,al ; │ 320x200 in Mode X
- NoThankYou: ; <───┘ (but our 320x200 is MCGA...)
-
- mov dx,3C4h ; Manipulations with MISCELLANEOUS register are over, we
- mov ax,0300h ; can now disengage the synchronous register of the TS.
- out dx,ax
-
- ; Now, what about teasing the CRTC?
-
- mov dx,3D4h ; In the 18th register of the CRTC, we will disengage the
- mov al,11h ; protection bit. Without this, the values we would have
- out dx,al ; sent to the CRTC registers would have been ignored.
- inc dx
- in al,dx
- and al,7Fh
- out dx,al
-
- dec dx ; DX points back to the CRTC register entry
- lodsb ; This loads in AL the number of CRTC registers to modify
- xor ecx,ecx ; You must clear ECX before...
- mov cl,al ; ... starting to repeat AL (CL) times OUTSW
- rep outsw ; Let's send all the CRTC parameters!
-
- ; Just in case the 20th CRTC register would have been forgotten in the
- ; initialisation table, we can compute it by ourselves (Yeah, we are good
- ; guys).
-
- mov ax,Screen_width ; You must tell the routine what is the Screen width
- shr ax,3
- mov ah,al
- mov al,13h
- out dx,ax
-
- mov dx,3C4h ; Now you have the good resolution but there can be
- mov ax,0F02h ; shitty pixels on the screen coming from the uncleared
- out dx,ax ; memory areas.
- mov edi,0A0000h ; So we will clean memory starting from 0A0000h with the
- xor eax,eax ; value 0 (whitch is the standard black) and on a range
- mov ecx,4000h ; of 4000h dwords (256Kb).
- rep stosd ; Let's wipe all this out.
-
-
-
- The constants table you must send is one of these:
- (These are tables for C but they can be easily used in other languages)
-
- word X320Y224[] =
- { 0x10E3, 0x6F06, 0xBA07, 0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0x0014,
- 0xC715, 0x0416, 0xE317, 0xE317 };
- word X320Y240[] =
- { 0x0AE3, 0x0D06, 0x3E07, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0x0014, 0xE715,
- 0x0616, 0xE317 };
- word X320Y256[] =
- { 0x0CE3, 0x2306, 0xB207, 0x0008, 0x6109, 0x0A10, 0xAC11, 0xFF12, 0x2013,
- 0x0014, 0x0715, 0x1A16, 0xE317 };
- word X320Y270[] =
- { 0x0BE7, 0x3006, 0xF007, 0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x0014,
- 0x1F15, 0x2F16, 0xE317 };
- word X320Y282[] =
- { 0x0CE3, 0x6206, 0xF007, 0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x2F13,
- 0x0014, 0x3C15, 0x5C16, 0xE317 };
- word X320Y300[] =
- { 0x0DE3, 0x4606, 0x1F07, 0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x2013,
- 0x0014, 0x2F15, 0x4416, 0xE317 };
- word X320Y360[] =
- { 0x09E3, 0x4009, 0x8810, 0x8511, 0x6712, 0x2013, 0x0014, 0x6D15, 0xBA16,
- 0xE317 };
- word X320Y400[] =
- { 0x03E3, 0x4009, 0x0014, 0xE317 };
- word X320Y448[] =
- { 0x0BE3, 0x6F06, 0xBA07, 0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0x0014,
- 0xC715, 0x0416, 0xE317 };
- word X320Y480[] =
- { 0x0AE3, 0x0D06, 0x3E07, 0x4009, 0xEA10, 0xAC11, 0xDF12, 0x0014, 0xE715,
- 0x0616 , 0xE317};
- word X320Y512[] =
- { 0x0CE3, 0x2306, 0xB207, 0x0008, 0x6009, 0x0A10, 0xAC11, 0xFF12, 0x2013,
- 0x0014, 0x0715, 0x1A16, 0xE317 };
- word X320Y540[] =
- { 0x0BE7, 0x3006, 0xF007, 0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x0014,
- 0x1F15, 0x2F16, 0xE317 };
- word X320Y564[] =
- { 0x0CE7, 0x6206, 0xF007, 0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x2013,
- 0x0014, 0x3C15, 0x5C16, 0xE317 };
- word X320Y600[] =
- { 0x0BE7, 0xBE06, 0xF007, 0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x0014,
- 0x5815, 0x7016, 0xE317 };
- word X360Y200[] =
- { 0x08E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x0014, 0xE317 };
- word X360Y224[] =
- { 0x10E3, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6F06, 0xBA07,
- 0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
- word X360Y240[] =
- { 0x11E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x0D06, 0x3E07,
- 0x4109, 0xEA10, 0xAC11, 0xDF12, 0x2D13, 0x0014, 0xE715, 0x0616, 0xE317 };
- word X360Y256[] =
- { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x2B06, 0xB207,
- 0x0008, 0x6109, 0x0E10, 0xAC11, 0xFF12, 0x2D13, 0x0014, 0x0715, 0x1A16,
- 0xE317 };
- word X360Y270[] =
- { 0x10E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x3006, 0xF007,
- 0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
- word X360Y282[] =
- { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6206, 0xF007,
- 0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x2F13, 0x0014, 0x3C15, 0x5C16,
- 0xE317 };
- word X360Y300[] =
- { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4606, 0x1F07,
- 0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x2D13, 0x0014, 0x2F15, 0xE317,
- 0x4416 };
- word X360Y360[] =
- { 0x0FE7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4009, 0x8810,
- 0x8511, 0x6712, 0x2D13, 0x0014, 0x6D15, 0xBA16, 0xE317 };
- word X360Y400[] =
- { 0x09E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4009, 0x0014,
- 0xE317 };
- word X360Y448[] =
- { 0x10E3, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6F06, 0xBA07,
- 0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
- word X360Y480[] =
- { 0x11E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x0D06, 0x3E07,
- 0x4009, 0xEA10, 0xAC11, 0xDF12, 0x2D13, 0x0014, 0xE715, 0x0616, 0xE317 };
- word X360Y512[] =
- { 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x2B06, 0xB207,
- 0x0008, 0x6009, 0x0E10, 0xAC11, 0xff12, 0x2D13, 0x0014, 0x0715, 0x1A16,
- 0xE317 };
- word X360Y540[] =
- { 0x10E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x3006, 0xF007,
- 0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
- word X360Y564[] =
- { 0x12EB, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6206, 0xF007,
- 0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x2D13, 0x0014, 0x3C15, 0x5C16,
- 0xE317 };
- word X360Y600[] =
- { 0x10E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0xBE06, 0xF007,
- 0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x5815, 0x7016, 0xE317 };
- word X400Y200[] =
- { 0x08E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x0014, 0xE317 };
- word X400Y224[] =
- { 0x10E3, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6F06, 0xBA07,
- 0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
- word X400Y240[] =
- { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x0D06, 0x3E07,
- 0x0008, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0x3213, 0x0014, 0xE715, 0x0616,
- 0xE317 };
- word X400Y256[] =
- { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x2B06, 0xB207,
- 0x0008, 0x6109, 0x1310, 0xAC11, 0xFF12, 0x3213, 0x0014, 0x0715, 0x1A16,
- 0xE317 };
- word X400Y270[] =
- { 0x10E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x3006, 0xF007,
- 0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
- word X400Y282[] =
- { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6206, 0xF007,
- 0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x2F13, 0x0014, 0x3C15, 0x5C16,
- 0xE317 };
- word X400Y300[] =
- { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x4606, 0x1F07,
- 0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x3213, 0x0014, 0x2F15, 0x4416,
- 0xE317 };
- word X400Y360[] =
- { 0x0FE7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x4009, 0x8810,
- 0x8511, 0x6712, 0x3213, 0x0014, 0x6D15, 0xBA16, 0xE317 };
- word X400Y400[] =
- { 0x09E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x4009, 0x0014,
- 0xE317 };
- word X400Y448[] =
- { 0x10E3, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6F06, 0xBA07,
- 0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0xC715, 0x0416, 0xE317 };
- word X400Y480[] =
- { 0x11E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x0D06, 0x3E07,
- 0x4009, 0xEA10, 0xAC11, 0xDF12, 0x3213, 0x0014, 0xE715, 0x0616, 0xE317 };
- word X400Y512[] =
- { 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x2B06, 0xB207,
- 0x0008, 0x6009, 0x1310, 0xAC11, 0xFF12, 0x3213, 0x0014, 0x0715, 0x1A16,
- 0xE317 };
- word X400Y540[] =
- { 0x10E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x3006, 0xF007,
- 0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x1F15, 0x2F16, 0xE317 };
- word X400Y564[] =
- { 0x12EB, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6206, 0xF007,
- 0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x3213, 0x0014, 0x3C15, 0x5C16,
- 0xE317 };
- word X400Y600[] =
- { 0x10E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0xBE06, 0xF007,
- 0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x5815, 0x7016, 0xE317 };
-
-
- The structure: (example)
-
- ┌────This is the number of values to send to the CRTC registers. This
- │ is actually the number of words in the tables minus 1 (because the
- │ 1st word of the table is not sent to the CRTC but contains a value
- │ to send to the MISCELLANEOUS register and the number of values to
- │ send to the CRTC registers ;) ).
- │
- │ ┌──This is the value to send to the MISCEALLANEOUS register (or ZERO
- │ │ if no value must be send to it).
- │ │
- │ │ ┌───This is a value to send to a register of the CRTC.
- │ │ │
- │ │ │ ┌─This is the index of the CRTC register which will recieve
- │ │ │ │ the value.
- ├┐├┐ ├┐├┐
- { 0x0AE3, 0x0D06, 0x3E07, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0x0014, 0xE715,
- 0x0616, 0xE317 };
-
- You can notice that CRTC registers 0 to 5 (and 13h) define the screen
- width while registers 6 to 17h (except 13h) define the screen height.
-
-
- We have more modes in our pocket than the "few" :) ones we included in
- GrafX 2.00, but they aren't really useful or stable. But we may decice to
- include them anyway in a next version if we modify the Set-resolution-window
- (a list of modes just like the file selector would be the best choice if we
- add more video modes).
- If some of your favourite modes are missing, just send us the list of
- constants we must shoot into the CRTC just following the structure we use
- above.
-
- IMPORTANT! The constant values listed above are not supported by every
- monitor or video card.
- We have tested GrafX2 with several different configurations and
- we constated that some modes don't work at all with some video
- cards while some others can be overscanned, out of center, dark,
- too bright, or shrunk.
- But they all work fine with our poor little Tseng Labs ET4000...
-
- If you already have a good knowledge about X-Modes and have different values
- than ours for certain modes, please let us know. We'll use them if they work
- better with a majority of computers.
-
-
-
- VESA: (A "pseudo-standard" for Super-VGA modes)
- ═════
-
- We use VESA for modes that require a width of 640, 800 or 1024 pixels.
- But there is a way to combine X-Modes height with VESA so it's possible to
- have modes as weird as in X-Mode.
-
-
- mov ax,4F02h
- mov bx,Video_mode
- int 10h
-
-
- 256-color-VESA video modes are:
- 100h : 640x400
- 101h : 640x480
- 103h : 800x600
- 105h : 1024x768
- 107h : 1280x1024 (not available in GrafX2 because only supported with
- video cards with 2 or more Megabytes of video memory)
-
-
- As with X-Modes, you can modify CRTC registers to access "Xtd-VESA" modes!
- (Note that some video cards don't support the modification of the VGA CRTC
- registers in VESA modes.)
-
-
- To enter these extended VESA modes, set a standard VESA mode with the right
- width, and then call Modify_CRTC_registers with the proper Height table.
-
- Example (640x512) :
- VESA_Set_mode(101h) /* Set a video mode with the same width */
- Modify_CRTC_registers(Y512) /* Modify height */
-
-
- * Height tables:
-
- word Y224[] =
- { 0x09E3, 0x6F06, 0xBA07, 0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0xC715,
- 0x0416 };
- word Y240[] =
- { 0x09E3, 0x0D06, 0x3E07, 0x0008, 0x4109, 0xEA10, 0xAC11, 0xDF12, 0xE715,
- 0x0616 };
- word Y256[] =
- { 0x0900, 0x2B06, 0xB207, 0x0008, 0x6109, 0x0A10, 0xAC11, 0xFF12, 0x0715,
- 0x1A16 };
- word Y270[] =
- { 0x09E7, 0x3006, 0xF007, 0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x1F15,
- 0x2F16 };
- word Y282[] =
- { 0x0CE3, 0x6206, 0xF007, 0x0008, 0x6109, 0x310F, 0x3710, 0x8911, 0x3312,
- 0x2F13, 0x0014, 0x3C15, 0x5C16 };
- word Y300[] =
- { 0x09E3, 0x4606, 0x1F07, 0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x2F15,
- 0x4416 };
- word Y350[] =
- { 0x09A3, 0xBF06, 0x1F07, 0x0008, 0x4009, 0x8310, 0x8511, 0x5D12, 0x6315,
- 0xBA16 };
- word Y360[] =
- { 0x09E3, 0x0008, 0x4009, 0x8810, 0x8511, 0x6712, 0x2013, 0x0014, 0x6D15,
- 0xBA16 };
- word Y400[] =
- { 0x02E3, 0x4009, 0x0014 };
- word Y448[] =
- { 0x09E3, 0x6F06, 0xBA07, 0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0xC715,
- 0x0416 };
- word Y480[] =
- { 0x09E3, 0x0D06, 0x3E07, 0x0008, 0x4009, 0xEA10, 0xAC11, 0xDF12, 0xE715,
- 0x0616 };
- word Y512[] =
- { 0x0900, 0x2B06, 0xB207, 0x0008, 0x6009, 0x0A10, 0xAC11, 0xFF12, 0x0715,
- 0x1A16 };
- word Y540[] =
- { 0x09E7, 0x3006, 0xF007, 0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x1F15,
- 0x2F16 };
- word Y564[] =
- { 0x09E7, 0x6206, 0xF007, 0x0008, 0x6009, 0x3E10, 0x8911, 0x3312, 0x3C15,
- 0x5C16 };
- word Y600[] =
- { 0x09E7, 0xBE06, 0xF007, 0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x5815,
- 0x7016 };
-
-
-
- Modifying CRTC registers: (inspired by X-Modes init... See above for more
- ───────────────────────── details or comments)
-
- mov esi,XVESA_Ptr
- cld
-
- lodsb
- or al,al ; Shall we modify the basic video mode?
- jz NoThankYou ; No?─┐ The answer can be "No" because initialisations
- mov dx,3C2h ; │ of certain VESA modes directly set the right
- out dx,al ; │ value for the Miscellaneous register.
- NoThankYou: ; <───┘
-
- mov dx,3D4h
- mov al,11h
- out dx,al
- inc dx
- in al,dx
- and al,7Fh
- out dx,al
-
- dec dx
- lodsb
- xor ecx,ecx
- mov cl,al
- rep outsw
-
-
-
- If you are cunning enough, you'll be able to combine constants used in
- X-Modes to get more "Xtd-VESA" modes such as 640x200, 800x480, etc...
- (but I don't think this will work with 1024x??? because this mode is
- generally interlaced... But who knows?...)
- The most difficult is to find the right value for the MISCELLANEOUS
- register.
-