Adding DOSBox as core for DOS TASing (#4217)

* Adding dosbox

* Adding placeholder

* Adding initial placeholder for DOSBox

* update

* Update

* Update

* progress

* Progress

* Increasing mem capacity

* Progress

* Now running timer correctly

* Progress

* Stable

* Parsin inputs

* Keyboard working

* stable before using memfiles

* Now accepting rw hdds

* Hard disk rw working

* Fixing conflict

* Getting samples

* Reading samples but sounds too low

* Reading samples but sounds too low

* Now accepting multiple cdrom/floppy images

* Allowing swapping

* Enabling cdrom and disk swapping

* Simplifying

* Simplifying

* Simplifications

* Simplfiications

* Capturing sdl delay

* Adding configuration presets

* Enabling joystick

* Enabling joysticks

* Added mouse support

* Adding mouse support

* Progress with hard disk

* Adding default hard disk images and making them selectable

* Adding mnemonics, more configs, and some refactoring on the standard confs

* Processing file extensions

* Adding sram

* Adding saveram

* Adding drive lights

* Adding drive lights

* Adding memory domains

* Removing warnings

* Fixing warning

* Revert unrelated changes to Multi-Disk Bundler

* Re-alphabetise lists and clean up diff

* Missed a bit

* Make `DOSBox`' `ISaveRam` implementations `override`

* Fix `DOSBox`' `[PortedCore]`

* Clean up string comparisons in `DOSBox` ctor

* Set values for `WriteableHardDiskOptions` instead of translating

* Clean up reading of DOSBox config presets from embedded resources

* Fix code style warning

* Removing duped line

* Fixing extension parsing

* Small adjustments

* Aligning fps to that of normal DOS

* Aligning fps to that of normal DOS

* Simplified extension getting and adding base config file resource

* Remove unused import

* Properly measuring extended mem size

* Adding more settings and simplifying machine presets

* Adding check for SRAM size to prevent wrong-sized HD being loaded

* Removing unnecessary directive

* Update correct DOS framerate

* Adding sensible configuration presets

* Adding to the config preset description text

* Update src/BizHawk.Emulation.Common/Base Implementations/Bk2MnemonicLookup.cs

Co-authored-by: feos <vadosnaprimer@users.noreply.github.com>

* Removing stale config files

* Fixed mouse emulation

* Fixed mouse emulation

* Removing unused keyboard flag

* Addressing feos' comment about virtual height/width

* Fixed bug with saveram

* fix VirtualWidth

scanlines remain constant so they aren't stretched, and width is adjusted to be 4/3 of height, because video modes in DOS were designed for a 4:3 monitor. exact pixel shapes may slightly differ depending on exact pixel clock but setting 4:3 for DOS is standard.

* DependentUpon

* Making FPS configurable

* Making FPS configurable

* Adding fps num/denom

* Implementing proper fps numerator / denominator defaults for DOS

* Passing mouse deltas from bk

* Passing mouse deltas from bk to the core

* expose and use deltas directly

to make it work in hawk, one needs to bind RMouse X/Y for Mouse X/Y Delta in config.ini, by manually editing the file (for now)

* Implementing support for .cue+.bin and other cdrom types

* Fixing sensitivity

* Adjusting mouse sensitivity

* Fixing integration for windows

* [WIP] loading cds from bk

* [WIP] loading cds from bk

* Using .cdrom extension for cdroms, and passing disk name to the read callback

* Using .cdrom extension for cdroms, and passing disk name to the read callback

* Cleanup and fixing .iso loading and swapping

* Fixing .iso loading and cdrom swapping

* Adding default controllers

* Added callback for video updates to prevent tearing

* Removing unnecessary message

* Fix line endings in `Bk2MnemonicLookup.cs`

* Fix indentation

* Fix misc. whitespace crimes

* Drop redundant `<None Remove/>`

* More whitespace fixes

* More code style fixes

* Small fixes

* Fixing misc comments

* Adjusting naming

* Fixing values

* Removing dead code

* Clarifying the source of DOS framerate chosen

* Removing unused variable

* Removing duped assignments

* Fixing typo

* Removing no-longer required SRAM management

* Removing no longer required sram management functions

* Removing no-longer needed SRAM logic

* Fixing framerates as per feos's comment

* Passing init struct for a more tidy initialization. Also fixing identation for good

* Fixing hard landing on failure to load SRAM. This is needed to prevent crashes in dosbox when preserving hard disk contents

* Added missing submodule and artifact

* Reverting unnecessary change

* Removing no longer needd dosbox-iso extensions

* Removing no-longer necessary virtuals

* fix

* Adding lines into readme

* fixing indentation

* Reducing job concurrency for dosbox -- otherwise the server gets overloaded

* adding recursive submodule for dosbox-x

* Simplifying

* Simplifying

* Simplifying

* Simplifying

* Only offer drive switching if more than one drive is present

* Adding proper Disc identification for ISO9660 / Joliet (default target DOS)

* Adding CDROM case

* Moving comments to proper place

* Moving comments to proper place

* Code style fixes

* Clean up handling of Next Disc buttons

* Clean up `DOSBoxKeyboard` definition

* Remove redundant button mnemonic overrides

* remove leftover hack from my initial 2-byte range

it's hard to tell from upstream code what the range should be...

* Fixing mouse buttons getting stuck and aligning mouse speed minmaxes to what dosbox expects

* Removing default framerate for DOS

* set mouse speed range to match raw deltas range
(see 93bc50288f)

since this makes minimal mouse delta 1 now instead of 2 or 3 (they were different for x and y because ranges were different), I readjusted default sensitivity to match default turning in doom in upsteam

* fix casing on public fields
we use PublicField, _privateField, and localVariable casing

this commit also includes WIP to expose attoseconds like mame does, so that 1 value could be used to determine framerate, and movie parsers won't need too many changes to support DOS framerates

* fix num/denom values to match dosbox-x for when it launches into dos
video dump info was not super clear so I relied on values that are actually assigned to `fps` in `VGA_SetupDrawing()`

TODO: check other machines, update sync settings descriptions when we expose render fps info to user

* use an existing thing instead of GetFullName
it was copied from uae where I made it because I didn't know about `Path.GetFileName(rom.RomPath)`, it's now fixed in master too

increased message duration so user could read potentially long filenames (copied from uae too)

* Move init of new `MouseState` to top and eliminate locals

* fix naming for mouse states

* update submodules

* Adding function to get video refresh rate

* Adding report on video refresh rate update

* Revert "Merge branch 'dosbox' of github.com:SergioMartin86/BizHawk into dosbox"

This reverts commit e5b16a6307, reversing
changes made to ced12c51b4.

* Merge branch 'dosbox' of github.com:SergioMartin86/BizHawk into dosbox

* Removing unnecessary directive

* Fixing reboot

* fps notice formatting

* Zero init fps vals

* Using variable framerates

* Now accepting variable framerates as given by the core

* Moving ISO9660 detection lower

* Storing refresh rate in savestate -- update it on load if different

* fix GetFullName()

* Adding function to get number of ran cycles

* Adding ICycleTiming

* attoseconds are obsolete now

* fix loading CDs with spaces in their name

* Message duration needs to be left to the user to configure. Just passing a null

* Setting notify times back to 4 seconds cause these require a bit more time to read/understand

* Updating CycleCount from within wbx

* Simplifying cycle timing

* Removing FPS change notification, using default waiting times

* Updating submodule

* Fixing bug in disc swapping

* Adding drive selection functionality

* fixing period input

* Adding logic to present disc swapping operations from repeating when holding the button

* added defines for drive id

* point submodule to specific branch

---------

Co-authored-by: YoshiRulz <OSSYoshiRulz+git@gmail.com>
Co-authored-by: feos <vadosnaprimer@users.noreply.github.com>
Co-authored-by: feos <feykomylce@gmail.com>
This commit is contained in:
Sergio Martin 2025-04-20 15:19:38 +02:00 committed by GitHub
parent 770c2954b1
commit 236ff74b2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
47 changed files with 5229 additions and 10 deletions

View File

@ -37,6 +37,7 @@ jobs:
git submodule update --init uae/libretro-uae;
git submodule update --init stella/core;
git submodule update --init dsda/core;
git submodule update --init --recursive dosbox/dosbox-x;
- name: Install clang 18
run: wget https://apt.llvm.org/llvm.sh;
chmod u+x llvm.sh;
@ -61,6 +62,7 @@ jobs:
Assets/dll/ares64_interpreter.wbx.zst
Assets/dll/ares64_recompiler.wbx.zst
Assets/dll/bsnes.wbx.zst
Assets/dll/dosbox.wbx.zst
Assets/dll/dsda.wbx.zst
Assets/dll/faust.wbx.zst
Assets/dll/gpgx.wbx.zst

4
.gitmodules vendored
View File

@ -85,6 +85,10 @@
[submodule "ExternalProjects/FlooohChips/chips"]
path = ExternalProjects/FlooohChips/chips
url = https://github.com/floooh/chips.git
[submodule "waterbox/dosbox/dosbox-x"]
path = waterbox/dosbox/dosbox-x
url = https://github.com/TASEmulators/dosbox-x.git
branch = wbx
[submodule "waterbox/dsda/core"]
path = waterbox/dsda/core
url = https://github.com/TASEmulators/dsda-doom.git

View File

@ -1108,6 +1108,28 @@
"Mult": 1.0,
"Deadzone": 0.0
}
},
"DOSBox Controller": {
"Mouse Position X": {
"Value": "WMouse X",
"Mult": 1.0,
"Deadzone": 0.0
},
"Mouse Position Y": {
"Value": "WMouse Y",
"Mult": 1.0,
"Deadzone": 0.0
},
"Mouse Speed X": {
"Value": "RMouse X",
"Mult": 1.0,
"Deadzone": 0.0
},
"Mouse Speed Y": {
"Value": "RMouse Y",
"Mult": 1.0,
"Deadzone": 0.0
}
}
},
"AllTrollersFeedbacks": {

BIN
Assets/dll/dosbox.wbx.zst Normal file

Binary file not shown.

View File

@ -251,6 +251,10 @@ namespace BizHawk.Client.Common
}
switch (discType)
{
case DiscType.DOS:
game.System = VSystemID.Raw.DOS;
break;
case DiscType.SegaSaturn:
game.System = VSystemID.Raw.SAT;
break;
@ -998,6 +1002,8 @@ namespace BizHawk.Client.Common
public static readonly IReadOnlyCollection<string> Doom = new[] { "wad" };
public static readonly IReadOnlyCollection<string> DOS = new[] { "ima", "img", "xdf", "dmf", "fdd", "fdi", "nfd", "d88" };
public static readonly IReadOnlyCollection<string> GB = new[] { "gb", "gbc", "sgb" };
public static readonly IReadOnlyCollection<string> GBA = new[] { "gba" };
@ -1056,6 +1062,7 @@ namespace BizHawk.Client.Common
.Concat(C64)
.Concat(Coleco)
.Concat(Doom)
.Concat(DOS)
.Concat(GB)
.Concat(GBA)
.Concat(GEN)
@ -1099,6 +1106,7 @@ namespace BizHawk.Client.Common
new FilesystemFilter(/*VSystemID.Raw.C64*/"SID Commodore 64 Music File", Array.Empty<string>(), devBuildExtraExts: new[] { "sid" }, devBuildAddArchiveExts: true),
new FilesystemFilter(/*VSystemID.Raw.Coleco*/"ColecoVision", RomFileExtensions.Coleco, addArchiveExts: true),
new FilesystemFilter(/*VSystemID.Raw.Doom*/"Doom / Hexen / Heretic WAD File", RomFileExtensions.Doom),
new FilesystemFilter(/*VSystemID.Raw.DOS*/"DOS", RomFileExtensions.DOS),
new FilesystemFilter(/*VSystemID.Raw.GB*/"Gameboy", RomFileExtensions.GB.Concat(new[] { "gbs" }).ToList(), addArchiveExts: true),
new FilesystemFilter(/*VSystemID.Raw.GBA*/"Gameboy Advance", RomFileExtensions.GBA, addArchiveExts: true),
new FilesystemFilter(/*VSystemID.Raw.GEN*/"Genesis", RomFileExtensions.GEN.Concat(FilesystemFilter.DiscExtensions).ToList(), addArchiveExts: true),

View File

@ -20,6 +20,7 @@ using BizHawk.Emulation.Cores.Computers.Amiga;
using BizHawk.Emulation.Cores.Computers.AmstradCPC;
using BizHawk.Emulation.Cores.Computers.AppleII;
using BizHawk.Emulation.Cores.Computers.Commodore64;
using BizHawk.Emulation.Cores.Computers.DOS;
using BizHawk.Emulation.Cores.Computers.Doom;
using BizHawk.Emulation.Cores.Computers.MSX;
using BizHawk.Emulation.Cores.Computers.SinclairSpectrum;
@ -1192,6 +1193,9 @@ namespace BizHawk.Client.EmuHawk
// Cygne
items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Cygne, CreateGenericCoreConfigItem<WonderSwan>(CoreNames.Cygne)));
// DOSBox
items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.DOSBox, CreateGenericCoreConfigItem<DOSBox>(CoreNames.DOSBox)));
// DSDA-Doom
items.Add(CreateCoreSubmenu(VSystemCategory.Other, CoreNames.DSDA, CreateGenericCoreConfigItem<DSDA>(CoreNames.DSDA)));

View File

@ -28,6 +28,7 @@ using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores;
using BizHawk.Emulation.Cores.Computers.AppleII;
using BizHawk.Emulation.Cores.Computers.Commodore64;
using BizHawk.Emulation.Cores.Computers.DOS;
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
using BizHawk.Emulation.Cores.Consoles.SNK;
using BizHawk.Emulation.Cores.Nintendo.GBA;
@ -2024,7 +2025,7 @@ namespace BizHawk.Client.EmuHawk
byte[] sram;
// some cores might not know how big the saveram ought to be, so just send it the whole file
if (Emulator is AppleII or C64 or MGBAHawk or NeoGeoPort or NES { BoardName: "FDS" })
if (Emulator is AppleII or C64 or DOSBox or MGBAHawk or NeoGeoPort or NES { BoardName: "FDS" })
{
sram = File.ReadAllBytes(saveRamPath);
}

View File

@ -39,6 +39,7 @@ namespace BizHawk.Client.EmuHawk
VSystemID.Raw.Arcade,
VSystemID.Raw.C64,
VSystemID.Raw.Doom,
VSystemID.Raw.DOS,
VSystemID.Raw.GBL,
VSystemID.Raw.GEN,
VSystemID.Raw.GGL,

View File

@ -856,6 +856,90 @@ namespace BizHawk.Emulation.Common
["Weapon Select 6"] = '6',
["Weapon Select 7"] = '7',
},
[VSystemID.Raw.DOS] = new()
{
["Joystick Button 1"] = '1',
["Joystick Button 2"] = '2',
["Joystick Up"] = 'U',
["Joystick Down"] = 'D',
["Joystick Left"] = 'L',
["Joystick Right"] = 'R',
["Mouse Left Button"] = 'l',
["Mouse Middle Button"] = 'm',
["Mouse Right Button"] = 'r',
["Previous Floppy Disk"] = '<',
["Next Floppy Disk"] = '>',
["Swap Floppy Disk"] = 'v',
["Previous CDROM"] = '{',
["Next CDROM"] = '}',
["Swap CDROM"] = 'w',
["F1"] = 'F',
["F2"] = 'F',
["F3"] = 'F',
["F4"] = 'F',
["F5"] = 'F',
["F6"] = 'F',
["F7"] = 'F',
["F8"] = 'F',
["F9"] = 'F',
["F10"] = 'F',
["F11"] = 'F',
["F12"] = 'F',
["Escape"] = 'e',
["Tab"] = 't',
["Backspace"] = 'b',
["Enter"] = 'e',
["Space"] = 's',
["LeftAlt"] = 'a',
["RightAlt"] = 'a',
["LeftCtrl"] = 'c',
["RightCtrl"] = 'c',
["LeftShift"] = 's',
["RightShift"] = 's',
["CapsLock"] = 'C',
["ScrollLock"] = 'S',
["NumLock"] = 'N',
["Grave"] = '`',
["Minus"] = '-',
["Equals"] = '=',
["Backslash"] = 'b',
["LeftBracket"] = '[',
["RightBracket"] = ']',
["Semicolon"] = ';',
["Quote"] = '\'',
["Period"] = 'p', // because '.' represents no input
["Comma"] = ',',
["Slash"] = '/',
["ExtraLtGt"] = '>',
["PrintScreen"] = 'p',
["Pause"] = 'p',
["Insert"] = 'i',
["Home"] = 'h',
["Pageup"] = 'p',
["Delete"] = 'd',
["End"] = 'e',
["Pagedown"] = 'p',
["Left"] = 'l',
["Up"] = 'u',
["Down"] = 'd',
["Right"] = 'r',
["Keypad1"] = '1',
["Keypad2"] = '2',
["KeyPad3"] = '3',
["KeyPad4"] = '4',
["KeyPad5"] = '5',
["KeyPad6"] = '6',
["KeyPad7"] = '7',
["KeyPad8"] = '8',
["KeyPad9"] = '9',
["KeyPad0"] = '0',
["KeyPadDivide"] = '/',
["KeyPadMultiply"] = '*',
["KeyPadMinus"] = '-',
["keyPadPlus"] = '+',
["KeyPadEnter"] = 'e',
["KeyPadPeriod"] = '.',
}
};
private static readonly Dictionary<string, string> BaseAxisLookupTable = new Dictionary<string, string>

View File

@ -463,6 +463,10 @@ namespace BizHawk.Emulation.Common
game.System = VSystemID.Raw.Amiga;
break;
case ".D88" or ".DMF" or ".FDD" /*or ".FDI"*/ or ".IMA" or ".IMG" or ".NFD" or ".XDF":
game.System = VSystemID.Raw.DOS;
break;
case ".IPF":
var ipfId = new IpfIdentifier(romData);
game.System = ipfId.IdentifiedSystem;

View File

@ -27,6 +27,7 @@ namespace BizHawk.Emulation.Common
[VSystemID.Raw.Coleco] = "ColecoVision",
// DEBUG
[VSystemID.Raw.Doom] = "Doom",
[VSystemID.Raw.DOS] = "DOS",
[VSystemID.Raw.GBL] = "Game Boy Link",
[VSystemID.Raw.GB] = "GB",
[VSystemID.Raw.SGB] = "SGB",

View File

@ -25,6 +25,7 @@ namespace BizHawk.Emulation.Common
public const string Coleco = "Coleco";
public const string DEBUG = "DEBUG";
public const string Doom = "Doom";
public const string DOS = "DOS";
public const string Dreamcast = "Dreamcast";
public const string GameCube = "GameCube";
public const string GB = "GB";

View File

@ -26,6 +26,7 @@
<Compile Update="Computers/AppleII/AppleII.*.cs" DependentUpon="AppleII.cs" />
<Compile Update="Computers/Commodore64/C64.*.cs" DependentUpon="C64.cs" />
<Compile Update="Computers/Doom/DSDA.*.cs" DependentUpon="DSDA.cs" />
<Compile Update="Computers/DOS/DOSBox.*.cs" DependentUpon="DOSBox.cs" />
<Compile Update="Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.*.cs" DependentUpon="NECUPD765.cs" />
<Compile Update="Computers/SinclairSpectrum/Hardware/Disk/NECUPS765.Static.cs" DependentUpon="NECUPD765.cs" />
<Compile Update="Computers/SinclairSpectrum/Machine/Pentagon128K/Pentagon128.*.cs" DependentUpon="Pentagon128.cs" />

View File

@ -0,0 +1,143 @@
using System.Collections.Generic;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.DOS
{
public partial class DOSBox
{
// A class to store the current state of the mouse for delta and button activation calculation
private class MouseState
{
public int PosX = 0;
public int PosY = 0;
public bool LeftButtonHeld = false;
public bool MiddleButtonHeld = false;
public bool RightButtonHeld = false;
}
private MouseState _lastMouseState = new MouseState();
private static readonly (string Name, LibDOSBox.DOSBoxKeyboard Key)[] _keyboardMap = CreateKeyboardMap();
private static (string Name, LibDOSBox.DOSBoxKeyboard Value)[] CreateKeyboardMap()
{
var keyboardMap = new List<(string, LibDOSBox.DOSBoxKeyboard)>();
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var k in Enum.GetValues(typeof(LibDOSBox.DOSBoxKeyboard)))
{
if (k is LibDOSBox.DOSBoxKeyboard.Key_None) continue;
var name = Enum.GetName(typeof(LibDOSBox.DOSBoxKeyboard), k)!.Replace('_', ' ');
keyboardMap.Add((name, (LibDOSBox.DOSBoxKeyboard) k));
}
return keyboardMap.ToArray();
}
private static ControllerDefinition CreateControllerDefinition(SyncSettings settings, int floppyDiskCount, int cdROMCount)
{
var controller = new ControllerDefinition("DOSBox Controller");
// Adding joystick buttons
if (settings.EnableJoystick1)
{
foreach (var button in JoystickButtonCollection)
{
controller.BoolButtons.Add("P1 " + Inputs.Joystick + " " + button);
}
}
if (settings.EnableJoystick2)
{
foreach (var button in JoystickButtonCollection)
{
controller.BoolButtons.Add("P2 " + Inputs.Joystick + " " + button);
}
}
// Adding mouse inputs
if (settings.EnableMouse)
{
controller.BoolButtons.Add(Inputs.Mouse + " " + MouseInputs.LeftButton);
controller.BoolButtons.Add(Inputs.Mouse + " " + MouseInputs.MiddleButton);
controller.BoolButtons.Add(Inputs.Mouse + " " + MouseInputs.RightButton);
// Although most apps (including windows) use speed to compute the mouse position, some games (SimCity) use the absolute value
// The absolute values needs to be 1:1 with the video size, as this is translated 1:1 to the core.
// The effect is that the position on BK's window translates perfectly to the core
controller.AddAxis(Inputs.Mouse + " " + MouseInputs.PosX, (0).RangeTo(LibDOSBox.SVGA_MAX_WIDTH), LibDOSBox.SVGA_MAX_WIDTH / 2);
controller.AddAxis(Inputs.Mouse + " " + MouseInputs.PosY, (0).RangeTo(LibDOSBox.SVGA_MAX_HEIGHT), LibDOSBox.SVGA_MAX_HEIGHT / 2);
// Range above 180 results in minimal mouse movement values bigger than 1, and we need 1 as a basis before sensitivity is applied
// To adjust sensitivity, use the corresponding sync setting (global sensitivity for raw deltas is a TODO)
controller.AddAxis(Inputs.Mouse + " " + MouseInputs.SpeedX, (-180).RangeTo(180), 0);
controller.AddAxis(Inputs.Mouse + " " + MouseInputs.SpeedY, (-180).RangeTo(180), 0);
}
// Adding drive management buttons
if (floppyDiskCount > 1)
{
controller.BoolButtons.Add(Inputs.PrevFloppyDisk);
controller.BoolButtons.Add(Inputs.NextFloppyDisk);
controller.BoolButtons.Add(Inputs.SwapFloppyDisk);
}
if (cdROMCount > 1)
{
controller.BoolButtons.Add(Inputs.PrevCDROM);
controller.BoolButtons.Add(Inputs.NextCDROM);
controller.BoolButtons.Add(Inputs.SwapCDROM);
}
foreach (var (name, _) in _keyboardMap)
{
controller.BoolButtons.Add(name);
controller.CategoryLabels[name] = "Keyboard";
}
return controller.MakeImmutable();
}
private static string[] JoystickButtonCollection = [
JoystickButtons.Up,
JoystickButtons.Down,
JoystickButtons.Left,
JoystickButtons.Right,
JoystickButtons.Button1,
JoystickButtons.Button2
];
private static class JoystickButtons
{
public const string Up = "Up";
public const string Down = "Down";
public const string Left = "Left";
public const string Right = "Right";
public const string Button1 = "Button 1";
public const string Button2 = "Button 2";
}
private static class MouseInputs
{
public const string LeftButton = "Left Button";
public const string RightButton = "Right Button";
public const string MiddleButton = "Middle Button";
public const string PosX = "Position X";
public const string PosY = "Position Y";
public const string SpeedX = "Speed X"; // How many pixels has it changed in a single frame
public const string SpeedY = "Speed Y";
}
private static class Inputs
{
public const string Joystick = "Joystick";
public const string Mouse = "Mouse";
public const string PrevFloppyDisk = "Previous Floppy Disk";
public const string NextFloppyDisk = "Next Floppy Disk";
public const string SwapFloppyDisk = "Swap Floppy Disk";
public const string PrevCDROM = "Previous CDROM";
public const string NextCDROM = "Next CDROM";
public const string SwapCDROM = "Swap CDROM";
}
}
}

View File

@ -0,0 +1,10 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.DOS
{
public partial class DOSBox : ICycleTiming
{
// DOSBox emulates the internal core at stable 1ms increments, regardless of the configuration. Therefore, this is basis for time calculation.
public double ClockRate => 1000.0;
}
}

View File

@ -0,0 +1,11 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.DOS
{
public partial class DOSBox : IDriveLight
{
public bool DriveLightEnabled { get; private set; }
public bool DriveLightOn { get; private set; }
public string DriveLightIconDescription => "Drive Activity";
}
}

View File

@ -0,0 +1,295 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.DOS
{
public partial class DOSBox : ISettable<object, DOSBox.SyncSettings>
{
public enum ConfigurationPreset
{
[Display(Name = "[1981] IBM XT 5150 (4.77Mhz, 256kb RAM, Monochrome, PC Speaker)")]
_1981_IBM_5150,
[Display(Name = "[1983] IBM XT 5160 (4.77Mhz, 640kb RAM, CGA, PC Speaker)")]
_1983_IBM_5160,
[Display(Name = "[1986] IBM XT 286 5162-286 (6Mhz, 640kb RAM, EGA, PC Speaker)")]
_1986_IBM_5162,
[Display(Name = "[1987] IBM PS/2 25 (8Mhz, 640kb RAM, MCGA, Game Blaster)")]
_1987_IBM_PS2_25,
[Display(Name = "[1990] IBM PS/2 25 286 (10Mhz, 4Mb RAM, VGA, Sound Blaster 1)")]
_1990_IBM_PS2_25_286,
[Display(Name = "[1991] IBM PS/2 25 386 (25Mhz, 6Mb RAM, VGA, Sound Blaster 2)")]
_1991_IBM_PS2_25_386,
[Display(Name = "[1993] IBM PS/2 53 SLC2 486 (50Mhz, 64Mb RAM, SVGA, Sound Blaster Pro 2)")]
_1993_IBM_PS2_53_SLC2_486,
[Display(Name = "[1994] IBM PS/2 76i SLC2 486 (100Mhz, 64Mb RAM, SVGA, Sound Blaster 16)")]
_1994_IBM_PS2_76i_SLC2_486,
[Display(Name = "[1997] IBM Aptiva 2140 (233Mhz, 96Mb RAM, SVGA + 3D Support, Sound Blaster 16)")]
_1997_IBM_APTIVA_2140,
[Display(Name = "[1999] IBM Thinkpad 240 (300Mhz, 128Mb, SVGA + 3D Support , Sound Blaster 16) ")]
_1999_IBM_THINKPAD_240,
}
/// <remarks>values are the actual size in bytes for each hdd selection</remarks>
public enum WriteableHardDiskOptions : ulong
{
None = 0UL,
[Display(Name = "21Mb (FAT16)")]
FAT16_21Mb = 21411840UL,
[Display(Name = "41Mb (FAT16)")]
FAT16_41Mb = 42823680UL,
[Display(Name = "241Mb (FAT16)")]
FAT16_241Mb = 252370944UL,
[Display(Name = "504Mb (FAT16)")]
FAT16_504Mb = 527966208UL,
[Display(Name = "2014Mb (FAT16)")]
FAT16_2014Mb = 2111864832UL,
[Display(Name = "4091Mb (FAT32)")]
FAT32_4091Mb = 4289725440UL,
}
public enum MachineType
{
Auto,
[Display(Name = "MDA")]
mda,
[Display(Name = "CGA")]
cga,
[Display(Name = "CGA Mono")]
cga_mono,
[Display(Name = "CGA RGB")]
cga_rgb,
[Display(Name = "CGA Composite")]
cga_composite,
[Display(Name = "CGA Composite 2")]
cga_composite2,
[Display(Name = "Hercules")]
hercules,
[Display(Name = "Hercules Plus")]
hercules_plus,
[Display(Name = "Hercules InColor")]
hercules_incolor,
[Display(Name = "Hercules Color")]
hercules_color,
[Display(Name = "Tandy")]
tandy,
[Display(Name = "PCjr")]
pcjr,
[Display(Name = "PCjr Composite")]
pcjr_composite,
[Display(Name = "PCjr Composite 2")]
pcjr_composite2,
[Display(Name = "Amstrad")]
amstrad,
[Display(Name = "EGA")]
ega,
[Display(Name = "EGA 200")]
ega200,
[Display(Name = "JEGA")]
jega,
[Display(Name = "MCGA")]
mcga,
[Display(Name = "VGA Only")]
vgaonly,
[Display(Name = "SVGA S3")]
svga_s3,
[Display(Name = "SVGA S3 386 C928")]
svga_s386c928,
[Display(Name = "SVGA S3 Vision 864")]
svga_s3vision864,
[Display(Name = "SVGA S3 Vision 868")]
svga_s3vision868,
[Display(Name = "SVGA S3 Vision 964")]
svga_s3vision964,
[Display(Name = "SVGA S3 Vision 968")]
svga_s3vision968,
[Display(Name = "SVGA S3 Trio 32")]
svga_s3trio32,
[Display(Name = "SVGA S3 Trio 64")]
svga_s3trio64,
[Display(Name = "SVGA S3 Trio 64 VP")]
svga_s3trio64vP,
[Display(Name = "SVGA S3 Virge")]
svga_s3virge,
[Display(Name = "SVGA S3 Virge VX")]
svga_s3virgevx,
[Display(Name = "SVGA Tseng Labs ET3000")]
svga_et3000,
[Display(Name = "SVGA Tseng Labs ET4000")]
svga_et4000,
[Display(Name = "SVGA Paradise")]
svga_paradise,
[Display(Name = "VESA No LFB")]
vesa_nolfb,
[Display(Name = "VESA Old VBE")]
vesa_oldvbe,
[Display(Name = "VESA Old VBE 10")]
vesa_oldvbe10,
[Display(Name = "PC98")]
pc98,
[Display(Name = "PC9801")]
pc9801,
[Display(Name = "PC9821")]
pc9821,
[Display(Name = "SVGA ATI EGA/VGA Wonder")]
svga_ati_egavgawonder,
[Display(Name = "SVGA ATI VGA Wonder")]
svga_ati_vgawonder,
[Display(Name = "SVGA ATI VGA Wonder Plus")]
svga_ati_vgawonderplus,
[Display(Name = "SVGA ATI VGA Wonder XL")]
svga_ati_vgawonderxl,
[Display(Name = "SVGA ATI VGA Wonder XL24")]
svga_ati_vgawonderxl24,
[Display(Name = "SVGA ATI Mach 8")]
svga_ati_mach8,
[Display(Name = "SVGA ATI Mach 32")]
svga_ati_mach32,
[Display(Name = "SVGA ATI Mach 64")]
svga_ati_mach64,
[Display(Name = "FM Towns")]
fm_towns
}
public enum SoundBlasterModel
{
Auto,
[Display(Name = "None")]
none,
[Display(Name = "Sound Blaster")]
sb1,
[Display(Name = "Sound Blaster 2")]
sb2,
[Display(Name = "Sound Blaster Pro")]
sbpro1,
[Display(Name = "Sound Blaster Pro 2")]
sbpro2,
[Display(Name = "Sound Blaster 16")]
sb16,
[Display(Name = "Sound Blaster Vibra")]
sb16vibra,
[Display(Name = "Game Blaster")]
gb,
[Display(Name = "ESS688")]
ess688,
[Display(Name = "Reveal SC400")]
reveal_sc400
}
public enum PCSpeaker : int
{
Auto = -1,
Disabled = 0,
Enabled = 1,
}
public object GetSettings() => null;
public PutSettingsDirtyBits PutSettings(object o) => PutSettingsDirtyBits.None;
private SyncSettings _syncSettings;
public SyncSettings GetSyncSettings()
=> _syncSettings.Clone();
public PutSettingsDirtyBits PutSyncSettings(SyncSettings o)
{
var ret = SyncSettings.NeedsReboot(_syncSettings, o);
_syncSettings = o;
return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None;
}
[CoreSettings]
public class SyncSettings
{
[DisplayName("Configuration Preset")]
[Description("Establishes a base configuration for DOSBox roughly corresponding to the selected computer model. We recommend choosing a model that is roughly of the same year or above of the game / tool you plan to run. More modern models may require more CPU power to emulate.")]
[DefaultValue(ConfigurationPreset._1993_IBM_PS2_53_SLC2_486)]
[TypeConverter(typeof(DescribableEnumConverter))]
public ConfigurationPreset ConfigurationPreset { get; set; }
[DisplayName("Enable Joystick 1")]
[Description("Determines whether a joystick will be plugged in the IBM PC Gameport 1")]
[DefaultValue(true)]
public bool EnableJoystick1 { get; set; }
[DisplayName("Enable Joystick 2")]
[Description("Determines whether a joystick will be plugged in the IBM PC Gameport 2")]
[DefaultValue(true)]
public bool EnableJoystick2 { get; set; }
[DisplayName("Enable Mouse")]
[Description("Determines whether a mouse will be plugged in")]
[DefaultValue(true)]
public bool EnableMouse { get; set; }
[DisplayName("Mouse Sensitivity")]
[Description("Adjusts the mouse relative speed (mickey) multiplier.")]
[DefaultValue(3.0)]
public float MouseSensitivity { get; set; }
[DisplayName("Mount Writeable Hard Disk Drive")]
[Description("Determines whether to mount an empty writable formatted hard disk in drive C:. This hard disk will be fully located in memory so make sure you have enough RAM available. Its contents can be saved and loaded as SaveRAM (can be slow).")]
[DefaultValue(WriteableHardDiskOptions.FAT16_241Mb)]
[TypeConverter(typeof(DescribableEnumConverter))]
public WriteableHardDiskOptions WriteableHardDisk { get; set; }
[DisplayName("Preserve Hard Disk Contents")]
[Description("Determines whether to store the contents of the writeable hard disk as SaveRAM to be reloaded on the next start. Enabling this option may cause the core to take some seconds to store and load the SRAM upon restart, depending on the size of the hard disk. If it is disabled, previous SaveRAM will not be loaded.")]
[DefaultValue(false)]
public bool PreserveHardDiskContents { get; set; }
[DisplayName("Force FPS Numerator")]
[Description("Forces a numerator for FPS: how many Bizhawk frames to run per second of emulation. We recommend leaving this value unmodified, to follow the core's own video refresh rate. You can set it higher if you need finer subframe inputs, and; lower, in case your game runs in lower FPS and it feels more natural.")]
[DefaultValue(0)]
public int forceFPSNumerator { get; set; }
[DisplayName("Force FPS Denominator")]
[Description("Forces denominator for FPS: how many Bizhawk frames to run per second of emulation. We recommend leaving this value unmodified, to follow the core's own video refresh rate. You can set it lower if you need finer subframe inputs, and; higher, in case your game runs in lower FPS and it feels more natural.")]
[DefaultValue(0)]
public int forceFPSDenominator { get; set; }
[DisplayName("CPU Cycles")]
[Description("How many CPU cycles to emulate per ms. Default: -1, to keep the one included in the configuration preset.")]
[DefaultValue(-1)]
public int CPUCycles { get; set; }
[DisplayName("Machine Type")]
[Description("Chooses the machine type (CPU/GPU) to emulate. Auto uses the configuration preset's default.")]
[TypeConverter(typeof(DescribableEnumConverter))]
[DefaultValue(MachineType.Auto)]
public MachineType MachineType { get; set; }
[DisplayName("RAM Size (Mb)")]
[Description("The size of the memory capacity (RAM) to emulate. -1 to keep the value for the machine preset")]
[DefaultValue(-1)]
public int RAMSize { get; set; }
[DisplayName("PC Speaker")]
[Description("Chooses the whether to enable/disable the PC Speaker. Auto uses the configuration preset's default.")]
[TypeConverter(typeof(DescribableEnumConverter))]
[DefaultValue(PCSpeaker.Auto)]
public PCSpeaker PCSpeaker { get; set; }
[DisplayName("Sound Blaster Model")]
[Description("Chooses the Sound Blaster model to emulate. Auto uses the configuration preset's default.")]
[TypeConverter(typeof(DescribableEnumConverter))]
[DefaultValue(SoundBlasterModel.Auto)]
public SoundBlasterModel SoundBlasterModel { get; set; }
[DisplayName("Sound Blaster IRQ")]
[Description("Chooses the interrupt request number for the Sound Blaster. -1 for automatic.")]
[DefaultValue(-1)]
public int SoundBlasterIRQ { get; set; }
public SyncSettings()
=> SettingsUtil.SetDefaultValues(this);
public SyncSettings Clone()
=> (SyncSettings) MemberwiseClone();
public static bool NeedsReboot(SyncSettings x, SyncSettings y)
=> !DeepEquality.DeepEquals(x, y);
}
}
}

View File

@ -0,0 +1,570 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using BizHawk.Common;
using BizHawk.Common.StringExtensions;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Properties;
using BizHawk.Emulation.Cores.Waterbox;
using BizHawk.Emulation.DiscSystem;
namespace BizHawk.Emulation.Cores.Computers.DOS
{
[PortedCore(
name: CoreNames.DOSBox,
author: "Jonathan Campbell et al.",
portedVersion: "2025.02.01 (324193b)",
portedUrl: "https://github.com/joncampbell123/dosbox-x",
isReleased: false)]
public partial class DOSBox : WaterboxCore
{
private static readonly Configuration DefaultConfig = new Configuration
{
SystemId = VSystemID.Raw.DOS,
MaxSamples = 8 * 1024,
DefaultWidth = LibDOSBox.VGA_MAX_WIDTH,
DefaultHeight = LibDOSBox.VGA_MAX_HEIGHT,
MaxWidth = LibDOSBox.SVGA_MAX_WIDTH,
MaxHeight = LibDOSBox.SVGA_MAX_HEIGHT,
DefaultFpsNumerator = LibDOSBox.DEFAULT_FRAMERATE_NUMERATOR_DOS,
DefaultFpsDenominator = LibDOSBox.DEFAULT_FRAMERATE_DENOMINATOR_DOS
};
private LibDOSBox _libDOSBox;
private readonly List<IRomAsset> _floppyDiskAssets;
private readonly List<IDiscAsset> _discAssets;
// Drive management variables
private List<IRomAsset> _floppyDiskImageFiles = new List<IRomAsset>();
private int _floppyDiskCount = 0;
private int _currentFloppyDisk = 0;
private int _currentCDROM = 0;
private string GetFullName(IRomAsset rom) => Path.GetFileName(rom.RomPath.SubstringAfter('|'));
// CD Handling logic
private List<string> _cdRomFileNames = new List<string>();
private Dictionary<string, DiscSectorReader> _cdRomFileToReaderMap = new Dictionary<string, DiscSectorReader>();
private readonly LibDOSBox.CDReadCallback _CDReadCallback;
public override int VirtualWidth => BufferHeight * 4 / 3;
// Image selection / swapping variables
[CoreConstructor(VSystemID.Raw.DOS)]
public DOSBox(CoreLoadParameters<object, SyncSettings> lp)
: base(lp.Comm, DefaultConfig)
{
_floppyDiskAssets = lp.Roms;
_discAssets = lp.Discs;
_syncSettings = lp.SyncSettings ?? new();
DriveLightEnabled = false;
ControllerDefinition = CreateControllerDefinition(_syncSettings, _floppyDiskAssets.Count, _discAssets.Count);
// Parsing input files
var ConfigFiles = new List<IRomAsset>();
// Parsing rom files
foreach (var file in _floppyDiskAssets)
{
var ext = Path.GetExtension(file.RomPath);
bool recognized = false;
// Checking for supported floppy disk extensions
if (ext is ".ima" or ".img" or ".xdf" or ".dmf" or ".fdd" or ".fdi" or ".nfd" or ".d88")
{
_floppyDiskImageFiles.Add(file);
recognized = true;
}
// Checking for DOSBox-x config files
else if (ext is ".conf")
{
ConfigFiles.Add(file);
recognized = true;
}
if (!recognized) throw new Exception($"Unrecognized input file provided: '{file.RomPath}'");
}
var writableHDDImageFileSize = (ulong) _syncSettings.WriteableHardDisk;
_CDReadCallback = CDRead;
_libDOSBox = PreInit<LibDOSBox>(new WaterboxOptions
{
Filename = "dosbox.wbx",
SbrkHeapSizeKB = 32 * 1024,
SealedHeapSizeKB = 32 * 1024,
InvisibleHeapSizeKB = 1024,
PlainHeapSizeKB = 32 * 1024,
MmapHeapSizeKB = 256 * 1024 + (uint) (writableHDDImageFileSize / 1024ul),
SkipCoreConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck),
SkipMemoryConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck),
}, new Delegate[] { _CDReadCallback });
////// CD Loading Logic Start
_libDOSBox.SetCdCallbacks(_CDReadCallback);
// Processing each disc
int curDiscIndex = 0;
for (var discIdx = 0; discIdx < _discAssets.Count; discIdx++)
{
// Creating file name to pass to dosbox
var cdRomFileName = $"{FileNames.CD}{discIdx}.cdrom";
// Getting disc data structure
var CDDataStruct = GetCDDataStruct(_discAssets[discIdx].DiscData);
Console.WriteLine($"[CD] Adding Disc {discIdx}: '{_discAssets[discIdx].DiscName}' as '{cdRomFileName}' with sector count: {CDDataStruct.End}, track count: {CDDataStruct.Last}.");
// Adding file name to list
_cdRomFileNames.Add(cdRomFileName);
// Creating reader
var discSectorReader = new DiscSectorReader(_discAssets[discIdx].DiscData);
// Adding reader to map
_cdRomFileToReaderMap[cdRomFileName] = discSectorReader;
// Passing CD Data to the core
_libDOSBox.pushCDData(curDiscIndex, CDDataStruct.End, CDDataStruct.Last);
// Passing track data to the core
for (var trackIdx = 0; trackIdx < CDDataStruct.Last; trackIdx++) _libDOSBox.pushTrackData(curDiscIndex, trackIdx, CDDataStruct.Tracks[trackIdx]);
}
////// CD Loading Logic End
// Getting base config file
var configString = Encoding.UTF8.GetString(Resources.DOSBOX_CONF_BASE.Value);
configString += "\n";
// Getting selected machine preset config file
configString += Encoding.UTF8.GetString(_syncSettings.ConfigurationPreset switch
{
ConfigurationPreset._1981_IBM_5150 => Resources.DOSBOX_CONF_1981_IBM_5150.Value,
ConfigurationPreset._1983_IBM_5160 => Resources.DOSBOX_CONF_1983_IBM_5160.Value,
ConfigurationPreset._1986_IBM_5162 => Resources.DOSBOX_CONF_1986_IBM_5162.Value,
ConfigurationPreset._1987_IBM_PS2_25 => Resources.DOSBOX_CONF_1987_IBM_PS2_25.Value,
ConfigurationPreset._1990_IBM_PS2_25_286 => Resources.DOSBOX_CONF_1990_IBM_PS2_25_286.Value,
ConfigurationPreset._1991_IBM_PS2_25_386 => Resources.DOSBOX_CONF_1991_IBM_PS2_25_386.Value,
ConfigurationPreset._1993_IBM_PS2_53_SLC2_486 => Resources.DOSBOX_CONF_1993_IBM_PS2_53_SLC2_486.Value,
ConfigurationPreset._1994_IBM_PS2_76i_SLC2_486 => Resources.DOSBOX_CONF_1994_IBM_PS2_76i_SLC2_486.Value,
ConfigurationPreset._1997_IBM_APTIVA_2140 => Resources.DOSBOX_CONF_1997_IBM_APTIVA_2140.Value,
ConfigurationPreset._1999_IBM_THINKPAD_240 => Resources.DOSBOX_CONF_1999_IBM_THINKPAD_240.Value,
_ => [ ]
});
configString += "\n";
// Adding joystick configuration
configString += "[joystick]\n";
if (_syncSettings.EnableJoystick1 || _syncSettings.EnableJoystick2) configString += "joysticktype = 2axis\n";
else configString += "joysticktype = none\n";
// Adding PC Speaker
configString += "[speaker]\n";
if (_syncSettings.PCSpeaker != PCSpeaker.Auto) configString += $"pcspeaker = {_syncSettings.PCSpeaker}\n";
configString += "\n";
// Adding sound blaser configuration
configString += "[sblaster]\n";
if (_syncSettings.SoundBlasterModel != SoundBlasterModel.Auto) configString += $"sbtype = {_syncSettings.SoundBlasterModel}\n";
if (_syncSettings.SoundBlasterIRQ != -1) configString += $"irq = {_syncSettings.SoundBlasterIRQ}\n";
configString += "\n";
// Adding memory size configuration
configString += "[dosbox]\n";
if (_syncSettings.RAMSize != -1) configString += $"memsize = {_syncSettings.RAMSize}\n";
configString += "\n";
// Adding autoexec line
configString += "[autoexec]\n";
configString += "@echo off\n";
////// Floppy disks: Mounting and appending mounting lines
string floppyMountLine = "imgmount a ";
foreach (var file in _floppyDiskImageFiles)
{
string floppyNewName = $"{FileNames.FD}{_floppyDiskCount}{Path.GetExtension(file.RomPath)}";
_exe.AddReadonlyFile(file.FileData, floppyNewName);
floppyMountLine += floppyNewName + " ";
_floppyDiskCount++;
}
if (_floppyDiskCount > 0) configString += floppyMountLine + "\n";
////// CD-ROMs: Mounting and appending mounting lines
string cdromMountLine = "imgmount d ";
foreach (var file in _cdRomFileNames) cdromMountLine += file + " ";
if (_cdRomFileNames.Count > 0) configString += cdromMountLine + "\n";
//// Hard Disk mounting
if (_syncSettings.WriteableHardDisk != WriteableHardDiskOptions.None)
{
var writableHDDImageFile = _syncSettings.WriteableHardDisk switch
{
WriteableHardDiskOptions.FAT16_21Mb => Resources.DOSBOX_HDD_IMAGE_FAT16_21MB.Value,
WriteableHardDiskOptions.FAT16_41Mb => Resources.DOSBOX_HDD_IMAGE_FAT16_41MB.Value,
WriteableHardDiskOptions.FAT16_241Mb => Resources.DOSBOX_HDD_IMAGE_FAT16_241MB.Value,
WriteableHardDiskOptions.FAT16_504Mb => Resources.DOSBOX_HDD_IMAGE_FAT16_504MB.Value,
WriteableHardDiskOptions.FAT16_2014Mb => Resources.DOSBOX_HDD_IMAGE_FAT16_2014MB.Value,
WriteableHardDiskOptions.FAT32_4091Mb => Resources.DOSBOX_HDD_IMAGE_FAT32_4091MB.Value,
_ => Resources.DOSBOX_HDD_IMAGE_FAT16_21MB.Value
};
var writableHDDImageData = Zstd.DecompressZstdStream(new MemoryStream(writableHDDImageFile)).ToArray();
_exe.AddReadonlyFile(writableHDDImageData, FileNames.WHD);
configString += "imgmount c " + FileNames.WHD + ".img\n";
}
//// CPU (core) configuration
configString += "[cpu]\n";
if (_syncSettings.CPUCycles != -1) configString += $"cycles = {_syncSettings.CPUCycles}";
//// DOSBox-x configuration
configString += "[dosbox]\n";
if (_syncSettings.MachineType != MachineType.Auto)
{
var machineName = Enum.GetName(typeof(MachineType), _syncSettings.MachineType)!.Replace('P', '+');
configString += $"machine = {machineName}\n";
}
/////////////// Configuration End: Adding single config file to the wbx
// Reconverting config to byte array
IEnumerable<byte> configData = Encoding.UTF8.GetBytes(configString);
// Adding EOL
configString += "@echo on\n";
configString += "\n";
/////// Appending any additional user-provided config files
foreach (var file in ConfigFiles)
{
// Forcing a new line
configData = configData.Concat("\n"u8.ToArray());
configData = configData.Concat(file.FileData);
}
_exe.AddReadonlyFile(configData.ToArray(), FileNames.Config);
Console.WriteLine($"Configuration: {System.Text.Encoding.Default.GetString(configData.ToArray())}");
////////////// Initializing Core
if (!_libDOSBox.Init(new LibDOSBox.InitSettings()
{
Joystick1Enabled = _syncSettings.EnableJoystick1 ? 1 : 0,
Joystick2Enabled = _syncSettings.EnableJoystick2 ? 1 : 0,
HardDiskDriveSize = writableHDDImageFileSize,
PreserveHardDiskContents = _syncSettings.PreserveHardDiskContents ? 1 : 0
}))
{
throw new InvalidOperationException("Core rejected the rom!");
}
// Setting framerate, if forced; otherwise, use the default.
// The default is necessary because DOSBox does not populate framerate value on init. Only after the first frame run
if (_syncSettings.forceFPSNumerator > 0 && _syncSettings.forceFPSDenominator > 0)
UpdateFramerate(_syncSettings.forceFPSNumerator, _syncSettings.forceFPSDenominator);
else
UpdateFramerate(LibDOSBox.DEFAULT_FRAMERATE_NUMERATOR_DOS, LibDOSBox.DEFAULT_FRAMERATE_DENOMINATOR_DOS);
PostInit();
DriveLightEnabled = false;
if (_syncSettings.WriteableHardDisk != WriteableHardDiskOptions.None) DriveLightEnabled = true;
if (_floppyDiskCount > 0) DriveLightEnabled = true;
if (_cdRomFileNames.Count > 0) DriveLightEnabled = true;
}
public static LibDOSBox.CDData GetCDDataStruct(Disc cd)
{
var ret = new LibDOSBox.CDData();
var ses = cd.Session1;
var ntrack = ses.InformationTrackCount;
for (var i = 0; i < LibDOSBox.CD_MAX_TRACKS; i++)
{
ret.Tracks[i] = new();
ret.Tracks[i].Offset = 0;
ret.Tracks[i].LoopEnabled = 0;
ret.Tracks[i].LoopOffset = 0;
if (i < ntrack)
{
ret.Tracks[i].Start = ses.Tracks[i + 1].LBA;
ret.Tracks[i].End = ses.Tracks[i + 2].LBA;
ret.Tracks[i].Mode = ses.Tracks[i + 1].Mode;
if (i == ntrack - 1)
{
ret.End = ret.Tracks[i].End;
ret.Last = ntrack;
}
}
else
{
ret.Tracks[i].Start = 0;
ret.Tracks[i].End = 0;
ret.Tracks[i].Mode = 0;
}
}
return ret;
}
private void CDRead(string cdRomName, int lba, IntPtr dest, int sectorSize)
{
// Console.WriteLine($"Reading from {cdRomName} : {lba} : {sectorSize}");
if (!_cdRomFileToReaderMap.TryGetValue(cdRomName, out var cdRomReader)) throw new InvalidOperationException($"Unrecognized CD File with name: {cdRomName}");
byte[] sectorBuffer = new byte[4096];
switch (sectorSize)
{
case 2048:
cdRomReader.ReadLBA_2048(lba, sectorBuffer, 0);
Marshal.Copy(sectorBuffer, 0, dest, 2048);
break;
case 2352:
cdRomReader.ReadLBA_2352(lba, sectorBuffer, 0);
Marshal.Copy(sectorBuffer, 0, dest, 2352);
break;
case 2448:
cdRomReader.ReadLBA_2448(lba, sectorBuffer, 0);
Marshal.Copy(sectorBuffer, 0, dest, 2448);
break;
default:
throw new InvalidOperationException($"Unsupported CD sector size: {sectorSize}");
}
DriveLightOn = true;
}
// These variables prevent buttons from acting too fast on consecutive frames
private bool _isPrevFloppyDiskPressed = false;
private bool _isNextFloppyDiskPressed = false;
private bool _isSwapFloppyDiskPressed = false;
private bool _isPrevCDROMPressed = false;
private bool _isNextCDROMPressed = false;
private bool _isSwapCDROMPressed = false;
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
{
DriveLightOn = false;
var fi = new LibDOSBox.FrameInfo();
// Setting joystick inputs
if (_syncSettings.EnableJoystick1)
{
fi.Joystick1.Up = controller.IsPressed($"P1 {Inputs.Joystick} {JoystickButtons.Up}") ? 1 : 0;
fi.Joystick1.Down = controller.IsPressed($"P1 {Inputs.Joystick} {JoystickButtons.Down}") ? 1 : 0;
fi.Joystick1.Left = controller.IsPressed($"P1 {Inputs.Joystick} {JoystickButtons.Left}") ? 1 : 0;
fi.Joystick1.Right = controller.IsPressed($"P1 {Inputs.Joystick} {JoystickButtons.Right}") ? 1 : 0;
fi.Joystick1.Button1 = controller.IsPressed($"P1 {Inputs.Joystick} {JoystickButtons.Button1}") ? 1 : 0;
fi.Joystick1.Button2 = controller.IsPressed($"P1 {Inputs.Joystick} {JoystickButtons.Button2}") ? 1 : 0;
}
if (_syncSettings.EnableJoystick2)
{
fi.Joystick2.Up = controller.IsPressed($"P2 {Inputs.Joystick} {JoystickButtons.Up}") ? 1 : 0;
fi.Joystick2.Down = controller.IsPressed($"P2 {Inputs.Joystick} {JoystickButtons.Down}") ? 1 : 0;
fi.Joystick2.Left = controller.IsPressed($"P2 {Inputs.Joystick} {JoystickButtons.Left}") ? 1 : 0;
fi.Joystick2.Right = controller.IsPressed($"P2 {Inputs.Joystick} {JoystickButtons.Right}") ? 1 : 0;
fi.Joystick2.Button1 = controller.IsPressed($"P2 {Inputs.Joystick} {JoystickButtons.Button1}") ? 1 : 0;
fi.Joystick2.Button2 = controller.IsPressed($"P2 {Inputs.Joystick} {JoystickButtons.Button2}") ? 1 : 0;
}
// Setting mouse inputs
if (_syncSettings.EnableMouse)
{
// Getting new mouse state values
DOSBox.MouseState mouseState = new()
{
PosX = controller.AxisValue($"{Inputs.Mouse} {MouseInputs.PosX}"),
PosY = controller.AxisValue($"{Inputs.Mouse} {MouseInputs.PosY}"),
LeftButtonHeld = controller.IsPressed($"{Inputs.Mouse} {MouseInputs.LeftButton}"),
MiddleButtonHeld = controller.IsPressed($"{Inputs.Mouse} {MouseInputs.MiddleButton}"),
RightButtonHeld = controller.IsPressed($"{Inputs.Mouse} {MouseInputs.RightButton}"),
};
var deltaX = controller.AxisValue($"{Inputs.Mouse} {MouseInputs.SpeedX}");
var deltaY = controller.AxisValue($"{Inputs.Mouse} {MouseInputs.SpeedY}");
fi.Mouse.PosX = mouseState.PosX;
fi.Mouse.PosY = mouseState.PosY;
fi.Mouse.DeltaX = deltaX != 0 ? deltaX : fi.Mouse.PosX - _lastMouseState.PosX;
fi.Mouse.DeltaY = deltaY != 0 ? deltaY : fi.Mouse.PosY - _lastMouseState.PosY;
// Button pressed criteria:
// If the input is made in this frame and the button is not held from before
fi.Mouse.LeftButtonPressed = mouseState.LeftButtonHeld && !_lastMouseState.LeftButtonHeld ? 1 : 0;
fi.Mouse.MiddleButtonPressed = mouseState.MiddleButtonHeld && !_lastMouseState.MiddleButtonHeld ? 1 : 0;
fi.Mouse.RightButtonPressed = mouseState.RightButtonHeld && !_lastMouseState.RightButtonHeld ? 1 : 0;
// Button released criteria:
// If the input is not pressed in this frame and the button is held from before
fi.Mouse.LeftButtonReleased = !mouseState.LeftButtonHeld && _lastMouseState.LeftButtonHeld ? 1 : 0;
fi.Mouse.MiddleButtonReleased = !mouseState.MiddleButtonHeld && _lastMouseState.MiddleButtonHeld ? 1 : 0;
fi.Mouse.RightButtonReleased = !mouseState.RightButtonHeld && _lastMouseState.RightButtonHeld ? 1 : 0;
fi.Mouse.Sensitivity = _syncSettings.MouseSensitivity;
// Updating mouse state
_lastMouseState = mouseState;
}
// Only manage multiple floppy disks if more than 1 were provided
fi.DriveActions.InsertFloppyDisk = -1; // -1 indicates no disk change this frame
if (_floppyDiskCount >= 2)
{
if (!_isPrevFloppyDiskPressed && controller.IsPressed(Inputs.PrevFloppyDisk))
{
_currentFloppyDisk = _currentFloppyDisk == 0 ? _floppyDiskCount - 1 : _currentFloppyDisk - 1;
CoreComm.Notify($"Selected {FileNames.FD}{_currentFloppyDisk}: {Path.GetFileName(_floppyDiskImageFiles[_currentFloppyDisk].RomPath)}", null);
}
if (!_isNextFloppyDiskPressed && controller.IsPressed(Inputs.NextFloppyDisk))
{
_currentFloppyDisk = (_currentFloppyDisk + 1) % _floppyDiskCount;
CoreComm.Notify($"Selected {FileNames.FD}{_currentFloppyDisk}: {Path.GetFileName(_floppyDiskImageFiles[_currentFloppyDisk].RomPath)}", null);
}
// Processing floppy disk swapping
if (!_isSwapFloppyDiskPressed && controller.IsPressed(Inputs.SwapFloppyDisk))
{
fi.DriveActions.InsertFloppyDisk = _currentFloppyDisk;
CoreComm.Notify($"Insterted {FileNames.FD}{_currentFloppyDisk}: {Path.GetFileName(_floppyDiskImageFiles[_currentFloppyDisk].RomPath)} into drive A:", null);
}
}
// Only manage multiple CDROMs if more than 1 were provided
fi.DriveActions.InsertCDROM = -1; // -1 indicates no disk change this frame
if (_cdRomFileNames.Count >= 2)
{
if (!_isPrevCDROMPressed && controller.IsPressed(Inputs.PrevCDROM))
{
_currentCDROM = _currentCDROM == 0 ? _cdRomFileNames.Count - 1 : _currentCDROM - 1;
CoreComm.Notify($"Selected {FileNames.CD}{_currentCDROM}: {_cdRomFileNames[_currentCDROM]}", null);
}
if (!_isNextCDROMPressed && controller.IsPressed(Inputs.NextCDROM))
{
_currentCDROM = (_currentCDROM + 1) % _cdRomFileNames.Count;
CoreComm.Notify($"Selected {FileNames.CD}{_currentCDROM}: {_cdRomFileNames[_currentCDROM]}", null);
}
// Processing CDROM disk swapping
if (!_isSwapCDROMPressed && controller.IsPressed(Inputs.SwapCDROM))
{
fi.DriveActions.InsertCDROM = _currentCDROM;
CoreComm.Notify($"Insterted {FileNames.CD}{_currentCDROM}: {_cdRomFileNames[_currentCDROM]} into drive D:", null);
}
}
// These variables prevent buttons from acting too fast on consecutive frames
_isPrevFloppyDiskPressed = controller.IsPressed(Inputs.PrevFloppyDisk);
_isNextFloppyDiskPressed = controller.IsPressed(Inputs.NextFloppyDisk);
_isSwapFloppyDiskPressed = controller.IsPressed(Inputs.SwapFloppyDisk);
_isPrevCDROMPressed = controller.IsPressed(Inputs.PrevCDROM);
_isNextCDROMPressed = controller.IsPressed(Inputs.NextCDROM);
_isSwapCDROMPressed = controller.IsPressed(Inputs.SwapCDROM);
// Processing keyboard inputs
foreach (var (name, key) in _keyboardMap)
{
if (controller.IsPressed(name))
{
unsafe
{
fi.Keys.Buffer[(int) key] = 1;
}
}
}
// Specifying frame rate
fi.framerateNumerator = VsyncNumerator;
fi.framerateDenominator = VsyncDenominator;
return fi;
}
private void UpdateFramerate(int numerator, int denominator)
{
VsyncNumerator = numerator;
VsyncDenominator = denominator;
var newRefreshRate = (double) VsyncNumerator / VsyncDenominator;
Console.WriteLine($"[Frame {Frame}] Refresh Rate set to: " +
$"{VsyncNumerator} / " +
$"{VsyncDenominator} = " +
$"{newRefreshRate.ToString(CultureInfo.InvariantCulture)} Hz");
}
protected override void FrameAdvancePost()
{
DriveLightOn = _libDOSBox.getDriveActivityFlag();
// Checking refresh rate base on the reported refresh rate updates
var currentRefreshRateNumerator = VsyncNumerator;
var currentRefreshRateDenominator = VsyncDenominator;
var newRefreshRateNumerator = _libDOSBox.getRefreshRateNumerator();
var newRefreshRateDenominator = _libDOSBox.getRefreshRateDenominator();
// Change BK's own framerate if the values changed. Only if not forced. And only if the provided values are valid (they might be zero initially until the core sets it).
if (currentRefreshRateNumerator != newRefreshRateNumerator || currentRefreshRateDenominator != newRefreshRateDenominator)
if (_syncSettings.forceFPSNumerator == 0 || _syncSettings.forceFPSDenominator == 0)
if (newRefreshRateNumerator > 0 && newRefreshRateDenominator > 0)
UpdateFramerate(newRefreshRateNumerator, newRefreshRateDenominator);
}
protected override void SaveStateBinaryInternal(BinaryWriter writer)
{
writer.Write(_currentFloppyDisk);
writer.Write(_currentCDROM);
writer.Write(_lastMouseState.PosX);
writer.Write(_lastMouseState.PosY);
writer.Write(_lastMouseState.LeftButtonHeld);
writer.Write(_lastMouseState.MiddleButtonHeld);
writer.Write(_lastMouseState.RightButtonHeld);
// Storing current refresh rate
writer.Write(VsyncNumerator);
writer.Write(VsyncDenominator);
}
protected override void LoadStateBinaryInternal(BinaryReader reader)
{
_currentFloppyDisk = reader.ReadInt32();
_currentCDROM = reader.ReadInt32();
_lastMouseState.PosX = reader.ReadInt32();
_lastMouseState.PosY = reader.ReadInt32();
_lastMouseState.LeftButtonHeld = reader.ReadBoolean();
_lastMouseState.MiddleButtonHeld = reader.ReadBoolean();
_lastMouseState.RightButtonHeld = reader.ReadBoolean();
// Restoring refresh rate
var newVsyncNumerator = reader.ReadInt32();
var newVsyncDenominator = reader.ReadInt32();
// Updating it now, if different
if (newVsyncNumerator != VsyncNumerator || newVsyncDenominator != VsyncDenominator)
UpdateFramerate(newVsyncNumerator, newVsyncDenominator);
}
private static class FileNames
{
public const string Config = "dosbox-x.conf";
public const string FD = "FloppyDisk";
public const string CD = "CompactDisk";
public const string WHD = "__WritableHardDiskDrive";
}
}
}

View File

@ -0,0 +1,264 @@
using System.Runtime.InteropServices;
using BizHawk.BizInvoke;
using BizHawk.Emulation.Cores.Waterbox;
namespace BizHawk.Emulation.Cores.Computers.DOS
{
public abstract class LibDOSBox : LibWaterboxCore
{
public const int VGA_MAX_WIDTH = 640;
public const int VGA_MAX_HEIGHT = 480;
public const int SVGA_MAX_WIDTH = 800;
public const int SVGA_MAX_HEIGHT = 600;
// Default FPS: 70.086592427616921
public const int DEFAULT_FRAMERATE_NUMERATOR_DOS = 3146888;
public const int DEFAULT_FRAMERATE_DENOMINATOR_DOS = 44900;
public const int FASTMEM_AUTO = -1;
public const int MAX_FLOPPIES = 4;
public const int FILENAME_MAXLENGTH = 64;
public const int KEY_COUNT = 0x65;
// CD Management Logic Start
[StructLayout(LayoutKind.Sequential)]
public class CDTrack
{
public int Offset;
public int Start;
public int End;
public int Mode;
public int LoopEnabled;
public int LoopOffset;
}
public const int CD_MAX_TRACKS = 100;
[StructLayout(LayoutKind.Sequential)]
public class CDData
{
public int End;
public int Last;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CD_MAX_TRACKS)]
public readonly CDTrack[] Tracks = new CDTrack[CD_MAX_TRACKS];
}
[UnmanagedFunctionPointer(CC)]
public delegate void CDReadCallback(string cdRomName, int lba, IntPtr dst, int sectorSize);
[BizImport(CC)]
public abstract void SetCdCallbacks(CDReadCallback cdrc);
[BizImport(CC)]
public abstract void pushCDData(int cdIdx, int numSectors, int numTracks);
[BizImport(CC)]
public abstract void pushTrackData(int cdIdx, int trackId, CDTrack data);
[BizImport(CC)]
public abstract uint getTicksElapsed();
[BizImport(CC)]
public abstract int getRefreshRateNumerator();
[BizImport(CC)]
public abstract int getRefreshRateDenominator();
[StructLayout(LayoutKind.Sequential)]
public class InitSettings
{
public int Joystick1Enabled;
public int Joystick2Enabled;
public ulong HardDiskDriveSize;
public int PreserveHardDiskContents;
}
// CD Management Logic END
[BizImport(CC, Compatibility = true)]
public abstract bool Init(InitSettings settings);
[BizImport(CC, Compatibility = true)]
public abstract bool getDriveActivityFlag();
[StructLayout(LayoutKind.Sequential)]
public new class FrameInfo : LibWaterboxCore.FrameInfo
{
public KeyBuffer Keys;
public struct KeyBuffer
{
public unsafe fixed byte Buffer[KEY_COUNT];
}
public DriveActions DriveActions;
public JoystickButtons Joystick1;
public JoystickButtons Joystick2;
public MouseInput Mouse;
public int framerateNumerator;
public int framerateDenominator;
}
[StructLayout(LayoutKind.Sequential)]
public struct DriveActions
{
public int InsertFloppyDisk;
public int InsertCDROM;
}
[StructLayout(LayoutKind.Sequential)]
public struct JoystickButtons
{
public int Up;
public int Down;
public int Left;
public int Right;
public int Button1;
public int Button2;
}
[StructLayout(LayoutKind.Sequential)]
public struct MouseInput
{
public int PosX;
public int PosY;
public int DeltaX;
public int DeltaY;
public int LeftButtonPressed;
public int MiddleButtonPressed;
public int RightButtonPressed;
public int LeftButtonReleased;
public int MiddleButtonReleased;
public int RightButtonReleased;
public float Sensitivity;
}
// Follows enumeration in DOSBox-x
// DOSBox-x/source/base/core/include/keyboard.h
public enum DOSBoxKeyboard : int
{
Key_None = 0,
Key_1,
Key_2,
Key_3,
Key_4,
Key_5,
Key_6,
Key_7,
Key_8,
Key_9,
Key_0,
Key_Q,
Key_W,
Key_E,
Key_R,
Key_T,
Key_Y,
Key_U,
Key_I,
Key_O,
Key_P,
Key_A,
Key_S,
Key_D,
Key_F,
Key_G,
Key_H,
Key_J,
Key_K,
Key_L,
Key_Z,
Key_X,
Key_C,
Key_V,
Key_B,
Key_N,
Key_M,
Key_F1,
Key_F2,
Key_F3,
Key_F4,
Key_F5,
Key_F6,
Key_F7,
Key_F8,
Key_F9,
Key_F10,
Key_F11,
Key_F12,
Key_Escape,
Key_Tab,
Key_Backspace,
Key_Enter,
Key_Space,
Key_LeftAlt,
Key_RightAlt,
Key_LeftCtrl,
Key_RightCtrl,
Key_LeftShift,
Key_RightShift,
Key_CapsLock,
Key_ScrollLock,
Key_NumLock,
Key_Grave,
Key_Minus,
Key_Equals,
Key_Backslash,
Key_LeftBracket,
Key_RightBracket,
Key_Semicolon,
Key_Quote,
Key_Period,
Key_Comma,
Key_Slash,
Key_ExtraLtGt,
Key_PrintScreen,
Key_Pause,
Key_Insert,
Key_Home,
Key_Pageup,
Key_Delete,
Key_End,
Key_Pagedown,
Key_Left,
Key_Up,
Key_Down,
Key_Right,
Key_KeyPad1,
Key_KeyPad2,
Key_KeyPad3,
Key_KeyPad4,
Key_KeyPad5,
Key_KeyPad6,
Key_KeyPad7,
Key_KeyPad8,
Key_KeyPad9,
Key_KeyPad0,
Key_KeyPadDivide,
Key_KeyPadMultiply,
Key_KeyPadMinus,
Key_KeyPadPlus,
Key_KeyPadEnter,
Key_KeyPadPeriod,
// 45 more, not including "count" member
}
}
}

View File

@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Cores
public const string ColecoHawk = "ColecoHawk";
public const string CPCHawk = "CPCHawk";
public const string Cygne = "Cygne/Mednafen";
public const string DOSBox = "DOSBox-X";
public const string DSDA = "DSDA-Doom";
public const string Emu83 = "Emu83";
public const string Encore = "Encore";

View File

@ -55,7 +55,16 @@ namespace BizHawk.Emulation.Cores
MP3, //can't be ID'd very readily..
//misc disc-related files:
ECM
ECM,
// DOS Floppy Disk Images
DOS_FLOPPY,
// DOS CD-ROM
DOS_CDROM,
// DOSBox-x Configuration File (can be provided as complementary configuration)
DOS_CONFIG_FILE,
}
public class FileIDResult
@ -376,6 +385,19 @@ namespace BizHawk.Emulation.Cores
// Doom IWad / PWad
{ "WAD", new ExtensionInfo(FileIDType.WAD, null ) },
// DOS Floppy Disks
{ "IMA", new(FileIDType.DOS_FLOPPY, null) },
{ "IMG", new(FileIDType.DOS_FLOPPY, null) },
{ "XDF", new(FileIDType.DOS_FLOPPY, null) },
{ "DMF", new(FileIDType.DOS_FLOPPY, null) },
{ "FDD", new(FileIDType.DOS_FLOPPY, null) },
{ "FDI", new(FileIDType.DOS_FLOPPY, null) },
{ "NDF", new(FileIDType.DOS_FLOPPY, null) },
{ "D88", new(FileIDType.DOS_FLOPPY, null) },
// DOSBox-X Configuration File
{ "CONF", new(FileIDType.DOS_CONFIG_FILE, null) },
//for now
{ "ROM", new ExtensionInfo(FileIDType.Multiple, null ) }, //could be MSX too

View File

@ -9,6 +9,24 @@ namespace BizHawk.Emulation.Cores.Properties {
internal static readonly Lazy<byte[]> CPC_BASIC_1_0_ROM = new(() => ReadEmbeddedByteArray("CPC_BASIC_1.0.ROM.zst"));
internal static readonly Lazy<byte[]> CPC_BASIC_1_1_ROM = new(() => ReadEmbeddedByteArray("CPC_BASIC_1.1.ROM.zst"));
internal static readonly Lazy<byte[]> CPC_OS_6128_ROM = new(() => ReadEmbeddedByteArray("CPC_OS_6128.ROM.zst"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_BASE = new(() => ReadEmbeddedByteArray("dosbox-x.base.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1981_IBM_5150 = new(() => ReadEmbeddedByteArray("dosbox-x.1981.ibm_xt5150.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1983_IBM_5160 = new(() => ReadEmbeddedByteArray("dosbox-x.1983.ibm_xt5160.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1986_IBM_5162 = new(() => ReadEmbeddedByteArray("dosbox-x.1986.ibm_xt5162.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1987_IBM_PS2_25 = new(() => ReadEmbeddedByteArray("dosbox-x.1987.ibm_ps2_25.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1990_IBM_PS2_25_286 = new(() => ReadEmbeddedByteArray("dosbox-x.1990.ibm_ps2_25_286.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1991_IBM_PS2_25_386 = new(() => ReadEmbeddedByteArray("dosbox-x.1991.ibm_ps2_25_386.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1993_IBM_PS2_53_SLC2_486 = new(() => ReadEmbeddedByteArray("dosbox-x.1993.ibm_ps2_53_slc2_486.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1994_IBM_PS2_76i_SLC2_486 = new(() => ReadEmbeddedByteArray("dosbox-x.1994.ibm_ps2_76i_slc2_486.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1997_IBM_APTIVA_2140 = new(() => ReadEmbeddedByteArray("dosbox-x.1997.ibm_aptiva_2140.conf"));
internal static readonly Lazy<byte[]> DOSBOX_CONF_1999_IBM_THINKPAD_240 = new(() => ReadEmbeddedByteArray("dosbox-x.1999.ibm_thinkpad_240.conf"));
internal static readonly Lazy<byte[]> DOSBOX_HDD_IMAGE_FAT16_21MB = new(() => ReadEmbeddedByteArray("dosbox-x.hdd.fat16.21mb.img.zst"));
internal static readonly Lazy<byte[]> DOSBOX_HDD_IMAGE_FAT16_41MB = new(() => ReadEmbeddedByteArray("dosbox-x.hdd.fat16.41mb.img.zst"));
internal static readonly Lazy<byte[]> DOSBOX_HDD_IMAGE_FAT16_241MB = new(() => ReadEmbeddedByteArray("dosbox-x.hdd.fat16.241mb.img.zst"));
internal static readonly Lazy<byte[]> DOSBOX_HDD_IMAGE_FAT16_504MB = new(() => ReadEmbeddedByteArray("dosbox-x.hdd.fat16.504mb.img.zst"));
internal static readonly Lazy<byte[]> DOSBOX_HDD_IMAGE_FAT16_2014MB = new(() => ReadEmbeddedByteArray("dosbox-x.hdd.fat16.2014mb.img.zst"));
internal static readonly Lazy<byte[]> DOSBOX_HDD_IMAGE_FAT32_4091MB = new(() => ReadEmbeddedByteArray("dosbox-x.hdd.fat32.4091mb.img.zst"));
internal static readonly Lazy<byte[]> OS_464_ROM = new(() => ReadEmbeddedByteArray("OS_464.ROM.zst"));
internal static readonly Lazy<byte[]> FastCgbBoot = new(() => ReadEmbeddedByteArray("cgb_boot.rom.zst"));
internal static readonly Lazy<byte[]> FastAgbBoot = new(() => ReadEmbeddedByteArray("agb_boot.rom.zst"));

View File

@ -0,0 +1,18 @@
# Computer Information: https://en.wikipedia.org/wiki/IBM_Personal_Computer_XT
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1981] IBM XT 5150 (4.77Mhz, 256kb RAM, Monochrome, PC Speaker)
[cpu]
cycles=fixed 315
core=normal
[sblaster]
sbtype=none
[dosbox]
machine=mda
memsize=0
memsizekb=256

View File

@ -0,0 +1,18 @@
# Computer Information: https://en.wikipedia.org/wiki/IBM_Personal_Computer_XT
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1983] IBM XT 5160 (4.77Mhz, 640kb RAM, CGA, PC Speaker)
[cpu]
cycles=fixed 315
core=normal
[sblaster]
sbtype=none
[dosbox]
machine=cga
memsize=0
memsizekb=640

View File

@ -0,0 +1,19 @@
# Computer Information: https://en.wikipedia.org/wiki/IBM_Personal_Computer_XT
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1986] IBM XT 286 5162-286 (6Mhz, 1Mb RAM, EGA, PC Speaker)
[cpu]
cycles=fixed 700
core=normal
[sblaster]
sbtype=none
[dosbox]
machine=ega
memsize=1
memsizekb=0

View File

@ -0,0 +1,18 @@
# Computer Information: https://en.wikipedia.org/wiki/IBM_Personal_Computer_XT
# Performance Approximation: https://en.wikipedia.org/wiki/IBM_Personal_Computer_XT
# Profile made by eien86
[ExtraInfo]
Name=[1987] IBM PS/2 25 (8Mhz, 640kb RAM, MCGA, Game Blaster)
[cpu]
cycles=fixed 1400
core=normal
[sblaster]
sbtype=gb
[dosbox]
machine=mcga
memsize=0
memsizekb=640

View File

@ -0,0 +1,17 @@
# Computer Information: https://en.wikipedia.org/wiki/List_of_IBM_PS/2_models
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1990] IBM PS/2 25 286 (10Mhz, 4Mb RAM, VGA, Sound Blaster 1)
[cpu]
cycles=fixed 2300
core=normal
[sblaster]
sbtype=sb1
[dosbox]
machine=vga
memsize=4

View File

@ -0,0 +1,17 @@
# Computer Information: https://en.wikipedia.org/wiki/List_of_IBM_PS/2_models
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1991] IBM PS/2 25 386 (25Mhz, 6Mb RAM, VGA, Sound Blaster 2)
[cpu]
cycles=fixed 6000
core=normal
[sblaster]
sbtype=sb2
[dosbox]
machine=vga
memsize=6

View File

@ -0,0 +1,17 @@
# Computer Information: https://en.wikipedia.org/wiki/List_of_IBM_PS/2_models
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1993] IBM PS/2 53 SLC2 486 (50Mhz, 32Mb RAM, SVGA, Sound Blaster Pro 2)
[cpu]
cycles=fixed 22000
core=normal
[sblaster]
sbtype=sbpro2
[dosbox]
machine=vga
memsize=32

View File

@ -0,0 +1,17 @@
# Computer Information: https://en.wikipedia.org/wiki/List_of_IBM_PS/2_models
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1994] IBM PS/2 76i SLC2 486 (100Mhz, 64Mb RAM, SVGA, Sound Blaster 16)
[cpu]
cycles=fixed 77000
core=normal
[sblaster]
sbtype=sb16
[dosbox]
machine=vga
memsize=64

View File

@ -0,0 +1,17 @@
# Computer Information: https://theretroweb.com/motherboards/s/ibm-aptiva-2142-type-a-2
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1997] IBM Aptiva 2140 (233Mhz, 96Mb RAM, SVGA + 3D Support, Sound Blaster 16)
[cpu]
cycles=fixed 200000
core=normal
[sblaster]
sbtype=sb16
[dosbox]
machine=svga_s3
memsize=96

View File

@ -0,0 +1,17 @@
# Computer Information: https://en.wikipedia.org/wiki/IBM_ThinkPad_240
# Performance Approximation: https://www.dosbox.com/wiki/Performance
# Profile made by eien86
[ExtraInfo]
Name=[1999] IBM Thinkpad 240 (300Mhz, 96Mb, SVGA + 3D Support, Sound Blaster 16)
[cpu]
cycles=fixed 200000
core=normal
[sblaster]
sbtype=sb16
[dosbox]
machine=svga_s3trio64
memsize=128

File diff suppressed because it is too large Load Diff

View File

@ -176,17 +176,22 @@ namespace BizHawk.Emulation.Cores.Waterbox
public void StoreSaveRam(byte[] data)
{
// Checking if the size of the SaveRAM provided coincides with that expected. This is important for cores whose SaveRAM size can vary depending on their configuration.
if (data.Length != _saveramSize)
{
Console.WriteLine($"Could not push SaveRam into the core: the length of the data provided ({data.Length}) is different than expected ({_saveramSize})");
// Here, the exception was too traumatic. The emulator shuts down when in debug mode, and is left in an unstable state on release.
// Using a softer landing here, although returning true/false plus a string explanation would be more adequate.
return;
}
using (_exe.EnterExit())
{
if (data.Length != _saveramSize)
throw new InvalidOperationException("Saveram size mismatch");
using (_exe.EnterExit())
var source = new MemoryStream(data, false);
foreach (var area in _saveramAreas)
{
var source = new MemoryStream(data, false);
foreach (var area in _saveramAreas)
{
MemoryBlockUtils.CopySome(source, new MemoryDomainStream(area), area.Size);
}
MemoryBlockUtils.CopySome(source, new MemoryDomainStream(area), area.Size);
}
}
}

View File

@ -112,6 +112,11 @@ namespace BizHawk.Emulation.DiscSystem
/// Atari Jaguar CD
/// </summary>
JaguarCD,
/// <summary>
/// DOS / Windows
/// </summary>
DOS,
}
public class DiscIdentifier
@ -185,6 +190,7 @@ namespace BizHawk.Emulation.DiscSystem
if (DetectWii())
return DiscType.Wii;
var discView = EDiscStreamView.DiscStreamView_Mode1_2048;
if (_disc.TOC.SessionFormat == SessionFormat.Type20_CDXA)
discView = EDiscStreamView.DiscStreamView_Mode2_Form1_2048;
@ -247,6 +253,9 @@ namespace BizHawk.Emulation.DiscSystem
var absTxt = iso.Root.Children.Where(kvp => kvp.Key.Contains("ABS.TXT")).Select(kvp => kvp.Value).FirstOrDefault();
if (absTxt != null && SectorContains("abstracted by snk", Convert.ToInt32(absTxt.Offset))) return DiscType.NeoGeoCD;
if (DetectISO9660()) return DiscType.DOS;
if (DetectUDF()) return DiscType.DOS;
return DiscType.UnknownCDFS;
}
@ -394,6 +403,28 @@ namespace BizHawk.Emulation.DiscSystem
return hexString == "5D1C9EA3";
}
/// <summary>Detects ISO9660 / Joliet CD formats (target for DOS / Windows)</summary>
/// <remarks><see href="https://en.wikipedia.org/wiki/ISO_9660"/></remarks>
private bool DetectISO9660()
{
if (SectorContains("CD001", 16)) return true;
if (SectorContains("CDROM", 16)) return true;
return false;
}
/// <remarks><see href="https://www.cnwrecovery.com/manual/HowToRecogniseTypeOfCDDVD.html"/></remarks>
private bool DetectUDF()
{
for (var i = 0; i < 256; i++)
{
if (SectorContains("BEA01", i)) return true;
if (SectorContains("NSR02", i)) return true;
if (SectorContains("TEA01", i)) return true;
}
return false;
}
private bool DetectJaguarCD()
{
// Atari Jaguar CDs are multisession discs which are encoded like audio CDs

490
waterbox/dosbox/Makefile Normal file
View File

@ -0,0 +1,490 @@
CCFLAGS := -I. \
-Idosbox-x/third_party/SDL2/include \
-Idosbox-x/third_party/SDL2/src/ \
-Idosbox-x/third_party/libco \
-Idosbox-x/third_party/jaffarCommon/include \
-Idosbox-x \
-Idosbox-x/include \
-Idosbox-x/src \
-Idosbox-x/vs/sdlnet/linux-host/include/ \
-Idosbox-x/vs/sdlnet/linux-host/include/SDL \
-Idosbox-x/src/hardware/snd_pc98/sound/ \
-Idosbox-x/src/aviwriter \
-Idosbox-x/src/libs/mt32 \
-Idosbox-x/src/hardware/snd_pc98/generic \
-Idosbox-x/src/gui \
-Idosbox-x/src/hardware/snd_pc98/common \
-Idosbox-x/src/hardware/snd_pc98/x11 \
-Idosbox-x/src/hardware/snd_pc98/sound/getsnd \
-Idosbox-x/src/hardware/snd_pc98/cbus \
-DSDL_BUILD_MAJOR_VERSION=2 \
-DSDL_BUILD_MINOR_VERSION=32 \
-DSDL_BUILD_MICRO_VERSION=0 \
-DHAVE_LINUX_VERSION_H \
-DUSING_GENERATED_CONFIG_H \
-D__LINUX__ \
-D__INLINE__=inline
CXXFLAGS := $(CCFLAGS) -std=c++20
LDFLAGS :=
TARGET := dosbox.wbx
SRCS = bizhawk.cpp \
dosbox-x/src/dos/dos_devices.cpp \
dosbox-x/src/dos/drive_physfs.cpp \
dosbox-x/src/dos/dos_ioctl.cpp \
dosbox-x/src/dos/eltorito.cpp \
dosbox-x/src/dos/drive_cache.cpp \
dosbox-x/src/dos/dos_execute.cpp \
dosbox-x/src/dos/dos_files.cpp \
dosbox-x/src/dos/cdrom_image.cpp \
dosbox-x/src/dos/drive_local.cpp \
dosbox-x/src/dos/drive_fat.cpp \
dosbox-x/src/dos/dos_mscdex.cpp \
dosbox-x/src/dos/cdrom.cpp \
dosbox-x/src/dos/dos_keyboard_layout.cpp \
dosbox-x/src/dos/drives.cpp \
dosbox-x/src/dos/dos_memory.cpp \
dosbox-x/src/dos/cdrom_aspi_win32.cpp \
dosbox-x/src/dos/cdrom_ioctl_os2.cpp \
dosbox-x/src/dos/dos_classes.cpp \
dosbox-x/src/dos/drive_virtual.cpp \
dosbox-x/src/dos/dos.cpp \
dosbox-x/src/dos/cdrom_ioctl_win32.cpp \
dosbox-x/src/dos/dos_misc.cpp \
dosbox-x/src/dos/dos_programs.cpp \
dosbox-x/src/dos/dos_tables.cpp \
dosbox-x/src/dos/drive_overlay.cpp \
dosbox-x/src/dos/drive_iso.cpp \
dosbox-x/src/debug/debug.cpp \
dosbox-x/src/debug/debug_gui.cpp \
dosbox-x/src/debug/debug_disasm.cpp \
dosbox-x/src/debug/debug_win32.cpp \
dosbox-x/src/dosbox.cpp \
dosbox-x/src/cpu/core_full.cpp \
dosbox-x/src/cpu/mmx.cpp \
dosbox-x/src/cpu/core_normal_8086.cpp \
dosbox-x/src/cpu/cpu.cpp \
dosbox-x/src/cpu/core_normal.cpp \
dosbox-x/src/cpu/core_prefetch_286.cpp \
dosbox-x/src/cpu/core_simple.cpp \
dosbox-x/src/cpu/callback.cpp \
dosbox-x/src/cpu/paging.cpp \
dosbox-x/src/cpu/core_dyn_x86.cpp \
dosbox-x/src/cpu/core_dynrec.cpp \
dosbox-x/src/cpu/modrm.cpp \
dosbox-x/src/cpu/core_normal_286.cpp \
dosbox-x/src/cpu/core_prefetch.cpp \
dosbox-x/src/cpu/flags.cpp \
dosbox-x/src/cpu/core_prefetch_8086.cpp \
dosbox-x/src/misc/regionalloctracking.cpp \
dosbox-x/src/misc/setup.cpp \
dosbox-x/src/misc/mkdir_p.cpp \
dosbox-x/src/misc/ethernet_nothing.cpp \
dosbox-x/src/misc/clipboard.cpp \
dosbox-x/src/misc/ethernet_slirp.cpp \
dosbox-x/src/misc/iconvpp.cpp \
dosbox-x/src/misc/shiftjis.cpp \
dosbox-x/src/misc/ethernet_pcap.cpp \
dosbox-x/src/misc/savestates.cpp \
dosbox-x/src/misc/ethernet.cpp \
dosbox-x/src/misc/programs.cpp \
dosbox-x/src/misc/cross.cpp \
dosbox-x/src/misc/support.cpp \
dosbox-x/src/misc/messages.cpp \
dosbox-x/src/gui/sdl_gui.cpp \
dosbox-x/src/gui/render.cpp \
dosbox-x/src/gui/render_scalers.cpp \
dosbox-x/src/gui/sdl_mapper.cpp \
dosbox-x/src/gui/zipfile.cpp \
dosbox-x/src/gui/sdlmain.cpp \
dosbox-x/src/gui/ptrop.cpp \
dosbox-x/src/gui/sdlmain_linux.cpp \
dosbox-x/src/gui/menu.cpp \
dosbox-x/src/gui/midi.cpp \
dosbox-x/src/gui/bitop.cpp \
dosbox-x/src/gui/menu_callback.cpp \
dosbox-x/src/ints/int10_modes.cpp \
dosbox-x/src/ints/bios.cpp \
dosbox-x/src/ints/int10.cpp \
dosbox-x/src/ints/bios_memdisk.cpp \
dosbox-x/src/ints/int10_vesa.cpp \
dosbox-x/src/ints/int_dosv.cpp \
dosbox-x/src/ints/int10_vptable.cpp \
dosbox-x/src/ints/int10_misc.cpp \
dosbox-x/src/ints/xms.cpp \
dosbox-x/src/ints/bios_disk.cpp \
dosbox-x/src/ints/qcow2_disk.cpp \
dosbox-x/src/ints/pc98_lio.cpp \
dosbox-x/src/ints/int10_memory.cpp \
dosbox-x/src/ints/mouse.cpp \
dosbox-x/src/ints/bios_keyboard.cpp \
dosbox-x/src/ints/ems.cpp \
dosbox-x/src/ints/bios_vhd.cpp \
dosbox-x/src/ints/int10_put_pixel.cpp \
dosbox-x/src/ints/int10_video_state.cpp \
dosbox-x/src/ints/int10_char.cpp \
dosbox-x/src/ints/int10_pal.cpp \
dosbox-x/src/aviwriter/riff_wav_writer.cpp \
dosbox-x/src/aviwriter/avi_rw_iobuf.cpp \
dosbox-x/src/aviwriter/riff.cpp \
dosbox-x/src/aviwriter/ksdataformat.cpp \
dosbox-x/src/aviwriter/avi_writer.cpp \
dosbox-x/src/aviwriter/guid.cpp \
dosbox-x/src/builtin/move_exe.cpp \
dosbox-x/src/builtin/hexmem16_exe.cpp \
dosbox-x/src/builtin/fdisk_exe.cpp \
dosbox-x/src/builtin/textutil.cpp \
dosbox-x/src/builtin/append_exe.cpp \
dosbox-x/src/builtin/format_exe.cpp \
dosbox-x/src/builtin/glide2x.cpp \
dosbox-x/src/builtin/50_com.cpp \
dosbox-x/src/builtin/debug_exe.cpp \
dosbox-x/src/builtin/edit_com.cpp \
dosbox-x/src/builtin/ne2000bin.cpp \
dosbox-x/src/builtin/28_com.cpp \
dosbox-x/src/builtin/find_exe.cpp \
dosbox-x/src/builtin/sys_com.cpp \
dosbox-x/src/builtin/eval.cpp \
dosbox-x/src/builtin/dosmid.cpp \
dosbox-x/src/builtin/dsxmenu_exe_pc98.cpp \
dosbox-x/src/builtin/diskcopy_exe.cpp \
dosbox-x/src/builtin/hexmem32_exe.cpp \
dosbox-x/src/builtin/zip.cpp \
dosbox-x/src/builtin/fcbs_com.cpp \
dosbox-x/src/builtin/cwsdpmi_exe.cpp \
dosbox-x/src/builtin/xcopy_exe.cpp \
dosbox-x/src/builtin/4dos.cpp \
dosbox-x/src/builtin/fc_exe.cpp \
dosbox-x/src/builtin/files_com.cpp \
dosbox-x/src/builtin/dos4gw_exe.cpp \
dosbox-x/src/builtin/emsmagic.cpp \
dosbox-x/src/builtin/chkdsk_exe.cpp \
dosbox-x/src/builtin/defrag_exe.cpp \
dosbox-x/src/builtin/print_com.cpp \
dosbox-x/src/builtin/mem_com.cpp \
dosbox-x/src/builtin/cwsdpmi_exe_pc98.cpp \
dosbox-x/src/builtin/cdplay.cpp \
dosbox-x/src/builtin/buffers_com.cpp \
dosbox-x/src/builtin/sort_exe.cpp \
dosbox-x/src/builtin/lastdriv_com.cpp \
dosbox-x/src/builtin/dsxmenu_exe_pc.cpp \
dosbox-x/src/builtin/replace_exe.cpp \
dosbox-x/src/builtin/dos32a_exe.cpp \
dosbox-x/src/builtin/dosidle_exe.cpp \
dosbox-x/src/builtin/25_com.cpp \
dosbox-x/src/builtin/device_com.cpp \
dosbox-x/src/builtin/shutdown.cpp \
dosbox-x/src/builtin/mpxplay.cpp \
dosbox-x/src/shell/shell.cpp \
dosbox-x/src/shell/shell_batch.cpp \
dosbox-x/src/shell/shell_cmds.cpp \
dosbox-x/src/shell/shell_misc.cpp \
dosbox-x/src/hardware/ps1_sound.cpp \
dosbox-x/src/hardware/vga_pc98_dac.cpp \
dosbox-x/src/hardware/vga_tseng.cpp \
dosbox-x/src/hardware/vga_pc98_crtc.cpp \
dosbox-x/src/hardware/vga_pc98_gdc_draw.cpp \
dosbox-x/src/hardware/vga_draw.cpp \
dosbox-x/src/hardware/gameblaster.cpp \
dosbox-x/src/hardware/pic.cpp \
dosbox-x/src/hardware/memory.cpp \
dosbox-x/src/hardware/cmos.cpp \
dosbox-x/src/hardware/voodoo_opengl.cpp \
dosbox-x/src/hardware/vga_dac.cpp \
dosbox-x/src/hardware/vga_gfx.cpp \
dosbox-x/src/hardware/vga_crtc.cpp \
dosbox-x/src/hardware/serialport/softmodem.cpp \
dosbox-x/src/hardware/serialport/misc_util.cpp \
dosbox-x/src/hardware/serialport/serialdummy.cpp \
dosbox-x/src/hardware/serialport/seriallog.cpp \
dosbox-x/src/hardware/serialport/serialport.cpp \
dosbox-x/src/hardware/serialport/directserial.cpp \
dosbox-x/src/hardware/serialport/serialfile.cpp \
dosbox-x/src/hardware/serialport/libserial.cpp \
dosbox-x/src/hardware/serialport/serialmouse.cpp \
dosbox-x/src/hardware/serialport/nullmodem.cpp \
dosbox-x/src/hardware/pci_bus.cpp \
dosbox-x/src/hardware/vga_s3.cpp \
dosbox-x/src/hardware/hardopl.cpp \
dosbox-x/src/hardware/glide.cpp \
dosbox-x/src/hardware/mpu401.cpp \
dosbox-x/src/hardware/dbopl.cpp \
dosbox-x/src/hardware/tandy_sound.cpp \
dosbox-x/src/hardware/keyboard.cpp \
dosbox-x/src/hardware/vga_pc98_gdc.cpp \
dosbox-x/src/hardware/gus.cpp \
dosbox-x/src/hardware/voodoo_emu.cpp \
dosbox-x/src/hardware/pcspeaker.cpp \
dosbox-x/src/hardware/innova.cpp \
dosbox-x/src/hardware/floppy.cpp \
dosbox-x/src/hardware/vga_memory.cpp \
dosbox-x/src/hardware/timer.cpp \
dosbox-x/src/hardware/pc98.cpp \
dosbox-x/src/hardware/vga_paradise.cpp \
dosbox-x/src/hardware/opl3duoboard/opl3duoboard.cpp \
dosbox-x/src/hardware/opl2board/opl2board.cpp \
dosbox-x/src/hardware/mame/ymf262.cpp \
dosbox-x/src/hardware/mame/sn76496.cpp \
dosbox-x/src/hardware/mame/ymdeltat.cpp \
dosbox-x/src/hardware/mame/fmopl.cpp \
dosbox-x/src/hardware/mame/saa1099.cpp \
dosbox-x/src/hardware/disney.cpp \
dosbox-x/src/hardware/vga_attr.cpp \
dosbox-x/src/hardware/ide.cpp \
dosbox-x/src/hardware/8255.cpp \
dosbox-x/src/hardware/vga_misc.cpp \
dosbox-x/src/hardware/voodoo_vogl.cpp \
dosbox-x/src/hardware/dongle.cpp \
dosbox-x/src/hardware/vga_seq.cpp \
dosbox-x/src/hardware/ipx.cpp \
dosbox-x/src/hardware/vga_ati.cpp \
dosbox-x/src/hardware/adlib.cpp \
dosbox-x/src/hardware/nukedopl.cpp \
dosbox-x/src/hardware/vga_pc98_cg.cpp \
dosbox-x/src/hardware/iohandler.cpp \
dosbox-x/src/hardware/hardware.cpp \
dosbox-x/src/hardware/ne2000.cpp \
dosbox-x/src/hardware/imfc.cpp \
dosbox-x/src/hardware/ipxserver.cpp \
dosbox-x/src/hardware/pc98_artic.cpp \
dosbox-x/src/hardware/vga_other.cpp \
dosbox-x/src/hardware/pc98_fm.cpp \
dosbox-x/src/hardware/vga_xga.cpp \
dosbox-x/src/hardware/vga.cpp \
dosbox-x/src/hardware/dma.cpp \
dosbox-x/src/hardware/opl.cpp \
dosbox-x/src/hardware/voodoo_interface.cpp \
dosbox-x/src/hardware/reSID/pot.cpp \
dosbox-x/src/hardware/reSID/wave6581_PS_.cpp \
dosbox-x/src/hardware/reSID/voice.cpp \
dosbox-x/src/hardware/reSID/wave8580_P_T.cpp \
dosbox-x/src/hardware/reSID/wave8580_PST.cpp \
dosbox-x/src/hardware/reSID/filter.cpp \
dosbox-x/src/hardware/reSID/wave6581__ST.cpp \
dosbox-x/src/hardware/reSID/wave.cpp \
dosbox-x/src/hardware/reSID/version.cpp \
dosbox-x/src/hardware/reSID/extfilt.cpp \
dosbox-x/src/hardware/reSID/wave8580_PS_.cpp \
dosbox-x/src/hardware/reSID/sid.cpp \
dosbox-x/src/hardware/reSID/envelope.cpp \
dosbox-x/src/hardware/reSID/wave6581_PST.cpp \
dosbox-x/src/hardware/reSID/wave6581_P_T.cpp \
dosbox-x/src/hardware/reSID/wave8580__ST.cpp \
dosbox-x/src/hardware/joystick.cpp \
dosbox-x/vs/sdl2/src/joystick/virtual/SDL_virtualjoystick.c \
dosbox-x/vs/sdl2/src/joystick/dummy/SDL_sysjoystick.c \
dosbox-x/src/hardware/parport/parport.cpp \
dosbox-x/src/hardware/mixer.cpp \
dosbox-x/src/hardware/voodoo.cpp \
dosbox-x/src/hardware/sblaster.cpp \
dosbox-x/src/hardware/vga_pc98_egc.cpp \
dosbox-x/src/libs/passthroughio/passthroughio.cpp \
dosbox-x/src/libs/gui_tk/gui_tk.cpp \
dosbox-x/src/libs/physfs/physfs_platform_winrt.cpp \
dosbox-x/src/libs/physfs/physfs_platform_haiku.cpp \
dosbox-x/src/libs/zmbv/zmbv.cpp \
dosbox-x/src/libs/mt32/LA32FloatWaveGenerator.cpp \
dosbox-x/src/libs/mt32/MidiStreamParser.cpp \
dosbox-x/src/libs/mt32/Synth.cpp \
dosbox-x/src/libs/mt32/ROMInfo.cpp \
dosbox-x/src/libs/mt32/VersionTagging.cpp \
dosbox-x/src/libs/mt32/LA32WaveGenerator.cpp \
dosbox-x/src/libs/mt32/LA32Ramp.cpp \
dosbox-x/src/libs/mt32/BReverbModel.cpp \
dosbox-x/src/libs/mt32/Poly.cpp \
dosbox-x/src/libs/mt32/File.cpp \
dosbox-x/src/libs/mt32/SampleRateConverter.cpp \
dosbox-x/src/libs/mt32/Part.cpp \
dosbox-x/src/libs/mt32/Display.cpp \
dosbox-x/src/libs/mt32/srchelper/srctools/src/SincResampler.cpp \
dosbox-x/src/libs/mt32/srchelper/srctools/src/LinearResampler.cpp \
dosbox-x/src/libs/mt32/srchelper/srctools/src/FIRResampler.cpp \
dosbox-x/src/libs/mt32/srchelper/srctools/src/IIR2xResampler.cpp \
dosbox-x/src/libs/mt32/srchelper/srctools/src/ResamplerModel.cpp \
dosbox-x/src/libs/mt32/srchelper/InternalResampler.cpp \
dosbox-x/src/libs/mt32/FileStream.cpp \
dosbox-x/src/libs/mt32/TVA.cpp \
dosbox-x/src/libs/mt32/TVP.cpp \
dosbox-x/src/libs/mt32/Partial.cpp \
dosbox-x/src/libs/mt32/c_interface/c_interface.cpp \
dosbox-x/src/libs/mt32/PartialManager.cpp \
dosbox-x/src/libs/mt32/Tables.cpp \
dosbox-x/src/libs/mt32/TVF.cpp \
dosbox-x/src/libs/mt32/Analog.cpp \
dosbox-x/src/libs/mt32/sha1/sha1.cpp \
dosbox-x/src/libs/xBRZ/xbrz.cpp \
dosbox-x/src/gamelink/gamelink_term.cpp \
dosbox-x/src/gamelink/gamelink.cpp \
dosbox-x/src/output/output_direct3d.cpp \
dosbox-x/src/output/direct3d/ScalingEffect.cpp \
dosbox-x/src/output/direct3d/direct3d.cpp \
dosbox-x/src/output/direct3d/hq2x_d3d.cpp \
dosbox-x/src/output/output_tools_xbrz.cpp \
dosbox-x/src/output/output_opengl.cpp \
dosbox-x/src/output/output_surface.cpp \
dosbox-x/src/output/output_ttf.cpp \
dosbox-x/src/output/output_gamelink.cpp \
dosbox-x/src/output/output_tools.cpp \
dosbox-x/src/fpu/fpu.cpp \
dosbox-x/src/gui/zipcrc.c \
dosbox-x/src/hardware/esfmu/esfm_registers.c \
dosbox-x/src/hardware/esfmu/esfm.c \
dosbox-x/src/hardware/imfc_rom.c \
dosbox-x/src/hardware/snd_pc98/common/parts.c \
dosbox-x/src/hardware/snd_pc98/sound/rhythmc.c \
dosbox-x/src/hardware/snd_pc98/sound/fmtimer.c \
dosbox-x/src/hardware/snd_pc98/sound/getsnd/getwave.c \
dosbox-x/src/hardware/snd_pc98/sound/getsnd/getsmix.c \
dosbox-x/src/hardware/snd_pc98/sound/getsnd/getsnd.c \
dosbox-x/src/hardware/snd_pc98/sound/sound.c \
dosbox-x/src/hardware/snd_pc98/sound/adpcmc.c \
dosbox-x/src/hardware/snd_pc98/sound/soundrom.c \
dosbox-x/src/hardware/snd_pc98/sound/opngeng.c \
dosbox-x/src/hardware/snd_pc98/sound/adpcmg.c \
dosbox-x/src/hardware/snd_pc98/sound/pcm86c.c \
dosbox-x/src/hardware/snd_pc98/sound/opngenc.c \
dosbox-x/src/hardware/snd_pc98/sound/psggeng.c \
dosbox-x/src/hardware/snd_pc98/sound/tms3631c.c \
dosbox-x/src/hardware/snd_pc98/sound/psggenc.c \
dosbox-x/src/hardware/snd_pc98/sound/tms3631g.c \
dosbox-x/src/hardware/snd_pc98/sound/fmboard.c \
dosbox-x/src/hardware/snd_pc98/sound/pcm86g.c \
dosbox-x/src/hardware/snd_pc98/cbus/board86.c \
dosbox-x/src/hardware/snd_pc98/cbus/pcm86io.c \
dosbox-x/src/hardware/snd_pc98/cbus/board26k.c \
dosbox-x/src/hardware/snd_pc98/generic/keydisp.c \
dosbox-x/src/hardware/snd_pc98/x11/dosio.c \
dosbox-x/third_party/libco/amd64.c \
dosbox-x/third_party/SDL2/src/SDL.c \
dosbox-x/third_party/SDL2/src/SDL_assert.c \
dosbox-x/third_party/SDL2/src/SDL_dataqueue.c \
dosbox-x/third_party/SDL2/src/SDL_error.c \
dosbox-x/third_party/SDL2/src/SDL_guid.c \
dosbox-x/third_party/SDL2/src/SDL_hints.c \
dosbox-x/third_party/SDL2/src/SDL_list.c \
dosbox-x/third_party/SDL2/src/SDL_log.c \
dosbox-x/third_party/SDL2/src/SDL_utils.c \
dosbox-x/third_party/SDL2/src/atomic/SDL_atomic.c \
dosbox-x/third_party/SDL2/src/atomic/SDL_spinlock.c \
dosbox-x/third_party/SDL2/src/audio/SDL_audio.c \
dosbox-x/third_party/SDL2/src/audio/SDL_audiocvt.c \
dosbox-x/third_party/SDL2/src/audio/SDL_audiodev.c \
dosbox-x/third_party/SDL2/src/audio/SDL_audiotypecvt.c \
dosbox-x/third_party/SDL2/src/audio/SDL_mixer.c \
dosbox-x/third_party/SDL2/src/audio/SDL_wave.c \
dosbox-x/third_party/SDL2/src/cpuinfo/SDL_cpuinfo.c \
dosbox-x/third_party/SDL2/src/dynapi/SDL_dynapi.c \
dosbox-x/third_party/SDL2/src/events/SDL_clipboardevents.c \
dosbox-x/third_party/SDL2/src/events/SDL_displayevents.c \
dosbox-x/third_party/SDL2/src/events/SDL_dropevents.c \
dosbox-x/third_party/SDL2/src/events/SDL_events.c \
dosbox-x/third_party/SDL2/src/events/SDL_gesture.c \
dosbox-x/third_party/SDL2/src/events/SDL_keyboard.c \
dosbox-x/third_party/SDL2/src/events/SDL_keysym_to_scancode.c \
dosbox-x/third_party/SDL2/src/events/SDL_mouse.c \
dosbox-x/third_party/SDL2/src/events/SDL_quit.c \
dosbox-x/third_party/SDL2/src/events/SDL_scancode_tables.c \
dosbox-x/third_party/SDL2/src/events/SDL_touch.c \
dosbox-x/third_party/SDL2/src/events/SDL_windowevents.c \
dosbox-x/third_party/SDL2/src/events/imKStoUCS.c \
dosbox-x/third_party/SDL2/src/file/SDL_rwops.c \
dosbox-x/third_party/SDL2/src/hidapi/SDL_hidapi.c \
dosbox-x/third_party/SDL2/src/joystick/SDL_gamecontroller.c \
dosbox-x/third_party/SDL2/src/joystick/SDL_joystick.c \
dosbox-x/third_party/SDL2/src/joystick/SDL_steam_virtual_gamepad.c \
dosbox-x/third_party/SDL2/src/joystick/controller_type.c \
dosbox-x/third_party/SDL2/src/haptic/SDL_haptic.c \
dosbox-x/third_party/SDL2/src/haptic/dummy/SDL_syshaptic.c \
dosbox-x/third_party/SDL2/src/libm/e_atan2.c \
dosbox-x/third_party/SDL2/src/libm/e_exp.c \
dosbox-x/third_party/SDL2/src/libm/e_fmod.c \
dosbox-x/third_party/SDL2/src/libm/e_log.c \
dosbox-x/third_party/SDL2/src/libm/e_log10.c \
dosbox-x/third_party/SDL2/src/libm/e_pow.c \
dosbox-x/third_party/SDL2/src/libm/e_rem_pio2.c \
dosbox-x/third_party/SDL2/src/libm/e_sqrt.c \
dosbox-x/third_party/SDL2/src/libm/k_cos.c \
dosbox-x/third_party/SDL2/src/libm/k_rem_pio2.c \
dosbox-x/third_party/SDL2/src/libm/k_sin.c \
dosbox-x/third_party/SDL2/src/libm/k_tan.c \
dosbox-x/third_party/SDL2/src/libm/s_atan.c \
dosbox-x/third_party/SDL2/src/libm/s_copysign.c \
dosbox-x/third_party/SDL2/src/libm/s_cos.c \
dosbox-x/third_party/SDL2/src/libm/s_fabs.c \
dosbox-x/third_party/SDL2/src/libm/s_floor.c \
dosbox-x/third_party/SDL2/src/libm/s_scalbn.c \
dosbox-x/third_party/SDL2/src/libm/s_sin.c \
dosbox-x/third_party/SDL2/src/libm/s_tan.c \
dosbox-x/third_party/SDL2/src/misc/SDL_url.c \
dosbox-x/third_party/SDL2/src/power/SDL_power.c \
dosbox-x/third_party/SDL2/src/render/SDL_d3dmath.c \
dosbox-x/third_party/SDL2/src/render/SDL_render.c \
dosbox-x/third_party/SDL2/src/render/SDL_yuv_sw.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_blendfillrect.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_blendline.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_blendpoint.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_drawline.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_drawpoint.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_render_sw.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_rotate.c \
dosbox-x/third_party/SDL2/src/render/software/SDL_triangle.c \
dosbox-x/third_party/SDL2/src/sensor/SDL_sensor.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_crc16.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_crc32.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_getenv.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_iconv.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_malloc.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_mslibc.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_qsort.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_stdlib.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_string.c \
dosbox-x/third_party/SDL2/src/stdlib/SDL_strtokr.c \
dosbox-x/third_party/SDL2/src/thread/SDL_thread.c \
dosbox-x/third_party/SDL2/src/timer/SDL_timer.c \
dosbox-x/third_party/SDL2/src/video/SDL_RLEaccel.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit_0.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit_1.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit_A.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit_N.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit_auto.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit_copy.c \
dosbox-x/third_party/SDL2/src/video/SDL_blit_slow.c \
dosbox-x/third_party/SDL2/src/video/SDL_bmp.c \
dosbox-x/third_party/SDL2/src/video/SDL_clipboard.c \
dosbox-x/third_party/SDL2/src/video/SDL_egl.c \
dosbox-x/third_party/SDL2/src/video/SDL_fillrect.c \
dosbox-x/third_party/SDL2/src/video/SDL_pixels.c \
dosbox-x/third_party/SDL2/src/video/SDL_rect.c \
dosbox-x/third_party/SDL2/src/video/SDL_shape.c \
dosbox-x/third_party/SDL2/src/video/SDL_stretch.c \
dosbox-x/third_party/SDL2/src/video/SDL_surface.c \
dosbox-x/third_party/SDL2/src/video/SDL_video.c \
dosbox-x/third_party/SDL2/src/video/SDL_vulkan_utils.c \
dosbox-x/third_party/SDL2/src/video/SDL_yuv.c \
dosbox-x/third_party/SDL2/src/video/yuv2rgb/yuv_rgb_lsx.c \
dosbox-x/third_party/SDL2/src/video/yuv2rgb/yuv_rgb_sse.c \
dosbox-x/third_party/SDL2/src/video/yuv2rgb/yuv_rgb_std.c \
dosbox-x/third_party/SDL2/src/locale/SDL_locale.c \
dosbox-x/third_party/SDL2/src/video/dummy/SDL_nullevents.c \
dosbox-x/third_party/SDL2/src/video/dummy/SDL_nullframebuffer.c \
dosbox-x/third_party/SDL2/src/video/dummy/SDL_nullvideo.c \
dosbox-x/third_party/SDL2/src/audio/dummy/SDL_dummyaudio.c \
dosbox-x/third_party/SDL2/src/loadso/dlopen/SDL_sysloadso.c \
dosbox-x/third_party/SDL2/src/timer/unix/SDL_systimer.c \
dosbox-x/third_party/SDL2/src/core/linux/SDL_threadprio.c \
dosbox-x/third_party/SDL2/src/core/linux/SDL_sandbox.c \
dosbox-x/third_party/SDL2/src/core/unix/SDL_poll.c \
dosbox-x/third_party/SDL2/src/misc/dummy/SDL_sysurl.c \
dosbox-x/third_party/SDL2/src/locale/dummy/SDL_syslocale.c \
dosbox-x/third_party/SDL2/src/sensor/dummy/SDL_dummysensor.c \
dosbox-x/third_party/SDL2/src/thread/generic/SDL_syscond.c \
dosbox-x/third_party/SDL2/src/thread/generic/SDL_sysmutex.c \
dosbox-x/third_party/SDL2/src/thread/generic/SDL_syssem.c \
dosbox-x/third_party/SDL2/src/thread/generic/SDL_systhread.c \
dosbox-x/third_party/SDL2/src/thread/generic/SDL_systls.c \
dosbox-x/third_party/SDL2/src/filesystem/dummy/SDL_sysfilesystem.c
include ../common.mak

419
waterbox/dosbox/bizhawk.cpp Normal file
View File

@ -0,0 +1,419 @@
#include "bizhawk.hpp"
#include "../libco/libco.h"
#include <stdlib.h>
#include <config.h>
#include <sdlmain.h>
#include <render.h>
#include <keyboard.h>
#include <set>
#include <jaffarCommon/file.hpp>
#include <mixer.h>
#include <joystick.h>
#include <mouse.h>
#include <vga.h>
#include <mem.h>
#define DOS_DRIVE_A 0
#define DOS_DRIVE_D 3
// DOSBox functions
extern int _main(int argc, char* argv[]);
void runMain() { _main(0, nullptr); }
extern void VGA_SetupDrawing(Bitu /*val*/);
extern void swapInDrive(int drive, unsigned int position);
// Coroutines: they allow us to jump in and out the dosbox core
cothread_t _emuCoroutine;
cothread_t _driverCoroutine;
// Timing-related stuff
double ticksTarget;
double ticksPerFrame;
uint32_t _ticksElapsed;
uint32_t _GetTicks() { return _ticksElapsed; }
void _Delay(uint32_t ticks) { _ticksElapsed += ticks; co_switch(_driverCoroutine); }
// Dosbox internal refresh rate information
int _refreshRateNumerator = 0;
int _refreshRateDenominator = 0;
// Memory file directory
jaffarCommon::file::MemoryFileDirectory _memFileDirectory;
// Audio stuff
std::vector<int16_t> _audioSamples;
// Keyboard related variables
std::set<KBD_KEYS> _prevPressedKeys;
extern std::set<KBD_KEYS> _pressedKeys;
extern std::set<KBD_KEYS> _releasedKeys;
// mouse related variables
extern int mickey_threshold;
extern bool user_cursor_locked;
#define MOUSE_MAX_X 800
#define MOUSE_MAX_Y 600
bool loadFileIntoMemoryFileDirectory(const std::string& srcFile, const std::string& dstFile, const ssize_t dstSize = -1)
{
// Loading entire source file
std::string srcFileData;
bool status = jaffarCommon::file::loadStringFromFile(srcFileData, srcFile);
if (status == false) { fprintf(stderr, "Could not find/read from file: %s\n", srcFile.c_str()); return false; }
// Uploading file into the mem file directory
auto f = _memFileDirectory.fopen(dstFile, "w");
if (f == NULL) { fprintf(stderr, "Could not open mem file for write: %s\n", dstFile.c_str()); return false; }
// Copying data into mem file
auto writtenBlocks = jaffarCommon::file::MemoryFile::fwrite(srcFileData.data(), 1, srcFileData.size(), f);
if (writtenBlocks != srcFileData.size())
{
fprintf(stderr, "Could not write data into mem file: %s\n", dstFile.c_str());
_memFileDirectory.fclose(f);
return false;
}
// If required, resize dst file
if (dstSize >= 0)
{
auto ret = f->resize(dstSize);
if (ret < 0)
{
fprintf(stderr, "Could not resize mem file: %s\n", dstFile.c_str());
_memFileDirectory.fclose(f);
return false;
}
}
// Closing mem file
_memFileDirectory.fclose(f);
return true;
}
// Drive activity monitoring
bool _driveUsed = false;
ECL_EXPORT bool getDriveActivityFlag() { return _driveUsed; }
// SRAM Management
bool _preserveHardDiskContents;
constexpr char writableHDDSrcFile[] = "__WritableHardDiskDrive";
constexpr char writableHDDDstFile[] = "__WritableHardDiskDrive.img";
int get_sram_size() { return (int)_memFileDirectory.getFileSize(writableHDDDstFile); }
uint8_t* get_sram_buffer() { return _memFileDirectory.getFileBuffer(writableHDDDstFile); }
ECL_EXPORT bool Init(InitSettings* settings)
{
// If size is non-negative, we need to load the writable hard disk into memory
if (settings->writableHDDImageFileSize == 0) printf("No writable hard disk drive selected.");
else {
// Loading HDD file into mem file directory
printf("Creating hard disk drive mem file '%s' -> '%s' (%lu bytes)\n", writableHDDSrcFile, writableHDDDstFile, settings->writableHDDImageFileSize);
auto result = loadFileIntoMemoryFileDirectory(writableHDDSrcFile, writableHDDDstFile, settings->writableHDDImageFileSize);
if (result == false || _memFileDirectory.contains(writableHDDDstFile) == false)
{
fprintf(stderr, "Could not create hard disk drive mem file\n");
return false;
}
}
// Storing hard disk preservation option
_preserveHardDiskContents = settings->preserveHardDiskContents == 1;
// Setting dummy drivers for env variables
setenv("SDL_VIDEODRIVER", "dummy", 1);
setenv("SDL_AUDIODRIVER", "dummy", 1);
printf("Starting DOSBox-x Coroutine...\n");
_driverCoroutine = co_active();
constexpr size_t stackSize = 4 * 1024 * 1024;
_emuCoroutine = co_create(stackSize, runMain);
co_switch(_emuCoroutine);
// Initializing joysticks
stick[0].enabled = settings->joystick1Enabled == 1;
stick[1].enabled = settings->joystick2Enabled == 1;
stick[0].xpos = 0.0;
stick[0].ypos = 0.0;
stick[0].button[0] = false;
stick[0].button[1] = false;
stick[1].xpos = 0.0;
stick[1].ypos = 0.0;
stick[1].button[0] = false;
stick[1].button[1] = false;
// Initializing mouse
user_cursor_locked = true;
// Setting initial timing values
ticksTarget = 0.0;
_ticksElapsed = 0;
return true;
}
// A callback function to update the output render, only when requested by the core
// Doing it on demand avoids screen tearing
uint32_t* _videoBuffer = nullptr;
size_t _videoBufferSize = 0;
int _videoWidth = 0;
int _videoHeight = 0;
void doRenderUpdateCallback()
{
// printf("w: %u, h: %u, bytes: %p\n", sdl.surface->w, sdl.surface->h, sdl.surface->pixels);
bool allocateBuffer = false;
if (sdl.surface->w != _videoWidth) { allocateBuffer = true; _videoWidth = sdl.surface->w; }
if (sdl.surface->h != _videoHeight) { allocateBuffer = true; _videoHeight = sdl.surface->h; }
_videoBufferSize = _videoWidth * _videoHeight * sizeof(uint32_t);
if (allocateBuffer == true)
{
if (_videoBuffer != nullptr) free(_videoBuffer);
_videoBuffer = (uint32_t*) malloc(_videoBufferSize);
}
// Updating buffer
memcpy(_videoBuffer, sdl.surface->pixels, _videoBufferSize);
}
ECL_EXPORT void FrameAdvance(MyFrameInfo* f)
{
// Clearing drive use flag
_driveUsed = false;
// Processing keyboard inputs
_releasedKeys.clear();
_pressedKeys.clear();
std::set<KBD_KEYS> newPressedKeys;
for (size_t i = 0; i < KEY_COUNT; i++)
{
auto key = (KBD_KEYS)i;
bool wasPressed = _prevPressedKeys.find(key) != _prevPressedKeys.end();
if (f->Keys[i] > 0)
{
if (wasPressed == false) _pressedKeys.insert(key);
newPressedKeys.insert(key);
}
if (f->Keys[i] == 0) if (wasPressed == true) _releasedKeys.insert(key);
}
_prevPressedKeys = newPressedKeys;
// Processing drive swapping
if (f->driveActions.insertFloppyDisk >= 0)
{
printf("Swapping to Floppy Disk: %d\n", f->driveActions.insertFloppyDisk);
swapInDrive(DOS_DRIVE_A, f->driveActions.insertFloppyDisk + 1); // 0 is A:
}
if (f->driveActions.insertCDROM >= 0)
{
printf("Swapping to CDROM: %d\n", f->driveActions.insertCDROM);
swapInDrive(DOS_DRIVE_D, f->driveActions.insertCDROM + 1); // 3 is D:
}
// Processing joystick inputs
if (stick[0].enabled)
{
stick[0].xpos = 0.0;
stick[0].ypos = 0.0;
if (f->joy1.up) stick[0].ypos = -1.0f;
if (f->joy1.down) stick[0].ypos = 1.0f;
if (f->joy1.left) stick[0].xpos = -1.0f;
if (f->joy1.right) stick[0].xpos = 1.0f;
stick[0].button[0] = f->joy1.button1;
stick[0].button[1] = f->joy1.button2;
}
if (stick[1].enabled)
{
stick[1].xpos = 0.0;
stick[1].ypos = 0.0;
if (f->joy2.up) stick[1].ypos = -1.0f;
if (f->joy2.down) stick[1].ypos = 1.0f;
if (f->joy2.left) stick[1].xpos = -1.0f;
if (f->joy2.right) stick[1].xpos = 1.0f;
stick[1].button[0] = f->joy2.button1;
stick[1].button[1] = f->joy2.button2;
}
// Processing mouse inputs
if (f->mouse.speedX != 0 || f->mouse.speedY != 0)
{
mouse.x = (double)mouse.min_x + ((double) f->mouse.posX / (double)MOUSE_MAX_X) * (double)mouse.max_x;
mouse.y = (double)mouse.min_y + ((double) f->mouse.posY / (double)MOUSE_MAX_Y) * (double)mouse.max_y;
float adjustedDeltaX = (float) f->mouse.speedX * (float) f->mouse.sensitivity;
float adjustedDeltaY = (float) f->mouse.speedY * (float) f->mouse.sensitivity;
float dx = adjustedDeltaX * mouse.pixelPerMickey_x;
float dy = adjustedDeltaY * mouse.pixelPerMickey_y;
mouse.mickey_x = adjustedDeltaX * mouse.mickeysPerPixel_x ;
mouse.mickey_y = adjustedDeltaY * mouse.mickeysPerPixel_y ;
mouse.mickey_accum_x += (dx * mouse.mickeysPerPixel_x);
mouse.mickey_accum_y += (dy * mouse.mickeysPerPixel_y);
mouse.ps2x += adjustedDeltaX;
mouse.ps2y += adjustedDeltaY;
if (mouse.ps2x >= 32768.0) mouse.ps2x -= 65536.0;
else if (mouse.ps2x <= -32769.0) mouse.ps2x += 65536.0;
if (mouse.ps2y >= 32768.0) mouse.ps2y -= 65536.0;
else if (mouse.ps2y <= -32769.0) mouse.ps2y += 65536.0;
// printf("X: %d (%d) Y: %d (%d)\n", f->mouse.posX, f->mouse.speedX, f->mouse.posY, f->mouse.speedY);
// printf("%d %f %d %f\n", mouse.mickey_x, mouse.mickey_accum_x, mouse.mickey_y, mouse.mickey_accum_y);
Mouse_AddEvent(MOUSE_HAS_MOVED);
}
if (f->mouse.leftButtonPressed) Mouse_ButtonPressed(0);
if (f->mouse.middleButtonPressed) Mouse_ButtonPressed(2);
if (f->mouse.rightButtonPressed) Mouse_ButtonPressed(1);
if (f->mouse.leftButtonReleased) Mouse_ButtonReleased(0);
if (f->mouse.middleButtonReleased) Mouse_ButtonReleased(2);
if (f->mouse.rightButtonReleased) Mouse_ButtonReleased(1);
// Clearing audio sample buffer
_audioSamples.clear();
// Calculating fps
double fps = (double)f->framerateNumerator / (double)f->framerateDenominator;
ticksPerFrame = 1000.0 / fps;
//printf("Running Framerate: %d / %d = %f\n", f->framerateNumerator, f->framerateDenominator, fps);
// Increasing ticks target
ticksTarget += ticksPerFrame;
// Advancing until the required tick target is met
while (_ticksElapsed < (int)ticksTarget) co_switch(_emuCoroutine);
// Updating ticks elapsed
f->base.Cycles = _ticksElapsed;
// Updating video output
// printf("w: %u, h: %u, bytes: %p\n", sdl.surface->w, sdl.surface->h, sdl.surface->pixels);
f->base.Width = sdl.surface->w;
f->base.Height = sdl.surface->h;
// size_t checksum = 0;
// for (size_t i = 0; i < sdl.surface->w * sdl.surface->h * 4; i++) checksum += ((uint8_t*)sdl.surface->pixels)[i];
// printf("Video checksum: %lu\n", checksum);
if (_videoBuffer != nullptr) memcpy(f->base.VideoBuffer, _videoBuffer, _videoBufferSize);
// Checking audio sample count
// size_t checksum = 0;
// for (size_t i = 0; i < _audioSamples.size(); i++) checksum += _audioSamples[i];
// printf("Audio samples: %lu - Checksum: %lu\n", _audioSamples.size(), checksum);
// Setting audio buffer
memcpy(f->base.SoundBuffer, _audioSamples.data(), _audioSamples.size() * sizeof(int16_t));
f->base.Samples = _audioSamples.size() / 2;
}
ECL_EXPORT uint64_t getRefreshRateNumerator() { return _refreshRateNumerator; }
ECL_EXPORT uint64_t getRefreshRateDenominator() { return _refreshRateDenominator; }
ECL_EXPORT uint32_t getTicksElapsed() { return _ticksElapsed; }
#define DOS_CONVENTIONAL_MEMORY_SIZE (640 * 1024)
#define DOS_UPPER_MEMORY_SIZE (384 * 1024)
#define DOS_LOWER_MEMORY_SIZE (DOS_CONVENTIONAL_MEMORY_SIZE + DOS_UPPER_MEMORY_SIZE)
/// CD Management Logic Start
void (*cd_read_callback)(char* cdRomFile, int32_t lba, void * dest, int sectorSize);
ECL_EXPORT void SetCdCallbacks(void (*cdrc)(char* cdRomFile, int32_t lba, void * dest, int sectorSize))
{
cd_read_callback = cdrc;
}
CDData_t _cdData[MAX_CD_COUNT];
size_t _cdCount = 0;
ECL_EXPORT void pushCDData(int cdIdx, int numSectors, int numTracks)
{
_cdCount++;
_cdData[cdIdx].numSectors = numSectors;
_cdData[cdIdx].numTracks = numTracks;
printf("Pushing CD %d. NumSectors: %d, NumTracks: %d\n", cdIdx, _cdData[cdIdx].numSectors, _cdData[cdIdx].numTracks);
}
ECL_EXPORT void pushTrackData(int cdIdx, int trackId, CDTrack_t* data)
{
_cdData[cdIdx].tracks[trackId] = *data;
printf(" + CD: %d Track %d - Offset: %d - Start: %d - End: %d - Mode: %d - loopEnabled: %d - loopOffset: %d\n", cdIdx, trackId,
_cdData[cdIdx].tracks[trackId].offset,
_cdData[cdIdx].tracks[trackId].start,
_cdData[cdIdx].tracks[trackId].end,
_cdData[cdIdx].tracks[trackId].mode,
_cdData[cdIdx].tracks[trackId].loopEnabled,
_cdData[cdIdx].tracks[trackId].loopOffset);
}
/// CD Management Logic End
ECL_EXPORT void GetMemoryAreas(MemoryArea *m)
{
int memAreaIdx = 0;
m[memAreaIdx].Data = MemBase;
m[memAreaIdx].Name = "Conventional Memory";
m[memAreaIdx].Size = DOS_CONVENTIONAL_MEMORY_SIZE;
m[memAreaIdx].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_PRIMARY;
memAreaIdx++;
m[memAreaIdx].Data = &MemBase[DOS_CONVENTIONAL_MEMORY_SIZE];
m[memAreaIdx].Name = "Upper Memory Area";
m[memAreaIdx].Size = DOS_UPPER_MEMORY_SIZE;
m[memAreaIdx].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE;
memAreaIdx++;
int highMemSize = MemSize - DOS_LOWER_MEMORY_SIZE;
if (highMemSize > 0)
{
m[memAreaIdx].Data = &MemBase[DOS_LOWER_MEMORY_SIZE];
m[memAreaIdx].Name = "Extended Memory";
m[memAreaIdx].Size = MemSize - DOS_LOWER_MEMORY_SIZE;
m[memAreaIdx].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE;
memAreaIdx++;
}
m[memAreaIdx].Data = MemBase;
m[memAreaIdx].Name = "Physical RAM";
m[memAreaIdx].Size = MemSize;
m[memAreaIdx].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE;
memAreaIdx++;
m[memAreaIdx].Data = vga.mem.linear;
m[memAreaIdx].Name = "Video RAM";
m[memAreaIdx].Size = vga.mem.memsize;
m[memAreaIdx].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE;
memAreaIdx++;
size_t sramSize = get_sram_size();
if (sramSize > 0)
{
m[memAreaIdx].Data = get_sram_buffer();
m[memAreaIdx].Name = "Writeable HDD (SaveRAM)";
m[memAreaIdx].Size = sramSize;
m[memAreaIdx].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE;
m[memAreaIdx].Flags |= _preserveHardDiskContents ? MEMORYAREA_FLAGS_SAVERAMMABLE : 0;
memAreaIdx++;
}
}
void (*LEDCallback)();
ECL_EXPORT void SetLEDCallback(void (*callback)())
{
LEDCallback = callback;
}
void (*InputCallback)();
ECL_EXPORT void SetInputCallback(void (*callback)())
{
InputCallback = callback;
}

View File

@ -0,0 +1,65 @@
#pragma once
// system
#include <limits.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
// waterbox
#include "emulibc.h"
#include "waterboxcore.h"
#include <src/dos/cdrom.h>
const int KEY_COUNT = 0x65;
typedef struct
{
int joystick1Enabled;
int joystick2Enabled;
uint64_t writableHDDImageFileSize;
int preserveHardDiskContents;
} InitSettings;
typedef struct
{
int insertFloppyDisk;
int insertCDROM;
} DriveActions;
typedef struct
{
int up;
int down;
int left;
int right;
int button1;
int button2;
} JoystickButtons;
typedef struct
{
int posX;
int posY;
int speedX;
int speedY;
int leftButtonPressed;
int middleButtonPressed;
int rightButtonPressed;
int leftButtonReleased;
int middleButtonReleased;
int rightButtonReleased;
float sensitivity;
} MouseInput;
typedef struct
{
FrameInfo base;
char Keys[KEY_COUNT];
DriveActions driveActions;
JoystickButtons joy1;
JoystickButtons joy2;
MouseInput mouse;
int framerateNumerator;
int framerateDenominator;
} MyFrameInfo;

@ -0,0 +1 @@
Subproject commit 3df6c89bae10917e1d8bef32d3e8abba09965b31

View File

@ -6,6 +6,7 @@ make -C emulibc $1 -j
make -C libco $1 -j
./ares64/make-both.sh $1
make -C bsnescore $1 -j
make -C dosbox $1 -j8
make -C dsda $1 -j
make -C gpgx $1 -j
make -C libsnes $1 -j

View File

@ -39,6 +39,7 @@ It consists of a modified musl libc, and build scripts to tie it all together.
* waterbox/uae/libretro-uae (required for uae)
* waterbox/stella/core (required for stella)
* waterbox/dsda/core (required for dsda)
* waterbox/dosbox/dosbox-x (required for DOSBox-x)
* none of these submodules need to be cloned recursively
3. Consider whether it is time to update your build environment (i.e. sudo apt-get upgrade). Build environment tools are generally best kept at the latest version, to ensure top performance for our users.
@ -65,6 +66,7 @@ It consists of a modified musl libc, and build scripts to tie it all together.
6. You are now ready to start building cores. Each supports `make` and `make install`, as well as `make debug` and `make install-debug` for local development. From the root directory, the following should all be valid:
cd ares64 && ./make-both.sh
cd bsnescore && make install
cd dosbox && make install
cd dsda && make install
cd gpgx && make install
cd libsnes && make install