cleanup: doc moved to doc folder
git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@22 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
732
doc/tech_eng.txt
Normal file
732
doc/tech_eng.txt
Normal file
@@ -0,0 +1,732 @@
|
||||
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
||||
³°±²Û Technical documentation for GrafX 2.00 - Version 1.08 (10/05/1997) Û²±°³
|
||||
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||||
|
||||
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
|
||||
2 : Back color (transparent color)
|
||||
|
||||
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.
|
||||
|
||||
* Back color:
|
||||
|
||||
Saving the back color (transparent color) is especially useful when you
|
||||
want to save a brush.
|
||||
The size of this field is 1 byte (index of the color between 0 and 255).
|
||||
|
||||
Example: [2],[1],[255]
|
||||
This sequence means:
|
||||
- the field is a screen dimensions descriptor
|
||||
- the value takes 1 byte
|
||||
- the transparent color is 255
|
||||
|
||||
|
||||
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 <binary file>
|
||||
*/
|
||||
|
||||
/* 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
|
||||
|
||||
/* Depacking loop: */
|
||||
WHILE ((Pixels_counter<Image_size) AND (Packed_data_counter<Data_size)) DO
|
||||
{
|
||||
Byte_read <- Read_byte(File)
|
||||
|
||||
/* 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
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
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:0000h).
|
||||
|
||||
|
||||
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, or Tweaked modes) all the VGA modes that use more
|
||||
that 64Kb of video memory with the "Unchained" structure.
|
||||
Setting a pixel in any X-Mode can be done by 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 (unchained, 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,3C6h ; During the initialization, we'll turn the palette into
|
||||
xor al,al ; black in order to avoid the user to see all our
|
||||
out dx,al ; manipulations.
|
||||
|
||||
mov dx,3C4h ; We will inform the TIMING SEQUENCER register to switch
|
||||
mov ax,0604h ; in unchained mode (mode-X), 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 al,01h ; Like with the palette, we ask the video card not to
|
||||
out dx,al ; peek the memory to display it anymore. Thus, it's
|
||||
inc dx ; one more way to avoid interferences in the display,
|
||||
in al,dx ; which happens until the mode is completely initialized
|
||||
mov ah,al ; and stable. In addition, we can expect that asking a
|
||||
mov al,01h ; memory reading interruption will turn the system
|
||||
push ax ; faster, and thus speed up the initialization of the
|
||||
mov al,ah ; graphic mode (hope makes you live :))
|
||||
or al,20h ;
|
||||
out dx,al ;
|
||||
|
||||
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 the Screen width is
|
||||
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'll clean memory starting from 0A0000h with the
|
||||
xor eax,eax ; value 0 (which is the standard black) and on a range
|
||||
mov ecx,4000h ; of 4000h dwords (256Kb).
|
||||
rep stosd ; Let's wipe all this out.
|
||||
|
||||
mov dx,3C4h ; We can ask the VGA to read again the memory to display
|
||||
pop ax ; it on the screen...
|
||||
out dx,ax ;
|
||||
mov dx,3C6h ; ... and turn on the palette so the picture appears to
|
||||
mov al,0FFh ; the user.
|
||||
out dx,al ;
|
||||
|
||||
|
||||
|
||||
The table of constants you must send is one of these:
|
||||
(These are tables for C but they can be easily used in other languages)
|
||||
|
||||
word X320Y224[] =
|
||||
{ 0x0BA3, 0x6F06, 0xBA07, 0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0x0014,
|
||||
0xC715, 0x0416, 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[] =
|
||||
{ 0x0BA3, 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[] =
|
||||
{ 0x09E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x2D13, 0x0014,
|
||||
0xE317 };
|
||||
word X360Y224[] =
|
||||
{ 0x12A7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6F06, 0xBA07,
|
||||
0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0x2D13, 0x0014, 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[] =
|
||||
{ 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x3006, 0xF007,
|
||||
0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x2D13, 0x0014, 0x1F15, 0x2F16,
|
||||
0xE317 };
|
||||
word X360Y282[] =
|
||||
{ 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6206, 0xF007,
|
||||
0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x2D13, 0x0014, 0x3C15, 0x5C16,
|
||||
0xE317 };
|
||||
word X360Y300[] =
|
||||
{ 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4606, 0x1F07,
|
||||
0x0008, 0x4009, 0x3110, 0x8011, 0x2B12, 0x2D13, 0x0014, 0x2F15, 0x4416,
|
||||
0xE317 };
|
||||
word X360Y360[] =
|
||||
{ 0x0FE7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4009, 0x8810,
|
||||
0x8511, 0x6712, 0x2D13, 0x0014, 0x6D15, 0xBA16, 0xE317 };
|
||||
word X360Y400[] =
|
||||
{ 0x0AE7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x4009, 0x2D13,
|
||||
0x0014, 0xE317 };
|
||||
word X360Y448[] =
|
||||
{ 0x12A7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x6F06, 0xBA07,
|
||||
0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0x2D13, 0x0014, 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[] =
|
||||
{ 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0x3006, 0xF007,
|
||||
0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x2D13, 0x0014, 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[] =
|
||||
{ 0x12E7, 0x6B00, 0x5901, 0x5A02, 0x8E03, 0x5E04, 0x8A05, 0xBE06, 0xF007,
|
||||
0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x2D13, 0x0014, 0x5815, 0x7016,
|
||||
0xE317 };
|
||||
word X400Y200[] =
|
||||
{ 0x09E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x3213, 0x0014,
|
||||
0xE317 };
|
||||
word X400Y224[] =
|
||||
{ 0x12A7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6F06, 0xBA07,
|
||||
0x0008, 0x4109, 0x0810, 0x8A11, 0xBF12, 0x3213, 0x0014, 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[] =
|
||||
{ 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x3006, 0xF007,
|
||||
0x0008, 0x6109, 0x2010, 0xA911, 0x1B12, 0x3213, 0x0014, 0x1F15, 0x2F16,
|
||||
0xE317 };
|
||||
word X400Y282[] =
|
||||
{ 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6206, 0xF007,
|
||||
0x6109, 0x310F, 0x3710, 0x8911, 0x3312, 0x3213, 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[] =
|
||||
{ 0x0AE7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x4009, 0x3213,
|
||||
0x0014, 0xE317 };
|
||||
word X400Y448[] =
|
||||
{ 0x12A7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x6F06, 0xBA07,
|
||||
0x0008, 0x4009, 0x0810, 0x8A11, 0xBF12, 0x3213, 0x0014, 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[] =
|
||||
{ 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0x3006, 0xF007,
|
||||
0x0008, 0x6009, 0x2010, 0xA911, 0x1B12, 0x3213, 0x0014, 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[] =
|
||||
{ 0x12E7, 0x7100, 0x6301, 0x6402, 0x9203, 0x6604, 0x8205, 0xBE06, 0xF007,
|
||||
0x0008, 0x6009, 0x7C10, 0x8C11, 0x5712, 0x3213, 0x0014, 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 sent to it).
|
||||
³ ³
|
||||
³ ³ ÚÄÄÄThis is a value to send to a register of the CRTC.
|
||||
³ ³ ³
|
||||
³ ³ ³ ÚÄThis is the index of the CRTC register that will receive
|
||||
³ ³ ³ ³ 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 some of your favourite modes are missing, just send us the list of
|
||||
constants we must shoot at 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 CRTC 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[] =
|
||||
{ 0x09A3, 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[] =
|
||||
{ 0x0AE3, 0x6206, 0xF007, 0x0008, 0x6109, 0x310F, 0x3710, 0x8911, 0x3312,
|
||||
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[] =
|
||||
{ 0x07E3, 0x0008, 0x4009, 0x8810, 0x8511, 0x6712, 0x6D15, 0xBA16 };
|
||||
word Y400[] =
|
||||
{ 0x01E3, 0x4009 };
|
||||
word Y448[] =
|
||||
{ 0x09A3, 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.
|
||||
Reference in New Issue
Block a user