Abbe's Routine Part 1: Mode 13h

zhaozj2021-02-08  340

[Declaration]: I got the consent of the original authors' translation of Abbe's Demoschool and Abbe's Bag of Tricks. If anyone wants to use Abbe's Demoschool and Abbe's Bag of Tricks, please contact the original author: Albert.veli@systemDesign.af.se.

Abe's Demoschool Part 1: Mode 13h

Abbe's Routine Part 1: Mode 13h

Welcome to the first part of the routine school. In routine schools, I will take you over a variety of graphics effects, including Palette Rotation, Plasma, Flame, Sprites, 3D graphic, shadow, roll screen, Mode-x, SoundBlaster, etc. All can be displayed. Most of the contents of the routine school are based on MODE 13H or called McGa-mode. This immediately introduced the first question:

[What is Mode 13H? ]

Ok, the answer is very simple: Mode 13h is a graphic mode of the PC, most of the games and graphics demonstrations are done based on Mode 13h. The resolution of MODE 13H is 320 pixels in the horizontal direction, and 200 pixels in the vertical direction. This makes a total of 320 × 200 = 64,000 pixels on the screen. Each pixel on the screen can have 256 different colors (of course, one pixel can only have a color). You must know that a BYTE (8bit) can take 256 different values. This means that every pixel in Mode 13h can be represented by a BYTE, and the fact is just this.

As mentioned above, Mode 13h has 320 × 200 = 64,000 pixels, 64000bytes. Mode 13h's Screen-Memory starts from the address A000: 0000H to A000: FFFFH. This has a total of 65535bytes, so that the bottom of the screen also contains four unacceptable rows.

Write a pixel on the screen, and must first set the segment register ES to a0000h, then calculate the offset of the pixel is placed in DI, and then write a colorbyte to ES: DI (ie, a BYTE indicating color). The offset is calculated in the formula:

Offset = 320 × y X

Where x is the X coordinate value, Y is Y coordinate value. The coordinates (0, 0) are located on the upper left corner of the screen, and the coordinates (319, 319) are located in the lower right corner of the screen. The following is listed below and its corresponding offsets thereof:

(0) (1, 0) (2, 0) (3, 0) ... (319, 0)

0 0 1 2 3 ... ... 319 ------ x-axis ----- à

1 320 321 322 323 ... ... 639 (319, 1)

2 640 641 642 643 ... ... 959 (319, 2)

... ... ..... ... ....

... ... ....

199 63680 63681 63682 63683 ... ... 63999

(0,199) (1,199) (2,199) (3,199) ... ... (319, 199)

Y-axis

Mode 13h belongs to a linear memory model, ie, one sequential arrangement of Byte.

To write a pixel in the coordinate (3, 2), you should write a pixel to A000: (320 × 2 3) = A000: 643. Try it, do it.

Below is an unopened example written by C:

Void Putpixel (int X, int y, char color)

{

Int offs;

OFFS = 320 * y x; // Calculate the offset using the formula

ASM MOV AX, 0A000H / / You can't put a value directly in ES

ASM MOV ES, AX / / Put the screen address in ES

ASM MOV DI, OFFS // Put the calculated offset into DI

ASM MOV Al, Color // Put ColorbyTe in Al

ASM MOV [ES: DI], Al // Finally write pixels into the screen

}

You must already be in MCGA-MODE 13H mode before writing pixels to the screen. You can switch to this Mode 13h with the following method:

MOV AX, 13H; put the pattern code in AX

INT 10H; use VideoInterRupt 10h to enter the modified mode

You can use the following method to switch back to our commonly used TEXTMODE 3:

MOV AX, 3; MODE 3 is the standard 80 × 25 16-color text mode of DOS

INT 10h; enter TextMode 3

You can use C to write a function of switching screen mode:

Void SetMode (int M)

{

ASM MOV AX, MODE

ASM INT 10H

}

In this way, you can start with setmode (0x0013) in the main program; switch to MODE 13H, then use setmode (3); switch back to text mode.

To optimize the Putpixel function, you can replace a very slow multiplication as a bit operation and addition. You must also know that one bit is equivalent to the left left by 2, and the left shift 2 is equivalent to multiplying 4, and so on. The skill used is to divide 320 into several power of 2. 320 is (256 64); Y × 320 is (Y left shift 8 bits) (Y left shift 6). You can refer to the C code that uses the optimized PUTPIEL implementation of the Inline-Assembler.

What color has a pixel depends on two factors: you write color values ​​(0 to 255) written to the screen and the colors represented in the palette. The palette has a total of 256 portions (0 to 255). Each color in the palette is represented by three Byte, represents red, green, and blue. Each Byte value is between 0 and 63. The size of the value represents the intensity of the color: 0 indicates that there is no intensity, and 63 indicates the maximum intensity. This has the possible color of 64 3 times. Common colors]

Red green color

_____________________________

0 0 0 Black Black

63 0 0 red red

20 0 0 DARK RED Dark Red

0 63 0 Green Green

0 0 63 Blue Blue

63 63 0 Yellow Yellow

63 32 0 Orange Orange

63 0 63 Purple purple

0 63 63 CYAN

63 63 63 White white

32 32 32 Gray gray

10 10 Darkgray Darkish

MCGA-MODE 13H always starts with the same palette (ie 0 means black, 1 means blue, etc.). But it is easy to change the palette yourself. We can change the palette by writing appropriate information to 3C8H and 8C9H ports. This didn't look so difficult. You only need to write the index value of the starting color you want to change to the 3C8H port, and write red, green, and blue value to the 3C9H port. After 3C9H is written to these three Colorbyte, the index will be accepted automatically.

If the palette is stored in an array PAL (3 × 256bytes long), we assume that 0 represents black, 1 generation of blue, 2 generation gray, then PAL will start like this: 0, 0, 0; 0, 0, 63 32, 32, 32; ......

Below is a C function, which sets the palette according to the value of the array PAL:

Void setPal (Char * PAL)

{

INT I;

OUTP (0x3c8, 0); // starts from color value 0

For (i = 0; i <256 * 3; i )

OUTP (0x3c9, pal [i]); // Send the palette data to 3C9H port

}

The most common way to control the palette is to use the array PAL in a particular program, and save the information of the palette to a file of the disk. This palette file is easily identified because its size is always 3 × 256 = 768bytes. In the program, you only need to load the palette file from this disk and put the information into an array, and then set the palette with the setpal function told above.

In assembly language, you can use a very fast instruction rep to set the palette. The REP OUTSB instruction passes the Byte to the port of the DX value indicated from the DS: Si, and the number of transmitted BYTE is specified by the value of the CX. Each passing byte, Si adds 1.

Below is an assembler for setting the entire palette:

MOV DX, 03C8H; put the port number to DX

XOR Al, Al; Clear AX

OUT DX, Al; pass 0 to 3C8H port

LDS Si, Pal; Let DS: Si point to PAL

MOV CX, 3 * 256; the number of BYTE to be transferred in CX

Inc DX; DX = 3c9hrep outsb; 768bytes from PAL to 3C9H port

One common graphics effect is the constant loop to change the array PAL and call SetPal (PAL) to form a loop change of the color. You can use this technique in other graphics special effects to create static Plasma effects. First set the array PAL, which contains a smooth cycle change between the color of the color; then draw a beautiful pattern on the screen using the SIN or COS function; the last constantly scrolling the palette, so that it keeps the loop.

Pictured patterns don't have to be Plasma Picture, you can draw any pattern to see what effect will be produced when the palette scrolls. To make the array PAL loop, first save the first color (ie the top three Byte), then move all the color values ​​in the array (ie 3 byte), and finally empty the tail. The location is set to the color you just saved.

Will the C generation of the scroll palette as follows:

(In fact, each time the first color in the palette is switched to the last position)

Void Rotpal (Char * PAL, INT First, int LAST)

{

CHAR R, G, B;

INT I;

R = PAL [first * 3 0]; // assigns the three values ​​of the first color to R, G, B.

g = pal [first * 3 1];

B = PAL [first * 3 2];

For (i = first * 3; i <(Last 1) * 3; i ) // move all colors forward a location

PAL [I] = PAL [i 3];

PAL [Last * 3 0] = R; // Set the last place to save the original color

PAL [Last * 3 1] = g;

PAL [Last * 3 2] = B;

WTSync (); // Waiting for electron beam sweeping the current frame

SetPal (PAL); // Set the palette according to the rolling PAL

}

You don't necessarily have to put the first and last colors as a function parameter. But doing this is true. In the routine, I used a group with more than 256 colors. When scrolling the entire palette each time, I didn't change the color of 0, I only set the top 256 colors. I don't let the color of the value of 0 participate in scrolling because I don't want the background color to change. You can let it participate in the scroll test, so you can understand what I mean.

WTSync functions should always be called before each change the palette to avoid so-called "snowflakes" effects generated by the electron bundle. WTSync is waiting for vertical backtrack, that is, the electronic bundle is scanned and jumped back to the initial position to start scanning the next frame.

Maybe you will say that this routine can only be considered half a Plasma effect - well, in the part of the routine school, I will give you a real PLASMA effect.

Let's take a look at the C source code of the routine.

[The routine is downloaded in http://www.mds.mdh.se/föreningar/small/abe/abedemo1.zip. ]

转载请注明原文地址:https://www.9cbs.com/read-410.html

New Post(0)