Приветствую, Хабравчане!
Я сейчас добавляю возможность вывода изображений с помощью GDI и XLib. Но до конца код не готов. Но решил пока кода мало попробовать его собрать на нескольких старых компиляторах 30-ти летней давности. И только такой путь может дать нормальный бинарник работающий на системах Windows 98, 95.
Для загрузки графики использую stb_image. В итоге получилось так. Правда в оригинале цвет должен быть красным, а не синим. Но пока вывод изображений не закончен.
Основная репа RetroFan.
Картинка выводится с масштабированием GDI.
А, должен выглядеть так:
Для моих целей подойдет не каждый старый компилятор, а только с поддержкой namespace и каким то подобием поддержки шаблонов.
Со сцены сразу уходят Borland C++ компиляторы до версии 4.0
Решил начать с Visual C++ 4.0.
Всё это непотребство тестирую и компилирую на Windows XP установленную на VirtualBox 7.1.4. Я выбрал VirtualBox, потому, что он поддерживаете общие папки. Что позволяет предаваться ретро программированию с комфортом. Разрабатывая код на современных системах, в современном IDE.
Устанавливаем.
Что бы не привязываться к системе сборки от майков, вида nmake и создавать проект непосредственно в студии. Буду собирать простым bat файлом. Подаем ключи и файлы компилятору.
call "c:\msdev\bin\VCVARS32.BAT"
cl /O2 -GX -FeLDL_Win.exe -I..\LDL\include ..\LDL_Win.cpp ..\LDL\source\*.cpp ..\LDL\source\Windows\*.cpp /link gdi32.lib winmm.lib user32.lib opengl32.lib
cl /O2 -GX -FeLDL_Img.exe -I..\LDL\include ..\LDL_Img.cpp ..\LDL\source\*.cpp ..\LDL\source\Windows\*.cpp /link gdi32.lib winmm.lib user32.lib opengl32.lib
pause
Ошибок конечно навалили:) Начнем разбираться.
Скрытый текст
Z:\make>call "c:\msdev\bin\VCVARS32.BAT"
Usage: vcvars32 [target]
Where target is one of the following: x86, m68k, mppc.
No target specified. Selecting x86 as default target.
Setting environment for building x86 target
LDL_Win.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
BaseRndr.cpp
..\LDL\include\LDL/Color.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory
BaseWin.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
Eventer.cpp
..\LDL\include\LDL/RngBuf.hpp(35) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/RngBuf.hpp(35) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/RngBuf.hpp(98) : error C2992: 'RingBuffer' : invalid or missing template parameter list
..\LDL\include\LDL/Events.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory
GdiRndr.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
GdiTex.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
MainWin.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
Generating Code...
LDL_Img.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
BaseRndr.cpp
..\LDL\include\LDL/Color.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory
BaseWin.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
Eventer.cpp
..\LDL\include\LDL/RngBuf.hpp(35) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/RngBuf.hpp(35) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/RngBuf.hpp(98) : error C2992: 'RingBuffer' : invalid or missing template parameter list
..\LDL\include\LDL/Events.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory
GdiRndr.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
GdiTex.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
MainWin.cpp
..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list
..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename'
..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list
..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared
..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<'
..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<'
..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory
Быстрым гуглением по кодам и описанию ошибок, приходит понимание. Что ещё в до стандартные времена С++ каждый вендор понимал С++ по своему. Ошибка не сложная нужно просто заменить в объявлении шаблона typename на class.
syntax error : identifier 'typename'
Здесь уже сложнее, в поставку не входит STL и заголовки от С99. Тогда создадим их и передадим компилятору.
#ifndef LDL_Support_stdint_h
#define LDL_Support_stdint_h
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
#endif
fatal error C1083: Cannot open include file: 'string': No such file or directory
fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory
На эту ошибку у меня ушло больше времени. Тип bool отсутствует, тогда я его добавил самым простым и очевидным способом.
typedef enum { false, true } bool;
error C2501: 'bool' : missing decl-specifiers
Но сработал другой способ. Переопределение через define. Правда теперь bool вместо 1-го байта, стал 4-ех байтным.
#if (_MSC_VER <= 1100)
#define __forceinline
#endif
#if (_MSC_VER <= 1020)
#include <Windows.h>
#define bool BOOL
#define true TRUE
#define false FALSE
#endif
Естественно компилятор 1995 года не знает ни о каких этих ваших интринсиках. Поэтому добавляем пару дефайнов, отключающие использование современных компиляторных фич.
..\stb_image.h(726) : fatal error C1083: Cannot open include file: 'emmintrin.h': No such file or directory
#if (_MSC_VER <= 1200)
#define STBI_NO_THREAD_LOCALS
#define STBI_NO_SIMD
#endif
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
Теперь все файлы собраны, на компиляторе 1995 года. Программы запускаются и работают корректно.
Z:\make>call "c:\msdev\bin\VCVARS32.BAT"
Usage: vcvars32 [target]
Where target is one of the following: x86, m68k, mppc.
No target specified. Selecting x86 as default target.
Setting environment for building x86 target
LDL_Win.cpp
BaseRndr.cpp
BaseWin.cpp
Eventer.cpp
GdiRndr.cpp
GdiTex.cpp
MainWin.cpp
Generating Code...
Microsoft (R) 32-Bit Incremental Linker Version 3.00.5270
Copyright (C) Microsoft Corp 1992-1995. All rights reserved.
/out:LDL_Win.exe
gdi32.lib
winmm.lib
user32.lib
opengl32.lib
LDL_Win.obj
BaseRndr.obj
BaseWin.obj
Eventer.obj
GdiRndr.obj
GdiTex.obj
MainWin.obj
LDL_Img.cpp
BaseRndr.cpp
BaseWin.cpp
Eventer.cpp
GdiRndr.cpp
GdiTex.cpp
MainWin.cpp
Generating Code...
Microsoft (R) 32-Bit Incremental Linker Version 3.00.5270
Copyright (C) Microsoft Corp 1992-1995. All rights reserved.
/out:LDL_Img.exe
gdi32.lib
winmm.lib
user32.lib
opengl32.lib
LDL_Img.obj
BaseRndr.obj
BaseWin.obj
Eventer.obj
GdiRndr.obj
GdiTex.obj
MainWin.obj
За кадром я протестировал версии Visual C++ 5.0 и 6.0 все собирается и больше никаких правок в код я не вносил.
Следующим шагом будут компиляторы от фирмы Borland. И ещё проверить Visual C++ 2.0, он поддерживает шаблоны и namespace. Тоже самое проделаю и со старыми Linux дистрибутивами, когда реализую вывод картинок на XLib.
В итоге, даже на таком древнем компиляторе можно использовать самописный STL и namespace. Что довольно хорошо. А самое главное, код совместим и с новыми компиляторами. Все несовместимости обернул в дефайны с проверкой версии.
Такими странными вещами я занимаюсь в свободное время:)
Буду рад предложениям, критике и советам. Уверен, есть куча компиляторов под Windows о которых я не знаю. Обязательно напишите их название, а я постараюсь собрать на них проект. К примеру узнал, что есть компилятор IBM VisualAge C++.
Комментарии (8)
NickDoom
24.01.2025 09:24Мне кажется, для легасей ничего лучше опенваткома не придумали ещё :)
Но может и казаться, конечно…
UPD: что-то охота поиграться с VGA для какого-нибудь элементарного рендерера типа Wolf3D. С нормальной пушкой — 320х200, а взял ночной снайперский прицел — включается 640х480, где рендерятся все 4 цветовые плоскости по очереди :) Такая цепочка «призраков» от прошлых кадров, типа это так ночная оптоэлектроника работает :) И 16 цветов, конечно, раз VGA 640x480. Может быть прикольно :)
Короче, меня тоже пробило на олдскул %)
JordanCpp Автор
24.01.2025 09:24Да это отличный компилятор. И мне нравится, что он может кросс компилировать под старые ОС. Но мне ещё интересен момент нативной сборки на устаревших ОС.
Мне это позволяет посмотреть и пощупать старые ОС, компиляторы и т.д
JordanCpp Автор
24.01.2025 09:24Я после gdi и xlib буду встраивать рендер в буфер, как это раньше делали с поддержкой палитры.
Короче, меня тоже пробило на олдскул %)
:)
unreal_undead2
24.01.2025 09:24Если под DOS - так можно и достаточно свежий gcc взять.
JordanCpp Автор
24.01.2025 09:24Интересно надо будет посмотреть. С дос пойду таким же нативным путем. У в проекте все имена сорцов длиной 8 символов. Что бы нативно все собирать под dos и windows 3.1
В идеале собирать под максимальное количество компиляторов. Зачем? По фану:)
unreal_undead2
Comeau славился хорошей поддержкой 98го стандарта (включая export), должен справиться (если удастся его найти). Topspeed ещё в своё время был на слуху, но боюсь туда новомодные namespace/template не доехали.
JordanCpp Автор
Спасибо, посмотрю.