├── LICENSE ├── README ├── demo └── plasma │ ├── Makefile │ ├── palette.pcx │ └── plasma.c └── src ├── Makefile ├── pcx.c ├── pcx.h ├── types.h ├── vesa.c └── vesa.h /LICENSE: -------------------------------------------------------------------------------- 1 | PUBLIC DOMAIN 2 | 3 | This code is in the Public Domain, you can do with it whatever you want. 4 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | DESCRIPTION 2 | 3 | A VESA VBE 2.0 video driver for DOS. 4 | 5 | 6 | DISCLAIMER 7 | 8 | This is *very* old code I wrote in 1999. It seems to work fine and you can even 9 | compile and run it in Dosbox. However, I assume no responsibilty for what it 10 | might do to your hardware. 11 | 12 | 13 | COMPILATION 14 | 15 | You need DJGPP, DJ Delorie's DOS port of the gcc, other compilers will *not* 16 | work. 17 | 18 | To compile, go to the 'src' folder and type 'make'. Then go to the 'demo\plasma' 19 | folder, for a usage example. 20 | 21 | -------------------------------------------------------------------------------- /demo/plasma/Makefile: -------------------------------------------------------------------------------- 1 | all: plasma 2 | 3 | plasma: plasma.c 4 | gcc plasma.c ..\..\src\vesa.o ..\..\src\pcx.o -I..\..\src -o plasma.exe -O2 5 | 6 | clean: 7 | del plasma.exe 8 | -------------------------------------------------------------------------------- /demo/plasma/palette.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobijk/vesa-dos-djgpp/e179b08df768569416ed57759fdf8b601f31fb13/demo/plasma/palette.pcx -------------------------------------------------------------------------------- /demo/plasma/plasma.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "types.h" 6 | #include "pcx.h" 7 | #include "vesa.h" 8 | 9 | int main(void) 10 | { 11 | VBESURFACE *vbesurface_ptr; 12 | FLATIMAGE *flatimage_ptr; 13 | 14 | ulong x, y, *offscreen, center_x, center_y; 15 | ulong angle; 16 | 17 | float sin_table[1024]; 18 | float cos_table[1024]; 19 | 20 | ulong *colortable; 21 | ulong colorindex; 22 | 23 | if((flatimage_ptr = (FLATIMAGE*) 24 | loadPcxImage((unsigned char*) "palette.pcx", 32)) == 0) { 25 | return 1; 26 | } else { 27 | colortable = (long unsigned int*) &flatimage_ptr->image; 28 | } 29 | 30 | if((vbesurface_ptr = VBEinit(320, 240, 32)) == 0) { 31 | puts("\nCould not initialize video."); 32 | free(flatimage_ptr); 33 | return 2; 34 | } else { 35 | offscreen = (long unsigned int*) vbesurface_ptr->offscreen_ptr; 36 | } 37 | 38 | for(angle = 0; angle < 1024; angle++) 39 | sin_table[angle] = sin((float)(PI / 512.0 * angle)); 40 | for(angle = 0; angle < 1024; angle++) 41 | cos_table[angle] = cos((float)(PI / 512.0 * angle)); 42 | 43 | angle = 0; 44 | 45 | while(!kbhit()) { 46 | 47 | angle += 16; 48 | 49 | center_x = 160 + 100 * cos_table[angle % 1024]; 50 | center_y = 120 + 100 * sin_table[angle % 1024]; 51 | 52 | for(x = 0; x < 320; x++) 53 | for(y = 0; y < 240; y++) { 54 | colorindex = 128 55 | + 63 * sin_table[(long)((hypot(center_y + (y-center_y/2), center_x + (x-center_x/2)) / 16) * (512.0 / PI)) % 1024] 56 | + 63 * sin_table[(long)((x / (30 + 15 * cos(y / 240))) * (512.0 / PI)) % 1024] * 57 | cos_table[(long)((y / (11 + 20 * sin(x / 320))) * (512.0 / PI)) % 1024] ; 58 | 59 | offscreen[y*320+x] = colortable[colorindex*32]; 60 | } 61 | 62 | flipScreen(); 63 | } 64 | 65 | VBEshutdown(); 66 | free(flatimage_ptr); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | all: pcx.o vesa.o 2 | 3 | pcx.o: pcx.c 4 | gcc pcx.c -c -O2 5 | 6 | vesa.o: vesa.c 7 | gcc vesa.c -c -O2 8 | 9 | clean: 10 | del *.o 11 | del *.swp 12 | -------------------------------------------------------------------------------- /src/pcx.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | *COMP:DJGPP PCX Routines * 3 | *****************************************************************************/ 4 | 5 | #include 6 | #include 7 | #include "types.h" 8 | #include "pcx.h" 9 | 10 | /***************************************************************************** 11 | * * 12 | * loadPcxHeader * 13 | * * 14 | *****************************************************************************/ 15 | PCXHEADER *getPcxInfo(FILE *pcx_file_ptr) 16 | { 17 | unsigned long file_cur_position; 18 | PCXHEADER *pcx_header_ptr; 19 | 20 | file_cur_position = ftell(pcx_file_ptr); 21 | rewind(pcx_file_ptr); 22 | 23 | /* get 128 bytes from the beginning of the file */ 24 | if((pcx_header_ptr = malloc(128 * sizeof(char))) == 0) return(0); 25 | if(fread(pcx_header_ptr , sizeof(char), 128, pcx_file_ptr) != 128) { 26 | free(pcx_header_ptr); 27 | return(0); 28 | } 29 | 30 | fseek(pcx_file_ptr, file_cur_position, SEEK_SET); 31 | return(pcx_header_ptr); 32 | } 33 | 34 | /***************************************************************************** 35 | * * 36 | * LoadPcxImage (8Bit) * 37 | * * 38 | *****************************************************************************/ 39 | FLATIMAGE_8Bit *loadPcxImage_8Bit(FILE *pcx_file_ptr, PCXHEADER *pcx_header_ptr) 40 | { 41 | FLATIMAGE_8Bit *flat_image_ptr; 42 | unsigned char pcx_byte, pcx_count_byte; 43 | unsigned long pcx_image_size, pcx_counter, color; 44 | 45 | pcx_image_size = (pcx_header_ptr->pcx_ymax - pcx_header_ptr->pcx_ymin + 1) * 46 | (pcx_header_ptr->pcx_xmax - pcx_header_ptr->pcx_xmin + 1); 47 | 48 | if((flat_image_ptr = malloc(2 * sizeof(long) + pcx_image_size + 768)) == 0) 49 | return(0); 50 | 51 | flat_image_ptr->width = (pcx_header_ptr->pcx_xmax - pcx_header_ptr->pcx_ymin + 1); 52 | flat_image_ptr->height = (pcx_header_ptr->pcx_ymax - pcx_header_ptr->pcx_ymin + 1); 53 | 54 | // LOAD THE PALETTE VALUES 55 | fseek(pcx_file_ptr, -768, SEEK_END); 56 | if((fread(&flat_image_ptr->palette[0][0], sizeof(char), 768, 57 | pcx_file_ptr)) != 768) { 58 | free(flat_image_ptr); 59 | return(0); 60 | } 61 | 62 | for(color = 0; color < 256; color++) { 63 | flat_image_ptr->palette[color][0] = flat_image_ptr->palette[color][0] / 4; 64 | flat_image_ptr->palette[color][1] = flat_image_ptr->palette[color][1] / 4; 65 | flat_image_ptr->palette[color][2] = flat_image_ptr->palette[color][2] / 4; 66 | } 67 | 68 | // DECODE IMAGE 69 | fseek(pcx_file_ptr, 128, SEEK_SET); 70 | for(pcx_counter = 0; pcx_counter < pcx_image_size;) { 71 | if(fread(&pcx_byte, sizeof(char), 1, pcx_file_ptr) != 1) { 72 | free(flat_image_ptr); 73 | return(0); 74 | } 75 | if(pcx_byte > 192) { 76 | pcx_count_byte = pcx_byte - 192; 77 | if(fread(&pcx_byte, sizeof(char), 1, pcx_file_ptr) != 1) { 78 | free(flat_image_ptr); 79 | return(0); 80 | } 81 | } else pcx_count_byte = 1; 82 | 83 | for(; pcx_count_byte > 0; pcx_count_byte--) { 84 | (&flat_image_ptr->image)[pcx_counter] = pcx_byte; 85 | pcx_counter++; 86 | if((pcx_header_ptr->pcx_bytes_per_line - flat_image_ptr->width == 1) && 87 | (pcx_counter % (flat_image_ptr->width) == 0)) 88 | fseek(pcx_file_ptr, 1, SEEK_CUR); 89 | } 90 | } 91 | 92 | return(flat_image_ptr); 93 | } 94 | 95 | /***************************************************************************** 96 | * * 97 | * LoadPcxImage (24Bit) * 98 | * * 99 | *****************************************************************************/ 100 | FLATIMAGE_32Bit *loadPcxImage_24Bit(FILE *pcx_file_ptr, PCXHEADER *pcx_header_ptr) 101 | { 102 | FLATIMAGE_32Bit *flat_image_ptr; 103 | unsigned char *scanline_ptr; 104 | unsigned char pcx_byte, pcx_count_byte; 105 | unsigned long pcx_image_size, pixel_nr, scanline; 106 | 107 | pcx_image_size = (pcx_header_ptr->pcx_ymax - pcx_header_ptr->pcx_ymin + 1) * 108 | (pcx_header_ptr->pcx_xmax - pcx_header_ptr->pcx_xmin + 1); 109 | 110 | if((flat_image_ptr = malloc(2 * sizeof(long) + pcx_image_size * sizeof(long))) == 0) 111 | return(0); 112 | 113 | flat_image_ptr->width = (pcx_header_ptr->pcx_xmax - pcx_header_ptr->pcx_ymin + 1); 114 | flat_image_ptr->height = (pcx_header_ptr->pcx_ymax - pcx_header_ptr->pcx_ymin + 1); 115 | 116 | // DECODE IMAGE 117 | fseek(pcx_file_ptr, 128, SEEK_SET); 118 | if((scanline_ptr = malloc(pcx_header_ptr->pcx_bytes_per_line * 3)) == 0) { 119 | free(flat_image_ptr); 120 | return(0); 121 | } 122 | 123 | for(scanline = 0; scanline < flat_image_ptr->height; scanline++) { 124 | for(pixel_nr = 0; pixel_nr < pcx_header_ptr->pcx_bytes_per_line * 3;) { 125 | if(fread(&pcx_byte, sizeof(char), 1, pcx_file_ptr) != 1) { 126 | free(scanline_ptr); 127 | free(flat_image_ptr); 128 | return(0); 129 | } 130 | if(pcx_byte > 192) { 131 | pcx_count_byte = pcx_byte - 192; 132 | if(fread(&pcx_byte, sizeof(char), 1, pcx_file_ptr) != 1) { 133 | free(scanline_ptr); 134 | free(flat_image_ptr); 135 | return(0); 136 | } 137 | } else pcx_count_byte = 1; 138 | 139 | for(; pcx_count_byte > 0; pcx_count_byte--) { 140 | scanline_ptr[pixel_nr] = pcx_byte; 141 | pixel_nr++; 142 | } 143 | } 144 | 145 | for(pixel_nr = 0; pixel_nr < pcx_header_ptr->pcx_bytes_per_line; pixel_nr++) 146 | ((char*)(&flat_image_ptr->image))[2 + pixel_nr * 4 + scanline * 147 | pcx_header_ptr->pcx_bytes_per_line * 4] 148 | = scanline_ptr[pixel_nr]; 149 | 150 | for(pixel_nr = 0; pixel_nr < pcx_header_ptr->pcx_bytes_per_line; pixel_nr++) 151 | ((char*)(&flat_image_ptr->image))[1 + pixel_nr * 4 + scanline * 152 | pcx_header_ptr->pcx_bytes_per_line * 4] 153 | = scanline_ptr[pixel_nr + pcx_header_ptr->pcx_bytes_per_line]; 154 | 155 | for(pixel_nr = 0; pixel_nr < pcx_header_ptr->pcx_bytes_per_line; pixel_nr++) 156 | ((char*)(&flat_image_ptr->image))[0 + pixel_nr * 4 + scanline * 157 | pcx_header_ptr->pcx_bytes_per_line * 4] 158 | = scanline_ptr[pixel_nr + pcx_header_ptr->pcx_bytes_per_line * 2]; 159 | } 160 | 161 | free(scanline_ptr); 162 | return(flat_image_ptr); 163 | } 164 | 165 | /***************************************************************************** 166 | * * 167 | * LoadPcxImage * 168 | * * 169 | *****************************************************************************/ 170 | void *loadPcxImage(uchar *image_filename, uchar bpp) 171 | { 172 | FILE *image_file_ptr; 173 | FLATIMAGE *flat_image_ptr; 174 | FLATIMAGE_8Bit *flat_image_ptr_8Bit; 175 | FLATIMAGE_32Bit *flat_image_ptr_32Bit; 176 | FLATIMAGE_16Bit *flat_image_ptr_16Bit; 177 | PCXHEADER *pcx_header_ptr; 178 | 179 | if((image_file_ptr = fopen(image_filename, "rb")) == 0) return(0); 180 | if((pcx_header_ptr = getPcxInfo(image_file_ptr)) == 0) { 181 | fclose(image_file_ptr); 182 | return(0); 183 | } 184 | 185 | if(((pcx_header_ptr->pcx_bits_per_pixel) *(pcx_header_ptr->pcx_num_planes)) == 8) { 186 | flat_image_ptr_8Bit = loadPcxImage_8Bit(image_file_ptr, pcx_header_ptr); 187 | flat_image_ptr_32Bit = image8Bit_to_32Bit(flat_image_ptr_8Bit); 188 | if(flat_image_ptr_8Bit) free(flat_image_ptr_8Bit); 189 | } else if(((pcx_header_ptr->pcx_bits_per_pixel) *(pcx_header_ptr->pcx_num_planes)) == 24) { 190 | flat_image_ptr_32Bit = loadPcxImage_24Bit(image_file_ptr, pcx_header_ptr); 191 | } else return(0); 192 | 193 | if(flat_image_ptr_32Bit == 0) { 194 | fclose(image_file_ptr); 195 | free(pcx_header_ptr); 196 | return(0); 197 | } 198 | 199 | if(bpp == 8) { 200 | flat_image_ptr = image32Bit_to_8Bit(flat_image_ptr_32Bit); 201 | free(flat_image_ptr_32Bit); 202 | free(pcx_header_ptr); 203 | fclose(image_file_ptr); 204 | return(flat_image_ptr); // return 8 bit depth 205 | } 206 | if(bpp == 16) { 207 | flat_image_ptr_16Bit = image32Bit_to_16Bit(flat_image_ptr_32Bit); 208 | free(flat_image_ptr_32Bit); 209 | free(pcx_header_ptr); 210 | fclose(image_file_ptr); 211 | return(flat_image_ptr_16Bit); // return 16 bit depth 212 | } 213 | if(bpp == 15) { 214 | flat_image_ptr_16Bit = image32Bit_to_15Bit(flat_image_ptr_32Bit); 215 | free(flat_image_ptr_32Bit); 216 | free(pcx_header_ptr); 217 | fclose(image_file_ptr); 218 | return(flat_image_ptr_16Bit); // return 15 bit depth 219 | } 220 | if(bpp == 32) { 221 | free(pcx_header_ptr); 222 | fclose(image_file_ptr); 223 | return(flat_image_ptr_32Bit); // return 32 bit depth 224 | } 225 | 226 | return(0); 227 | } 228 | 229 | /***************************************************************************** 230 | * * 231 | * Convert Image 8 to 32 Bit * 232 | * * 233 | *****************************************************************************/ 234 | FLATIMAGE_32Bit *image8Bit_to_32Bit(FLATIMAGE_8Bit *flat_image_ptr_8Bit) 235 | { 236 | FLATIMAGE_32Bit *flat_image_ptr_32Bit; 237 | unsigned long flat_image_size, pixel_nr, color; 238 | unsigned char PixelValue; 239 | 240 | if(flat_image_ptr_8Bit == 0) return(0); 241 | 242 | flat_image_size = flat_image_ptr_8Bit->width * flat_image_ptr_8Bit->height; 243 | if((flat_image_ptr_32Bit = 244 | malloc(2 * sizeof(long) + flat_image_size * sizeof(long))) == 0) 245 | return(0); 246 | 247 | flat_image_ptr_32Bit->width = flat_image_ptr_8Bit->width; 248 | flat_image_ptr_32Bit->height = flat_image_ptr_8Bit->height; 249 | 250 | for(color = 0; color < 256; color++) { 251 | flat_image_ptr_8Bit->palette[color][0] = 252 | flat_image_ptr_8Bit->palette[color][0] * 4; 253 | flat_image_ptr_8Bit->palette[color][1] = 254 | flat_image_ptr_8Bit->palette[color][1] * 4; 255 | flat_image_ptr_8Bit->palette[color][2] = 256 | flat_image_ptr_8Bit->palette[color][2] * 4; 257 | } 258 | 259 | for(pixel_nr = 0; pixel_nr < flat_image_size; pixel_nr++) { 260 | PixelValue = ((char*)&flat_image_ptr_8Bit->image)[pixel_nr]; 261 | ((char*)&flat_image_ptr_32Bit->image)[pixel_nr*4] = 262 | (flat_image_ptr_8Bit->palette)[PixelValue][2]; 263 | ((char*)&flat_image_ptr_32Bit->image)[pixel_nr*4+1] = 264 | (flat_image_ptr_8Bit->palette)[PixelValue][1]; 265 | ((char*)&flat_image_ptr_32Bit->image)[pixel_nr*4+2] = 266 | (flat_image_ptr_8Bit->palette)[PixelValue][0]; 267 | } 268 | return(flat_image_ptr_32Bit); 269 | } 270 | 271 | /***************************************************************************** 272 | * * 273 | * Convert Image 32 to 16 Bit * 274 | * * 275 | *****************************************************************************/ 276 | FLATIMAGE_16Bit *image32Bit_to_16Bit(FLATIMAGE_32Bit *flat_image_ptr_32Bit) 277 | { 278 | FLATIMAGE_16Bit *flat_image_ptr_16Bit; 279 | unsigned long flat_image_size, pixel_nr; 280 | 281 | if(flat_image_ptr_32Bit == 0) return(0); 282 | 283 | flat_image_size = flat_image_ptr_32Bit->width * flat_image_ptr_32Bit->height; 284 | if((flat_image_ptr_16Bit = 285 | malloc(2 * sizeof(long) + flat_image_size * sizeof(short))) == 0) 286 | return(0); 287 | 288 | flat_image_ptr_16Bit->width = flat_image_ptr_32Bit->width; 289 | flat_image_ptr_16Bit->height = flat_image_ptr_32Bit->height; 290 | 291 | for(pixel_nr = 0; pixel_nr < flat_image_size; pixel_nr++) { 292 | (&flat_image_ptr_16Bit->image)[pixel_nr] = 293 | ((((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 2] << 8) & 0xF800) + 294 | ((((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 1] << 3) & 0x07E0) + 295 | ((((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 0] >> 3) & 0x001F); 296 | } 297 | 298 | return(flat_image_ptr_16Bit); 299 | } 300 | 301 | /***************************************************************************** 302 | * * 303 | * Convert Image 32 to 15 Bit * 304 | * * 305 | *****************************************************************************/ 306 | FLATIMAGE_16Bit *image32Bit_to_15Bit(FLATIMAGE_32Bit *flat_image_ptr_32Bit) 307 | { 308 | FLATIMAGE_16Bit *flat_image_ptr_15Bit; 309 | unsigned long flat_image_size, pixel_nr; 310 | 311 | if(flat_image_ptr_32Bit == 0) return(0); 312 | 313 | flat_image_size = flat_image_ptr_32Bit->width * flat_image_ptr_32Bit->height; 314 | if((flat_image_ptr_15Bit = 315 | malloc(2 * sizeof(long) + flat_image_size * sizeof(short))) == 0) 316 | return(0); 317 | 318 | flat_image_ptr_15Bit->width = flat_image_ptr_32Bit->width; 319 | flat_image_ptr_15Bit->height = flat_image_ptr_32Bit->height; 320 | 321 | for(pixel_nr = 0; pixel_nr < flat_image_size; pixel_nr++) { 322 | (&flat_image_ptr_15Bit->image)[pixel_nr] = 323 | ((((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 2] << 7) & 0x7C00) + 324 | ((((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 1] << 2) & 0x03E0) + 325 | ((((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 0] >> 3) & 0x001F); 326 | } 327 | 328 | return(flat_image_ptr_15Bit); 329 | } 330 | 331 | /***************************************************************************** 332 | * * 333 | * Convert Image 32 to 8 Bit * 334 | * * 335 | *****************************************************************************/ 336 | FLATIMAGE *image32Bit_to_8Bit(FLATIMAGE_32Bit *flat_image_ptr_32Bit) 337 | { 338 | FLATIMAGE *flat_image_ptr_8Bit; 339 | unsigned long flat_image_size, pixel_nr; 340 | unsigned short red, green, blue; 341 | 342 | if(flat_image_ptr_32Bit == 0) return(0); 343 | 344 | flat_image_size = flat_image_ptr_32Bit->width * flat_image_ptr_32Bit->height; 345 | if((flat_image_ptr_8Bit = 346 | malloc(2 * sizeof(long) + flat_image_size)) == 0) 347 | return(0); 348 | 349 | flat_image_ptr_8Bit->width = flat_image_ptr_32Bit->width; 350 | flat_image_ptr_8Bit->height = flat_image_ptr_32Bit->height; 351 | 352 | for(pixel_nr = 0; pixel_nr < flat_image_size; pixel_nr++) { 353 | red = 354 | (((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 2] >> 5) & 0x7; 355 | green = 356 | (((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 1] >> 5) & 0x7; 357 | blue = 358 | (((char*)&flat_image_ptr_32Bit->image)[pixel_nr * 4 + 0] >> 6) & 0x3; 359 | 360 | (&flat_image_ptr_8Bit->image)[pixel_nr] = (red * 32 + green * 4 + blue); 361 | } 362 | 363 | return(flat_image_ptr_8Bit); 364 | } 365 | -------------------------------------------------------------------------------- /src/pcx.h: -------------------------------------------------------------------------------- 1 | #ifndef __PCX_H_INCLUDED 2 | #define __PCX_H_INCLUDED 3 | 4 | // PCX header structure 5 | struct PcxHeader { 6 | unsigned char manufacturer; 7 | unsigned char pcx_version; 8 | unsigned char pcx_encoding; 9 | unsigned char pcx_bits_per_pixel; 10 | /* window dimensions */ 11 | unsigned short pcx_xmin; 12 | unsigned short pcx_ymin; 13 | unsigned short pcx_xmax; 14 | unsigned short pcx_ymax; 15 | /* non vital info */ 16 | unsigned short pcx_hor_ppi; 17 | unsigned short pcx_ver_dpi; 18 | unsigned char pcx_color_map[48]; 19 | unsigned char reserved; 20 | unsigned char pcx_num_planes; 21 | unsigned short pcx_bytes_per_line; 22 | unsigned short pcx_palette_info; 23 | /* mandatory only for PB.IV and above */ 24 | unsigned short pcx_hor_size; 25 | unsigned short pcx_ver_size; 26 | unsigned char filler[54]; 27 | } __attribute__ ((packed)); 28 | 29 | typedef struct PcxHeader PCXHEADER; 30 | 31 | struct FlatImage_8Bit { 32 | unsigned long width; 33 | unsigned long height; 34 | unsigned char palette[256][3]; 35 | unsigned char image; 36 | } __attribute__ ((packed)); 37 | 38 | typedef struct FlatImage_8Bit FLATIMAGE_8Bit; 39 | 40 | struct FlatImage_32Bit { 41 | unsigned long width; 42 | unsigned long height; 43 | unsigned long image; 44 | } __attribute__ ((packed)); 45 | 46 | typedef struct FlatImage_32Bit FLATIMAGE_32Bit; 47 | 48 | struct FlatImage_16Bit { 49 | unsigned long width; 50 | unsigned long height; 51 | unsigned short image; 52 | } __attribute__ ((packed)); 53 | 54 | typedef struct FlatImage_16Bit FLATIMAGE_16Bit; 55 | 56 | struct FlatImage { 57 | unsigned long width; 58 | unsigned long height; 59 | unsigned char image; 60 | } __attribute__ ((packed)); 61 | 62 | typedef struct FlatImage FLATIMAGE; 63 | 64 | //********************************FUNCTIONS*********************************** 65 | 66 | PCXHEADER *getPcxInfo(FILE *file_ptr); 67 | FLATIMAGE_8Bit *loadPcxImage_8Bit(FILE *pcx_file_ptr, PCXHEADER *pcx_header_ptr); 68 | FLATIMAGE_32Bit *loadPcxImage_24Bit(FILE *pcx_file_ptr, PCXHEADER *pcx_header_ptr); 69 | void *loadPcxImage(unsigned char *filename, unsigned char bpp); 70 | FLATIMAGE_32Bit *image8Bit_to_32Bit(FLATIMAGE_8Bit *image_ptr); 71 | FLATIMAGE_16Bit *image32Bit_to_16Bit(FLATIMAGE_32Bit *image_ptr); 72 | FLATIMAGE_16Bit *image32Bit_to_15Bit(FLATIMAGE_32Bit *image_ptr); 73 | FLATIMAGE *image32Bit_to_8Bit(FLATIMAGE_32Bit *image_ptr); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | #ifndef __TYPES_H_INCLUDED 2 | #define __TYPES_H_INCLUDED 3 | 4 | #define ushort unsigned short 5 | #define ulong unsigned long 6 | #define uchar unsigned char 7 | #define uint unsigned int 8 | #define dword signed long 9 | #define word signed short 10 | #define byte signed char 11 | #define bool signed int 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/vesa.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * VBE 2.0 detection and routines for DJGPP C. * 3 | *****************************************************************************/ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "types.h" 15 | #include "vesa.h" 16 | 17 | #define global 18 | 19 | static VBESURFACE _vbe_surface; 20 | static VBEINFO _vbe_info; 21 | static MODEINFO _vbe_mode_info; 22 | static PMINTERFACE *_pmode_interface_ptr; 23 | static ulong *_ytable; 24 | 25 | static void (*PM_VBEsetDisplayStart)(void); 26 | 27 | global void (*putPixel)(long x, long y, ulong color); 28 | 29 | /***************************************************************************** 30 | * * 31 | * VBEgetInfo returns a pointer to a VBEINFO structure or NULL on error * 32 | * * 33 | *****************************************************************************/ 34 | VBEINFO *VBEgetInfo(void) 35 | { 36 | ushort counter = 0; 37 | ushort offset = 0; 38 | ushort vbe_mode = 0xFFFF; 39 | ushort *vbe_mode_list = 0; 40 | __dpmi_regs r; 41 | 42 | // we want VBE 2.0+ info 43 | strncpy(_vbe_info.vbe_signature, "VBE2", 4); 44 | 45 | // request info 46 | r.x.ax = 0x4F00; 47 | r.x.di = __tb & 0x0F; 48 | r.x.es = (__tb >> 4) & 0xFFFF; 49 | dosmemput(&_vbe_info, sizeof(VBEINFO), __tb); 50 | __dpmi_int(0x10, &r); 51 | if(r.x.ax != 0x004F) return(0); 52 | dosmemget(__tb, sizeof(VBEINFO), &_vbe_info); 53 | 54 | if(strncmp(_vbe_info.vbe_signature, "VESA", 4) != 0) return(0); // VESA ? 55 | 56 | // get the videomode list 57 | do { 58 | dosmemget(((((long)_vbe_info.video_mode_ptr >> 16) & 0xFFFF) << 4) + 59 | ((long)_vbe_info.video_mode_ptr & 0xFFFF) + 60 | (counter * sizeof(short)), 61 | sizeof(short), &vbe_mode); 62 | counter++; 63 | } while(vbe_mode != 0xFFFF); 64 | vbe_mode_list = malloc((counter + 1) * sizeof(short)); 65 | counter = 0; 66 | 67 | do { 68 | dosmemget(((((long)_vbe_info.video_mode_ptr >> 16) & 0xFFFF) << 4) + 69 | ((long)_vbe_info.video_mode_ptr & 0xFFFF) + 70 | (counter * sizeof(short)), 71 | sizeof(short), &vbe_mode_list[counter]); 72 | counter++; 73 | } while(vbe_mode_list[counter-1] != 0xFFFF); 74 | _vbe_info.video_mode_ptr = vbe_mode_list; 75 | counter = 0; 76 | 77 | // get the OEM string 78 | do { 79 | dosmemget(((((long)_vbe_info.oem_string_ptr >> 16) & 0xFFFF) << 4) + 80 | ((long)_vbe_info.oem_string_ptr & 0xFFFF) + counter, 81 | sizeof(char), &_vbe_info.oem_data[counter]); 82 | counter++; 83 | } while(_vbe_info.oem_data[counter-1] != 0); 84 | _vbe_info.oem_string_ptr = &_vbe_info.oem_data[0]; 85 | offset = counter; 86 | counter = 0; 87 | 88 | if(_vbe_info.vbe_version >= 0x0200) { 89 | 90 | // get the vendor name 91 | do { 92 | dosmemget(((((long)_vbe_info.oem_vendor_name_ptr >> 16) & 0xFFFF) << 4) + 93 | ((long)_vbe_info.oem_vendor_name_ptr & 0xFFFF) + counter, 94 | sizeof(char), &_vbe_info.oem_data[counter+offset]); 95 | counter++; 96 | } while(_vbe_info.oem_data[counter+offset-1] != 0); 97 | _vbe_info.oem_vendor_name_ptr = &_vbe_info.oem_data[offset]; 98 | offset = offset + counter; 99 | counter = 0; 100 | 101 | // get the product name 102 | do { 103 | dosmemget(((((long)_vbe_info.oem_product_name_ptr >> 16) & 0xFFFF) << 4) + 104 | ((long)_vbe_info.oem_product_name_ptr & 0xFFFF) + counter, 105 | sizeof(char), &_vbe_info.oem_data[counter+offset]); 106 | counter++; 107 | } while(_vbe_info.oem_data[counter+offset-1] != 0); 108 | _vbe_info.oem_product_name_ptr = &_vbe_info.oem_data[offset]; 109 | offset = offset + counter; 110 | counter = 0; 111 | 112 | //get the product revision 113 | do { 114 | dosmemget(((((long)_vbe_info.oem_product_rev_ptr >> 16) & 0xFFFF) << 4) + 115 | ((long)_vbe_info.oem_product_rev_ptr & 0xFFFF) + counter, 116 | sizeof(char), &_vbe_info.oem_data[counter+offset]); 117 | counter++; 118 | } while(_vbe_info.oem_data[counter+offset-1] != 0); 119 | _vbe_info.oem_product_rev_ptr = &_vbe_info.oem_data[offset]; 120 | } 121 | 122 | _vbe_surface.vbe_boolean = 1; 123 | return(&_vbe_info); 124 | } 125 | 126 | /***************************************************************************** 127 | * * 128 | * VBEgetModeInfo takes a ModeNr on entry and returns a pointer to a * 129 | * ModeInfoBlock Structure or NULL on failure. * 130 | * * 131 | *****************************************************************************/ 132 | MODEINFO *VBEgetModeInfo(unsigned short vbe_mode_nr) 133 | { 134 | __dpmi_regs r; 135 | 136 | if(_vbe_surface.vbe_boolean == 0) return(0); 137 | 138 | r.x.ax = 0x4F01; 139 | r.x.cx = vbe_mode_nr; 140 | r.x.di = __tb & 0x0F; 141 | r.x.es = (__tb >> 4) & 0xFFFF; 142 | __dpmi_int(0x10, &r); 143 | 144 | if(r.x.ax != 0x004F) return(0); 145 | 146 | dosmemget(__tb, sizeof(MODEINFO), &_vbe_mode_info); 147 | 148 | if(_vbe_mode_info.bits_per_pixel == 16) // for buggy VBE implementations 149 | _vbe_mode_info.bits_per_pixel = _vbe_mode_info.red_mask_size + 150 | _vbe_mode_info.green_mask_size + 151 | _vbe_mode_info.blue_mask_size; 152 | return(&_vbe_mode_info); 153 | } 154 | 155 | /***************************************************************************** 156 | * * 157 | * Get protected mode interface * 158 | * * 159 | *****************************************************************************/ 160 | void *VBEgetPmodeInterface(void) 161 | { 162 | __dpmi_regs r; 163 | __dpmi_meminfo m; 164 | ushort *ptr; 165 | 166 | // only available in VBE 2.0+ 167 | if(_vbe_info.vbe_version < 0x200) return(0); 168 | 169 | r.x.ax = 0x4F0A; 170 | r.x.bx = 0; 171 | __dpmi_int(0x10, &r); 172 | if(r.x.ax != 0x004F) return(0); 173 | 174 | // copy interface 175 | _pmode_interface_ptr = malloc(r.x.cx); 176 | dosmemget((r.x.es * 16) + r.x.di, r.x.cx, _pmode_interface_ptr); 177 | _go32_dpmi_lock_data(_pmode_interface_ptr, r.x.cx); 178 | 179 | // need memory-mapped IO? 180 | if(_pmode_interface_ptr->io_info) { 181 | ptr = (ushort *)((char *)_pmode_interface_ptr + _pmode_interface_ptr->io_info); 182 | while(*ptr != 0xFFFF) ptr++; 183 | ptr++; // skip the port table and 184 | if(*ptr != 0xFFFF) { // get descriptor 185 | m.address = *((ulong *)ptr); 186 | m.size = *(ptr + 2); 187 | if(__dpmi_physical_address_mapping(&m) != 0) return(0); 188 | 189 | _vbe_surface.io_linear = m.address; 190 | __dpmi_lock_linear_region(&m); 191 | 192 | _vbe_surface.io_segment = __dpmi_allocate_ldt_descriptors(1); 193 | if(_vbe_surface.io_segment < 0) { 194 | __dpmi_unlock_linear_region(&m); 195 | __dpmi_free_physical_address_mapping(&m); 196 | return(0); 197 | } 198 | 199 | __dpmi_set_segment_base_address(_vbe_surface.io_segment, 200 | _vbe_surface.io_linear); 201 | __dpmi_set_segment_limit(_vbe_surface.io_segment, m.size - 1); 202 | 203 | } 204 | } 205 | 206 | PM_VBEsetDisplayStart = (void *)((char *)_pmode_interface_ptr + 207 | _pmode_interface_ptr->set_display_start); 208 | return(PM_VBEsetDisplayStart); 209 | } 210 | 211 | /***************************************************************************** 212 | * * 213 | * VBEselectModeNr searches the vbe_mode_list for a Mode that matches the * 214 | * requirements given on entry (xres, yres, bpp). * 215 | * * 216 | *****************************************************************************/ 217 | ushort VBEselectModeNr(ushort xres, ushort yres, uchar bpp) 218 | { 219 | ushort counter; 220 | 221 | if(_vbe_surface.vbe_boolean == 0) return(0); 222 | 223 | for(counter = 0; ; counter++) { 224 | if(_vbe_info.video_mode_ptr[counter] == 0xFFFF) return(0); 225 | 226 | VBEgetModeInfo(_vbe_info.video_mode_ptr[counter]); 227 | 228 | if(_vbe_mode_info.x_resolution == xres && 229 | _vbe_mode_info.y_resolution == yres && 230 | _vbe_mode_info.bits_per_pixel == bpp) break; 231 | } 232 | 233 | return(_vbe_info.video_mode_ptr[counter]); 234 | } 235 | 236 | /***************************************************************************** 237 | * * 238 | * Set inquired Mode and return a VbeSurface Structure or Null on failure * 239 | * * 240 | *****************************************************************************/ 241 | VBESURFACE *VBEsetMode(ushort vbe_mode_nr) 242 | { 243 | __dpmi_regs r; 244 | __dpmi_meminfo m; 245 | ulong counter; 246 | 247 | if(_vbe_surface.vbe_boolean == 0) return(0); 248 | if(_vbe_surface.vbe_init_boolean == 1) return(0); 249 | if(VBEgetModeInfo(vbe_mode_nr) == 0) return(0); 250 | 251 | // create lookup table for putPixel routines 252 | if(_ytable) free(_ytable); 253 | if((_ytable = malloc(4 * (_vbe_mode_info.y_resolution + 1))) == 0) return(0); 254 | for(counter = 0; counter <= _vbe_mode_info.y_resolution; counter++) 255 | _ytable[counter] = _vbe_mode_info.x_resolution * counter * 256 | ((_vbe_mode_info.bits_per_pixel + 1) / 8); 257 | 258 | // request frame buffer 259 | r.x.ax = 0x4F02; 260 | r.x.bx = (vbe_mode_nr | 0x4000); 261 | __dpmi_int(0x10, &r); 262 | if(r.x.ax != 0x004F) return(0); 263 | 264 | m.size = (_vbe_info.total_memory * 64 * 1024); 265 | m.address = _vbe_mode_info.phys_base_ptr; 266 | __dpmi_physical_address_mapping(&m); 267 | __dpmi_lock_linear_region(&m); 268 | 269 | _vbe_surface.lfb_linear_address = m.address; 270 | _vbe_surface.lfb_selector = __dpmi_allocate_ldt_descriptors(1); 271 | 272 | __dpmi_set_segment_base_address(_vbe_surface.lfb_selector, 273 | _vbe_surface.lfb_linear_address); 274 | __dpmi_set_segment_limit(_vbe_surface.lfb_selector, 275 | (_vbe_info.total_memory * 64 * 1024) - 1); 276 | 277 | _vbe_surface.lfb_near_ptr = (void*)(_vbe_surface.lfb_linear_address 278 | + __djgpp_conventional_base); 279 | _vbe_surface.x_resolution = _vbe_mode_info.x_resolution; 280 | _vbe_surface.y_resolution = _vbe_mode_info.y_resolution; 281 | _vbe_surface.bits_per_pixel = _vbe_mode_info.bits_per_pixel; 282 | _vbe_surface.virtual_x_resolution = _vbe_mode_info.x_resolution; 283 | _vbe_surface.bytes_per_pixel = (_vbe_mode_info.bits_per_pixel + 1) / 8; 284 | _vbe_surface.center_x = _vbe_surface.virtual_x_resolution / 2; 285 | _vbe_surface.center_y = _vbe_surface.y_resolution / 2; 286 | _vbe_surface.number_of_offscreens = 287 | VBEsetScanlineLength(_vbe_mode_info.x_resolution) / _vbe_mode_info.y_resolution; 288 | _vbe_surface.vbe_init_boolean = 1; 289 | _vbe_surface.screen_bytes = (_vbe_surface.x_resolution * 290 | _vbe_surface.y_resolution * 291 | _vbe_surface.bytes_per_pixel); 292 | _vbe_surface.screen_dwords = _vbe_surface.screen_bytes / 4; 293 | _vbe_surface.lfb_mem_size = (_vbe_surface.x_resolution * 294 | _vbe_surface.y_resolution * 295 | _vbe_surface.bytes_per_pixel) / 1024 + 296 | _vbe_mode_info.off_screen_mem_size; 297 | 298 | for(counter = 0; counter < (_vbe_surface.lfb_mem_size * 1024); counter++) 299 | _farpokeb(_vbe_surface.lfb_selector, counter, 0x0); // clear Lfb 300 | 301 | if(_vbe_surface.offscreen_ptr) free(_vbe_surface.offscreen_ptr); 302 | if((_vbe_surface.offscreen_ptr = malloc(_vbe_surface.screen_bytes)) == 0) 303 | return(0); 304 | else 305 | memset(_vbe_surface.offscreen_ptr, 0, _vbe_surface.screen_bytes); 306 | 307 | if(_vbe_surface.bits_per_pixel == 8) { 308 | putPixel = putPixel8; 309 | VGAcreatePalette(); 310 | } 311 | if(_vbe_surface.bits_per_pixel == 16) putPixel = putPixel16; 312 | if(_vbe_surface.bits_per_pixel == 15) putPixel = putPixel16; 313 | if(_vbe_surface.bits_per_pixel == 32) putPixel = putPixel32; 314 | 315 | return(&_vbe_surface); 316 | } 317 | 318 | /***************************************************************************** 319 | * * 320 | * VBEmodeInit switches to the desired resolution * 321 | * * 322 | *****************************************************************************/ 323 | VBESURFACE *VBEmodeInit(ushort xres, ushort yres, uchar bpp) 324 | { 325 | ushort vbe_mode_nr; 326 | __dpmi_meminfo m; 327 | 328 | if(_vbe_surface.vbe_boolean == 0) return(0); 329 | if(_vbe_surface.vbe_init_boolean == 0) return(0); 330 | 331 | m.size = (_vbe_info.total_memory * 64 * 1024); 332 | m.address = _vbe_surface.lfb_linear_address; 333 | __dpmi_unlock_linear_region(&m); 334 | __dpmi_free_physical_address_mapping(&m); 335 | __dpmi_free_ldt_descriptor(_vbe_surface.lfb_selector); 336 | 337 | _vbe_surface.vbe_init_boolean = 0; 338 | 339 | if((vbe_mode_nr = VBEselectModeNr(xres, yres, bpp)) == NULL) return(0); 340 | 341 | vbe_mode_nr |= 0x8000; 342 | if(VBEsetMode(vbe_mode_nr) == NULL) return(0); 343 | 344 | return(&_vbe_surface); 345 | } 346 | 347 | /***************************************************************************** 348 | * * 349 | * VBEsetScanlineLength returns the MaxNum of logical scanlines * 350 | * * 351 | *****************************************************************************/ 352 | ushort VBEsetScanlineLength(ushort pixel_length) 353 | { 354 | __dpmi_regs r; 355 | 356 | if(_vbe_surface.vbe_boolean == 0) return(0); 357 | 358 | r.x.ax = 0x4F06; 359 | r.x.bx = 0x0000; 360 | r.x.cx = pixel_length; 361 | __dpmi_int(0x10, &r); 362 | if(r.h.ah != 0) return(0); 363 | if(r.x.cx != pixel_length) return(0); 364 | 365 | _vbe_surface.virtual_x_resolution = pixel_length; 366 | 367 | return(r.x.dx); 368 | } 369 | 370 | /***************************************************************************** 371 | * * 372 | * VBEsetDisplayStart: let's scroll! * 373 | * * 374 | *****************************************************************************/ 375 | void VBEsetDisplayStart(ulong pixel, ulong scanline) 376 | { 377 | __dpmi_regs r; 378 | long address; 379 | long selector; 380 | 381 | if(PM_VBEsetDisplayStart) { 382 | address = (_ytable[scanline] + (pixel * _vbe_surface.bytes_per_pixel)) >> 2; 383 | 384 | selector = (_vbe_surface.io_segment) ? _vbe_surface.io_segment : _my_ds(); 385 | 386 | asm( 387 | " pushw %%es ; " 388 | " movw %w1, %%es ; " // set the IO segment 389 | " call *%0 ; " // call the VESA function 390 | " popw %%es " 391 | : // no outputs 392 | 393 | : "S"(PM_VBEsetDisplayStart), // function pointer in esi 394 | "a"(selector), // IO segment in eax 395 | "b"(0x0080), // mode in ebx 396 | "c"(address & 0xFFFF), // low word of address in ecx 397 | "d"((address >> 16)) // high word of address in edx 398 | 399 | : "memory", "%edi", "%cc" // touches edi and flags 400 | ); 401 | 402 | return; 403 | } 404 | 405 | r.x.ax = 0x4F07; 406 | r.x.bx = 0x0080; 407 | r.x.cx = pixel; 408 | r.x.dx = scanline; 409 | __dpmi_int(0x10, &r); 410 | 411 | } 412 | 413 | /***************************************************************************** 414 | * * 415 | * VBEgetVbeSurfacePtr(void) * 416 | * * 417 | *****************************************************************************/ 418 | VBESURFACE *VBEgetVbeSurfacePtr(void) 419 | { 420 | return(&_vbe_surface); 421 | } 422 | 423 | /***************************************************************************** 424 | * * 425 | * VBEgetModeInfoPtr(void) * 426 | * * 427 | *****************************************************************************/ 428 | MODEINFO *VBEgetModeInfoPtr(void) 429 | { 430 | return(&_vbe_mode_info); 431 | } 432 | 433 | /***************************************************************************** 434 | * * 435 | * VBEinit silently enters the desired mode and returns VbeSurface * 436 | * * 437 | *****************************************************************************/ 438 | VBESURFACE *VBEinit(ushort xres, ushort yres, uchar bpp) 439 | { 440 | ushort vbe_mode_nr; 441 | 442 | if(VBEgetInfo() == NULL) { 443 | puts("\nNo Vesa Bios Extension found..."); 444 | return(0); 445 | } 446 | 447 | if(_vbe_info.vbe_version < 0x0200) { 448 | puts("\nVBE Version 2.0 or better required..."); 449 | return(0); 450 | } 451 | 452 | VBEgetPmodeInterface(); 453 | 454 | if((vbe_mode_nr = VBEselectModeNr(xres, yres, bpp)) == NULL) { 455 | puts("\nNo appropriate Videomode available..."); 456 | return(0); 457 | } 458 | 459 | if(VBEsetMode(vbe_mode_nr) == NULL) 460 | return(0); 461 | else 462 | return(&_vbe_surface); 463 | } 464 | 465 | /***************************************************************************** 466 | * * 467 | * VBEinit shows an info screen then enters the mode, returns VbeSurface * 468 | * * 469 | *****************************************************************************/ 470 | VBESURFACE *VBEinfoInit(ushort xres, ushort yres, uchar bpp, ushort delay_ms) 471 | { 472 | ushort vbe_mode_nr; 473 | char *LFBmsg[] = { "NOLFB present", "LFB present"}; 474 | signed char counter; 475 | 476 | puts("\nVBE2.0 driver v1.0 (c) 1999, Tobias Koch \n"); 477 | 478 | if(VBEgetInfo() == NULL) { 479 | puts("\n\nNo VESA Bios Extension found...\n\n"); 480 | return(0); 481 | } 482 | printf("Video Memory - %d KB \n" 483 | "VBE version - %d.%d detected \n" 484 | "OEM spec. - %s \n", 485 | _vbe_info.total_memory * 64, 486 | _vbe_info.vbe_version >> 8, _vbe_info.vbe_version & 0x00FF, 487 | _vbe_info.oem_string_ptr); 488 | 489 | if(_vbe_info.vbe_version >= 0x0200) { 490 | printf("OEM software rev. - %d.%d\n" 491 | "OEM vendor name - %s \n" 492 | "OEM product name - %s \n" 493 | "OEM product rev. - %s \n", 494 | _vbe_info.oem_software_rev >> 8, _vbe_info.oem_software_rev & 0x00FF, 495 | _vbe_info.oem_vendor_name_ptr, 496 | _vbe_info.oem_product_name_ptr, 497 | _vbe_info.oem_product_rev_ptr); 498 | } else puts("\nVESA Bios Extension 2.0 or better required! " 499 | "\nAttempting to set the mode anyway..."); 500 | 501 | if(VBEgetPmodeInterface()) 502 | puts("\nProtected Mode Interface detected ... "); 503 | 504 | if((vbe_mode_nr = VBEselectModeNr(xres, yres, bpp)) == NULL) { 505 | puts("\nNo appropriate Videomode Available..."); 506 | return(0); 507 | } else if(VBEgetModeInfo(vbe_mode_nr) != NULL) { 508 | printf("\nMode %Xh - %dx%dx%dbpp - RGB %d:%d:%d - %s\n\n", 509 | vbe_mode_nr, 510 | _vbe_mode_info.x_resolution, 511 | _vbe_mode_info.y_resolution, 512 | _vbe_mode_info.bits_per_pixel, 513 | _vbe_mode_info.red_mask_size, 514 | _vbe_mode_info.green_mask_size, 515 | _vbe_mode_info.blue_mask_size, 516 | LFBmsg[((_vbe_mode_info.mode_attributes) & (1<<7)) >> 7]); 517 | } 518 | 519 | delay_ms /= 10; // 10...9...8...7...6...5...4...3...2...1...GO! 520 | if(delay_ms > 0) { 521 | for(counter = 10; counter > 0; counter--) { 522 | delay(delay_ms); 523 | printf("%d..", counter); 524 | } 525 | delay(delay_ms); 526 | printf("Launch"); 527 | delay(delay_ms); 528 | } else getch(); 529 | 530 | if(VBEsetMode(vbe_mode_nr) == NULL) { 531 | VBEshutdown(); 532 | puts("\n\nUnable to access linear frame buffered mode!" 533 | "\nTry loading UNIVBE by Scitech Software (tm). "); 534 | return(0); 535 | } 536 | 537 | return(&_vbe_surface); 538 | } 539 | 540 | /***************************************************************************** 541 | * * 542 | * VBEshutdown cleans up descriptors, memory, etc. * 543 | * * 544 | *****************************************************************************/ 545 | int VBEshutdown(void) 546 | { 547 | __dpmi_regs r; 548 | __dpmi_meminfo m; 549 | 550 | if(_vbe_surface.vbe_init_boolean == 0) { 551 | r.x.ax = 0x03; // make sure we're in 3h 552 | __dpmi_int(0x10, &r); // for buggy vesa implementations 553 | puts("\nuninitialized..."); 554 | return(1); 555 | } 556 | 557 | // free mapping etc. 558 | m.size = (_vbe_info.total_memory * 64 * 1024); 559 | m.address = _vbe_surface.lfb_linear_address; 560 | __dpmi_unlock_linear_region(&m); 561 | __dpmi_free_physical_address_mapping(&m); 562 | __dpmi_free_ldt_descriptor(_vbe_surface.lfb_selector); 563 | 564 | // get rid of PMI interface 565 | if(_pmode_interface_ptr) free(_pmode_interface_ptr); 566 | if(_vbe_surface.io_segment) { 567 | m.address = _vbe_surface.io_linear; 568 | __dpmi_free_physical_address_mapping(&m); 569 | __dpmi_free_ldt_descriptor(_vbe_surface.io_segment); 570 | } 571 | 572 | if(_vbe_surface.offscreen_ptr) free(_vbe_surface.offscreen_ptr); 573 | 574 | // return do DOS 575 | r.x.ax = 0x03; 576 | __dpmi_int(0x10, &r); 577 | 578 | // deinit VBE surface 579 | _vbe_surface.vbe_init_boolean = 0; 580 | _vbe_surface.vbe_boolean = 0; 581 | 582 | puts("Elvis has left the building..."); 583 | 584 | // dealloc mode list 585 | free(_vbe_info.video_mode_ptr); 586 | return(0); 587 | } 588 | 589 | /***************************************************************************** 590 | * * 591 | * Create a Palette for 3:3:2 True-Color emulation * 592 | * * 593 | *****************************************************************************/ 594 | void VGAcreatePalette(void) 595 | { 596 | unsigned char color, red, green, blue; 597 | 598 | color = 0; 599 | for(red = 4; red < 68; red += 8) { 600 | for(green = 4; green < 68; green += 8) { 601 | for(blue = 4; blue < 68; blue += 16) { 602 | outportb(0x3C8, color); 603 | outportb(0x3C9, red); 604 | outportb(0x3C9, green); 605 | outportb(0x3C9, blue); 606 | color++; 607 | } 608 | } 609 | } 610 | } 611 | 612 | /***************************************************************************** 613 | * * 614 | * Wait for Vertical Retrace * 615 | * * 616 | *****************************************************************************/ 617 | void VGAwaitVrt(void) 618 | { 619 | while(inportb(0x3DA) & 8); 620 | while(!(inportb(0x3DA) & 8)); 621 | } 622 | 623 | /***************************************************************************** 624 | * * 625 | * putPixel for 8Bit Screen modes * 626 | * * 627 | *****************************************************************************/ 628 | inline void putPixel8(long x, long y, ulong color) 629 | { 630 | x = +x + _vbe_surface.center_x; 631 | y = -y + _vbe_surface.center_y; 632 | 633 | _farpokeb(_vbe_surface.lfb_selector, _ytable[y] + x , color); 634 | } 635 | 636 | /***************************************************************************** 637 | * * 638 | * putPixel for 16Bit Screen modes * 639 | * * 640 | *****************************************************************************/ 641 | inline void putPixel16(long x, long y, ulong color) 642 | { 643 | x = +x + _vbe_surface.center_x; 644 | y = -y + _vbe_surface.center_y; 645 | 646 | _farpokew(_vbe_surface.lfb_selector, _ytable[y] + (x << 1), color); 647 | } 648 | 649 | /***************************************************************************** 650 | * * 651 | * putPixel for 32Bit Screen modes * 652 | * * 653 | *****************************************************************************/ 654 | inline void putPixel32(long x, long y, ulong color) 655 | { 656 | x = +x + _vbe_surface.center_x; 657 | y = -y + _vbe_surface.center_y; 658 | 659 | _farpokel(_vbe_surface.lfb_selector, _ytable[y] + (x << 2), color); 660 | } 661 | 662 | /***************************************************************************** 663 | * * 664 | * Flip Offsreen to active Screen * 665 | * * 666 | *****************************************************************************/ 667 | inline void flipScreen(void) 668 | { 669 | _movedatal(_my_ds(), (long)_vbe_surface.offscreen_ptr, 670 | _vbe_surface.lfb_selector, 0x0, _vbe_surface.screen_dwords); 671 | } 672 | 673 | -------------------------------------------------------------------------------- /src/vesa.h: -------------------------------------------------------------------------------- 1 | #ifndef __VESA20_H_INCLUDED 2 | #define __VESA20_H_INCLUDED 3 | 4 | struct VBEInfo { 5 | char vbe_signature[4]; // 'VESA' 4 byte signature 6 | short vbe_version; // VBE version number 7 | char *oem_string_ptr; // Pointer to OEM string 8 | unsigned long capabilities; // Capabilities of video card 9 | unsigned short *video_mode_ptr; // Pointer to supported modes 10 | short total_memory; // Number of 64kb memory blocks 11 | // added for VBE 2.0 12 | short oem_software_rev; // OEM Software revision number 13 | char *oem_vendor_name_ptr; // Pointer to Vendor Name string 14 | char *oem_product_name_ptr; // Pointer to Product Name string 15 | char *oem_product_rev_ptr; // Pointer to Product Revision str 16 | char reserved[222]; // Pad to 256 byte block size 17 | char oem_data[256]; // Scratch pad for OEM data 18 | 19 | } __attribute__ ((packed)); 20 | 21 | typedef struct VBEInfo VBEINFO; 22 | 23 | struct VBEModeInfo { 24 | // Mandatory information for all VBE revisions: 25 | unsigned short mode_attributes; // mode attributes 26 | unsigned char win_a_attributes; // window A attributes 27 | unsigned char win_b_attributes; // window B attributes 28 | unsigned short win_granularity; // window granularity 29 | unsigned short win_size; // window size 30 | unsigned short win_a_segment; // window A start segment 31 | unsigned short win_b_segment; // window B start segment 32 | unsigned long win_func_ptr; // pointer to window function 33 | unsigned short bytes_per_scan_line; // bytes per scan line 34 | 35 | // Mandatory information for VBE 1.2 and above: 36 | unsigned short x_resolution; // horizontal resolution in pixels or chars 37 | unsigned short y_resolution; // vertical resolution in pixels or chars 38 | unsigned char x_char_size; // character cell width in pixels 39 | unsigned char y_char_size; // character cell height in pixels 40 | unsigned char number_of_planes; // number of memory planes 41 | unsigned char bits_per_pixel; // bits per pixel 42 | unsigned char number_of_banks; // number of banks 43 | unsigned char memory_model; // memory model type 44 | unsigned char bank_size; // bank size in KB 45 | unsigned char number_of_image_pages; // number of images 46 | unsigned char reserved; // reserved for page function 47 | 48 | // Direct Color fields (required for direct/6 and YUV/7 memory models) 49 | unsigned char red_mask_size; // size of direct color red mask in bits 50 | unsigned char red_field_position; // bit position of lsb of red mask 51 | unsigned char green_mask_size; // size of direct color green mask in bits 52 | unsigned char green_field_position; // bit position of lsb of green mask 53 | unsigned char blue_mask_size; // size of direct color blue mask in bits 54 | unsigned char blue_field_position; // bit position of lsb of blue mask 55 | unsigned char rsvd_mask_size; // size of direct color reserved mask in bits 56 | unsigned char rsvd_field_position; // bit position of lsb of reserved mask 57 | unsigned char direct_color_mode_info; // direct color mode attributes 58 | 59 | // Mandatory information for VBE 2.0 and above: 60 | unsigned long phys_base_ptr; // physical address for flat frame buffer 61 | unsigned long off_screen_mem_offset; // pointer to start of off screen memory 62 | unsigned short off_screen_mem_size; // amount of off screen memory in 1k units 63 | char reserved_buf[206]; 64 | 65 | } __attribute__ ((packed)); 66 | 67 | typedef struct VBEModeInfo MODEINFO; 68 | 69 | struct PModeInterface { 70 | short set_window; 71 | short set_display_start; 72 | short set_palette; 73 | char io_info; 74 | } __attribute__ ((packed)); 75 | 76 | typedef struct PModeInterface PMINTERFACE; 77 | 78 | struct VBESurface { 79 | unsigned long lfb_linear_address; 80 | unsigned short lfb_selector; 81 | void *lfb_near_ptr; 82 | unsigned long lfb_mem_size; 83 | unsigned short x_resolution; 84 | unsigned short y_resolution; 85 | unsigned long bits_per_pixel; 86 | unsigned short virtual_x_resolution; 87 | unsigned long bytes_per_pixel; 88 | unsigned long screen_bytes; 89 | unsigned long screen_dwords; 90 | unsigned long center_x; 91 | unsigned long center_y; 92 | unsigned short number_of_offscreens; 93 | void* offscreen_ptr; 94 | unsigned char vbe_boolean; 95 | unsigned char vbe_init_boolean; 96 | signed long io_segment; 97 | unsigned long io_linear; 98 | 99 | }; 100 | 101 | typedef struct VBESurface VBESURFACE; 102 | 103 | //********************************Functions*********************************// 104 | 105 | VBEINFO *VBEgetInfo(void); 106 | MODEINFO *VBEgetModeInfo(ushort vbe_mode_nr); 107 | void *VBEgetPmodeInterface(void); 108 | ushort VBEselectModeNr(ushort xres, ushort yres, uchar bpp); 109 | VBESURFACE *VBEsetMode(ushort vbe_mode_nr); 110 | VBESURFACE *VBEmodeInit(ushort xres, ushort yres, uchar bpp); 111 | ushort VBEsetScanlineLength(ushort pixel_length); 112 | void VBEsetDisplayStart(ulong pixel, ulong scanline); 113 | VBESURFACE *VBEgetVbeSurfacePtr(void); 114 | MODEINFO *VBEgetModeInfoPtr(void); 115 | VBESURFACE *VBEinfoInit(ushort xres, ushort yres, uchar bpp, ushort delay); 116 | VBESURFACE *VBEinit(ushort xres, ushort yres, uchar bpp); 117 | int VBEshutdown(void); 118 | 119 | void VGAcreatePalette(void); 120 | void VGAwaitVrt(void); 121 | 122 | inline void putPixel8(long x, long y, ulong color); 123 | inline void putPixel16(long x, long y, ulong color); 124 | inline void putPixel32(long x, long y, ulong color); 125 | inline void flipScreen(void); 126 | 127 | extern void (*putPixel)(long x, long y, ulong color); 128 | 129 | #endif 130 | --------------------------------------------------------------------------------