diff --git a/data/Tupfile.lua b/data/Tupfile.lua index 49b4e843dc..1e495d0920 100644 --- a/data/Tupfile.lua +++ b/data/Tupfile.lua @@ -137,6 +137,8 @@ extra_files = { {"kolibrios/emul/", "common/emul/zsnes"}, {"kolibrios/games/doom/", "common/games/doom/*"}, {"kolibrios/games/fara/fara.gfx", "common/games/fara.gfx"}, + {"kolibrios/games/LaserTank/", "common/games/LaserTank/levels.lvl"}, + {"kolibrios/games/LaserTank/", "common/games/LaserTank/arh.pak"}, {"kolibrios/games/jumpbump/", "common/games/jumpbump/*"}, {"kolibrios/games/lrl/", "common/games/lrl/*"}, {"kolibrios/games/rstearth/barret_8bpp.png", PROGS .. "/games/rstearth/resources/barret_8bpp.png"}, @@ -466,6 +468,7 @@ tup.append_table(img_files, { }) tup.append_table(extra_files, { {"kolibrios/games/fara/fara", PROGS .. "/games/fara/trunk/fara"}, + {"kolibrios/games/LaserTank/LaserTank", PROGS .. "/games/LaserTank/trunk/LaserTank"}, }) end -- tup.getconfig('NO_MSVC') ~= 'full' diff --git a/data/common/games/LaserTank/arh.pak b/data/common/games/LaserTank/arh.pak new file mode 100644 index 0000000000..b9be3f86b8 Binary files /dev/null and b/data/common/games/LaserTank/arh.pak differ diff --git a/data/common/games/LaserTank/levels.lvl b/data/common/games/LaserTank/levels.lvl new file mode 100644 index 0000000000..dc7b894f67 Binary files /dev/null and b/data/common/games/LaserTank/levels.lvl differ diff --git a/programs/games/LaserTank/trunk/LaserTank.cpp b/programs/games/LaserTank/trunk/LaserTank.cpp new file mode 100644 index 0000000000..ea332e0b0e --- /dev/null +++ b/programs/games/LaserTank/trunk/LaserTank.cpp @@ -0,0 +1,811 @@ +#include +#include +#include +#include +#include "render.h" +#include "image.h" + +#define MODE_MENU 0 +#define MODE_LEVELS 1 +#define MODE_GAME 2 + +#define GAME_NONE 0 +#define GAME_VICTORY 1 +#define GAME_DEFEAT 2 + +#define MOUSE_LEFT 0 + +char* header = "Laser Tank"; + +struct Level +{ + char fileds[16][16]; +}; + +Level *levels; +int levelCount = 0; +int levelIndex = 0; + +RGBA img_tank[576]; +RGB img_water[576]; +RGB img_brick[576]; +RGB img_waterbox[576]; +RGB img_ground[576]; +RGB img_wall[576]; +RGB img_finish[576]; +RGBA img_box[576]; +RGBA img_laser[576]; +RGBA img_mirror[576]; +RGBA img_mirror90[576]; +RGBA img_mirror180[576]; +RGBA img_mirror270[576]; +RGBA img_mini_mirror[576]; +RGBA img_mini_mirror90[576]; +RGBA img_mini_mirror180[576]; +RGBA img_mini_mirror270[576]; +RGBA img_laser1[576]; +RGBA img_laser2[576]; +RGB img_brick1[576]; +RGB img_menu[147456]; +RGBA img_explosion[8064]; + +RGB img_button[7500]; + +Player player; + +CKosRender* renderPlayer; +CKosImage* objPlayer; + +CKosRender* renderLaser; +CKosImage* objLaser; +CKosImage* objLaser1; +CKosImage* objLaser2; + +CKosRender* renderMirror; +CKosImage* objMirror; +CKosImage* objMirror90; +CKosImage* objMirror180; +CKosImage* objMirror270; + +CKosImage* objMiniMirror; +CKosImage* objMiniMirror90; +CKosImage* objMiniMirror180; +CKosImage* objMiniMirror270; + +CKosRender* renderBox; +CKosImage* objBox; + +CKosRender* renderExplosion; +CKosImage* objExplosion; + +int gameMode = MODE_MENU; +int gameStatus = GAME_NONE; + +void draw_window(); +void openLevel(int index); + +bool CollRecrVsPoint(Point point, Rect rect) +{ + return (point.X > rect.X && point.Y > rect.Y && point.X < rect.X + rect.Width && point.Y < rect.Y + rect.Height); +} + +struct Button +{ + Rect rect; + char* caption; + Button() {} + Button(char* caption, Rect rect) + { + this->caption = caption; + this->rect = rect; + } +}; + +Button ToGame("Game", Rect(150, 258, 224, 50)); +Button ToExit("Exit", Rect(150, 321, 224, 50)); + +struct LvlItem +{ + char s; + char d; + Byte l; +}; + +LvlItem level[16][16]; + +char GetField(Point position, bool din) +{ + if (din && level[position.Y][position.X].d != ' ') + return level[position.Y][position.X].d; + return level[position.Y][position.X].s; +} + +RGB* GetImg(Point position, bool din) +{ + switch (GetField(position, din)) + { + case 's': + return (RGB*)img_wall; + case '7': + renderMirror->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objMirror->Draw(Point(0, 0), 0); + return renderMirror->buffer; + case '9': + renderMirror->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objMirror90->Draw(Point(0, 0), 0); + return renderMirror->buffer; + case '3': + renderMirror->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objMirror180->Draw(Point(0, 0), 0); + return renderMirror->buffer; + case '1': + renderMirror->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objMirror270->Draw(Point(0, 0), 0); + return renderMirror->buffer; + case 'h': + case 'g': + return (RGB*)img_ground; + case 'b': + renderBox->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objBox->Draw(Point(0, 0), 0); + return renderBox->buffer; + // return (RGB*)img_box; + case 'f': + return (RGB*)img_finish; + case 'x': + return (RGB*)img_brick; + case 'w': + return (RGB*)img_water; + case 'e': + return (RGB*)img_waterbox; + case 'y': + return (RGB*)img_brick1; + } + return NULL; +} + +void DrawElevent(Point position, bool din) +{ + kos_PutImage(GetImg(position, din), 24, 24, 24 * position.X, 24 * position.Y); +} + +void MoveBox(Point a, Point b) +{ + level[a.Y][a.X].d = ' '; + DrawElevent(a, true); + if (level[b.Y][b.X].s == 'w') + { + level[b.Y][b.X].s = 'e'; + DrawElevent(b, true); + } + else + { + level[b.Y][b.X].d = 'b'; + DrawElevent(b, true); + } +} + +void animation(Point vector, float angle) +{ + for (int i = 2; i < 23; ++i) + { + kos_WindowRedrawStatus(1); + DrawElevent(player.position, false); + DrawElevent(player.position + vector, false); + + renderPlayer->RenderImg(GetImg(player.position, true), Point(0, 0), 24, 24); + objPlayer->Draw(Point(0, 0), angle); + renderPlayer->Draw(player.position * 24 + vector * i); + if (level[player.position.Y + vector.Y][player.position.X + vector.X].d == 'b') + { + renderBox->RenderImg(GetImg(player.position, true), Point(0, 0), 24, 24); + objBox->Draw(Point(0, 0), 0); + renderBox->Draw((player.position + vector) * 24 + vector * i); + } + kos_WindowRedrawStatus(2); + kos_Pause(1); + } + + if (level[player.position.Y + vector.Y][player.position.X + vector.X].d == 'b') + MoveBox(player.position + vector, player.position + vector * 2); + + DrawElevent(player.position, true); + DrawElevent(player.position + vector, true); + player.position = player.position + vector; + //kos_PutImage(GetImg(player.position + vector), 24, 24, 24 * player.position.X, 24 * player.position.Y); + renderPlayer->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objPlayer->Draw(Point(0, 0), angle); + renderPlayer->Draw(player.position * 24); +} + +void DrawLaser(Point position, int frame) +{ + renderLaser->RenderImg(GetImg(position, false), Point(0, 0), 24, 24); + switch (frame) + { + case 1: + objLaser->Draw(Point(0, 0), 0, (RGB)0x00FF00); + break; + case 2: + objLaser->Draw(Point(0, 0), 90, (RGB)0x00FF00); + break; + case 3: + objLaser2->Draw(Point(0, 0), 0, (RGB)0x00FF00); + break; + default: + objLaser1->Draw(Point(-1, 0), (float)frame, (RGB)0x00FF00); + } + renderLaser->Draw(position * 24); + level[position.Y][position.X].l = 1; +} + +void PlayerLaser(void) +{ + Point vector = player.vector; + Point position = player.position + vector; + bool en = true; + + while (en) + { + switch (GetField(position, true)) + { + case 'b': + if (position + vector != player.position) + switch (GetField(position + vector, true)) + { + case 'g': + case 'w': + case 'e': + for (int i = 2; i < 23; ++i) + { + DrawElevent(position, false); + DrawElevent(position + vector, true); + DrawLaser(position, (vector.X != 0) ? 1 : 2); + renderBox->RenderImg(GetImg(position, false), Point(0, 0), 24, 24); + objBox->Draw(Point(0, 0), 0); + renderBox->Draw((position) * 24 + vector * i); + kos_Pause(1); + } + MoveBox(position, position + vector); + } + en = false; + break; + case 'x': + for (int i = 0; i < 23; ++i) + { + if (i == 11 || i == 22) + { + level[position.Y][position.X].l -= 1; + if (level[position.Y][position.X].l == 2) + { + level[position.Y][position.X].s = 'y'; + level[position.Y][position.X].l = 0; + } + // rtlDebugOutString(ftoa(level[position.Y][position.X].l)); + + DrawElevent(position, false); + } + kos_Pause(1); + } + en = false; + break; + case 'g': + case 'w': + case 'y': + case 'e': + if (player.position == position) + { + + for (int i = 2; i < 23; ++i) + kos_Pause(1); + for (int y = 0; y < 16; y++) + for (int x = 0; x < 16; x++) + if (level[y][x].l == 1) + { + DrawElevent(Point(x, y), true); + level[y][x].l = 0; + } + for (int i = 0; i < 14; ++i) + { + renderExplosion->RenderImg(GetImg(position, false), Point(0, 0), 24, 24); + objExplosion->Draw(Point(0, 0), 0, i); + renderExplosion->Draw((position)* 24); + kos_Pause(2); + } + gameStatus = GAME_DEFEAT; + draw_window(); + return; + } + else + { + if (level[position.Y][position.X].l == 1) + DrawLaser(position, 3); + else + DrawLaser(position, (vector.X != 0) ? 1 : 2); + } + break; + case '7': + if (vector == Point(-1, 0) || vector == Point(0, -1)) + { + vector = (vector.Y == -1) ? Point(1, 0) : Point(0, 1); + DrawLaser(position, 0); + } + else + { + for (int i = 2; i < 23; ++i) + kos_Pause(1); + en = false; + } + break; + case '9': + if (vector == Point(0, -1) || vector == Point(1, 0)) + { + vector = (vector.Y == -1) ? Point(-1, 0) : Point(0, 1); + DrawLaser(position, 90); + } + else + { + for (int i = 2; i < 23; ++i) + kos_Pause(1); + en = false; + } + break; + case '1': + if (vector == Point(-1, 0) || vector == Point(0, 1)) + { + vector = (vector.Y == 1) ? Point(1, 0) : Point(0, -1); + DrawLaser(position, 270); + } + else + { + for (int i = 2; i < 23; ++i) + kos_Pause(1); + en = false; + } + break; + case '3': + if (vector == Point(1, 0) || vector == Point(0, 1)) + { + vector = (vector.Y == 1) ? Point(-1, 0) : Point(0, -1); + DrawLaser(position, 180); + } + else + { + for (int i = 2; i < 23; ++i) + kos_Pause(1); + en = false; + } + break; + default: + for (int i = 2; i < 23; ++i) + kos_Pause(1); + en = false; + } + position = position + vector; + } + + for (int y = 0; y < 16; y++) + for (int x = 0; x < 16; x++) + if (level[y][x].l == 1) + { + DrawElevent(Point(x, y), true); + level[y][x].l = 0; + } + +} + +void player_move(Point vector, float angle) +{ + if (player.vector == vector) + { + switch (GetField(player.position + vector, true)) + { + case 'b': + switch (GetField(player.position + vector * 2, true)) + { + case 'g': + case 'w': + case 'e': + case 'y': + animation(vector, angle); + return; + } + break; + case 'f': + gameStatus = GAME_VICTORY; + draw_window(); + break; + case ' ': + case 'x': + case 's': + case 'w': + case '7': + case '9': + case '3': + case '1': + break; + default: + animation(vector, angle); + } + } + else + { + int cnt; + float addAngle; + if (player.vector == vector * -1) + { + cnt = 48; + addAngle = 3.5f; + } + else + { + cnt = 24; + if (player.angle == 270 && angle == 0 || player.angle == 0 && angle == 270) + addAngle = (player.angle == 0) ? -3.5f : 3.5f; + else + addAngle = (angle < player.angle) ? -3.5f : 3.5f; + } + + for (int i = 1; i < cnt - 1; ++i) + { + player.angle += addAngle; + renderPlayer->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objPlayer->Draw(Point(0, 0), player.angle); + renderPlayer->Draw(player.position * 24); + kos_Pause(1); + } + + player.vector = vector; + player.angle = angle; + + renderPlayer->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objPlayer->Draw(Point(0, 0), player.angle); + renderPlayer->Draw(player.position * 24); + } +} + +void SetMode(int mode) +{ + gameMode = mode; + draw_window(); +} + +void key_press(int key) +{ + //rtlDebugOutString(ftoa(key)); + + switch (gameMode) + { + case MODE_MENU: + + break; + case MODE_LEVELS: + + break; + case MODE_GAME: + switch (key) + { + case 119: // Up + case 178: // W + if (gameStatus == GAME_NONE) + player_move(Point(0, -1), 270); + break; + case 177: // Down + case 115: // S + if (gameStatus == GAME_NONE) + player_move(Point(0, 1), 90); + break; + case 176: // Left + case 97: // A + if (gameStatus == GAME_NONE) + player_move(Point(-1, 0), 180); + break; + case 179: // Right + case 100: // D + if (gameStatus == GAME_NONE) + player_move(Point(1, 0), 0); + break; + case 32: // Space + if (gameStatus == GAME_NONE) + PlayerLaser(); + break; + case 13: + if (gameStatus == GAME_VICTORY) + openLevel(levelIndex + 1); + else + if (gameStatus == GAME_DEFEAT) + openLevel(levelIndex); + break; + } + break; + } +} + +void MousePress(int button, Point position) +{ + //rtlDebugOutString("Mouse"); + //rtlDebugOutString(ftoa(position.X)); + //rtlDebugOutString(ftoa(position.Y)); + + switch (gameMode) + { + case MODE_MENU: + if (CollRecrVsPoint(position, ToGame.rect)) + SetMode(MODE_GAME); + if (CollRecrVsPoint(position, ToExit.rect)) + kos_ExitApp(); + break; + case MODE_LEVELS: + + break; + case MODE_GAME: + + break; + } +} + +void draw_window(void) +{ + kos_WindowRedrawStatus(1); + kos_DefineAndDrawWindow(10, 40, 384 + 9, 384 + 25, 0x33, 0x444444, 0, 0, (Dword)header); + + switch (gameMode) + { + case MODE_MENU: + kos_PutImage((RGB*)img_menu, 384, 384, 0, 0); + + // kos_PutImage((RGB*)img_button, 150, 50, ToGame.rect.X, ToGame.rect.Y); + + + break; + case MODE_LEVELS: + + break; + case MODE_GAME: + for (int y = 0; y < 16; y++) + for (int x = 0; x < 16; x++) + { + if (level[y][x].s != ' ') + kos_PutImage(GetImg(Point(x, y), true), 24, 24, 24 * x, 24 * y); + if (level[y][x].d == 'b') + { + renderBox->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objBox->Draw(Point(0, 0), 0); + renderBox->Draw(Point(x, y) * 24); + } + } + + switch (gameStatus) + { + case GAME_NONE: + renderPlayer->RenderImg(GetImg(player.position, false), Point(0, 0), 24, 24); + objPlayer->Draw(Point(0, 0), player.angle); + renderPlayer->Draw(player.position * 24); + break; + case GAME_VICTORY: + kos_WriteTextToWindow(30, 10, 0x80, 0xFFFFFF, "VICTORY", 0); + break; + case GAME_DEFEAT: + kos_WriteTextToWindow(30, 10, 0x80, 0xFFFFFF, "DEFEAT", 0); + break; + } + break; + } + kos_WindowRedrawStatus(2); +} + +void LevelsLoad() +{ + char *cPtr; + cPtr = strrchr(kosExePath, '/'); + + if (cPtr == NULL) + { + rtlDebugOutString("Invalid path to executable."); + return; + } + cPtr[1] = 0; + strcpy(cPtr + 1, "levels.lvl"); + + CKosFile *file = new CKosFile(kosExePath); + + Byte block[256]; + while (file->Read(block, 256) == 256) + { + levelCount++; + } + //levelCount++; + rtlDebugOutString(ftoa(levelCount)); + + levels = new Level[levelCount]; + + file->Seek(0, SEEK_SET); + for (int i = 0; i < levelCount; ++i) + { + file->Read(block, 256); + int k = 0; + + for (int y = 0; y < 16; y++) + for (int x = 0; x < 16; x++) + { + // if (block[k] != 0) + // rtlDebugOutString(ftoa(block[k])); + switch (block[k]) + { + case 0: + levels[i].fileds[y][x] = ' '; + break; + case 1: + levels[i].fileds[y][x] = 'w'; + break; + case 2: + levels[i].fileds[y][x] = 'g'; + break; + case 3: + levels[i].fileds[y][x] = 'x'; + break; + case 4: + levels[i].fileds[y][x] = 's'; + break; + case 5: + levels[i].fileds[y][x] = 'b'; + break; + case 6: + levels[i].fileds[y][x] = '7'; + break; + case 7: + levels[i].fileds[y][x] = '9'; + break; + case 8: + levels[i].fileds[y][x] = '3'; + break; + case 9: + levels[i].fileds[y][x] = '1'; + break; + case 10: + levels[i].fileds[y][x] = 'h'; + break; + case 11: + levels[i].fileds[y][x] = 'f'; + break; + } + k++; + } + } + + +} + +void openLevel(int index) +{ + levelIndex = index; + for (int y = 0; y < 16; y++) + for (int x = 0; x < 16; x++) + { + level[y][x].s = levels[index].fileds[y][x]; + level[y][x].d = ' '; + level[y][x].l = 0; + switch (levels[index].fileds[y][x]) + { + case 'b': + level[y][x].s = 'g'; + level[y][x].d = 'b'; + break; + case 'h': + player = Player(Point(x, y)); + level[y][x].s = 'g'; + break; + case 'x': + level[y][x].l = 6; + break; + } + } + gameStatus = GAME_NONE; + draw_window(); +} + +void kos_Main() +{ + rtlDebugOutString(" "); + rtlDebugOutString("kos_Main"); + char *cPtr; + cPtr = strrchr(kosExePath, '/'); + // проверка ;) + if (cPtr == NULL) + { + rtlDebugOutString("Invalid path to executable."); + return; + } + cPtr[1] = 0; + strcpy(cPtr + 1, "arh.pak"); + + CKosFile *file = new CKosFile(kosExePath); + + file->LoadTex((Byte*)img_box, 4, 24, 24); + file->LoadTex((Byte*)img_brick, 3, 24, 24); + file->LoadTex((Byte*)img_finish, 3, 24, 24); + file->LoadTex((Byte*)img_ground, 3, 24, 24); + file->LoadTex((Byte*)img_laser, 4, 24, 24); + file->LoadTex((Byte*)img_laser1, 4, 24, 24); + file->LoadTex((Byte*)img_laser2, 4, 24, 24); + + file->LoadTex((Byte*)img_mirror, 4, 24, 24); + file->LoadTex((Byte*)img_mirror90, 4, 24, 24); + file->LoadTex((Byte*)img_mirror180, 4, 24, 24); + file->LoadTex((Byte*)img_mirror270, 4, 24, 24); + + file->LoadTex((Byte*)img_mini_mirror, 4, 24, 24); + file->LoadTex((Byte*)img_mini_mirror90, 4, 24, 24); + file->LoadTex((Byte*)img_mini_mirror180, 4, 24, 24); + file->LoadTex((Byte*)img_mini_mirror270, 4, 24, 24); + + file->LoadTex((Byte*)img_tank, 4, 24, 24); + file->LoadTex((Byte*)img_wall, 3, 24, 24); + file->LoadTex((Byte*)img_water, 3, 24, 24); + file->LoadTex((Byte*)img_waterbox, 3, 24, 24); + file->LoadTex((Byte*)img_brick1, 3, 24, 24); + file->LoadTex((Byte*)img_menu, 3, 384, 384); + file->LoadTex((Byte*)img_button, 3, 150, 50); + file->LoadTex((Byte*)img_explosion, 4, 24, 336); + + delete file; + + renderPlayer = new CKosRender(24, 24); + objPlayer = new CKosImage(renderPlayer, (RGBA*)img_tank, 24, 24); + + renderLaser = new CKosRender(24, 24); + objLaser = new CKosImage(renderLaser, (RGBA*)img_laser, 24, 24); + objLaser->SetMode(DRAW_ALPHA_ADD); + objLaser1 = new CKosImage(renderLaser, (RGBA*)img_laser1, 24, 24); + objLaser1->SetMode(DRAW_ALPHA_ADD); + objLaser2 = new CKosImage(renderLaser, (RGBA*)img_laser2, 24, 24); + objLaser2->SetMode(DRAW_ALPHA_ADD); + + renderMirror = new CKosRender(24, 24); + objMirror = new CKosImage(renderMirror, (RGBA*)img_mirror, 24, 24); + objMirror90 = new CKosImage(renderMirror, (RGBA*)img_mirror90, 24, 24); + objMirror180 = new CKosImage(renderMirror, (RGBA*)img_mirror180, 24, 24); + objMirror270 = new CKosImage(renderMirror, (RGBA*)img_mirror270, 24, 24); + + objMiniMirror = new CKosImage(renderMirror, (RGBA*)img_mini_mirror, 24, 24); + objMiniMirror = new CKosImage(renderMirror, (RGBA*)img_mini_mirror90, 24, 24); + objMiniMirror = new CKosImage(renderMirror, (RGBA*)img_mini_mirror180, 24, 24); + objMiniMirror = new CKosImage(renderMirror, (RGBA*)img_mini_mirror270, 24, 24); + + renderBox = new CKosRender(24, 24); + objBox = new CKosImage(renderBox, (RGBA*)img_box, 24, 24); + + renderExplosion = new CKosRender(24, 24); + objExplosion = new CKosImage(renderExplosion, (RGBA*)img_explosion, 24, 24); + objExplosion->SetFrameSize(24, 24); + + LevelsLoad(); + + openLevel(0); + + kos_SetMaskForEvents(0x27); + for (;;) + { + switch (kos_WaitForEvent()) + { + case 1: + draw_window(); + break; + case 2: + Byte keyCode; + kos_GetKey(keyCode); + key_press(keyCode); + break; + case 3: + kos_ExitApp(); + break; + case 6: + Dword buttons; + int mX, mY; + kos_GetMouseState(buttons, mX, mY); + if (buttons & 1) + MousePress(MOUSE_LEFT, Point(mX, mY)); + break; + } + } +} diff --git a/programs/games/LaserTank/trunk/LaserTank.sdf b/programs/games/LaserTank/trunk/LaserTank.sdf new file mode 100644 index 0000000000..b479f130df Binary files /dev/null and b/programs/games/LaserTank/trunk/LaserTank.sdf differ diff --git a/programs/games/LaserTank/trunk/LaserTank.sln b/programs/games/LaserTank/trunk/LaserTank.sln new file mode 100644 index 0000000000..ac91ee8cbb --- /dev/null +++ b/programs/games/LaserTank/trunk/LaserTank.sln @@ -0,0 +1,20 @@ +п»їMicrosoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LaserTank", "LaserTank.vcxproj", "{A88BE65F-43CA-46F4-BC96-2B0ECC07C63B}" + ProjectSection(ProjectDependencies) = postProject + {911D4818-1AA1-4351-9C0A-38749130FAA6} = {911D4818-1AA1-4351-9C0A-38749130FAA6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smalllibc", "smalllibc\smalllibc.vcxproj", "{911D4818-1AA1-4351-9C0A-38749130FAA6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A88BE65F-43CA-46F4-BC96-2B0ECC07C63B}.Release|Win32.ActiveCfg = Release|Win32 + {A88BE65F-43CA-46F4-BC96-2B0ECC07C63B}.Release|Win32.Build.0 = Release|Win32 + {911D4818-1AA1-4351-9C0A-38749130FAA6}.Release|Win32.ActiveCfg = Release|Win32 + {911D4818-1AA1-4351-9C0A-38749130FAA6}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection +EndGlobal diff --git a/programs/games/LaserTank/trunk/LaserTank.vcxproj b/programs/games/LaserTank/trunk/LaserTank.vcxproj new file mode 100644 index 0000000000..f1522b9a39 --- /dev/null +++ b/programs/games/LaserTank/trunk/LaserTank.vcxproj @@ -0,0 +1,78 @@ +п»ї + + + + Release + Win32 + + + + {A88BE65F-43CA-46F4-BC96-2B0ECC07C63B} + LaserTank + + + + Application + false + true + MultiByte + v120 + + + + + + + + + + false + false + h:\ + + + + Level3 + MinSpace + true + true + false + MultiThreaded + smalllibc + true + Size + false + + + false + true + true + true + fakeEntry + Native + /merge:.data=.text /merge:.rdata=.text /merge:.1seg=.text /section:.bss,E %(AdditionalOptions) + true + + + set EXENAME=$(TargetPath) +"D:\Download\fasmw17122\FASM.EXE" $(ProjectDir)smalllibc\doexe2.asm $(TargetDir)$(TargetName) + + + + + + + + + + {911D4818-1AA1-4351-9C0A-38749130FAA6} + + + + + + + + + + \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/LaserTank.vcxproj.filters b/programs/games/LaserTank/trunk/LaserTank.vcxproj.filters new file mode 100644 index 0000000000..e2c063969c --- /dev/null +++ b/programs/games/LaserTank/trunk/LaserTank.vcxproj.filters @@ -0,0 +1,36 @@ +п»ї + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + + + Заголовочные файлы + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/Tupfile.lua b/programs/games/LaserTank/trunk/Tupfile.lua new file mode 100644 index 0000000000..684f9f0d8e --- /dev/null +++ b/programs/games/LaserTank/trunk/Tupfile.lua @@ -0,0 +1,13 @@ +if tup.getconfig("NO_FASM") ~= "" or tup.getconfig("NO_MSVC") ~= "" then return end +HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../.." or tup.getconfig("HELPERDIR") +tup.include(HELPERDIR .. "/use_msvc.lua") +if tup.getconfig("LANG") == "ru" +then CFLAGS = CFLAGS .. " /DLANG=RUS" +else CFLAGS = CFLAGS .. " /DLANG=ENG" +end +tup.append_table(OBJS, + tup.foreach_rule("memcmp.asm", "fasm %f %o", "%B.obj") +) +table.insert(OBJS, "smalllibc/init.obj") -- ??? it doesn't work after fasm recompilation +compile_msvc{"smalllibc/func.cpp", "smalllibc/kosFile.cpp", "smalllibc/kosSyst.cpp", "smalllibc/math2.cpp", "smalllibc/mcsmemm.cpp", "smalllibc/purecall.cpp", "smalllibc/sprintf.cpp", "image.cpp", "render.cpp", "LaserTank.cpp" } +link_msvc("LaserTank") diff --git a/programs/games/LaserTank/trunk/customMode.h b/programs/games/LaserTank/trunk/customMode.h new file mode 100644 index 0000000000..b0bd10a536 --- /dev/null +++ b/programs/games/LaserTank/trunk/customMode.h @@ -0,0 +1,25 @@ +class CCustomMode // базовый класс +{ +protected: // спецификатор доступа к элементу value + +public: + CCustomMode() + { + + } + + ~CCustomMode() + { + + } + + void Process() + { + + } + + void Draw() + { + + } +}; \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/image.cpp b/programs/games/LaserTank/trunk/image.cpp new file mode 100644 index 0000000000..919f860182 --- /dev/null +++ b/programs/games/LaserTank/trunk/image.cpp @@ -0,0 +1,130 @@ +#include "kosSyst.h" +#include "render.h" +#include +#include "image.h" +//#include "mymath.h" + +CKosImage::CKosImage(CKosRender *render, RGBA *buffer, int width, int height) +{ + this->isColor = false; + this->width = width; + this->height = height; + this->buffer = buffer; + this->render = render; + this->mode = DRAW_ALPHA; + this->frame = 0; + this->frameWidth = 0; + this->frameHeight = 0; +} + +CKosImage::~CKosImage(void) +{ + +} + +void CKosImage::SetMode(int mode) +{ + this->mode = mode; +} + +void CKosImage::SetFrameSize(int width, int height) +{ + this->frameWidth = width; + this->frameHeight = height; +} + +void CKosImage::Draw(Point position, float angle, RGB color) +{ + this->isColor = true; + this->color = color; + this->Draw(position, angle); + this->isColor = false; +} + +int CKosImage::getPixel(int x, int y) +{ + return y * this->width + x; +} + +void CKosImage::Draw(Point position, float angle, int frame) +{ + this->frame = frame; + Draw(position, angle); +} + +void CKosImage::Draw(Point position, float angle) +{ + float alpha; + Point p, p1; + RGB pixel, newPixel; + RGBA addPixel; + int PixelID; + Point fix; + if (angle == 270) + fix = Point(0, -1); + else + if (angle == 180) + fix = Point(-1, -1); + else + if (angle == 90) + fix = Point(-1, 0); + else + fix = Point(0, 0); + + Point center = Point(this->width / 2, this->height / 2); + double a = -angle * (3.14 / 180); + + double SinRad = sin(a); + double CosRad = cos(a); + + for (int y = 0; y < 24; ++y) + for (int x = 0; x < 24; ++x) + { + p1 = Point(x, y) - center; + + p.X = roundInt(p1.X * CosRad - p1.Y * SinRad) + center.X; + p.Y = roundInt(p1.X * SinRad + p1.Y * CosRad) + center.Y; + + if (p.X >= 0 && p.X < this->width && p.Y >= 0 && p.Y < this->height) + { + p.Y += this->frame * this->frameHeight; + addPixel = this->buffer[this->getPixel(p.X, p.Y)]; + PixelID = this->render->getPixel(x + fix.X, y + fix.Y); + pixel = this->render->buffer[PixelID]; + + if (addPixel.a > 0) + { + if (this->isColor) + { + addPixel.r = this->color.r; + addPixel.g = this->color.g; + addPixel.b = this->color.b; + } + + alpha = (float)addPixel.a / 255.0f; + + if (this->mode = DRAW_ALPHA) + { + newPixel.r = di((double)(pixel.r * (1 - alpha) + addPixel.r * alpha)); + newPixel.g = di((double)(pixel.g * (1 - alpha) + addPixel.g * alpha)); + newPixel.b = di((double)(pixel.b * (1 - alpha) + addPixel.b * alpha)); + } + else + if (this->mode = DRAW_ALPHA_ADD) + { + newPixel.r = di(min(255, (double)(pixel.r * (1 - alpha) + addPixel.r * alpha))); + newPixel.g = di(min(255, (double)(pixel.g * (1 - alpha) + addPixel.g * alpha))); + newPixel.b = di(min(255, (double)(pixel.b * (1 - alpha) + addPixel.b * alpha))); + } + else + { + newPixel.r = addPixel.r; + newPixel.g = addPixel.g; + newPixel.b = addPixel.b; + } + + this->render->buffer[PixelID] = newPixel; + } + } + } +} diff --git a/programs/games/LaserTank/trunk/image.h b/programs/games/LaserTank/trunk/image.h new file mode 100644 index 0000000000..d634a775f1 --- /dev/null +++ b/programs/games/LaserTank/trunk/image.h @@ -0,0 +1,31 @@ +#include + +#define DRAW_NONE 0 +#define DRAW_ALPHA 1 +#define DRAW_ALPHA_ADD 2 + +class CKosImage +{ +private: + bool isColor; + RGB color; + int getPixel(int x, int y); + Byte mode; + int frame; + int frameWidth; + int frameHeight; +public: + CKosImage(CKosRender *render, RGBA *buffer, int width, int height); + ~CKosImage(void); + + void Draw(Point position, float angle, RGB color); + void Draw(Point position, float angle); + void Draw(Point position, float angle, int frame); + void SetMode(int mode); + void SetFrameSize(int width, int height); +protected: + CKosRender *render; + RGBA *buffer; + int width; + int height; +}; \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/levels.lvl b/programs/games/LaserTank/trunk/levels.lvl new file mode 100644 index 0000000000..dc7b894f67 Binary files /dev/null and b/programs/games/LaserTank/trunk/levels.lvl differ diff --git a/programs/games/LaserTank/trunk/memcmp.asm b/programs/games/LaserTank/trunk/memcmp.asm new file mode 100644 index 0000000000..b4fc2bed57 --- /dev/null +++ b/programs/games/LaserTank/trunk/memcmp.asm @@ -0,0 +1,15 @@ +format MS COFF +section '.text' code readable executable +public _memcmp +_memcmp: + push esi edi + mov esi, [esp+12] + mov edi, [esp+16] + mov ecx, [esp+20] + repz cmpsb + pop edi esi + setb ah + seta al + sub al, ah + movsx eax, al + ret diff --git a/programs/games/LaserTank/trunk/render.cpp b/programs/games/LaserTank/trunk/render.cpp new file mode 100644 index 0000000000..087710ee92 --- /dev/null +++ b/programs/games/LaserTank/trunk/render.cpp @@ -0,0 +1,34 @@ +#include "kosSyst.h" +#include "render.h" + +CKosRender::CKosRender(int width, int height) +{ + this->width = width; + this->height = height; + this->buffer = new RGB[width * height]; + for (int i = 0; i < width * height; i++) + this->buffer[i] = 0x000000; +} + +CKosRender::~CKosRender(void) +{ + //delete this->buffer; +} + +void CKosRender::Draw(Point position) +{ + kos_PutImage((RGB*)this->buffer, this->width, this->height, position.X, position.Y); +} + +void CKosRender::RenderImg(RGB *img, Point position, int width, int height) +{ + for (int i = 0; i < width * height; i++) + this->buffer[i] = img[i]; + // if ( ) + // this->buffer[getPixel(x, y)] +} + +int CKosRender::getPixel(int x, int y) +{ + return y * this->width + x; +} diff --git a/programs/games/LaserTank/trunk/render.h b/programs/games/LaserTank/trunk/render.h new file mode 100644 index 0000000000..235e35807e --- /dev/null +++ b/programs/games/LaserTank/trunk/render.h @@ -0,0 +1,15 @@ + +class CKosRender +{ +public: + RGB *buffer; + int width; + int height; + CKosRender(int width, int height); + ~CKosRender(void); + + void Draw(Point position); + void RenderImg(RGB *img, Point position, int width, int height); + int getPixel(int x, int y); +// void DrawImage(CKosImage *img, int x, int y, int angle); +}; \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/smalllibc/doexe2.asm b/programs/games/LaserTank/trunk/smalllibc/doexe2.asm new file mode 100644 index 0000000000..eaebd8aaf8 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/doexe2.asm @@ -0,0 +1,68 @@ +filename equ '%EXENAME%' + +virtual at 0 +file filename:3Ch,4 +load pehea dword from 0 +file filename:pehea,0F8h+28h*3 +load NumberOfSections word from 4+6 +load SizeOfOptionalHeader word from 4+14h +if NumberOfSections<>3 +error Expected three sections, .text, .bss and .reloc +end if +if SizeOfOptionalHeader<>0E0h +error Nonstandard PE header +end if +load RelocsRVA dword from 4+0A0h +load RelocsSize dword from 4+0A4h +load ImageBase dword from 4+34h +load TextRVA dword from 4+0F8h+0Ch +load TextSize dword from 4+0F8h+8 +load TextOffs dword from 4+0F8h+14h +load BSSSize dword from 4+0F8h+28h+10h +load RelocRVA dword from 4+0F8h+28h*2+0Ch +load RelocOffs dword from 4+0F8h+28h*2+14h +if BSSSize +error Second section expected to be .bss +end if +if RelocRVA<>RelocsRVA +error Third section expected to be .reloc +end if +;file 'test.exe':pehea+0F8h,28h +;load physofs dword from 4+14h +;load mem dword from 4+8 +;file 'test.exe':physofs+16,4 +;load sz dword from $-4 +end virtual + +file filename:TextOffs,TextSize + +while RelocsSize>8 +virtual at 0 +file filename:RelocOffs,8 +load CurRelocPage dword from 0 +load CurRelocChunkSize dword from 4 +end virtual +RelocsSize=RelocsSize-CurRelocChunkSize +CurRelocChunkSize = CurRelocChunkSize-8 +RelocOffs=RelocOffs+8 +while CurRelocChunkSize +virtual at 0 +file filename:RelocOffs,2 +RelocOffs=RelocOffs+2 +CurRelocChunkSize=CurRelocChunkSize-2 +load s word from 0 +end virtual +CurRelocType = s shr 12 +RelocItem = CurRelocPage + (s and 0xFFF) +if CurRelocType=0 +else if CurRelocType=3 +load z dword from RelocItem-TextRVA +store dword z-(TextRVA+ImageBase) at RelocItem-TextRVA +else +error Unexpected relocation type +end if +end while +end while + +store dword TextSize at 10h +store dword RelocRVA-TextRVA at 14h diff --git a/programs/games/LaserTank/trunk/smalllibc/func.cpp b/programs/games/LaserTank/trunk/smalllibc/func.cpp new file mode 100644 index 0000000000..df6a8d5a4d --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/func.cpp @@ -0,0 +1,550 @@ + + +#include "func.h" + +int convert_error = 0; +int SysColor = 0; +char debuf[50] = ""; + + +// почему-то не было в стандартной библиотеке +void kos_DrawLine( Word x1, Word y1, Word x2, Word y2, Dword colour, Dword invert ) +{ + Dword arg1, arg2, arg3; + + // + arg1 = ( x1 << 16 ) | x2; + arg2 = ( y1 << 16 ) | y2; + arg3 = (invert)?0x01000000:colour; + // + __asm{ + mov eax, 38 + mov ebx, arg1 + mov ecx, arg2 + mov edx, arg3 + int 0x40 + } +} + +// похищено из библиотеки к C-- +void DrawRegion(Dword x,Dword y,Dword width,Dword height,Dword color1) +{ + kos_DrawBar(x,y,width,1,color1); //полоса гор сверху + kos_DrawBar(x,y+height,width,1,color1); //полоса гор снизу + kos_DrawBar(x,y,1,height,color1); //полоса верт слева + kos_DrawBar(x+width,y,1,height+1,color1); //полоса верт справа +} + + +// да, это баян +int atoi(const char* string) +{ + int res=0; + int sign=0; + const char* ptr; + for (ptr=string; *ptr && *ptr<=' ';ptr++); + if (*ptr=='-') {sign=1;++ptr;} + while (*ptr >= '0' && *ptr <= '9') + { + res = res*10 + *ptr++ - '0'; + } + if (sign) res = -res; + return res; +} + +/*int abs(int n) +{ + return (n<0)?-n:n; +}*/ + + + + + +double fabs(double x) +{ + __asm fld x + __asm fabs +} +#define M_PI 3.14159265358979323846 +double cos(double x) +{ + __asm fld x + __asm fcos +} +double sin(double x) +{ + __asm fld x + __asm fsin +} + +bool isalpha(char c) +{ + return (c==' ' || c=='\n' || c=='\t' || c=='\r'); +} + +// эта функция - велосипед. но проще было написать чем найти. +double convert(char *s, int *len) +{ + + int i; + + + double sign,res, tail, div; + + convert_error = 0; + + res = 0.0; + + i=0; + while (s[i] && isalpha(s[i])) i++; + if (len) *len=i; + if (s[i] == '\0') + { + convert_error = ERROR_END; + return 0.0; + } + + sign=1.0; + if (s[i] == '-') + { + sign=-1.0; + i++; + } + while (s[i] && s[i] >= '0' && s[i] <= '9') + { + res *= 10.0; + res += id(s[i] - '0'); + i++; + } + if (len) *len=i; + if (!s[i] || isalpha(s[i])) + return sign*res; + if (s[i] != '.' && s[i] != ',') + { + convert_error = ERROR; + return 0; + } + i++; + if (len) *len=i; + if (!s[i]) + return sign*res; + + div = 1.0; + tail = 0.0; + while (s[i] && s[i] >= '0' && s[i] <= '9') + { + tail *= 10.0; + tail += id(s[i] - '0'); + div *= 10.0; + i++; + } + res += tail/div; + if (len) *len=i; + return sign*res; +} + +/* +#define PREC 2 + +double double_tab[]={1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15}; + +// это sprintf, умеющий форматировать _только_ вещественные числа (double) %f +void format( char *Str, int len, char* Format, ... ) +{ + int i, fmtlinesize, j, k, flag; + char c; + va_list arglist; + // + va_start(arglist, Format); + + // + fmtlinesize = strlen( Format ); + // + if( fmtlinesize == 0 ) return; + + for (i = 0; i < len; i++) + Str[i] = 0; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = Format[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = Format[i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // auaia aauanoaaiiiai ?enea + case 'f': + // ii?aaaeeou ?enei oeo? ai oi?ee + double val, w; + int p; + val = va_arg(arglist, double); + if (val < 0.0) + { + Str[j++] = '-'; + val = -val; + } + for (k = 0; k < 15; k++) + if (val < double_tab[k]) + break; + + if (val < 1.0) + { + Str[j++] = '0'; + } + + for (p = 1; p < k + 1; p++) + { + Str[j++] = '0' + di(val / double_tab[k - p] - 0.499) % 10; + } + Str[j++] = '.'; + w = 0.1; + for (p = 0; p < 2; p++) + { + val-=floor(val); + Str[j++] = '0' + di(val / w - 0.499) % 10; + w /= 10.0; + } + + // + default: + break; + } + } + // + Str[j] = 0; +} + +void *memcpy(void *dst, const void *src, unsigned size) +{ + while (size--) + *((char*)dst+size) = *((char*)src+size); + return dst; +} +*/ +int strcmp(const char *s1, const char *s2) +{ + int i; + + if (s1 == NULL) + if (s2 == NULL) + return 0; + else + return 1; + else + if (s2 == NULL) + return 1; + + for (i = 0;;i++) + { + if (s1[i] == '\0') + if (s2[i] == '\0') + return 0; + else + return 1; + else + if (s2[i] == '\0') + return 1; + else + { + if (s1[i] != s2[i]) + return 1; + } + } + return 0; +} + +kol_struct_import* kol_cofflib_load(char *name) +{ +//asm ("int $0x40"::"a"(68), "b"(19), "c"(name)); + __asm + { + mov eax, 68 + mov ebx, 19 + mov ecx, name + int 0x40 + } +} + + +void* kol_cofflib_procload (kol_struct_import *imp, char *name) +{ + +int i; +for (i=0;;i++) + if ( NULL == ((imp+i) -> name)) + break; + else + if ( 0 == strcmp(name, (imp+i)->name) ) + return (imp+i)->data; +return NULL; + +} + + +unsigned kol_cofflib_procnum (kol_struct_import *imp) +{ + +unsigned i, n; + +for (i=n=0;;i++) + if ( NULL == ((imp+i) -> name)) + break; + else + n++; + +return n; + +} + + +void kol_cofflib_procname (kol_struct_import *imp, char *name, unsigned n) +{ + +unsigned i; +*name = 0; + +for (i=0;;i++) + if ( NULL == ((imp+i) -> name)) + break; + else + if ( i == n ) + { + strcpy(name, ((imp+i)->name)); + break; + } + +} + + + +/* +end of system part +*/ + + +// поскольку я портировал с древнего доса... +void line( int x1, int y1, int x2, int y2) +{ + kos_DrawLine(x1,y1,x2,y2,SysColor,0); +} + +void outtextxy( int x, int y, char *s, int len) +{ + kos_WriteTextToWindow(x,y,0,SysColor,s,len); +} + +double textwidth( char *s, int len) +{ + int i; + for (i = 0; i < len; i++) + if (s[i] == 0) + break; + return id(i * 6); +} + +double textheight( char *s, int len) +{ + return 8.0; +} + +void setcolor( DWORD color) +{ + SysColor = color; +} + +void rectangle( int x1, int y1, int x2, int y2) +{ + kos_DrawBar(x1,y1,x2-x1,y2-y1,SysColor); +} + + + +Dword kos_GetSkinHeight() +{ + __asm{ + mov eax, 48 + mov ebx, 4 + int 0x40 + } +} + +Dword kos_GetSpecialKeyState() +{ + __asm{ + mov eax, 66 + mov ebx, 3 + int 0x40 + } +} + + + +Dword kos_GetSlotByPID(Dword PID) +{ + __asm + { + push ebx + push ecx + mov eax, 18 + mov ebx, 21 + mov ecx, PID + int 0x40 + pop ecx + pop ebx + } +} + + +Dword kos_GetActiveSlot() +{ + __asm + { + push ebx + mov eax, 18 + mov ebx, 7 + int 0x40 + pop ebx + } +} + + + +void kos_GetScrollInfo(int &vert, int &hor) +{ + short v, h; + __asm + { + mov eax, 37 + mov ebx, 7 + int 0x40 + mov ebx, eax + and eax, 0xffff + mov v, ax + shr ebx, 16 + mov h, bx + } + vert = v; + hor = h; +} + + +// получение информации о состоянии "мыши" функция 37/1 +void kos_GetMouseStateWnd( Dword & buttons, int & cursorX, int & cursorY ) +{ + Dword mB; + Word curX; + Word curY; + sProcessInfo sPI; + + // + __asm{ + mov eax, 37 + mov ebx, 1 + int 0x40 + mov curY, ax + shr eax, 16 + mov curX, ax + mov eax, 37 + mov ebx, 2 + int 0x40 + mov mB, eax + } + // + kos_ProcessInfo( &sPI ); + // + buttons = mB; + cursorX = curX - sPI.processInfo.x_start; + cursorY = curY - sPI.processInfo.y_start; +} + +double atof(char *s) +{ + return convert(s, NULL); +} + + +int di(double x) +{ + int a; + __asm fld x + __asm fistp a + return a; +} + +double id(int x) +{ + double a; + __asm fild x + __asm fstp a + return a; +} + +double sqrtd(double x) +{ + __asm fld x + __asm fsqrt +} + +double arccos(double x) +{ + __asm fld x + __asm fld st(0) + __asm fmul st, st(1) + __asm fld1 + __asm fsubrp st(1), st(0) + __asm fsqrt + __asm fxch st(1) + __asm fpatan +} + +double atan(double Rad) +{ + _asm{ + fld dword ptr[Rad] + fld1 + fpatan + fstp dword ptr[Rad] + } + return Rad; +} + +double atan2(double x, double y) +{ + return abs(atan(y / x) /* (180 / M_PI)*/); +} + +int roundInt(double x) +{ + int i; + static const float round_to_nearest = 0.5f; + __asm + { + fld x + fadd st, st(0) + fadd round_to_nearest + fistp i + sar i, 1 + } + return i; +} \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/smalllibc/func.h b/programs/games/LaserTank/trunk/smalllibc/func.h new file mode 100644 index 0000000000..ed83d4536f --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/func.h @@ -0,0 +1,135 @@ + +#pragma once + +#include "kosSyst.h" +#include "kosFile.h" +#include "MCSMEMM.H" + +#include + + +#define min(a,b) (((a)<(b))?(a):(b)) +#define max(a,b) (((a)>(b))?(a):(b)) + + +#define ERROR -1 +#define ERROR_END -2 + +extern int convert_error; + +typedef int HDC; +typedef int DWORD; + +extern int SysColor; +extern char debuf[50]; + +typedef double (*function_t)(double); + +typedef struct +{ + double x, y; +} TCoord; + +struct kosBDVK +{ + Dword attrib; + Dword name_type; + Dword create_time; + Dword create_date; + Dword access_time; + Dword access_date; + Dword modify_time; + Dword modify_date; + Dword size_low; + Dword size_high; +}; + +Dword kos_GetSlotByPID(Dword PID); +Dword kos_GetActiveSlot(); +Dword kos_GetSkinHeight(); +Dword kos_GetSpecialKeyState(); +void kos_GetMouseStateWnd( Dword & buttons, int & cursorX, int & cursorY ); +void kos_DrawLine( Word x1, Word y1, Word x2, Word y2, Dword colour, Dword invert); +void DrawRegion(Dword x,Dword y,Dword width,Dword height,Dword color1); +int atoi(const char* string); +void kos_GetScrollInfo(int &vert, int &hor); + + +Dword kos_GetSlotByPID(Dword PID); +Dword kos_GetActiveSlot(); +Dword kos_GetSkinHeight(); +Dword kos_GetSpecialKeyState(); + + +double fabs(double x); +double cos(double x); +double sin(double x); +bool isalpha(char c); +double convert(char *s, int *len=NULL); +void format( char *Str, int len, char* Format, ... ); + +void line( int x1, int y1, int x2, int y2); + +void outtextxy( int x, int y, char *s, int len); +void settextstyle( int a1, int a2, int a3); + + +double textwidth( char *s, int len); +double textheight( char *s, int len); +void setcolor( DWORD color); +void unsetcolor(HDC hdc); +void rectangle( int x1, int y1, int x2, int y2); + +typedef struct +{ +unsigned p00 ; +unsigned p04 ; +unsigned p08 ; +unsigned p12 ; +unsigned p16 ; +char p20 ; +char *p21 ; +} kol_struct70 ; + + +typedef struct +{ +unsigned p00 ; +char p04 ; +char p05[3] ; +unsigned p08 ; +unsigned p12 ; +unsigned p16 ; +unsigned p20 ; +unsigned p24 ; +unsigned p28 ; +unsigned p32[2] ; +unsigned p40 ; +} kol_struct_BDVK ; + +typedef struct +{ +char *name ; +void *data ; +} kol_struct_import ; + + + +kol_struct_import* kol_cofflib_load(char *name); +void* kol_cofflib_procload (kol_struct_import *imp, char *name); +unsigned kol_cofflib_procnum (kol_struct_import *imp); +void kol_cofflib_procname (kol_struct_import *imp, char *name, unsigned n); +int strcmp(const char* string1, const char* string2); + +char *ftoa(double d); +double atof(char *s); + + +int di(double x); +double id(int x); + +double atan(double x); +double arccos(double x); +double sqrtd(double x); +double atan2(double x, double y); +int roundInt(double x); diff --git a/programs/games/LaserTank/trunk/smalllibc/init.asm b/programs/games/LaserTank/trunk/smalllibc/init.asm new file mode 100644 index 0000000000..c18d337b1e --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/init.asm @@ -0,0 +1,31 @@ +format MS COFF + +StackSize = 16384 + +; must be alphabetically first in the image +section '.1seg' data readable writable +extrn _crtStartUp ; real entry point +extrn _kosCmdLine +extrn _kosExePath +extrn _exeStack +public fakeEntry + +kos_header: + db 'MENUET01' ; header + dd 1 ; headerver + dd _crtStartUp ; entry + dd 0 ; i_end, filled by doexe2.asm + dd 0 ; memsize, filled by doexe2.asm + dd _exeStack + StackSize ; stack + dd _kosCmdLine ; params + dd _kosExePath ; icon +fakeEntry: ; only for linker, to force including this obj file + ; real entry is crtStartUp + +; initializers +section '.CRT$XCA' data readable writable +public ___xc_a +___xc_a: +section '.CRT$XCZ' data readable writable +public ___xc_z +___xc_z: diff --git a/programs/games/LaserTank/trunk/smalllibc/init.obj b/programs/games/LaserTank/trunk/smalllibc/init.obj new file mode 100644 index 0000000000..a1d6776a06 Binary files /dev/null and b/programs/games/LaserTank/trunk/smalllibc/init.obj differ diff --git a/programs/games/LaserTank/trunk/smalllibc/kosFile.cpp b/programs/games/LaserTank/trunk/smalllibc/kosFile.cpp new file mode 100644 index 0000000000..8cc61efd90 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/kosFile.cpp @@ -0,0 +1,137 @@ +#include "kosSyst.h" +#include "kosFile.h" +//#include "string.h" + +CKosFile::CKosFile(char *fileName) +{ + // + rtlDebugOutString(fileName); + this->fileInfo.bufferPtr = new Byte[FILE_BUFFER_SIZE]; + // + this->filePointer = 0; + this->bufferPointer = 0; + this->validBuffer = false; + // + strcpy( this->fileInfo.fileURL, fileName ); +} + + +CKosFile::~CKosFile(void) +{ + // + delete this->fileInfo.bufferPtr; +} + +void CKosFile::ValidateBuffer() +{ + // + if ( this->validBuffer ) + { + // + if ( this->filePointer < this->bufferPointer + || this->filePointer >= (this->bufferPointer + FILE_BUFFER_SIZE) ) + { + // + this->validBuffer = false; + } + } +} + + +void CKosFile::UpdateBuffer(void) +{ + // + if ( ! this->validBuffer ) + { + // + this->fileInfo.OffsetLow = this->filePointer / OS_BLOCK_SIZE; + this->fileInfo.OffsetHigh = 0; + // + this->bufferPointer = this->fileInfo.OffsetLow * OS_BLOCK_SIZE; + // + this->fileInfo.dataCount = FILE_BUFFER_BLOCKS; + // + this->fileInfo.rwMode = 0; + // + Dword rr = kos_FileSystemAccess( &(this->fileInfo) ); + this->validBuffer = ( rr == 0 ); + } +} + + +int CKosFile::Seek(int seekFrom, int seekStep) +{ + // + switch ( seekFrom ) + { + // + case SEEK_SET: + // + this->filePointer = seekStep; + break; + // + case SEEK_CUR: + // + this->filePointer += seekStep; + break; + } + // + this->ValidateBuffer(); + // + return this->filePointer; +} + + +int CKosFile::Read(Byte *targetPtr, int readCount) +{ + int bufferLeast, result; + + // + result = 0; + // + do + { + // + this->UpdateBuffer(); + // + if ( ! this->validBuffer ) return result; + // + bufferLeast = FILE_BUFFER_SIZE - (this->filePointer - this->bufferPointer); + // + if ( bufferLeast > readCount ) bufferLeast = readCount; + // + if ( bufferLeast ) + { + // + memcpy( + targetPtr, + this->fileInfo.bufferPtr + (this->filePointer - this->bufferPointer), + bufferLeast + ); + // + targetPtr += bufferLeast; + readCount -= bufferLeast; + this->filePointer += bufferLeast; + // + result += bufferLeast; + } + // + this->ValidateBuffer(); + } + while ( readCount > 0 ); + // + return result; +} + + +int CKosFile::Write(Byte *sourcePtr, int writeCount) +{ + return 0; +} + +void CKosFile::LoadTex(Byte *targetPtr, Byte Size, int width, int height) +{ + this->Read(targetPtr, width * height * Size); +} + + diff --git a/programs/games/LaserTank/trunk/smalllibc/kosFile.h b/programs/games/LaserTank/trunk/smalllibc/kosFile.h new file mode 100644 index 0000000000..f155e2a1d0 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/kosFile.h @@ -0,0 +1,27 @@ +#pragma once + +#define SEEK_SET 0 +#define SEEK_CUR 1 + +#define FILE_BUFFER_SIZE 512 +#define OS_BLOCK_SIZE 1 +#define FILE_BUFFER_BLOCKS (FILE_BUFFER_SIZE / OS_BLOCK_SIZE) + + +class CKosFile +{ +public: + CKosFile(char *fileName); + ~CKosFile(void); + int Read(Byte *targetPtr, int readCount); + int Write(Byte *sourcePtr, int writeCount); + int Seek(int seekFrom, int seekStep); + void LoadTex(Byte *targetPtr, Byte Size, int width, int height); +protected: + int filePointer; + int bufferPointer; + bool validBuffer; + kosFileInfo fileInfo; + void ValidateBuffer(void); + void UpdateBuffer(void); +}; diff --git a/programs/games/LaserTank/trunk/smalllibc/kosSyst.cpp b/programs/games/LaserTank/trunk/smalllibc/kosSyst.cpp new file mode 100644 index 0000000000..d81634ef92 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/kosSyst.cpp @@ -0,0 +1,708 @@ +#include "kosSyst.h" +#include "func.h" +#include + +char kosCmdLine[257]; +char kosExePath[1024]; +extern "C" char exeStack[]; +char exeStack[16384]; + +#define atexitBufferSize 32 + +#ifndef SMALLLIBC_NO_ATEXIT +// +void (__cdecl *atExitList[atexitBufferSize])(); +int atExitFnNum = 0; +// +int __cdecl atexit( void (__cdecl *func )( void )) +{ + // + if ( atExitFnNum < atexitBufferSize ) + { + // + atExitList[atExitFnNum++] = func; + return 0; + } + else + { + return 1; + } +} +#endif + +float Point::Lingrh() +{ + return sqrtd(this->X * this->X + this->Y * this->Y); +} + +float Point::Angle() +{ + return atan2(this->X, this->Y); +} + +// +Dword RandomSeed = 0; +// +void rtlSrand( Dword seed ) +{ + RandomSeed = seed; +} +// +Dword rtlRand( void ) +{ + //маска 0x80000776 + + Dword dwi, i; + + for ( i = 0; i < 32; i++ ) + { + + dwi = RandomSeed & 0x80000776; + + __asm{ + mov eax, dwi + mov edx, eax + bswap eax + xor eax, edx + xor al, ah + setpo al + movzx eax, al + mov dwi, eax + } + + RandomSeed = ( RandomSeed << 1 ) | ( dwi & 1 ); + } + + return RandomSeed; +} + +void* __cdecl memcpy( void *dst, const void *src, size_t bytesCount ) +{ + __asm{ + mov edi, dst + mov eax, dst + mov esi, src + mov ecx, bytesCount + rep movsb + } +} + +// +void memset( Byte *dst, Byte filler, Dword count ) +{ + // + __asm{ + mov edi, dst + mov al, filler + mov ecx, count + rep stosb + } +} + + +// +Dword rtlInterlockedExchange( Dword *target, Dword value ) +{ +// Dword result; + + // + __asm{ + mov eax, value + mov ebx, target + xchg eax, [ebx] +// mov result, eax + } + // +// return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// копирование строки +// + +char * __cdecl strcpy( char *target, const char *source ) +{ + char *result = target; + + while( target[0] = source[0] ) + { + target++; + source++; + } + + return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// реверсивный поиск символа +// + +char * __cdecl strrchr( const char * string, int c ) +{ + char *cPtr; + + // + for ( cPtr = (char *)string + strlen( string ); cPtr >= string; cPtr-- ) + { + // + if ( *cPtr == c ) return cPtr; + } + // + return NULL; +} + + +////////////////////////////////////////////////////////////////////// +// +// определение длины строки +// + +int __cdecl strlen( const char *line ) +{ + int i; + + for( i=0; line[i] != 0; i++ ); + return i; +} + + + +////////////////////////////////////////////////////////////////////// +// +// перевод шестнадцатиричного числа в символ +// + +unsigned int num2hex( unsigned int num ) +{ + if( num < 10 ) + return num + '0'; + return num - 10 + 'A'; +} + + +inline void __declspec(noreturn) kos_sysfuncm1(void) +{ + __asm or eax, -1 + __asm int 0x40 +} + +// функция -1 завершения процесса +void kos_ExitApp() +{ +#ifndef SMALLLIBC_NO_ATEXIT + int i; + + // + for ( i = atExitFnNum - 1; i >= 0; i-- ) + { + // + atExitList[i](); + } +#endif + // + kos_sysfuncm1(); +} + +static void __declspec(noinline) __fastcall kos_sysfunc0(Dword _ecx, Dword _edx, Dword _ebx, Dword _esi, Dword _edi) +{ + __asm xor eax, eax + __asm mov ebx, _ebx + __asm mov esi, _esi + __asm mov edi, _edi + __asm int 0x40 +} + +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, + Dword mainAreaColour, + Byte headerType, + Dword headerColour, + Dword borderColour + ) +{ + Dword arg1, arg2, arg3, arg4; + + // + arg1 = ( x << 16 ) + sizeX; + arg2 = ( y << 16 ) + sizeY; + arg3 = ( mainAreaType << 24 ) | mainAreaColour; + arg4 = ( headerType << 24 ) | headerColour; + // + kos_sysfunc0(arg2, arg3, arg1, arg4, borderColour); +} + + +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ) +{ + // + __asm{ + push 1 + pop eax + mov ebx, x + mov ecx, y + mov edx, colour + int 0x40 + } +} + +inline Dword kos_sysfunc2(void) +{ + __asm push 2 + __asm pop eax + __asm int 0x40 +} + +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ) +{ + Dword result = kos_sysfunc2(); + // + keyCode = result >> 8; + // + return ( result & 0xFF ) == 0; +} + + +// функция 3 получить время +Dword kos_GetSystemClock() +{ +// Dword result; + + // + __asm{ + push 3 + pop eax + int 0x40 +// mov result, eax + } + // +// return result; +} + +static void __declspec(noinline) __fastcall kos_sysfunc4(Dword _ecx, const char* _edx, Dword _ebx, Dword _esi) +{ + __asm push 4 + __asm pop eax + __asm mov ebx, [_ebx] + __asm mov esi, [_esi] + __asm int 0x40 +} + +// функция 4 +void kos_WriteTextToWindow( + Word x, + Word y, + Byte fontType, + Dword textColour, + const char *textPtr, + Dword textLen + ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | y; + arg2 = ( fontType << 24 ) | textColour; + // + kos_sysfunc4(arg2, textPtr, arg1, textLen); +} + + +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ) +{ + // + __asm{ + push 5 + pop eax + mov ebx, value + int 0x40 + } +} + + +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ) +{ + Dword arg1, arg2; + + // + arg1 = ( sizeX << 16 ) | sizeY; + arg2 = ( x << 16 ) | y; + // + __asm{ + push 7 + pop eax + mov ebx, imagePtr + mov ecx, arg1 + mov edx, arg2 + int 0x40 + } +} + + + +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + push 8 + pop eax + mov ebx, arg1 + mov ecx, arg2 + mov edx, buttonID + mov esi, colour + int 0x40 + } +} + + +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID ) +{ +// Dword result; + + // + __asm{ + push 9 + pop eax + mov ebx, targetPtr + mov ecx, processID + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 10 +Dword kos_WaitForEvent() +{ +// Dword result; + + __asm{ + push 10 + pop eax + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 11 +Dword kos_CheckForEvent() +{ +// Dword result; + + __asm{ + push 11 + pop eax + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 12 +void kos_WindowRedrawStatus( Dword status ) +{ + __asm{ + push 12 + pop eax + mov ebx, status + int 0x40 + } +} + + +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + push 13 + pop eax + mov ebx, arg1 + mov ecx, arg2 + mov edx, colour + int 0x40 + } +} + + +// функция 17 +bool kos_GetButtonID( Dword &buttonID ) +{ + Dword result; + + // + __asm{ + push 17 + pop eax + int 0x40 + mov result, eax + } + // + buttonID = result >> 8; + // + return (result & 0xFF) == 0; +} + + +// функция 23 +Dword kos_WaitForEventTimeout( Dword timeOut ) +{ +// Dword result; + + __asm{ + push 23 + pop eax + mov ebx, timeOut + int 0x40 +// mov result, eax + } + +// return result; +} + + +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ) +{ + Dword mB; + Word curX; + Word curY; + sProcessInfo sPI; + + // + __asm{ + push 37 + pop eax + xor ebx, ebx + int 0x40 + mov curY, ax + shr eax, 16 + mov curX, ax + push 37 + pop eax + push 2 + pop ebx + int 0x40 + mov mB, eax + } + // + kos_ProcessInfo( &sPI ); + // + buttons = mB; + cursorX = curX - sPI.processInfo.x_start; + cursorY = curY - sPI.processInfo.y_start; +} + + +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ) +{ + // + __asm{ + push 40 + pop eax + mov ebx, mask + int 0x40 + } +} + + +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase, + bool valueIsPointer + ) +{ + Dword arg1, arg2; + + // + arg1 = ( valueIsPointer ? 1 : 0 ) | + ( ((Byte)nBase) << 8 ) | + ( ( digitsNum & 0x1F ) << 16 ); + arg2 = ( x << 16 ) | y; + // + __asm{ + push 47 + pop eax + mov ebx, arg1 + mov ecx, value + mov edx, arg2 + mov esi, colour + int 0x40 + } +} + + +// функция 70 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ) +{ +// Dword result; + + // + __asm{ + mov eax, 70 + mov ebx, fileInfo + int 0x40 + // push 70 +// pop eax + // mov ebx, fileInfo + // int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 63 вывод символя в окно отладки +void kos_DebugOutChar( char ccc ) +{ + // + __asm{ + push 63 + pop eax + push 1 + pop ebx + mov cl, ccc + int 0x40 + } +} + + +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ) +{ + // + __asm{ + push 66 + pop eax + push 1 + pop ebx + mov ecx, mode + int 0x40 + } +} + + +// вывод строки в окно отладки +void rtlDebugOutString( char *str ) +{ + // + for ( ; str[0] != 0; str++ ) + { + kos_DebugOutChar( str[0] ); + } + // + kos_DebugOutChar( 13 ); + kos_DebugOutChar( 10 ); +} + + +// функция 64 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ) +{ + Dword result; + + // + __asm{ + push 64 + pop eax + push 1 + pop ebx + mov ecx, targetSize + int 0x40 + mov result, eax + } + // + return result == 0; +} + + +// функция 67 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ) +{ + // + __asm{ + push 67 + pop eax + mov ebx, x + mov ecx, y + mov edx, sizeX + mov esi, sizeY + int 0x40 + } +} + +void kos_InitHeap() +{ + __asm{ + push 68 + pop eax + push 11 + pop ebx + int 0x40 + } +} + + + +// вызов статических инициализаторов +typedef void (__cdecl *_PVFV)(void); +extern "C" _PVFV __xc_a[]; +extern "C" _PVFV __xc_z[]; +#pragma comment(linker, "/merge:.CRT=.rdata") +// +void __cdecl crtStartUp() +{ +#ifndef SMALLLIBC_NO_INIT + // вызываем инициализаторы по списку + for ( _PVFV *pbegin = __xc_a; pbegin < __xc_z; pbegin++ ) + { + // + (**pbegin)(); + } +#endif + // инициализируем генератор случайных чисел + // если надо для приложения, делать это в kos_Main() + //rtlSrand( kos_GetSystemClock() ); + // вызов главной функции приложения + kos_Main(); + // выход + kos_ExitApp(); +} + + diff --git a/programs/games/LaserTank/trunk/smalllibc/kosSyst.h b/programs/games/LaserTank/trunk/smalllibc/kosSyst.h new file mode 100644 index 0000000000..01a6a5e098 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/kosSyst.h @@ -0,0 +1,300 @@ +#pragma once + +typedef unsigned __int32 Dword; +typedef unsigned __int16 Word; +typedef unsigned __int8 Byte; +//typedef unsigned __int32 size_t; + +extern "C" char kosCmdLine[]; // command line initialized by OS +extern "C" char kosExePath[]; // path to binary initialized by OS + +#define NULL 0 + +#define MAX_PATH 256 + +#define FO_READ 0 +#define FO_WRITE 2 + +#define EM_WINDOW_REDRAW 1 +#define EM_KEY_PRESS 2 +#define EM_BUTTON_CLICK 4 +#define EM_APP_CLOSE 8 +#define EM_DRAW_BACKGROUND 16 +#define EM_MOUSE_EVENT 32 +#define EM_IPC 64 +#define EM_NETWORK 256 + +#define KM_CHARS 0 +#define KM_SCANS 1 + +#define WRS_BEGIN 1 +#define WRS_END 2 + +#define PROCESS_ID_SELF -1 + +#define abs(a) (a<0?0-a:a) + +extern "C" double __cdecl acos(double x); +extern "C" double __cdecl asin(double x); +extern "C" double __cdecl floor(double x); +extern "C" double __cdecl round(double x); +#pragma function(acos,asin) +#if _MSC_VER > 1200 +#pragma function(floor) +#endif + + +struct kosFileInfo +{ + Dword rwMode; + Dword OffsetLow; + Dword OffsetHigh; + Dword dataCount; + Byte *bufferPtr; + char fileURL[MAX_PATH]; +}; + +struct Point +{ + int X; + int Y; + + Point() {}; + Point(int x, int y) + { + this->X = x; + this->Y = y; + }; + bool operator != (Point &a){ return this->X != a.X || this->Y != a.Y; }; + bool operator == (Point &a){ return this->X == a.X && this->Y == a.Y; }; + Point operator + (Point &a){ return Point(this->X + a.X, this->Y + a.Y); } + Point operator + (int a){ return Point(this->X + a, this->Y + a); } + Point operator - (Point &a){ return Point(this->X - a.X, this->Y - a.Y); } + Point operator - (int a){ return Point(this->X - a, this->Y - a); } + Point operator * (Point &a){ return Point(this->X * a.X, this->Y * a.Y); } + Point operator * (int a){ return Point(this->X * a, this->Y * a); } + Point operator / (Point &a){ return Point(this->X / a.X, this->Y / a.Y); } + Point operator / (int a){ return Point(this->X / a, this->Y / a); } + + float Lingrh(); + float Angle(); +}; + +struct Rect +{ + int X; + int Y; + int Width; + int Height; + Rect() {} + Rect(int X, int Y, int Width, int Height) + { + this->X = X; + this->Y = Y; + this->Width = Width; + this->Height = Height; + } +}; + +struct RGBA +{ + Byte b; + Byte g; + Byte r; + Byte a; + + RGBA() {}; + + RGBA(Dword value) + { + a = (Byte)(value >> 24); + r = (Byte)(value >> 16); + g = (Byte)(value >> 8); + b = (Byte)value; + }; + // + bool operator != (RGBA &another) + { + return this->b != another.b || this->g != another.g || this->r != another.r || this->a != another.a; + }; + // + bool operator == (RGBA &another) + { + return this->b == another.b && this->g == another.g && this->r == another.r && this->a == another.a; + }; +}; + + +struct RGB +{ + Byte b; + Byte g; + Byte r; + // + RGB() {}; + // + RGB( Dword value ) + { + r = (Byte)(value >> 16); + g = (Byte)(value >> 8); + b = (Byte)value; + }; + // + bool operator != ( RGB &another ) + { + return this->b != another.b || this->g != another.g || this->r != another.r; + }; + // + bool operator == ( RGB &another ) + { + return this->b == another.b && this->g == another.g && this->r == another.r; + }; +}; + +struct Player +{ + Point vector; + Point position; + float angle; + + Player() {} + Player(Point position) + { + this->vector = Point(0, -1); + this->position = position; + this->angle = 270; + }; +}; + +#pragma pack(push, 1) +union sProcessInfo +{ + Byte rawData[1024]; + struct + { + Dword cpu_usage; + Word window_stack_position; + Word window_stack_value; + Word reserved1; + char process_name[12]; + Dword memory_start; + Dword used_memory; + Dword PID; + Dword x_start; + Dword y_start; + Dword x_size; + Dword y_size; + Word slot_state; + } processInfo; +}; +#pragma pack(pop) + +// +extern "C" void __cdecl crtStartUp(); +// +int __cdecl _purecall(); +// +int __cdecl atexit( void (__cdecl *func )( void )); +// +void rtlSrand( Dword seed ); +Dword rtlRand( void ); +// +char * __cdecl strcpy( char *target, const char *source ); +int __cdecl strlen( const char *line ); +char * __cdecl strrchr( const char * string, int c ); + +#if _MSC_VER < 1400 +extern "C" void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ); +extern "C" void memset( Byte *dst, Byte filler, Dword count ); +//#pragma intrinsic(memcpy,memset) +#else +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ); +void memset( Byte *dst, Byte filler, Dword count ); +#endif + +unsigned int num2hex( unsigned int num ); +void sprintf( char *Str, char* Format, ... ); +// +Dword rtlInterlockedExchange( Dword *target, Dword value ); +// функция -1 завершения процесса +void __declspec(noreturn) kos_ExitApp(); +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, Dword mainAreaColour, + Byte headerType, Dword headerColour, + Dword borderColour + ); +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ); +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ); +// функция 3 получить время +Dword kos_GetSystemClock(); +// функция 4 +void kos_WriteTextToWindow( + Word x, Word y, + Byte fontType, + Dword textColour, + const char *textPtr, + Dword textLen + ); +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ); +// функция 8 определить кнопку +void __declspec(noinline) kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ); +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ); +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID = PROCESS_ID_SELF ); +// функция 10 +Dword kos_WaitForEvent(); +// функция 11 +Dword kos_CheckForEvent(); +// функция 12 +void kos_WindowRedrawStatus( Dword status ); +// функция 13 нарисовать полосу +void __declspec(noinline) kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ); +// функция 17 +bool kos_GetButtonID( Dword &buttonID ); +// функция 23 +Dword kos_WaitForEventTimeout( Dword timeOut ); +// +enum eNumberBase +{ + nbDecimal = 0, + nbHex, + nbBin +}; +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ); +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ); +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase = nbDecimal, + bool valueIsPointer = false + ); +// функция 58 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ); +// функция 63 +void kos_DebugOutChar( char ccc ); +// +void rtlDebugOutString( char *str ); +// функция 64 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ); +// функция 67 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ); +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ); + +void kos_InitHeap(); + +// +void kos_Main(); diff --git a/programs/games/LaserTank/trunk/smalllibc/math2.cpp b/programs/games/LaserTank/trunk/smalllibc/math2.cpp new file mode 100644 index 0000000000..17215478bb --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/math2.cpp @@ -0,0 +1,87 @@ +#include +#include "kosSyst.h" +extern "C" int _fltused = 0; + +#define M_PI 3.14159265358979323846 + +double __cdecl acos(double x) +{ + __asm { + fld qword ptr [esp+4] + fld1 + fadd st, st(1) + fld1 + fsub st, st(2) + fmulp st(1), st + fsqrt + fxch st(1) + fpatan + } +} +double __cdecl asin(double x) +{ + __asm { + fld qword ptr [esp+4] + fld1 + fadd st, st(1) + fld1 + fsub st, st(2) + fmulp st(1), st + fsqrt + fpatan + ret + } +} +#if _MSC_VER <= 1200 +extern "C" double _ftol(double x) +{ + __asm { + fld qword ptr [esp+4] + push 1F3Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} +#endif +/* +double __cdecl ceil(double x) +{ + __asm { + fld qword ptr [esp+4] + push 1B3Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} +*/ +double __cdecl floor(double x) +{ + __asm { + fld qword ptr [esp+4] + push 173Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} + +double __cdecl round(double x) +{ + __asm { + fld qword ptr [esp+4] + push 133Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/smalllibc/mcsmemm.cpp b/programs/games/LaserTank/trunk/smalllibc/mcsmemm.cpp new file mode 100644 index 0000000000..c2593293ed --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/mcsmemm.cpp @@ -0,0 +1,373 @@ +// memman.cpp : Defines the entry point for the console application. +// + +#include "kosSyst.h" +#include "mcsmemm.h" + + +void * __cdecl operator new ( size_t count, size_t element_size ) +{ + return allocmem( (Dword)(count * element_size) ); +} + +void * __cdecl operator new [] ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void * __cdecl operator new ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void __cdecl operator delete ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + +void __cdecl operator delete [] ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + +void __cdecl initHeap(void) +{ + __asm + { + push 68 + pop eax + push 11 + pop ebx + int 0x40 + } +} + +#pragma data_seg(".CRT$XCB") +__declspec(allocate(".CRT$XCB")) void (__cdecl *initHeapPtr)(void) = &initHeap; + +__declspec(noinline) Byte* __fastcall allocmem( Dword reqsize ) +{ + initHeapPtr; // force dependency + __asm + { + push 68 + pop eax + push 12 + pop ebx + int 0x40 + } + +} + +__declspec(noinline) void __fastcall freemem( void *vaddress ) +{ + initHeapPtr; // force dependency + __asm + { + push 68 + pop eax + push 13 + pop ebx + int 0x40 + } + +} +/* + +// +Dword mmMutex = FALSE; +MemBlock *rootfree = NULL; +MemBlock *rootuser = NULL; +bool mmInitialized = false; +Byte *mmHeapTop = NULL; + + +// +Byte * AllocMemFromSystem( Dword reqSize ) +{ + Byte *result; + sProcessInfo pInfo; + + // + if ( mmInitialized ) + { + result = mmHeapTop; + } + else + { + // + kos_ProcessInfo( &pInfo ); + // + result = (Byte *)(pInfo.processInfo.used_memory + 1); + // + mmInitialized = true; + } + // + if ( ! kos_ApplicationMemoryResize( ((Dword)result) + reqSize ) ) + { + result = NULL; + } + // + mmHeapTop = result + reqSize; + // + return result; +} + + +// +Byte *allocmem( Dword reqsize ) +{ + MemBlock *BlockForCheck; + MemBlock *LastKnownGood; + Dword tail; + Byte *address; + + //подровняем размер + if( ( tail = reqsize % SIZE_ALIGN ) != 0 ) + { + reqsize += SIZE_ALIGN - tail; + } + + LastKnownGood = NULL; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + //ищем подходящий свободный блок + if( rootfree != NULL ) + { + for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next ) + { + if ( BlockForCheck->Size >= reqsize ) + { + //нашли + if ( LastKnownGood != NULL ) + { + if ( LastKnownGood->Size >= BlockForCheck->Size ) + LastKnownGood = BlockForCheck; + } + else + LastKnownGood = BlockForCheck; + if ( LastKnownGood->Size == reqsize ) + break; + } + if ( BlockForCheck->Next == NULL ) + break; + } + } + + if ( LastKnownGood != NULL ) + { + //проверим найденный блок на возможность деления + tail = LastKnownGood->Size - reqsize; + if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) ) + { + //будем разбивать + BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail ); + BlockForCheck->Size = reqsize; + //вставим занятый блок в начало списка занатых блоков + if( rootuser != NULL ) + { + BlockForCheck->Next = rootuser; + rootuser->Previous = BlockForCheck; + BlockForCheck->Previous = NULL; + rootuser = BlockForCheck; + } + else + { + rootuser = BlockForCheck; + BlockForCheck->Next = NULL; + BlockForCheck->Previous = NULL; + } + + //изменим размер оставшейся части + LastKnownGood->Size = tail - sizeof(MemBlock); + address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + else + { + //перемести блок из очереди свободных в начало очереди занятых + //сначала выкинем его из очереди свободных + if ( LastKnownGood->Previous != NULL ) + { + LastKnownGood->Previous->Next = LastKnownGood->Next; + } + else + { + //блок стоит в начале очереди + rootfree = LastKnownGood->Next; + } + if( LastKnownGood->Next != NULL ) + { + LastKnownGood->Next->Previous = LastKnownGood->Previous; + } + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + // + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + else + { + //надо получить ещё кусочек памяти + LastKnownGood = (MemBlock *)AllocMemFromSystem( reqsize + sizeof(MemBlock) ); + // + if( LastKnownGood != NULL ) + { + LastKnownGood->Size = reqsize; + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + // + rtlDebugOutString( "allocmem failed." ); + kos_ExitApp(); + // + return NULL; +} + +// +Dword freemem( void *vaddress ) +{ + Dword result; + + Byte *checknext, *address = (Byte *)vaddress; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) ); + + result = released->Size; + + //убираем блок из списка занятых + if ( released->Previous != NULL ) + { + released->Previous->Next = released->Next; + } + else + { + rootuser = released->Next; + } + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //закинем теперь этот блок в список свободных + released->Next = rootfree; + released->Previous = NULL; + rootfree = released; + if ( released->Next != NULL ) + { + released->Next->Previous = released; + } + + //теперь поищем смежные свободные блоки + checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) ); + // + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released ) + { + //собираем блоки вместе + //сначала выкинем из очереди свободных + released->Previous->Next = released->Next; + if( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //теперь увеличим размер корневого блока + rootfree->Size += released->Size + sizeof(MemBlock); + break; + } + } + //если надо, поищем блоки перед текщим. + checknext = (Byte *)(rootfree); + // + if ( released == NULL ) + { + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) ) + { + //собираем блоки вместе + //увеличим размер блока + released->Size += rootfree->Size + sizeof(MemBlock); + //теперь выкинем из очереди свободных + released->Previous->Next = released->Next; + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //и закинем его в начало очереди вместо присоединённого блока из корня списка + if ( rootfree->Next != NULL ) + { + rootfree->Next->Previous = released; + } + released->Next = rootfree->Next; + released->Previous = NULL; + rootfree = released; + break; + } + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return result; +} + +*/ \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/smalllibc/mcsmemm.h b/programs/games/LaserTank/trunk/smalllibc/mcsmemm.h new file mode 100644 index 0000000000..dd94a0e7b4 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/mcsmemm.h @@ -0,0 +1,28 @@ +// + +struct MemBlock +{ + Dword Size; + Dword Addr; + MemBlock *Next; + MemBlock *Previous; +}; + + +#define INITIALQUEUESIZE (32 * 4) + +#define FALSE 0 +#define TRUE -1 + +#define MB_FREE 0 +#define MB_USER 1 + +#define SIZE_ALIGN 4 + + + +Byte * __fastcall allocmem( Dword reqsize ); +void __fastcall freemem( void *vaddress ); + + + diff --git a/programs/games/LaserTank/trunk/smalllibc/mymath.h b/programs/games/LaserTank/trunk/smalllibc/mymath.h new file mode 100644 index 0000000000..6d911d875c --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/mymath.h @@ -0,0 +1,95 @@ +/* Rocket Forces + * Filename: mymath.h + * Version 0.1 + * Copyright (c) Serial 2007 + */ + + +extern "C" int _fltused = 0; + +#define M_PI 3.14159265358979323846 + +inline double sin(double x) +{ + __asm fld x + __asm fsin +} + +inline double cos(double x) +{ + __asm fld x + __asm fcos +} + +inline double sqrt(double x) +{ + __asm fld x + __asm fsqrt +} + +inline double acos(double x) +{ + __asm fld x + __asm fld st(0) + __asm fmul st,st(1) + __asm fld1 + __asm fsubrp st(1),st(0) + __asm fsqrt + __asm fxch st(1) + __asm fpatan +} + +inline double atan(double x) +{ + double res = acos(1 / sqrt(1 + x * x)); + if (x < 0) + { + res *= -1; + } + return res; +} + +inline int round_int(double x) +{ + int i; + static const float round_to_nearest = 0.5f; + __asm + { + fld x + fadd st, st(0) + fadd round_to_nearest + fistp i + sar i, 1 + } + return i; +} + +inline int floor_int(double x) +{ + int i; + static const float round_toward_m_i = -0.5f; + __asm + { + fld x + fadd st, st (0) + fadd round_toward_m_i + fistp i + sar i, 1 + } + return i; +} + +inline int ceil_int(double x) +{ + int i; + static const float round_toward_p_i = -0.5f; + __asm + { + fld x + fadd st, st (0) + fsubr round_toward_p_i + fistp i + sar i, 1 + } + return (-i); +} diff --git a/programs/games/LaserTank/trunk/smalllibc/purecall.cpp b/programs/games/LaserTank/trunk/smalllibc/purecall.cpp new file mode 100644 index 0000000000..adad04dd74 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/purecall.cpp @@ -0,0 +1,11 @@ +#include "kosSyst.h" +static char pureCallMessage[] = "PURE function call!"; + +// вызов абстрактного метода +int __cdecl _purecall() +{ + rtlDebugOutString( pureCallMessage ); + kos_ExitApp(); + return 0; +} + diff --git a/programs/games/LaserTank/trunk/smalllibc/smalllibc.vcxproj b/programs/games/LaserTank/trunk/smalllibc/smalllibc.vcxproj new file mode 100644 index 0000000000..606bef6ad2 --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/smalllibc.vcxproj @@ -0,0 +1,73 @@ +п»ї + + + + Release + Win32 + + + + {911D4818-1AA1-4351-9C0A-38749130FAA6} + Win32Proj + smalllibc + + + + StaticLibrary + false + true + Unicode + v120 + + + + + + + + + + + + Level3 + + + MinSpace + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded + false + true + Size + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/smalllibc/smalllibc.vcxproj.filters b/programs/games/LaserTank/trunk/smalllibc/smalllibc.vcxproj.filters new file mode 100644 index 0000000000..a77412e5ac --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/smalllibc.vcxproj.filters @@ -0,0 +1,60 @@ +п»ї + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + Файлы РёСЃС…РѕРґРЅРѕРіРѕ РєРѕРґР° + + + + + + \ No newline at end of file diff --git a/programs/games/LaserTank/trunk/smalllibc/sprintf.cpp b/programs/games/LaserTank/trunk/smalllibc/sprintf.cpp new file mode 100644 index 0000000000..dde80e5f2d --- /dev/null +++ b/programs/games/LaserTank/trunk/smalllibc/sprintf.cpp @@ -0,0 +1,228 @@ +#include "kosSyst.h" +#include "func.h" +#include + +////////////////////////////////////////////////////////////////////// +// +// вывод строки на печать. barsuk добавил %f + +//#define PREC 2 +//#define HALF 0.499 +#define PREC 6 +#define HALF 0.4999999 + +static double double_tab[]={1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, +1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30}; + + +// + +static Dword dectab[] = { 1000000000, 100000000, 10000000, 1000000, 100000, + 10000, 1000, 100, 10, 0 }; + +// +void sprintf( char *Str, char* Format, ... ) +{ + int i, fmtlinesize, j, k, flag; + Dword head, tail; + char c; + va_list arglist; + // + va_start(arglist, Format); + + // + fmtlinesize = strlen( Format ); + // + if( fmtlinesize == 0 ) return; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = Format[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = Format[i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // вывод строки + case 'S': + Byte* str; + str = va_arg(arglist, Byte*); + for( k = 0; ( c = str[k] ) != 0; k++ ) + { + Str[j++] = c; + } + break; + // вывод байта + case 'B': + k = va_arg(arglist, int) & 0xFF; + Str[j++] = num2hex( ( k >> 4 ) & 0xF ); + Str[j++] = num2hex( k & 0xF ); + break; + // вывод символа + case 'C': + Str[j++] = va_arg(arglist, int) & 0xFF; + break; + // вывод двойного слова в шестнадцатиричном виде + case 'X': + Dword val; + val = va_arg(arglist, Dword); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( val >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + break; + // вывод двойного слова в десятичном виде + case 'U': + head = va_arg(arglist, Dword); + tail = 0; + for( k = 0; dectab[k] != 0; k++ ) + { + tail = head % dectab[k]; + head /= dectab[k]; + c = head + '0'; + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + // + head = tail; + } + // + c = head + '0'; + Str[j++] = c; + break; + // вещественное число в формате 7.2 + case 'f': + case 'F': + case 'g': + case 'G': + { + double val, w; + int p; + val = va_arg(arglist, double); + if (val < 0.0) + { + Str[j++] = '-'; + val = -val; + } + for (k = 0; k < 30; k++) + if (val < double_tab[k]) + break; + + if (val < 1.0) + { + Str[j++] = '0'; + } + + for (p = 1; p < k + 1; p++) + { + int d = (int)di(val / double_tab[k - p] - HALF) % 10; + Str[j++] = '0' + d; + val -= d * double_tab[k - p]; + } + Str[j++] = '.'; + w = 0.1; + for (p = 0; p < PREC - 1; p++) + { + val-=floor(val); + Str[j++] = '0' + di(val / w - HALF) % 10; + w /= 10.0; + } + } + break; + + // вывод 64-битного слова в шестнадцатиричном виде + case 'Q': + unsigned int low_dword, high_dword; + low_dword = va_arg(arglist, unsigned int); + high_dword = va_arg(arglist, unsigned int); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( ( high_dword + 1) >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + for( k=7; k >= 0; k-- ) + { + // + c = num2hex ( ( low_dword >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + // + break; + // + default: + break; + } + } + // + Str[j] = 0; +} + +char *ftoa(double d) +{ + char buffer[256], *p; + sprintf(buffer, "%f", d); + p = (char*)allocmem(strlen(buffer)+1); + strcpy(p, buffer); + return p; +} +