Прикол Скелетон. Программа для MS-Dos.
Показывает картинку. Масштабирует.
При запуске без параметров, будет пытаться
открыть файл Skeleton.bmp
Картинка должна быть 256-ти цветная, размеры 320 на 200.
Запуск своей картинки: Skeleton Picture.BMP
Рабочие клавиши: Q - Выйти.
Стрелки Вверх, Вниз - увеличить, уменьшить.
Клавиши Плюс, Минус - медленнее, быстрее.
R - сброс.

Внимание: программа корректно работает только в Dos, Windows 9x - XP.
В DosBox - не работает (тормозит)!
Развернуть: Исходный код- Код: Выделить всё
// Skeleton.cpp
//
// Draw bitmap 320 x 200 256 colors. Scaling. Rotate.
// Work key:
// Q - Exit program.
// Arrows Up, Down, key Plus, Minus.
// R - reset.
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <alloc.h>
#include <memory.h>
#include <math.h>
#pragma warn -sig // Suppress warn msg Conversion may lose significant digits.
typedef unsigned char byte;
byte far* vgaScreen=(byte far*)0xA0000000L; // This points to video memory.
char* g_szFilename="Skeleton.bmp"; // Default filename.
void SetVideoMode(byte mode)
{
union REGS inregs,outregs;
inregs.h.ah=0;
inregs.h.al=mode;
int86(0x10,&inregs,&outregs);
}
/*
* Entry point.
*/
void main(unsigned int argc, char* argv[])
{
char* fname=g_szFilename; // Default filename.
if (argc>=2) // If we have enought arguments.
fname=argv[1];
FILE* stream=fopen(fname,"rb");
if (!stream) {
printf("%s cant open file.\n",fname);
system("pause>nul"); // Press Any key...
exit(1);
}
// Check picture format.
if ('B'!=fgetc(stream) || 'M'!=fgetc(stream)) {
fclose(stream);
printf("%s is not a bitmap file.\n",fname);
system("pause>nul");
exit(1);
}
int nWidth,nHeight; // Check picture size.
fseek(stream,18,SEEK_SET);
fread(&nWidth,sizeof(int),1,stream);
fseek(stream,22,SEEK_SET);
fread(&nHeight,sizeof(int),1,stream);
if (nWidth>320 || nHeight>200) {
fclose(stream);
printf("%s is picture format not supported.\n",fname);
system("pause>nul");
exit(1);
}
int nColors; // Check dept colors.
fseek(stream,28,SEEK_SET);
fread(&nColors,sizeof(int),1,stream);
if (nColors>8) {
fclose(stream);
printf("%s is bitmap dept colors need 256 (8BPP).\n",fname);
system("pause>nul");
exit(1);
}
// Allocate screen buffer memory.
byte far* screen=(byte far*)farmalloc(64000U);
if (!screen) {
printf("Error allocating screen memory.\n");
exit(1);
}
byte far* scrImage=(byte far*)farmalloc(64000U);
if (!scrImage) {
printf("Error allocating screen memory #2.\n");
system("pause>nul");
exit(1);
}
SetVideoMode(0x13); // Set video mode to graphics mode 320X200X256
outportb(0x3C2,0xE3); // Set square aspect ratio.
fseek(stream,54,SEEK_SET); // Set pointer to palette.
// This sets a DAC register to a specific red green blue value.
byte palBuff[256][4];
fread(&palBuff,1024,1,stream);
for (int i=0;i<256;++i) {
outportb(0x3C8,i);
outportb(0x3C9,palBuff[i][2]>>2);
outportb(0x3C9,palBuff[i][1]>>2);
outportb(0x3C9,palBuff[i][0]>>2);
}
long nCount=64000U; // Set pointer to data and load.
while (nCount>0)
scrImage[--nCount]=getc(stream);
fclose(stream);
for (int i=0;i<nHeight;++i)
for (int j=0;j<nWidth;++j)
vgaScreen[((i<<8)+(i<<6))+(nWidth-j)]=scrImage[((i<<8)+(i<<6))+j];
_fmemset(vgaScreen,0,64000U);
// Initialize fixed point sin, cos tables.
static long cosTab[256];
static long sinTab[256];
for (int i=0;i<256;++i) {
cosTab[i]=cos((6.28/256)*i)*1024;
sinTab[i]=sin((6.28/256)*i)*1024;
}
// Initialize y offset table.
static int yTab[200];
for (int i=0;i<200;++i)
yTab[i]=i*320;
int nAngle,nDone,nScale=800;
nAngle=nDone=nCount=0;
int nDelay=20;
int ch=0;
while (ch != 'q' && ch != 'Q') // Q - Exit program
{
if (kbhit())
{
ch = getch();
if (ch == 72) // Arrow Up
{
if (nScale <= 0)
nScale = 0;
else
nScale -= 10;
}
if (ch == 80) // Arrow Down
{
if (nScale >= 7000)
nScale = 7000;
else
nScale += 10;
}
if (ch == '+' || ch == '=') // Plus +
{
if (nDelay >= 100)
nDelay = 100;
else
nDelay += 1;
}
if (ch == '-') // Minus -
{
if (nDelay <= 1)
nDelay = 1;
else
nDelay -= 1;
}
if (ch == 'r' || ch == 'R') // Reset
{
nScale = 800;
nDelay = 20;
}
}
switch (nDone)
{
case 0:
if (nCount>=50)
nDone = 1;
++nCount;
nAngle = nCount;
break;
case 1:
if (nCount<=1)
nDone = 2;
--nCount;
nAngle = nCount;
break;
case 2:
if (nCount>=50)
nDone = 3;
++nCount;
nAngle = 255-nCount;
break;
case 3:
if (nCount<=1)
nDone = 0;
--nCount;
nAngle = 255-nCount;
}
long c=cosTab[nAngle];
long s=sinTab[nAngle];
for (int y=-100; y<100; ++y)
{
long ys=(y*s>>10);
long yc=(y*c>>10);
for (int x=-160; x<160; ++x)
{
// x = cos(x)-sin(y) * nScale;
int xT = ((((x*c)>>10)-ys)*nScale)>>10;
// y = sin(x)+cos(y) * nScale;
int yT = ((((x*s)>>10)+yc)*nScale)>>10;
if (xT > -160 && xT < 160 && yT > -100 && yT < 100)
{
screen[(x+160)+yTab[(y+100)]]=
scrImage[(xT+160)+yTab[yT+100]];
}
}
}
_fmemcpy(vgaScreen,screen,64000U);
_fmemset(screen,0,64000U);
delay(nDelay);
}
// Clean up.
if (screen)
farfree(screen);
if (scrImage)
farfree(scrImage);
SetVideoMode(0x03); // Return to text mode.
}
P.S. Отредактировано.
Исправлена ошибка в тексте (клавиша сброса R).