Приветствую, Хабравчане!

Я сейчас добавляю возможность вывода изображений с помощью 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)


  1. unreal_undead2
    24.01.2025 09:24

    Comeau славился хорошей поддержкой 98го стандарта (включая export), должен справиться (если удастся его найти). Topspeed ещё в своё время был на слуху, но боюсь туда новомодные namespace/template не доехали.


    1. JordanCpp Автор
      24.01.2025 09:24

      Спасибо, посмотрю.


  1. NickDoom
    24.01.2025 09:24

    Мне кажется, для легасей ничего лучше опенваткома не придумали ещё :)

    Но может и казаться, конечно…

    UPD: что-то охота поиграться с VGA для какого-нибудь элементарного рендерера типа Wolf3D. С нормальной пушкой — 320х200, а взял ночной снайперский прицел — включается 640х480, где рендерятся все 4 цветовые плоскости по очереди :) Такая цепочка «призраков» от прошлых кадров, типа это так ночная оптоэлектроника работает :) И 16 цветов, конечно, раз VGA 640x480. Может быть прикольно :)

    Короче, меня тоже пробило на олдскул %)


    1. JordanCpp Автор
      24.01.2025 09:24

      Да это отличный компилятор. И мне нравится, что он может кросс компилировать под старые ОС. Но мне ещё интересен момент нативной сборки на устаревших ОС.

      Мне это позволяет посмотреть и пощупать старые ОС, компиляторы и т.д


    1. JordanCpp Автор
      24.01.2025 09:24

      Я после gdi и xlib буду встраивать рендер в буфер, как это раньше делали с поддержкой палитры.

      Короче, меня тоже пробило на олдскул %)

      :)


    1. unreal_undead2
      24.01.2025 09:24

      Если под DOS - так можно и достаточно свежий gcc взять.


      1. JordanCpp Автор
        24.01.2025 09:24

        Интересно надо будет посмотреть. С дос пойду таким же нативным путем. У в проекте все имена сорцов длиной 8 символов. Что бы нативно все собирать под dos и windows 3.1

        В идеале собирать под максимальное количество компиляторов. Зачем? По фану:)


        1. unreal_undead2
          24.01.2025 09:24

          Тогда как вариант ещё попробовать CodeWarrior под MacOS 9.x и BeOS )