forked from joncampbell123/dosbox-x
-
Notifications
You must be signed in to change notification settings - Fork 3
/
README.source-code-description
1634 lines (1235 loc) · 63.9 KB
/
README.source-code-description
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
DOSBox-X Source Code Description
================================
This page tries to explain the source code of DOSBox-X, including compiling
information and some technical details.
Such information is primarily targeted at advanced users or developers, and
anyone who wants to contribute to the DOSBox-X project.
Users who are primarily looking for instructions on installing and running
DOSBox-X may want to look at the INSTALL.md file and the DOSBox-X Wiki instead.
There is also a section for crediting the source code in the end of this page.
General information on source code compilation
----------------------------------------------
The four major operating systems and platforms of DOSBox-X are:
1. Linux (with X11) 32-bit and 64-bit x86, and on a Raspberry Pi 3 (arm 7).
2. Windows 10, 8, 7, Vista and XP for 32-bit and 64-bit x86 and ARM.
3. macOS (Mac OS X) Sierra 10.12 or higher 64-bit.
4. DOS (MS-DOS 5.0+ or compatible).
Straight Windows builds are expected to compile using the free community edition
of Visual Studio 2015 to Visual Studio 2019 and the DirectX 2010 SDK.
Linux and MinGW Windows builds are expected to compile with the GNU autotools.
macOS builds are expected to compile on the terminal using GNU autotools and
the LLVM/Clang compiler provided by XCode.
In all cases, the code requires a C++ compiler that can support the C++11
standard.
Note that DOSBox-X is written to compile against the in-tree copy of the
SDL 1.x (Simple Directmedia Libary), or against the SDL 2.x library provided
by your Linux distribution.
For Visual Studio and MinGW compilation, the in-tree copy of SDL is always
used. Note that the in-tree SDL 1.x library has been HEAVILY MODIFIED from
the original SDL 1.x source code and is thus somewhat incompatible with the
stock library.
The modifications provide additional functions needed to improve DOSBox-X
and fix many issues with keyboard input, window mangement, and display
management that previously required terrible kludges within the DOSBox
and DOSBox-X source code.
In Windows, the modifications also permit the emulation to run independent
of the main window so that moving, resizing, or using menus does not cause
emulation to pause.
In macOS, the modifications provide an interface to allow DOSBox-X to
replace and manage the macOS menu bar.
How to compile the source code (cross-platform)
-----------------------------------------------
General Linux compile (SDL1)
./build-debug
sudo make install
General Linux compile (SDL2)
./build-debug-sdl2
sudo make install
macOS compile (SDL1)
./build-macosx
macOS compile (SDL2)
./build-macosx-sdl2
MinGW compile (using MinGW32 or MinGW64) for Windows XP or later (SDL1)
./build-mingw
MinGW compile (using MinGW32 or MinGW64) for Windows XP or later (SDL1), lower-end systems that lack MMX/SSE
./build-mingw-lowend
MinGW compile (using MinGW32 or MinGW64) for Windows XP or later (SDL2)
./build-mingw-sdl2
MinGW compile (on Windows, using MinGW, not MinGW64) to target the DOS platform (MS-DOS or compatible with HX DOS Extender)
./build-mingw-hx-dos
NOTICE: Use the 32-bit toolchain from the original MinGW project for this build, not the MinGW64 project.
Binaries compiled with MinGW64 have extra dependencies not provided by the HX DOS Extender.
macOS: If you want to make an .app bundle you can run from the Finder, compile the program as instructed then run "make dosbox-x.app".
XCode (on macOS, from the Terminal) to target macOS
./build-debug
## To compile DOSBox-X in Ubuntu (tested with 20.04 and 20.10):
First install the development tools, headers and libraries needed
sudo apt install automake gcc g++ make libncurses-dev nasm libsdl-net1.2-dev libsdl2-net-dev libpcap-dev libslirp-dev fluidsynth libfluidsynth-dev libavdevice58 libavformat-dev libavcodec-dev libavcodec-extra libavcodec-extra58 libswscale-dev libfreetype-dev libxkbfile-dev libxrandr-dev
Then change to the directory where you unpacked the DOSBox-X source code, and run the following commands:
./build-debug
sudo make install
Alternatively you can also compile the SDL2 version by running the ./build-debug-sdl2 script.
## To compile DOSBox-X in Fedora Workstation:
First install the development tools, headers and libraries needed
sudo dnf group install "C Development Tools and Libraries"
sudo dnf install SDL_net-devel SDL2_net-devel libxkbfile-devel ncurses-devel libpcap-devel libslirp-devel libpng-devel fluidsynth-devel freetype-devel nasm
If you want to be able to record video, you will also need to install ffmpeg-devel which you can get from the optional rpmfusion-free repository.
Then change to the directory where you unpacked the DOSBox-X source code, and run the following commands:
./build-debug
sudo make install
Alternatively you can also compile the SDL2 version by running the ./build-debug-sdl2 script.
## To create a DOSBox-X RPM for use in RHEL, CentOS or Fedora:
First ensure that your system has all the necessary development tools and libraries installed, such as by following the dnf steps in the above "To compile DOSBox-X in Fedora Workstation".
Then run the following commands:
sudo dnf group install "RPM Development Tools"
./make-rpm.sh
After a successful compile, the RPM can be found in the releases directory.
Compiling the source code using Visual Studio (Windows)
-------------------------------------------------------
You can build the source code with Visual Studio (2015, 2017, 2019).
The executables will work on 32-bit and 64-bit Windows Vista or higher.
Use the ./vs2015/dosbox-x.sln "solution" file and build the source code.
You will need the DirectX 2010 SDK for Direct3D9 support.
By default the targeted platform is v142 (Visual Studio 2019).
For building the source code in Visual Studio 2015 or 2017,
you may change the platform toolset to v140 or v141 respectively.
Libraries such as SDL, freetype, libpdcurses, libpng and zlib are already included,
and as of DOSBox-X 0.83.6 support for FluidSynth MIDI Synthesizer is also included
(set "mididevice=fluidsynth" in the [midi] section of DOSBox-X's configuration file
(dosbox-x.conf) along with required soundfont file (e.g. FluidR3_GM.sf2) to use it).
The slirp backend is only supported by MinGW builds but not Visual Studio builds.
Build the source code for your platform (Win32, x64, ARM and ARM64 are supported).
As of 2018/06/06, Visual Studio 2017 builds (32-bit and 64-bit) explicitly require
a processor that supports the SSE instruction set.
Visual Studio Code is supported, too.
Check the README.development-in-Windows file for more information about this platform.
Libraries used by DOSBox-X
--------------------------
The following libraries are used by DOSBox-X:
SDL 1.2.x or SDL 2.0.x
The Simple DirectMedia Library available at https://www.libsdl.org
The DLL distributed with the Windows SDL1 version of DOSBox-X had
been modified from the original. You can find the changes in the
source package of DOSBox-X (src/platform/sdl-win32.diff). If you
want the patched source tree send us an email. (see README)
Note that only version 1.2.x (SDL1 version) and version 2.0.x
(SDL2 version) are currently supported.
License: LGPLv2+
Curses (optional)
If you want to enable the debugger you need a curses library.
ncurses should be installed on just about every unix distro.
For win32 get pdcurses at https://pdcurses.org/
License: Public Domain
Libpng (optional)
Needed for the screenshots.
For win32 get libpng from https://gnuwin32.sourceforge.net/packages.html
See http://www.libpng.org/pub/png/ for more details.
License: zlib/libpng
Zlib
Needed by libpng, and for saving state and CHD support.
For win32 get libz (rename to zlib) from https://gnuwin32.sourceforge.net/packages.html
See https://www.zlib.net/ for more details.
License: zlib
FreeType (optional)
Needed for TrueType font (TTF) output and printing support.
It is available from https://www.freetype.org/download.html
License: FTL or GPLv2+
FluidSynth (optional)
For soundfont support.
It is available from https://www.fluidsynth.org/download/
License: LGPLv2+
libpcap (optional)
For pcap backend of NE2000 networking support.
Get it from https://www.tcpdump.org/index.html#latest-releases
For win32 get Npcap (WinPcap for Windows 10) from https://nmap.org/download.html
License: 3-clause BSD license
libslirp (optional)
For slirp backend of NE2000 networking support.
Get it from https://gitlab.freedesktop.org/slirp/libslirp
License: Modified 4-clause BSD license
SDL_Net (optional)
For modem/ipx support.
Get it from https://www.libsdl.org/projects/SDL_net/release-1.2.html
License: LGPLv2+
SDL_Sound (optional)
For compressed audio on diskimages (cue sheets) support.
This is for cue/bin CD-ROM images with compressed (MP3/OGG/FLAC) audio tracks.
Get it from https://icculus.org/SDL_sound
Licence: LGPLv2+
ALSA_Headers (optional)
for Alsa support under linux. Part of the linux kernel sources
License: LGPLv2+
Configure script options
------------------------
The DOSBox-X configure script accepts the following switches, which you can use to customize the code compilation:
--enable-FEATURE[=ARG]
Includes FEATURE [ARG=yes]
--enable-silent-rules
Less verbose build output (undo: "make V=1")
--enable-dependency-tracking
Do not reject slow dependency extractors
--enable-force-menu-sdldraw
Forces SDL drawn menus
--enable-hx-dos
Enables HX-DOS target
--enable-emscripten
Enables Emscripten target
--enable-sdl
Enables SDL 1.x
--enable-sdl2
Enables SDL 2.x
--enable-xbrz
Compiles with xBRZ scaler (default yes)
--enable-scaler-full-line
Scaler render full line instead of detecting
changes, for slower systems
--enable-alsa-midi
Compiles with ALSA MIDI support (default yes)
--enable-d3d9
Enables Direct3D 9 support
--enable-d3d-shaders
Enables Direct3D shaders
--enable-debug
Enables the internal debugger. --enable-debug=heavy enables even more
debug options. To use the debugger, DOSBox-X should be run from an xterm
and when the sdl-window is active press alt-pause to enter the
debugger.
--disable-FEATURE
Do not include FEATURE (same as --enable-FEATURE=no)
--disable-silent-rules
Verbose build output (undo: "make V=0")
--disable-dependency-tracking
Speeds up one-time build
--disable-largefile
Omits support for large files
--disable-x11
Do not enable X11 integration
--disable-optimize
Do not enable compiler optimizations
--disable-sdl2test
Do not try to compile and run a test SDL 2.x program
--disable-sdltest
Do not try to compile and run a test SDL 1.x program
--disable-alsatest
Do not try to compile and run a test ALSA program
--disable-freetype
Disables FreeType support
--disable-printer
Disables printer emulation
--disable-mt32
Disables MT32 emulation
--disable-screenshots
Disables screenshots and movie recording
--disable-avcodec
Disables FFMPEG avcodec support
--disable-core-inline
Disables some memory increasing inlines. This will reduces compiletime
for a possible speed decrease.
--disable-fpu
Disables the emulated FPU. Although the FPU emulation code isn't
finished and isn't entirely accurate, it's advised to leave it on.
--disable-fpu-x86
--disable-fpu-x64
Disables the assembly FPU core. Although relatively new, the x86/x64
FPU core has more accuracy than the regular FPU core.
--disable-dynamic-x86
Disables the dynamic x86/x64 specific CPU core. Although it might be
a bit unstable, it can greatly improve the speed of dosbox-x on x86
and x64 hosts.
Please note that this option on x86/x64 will result in a different
dynamic/recompiling CPU core being compiled than the default.
For more information see the option --disable-dynrec
--disable-dynrec
Disables the recompiling CPU core. Currently x86/x64 and arm only.
You can activate this core on x86/x64 by disabling the dynamic-x86
core.
--disable-dynamic-core
Disables all dynamic cores. (same effect as --disable-dynamic-x86
or --disable-dynrec).
--disable-opengl
Disables OpenGL support (output mode that can be selected in the
DOSBox-X configuration file).
--disable-unaligned-memory
Disables unaligned memory access.
General description of source code
----------------------------------
src/shell/shell.cpp SHELL init, SHELL run, fake COMMAND.COM setup,
startup messages and ANSI art, CONFIG.SYS and
AUTOEXEC.BAT emulation and setup, shell interface,
input, parsing, and execution.
src/shell/shell_batch.cpp Batch file (*.BAT) handling
src/shell/shell_cmds.cpp Shell internal command handling, shell commands:
DIR CD/CHDIR ADDKEY ALIAS
ATTRIB BREAK CALL CHOICE
CLS COPY COUNTRY CTTY
DATE DEBUGBOX DEL/ERASE DELTREE
DX-CAPTURE ECHO EXIT FOR
GOTO HELP IF LFNFOR
LH/LOADHIGH MD/MKDIR MORE PATH
PAUSE POPD PROMPT PUSHD
RD/RMDIR REM REN/RENAME SET
SHIFT SUBST TIME TYPE
VER VERIFY VOL TRUENAME
src/shell/shell_misc.cpp PROMPT generator, command line input interface,
shell execution, and command location via PATH
interface.
src/gui/sdlmain.cpp Entry point, emulator setup, runtime execution,
cleanup. Menu management, GFX start/end handling,
GFX mode setup and management. Menu handling.
Logging of GFX state. A lot of other misc code.
src/gui/sdlmain_linux.cpp Linux-specific state tracking and handling.
src/gui/sdl_mapper.cpp Mapper interface, mapper event handling and routing,
mapper file reading and writing. Keyboard, mouse,
joystick, and shortcut handling. In DOSBox-X,
also ties mapper shortcuts to the menu system.
src/gui/sdl_gui.cpp Configuration GUI (using gui_tk), dialog boxes,
background "golden blur" behind dialog boxes,
input management and display of dialog boxes.
src/gui/menu.cpp Menu handling and management, processing,
application of menu to host OS menu framework
if applicable. In DOSBox-X, contains the menu
C++ class and menu item object system which then
maps to Windows HMENU, macOS NSMenu, or the
custom drawn SDL menus if neither are available.
Which menu framework is used depends on the
assignment of the DOSBOXMENU_* constant as defined
in include/menu.h. By default:
Windows (HMENU) is used if targeting Windows
and not HX DOS and not SDL2
macOS (NSMENU) is used if targeting Apple
macOS and not SDL2
SDL drawn menus are used in all other cases.
A define is available via configure.ac if
SDL drawn menus should be used regardless of
the host OS and environment.
A NULL menu define is provided if a build
with no visible menus is desired.
src/gui/render.cpp RENDER_ and render scaler code. Also handles
color palette, aspect ratio, autofit options.
The selection of render scaler is defined and
chosen here.
src/gui/render_scalers.cpp Render scaler definitions and code. Note that
scalers are defined using header files as
templates and #defines to support each color
format.
src/gui/midi.cpp MIDI output framework. Header files include
additional platform-specific code.
src/gui/menu_macos.mm macOS Objective C++ code to bridge Objective C
and C++ so that the menu manipulation code can
work correctly.
src/gui/direct3d.cpp Windows Direct3D9 support code. This code allows
output=direct3d to work properly. Uses DirectX 9
interfaces.
include/bitop.h Header file to provide compile-time and runtime
inline functions for bit manipulation and masking.
Additional code is in src/gui/bitop.cpp
include/ptrop.h Header file to provide compile-time and runtime
inline functions for pointer manipulation and
alignment. Additional code is in src/gui/ptrop.cpp.
src/aviwriter/* AVI writer library, written by Jonathan Campbell
sometime around 2010, and incorporated into DOSBox-X.
Unlike the initial code from DOSBox SVN, this code
can support writing OpenDML AVI files that exceed
the 2GB file size limit.
All definitions, including Windows PCM formats and
GUIDs, are provided here.
src/misc/cross.cpp Cross-platform utility functions.
src/misc/messages.cpp Message translation table functions.
src/misc/setup.cpp Configuration, section, and setting management.
src/misc/shiftjis.cpp Shift-JIS utility functions.
src/misc/support.cpp String support functions including case conversion.
src/builtin/*.cpp Built-in executable binaries, defined as unsigned char[]
arrays and registered at runtime:
25.COM 28.COM 50.COM APPEND.EXE
BUFFERS.COM COPY.EXE CWSDPMI.EXE DEBUG.EXE
DEVICE.COM DOS32A.EXE DOS4GW.EXE DOSIDLE.EXE
EDIT.COM FCBS.COM FIND.EXE HEXMEM16.EXE
HEXMEM32.EXE LASTDRIV.COM MEM.COM MOVE.EXE
TREE.EXE UNZIP.EXE XCOPY.EXE ZIP.EXE
Plus a few more...
src/cpu/paging.cpp Paging and page handling code, TLB (translation lookaside buffer),
Page handlers
src/cpu/modrm.cpp x86 mod/reg/rm effective address handling and lookup
src/cpu/mmx.cpp Minimalist MMX register handling and effective address lookup
src/cpu/lazyflags.cpp Lazy CPU flag evalulation. CPU flags are evaluated only if needed.
src/cpu/flags.cpp CPU flag evaluation code.
src/cpu/cpu.cpp NMI emulation, protected mode descriptors, stack push/pop,
Selector base/limit handling, CPL, flags, exception handling,
TSS (Task State Segment), task switching, I/O exception
handling, general exception handling, interrupt handling,
general flow control instruction handling, evaluation of
[cpu] section settings and application of settings and
changes to settings, I/O instruction stubs, model-specific
register emulation, CMPXCHG8B.
src/cpu/core_simple.cpp Simple CPU core (core=simple). Uses normal core header files.
Core cannot be used if paging is enabled or when executing
from memory outside the valid range of system memory.
src/cpu/core_prefetch.cpp Prefetch CPU core (cputype=*_prefetch). Uses normal core header files.
This core should be used for any application that is dependent
on CPU prefetch including anti-debugger, copy protection, or
self modifying code.
src/cpu/core_normal.cpp Normal CPU core.
src/cpu/core_normal_286.cpp Normal CPU core, 286 emulation.
src/cpu/core_normal_8086.cpp Normal CPU core, 8086 emulation.
src/cpu/core_full.cpp Full CPU core (core=full). Appears to have been borrowed from
Bochs.
src/cpu/core_dyn_x86.cpp Dynamic CPU core (core=dynamic). On 32-bit x86 builds, this code
interprets the guest executable code and produces executable
code for the host process. This core is faster than the other
cores however it may have problems with paging and it does not
emulate CPU cycle counts accurately.
src/cpu/callback.cpp DOSBox/DOSBox-X callback instruction and callback handling system.
src/debug/debug.cpp Debugger, breakpoint handling and enforcement, debugger commands,
debugger interface, debug runtime loop (when broken into the
debugger)
src/debug/debug_gui.cpp Debugger interface windowing system, GUI drawing, logging system
and LOG() C++ class, LOG_MSG() function, log file writing
src/debug/debug_disasm.cpp 16/32-bit i486 instruction disassembler, used in the debugger
to show instructions in the code window. Apparently taken from
the GNU debugger.
src/debug/debug_win32.cpp Win32 console handling code, including resizing.
src/hardware/iohandler.cpp I/O port handling code and registration system.
src/hardware/memory.cpp Memory mapping, handling code, registration,
system RAM allocation, A20 gate control,
CPU reset vector handling, A20 config setting.
src/hardware/mixer.cpp Audio mixer, audio system. All audio is mixed
in 1ms frames from all mixer channels. Other parts of
the emulator register mixer callbacks, where they are
called on to render up to 1ms of audio. All audio is
processed and rendered as 16-bit stereo PCM even if
the audio source provides 8/16-bit mono/stereo. See
mixer framework section for more information. This
also provides MIXER.COM on drive Z:, volume control
mapper shortcuts, menu controls "mute" and "swap stereo".
src/hardware/adlib.cpp Adlib OPL2 and OPL3 emulation. Also provides the NukedOPL
emulation. Note that this is accomplished by including
nukedopl.h, and including opl.cpp twice inline. Once
for OPL2, and once for OPL3.
src/hardware/opl.cpp This is the OPL2/OPL3 implementation, except for NukedOPL.
src/hardware/nukedopl.cpp NukedOPL FM emulation.
src/hardware/sblaster.cpp Sound Blaster emulation, overall. The same codebase
emulates Sound Blaster 1.0 through Sound Blaster 16
as well as ESS688 and Reveal SC400.
src/hardware/pci_bus.cpp PCI bus emulation and framework.
src/hardware/vga.cpp VGA emulation, modeset, resize event, lookup tables,
config parsing.
src/hardware/vga_attr.cpp VGA attribute controller emulation
src/hardware/vga_crtc.cpp VGA CRTC emulation
src/hardware/vga_dac.cpp VGA DAC (palette) emulation
src/hardware/vga_draw.cpp Code to draw pixels in each VGA mode, including PC-98
src/hardware/vga_gfx.cpp VGA GFX (0x3CE-0x3CF) emulation
src/hardware/vga_memory.cpp VGA RAM and RAM access emulation, video RAM allocation
src/hardware/vga_misc.cpp Misc VGA ports, including port 3DAh, 3C2h, 3CCh, 3CAh, 3C8h
src/hardware/vga_other.cpp Other emulation, including CGA functions
src/hardware/vga_paradise.cpp Paradise SVGA emulation
src/hardware/vga_s3.cpp S3 SVGA emulation
src/hardware/vga_seq.cpp VGA sequencer emulation
src/hardware/vga_tseng.cpp Tseng ET3000/ET4000 emulation
src/hardware/vga_xga.cpp VGA XGA emulation
src/hardware/vga_pc98_cg.cpp PC-98 CG (character generator) emulation
src/hardware/vga_pc98_crtc.cpp PC-98 CRTC emulation
src/hardware/vga_pc98_dac.cpp PC-98 DAC (palette) emulation
src/hardware/vga_pc98_egc.cpp PC-98 EGC (extended graphics charger) emulation
src/hardware/vga_pc98_gdc.cpp PC-98 GDC (graphics display controller) emulation
src/hardware/voodoo.cpp 3Dfx Voodoo emulation
src/hardware/voodoo_emu.cpp 3Dfx Voodoo emulation
src/hardware/voodoo_interface.cpp 3Dfx Voodoo emulation
src/hardware/voodoo_opengl.cpp 3Dfx Voodoo emulation
src/hardware/voodoo_vogl.cpp 3Dfx Voodoo emulation
src/hardware/glide.cpp 3Dfx Voodoo Glide emulation
src/hardware/pc98.cpp PC98UTIL.COM utility built-in command
src/hardware/pc98_fm.cpp PC-98 FM board emulation (ties DOSBox-X to emulation
code borrowed from Neko Project II)
src/hardware/snd_pc98/* PC-98 FM board emulation (code borrowed from
Neko Project II)
Tips for hacking and modifying the source code
----------------------------------------------
As a SDL (Simple Directmedia Layer) based application,
DOSBox-X starts execution from main(), which is either
the real main() function or a redefined main() function
called from SDLmain depending on the platform.
On Linux and macOS, main() is the real main function.
On Windows, main() is SDLmain() and is called from the
WinMain function defined in the SDL library.
The entry point main() is in src/gui/sdlmain.cpp,
somewhere closer to the bottom.
Configuration and control state (from dosbox-x.conf and
the command line) are accessible through a globally
scoped pointer named "control".
In the original DOSBox SVN project, "control" is
most often used for accessing the sections and
settings of dosbox.conf.
In DOSBox-X, "control" also holds flags and variables
gathered from the command line (such as -conf).
Most (though not all) of the sections and settings
are defined in src/dosbox.cpp. There is one function
DOSBox_SetupConfigSections() that adds sections and
settings.
Each section has a list of settings by name. Each
setting can be defined as an int, hexadecimal,
string, double, and multivalue item. Read
include/setup.h and src/misc/setup.cpp for more
information.
There is one section (the autoexec section) that
is defined as lines of text.
In the original DOSBox SVN project, each section
also has an init and destructor function. The
codebase in SVN is heavily written around emulator
setup from each section, which is why the order
of the sections is important. DOSBox-X eliminated
these init and destructor functions and encourages
initial setup from functions called in main(),
and additional setup/teardown through VM event
callbacks (see include/setup.h). A callback
mechanism is provided however (at a section level)
when settings change.
Most of the code in this codebase assumes that
it can retrieve a section by name, and a setting
by name, without checking whether the returned
referce to a setting is NULL. Therefore, removing
a setting or referring to settings before the
creation of them can cause this code to crash
until that reference is removed.
Warnings regarding C integer types
----------------------------------
Contrary to initial assumptions, never assume that int and long have specific
sizes. Even long long.
The general assumption is that int is 32 bit and long is 32 bit.
That is not always true, and that can get you in trouble when
working on this or other projects.
Another common problem is the use of integers for pointer manipulation.
Storing pointers or computing differences between pointers may happen
to work on 32-bit, where ints and pointers are the same size, but the
same code may break on 64-bit.
Therefore, for manipulating pointers, use uintptr_t instead of int or
long.
For quick reference, here is a breakdown of the development
targets and their sizes:
Windows (Microsoft C++) 32-bit:
sizeof(int) == 32-bit
sizeof(long) == 32-bit
sizeof(long long) == 64-bit
sizeof(uintptr_t) == 32-bit
Windows (Microsoft C++) 64-bit:
sizeof(int) == 32-bit
sizeof(long) == 32-bit
sizeof(long long) == 64-bit
sizeof(uintptr_t) == 64-bit
NOTE: If you ever intend to compile against older versions of Microsoft C++/Visual Studio,
the "long long" type will need to be replaced by __int64.
Linux 32-bit:
sizeof(int) == 32-bit
sizeof(long) == 32-bit
sizeof(long long) == 64-bit
sizeof(uintptr_t) == 32-bit
Linux 64-bit:
sizeof(int) == 32-bit
sizeof(long) == 64-bit
sizeof(long long) == 64-bit
sizeof(uintptr_t) == 64-bit
This code is written to assume that sizeof(int) >= 32-bit.
However know that there are platforms where sizeof(int) is
even smaller. In real-mode MS-DOS and 16-bit Windows for
example, sizeof(int) == 16 bits (2 bytes). DOSBox-X will
not target 16-bit DOS and Windows, so this is not a problem
so far.
For obvious reasons, far pointers are not supported. The
memory map of the runtime environment is assumed to be
flat with possible virtual memory and paging.
When working on this code, please understand the limits of
the integer type in the code you are writing to avoid
problems. Pick a data type that is large enough for the
expected range of input.
It is suggested to use C header constants if possible
for min and max integer values, like UINT_MAX.
If the code needs to operate with specific widths of
integer, please use data types like uint16_t, uint32_t,
int16_t and int32_t provided by modern C libraries, and
do not assume the width of int and long.
If compiling with older versions of Visual Studio, you will
need to include a header file to provide the uintptr_t and
uint32_t datatypes to fill in what is lacking in the C library.
When multiplying integers, overflow cases can be avoided
with a * b by rejecting the operation if b > (UINT_MAX / a)
or by multiplying a * b with a and b typecast to the next
largest datatype.
Remember that signed and unsigned integers have the same
width but the MSB changes the interpretation. This code
is written for processors (such as x86) where signed integers
are 2's complement. It will not work correctly with any
other type of signed integer.
2's complement means that the MSB bit of an integer indicates
the number is negative. When it is negative, the value could
be thought of as N - (2^sizeof_in_bits(int)). For a 16-bit
signed integer:
2^16 = 0x10000 = 65536
hex int unsigned int equiv
0x7FFE 32766 32766 32766 - 0
0x7FFF 32767 32767 32767 - 0
0x8000 -32768 32768 32768 - 65536
0x8001 -32767 32769 32769 - 65536
...
0xFFFE -2 65534 65534 - 65536
0xFFFF -1 65535 65535 - 65536
(carry, overflow all 16-bits, roll back to 0)
0x0000 0 0 0 - 0
0x0001 1 1 1 - 0
Another possible problem may lie in using negation (-) or
inverting all bits (~) of an integer for masking. The
result may be treated by the compiler as an integer. Make
sure to typecast it to clarify.
Another possible incompatiblity lies with printf() and
long long integers.
Always typecast the printf() parameters to the data type
intended to avoid problems and warnings.
While macOS and Linux have runtimes that can take %llu
or %llx, Microsoft's runtime in Windows cannot. Either
avoid printing long long integers or add conditional code
to use %llx or %llx on Linux and %I64u or %I64d on Windows.
Note that MinGW compilation on Windows suffers from the
same limitation due to use of Microsoft C runtime.
When dealing with sizes, including file I/O and byte counts,
use size_t (unsigned value) and ssize_t (signed value) instead.
This will help with using the C++ standard template library
and the C file I/O library. If compiling for a target where
read and write use int for a return value instead, then
use typecasting.
When handling file offsets, use off_t instead of long.
Modern C runtime versions of lseek and tell will use that
datatype. For older runtimes that use "long", make a typecast
in a header file for your target to declare off_t. Remember
that off_t is a signed value and that it can be negative.
Make sure to use the 64-bit version of lseek (often named
lseek64 or _lseeki64) in order to support files 4GB or
larger if allowed by the runtime environment.
On most modern runtimes, an alternate version of open()
may be required in order to open or create files larger
than 2GB. However the alternate open() reference can be
eliminated in certain cases.
On 32-bit Linux, direct calls to open64() can be avoided
if CFLAGS contains -D_FILE_OFFSET_BITS=64 or
#define _FILE_OFFSET_BITS=64 is added to the project.
Remember that lseek() can return -1 to indicate an error.
lseek() however will permit seeking past the end of a file.
writing at that point will extend the file to allow the
file write to occur at that offset. Depending on the platform,
that will either cause a sparse file (Linux + ext) or will
cause a loop within the filesystem driver to extend the file
and zero clusters to make it happen (Windows XP through 10).
Use of the FILE* file I/O layer is OK, but not recommended
unless there is a need to use text parsing with functions
like fgets() or fprintf(). For other uses, please use C
functions open, close, read, write, lseek and learn to use
file handles.
Understand that when fgets() returns with the buffer filled
with the line of text, the end of the string will always include
the newline (\n) that fgets() stopped reading at.
If fopen() was called with the "b" flag on DOS and Windows
formatted text files, the end of the string will probably
contain \r\n (CR LF). On platforms other than DOS and Windows,
\r\n will always appear if it is in the file.
C file handles are signed integers. They can be negative.
File handles returned by the C runtime however are never
negative except to indicate an error.
A good way to track whether an int holds an open file therefore,
is to initialize at startup that integer to -1, and then when
open succeeds, assign that value the file handle. When closing
the file, assign -1 to the integer to record that the handle was
closed.
Other parts of the code can also check if the file handle is
non-negative before operating on the file as a safety measure
against calling that function when the file was never opened.
On Windows, the HANDLE value at the Win32 API level can be obtained
from an integer file handle using _get_osfhandle() for use with
the Win32 API functions directly.
When using open(), make sure to use O_BINARY to avoid
CR/LF translation on DOS and Windows systems. Make sure
there is a header that defines O_BINARY as (0) if the
platform does not provide O_BINARY to avoid #ifdef's
around each open() call.
When using arithmetic with C pointers and integers,
understand that the pointer is adjusted by the value of the
integer times the size of the pointer type. If you intend
to adjust by bytes, then typecast the pointer to char* or
unsigned char* first, or typecast to uintptr_t to operate
on the pointer value as if an integer, then add the integer
value to the pointer.
At the lowest level, a pointer could be thought of as an
integer that is interepreted by the CPU as a memory address
to operate on, rather than an integer value directly.
Therefore, when adding an integer to a pointer value, the
result could be thought of as:
(new pointer value in bytes) = (current pointer value in bytes) + integer value * sizeof(pointer data type)
If the pointer is char, then adding 4 will advance by 4 bytes.
If the pointer is int, then adding 4 will advance by 4 * sizeof(int) bytes, or, 4 memory locations of type int.
Keep this in mind when manipulating pointers while working
on this code.
Time and cycles in DOSBox-X
---------------------------
Time is handled as a macro unit of 1ms time called "ticks",
tied heavily to SDL_GetTicks() to track time.
Within each 1ms tick, a cycle count specified by the user
is executed as CPU time.
Setting cycles=3000 therefore, instructs DOSBox and DOSBox-X
to execute 3000 CPU cycles per millisecond. That generally
means (though not always) that 3000 instructions are executed
per millisecond.
Other parts of emulation may consume additional CPU cycles
to simulate I/O or video RAM delay.
Normal_Loop() in src/dosbox.cpp controls per-tick execution
as directed by PIC_RunQueue() whether or not the 1ms tick
has completed.
Generally the CPU core will execute instructions for the
entire 1ms tick, but the loop will cut short if events
are scheduled to execute sooner.
Events are scheduled in src/hardware/timer.cpp, using
PIC_AddEvent() given a callback and a delay in milliseconds.
Scheduling an event will cut the CPU cycle count back to
enable the event to execute on time.
PIC_AddEvent() events are scheduled once. Periodic events
should call PIC_AddEvent() again within the callback. For
precision reasons, PIC_AddEvent() can identify whether it
is being called from an event callback, and it will use
the delta time differently to help periodic events maintain
regular intervals.
Events can be removed using PIC_RemoveEvents().
Per-tick event handlers can be added using the
TIMER_AddTickHandler() function in src/hardware/pic.cpp.
The callback will be called at the completion of the
1ms tick.
Emulator code can query emulator time at any time
using the functions in include/pic.h.
PIC_TickIndex() returns the time within the 1ms
tick as a floating point value from 0.0 to 1.0.
PIC_TickIndexND() returns the same as cycle counts
within the 1ms tick.
PIC_FullIndex() returns absolute emulator time
by combining ticks and cycle count time.
How DOSBox and DOSBox-X mix x86 and native code
-----------------------------------------------
Much of the DOS and BIOS handling in DOSBox and DOSBox-X
is done through the use of the "callback" instruction
and a callback system in src/cpu/callback.cpp.
Each BIOS interrupt is a callback, as is the DOS kernel
interrupts. INT 21h is handled as a callback to src/dos/dos.cpp
function DOS21_Handler(), for example. That native code
function can then manipulate CPU registers and memory as
needed to emulate the DOS call.
Some callback functions will also modify the stack frame
to set or clear specific CPU flags on return, using
functions CALLBACK_SCF(), CALLBACK_SZF(), and CALLBACK_SIF().
The callback instruction is 0xFE 0x38 <uint16_t>. This
is an invalid opcode on actual x86 hardware, but it is
a call into a callback function within the DOSBox