Removed DOSBox OPL code, and made NukedOPL, the CD-ROM image code (incl. former cdrom_dosbox.cpp/h), and Raw Input mouse code C instead of C++, and fixed OPL2 emulation with NukedOPL.

This commit is contained in:
OBattler
2019-12-21 20:06:34 +01:00
parent 6881b6ec64
commit 51b06be28c
25 changed files with 1476 additions and 3437 deletions

View File

@@ -8,7 +8,7 @@
*
* Generic CD-ROM drive core.
*
* Version: @(#)cdrom.c 1.0.8 2019/09/26
* Version: @(#)cdrom.c 1.0.9 2019/12/13
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -332,7 +332,7 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf)
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
pclog("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
cdrom_stop(dev);
return 0;
}

View File

@@ -1,884 +0,0 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* CD-ROM image file handling module.
*
* Re-hacked to remove the dirname() function, and to have this
* code using stdio instead of C++ fstream - fstream cannot deal
* with Unicode pathnames, and we need those. --FvK
*
* **NOTE** This code will very soon be replaced with a C variant, so
* no more changes will be done.
*
* Version: @(#)cdrom_dosbox.cpp 1.0.12 2019/10/22
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* The DOSBox Team, <unknown>
*
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2016-2019 Miran Grca.
* Copyright 2002-2019 The DOSBox Team.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define __STDC_FORMAT_MACROS
#include <stdarg.h>
#include <cinttypes>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#ifdef _WIN32
# include <string.h>
#else
# include <libgen.h>
#endif
#include <wchar.h>
#include <vector>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../plat.h"
#include "cdrom_dosbox.h"
using namespace std;
#define MAX_LINE_LENGTH 512
#define MAX_FILENAME_LENGTH 256
#define CROSS_LEN 512
#ifdef ENABLE_CDROM_DOSBOX_LOG
int cdrom_dosbox_do_log = ENABLE_CDROM_DOSBOX_LOG;
void
cdrom_dosbox_log(const char *fmt, ...)
{
va_list ap;
if (cdrom_dosbox_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define cdrom_dosbox_log(fmt, ...)
#endif
CDROM_Interface_Image::BinaryFile::BinaryFile(const wchar_t *filename, bool &error)
{
memset(fn, 0x00, sizeof(fn));
wcscpy(fn, filename);
file = plat_fopen64(fn, L"rb");
cdrom_dosbox_log("CDROM: binary_open(%ls) = %08lx\n", fn, file);
if (file == NULL)
error = true;
else
error = false;
}
CDROM_Interface_Image::BinaryFile::~BinaryFile(void)
{
if (file != NULL) {
fclose(file);
file = NULL;
}
memset(fn, 0x00, sizeof(fn));
}
bool
CDROM_Interface_Image::BinaryFile::read(uint8_t *buffer, uint64_t seek, size_t count)
{
cdrom_dosbox_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n",
file, seek, count);
if (file == NULL) return 0;
fseeko64(file, seek, SEEK_SET);
if (fread(buffer, count, 1, file) != 1) {
#ifdef ENABLE_CDROM_DOSBOX_LOG
cdrom_dosbox_log("CDROM: binary_read failed!\n");
#endif
return 0;
}
return 1;
}
uint64_t
CDROM_Interface_Image::BinaryFile::getLength(void)
{
off64_t len;
cdrom_dosbox_log("CDROM: binary_length(%08lx)\n", file);
if (file == NULL) return 0;
fseeko64(file, 0, SEEK_END);
len = ftello64(file);
cdrom_dosbox_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", file, len);
return len;
}
CDROM_Interface_Image::CDROM_Interface_Image(void)
{
}
CDROM_Interface_Image::~CDROM_Interface_Image(void)
{
ClearTracks();
}
void
CDROM_Interface_Image::InitNewMedia(void)
{
}
bool
CDROM_Interface_Image::SetDevice(const wchar_t *path, int forceCD)
{
(void)forceCD;
if (CueLoadSheet(path)) return true;
if (IsoLoadFile(path)) return true;
return false;
}
bool
CDROM_Interface_Image::GetUPC(uint8_t& attr, char* upc)
{
attr = 0;
strcpy(upc, this->mcn.c_str());
return true;
}
bool
CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut)
{
stTrack = 1;
end = (int)(tracks.size() - 1);
FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr);
return true;
}
bool
CDROM_Interface_Image::GetAudioTrackInfo(int track, int& track_number, TMSF& start, uint8_t& attr)
{
if (track < 1 || track > (int)tracks.size()) return false;
FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr);
track_number = tracks[track - 1].track_number;
attr = tracks[track - 1].attr;
return true;
}
bool
CDROM_Interface_Image::GetAudioTrackEndInfo(int track, int& track_number, TMSF& start, unsigned char& attr)
{
if (track < 1 || track > (int)tracks.size()) return false;
FRAMES_TO_MSF(tracks[track - 1].start + tracks[track - 1].length + 150, &start.min, &start.sec, &start.fr);
track_number = tracks[track - 1].track_number;
attr = tracks[track - 1].attr;
return true;
}
bool
CDROM_Interface_Image::GetAudioSub(int sector, uint8_t& attr, uint8_t& track, uint8_t& index, TMSF& relPos, TMSF& absPos)
{
int cur_track = GetTrack(sector);
if (cur_track < 1) return false;
track = (uint8_t)cur_track;
attr = tracks[track - 1].attr;
index = 1;
FRAMES_TO_MSF(sector + 150, &absPos.min, &absPos.sec, &absPos.fr);
/* Absolute position should be adjusted by 150, not the relative ones. */
FRAMES_TO_MSF(sector - tracks[track - 1].start, &relPos.min, &relPos.sec, &relPos.fr);
return true;
}
bool
CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
{
mediaPresent = true;
mediaChanged = false;
trayOpen = false;
return true;
}
bool
CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, uint32_t sector, uint32_t num)
{
int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
uint8_t buflen = num * sectorSize;
uint8_t* buf = new uint8_t[buflen];
bool success = true; /* reading 0 sectors is OK */
uint32_t i;
for (i = 0; i < num; i++) {
success = ReadSector(&buf[i * sectorSize], raw, sector + i);
if (! success) break;
}
memcpy((void*)buffer, buf, buflen);
delete[] buf;
return success;
}
bool
CDROM_Interface_Image::LoadUnloadMedia(bool unload)
{
(void)unload;
return true;
}
int
CDROM_Interface_Image::GetTrack(unsigned int sector)
{
vector<Track>::iterator i = tracks.begin();
vector<Track>::iterator end = tracks.end() - 1;
while (i != end) {
Track &curr = *i;
Track &next = *(i + 1);
if (curr.start <= sector && sector < next.start)
return curr.number;
i++;
}
return -1;
}
bool
CDROM_Interface_Image::ReadSector(uint8_t *buffer, bool raw, uint32_t sector)
{
size_t length;
int track = GetTrack(sector) - 1;
if (track < 0) return false;
uint64_t s = (uint64_t) sector;
uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize);
if (tracks[track].mode2)
length = (raw ? RAW_SECTOR_SIZE : 2336);
else
length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE);
if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false;
if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16;
if (tracks[track].mode2 && !raw) seek += 24;
return tracks[track].file->read(buffer, seek, length);
}
bool
CDROM_Interface_Image::ReadSectorSub(uint8_t *buffer, uint32_t sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return false;
uint64_t s = (uint64_t) sector;
uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize);
if (tracks[track].sectorSize != 2448) return false;
return tracks[track].file->read(buffer, seek, 2448);
}
int
CDROM_Interface_Image::GetSectorSize(uint32_t sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return 0;
return tracks[track].sectorSize;
}
bool
CDROM_Interface_Image::IsMode2(uint32_t sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return false;
if (tracks[track].mode2)
return true;
return false;
}
int
CDROM_Interface_Image::GetMode2Form(uint32_t sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return false;
return tracks[track].form;
}
bool
CDROM_Interface_Image::CanReadPVD(TrackFile *file, uint64_t sectorSize, bool mode2)
{
uint8_t pvd[COOKED_SECTOR_SIZE];
uint64_t seek = 16 * sectorSize; // first vd is located at sector 16
if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16;
if (mode2) seek += 24;
file->read(pvd, seek, COOKED_SECTOR_SIZE);
#if 0
pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version (+8 for High Sierra)
#endif
return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) ||
(pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1));
}
bool
CDROM_Interface_Image::IsoLoadFile(const wchar_t *filename)
{
tracks.clear();
// data track
Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL};
bool error;
track.file = new BinaryFile(filename, error);
if (error) {
delete track.file;
return false;
}
track.number = 1;
track.track_number = 1; //IMPORTANT: This is needed.
track.attr = DATA_TRACK; //data
track.form = 0;
// try to detect iso type
if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) {
track.sectorSize = COOKED_SECTOR_SIZE;
track.mode2 = false;
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = false;
} else if (CanReadPVD(track.file, 2336, true)) {
track.sectorSize = 2336;
track.mode2 = true;
} else if (CanReadPVD(track.file, 2324, true)) {
track.sectorSize = 2324;
track.form = 2;
track.mode2 = true;
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = true;
} else {
/* Unknown mode: Assume regular 2048-byte sectors, this is needed so Apple Rhapsody ISO's can be mounted. */
track.sectorSize = COOKED_SECTOR_SIZE;
track.mode2 = false;
}
track.length = track.file->getLength() / track.sectorSize;
tracks.push_back(track);
// leadout track
track.number = 2;
track.track_number = 0xAA;
track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */
track.start = track.length;
track.length = 0;
track.file = NULL;
tracks.push_back(track);
return true;
}
bool
CDROM_Interface_Image::CueGetBuffer(char *str, char **line, bool up)
{
char *s = *line;
char *p = str;
int quote = 0;
int done = 0;
int space = 1;
/* Copy to local buffer until we have end of string or whitespace. */
while (! done) {
switch(*s) {
case '\0':
if (quote) {
/* Ouch, unterminated string.. */
return false;
}
done = 1;
break;
case '\"':
quote ^= 1;
break;
case ' ':
case '\t':
if (space)
break;
if (! quote) {
done = 1;
break;
}
/*FALLTHROUGH*/
default:
if (up && islower((int) *s))
*p++ = toupper((int) *s);
else
*p++ = *s;
space = 0;
break;
}
if (! done)
s++;
}
*p = '\0';
*line = s;
return true;
}
/* Get a filename string from the input line. */
bool
CDROM_Interface_Image::CueGetString(string &dest, char **line)
{
char temp[1024];
bool success;
success = CueGetBuffer(temp, line, false);
if (success)
dest = temp;
return success;
}
bool
CDROM_Interface_Image::CueGetKeyword(string &dest, char **line)
{
char temp[1024];
bool success;
success = CueGetBuffer(temp, line, true);
if (success)
dest = temp;
return success;
}
/* Get a string from the input line, handling quotes properly. */
uint64_t
CDROM_Interface_Image::CueGetNumber(char **line)
{
char temp[128];
uint64_t num;
if (! CueGetBuffer(temp, line, false))
return 0;
if (sscanf(temp, "%" PRIu64, &num) != 1)
return 0;
return num;
}
bool
CDROM_Interface_Image::CueGetFrame(uint64_t &frames, char **line)
{
char temp[128];
int min, sec, fr;
bool success;
success = CueGetBuffer(temp, line, false);
if (! success) return false;
success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3;
if (! success) return false;
frames = MSF_TO_FRAMES(min, sec, fr);
return true;
}
bool
CDROM_Interface_Image::CueLoadSheet(const wchar_t *cuefile)
{
Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL};
wchar_t pathname[MAX_FILENAME_LENGTH];
uint64_t shift = 0;
uint64_t currPregap = 0;
uint64_t totalPregap = 0;
uint64_t prestart = 0;
int i;
bool canAddTrack = false;
bool success;
FILE *fp;
wstring name(L"r");
tracks.clear();
/* Get a copy of the filename into pathname, we need it later. */
memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t));
plat_get_dirname(pathname, cuefile);
/* Open the file. */
fp = plat_fopen((wchar_t *) cuefile, (wchar_t *) name.c_str());
if (fp == NULL)
return false;
success = false;
for (;;) {
char buf[MAX_LINE_LENGTH];
char *line = buf;
/* Read a line from the cuesheet file. */
if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp))
break;
/* Do two iterations to make sure to nuke even if it's \r\n or \n\r,
but do checks to make sure we're not nuking other bytes. */
for (i = 0; i < 2; i++) {
if (strlen(buf) > 0) {
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */
else if (buf[strlen(buf) - 1] == '\r')
buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */
}
}
string command;
success = CueGetKeyword(command, &line);
if (command == "TRACK") {
if (canAddTrack)
success = AddTrack(track, shift, prestart, totalPregap, currPregap);
else
success = true;
track.start = 0;
track.skip = 0;
currPregap = 0;
prestart = 0;
track.number = CueGetNumber(&line);
track.track_number = track.number;
string type;
success = CueGetKeyword(type, &line);
if (! success) break;
track.form = 0;
if (type == "AUDIO") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = AUDIO_TRACK;
track.mode2 = false;
} else if (type == "MODE1/2048") {
track.sectorSize = COOKED_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = false;
} else if (type == "MODE1/2352") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = false;
} else if (type == "MODE2/2048") {
track.form = 1;
track.sectorSize = 2048;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "MODE2/2324") {
track.form = 2;
track.sectorSize = 2324;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "MODE2/2336") {
track.sectorSize = 2336;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "MODE2/2352") {
track.form = 1; /* Assume this is XA Mode 2 Form 1. */
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "CDG/2448") {
track.sectorSize = 2448;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "CDI/2336") {
track.sectorSize = 2336;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "CDI/2352") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = true;
} else
success = false;
canAddTrack = true;
} else if (command == "INDEX") {
uint64_t frame = 0ULL, index;
index = CueGetNumber(&line);
success = CueGetFrame(frame, &line);
switch(index) {
case 0:
prestart = frame;
break;
case 1:
track.start = frame;
break;
default:
/* ignore other indices */
break;
}
} else if (command == "FILE") {
if (canAddTrack)
success = AddTrack(track, shift, prestart, totalPregap, currPregap);
else
success = true;
canAddTrack = false;
char ansi[MAX_FILENAME_LENGTH];
wchar_t filename[MAX_FILENAME_LENGTH];
string type;
memset(ansi, 0, MAX_FILENAME_LENGTH);
memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t));
success = CueGetBuffer(ansi, &line, false);
if (! success) break;
success = CueGetKeyword(type, &line);
if (! success) break;
track.file = NULL;
bool error = true;
if (type == "BINARY") {
wchar_t temp[MAX_FILENAME_LENGTH];
memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t));
mbstowcs(temp, ansi, sizeof_w(temp));
plat_append_filename(filename, pathname, temp);
track.file = new BinaryFile(filename, error);
}
if (error) {
#ifdef ENABLE_CDROM_DOSBOX_LOG
cdrom_dosbox_log("CUE: cannot open fille '%ls' in cue sheet!\n",
filename);
#endif
delete track.file;
track.file = NULL;
success = false;
}
} else if (command == "PREGAP")
success = CueGetFrame(currPregap, &line);
else if (command == "CATALOG") {
success = CueGetString(mcn, &line);
// ignored commands
} else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC"
|| command == "PERFORMER" || command == "POSTGAP" || command == "REM"
|| command == "SONGWRITER" || command == "TITLE" || command == "") success = true;
// failure
else {
#ifdef ENABLE_CDROM_DOSBOX_LOG
cdrom_dosbox_log("CUE: unsupported command '%s' in cue sheet!\n",
command.c_str());
#endif
success = false;
}
if (! success)
break;
}
fclose(fp);
if (! success)
return false;
// add last track
if (! AddTrack(track, shift, prestart, totalPregap, currPregap))
return false;
// add leadout track
track.number++;
track.track_number = 0xAA;
// track.attr = 0;//sync with load iso
track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */
track.start = 0;
track.length = 0;
track.file = NULL;
if (! AddTrack(track, shift, 0, totalPregap, 0))
return false;
return true;
}
bool
CDROM_Interface_Image::AddTrack(Track &curr, uint64_t &shift, uint64_t prestart, uint64_t &totalPregap, uint64_t currPregap)
{
// frames between index 0(prestart) and 1(curr.start) must be skipped
uint64_t skip;
if (prestart > 0) {
if (prestart > curr.start) return false;
skip = curr.start - prestart;
} else skip = 0;
// first track (track number must be 1)
if (tracks.empty()) {
if (curr.number != 1) return false;
curr.skip = skip * curr.sectorSize;
curr.start += currPregap;
totalPregap = currPregap;
tracks.push_back(curr);
return true;
}
Track &prev = *(tracks.end() - 1);
// current track consumes data from the same file as the previous
if (prev.file == curr.file) {
curr.start += shift;
prev.length = curr.start + totalPregap - prev.start - skip;
curr.skip += prev.skip + (prev.length * prev.sectorSize) + (skip * curr.sectorSize);
totalPregap += currPregap;
curr.start += totalPregap;
// current track uses a different file as the previous track
} else {
uint64_t tmp = prev.file->getLength() - ((uint64_t) prev.skip);
prev.length = tmp / ((uint64_t) prev.sectorSize);
if (tmp % prev.sectorSize != 0) prev.length++; // padding
curr.start += prev.start + prev.length + currPregap;
curr.skip = skip * curr.sectorSize;
shift += prev.start + prev.length;
totalPregap = currPregap;
}
// error checks
if (curr.number <= 1) return false;
if (prev.number + 1 != curr.number) return false;
if (curr.start < prev.start + prev.length) return false;
tracks.push_back(curr);
return true;
}
bool
CDROM_Interface_Image::HasDataTrack(void)
{
//Data track has attribute 0x14
for (track_it it = tracks.begin(); it != tracks.end(); it++) {
if ((*it).attr == DATA_TRACK) return true;
}
return false;
}
bool
CDROM_Interface_Image::HasAudioTracks(void)
{
for (track_it it = tracks.begin(); it != tracks.end(); it++) {
if ((*it).attr == AUDIO_TRACK) return true;
}
return false;
}
void
CDROM_Interface_Image::ClearTracks(void)
{
vector<Track>::iterator i = tracks.begin();
vector<Track>::iterator end = tracks.end();
TrackFile* last = NULL;
while(i != end) {
Track &curr = *i;
if (curr.file != last) {
delete curr.file;
last = curr.file;
}
i++;
}
tracks.clear();
}

View File

@@ -1,200 +0,0 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Definitions for the CD-ROM image file handling module.
*
* Version: @(#)cdrom_dosbox.h 1.0.3 2019/03/05
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* The DOSBox Team, <unknown>
*
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2002-2015 The DOSBox Team.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef CDROM_INTERFACE
# define CDROM_INTERFACE
#include <stdint.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
//typedef signed int Bits;
//typedef unsigned int Bitu;
//typedef int8_t Bit8s;
//typedef int16_t Bit16s;
//typedef uint16_t Bit16u;
//typedef int32_t Bit32s;
//typedef uint32_t Bit32u;
typedef size_t PhysPt;
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define DATA_TRACK 0x14
#define AUDIO_TRACK 0x10
#define CD_FPS 75
#define FRAMES_TO_MSF(f, M,S,F) { \
uint64_t value = f; \
*(F) = (value%CD_FPS) & 0xff; \
value /= CD_FPS; \
*(S) = (value%60) & 0xff; \
value /= 60; \
*(M) = value & 0xff; \
}
#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F))
typedef struct SMSF {
uint8_t min;
uint8_t sec;
uint8_t fr;
} TMSF;
typedef struct SCtrl {
uint8_t out[4]; // output channel
uint8_t vol[4]; // channel volume
} TCtrl;
class CDROM_Interface {
public:
// CDROM_Interface(void);
virtual ~CDROM_Interface(void) {};
virtual bool SetDevice(const wchar_t *path, int forceCD) = 0;
virtual bool GetUPC(uint8_t& attr, char* upc) = 0;
virtual bool GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) = 0;
virtual bool GetAudioTrackInfo(int track, int& number, TMSF& start, uint8_t& attr) = 0;
virtual bool GetAudioTrackEndInfo(int track, int& number, TMSF& start, unsigned char& attr) = 0;
virtual bool GetAudioSub(int sector, uint8_t& attr, uint8_t& track, uint8_t& index, TMSF& relPos, TMSF& absPos) = 0;
virtual bool GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0;
virtual bool ReadSectors(PhysPt buffer, bool raw, uint32_t sector, uint32_t num) = 0;
virtual bool LoadUnloadMedia(bool unload) = 0;
virtual void InitNewMedia(void) {};
};
class CDROM_Interface_Image : public CDROM_Interface {
private:
class TrackFile {
public:
virtual bool read(uint8_t *buffer, uint64_t seek, size_t count) = 0;
virtual uint64_t getLength() = 0;
virtual ~TrackFile() { };
};
class BinaryFile : public TrackFile {
public:
BinaryFile(const wchar_t *filename, bool &error);
~BinaryFile();
bool read(uint8_t *buffer, uint64_t seek, size_t count);
uint64_t getLength();
private:
BinaryFile();
wchar_t fn[260];
FILE *file;
};
struct Track {
int number;
int track_number;
int attr;
int form;
uint64_t start;
uint64_t length;
uint64_t skip;
int sectorSize;
bool mode2;
TrackFile *file;
};
public:
CDROM_Interface_Image();
virtual ~CDROM_Interface_Image(void);
void InitNewMedia(void);
bool SetDevice(const wchar_t* path, int forceCD);
bool GetUPC(uint8_t& attr, char* upc);
bool GetAudioTracks(int& stTrack, int& end, TMSF& leadOut);
bool GetAudioTrackInfo(int track, int& number, TMSF& start, uint8_t& attr);
bool GetAudioTrackEndInfo(int track, int& number, TMSF& start, unsigned char& attr);
bool GetAudioSub(int sector, uint8_t& attr, uint8_t& track, uint8_t& index, TMSF& relPos, TMSF& absPos);
bool GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
bool ReadSectors(PhysPt buffer, bool raw, uint32_t sector, uint32_t num);
bool LoadUnloadMedia(bool unload);
bool ReadSector(uint8_t *buffer, bool raw, uint32_t sector);
bool ReadSectorSub(uint8_t *buffer, uint32_t sector);
int GetSectorSize(uint32_t sector);
bool IsMode2(uint32_t sector);
int GetMode2Form(uint32_t sector);
bool HasDataTrack(void);
bool HasAudioTracks(void);
int GetTrack(unsigned int sector);
private:
// player
static void CDAudioCallBack(unsigned int len);
void ClearTracks();
bool IsoLoadFile(const wchar_t *filename);
bool CanReadPVD(TrackFile *file, uint64_t sectorSize, bool mode2);
// cue sheet processing
bool CueGetBuffer(char *str, char **line, bool up);
bool CueGetString(std::string &str, char **line);
bool CueGetKeyword(std::string &keyword, char **line);
uint64_t CueGetNumber(char **line);
bool CueGetFrame(uint64_t &frames, char **line);
bool CueLoadSheet(const wchar_t *cuefile);
bool AddTrack(Track &curr, uint64_t &shift, uint64_t prestart, uint64_t &totalPregap, uint64_t currPregap);
std::vector<Track> tracks;
typedef std::vector<Track>::iterator track_it;
std::string mcn;
};
extern int CDROM_GetMountType(char* path, int force);
extern void cdrom_image_log(const char *format, ...);
#endif /* __CDROM_INTERFACE__ */

View File

@@ -8,7 +8,7 @@
*
* CD-ROM image support.
*
* Version: @(#)cdrom_image.cc 1.0.10 2019/03/06
* Version: @(#)cdrom_image.c 1.0.11 2019/03/06
*
* Author: RichardG867,
* Miran Grca, <mgrca8@gmail.com>
@@ -32,7 +32,7 @@
#include "../config.h"
#include "../plat.h"
#include "../scsi/scsi_device.h"
#include "cdrom_dosbox.h"
#include "cdrom_image_backend.h"
#include "cdrom.h"
#include "cdrom_image.h"
@@ -60,29 +60,26 @@ cdrom_image_log(const char *fmt, ...)
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
#define MSFtoLBA(m,s,f) ((((m * 60) + s) * 75) + f)
static void
image_get_tracks(cdrom_t *dev, int *first, int *last)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
TMSF tmsf;
img->GetAudioTracks(*first, *last, tmsf);
cdi_get_audio_tracks(img, first, last, &tmsf);
}
static void
image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
TMSF tmsf;
if (end)
img->GetAudioTrackEndInfo(track, ti->number, tmsf, ti->attr);
else
img->GetAudioTrackInfo(track, ti->number, tmsf, ti->attr);
cdi_get_audio_track_info(img, end, track, &ti->number, &tmsf, &ti->attr);
ti->m = tmsf.min;
ti->s = tmsf.sec;
@@ -93,11 +90,11 @@ image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti)
static void
image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
TMSF rel_pos, abs_pos;
img->GetAudioSub(lba, subc->attr, subc->track, subc->index,
rel_pos, abs_pos);
cdi_get_audio_sub(img, lba, &subc->attr, &subc->track, &subc->index,
&rel_pos, &abs_pos);
subc->abs_m = abs_pos.min;
subc->abs_s = abs_pos.sec;
@@ -112,7 +109,7 @@ image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc)
static int
image_get_capacity(cdrom_t *dev)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
int first_track, last_track;
int number, c;
unsigned char attr;
@@ -123,10 +120,10 @@ image_get_capacity(cdrom_t *dev)
if (!img)
return 0;
img->GetAudioTracks(first_track, last_track, tmsf);
cdi_get_audio_tracks(img, &first_track, &last_track, &tmsf);
for (c = 0; c <= last_track; c++) {
img->GetAudioTrackInfo(c+1, number, tmsf, attr);
cdi_get_audio_track_info(img, 0, c + 1, &number, &tmsf, &attr);
address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */
if (address > lb)
lb = address;
@@ -139,7 +136,7 @@ image_get_capacity(cdrom_t *dev)
static int
image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
uint8_t attr;
TMSF tmsf;
int m, s, f;
@@ -156,7 +153,7 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
}
/* GetTrack requires LBA. */
img->GetAudioTrackInfo(img->GetTrack(pos), number, tmsf, attr);
cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr);
return attr == AUDIO_TRACK;
}
@@ -165,27 +162,27 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
static int
image_sector_size(struct cdrom *dev, uint32_t lba)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
return img->GetSectorSize(lba);
return cdi_get_sector_size(img, lba);
}
static int
image_read_sector(struct cdrom *dev, int type, uint8_t *b, uint32_t lba)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
switch (type) {
case CD_READ_DATA:
return img->ReadSector(b, false, lba);
return cdi_read_sector(img, b, 0, lba);
case CD_READ_AUDIO:
return img->ReadSector(b, true, lba);
return cdi_read_sector(img, b, 1, lba);
case CD_READ_RAW:
if (img->GetSectorSize(lba) == 2352)
return img->ReadSector(b, true, lba);
if (cdi_get_sector_size(img, lba) == 2352)
return cdi_read_sector(img, b, 1, lba);
else
return img->ReadSectorSub(b, lba);
return cdi_read_sector_sub(img, b, lba);
default:
cdrom_image_log("CD-ROM %i: Unknown CD read type\n", dev->id);
return 0;
@@ -196,14 +193,14 @@ image_read_sector(struct cdrom *dev, int type, uint8_t *b, uint32_t lba)
static int
image_track_type(cdrom_t *dev, uint32_t lba)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
if (img) {
if (image_is_track_audio(dev, lba, 0))
return CD_TRACK_AUDIO;
else {
if (img->IsMode2(lba))
return CD_TRACK_MODE2 | img->GetMode2Form(lba);
if (cdi_is_mode2(img, lba))
return CD_TRACK_MODE2 | cdi_get_mode2_form(img, lba);
}
}
@@ -214,13 +211,13 @@ image_track_type(cdrom_t *dev, uint32_t lba)
static void
image_exit(cdrom_t *dev)
{
CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image;
cd_img_t *img = (cd_img_t *)dev->image;
cdrom_image_log("CDROM: image_exit(%ls)\n", dev->image_path);
dev->cd_status = CD_STATUS_EMPTY;
if (img) {
delete img;
cdi_close(img);
dev->image = NULL;
}
@@ -252,22 +249,23 @@ image_open_abort(cdrom_t *dev)
int
cdrom_image_open(cdrom_t *dev, const wchar_t *fn)
{
CDROM_Interface_Image *img;
cd_img_t *img;
wcscpy(dev->image_path, fn);
/* Create new instance of the CDROM_Image class. */
img = new CDROM_Interface_Image();
img = (cd_img_t *) malloc(sizeof(cd_img_t));
/* This guarantees that if ops is not NULL, then
neither is the image pointer. */
if (!img)
return image_open_abort(dev);
memset(img, 0, sizeof(cd_img_t));
dev->image = img;
/* Open the image. */
if (! img->SetDevice(fn, false))
if (!cdi_set_device(img, fn))
return image_open_abort(dev);
/* All good, reset state. */

View File

@@ -0,0 +1,937 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* CD-ROM image file handling module, translated to C from
* cdrom_dosbox.cpp.
*
* Version: @(#)cdrom_image_backend.c 1.0.0 2019/12/19
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* The DOSBox Team, <unknown>
*
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2002-2019 The DOSBox Team.
*/
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define __STDC_FORMAT_MACROS
#include <stdarg.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#ifdef _WIN32
# include <string.h>
#else
# include <libgen.h>
#endif
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../plat.h"
#include "cdrom_image_backend.h"
#define MAX_LINE_LENGTH 512
#define MAX_FILENAME_LENGTH 256
#define CROSS_LEN 512
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG;
void
cdrom_image_backend_log(const char *fmt, ...)
{
va_list ap;
if (cdrom_image_backend_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define cdrom_image_backend_log(fmt, ...)
#endif
/* Binary file functions. */
static int
bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count)
{
track_file_t *tf = (track_file_t *) p;
cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n",
tf->file, seek, count);
if (tf->file == NULL)
return 0;
fseeko64(tf->file, seek, SEEK_SET);
if (fread(buffer, count, 1, tf->file) != 1) {
#ifdef ENABLE_cdrom_image_backend_log
cdrom_image_backend_log("CDROM: binary_read failed!\n");
#endif
return 0;
}
return 1;
}
static uint64_t
bin_get_length(void *p)
{
off64_t len;
track_file_t *tf = (track_file_t *) p;
cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", bf->file);
if (tf->file == NULL)
return 0;
fseeko64(tf->file, 0, SEEK_END);
len = ftello64(tf->file);
cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->file, len);
return len;
}
static void
bin_close(void *p)
{
track_file_t *tf = (track_file_t *) p;
if (tf == NULL)
return;
if (tf->file != NULL) {
fclose(tf->file);
tf->file = NULL;
}
memset(tf->fn, 0x00, sizeof(tf->fn));
free(p);
}
static track_file_t *
bin_init(const wchar_t *filename, int *error)
{
track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t));
memset(tf->fn, 0x00, sizeof(tf->fn));
wcscpy(tf->fn, filename);
tf->file = plat_fopen64(tf->fn, L"rb");
cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file);
*error = (tf->file == NULL);
/* Set the function pointers. */
if (!*error) {
tf->read = bin_read;
tf->get_length = bin_get_length;
tf->close = bin_close;
}
return tf;
}
static track_file_t *
track_file_init(const wchar_t *filename, int *error)
{
/* Current we only support .BIN files, either combined or one per
track. In the future, more is planned. */
return bin_init(filename, error);
}
static void
track_file_close(track_t *trk)
{
if (trk == NULL)
return;
if (trk->file == NULL)
return;
trk->file->close(trk->file);
trk->file = NULL;
}
/* Root functions. */
static void
cdi_clear_tracks(cd_img_t *cdi)
{
int i;
track_file_t *last = NULL;
track_t *cur = NULL;
if ((cdi->tracks == NULL) || (cdi->tracks_num == 0))
return;
for (i = 0; i < cdi->tracks_num; i++) {
cur = &cdi->tracks[i];
if (cur->file != last) {
track_file_close(cur);
last = cur->file;
}
}
/* Now free the array. */
free(cdi->tracks);
cdi->tracks = NULL;
/* Mark that there's no tracks. */
cdi->tracks_num = 0;
}
void
cdi_close(cd_img_t *cdi)
{
cdi_clear_tracks(cdi);
free(cdi);
}
int
cdi_set_device(cd_img_t *cdi, const wchar_t *path)
{
if (cdi_load_cue(cdi, path))
return 1;
if (cdi_load_iso(cdi, path))
return 1;
return 0;
}
/* TODO: This never returns anything other than 1, should it even be an int? */
int
cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out)
{
*st_track = 1;
*end = cdi->tracks_num - 1;
FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr);
return 1;
}
/* This replaces both Info and EndInfo, they are specified by a variable. */
int
cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr)
{
track_t *trk = &cdi->tracks[track - 1];
int pos = trk->start + 150;
if ((track < 1) || (track > cdi->tracks_num))
return 0;
pos = trk->start + 150;
FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr);
*track_num = trk->track_number;
*attr = trk->attr;
return 1;
}
int
cdi_get_track(cd_img_t *cdi, uint32_t sector)
{
int i;
track_t *cur, *next;
/* There must be at least two tracks - data and lead out. */
if (cdi->tracks_num < 2)
return -1;
/* This has a problem - the code skips the last track, which is
lead out - is that correct? */
for (i = 0; i < (cdi->tracks_num - 1); i++) {
cur = &cdi->tracks[i];
next = &cdi->tracks[i + 1];
if ((cur->start <= sector) && (sector < next->start))
return cur->number;
}
return -1;
}
/* TODO: See if track start is adjusted by 150 or not. */
int
cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos)
{
int cur_track = cdi_get_track(cdi, sector);
track_t *trk;
if (cur_track < 1)
return 0;
*track = (uint8_t) cur_track;
trk = &cdi->tracks[*track - 1];
*attr = trk->attr;
*index = 1;
FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr);
/* Absolute position should be adjusted by 150, not the relative ones. */
FRAMES_TO_MSF(sector - trk->start, &rel_pos->min, &rel_pos->sec, &rel_pos->fr);
return 1;
}
int
cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
{
size_t length;
int track = cdi_get_track(cdi, sector) - 1;
uint64_t s = (uint64_t) sector, seek;
track_t *trk;
if (track < 0)
return 0;
trk = &cdi->tracks[track];
seek = trk->skip + ((s - trk->start) * trk->sector_size);
/* TODO: Is this correct? Is cooked sector size 2336 for all Mode 2 variants? */
if (trk->mode2 && (trk->form != 1)) {
if (trk->form == 2)
length = (raw ? RAW_SECTOR_SIZE : 2324);
else
length = (raw ? RAW_SECTOR_SIZE : 2336);
} else
length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE);
if (raw && (trk->sector_size != RAW_SECTOR_SIZE))
return 0;
if (!raw && !trk->mode2 && (trk->sector_size == RAW_SECTOR_SIZE))
seek += 16ULL;
/* TODO: See if Mode 2 is handled correctly here. */
if (!raw && trk->mode2)
seek += 24ULL;
return trk->file->read(trk->file, buffer, seek, length);
}
int
cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num)
{
int sector_size, success = 1;
uint8_t buf_len, *buf;
uint32_t i;
/* TODO: This fails to account for Mode 2. Shouldn't we have a function
to get sector size? */
sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
buf_len = num * sector_size;
buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t));
for (i = 0; i < num; i++) {
success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i);
if (!success)
break;
}
memcpy((void *) buffer, buf, buf_len);
free(buf);
buf = NULL;
return success;
}
/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */
int
cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector)
{
int track = cdi_get_track(cdi, sector) - 1;
track_t *trk;
uint64_t s = (uint64_t) sector, seek;
if (track < 0)
return 0;
trk = &cdi->tracks[track];
seek = trk->skip + ((s - trk->start) * trk->sector_size);
if (trk->sector_size != 2448)
return 0;
return trk->file->read(trk->file, buffer, seek, 2448);
}
int
cdi_get_sector_size(cd_img_t *cdi, uint32_t sector)
{
int track = cdi_get_track(cdi, sector) - 1;
track_t *trk;
if (track < 0)
return 0;
trk = &cdi->tracks[track];
return trk->sector_size;
}
int
cdi_is_mode2(cd_img_t *cdi, uint32_t sector)
{
int track = cdi_get_track(cdi, sector) - 1;
track_t *trk;
if (track < 0)
return 0;
trk = &cdi->tracks[track];
return !!(trk->mode2);
}
int
cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector)
{
int track = cdi_get_track(cdi, sector) - 1;
track_t *trk;
if (track < 0)
return 0;
trk = &cdi->tracks[track];
return trk->form;
}
int
cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2)
{
uint8_t pvd[COOKED_SECTOR_SIZE];
uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */
if (!mode2 && (sector_size == RAW_SECTOR_SIZE))
seek += 16;
if (mode2)
seek += 24;
file->read(file, pvd, seek, COOKED_SECTOR_SIZE);
return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) ||
(pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1));
}
/* This reallocates the array and returns the pointer to the last track. */
static void
cdi_track_push_back(cd_img_t *cdi, track_t *trk)
{
/* This has to be done so situations in which realloc would misbehave
can be detected and reported to the user. */
if ((cdi->tracks != NULL) && (cdi->tracks_num == 0))
fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n");
if ((cdi->tracks == NULL) && (cdi->tracks_num != 0))
fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n");
cdi->tracks = realloc(cdi->tracks, (cdi->tracks_num + 1) * sizeof(track_t));
memcpy(&(cdi->tracks[cdi->tracks_num]), trk, sizeof(track_t));
cdi->tracks_num++;
}
int
cdi_load_iso(cd_img_t *cdi, const wchar_t *filename)
{
int error;
track_t trk;
cdi->tracks = NULL;
cdi->tracks_num = 0;
memset(&trk, 0, sizeof(track_t));
/* Data track (shouldn't there be a lead in track?). */
trk.file = bin_init(filename, &error);
if (error) {
if (trk.file != NULL)
trk.file->close(trk.file);
return 0;
}
trk.number = 1;
trk.track_number = 1;
trk.attr = DATA_TRACK;
/* Try to detect ISO type. */
trk.form = 0;
trk.mode2 = 0;
/* TODO: Merge the first and last cases since they result in the same thing. */
if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0))
trk.sector_size = RAW_SECTOR_SIZE;
else if (cdi_can_read_pvd(trk.file, 2336, 1)) {
trk.sector_size = 2336;
trk.mode2 = 1;
} else if (cdi_can_read_pvd(trk.file, 2324, 1)) {
trk.sector_size = 2324;
trk.mode2 = 1;
trk.form = 2;
} else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1)) {
trk.sector_size = RAW_SECTOR_SIZE;
trk.mode2 = 1;
} else {
/* We use 2048 mode 1 as the default. */
trk.sector_size = COOKED_SECTOR_SIZE;
}
trk.length = trk.file->get_length(trk.file) / trk.sector_size;
cdi_track_push_back(cdi, &trk);
/* Lead out track. */
trk.number = 2;
trk.track_number = 0xAA;
trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */
trk.start = trk.length;
trk.length = 0;
trk.file = NULL;
cdi_track_push_back(cdi, &trk);
return 1;
}
static int
cdi_cue_get_buffer(char *str, char **line, int up)
{
char *s = *line;
char *p = str;
int quote = 0;
int done = 0;
int space = 1;
/* Copy to local buffer until we have end of string or whitespace. */
while (! done) {
switch(*s) {
case '\0':
if (quote) {
/* Ouch, unterminated string.. */
return 0;
}
done = 1;
break;
case '\"':
quote ^= 1;
break;
case ' ':
case '\t':
if (space)
break;
if (! quote) {
done = 1;
break;
}
/*FALLTHROUGH*/
default:
if (up && islower((int) *s))
*p++ = toupper((int) *s);
else
*p++ = *s;
space = 0;
break;
}
if (! done)
s++;
}
*p = '\0';
*line = s;
return 1;
}
static int
cdi_cue_get_keyword(char **dest, char **line)
{
char temp[1024];
int success;
success = cdi_cue_get_buffer(temp, line, 1);
if (success)
*dest = temp;
return success;
}
/* Get a string from the input line, handling quotes properly. */
static uint64_t
cdi_cue_get_number(char **line)
{
char temp[128];
uint64_t num;
if (!cdi_cue_get_buffer(temp, line, 0))
return 0;
if (sscanf(temp, "%" PRIu64, &num) != 1)
return 0;
return num;
}
static int
cdi_cue_get_frame(uint64_t *frames, char **line)
{
char temp[128];
int min, sec, fr;
int success;
success = cdi_cue_get_buffer(temp, line, 0);
if (! success) return 0;
success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3;
if (! success) return 0;
*frames = MSF_TO_FRAMES(min, sec, fr);
return 1;
}
static int
cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap)
{
/* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */
uint64_t skip, temp;
track_t *prev = NULL;
if (prestart > 0) {
if (prestart > cur->start)
return 0;
skip = cur->start - prestart;
} else
skip = 0ULL;
if ((cdi->tracks != NULL) && (cdi->tracks_num != 0))
prev = &cdi->tracks[cdi->tracks_num - 1];
/* First track (track number must be 1). */
if (cdi->tracks_num == 0) {
/* I guess this makes sure the structure is not filled with invalid data. */
if (cur->number != 1)
return 0;
cur->skip = skip * cur->sector_size;
cur->start += cur_pregap;
*total_pregap = cur_pregap;
cdi_track_push_back(cdi, cur);
return 1;
}
/* Current track consumes data from the same file as the previous. */
if (prev->file == cur->file) {
cur->start += *shift;
prev->length = cur->start + *total_pregap - prev->start - skip;
cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size);
*total_pregap += cur_pregap;
cur->start += *total_pregap;
} else {
temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip);
prev->length = temp / ((uint64_t) prev->sector_size);
if ((temp % prev->sector_size) != 0)
prev->length++; /* Padding. */
cur->start += prev->start + prev->length + cur_pregap;
cur->skip = skip * cur->sector_size;
*shift += prev->start + prev->length;
*total_pregap = cur_pregap;
}
/* Error checks. */
if (cur->number <= 1)
return 0;
if ((prev->number + 1) != cur->number)
return 0;
if (cur->start < (prev->start + prev->length))
return 0;
cdi_track_push_back(cdi, cur);
return 1;
}
int
cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile)
{
track_t trk;
wchar_t pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH];
wchar_t temp[MAX_FILENAME_LENGTH];
uint64_t shift = 0ULL, prestart = 0ULL;
uint64_t cur_pregap = 0ULL, total_pregap = 0ULL;
uint64_t frame = 0ULL, index;
int i, success;
int error, can_add_track = 0;
FILE *fp;
char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH];
char *line, *command;
char *type;
cdi->tracks = NULL;
cdi->tracks_num = 0;
memset(&trk, 0, sizeof(track_t));
/* Get a copy of the filename into pathname, we need it later. */
memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t));
plat_get_dirname(pathname, cuefile);
/* Open the file. */
fp = plat_fopen((wchar_t *) cuefile, L"r");
if (fp == NULL)
return 0;
success = 0;
for (;;) {
line = buf;
/* Read a line from the cuesheet file. */
if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp))
break;
/* Do two iterations to make sure to nuke even if it's \r\n or \n\r,
but do checks to make sure we're not nuking other bytes. */
for (i = 0; i < 2; i++) {
if (strlen(buf) > 0) {
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */
else if (buf[strlen(buf) - 1] == '\r')
buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */
}
}
success = cdi_cue_get_keyword(&command, &line);
if (!strcmp(command, "TRACK")) {
if (can_add_track)
success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap);
else
success = 1;
trk.start = 0;
trk.skip = 0;
cur_pregap = 0;
prestart = 0;
trk.number = cdi_cue_get_number(&line);
trk.track_number = trk.number;
success = cdi_cue_get_keyword(&type, &line);
if (!success)
break;
trk.form = 0;
trk.mode2 = 0;
if (!strcmp(type, "AUDIO")) {
trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = AUDIO_TRACK;
} else if (!strcmp(type, "MODE1/2048")) {
trk.sector_size = COOKED_SECTOR_SIZE;
trk.attr = DATA_TRACK;
} else if (!strcmp(type, "MODE1/2352")) {
trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = DATA_TRACK;
} else if (!strcmp(type, "MODE2/2048")) {
trk.form = 1;
trk.sector_size = COOKED_SECTOR_SIZE;
trk.attr = DATA_TRACK;
trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2324")) {
trk.form = 2;
trk.sector_size = 2324;
trk.attr = DATA_TRACK;
trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2336")) {
trk.sector_size = 2336;
trk.attr = DATA_TRACK;
trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2352")) {
trk.form = 1; /* Assume this is XA Mode 2 Form 1. */
trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = DATA_TRACK;
trk.mode2 = 1;
} else if (!strcmp(type, "CDG/2448")) {
trk.sector_size = 2448;
trk.attr = DATA_TRACK;
trk.mode2 = 1;
} else if (!strcmp(type, "CDI/2336")) {
trk.sector_size = 2336;
trk.attr = DATA_TRACK;
trk.mode2 = 1;
} else if (!strcmp(type, "CDI/2352")) {
trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = DATA_TRACK;
trk.mode2 = 1;
} else
success = 0;
can_add_track = 1;
} else if (!strcmp(command, "INDEX")) {
index = cdi_cue_get_number(&line);
success = cdi_cue_get_frame(&frame, &line);
switch(index) {
case 0:
prestart = frame;
break;
case 1:
trk.start = frame;
break;
default:
/* ignore other indices */
break;
}
} else if (!strcmp(command, "FILE")) {
if (can_add_track)
success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap);
else
success = 1;
can_add_track = 0;
memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char));
memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t));
success = cdi_cue_get_buffer(ansi, &line, 0);
if (!success)
break;
success = cdi_cue_get_keyword(&type, &line);
if (!success)
break;
trk.file = NULL;
error = 1;
if (!strcmp(type, "BINARY")) {
memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t));
mbstowcs(temp, ansi, sizeof_w(temp));
plat_append_filename(filename, pathname, temp);
trk.file = track_file_init(filename, &error);
}
if (error) {
#ifdef ENABLE_cdrom_image_backend_log
cdrom_image_backend_log("CUE: cannot open fille '%ls' in cue sheet!\n",
filename);
#endif
if (trk.file != NULL) {
trk.file->close(trk.file);
trk.file = NULL;
}
success = 0;
}
} else if (!strcmp(command, "FILE"))
success = cdi_cue_get_frame(&cur_pregap, &line);
else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") ||
!strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") ||
!strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) {
/* Ignored commands. */
success = 1;
} else {
#ifdef ENABLE_cdrom_image_backend_log
cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n",
command.c_str());
#endif
success = 0;
}
if (!success)
break;
}
fclose(fp);
if (!success)
return 0;
/* Add last track. */
if (!cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap))
return 0;
/* Add lead out track. */
trk.number++;
trk.track_number = 0xAA;
trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */
trk.start = 0;
trk.length = 0;
trk.file = NULL;
if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0))
return 0;
return 1;
}
int
cdi_has_data_track(cd_img_t *cdi)
{
int i;
if ((cdi == NULL) || (cdi->tracks == NULL))
return 0;
/* Data track has attribute 0x14. */
for (i = 0; i < cdi->tracks_num; i++) {
if (cdi->tracks[i].attr == DATA_TRACK)
return 1;
}
return 0;
}
int
cdi_has_audio_track(cd_img_t *cdi)
{
int i;
if ((cdi == NULL) || (cdi->tracks == NULL))
return 0;
/* Audio track has attribute 0x14. */
for (i = 0; i < cdi->tracks_num; i++) {
if (cdi->tracks[i].attr == AUDIO_TRACK)
return 1;
}
return 0;
}

View File

@@ -0,0 +1,94 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* CD-ROM image file handling module header , translated to C
* from cdrom_dosbox.h.
*
* Version: @(#)cdrom_image_backend.h 1.0.0 2019/12/19
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* The DOSBox Team, <unknown>
*
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2002-2019 The DOSBox Team.
*/
#ifndef CDROM_IMAGE_BACKEND_H
#define CDROM_IMAGE_BACKEND_H
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define DATA_TRACK 0x14
#define AUDIO_TRACK 0x10
#define CD_FPS 75
#define FRAMES_TO_MSF(f, M,S,F) { \
uint64_t value = f; \
*(F) = (value%CD_FPS) & 0xff; \
value /= CD_FPS; \
*(S) = (value%60) & 0xff; \
value /= 60; \
*(M) = value & 0xff; \
}
#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F))
typedef struct SMSF {
uint8_t min;
uint8_t sec;
uint8_t fr;
} TMSF;
/* Track file struct. */
typedef struct {
int (*read)(void *p, uint8_t *buffer, uint64_t seek, size_t count);
uint64_t (*get_length)(void *p);
void (*close)(void *p);
wchar_t fn[260];
FILE *file;
} track_file_t;
typedef struct {
int number, track_number, attr, sector_size,
mode2, form;
uint64_t start, length,
skip;
track_file_t *file;
} track_t;
typedef struct {
int tracks_num;
track_t *tracks;
} cd_img_t;
/* Binary file functions. */
extern void cdi_close(cd_img_t *cdi);
extern int cdi_set_device(cd_img_t *cdi, const wchar_t *path);
extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out);
extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr);
extern int cdi_get_track(cd_img_t *cdi, uint32_t sector);
extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos);
extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector);
extern int cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num);
extern int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector);
extern int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector);
extern int cdi_is_mode2(cd_img_t *cdi, uint32_t sector);
extern int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector);
extern int cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2);
extern int cdi_load_iso(cd_img_t *cdi, const wchar_t *filename);
extern int cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile);
extern int cdi_has_data_track(cd_img_t *cdi);
extern int cdi_has_audio_track(cd_img_t *cdi);
#endif /* ! CDROM_IMAGE_BACKEND_H */

View File

@@ -8,7 +8,7 @@
*
* Configuration file handler.
*
* Version: @(#)config.c 1.0.65 2019/12/05
* Version: @(#)config.c 1.0.66 2019/12/21
*
* Authors: Sarah Walker,
* Miran Grca, <mgrca8@gmail.com>
@@ -57,9 +57,7 @@
#include "disk/zip.h"
#include "sound/sound.h"
#include "sound/midi.h"
#include "sound/snd_dbopl.h"
#include "sound/snd_mpu401.h"
#include "sound/snd_opl.h"
#include "sound/sound.h"
#include "video/video.h"
#include "plat.h"
@@ -657,14 +655,6 @@ load_sound(void)
GAMEBLASTER = !!config_get_int(cat, "gameblaster", 0);
GUS = !!config_get_int(cat, "gus", 0);
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "opl_type", "dbopl");
strcpy(temp, p);
if (!strcmp(temp, "nukedopl") || !strcmp(temp, "1"))
opl_type = 1;
else
opl_type = 0;
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "sound_type", "float");
strcpy(temp, p);
@@ -1271,7 +1261,6 @@ config_load(void)
fdd_set_check_bpb(i, 1);
}
mem_size = 640;
opl_type = 0;
isartc_type = 0;
for (i = 0; i < ISAMEM_MAX; i++)
isamem_type[i] = 0;
@@ -1562,11 +1551,6 @@ save_sound(void)
else
config_set_int(cat, "gus", GUS);
if (opl_type == 0)
config_delete_var(cat, "opl_type");
else
config_set_string(cat, "opl_type", (opl_type == 1) ? "nukedopl" : "dbopl");
if (sound_is_float == 1)
config_delete_var(cat, "sound_type");
else

View File

@@ -248,7 +248,7 @@
#define CHECK_READY 2
#define ALLOW_UA 1
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
#define MSFtoLBA(m,s,f) ((((m * 60) + s) * 75) + f)
#define MSG_COMMAND_COMPLETE 0x00

File diff suppressed because it is too large Load Diff

View File

@@ -1,259 +0,0 @@
/* Copyright holders: The DOSBox Team
see COPYING for more details
*/
//#include "adlib.h"
//#include "dosbox.h"
#include <stdint.h>
typedef signed int Bits;
typedef unsigned int Bitu;
typedef int8_t Bit8s;
typedef uint8_t Bit8u;
typedef int16_t Bit16s;
typedef uint16_t Bit16u;
typedef int32_t Bit32s;
typedef uint32_t Bit32u;
#define INLINE inline
#define GCC_UNLIKELY(x) (x)
//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
#define WAVE_HANDLER 10
//Use a logarithmic wavetable with an exponential table for volume
#define WAVE_TABLELOG 11
//Use a linear wavetable with a multiply table for volume
#define WAVE_TABLEMUL 12
//Select the type of wave generator routine
#define DBOPL_WAVE WAVE_TABLEMUL
namespace DBOPL {
struct Chip;
struct Operator;
struct Channel;
#if (DBOPL_WAVE == WAVE_HANDLER)
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
#endif
typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
//Different synth modes that can generate blocks of data
typedef enum {
sm2AM,
sm2FM,
sm3AM,
sm3FM,
sm4Start,
sm3FMFM,
sm3AMFM,
sm3FMAM,
sm3AMAM,
sm6Start,
sm2Percussion,
sm3Percussion,
} SynthMode;
//Shifts for the values contained in chandata variable
enum {
SHIFT_KSLBASE = 16,
SHIFT_KEYCODE = 24,
};
struct Operator {
public:
//Masks for operator 20 values
enum {
MASK_KSR = 0x10,
MASK_SUSTAIN = 0x20,
MASK_VIBRATO = 0x40,
MASK_TREMOLO = 0x80,
};
typedef enum {
OFF,
RELEASE,
SUSTAIN,
DECAY,
ATTACK,
} State;
VolumeHandler volHandler;
#if (DBOPL_WAVE == WAVE_HANDLER)
WaveHandler waveHandler; //Routine that generate a wave
#else
Bit16s* waveBase;
Bit32u waveMask;
Bit32u waveStart;
#endif
Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
Bit32u waveAdd; //The base frequency without vibrato
Bit32u waveCurrent; //waveAdd + vibratao
Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
Bit32u vibrato; //Scaled up vibrato strength
Bit32s sustainLevel; //When stopping at sustain level stop here
Bit32s totalLevel; //totalLevel is added to every generated volume
Bit32u currentLevel; //totalLevel + tremolo
Bit32s volume; //The currently active volume
Bit32u attackAdd; //Timers for the different states of the envelope
Bit32u decayAdd;
Bit32u releaseAdd;
Bit32u rateIndex; //Current position of the evenlope
Bit8u rateZero; //Bits for the different states of the envelope having no changes
Bit8u keyOn; //Bitmask of different values that can generate keyon
//Registers, also used to check for changes
Bit8u reg20, reg40, reg60, reg80, regE0;
//Active part of the envelope we're in
Bit8u state;
//0xff when tremolo is enabled
Bit8u tremoloMask;
//Strength of the vibrato
Bit8u vibStrength;
//Keep track of the calculated KSR so we can check for changes
Bit8u ksr;
private:
void SetState( Bit8u s );
void UpdateAttack( const Chip* chip );
void UpdateRelease( const Chip* chip );
void UpdateDecay( const Chip* chip );
public:
void UpdateAttenuation();
void UpdateRates( const Chip* chip );
void UpdateFrequency( );
void Write20( const Chip* chip, Bit8u val );
void Write40( const Chip* chip, Bit8u val );
void Write60( const Chip* chip, Bit8u val );
void Write80( const Chip* chip, Bit8u val );
void WriteE0( const Chip* chip, Bit8u val );
bool Silent() const;
void Prepare( const Chip* chip );
void KeyOn( Bit8u mask);
void KeyOff( Bit8u mask);
template< State state>
Bits TemplateVolume( );
Bit32s RateForward( Bit32u add );
Bitu ForwardWave();
Bitu ForwardVolume();
Bits GetSample( Bits modulation );
Bits GetWave( Bitu index, Bitu vol );
public:
Operator();
};
struct Channel {
Operator op[2];
inline Operator* Op( Bitu index ) {
return &( ( this + (index >> 1) )->op[ index & 1 ]);
}
SynthHandler synthHandler;
Bit32u chanData; //Frequency/octave and derived values
Bit32s old[2]; //Old data for feedback
Bit8u feedback; //Feedback shift
Bit8u regB0; //Register values to check for changes
Bit8u regC0;
//This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
Bit8u fourMask;
Bit8s maskLeft; //Sign extended values for both channel's panning
Bit8s maskRight;
//Forward the channel data to the operators of the channel
void SetChanData( const Chip* chip, Bit32u data );
//Change in the chandata, check for new values and if we have to forward to operators
void UpdateFrequency( const Chip* chip, Bit8u fourOp );
void WriteA0( const Chip* chip, Bit8u val );
void WriteB0( const Chip* chip, Bit8u val );
void WriteC0( const Chip* chip, Bit8u val );
void ResetC0( const Chip* chip );
//call this for the first channel
template< bool opl3Mode >
void GeneratePercussion( Chip* chip, Bit32s* output );
//Generate blocks of data in specific modes
template<SynthMode mode>
Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
Channel();
};
struct Chip {
//This is used as the base counter for vibrato and tremolo
Bit32u lfoCounter;
Bit32u lfoAdd;
Bit32u noiseCounter;
Bit32u noiseAdd;
Bit32u noiseValue;
//Frequency scales for the different multiplications
Bit32u freqMul[16];
//Rates for decay and release for rate of this chip
Bit32u linearRates[76];
//Best match attack rates for the rate of this chip
Bit32u attackRates[76];
//18 channels with 2 operators each
Channel chan[18];
Bit8u reg104;
Bit8u reg08;
Bit8u reg04;
Bit8u regBD;
Bit8u vibratoIndex;
Bit8u tremoloIndex;
Bit8s vibratoSign;
Bit8u vibratoShift;
Bit8u tremoloValue;
Bit8u vibratoStrength;
Bit8u tremoloStrength;
//Mask for allowed wave forms
Bit8u waveFormMask;
//0 or -1 when enabled
Bit8s opl3Active;
int is_opl3;
//Return the maximum amount of samples before and LFO change
Bit32u ForwardLFO( Bit32u samples );
Bit32u ForwardNoise();
void WriteBD( Bit8u val );
void WriteReg(Bit32u reg, Bit8u val );
Bit32u WriteAddr( Bit32u port, Bit8u val );
void GenerateBlock2( Bitu samples, Bit32s* output );
void GenerateBlock3( Bitu samples, Bit32s* output );
void Generate( Bit32u samples );
void Setup( Bit32u r, int chip_is_opl3 );
Chip();
};
/*struct Handler : public Adlib::Handler {
DBOPL::Chip chip;
virtual Bit32u WriteAddr( Bit32u port, Bit8u val );
virtual void WriteReg( Bit32u addr, Bit8u val );
virtual void Generate( MixerChannel* chan, Bitu samples );
virtual void Init( Bitu rate );
};*/
void InitTables( void );
}; //Namespace

View File

@@ -179,7 +179,7 @@ static const Bit8u ch_slot[18] = {
//
typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope);
typedef void(*envelope_genfunc)(opl3_slot *slott);
typedef void(*envelope_genfunc)(struct opl3_slot *slott);
static Bit16s OPL3_EnvelopeCalcExp(Bit32u level)
{
@@ -346,7 +346,7 @@ enum envelope_gen_num
envelope_gen_num_release = 3
};
static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot)
static void OPL3_EnvelopeUpdateKSL(struct opl3_slot *slot)
{
Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2)
- ((0x08 - slot->channel->block) << 5);
@@ -357,7 +357,7 @@ static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot)
slot->eg_ksl = (Bit8u)ksl;
}
static void OPL3_EnvelopeCalc(opl3_slot *slot)
static void OPL3_EnvelopeCalc(struct opl3_slot *slot)
{
Bit8u nonzero;
Bit8u rate;
@@ -504,12 +504,12 @@ static void OPL3_EnvelopeCalc(opl3_slot *slot)
}
}
static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type)
static void OPL3_EnvelopeKeyOn(struct opl3_slot *slot, Bit8u type)
{
slot->key |= type;
}
static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type)
static void OPL3_EnvelopeKeyOff(struct opl3_slot *slot, Bit8u type)
{
slot->key &= ~type;
}
@@ -518,9 +518,9 @@ static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type)
// Phase Generator
//
static void OPL3_PhaseGenerate(opl3_slot *slot)
static void OPL3_PhaseGenerate(struct opl3_slot *slot)
{
opl3_chip *chip;
struct opl3_chip *chip;
Bit16u f_num;
Bit32u basefreq;
Bit8u rm_xor, n_bit;
@@ -612,7 +612,7 @@ static void OPL3_PhaseGenerate(opl3_slot *slot)
// Slot
//
static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data)
static void OPL3_SlotWrite20(struct opl3_slot *slot, Bit8u data)
{
if ((data >> 7) & 0x01)
{
@@ -628,20 +628,20 @@ static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data)
slot->reg_mult = data & 0x0f;
}
static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data)
static void OPL3_SlotWrite40(struct opl3_slot *slot, Bit8u data)
{
slot->reg_ksl = (data >> 6) & 0x03;
slot->reg_tl = data & 0x3f;
OPL3_EnvelopeUpdateKSL(slot);
}
static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data)
static void OPL3_SlotWrite60(struct opl3_slot *slot, Bit8u data)
{
slot->reg_ar = (data >> 4) & 0x0f;
slot->reg_dr = data & 0x0f;
}
static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data)
static void OPL3_SlotWrite80(struct opl3_slot *slot, Bit8u data)
{
slot->reg_sl = (data >> 4) & 0x0f;
if (slot->reg_sl == 0x0f)
@@ -651,7 +651,7 @@ static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data)
slot->reg_rr = data & 0x0f;
}
static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data)
static void OPL3_SlotWriteE0(struct opl3_slot *slot, Bit8u data)
{
slot->reg_wf = data & 0x07;
if (slot->chip->newm == 0x00)
@@ -660,12 +660,12 @@ static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data)
}
}
static void OPL3_SlotGenerate(opl3_slot *slot)
static void OPL3_SlotGenerate(struct opl3_slot *slot)
{
slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out);
}
static void OPL3_SlotCalcFB(opl3_slot *slot)
static void OPL3_SlotCalcFB(struct opl3_slot *slot)
{
if (slot->channel->fb != 0x00)
{
@@ -682,13 +682,13 @@ static void OPL3_SlotCalcFB(opl3_slot *slot)
// Channel
//
static void OPL3_ChannelSetupAlg(opl3_channel *channel);
static void OPL3_ChannelSetupAlg(struct opl3_channel *channel);
static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data)
static void OPL3_ChannelUpdateRhythm(struct opl3_chip *chip, Bit8u data)
{
opl3_channel *channel6;
opl3_channel *channel7;
opl3_channel *channel8;
struct opl3_channel *channel6;
struct opl3_channel *channel7;
struct opl3_channel *channel8;
Bit8u chnum;
chip->rhy = data & 0x3f;
@@ -776,7 +776,7 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data)
}
}
static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data)
static void OPL3_ChannelWriteA0(struct opl3_channel *channel, Bit8u data)
{
if (channel->chip->newm && channel->chtype == ch_4op2)
{
@@ -796,7 +796,7 @@ static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data)
}
}
static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data)
static void OPL3_ChannelWriteB0(struct opl3_channel *channel, Bit8u data)
{
if (channel->chip->newm && channel->chtype == ch_4op2)
{
@@ -818,7 +818,7 @@ static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data)
}
}
static void OPL3_ChannelSetupAlg(opl3_channel *channel)
static void OPL3_ChannelSetupAlg(struct opl3_channel *channel)
{
if (channel->chtype == ch_drum)
{
@@ -919,7 +919,7 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel)
}
}
static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data)
static void OPL3_ChannelWriteC0(struct opl3_channel *channel, Bit8u data)
{
channel->fb = (data & 0x0e) >> 1;
channel->con = data & 0x01;
@@ -958,7 +958,7 @@ static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data)
}
}
static void OPL3_ChannelKeyOn(opl3_channel *channel)
static void OPL3_ChannelKeyOn(struct opl3_channel *channel)
{
if (channel->chip->newm)
{
@@ -982,7 +982,7 @@ static void OPL3_ChannelKeyOn(opl3_channel *channel)
}
}
static void OPL3_ChannelKeyOff(opl3_channel *channel)
static void OPL3_ChannelKeyOff(struct opl3_channel *channel)
{
if (channel->chip->newm)
{
@@ -1006,7 +1006,7 @@ static void OPL3_ChannelKeyOff(opl3_channel *channel)
}
}
static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data)
static void OPL3_ChannelSet4Op(struct opl3_chip *chip, Bit8u data)
{
Bit8u bit;
Bit8u chnum;
@@ -1043,7 +1043,7 @@ static Bit16s OPL3_ClipSample(Bit32s sample)
return (Bit16s)sample;
}
void OPL3_Generate(opl3_chip *chip, Bit16s *buf)
void OPL3_Generate(struct opl3_chip *chip, Bit16s *buf)
{
Bit8u ii;
Bit8u jj;
@@ -1175,7 +1175,7 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf)
chip->writebuf_samplecnt++;
}
void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf)
void OPL3_GenerateResampled(struct opl3_chip *chip, Bit32s *buf)
{
while (chip->samplecnt >= chip->rateratio)
{
@@ -1184,19 +1184,19 @@ void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf)
OPL3_Generate(chip, chip->samples);
chip->samplecnt -= chip->rateratio;
}
buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)
buf[0] = (Bit32s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)
+ chip->samples[0] * chip->samplecnt) / chip->rateratio);
buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)
buf[1] = (Bit32s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)
+ chip->samples[1] * chip->samplecnt) / chip->rateratio);
chip->samplecnt += 1 << RSM_FRAC;
}
void OPL3_Reset(opl3_chip *chip, Bit32u samplerate)
void OPL3_Reset(struct opl3_chip *chip, Bit32u samplerate)
{
Bit8u slotnum;
Bit8u channum;
memset(chip, 0, sizeof(opl3_chip));
memset(chip, 0, sizeof(struct opl3_chip));
for (slotnum = 0; slotnum < 36; slotnum++)
{
chip->slot[slotnum].chip = chip;
@@ -1238,7 +1238,7 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate)
chip->vibshift = 1;
}
Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val)
Bit32u OPL3_WriteAddr(struct opl3_chip *chip, Bit32u port, Bit8u val)
{
Bit16u addr;
addr = val;
@@ -1248,7 +1248,7 @@ Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val)
return addr;
}
void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v)
void OPL3_WriteReg(struct opl3_chip *chip, Bit16u reg, Bit8u v)
{
Bit8u high = (reg >> 8) & 0x01;
Bit8u regm = reg & 0xff;
@@ -1347,7 +1347,7 @@ void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v)
}
}
void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v)
void OPL3_WriteRegBuffered(struct opl3_chip *chip, Bit16u reg, Bit8u v)
{
Bit64u time1, time2;
@@ -1375,7 +1375,7 @@ void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v)
chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE;
}
void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples)
void OPL3_GenerateStream(struct opl3_chip *chip, Bit32s *sndptr, Bit32u numsamples)
{
Bit32u i;

View File

@@ -46,11 +46,12 @@ typedef uint64_t Bit64u;
struct opl3_slot;
struct opl3_channel;
struct opl3_writebuf;
struct opl3_chip;
struct opl3_slot {
opl3_channel *channel;
opl3_chip *chip;
struct opl3_channel *channel;
struct opl3_chip *chip;
Bit16s out;
Bit16s fbmod;
Bit16s *mod;
@@ -81,9 +82,9 @@ struct opl3_slot {
};
struct opl3_channel {
opl3_slot *slots[2];
opl3_channel *pair;
opl3_chip *chip;
struct opl3_slot *slots[2];
struct opl3_channel *pair;
struct opl3_chip *chip;
Bit16s *out[4];
Bit8u chtype;
Bit16u f_num;
@@ -103,8 +104,8 @@ struct opl3_writebuf {
};
struct opl3_chip {
opl3_channel channel[18];
opl3_slot slot[36];
struct opl3_channel channel[18];
struct opl3_slot slot[36];
Bit16u timer;
Bit64u eg_timer;
Bit8u eg_timerrem;
@@ -137,14 +138,14 @@ struct opl3_chip {
Bit32u writebuf_cur;
Bit32u writebuf_last;
Bit64u writebuf_lasttime;
opl3_writebuf writebuf[OPL_WRITEBUF_SIZE];
struct opl3_writebuf writebuf[OPL_WRITEBUF_SIZE];
};
void OPL3_Generate(opl3_chip *chip, Bit16s *buf);
void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf);
void OPL3_Reset(opl3_chip *chip, Bit32u samplerate);
Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val);
void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v);
void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v);
void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples);
void OPL3_Generate(struct opl3_chip *chip, Bit16s *buf);
void OPL3_GenerateResampled(struct opl3_chip *chip, Bit32s *buf);
void OPL3_Reset(struct opl3_chip *chip, Bit32u samplerate);
Bit32u OPL3_WriteAddr(struct opl3_chip *chip, Bit32u port, Bit8u val);
void OPL3_WriteReg(struct opl3_chip *chip, Bit16u reg, Bit8u v);
void OPL3_WriteRegBuffered(struct opl3_chip *chip, Bit16u reg, Bit8u v);
void OPL3_GenerateStream(struct opl3_chip *chip, Bit32s *sndptr, Bit32u numsamples);
#endif

View File

@@ -1,187 +0,0 @@
/* Copyright holders: Sarah Walker, SA1988
see COPYING for more details
*/
#include "dbopl.h"
#include "nukedopl.h"
#include "sound.h"
#include "snd_dbopl.h"
int opl_type = 0;
static struct
{
DBOPL::Chip chip;
opl3_chip opl3chip;
int addr;
int timer[2];
uint8_t timer_ctrl;
uint8_t status_mask;
uint8_t status;
int is_opl3;
void (*timer_callback)(void *param, int timer, uint64_t period);
void *timer_param;
} opl[2];
enum
{
STATUS_TIMER_1 = 0x40,
STATUS_TIMER_2 = 0x20,
STATUS_TIMER_ALL = 0x80
};
enum
{
CTRL_IRQ_RESET = 0x80,
CTRL_TIMER1_MASK = 0x40,
CTRL_TIMER2_MASK = 0x20,
CTRL_TIMER2_CTRL = 0x02,
CTRL_TIMER1_CTRL = 0x01
};
void opl_init(void (*timer_callback)(void *param, int timer, uint64_t period), void *timer_param, int nr, int is_opl3)
{
opl[nr].timer_callback = timer_callback;
opl[nr].timer_param = timer_param;
opl[nr].is_opl3 = is_opl3;
if (!opl_type)
{
DBOPL::InitTables();
opl[nr].chip.Setup(48000, is_opl3);
}
else
{
opl[nr].opl3chip.newm = 0;
OPL3_Reset(&opl[nr].opl3chip, 48000);
}
}
void opl_status_update(int nr)
{
if (opl[nr].status & (STATUS_TIMER_1 | STATUS_TIMER_2) & opl[nr].status_mask)
opl[nr].status |= STATUS_TIMER_ALL;
else
opl[nr].status &= ~STATUS_TIMER_ALL;
}
void opl_timer_over(int nr, int timer)
{
if (!timer)
{
opl[nr].status |= STATUS_TIMER_1;
opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4);
}
else
{
opl[nr].status |= STATUS_TIMER_2;
opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16);
}
opl_status_update(nr);
}
void opl_write(int nr, uint16_t addr, uint8_t val)
{
if (!(addr & 1))
{
if (!opl_type)
opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & 0x1ff;
else
opl[nr].addr = (int)OPL3_WriteAddr(&opl[nr].opl3chip, addr, val) & 0x1ff;
if (!opl[nr].is_opl3)
opl[nr].addr &= 0xff;
}
else
{
if (!opl_type)
opl[nr].chip.WriteReg(opl[nr].addr, val);
else {
OPL3_WriteRegBuffered(&opl[nr].opl3chip, (uint16_t) opl[nr].addr, val);
if (opl[nr].addr == 0x105)
opl[nr].opl3chip.newm = opl[nr].addr & 0x01;
}
switch (opl[nr].addr)
{
case 0x02: /*Timer 1*/
opl[nr].timer[0] = 256 - val;
break;
case 0x03: /*Timer 2*/
opl[nr].timer[1] = 256 - val;
break;
case 0x04: /*Timer control*/
if (val & CTRL_IRQ_RESET) /*IRQ reset*/
{
opl[nr].status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2);
opl_status_update(nr);
return;
}
if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER1_CTRL)
{
if (val & CTRL_TIMER1_CTRL)
opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4);
else
opl[nr].timer_callback(opl[nr].timer_param, 0, 0);
}
if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER2_CTRL)
{
if (val & CTRL_TIMER2_CTRL)
opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16);
else
opl[nr].timer_callback(opl[nr].timer_param, 1, 0);
}
opl[nr].status_mask = (~val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)) | 0x80;
opl[nr].timer_ctrl = val;
break;
}
}
}
uint8_t opl_read(int nr, uint16_t addr)
{
if (!(addr & 1))
{
return (opl[nr].status & opl[nr].status_mask) | (opl[nr].is_opl3 ? 0 : 0x06);
}
return opl[nr].is_opl3 ? 0 : 0xff;
}
void opl2_update(int nr, int16_t *buffer, int samples)
{
int c;
Bit32s buffer_32[samples];
if (opl_type)
{
OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples);
}
else
{
opl[nr].chip.GenerateBlock2(samples, buffer_32);
for (c = 0; c < samples; c++)
buffer[c*2] = (int16_t)buffer_32[c];
}
}
void opl3_update(int nr, int16_t *buffer, int samples)
{
int c;
Bit32s buffer_32[samples*2];
if (opl_type)
{
OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples);
}
else
{
opl[nr].chip.GenerateBlock3(samples, buffer_32);
for (c = 0; c < samples*2; c++)
buffer[c] = (int16_t)buffer_32[c];
}
}

View File

@@ -12,21 +12,26 @@
#include "../timer.h"
#include "sound.h"
#include "snd_opl.h"
#include "snd_dbopl.h"
#include "snd_opl_backend.h"
/*Interfaces between 86Box and the actual OPL emulator*/
uint8_t opl2_read(uint16_t a, void *priv)
uint8_t
opl2_read(uint16_t a, void *priv)
{
opl_t *opl = (opl_t *)priv;
sub_cycles((int)(isa_timing * 8));
sub_cycles((int) (isa_timing * 8));
opl2_update2(opl);
return opl_read(0, a);
}
void opl2_write(uint16_t a, uint8_t v, void *priv)
void
opl2_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
@@ -35,15 +40,21 @@ void opl2_write(uint16_t a, uint8_t v, void *priv)
opl_write(1, a, v);
}
uint8_t opl2_l_read(uint16_t a, void *priv)
uint8_t
opl2_l_read(uint16_t a, void *priv)
{
opl_t *opl = (opl_t *)priv;
sub_cycles((int)(isa_timing * 8));
opl2_update2(opl);
return opl_read(0, a);
}
void opl2_l_write(uint16_t a, uint8_t v, void *priv)
void
opl2_l_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
@@ -51,15 +62,21 @@ void opl2_l_write(uint16_t a, uint8_t v, void *priv)
opl_write(0, a, v);
}
uint8_t opl2_r_read(uint16_t a, void *priv)
uint8_t
opl2_r_read(uint16_t a, void *priv)
{
opl_t *opl = (opl_t *)priv;
sub_cycles((int)(isa_timing * 8));
opl2_update2(opl);
return opl_read(1, a);
}
void opl2_r_write(uint16_t a, uint8_t v, void *priv)
void
opl2_r_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
@@ -67,15 +84,21 @@ void opl2_r_write(uint16_t a, uint8_t v, void *priv)
opl_write(1, a, v);
}
uint8_t opl3_read(uint16_t a, void *priv)
uint8_t
opl3_read(uint16_t a, void *priv)
{
opl_t *opl = (opl_t *)priv;
sub_cycles((int)(isa_timing * 8));
opl3_update2(opl);
return opl_read(0, a);
}
void opl3_write(uint16_t a, uint8_t v, void *priv)
void
opl3_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
@@ -84,34 +107,36 @@ void opl3_write(uint16_t a, uint8_t v, void *priv)
}
void opl2_update2(opl_t *opl)
void
opl2_update2(opl_t *opl)
{
if (opl->pos < sound_pos_global)
{
opl2_update(0, &opl->buffer[opl->pos*2], sound_pos_global - opl->pos);
opl2_update(1, &opl->buffer[opl->pos*2 + 1], sound_pos_global - opl->pos);
for (; opl->pos < sound_pos_global; opl->pos++)
{
opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 2);
opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 2);
if (opl->pos < sound_pos_global) {
opl2_update(0, &opl->buffer[opl->pos << 1], sound_pos_global - opl->pos);
opl2_update(1, &opl->buffer2[opl->pos << 1], sound_pos_global - opl->pos);
for (; opl->pos < sound_pos_global; opl->pos++) {
opl->buffer[(opl->pos << 1) + 1] = opl->buffer2[(opl->pos << 1) + 1];
opl->filtbuf[0] = opl->buffer[opl->pos << 1] = (opl->buffer[opl->pos << 1] / 2);
opl->filtbuf[1] = opl->buffer[(opl->pos << 1) + 1] = (opl->buffer[(opl->pos << 1) + 1] / 2);
}
}
}
void opl3_update2(opl_t *opl)
void
opl3_update2(opl_t *opl)
{
if (opl->pos < sound_pos_global)
{
opl3_update(0, &opl->buffer[opl->pos*2], sound_pos_global - opl->pos);
for (; opl->pos < sound_pos_global; opl->pos++)
{
opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 2);
opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 2);
if (opl->pos < sound_pos_global) {
opl3_update(0, &opl->buffer[(opl->pos << 1)], sound_pos_global - opl->pos);
for (; opl->pos < sound_pos_global; opl->pos++) {
opl->filtbuf[0] = opl->buffer[opl->pos << 1] = (opl->buffer[opl->pos << 1] / 2);
opl->filtbuf[1] = opl->buffer[(opl->pos << 1) + 1] = (opl->buffer[(opl->pos << 1) + 1] / 2);
}
}
}
void ym3812_timer_set_0(void *param, int timer, uint64_t period)
void
ym3812_timer_set_0(void *param, int timer, uint64_t period)
{
opl_t *opl = (opl_t *)param;
@@ -120,7 +145,10 @@ void ym3812_timer_set_0(void *param, int timer, uint64_t period)
else
timer_disable(&opl->timers[0][timer]);
}
void ym3812_timer_set_1(void *param, int timer, uint64_t period)
void
ym3812_timer_set_1(void *param, int timer, uint64_t period)
{
opl_t *opl = (opl_t *)param;
@@ -130,7 +158,9 @@ void ym3812_timer_set_1(void *param, int timer, uint64_t period)
timer_disable(&opl->timers[1][timer]);
}
void ymf262_timer_set(void *param, int timer, uint64_t period)
void
ymf262_timer_set(void *param, int timer, uint64_t period)
{
opl_t *opl = (opl_t *)param;
@@ -140,37 +170,53 @@ void ymf262_timer_set(void *param, int timer, uint64_t period)
timer_disable(&opl->timers[0][timer]);
}
static void opl_timer_callback00(void *p)
static void
opl_timer_callback00(void *p)
{
opl_timer_over(0, 0);
}
static void opl_timer_callback01(void *p)
static void
opl_timer_callback01(void *p)
{
opl_timer_over(0, 1);
}
static void opl_timer_callback10(void *p)
static void
opl_timer_callback10(void *p)
{
opl_timer_over(1, 0);
}
static void opl_timer_callback11(void *p)
static void
opl_timer_callback11(void *p)
{
opl_timer_over(1, 1);
}
void opl2_init(opl_t *opl)
void
opl2_init(opl_t *opl)
{
opl_init(ym3812_timer_set_0, opl, 0, 0);
opl_init(ym3812_timer_set_1, opl, 1, 0);
timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0);
timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0);
}
void opl3_init(opl_t *opl)
void
opl3_init(opl_t *opl)
{
opl_init(ymf262_timer_set, opl, 0, 1);
timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
}

View File

@@ -3,30 +3,30 @@
*/
typedef struct opl_t
{
int chip_nr[2];
int pos, chip_nr[2];
int32_t filtbuf[2],
buffer[SOUNDBUFLEN * 2],
buffer2[SOUNDBUFLEN * 2];
pc_timer_t timers[2][2];
int16_t filtbuf[2];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
} opl_t;
uint8_t opl2_read(uint16_t a, void *priv);
void opl2_write(uint16_t a, uint8_t v, void *priv);
uint8_t opl2_l_read(uint16_t a, void *priv);
void opl2_l_write(uint16_t a, uint8_t v, void *priv);
uint8_t opl2_r_read(uint16_t a, void *priv);
void opl2_r_write(uint16_t a, uint8_t v, void *priv);
uint8_t opl3_read(uint16_t a, void *priv);
void opl3_write(uint16_t a, uint8_t v, void *priv);
void opl2_poll(opl_t *opl, int16_t *bufl, int16_t *bufr);
void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr);
extern uint8_t opl2_read(uint16_t a, void *priv);
extern void opl2_write(uint16_t a, uint8_t v, void *priv);
extern uint8_t opl2_l_read(uint16_t a, void *priv);
extern void opl2_l_write(uint16_t a, uint8_t v, void *priv);
extern uint8_t opl2_r_read(uint16_t a, void *priv);
extern void opl2_r_write(uint16_t a, uint8_t v, void *priv);
extern uint8_t opl3_read(uint16_t a, void *priv);
extern void opl3_write(uint16_t a, uint8_t v, void *priv);
void opl2_init(opl_t *opl);
void opl3_init(opl_t *opl);
extern void opl2_poll(opl_t *opl, int16_t *bufl, int16_t *bufr);
extern void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr);
void opl2_update2(opl_t *opl);
void opl3_update2(opl_t *opl);
extern void opl2_init(opl_t *opl);
extern void opl3_init(opl_t *opl);
extern void opl2_update2(opl_t *opl);
extern void opl3_update2(opl_t *opl);

147
src/sound/snd_opl_backend.c Normal file
View File

@@ -0,0 +1,147 @@
/* Copyright holders: Sarah Walker, SA1988
see COPYING for more details
*/
#include "nukedopl.h"
#include "sound.h"
#include "snd_opl_backend.h"
int opl_type = 0;
static struct
{
struct opl3_chip opl3chip;
int addr;
int timer[2];
uint8_t timer_ctrl;
uint8_t status_mask;
uint8_t status;
int is_opl3;
void (*timer_callback)(void *param, int timer, uint64_t period);
void *timer_param;
} opl[2];
enum
{
STATUS_TIMER_1 = 0x40,
STATUS_TIMER_2 = 0x20,
STATUS_TIMER_ALL = 0x80
};
enum
{
CTRL_IRQ_RESET = 0x80,
CTRL_TIMER1_MASK = 0x40,
CTRL_TIMER2_MASK = 0x20,
CTRL_TIMER2_CTRL = 0x02,
CTRL_TIMER1_CTRL = 0x01
};
void
opl_init(void (*timer_callback)(void *param, int timer, uint64_t period), void *timer_param, int nr, int is_opl3)
{
opl[nr].timer_callback = timer_callback;
opl[nr].timer_param = timer_param;
opl[nr].is_opl3 = is_opl3;
opl[nr].opl3chip.newm = 0;
OPL3_Reset(&opl[nr].opl3chip, 48000);
}
void
opl_status_update(int nr)
{
if (opl[nr].status & (STATUS_TIMER_1 | STATUS_TIMER_2) & opl[nr].status_mask)
opl[nr].status |= STATUS_TIMER_ALL;
else
opl[nr].status &= ~STATUS_TIMER_ALL;
}
void
opl_timer_over(int nr, int timer)
{
if (!timer) {
opl[nr].status |= STATUS_TIMER_1;
opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4);
} else {
opl[nr].status |= STATUS_TIMER_2;
opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16);
}
opl_status_update(nr);
}
void
opl_write(int nr, uint16_t addr, uint8_t val)
{
if (!(addr & 1)) {
opl[nr].addr = (int)OPL3_WriteAddr(&opl[nr].opl3chip, addr, val) & 0x1ff;
if (!opl[nr].is_opl3)
opl[nr].addr &= 0xff;
} else {
OPL3_WriteRegBuffered(&opl[nr].opl3chip, (uint16_t) opl[nr].addr, val);
if (opl[nr].addr == 0x105)
opl[nr].opl3chip.newm = opl[nr].addr & 0x01;
switch (opl[nr].addr) {
case 0x02: /*Timer 1*/
opl[nr].timer[0] = 256 - val;
break;
case 0x03: /*Timer 2*/
opl[nr].timer[1] = 256 - val;
break;
case 0x04: /*Timer control*/
if (val & CTRL_IRQ_RESET) { /*IRQ reset*/
opl[nr].status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2);
opl_status_update(nr);
return;
}
if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER1_CTRL) {
if (val & CTRL_TIMER1_CTRL)
opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4);
else
opl[nr].timer_callback(opl[nr].timer_param, 0, 0);
}
if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER2_CTRL) {
if (val & CTRL_TIMER2_CTRL)
opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16);
else
opl[nr].timer_callback(opl[nr].timer_param, 1, 0);
}
opl[nr].status_mask = (~val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)) | 0x80;
opl[nr].timer_ctrl = val;
break;
}
}
}
uint8_t
opl_read(int nr, uint16_t addr)
{
if (!(addr & 1))
return (opl[nr].status & opl[nr].status_mask) | (opl[nr].is_opl3 ? 0 : 0x06);
return opl[nr].is_opl3 ? 0 : 0xff;
}
void
opl2_update(int nr, int32_t *buffer, int samples)
{
OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples);
}
void
opl3_update(int nr, int32_t *buffer, int samples)
{
OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples);
}

View File

@@ -8,8 +8,8 @@ extern "C" {
void opl_write(int nr, uint16_t addr, uint8_t val);
uint8_t opl_read(int nr, uint16_t addr);
void opl_timer_over(int nr, int timer);
void opl2_update(int nr, int16_t *buffer, int samples);
void opl3_update(int nr, int16_t *buffer, int samples);
void opl2_update(int nr, int32_t *buffer, int samples);
void opl3_update(int nr, int32_t *buffer, int samples);
extern int opl_type;
#ifdef __cplusplus

View File

@@ -33,7 +33,6 @@
#include "../device.h"
#include "sound.h"
#include "filters.h"
#include "snd_dbopl.h"
#include "snd_emu8k.h"
#include "snd_mpu401.h"
#include "snd_opl.h"
@@ -203,7 +202,7 @@ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p)
{
int32_t out = 0;
if (sb->opl_enabled)
out = ((sb->opl.buffer[c] * 51000) >> 16);
out = ((sb->opl.buffer[c] * (sb->opl_emu ? 47000 : 51000)) >> 16);
//TODO: Recording: Mic and line In with AGC
out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * 65536) / 3) >> 16;
@@ -231,7 +230,7 @@ static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p)
int32_t out = 0;
if (sb->opl_enabled)
out = ((((sb->opl.buffer[c] * mixer->fm) >> 16) * 51000) >> 15);
out = ((((sb->opl.buffer[c] * mixer->fm) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15);
/* TODO: Recording : I assume it has direct mic and line in like sb2 */
/* It is unclear from the docs if it has a filter, but it probably does */
out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice) / 3) >> 15;

View File

@@ -8,7 +8,7 @@
*
* Application resource script for Windows.
*
* Version: @(#)86Box.rc 1.0.55 2019/12/05
* Version: @(#)86Box.rc 1.0.56 2019/12/21
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -391,11 +391,8 @@ BEGIN
CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,81,94,10
CONTROL "Use Nuked OPL",IDC_CHECK_NUKEDOPL,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,147,81,94,10
CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10
BS_AUTOCHECKBOX | WS_TABSTOP,147,81,94,10
END
DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63
@@ -903,7 +900,6 @@ BEGIN
IDS_2120 "Unable to initialize SDL, SDL2.dll is required"
IDS_2121 "Are you sure you want to hard reset the emulated machine?"
IDS_2122 "Are you sure you want to quit 86Box?"
IDS_2123 "Unable to initialize Ghostscript, gsdll32.dll is required for automatic convertion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript files (.ps)."
END
STRINGTABLE DISCARDABLE

View File

@@ -8,7 +8,7 @@
#
# Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.139 2019/12/05
# Version: @(#)Makefile.mingw 1.0.140 2019/12/21
#
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
@@ -604,7 +604,7 @@ HDDOBJ := hdd.o \
hdc_ide_sff8038i.o
CDROMOBJ := cdrom.o \
cdrom_dosbox.o cdrom_image.o
cdrom_image_backend.o cdrom_image.o
ZIPOBJ := zip.o
@@ -633,8 +633,8 @@ PRINTOBJ := png.o prt_cpmap.o \
SNDOBJ := sound.o \
openal.o \
snd_opl.o snd_dbopl.o \
dbopl.o nukedopl.o \
snd_opl.o snd_opl_backend.o \
nukedopl.o \
snd_resid.o \
convolve.o convolve-sse.o envelope.o extfilt.o \
filter.o pot.o sid.o voice.o wave6581__ST.o \
@@ -691,12 +691,8 @@ VIDOBJ := video.o \
PLATOBJ := win.o \
win_dynld.o win_thread.o \
win_cdrom.o win_keyboard.o \
win_midi.o
ifeq ($(DINPUT), y)
PLATOBJ += win_mouse.o win_joystick.o
else
PLATOBJ += win_mouse_rawinput.o win_joystick.o
endif
win_midi.o \
win_mouse.o win_joystick.o
OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) \
$(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \

View File

@@ -8,7 +8,7 @@
#
# Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.139 2019/12/05
# Version: @(#)Makefile.mingw 1.0.140 2019/12/21
#
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
@@ -610,7 +610,7 @@ HDDOBJ := hdd.o \
hdc_ide_sff8038i.o
CDROMOBJ := cdrom.o \
cdrom_dosbox.o cdrom_image.o
cdrom_image_backend.o cdrom_image.o
ZIPOBJ := zip.o
@@ -639,8 +639,8 @@ PRINTOBJ := png.o prt_cpmap.o \
SNDOBJ := sound.o \
openal.o \
snd_opl.o snd_dbopl.o \
dbopl.o nukedopl.o \
snd_opl.o snd_opl_backend.o \
nukedopl.o \
snd_resid.o \
convolve.o convolve-sse.o envelope.o extfilt.o \
filter.o pot.o sid.o voice.o wave6581__ST.o \
@@ -697,12 +697,8 @@ VIDOBJ := video.o \
PLATOBJ := win.o \
win_dynld.o win_thread.o \
win_cdrom.o win_keyboard.o \
win_midi.o
ifeq ($(DINPUT), y)
PLATOBJ += win_mouse.o win_joystick.o
else
PLATOBJ += win_mouse_rawinput.o win_joystick.o
endif
win_midi.o \
win_mouse.o win_joystick.o
OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) \
$(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \

View File

@@ -8,7 +8,7 @@
*
* Windows resource defines.
*
* Version: @(#)resource.h 1.0.31 2019/12/05
* Version: @(#)resource.h 1.0.32 2019/12/21
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -144,12 +144,11 @@
#define IDC_CHECK_SSI 1072
#define IDC_CHECK_CMS 1073
#define IDC_CHECK_GUS 1074
#define IDC_CHECK_NUKEDOPL 1075
#define IDC_COMBO_MIDI 1076
#define IDC_CHECK_MPU401 1077
#define IDC_CONFIGURE_MPU401 1078
#define IDC_CHECK_FLOAT 1079
#define IDC_CHECK_GUSMAX 1080
#define IDC_COMBO_MIDI 1075
#define IDC_CHECK_MPU401 1076
#define IDC_CONFIGURE_MPU401 1077
#define IDC_CHECK_FLOAT 1078
#define IDC_CHECK_GUSMAX 1079
#define IDC_COMBO_NET_TYPE 1090 /* network config */
#define IDC_COMBO_PCAP 1091

View File

@@ -64,6 +64,7 @@ win_mouse_handle(LPARAM lParam, int infocus)
UINT size;
RAWINPUT *raw;
RAWMOUSE state;
static int x, y;
if (! infocus) return;
@@ -109,7 +110,7 @@ win_mouse_handle(LPARAM lParam, int infocus)
* seems to work fine for RDP on Windows 10
* Not sure about other environments.
*/
static int x=state.lLastX, y=state.lLastY;
x=state.lLastX, y=state.lLastY;
mousestate.dx += (state.lLastX - x)/100;
mousestate.dy += (state.lLastY - y)/100;
x=state.lLastX;

View File

@@ -1,103 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Mouse interface to host device.
*
* Version: @(#)win_mouse.cpp 1.0.6 2017/11/25
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include <stdio.h>
#include <stdint.h>
#include "../86box.h"
#include "../mouse.h"
#include "../plat.h"
#include "win.h"
int mouse_capture;
static LPDIRECTINPUT8 lpdi;
static LPDIRECTINPUTDEVICE8 lpdi_mouse = NULL;
static DIMOUSESTATE mousestate;
void
win_mouse_init(void)
{
atexit(win_mouse_close);
mouse_capture = 0;
if (FAILED(DirectInput8Create(hinstance, DIRECTINPUT_VERSION,
IID_IDirectInput8A, (void **) &lpdi, NULL)))
fatal("plat_mouse_init: DirectInputCreate failed\n");
if (FAILED(lpdi->CreateDevice(GUID_SysMouse, &lpdi_mouse, NULL)))
fatal("plat_mouse_init: CreateDevice failed\n");
if (FAILED(lpdi_mouse->SetCooperativeLevel(hwndMain,
DISCL_FOREGROUND | (video_fullscreen ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE))))
fatal("plat_mouse_init: SetCooperativeLevel failed\n");
if (FAILED(lpdi_mouse->SetDataFormat(&c_dfDIMouse)))
fatal("plat_mouse_init: SetDataFormat failed\n");
}
void
win_mouse_close(void)
{
if (lpdi_mouse != NULL) {
lpdi_mouse->Release();
lpdi_mouse = NULL;
}
}
void
mouse_poll(void)
{
static int buttons = 0;
static int x = 0, y = 0, z = 0;
int b;
if (FAILED(lpdi_mouse->GetDeviceState(sizeof(DIMOUSESTATE),
(LPVOID)&mousestate))) {
lpdi_mouse->Acquire();
lpdi_mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mousestate);
}
if (mouse_capture || video_fullscreen) {
if (x != mousestate.lX || y != mousestate.lY || z != mousestate.lZ) {
mouse_x += mousestate.lX;
mouse_y += mousestate.lY;
mouse_z += mousestate.lZ/120;
x = mousestate.lX;
y = mousestate.lY;
z = mousestate.lZ/120;
}
b = 0;
if (mousestate.rgbButtons[0] & 0x80) b |= 1;
if (mousestate.rgbButtons[1] & 0x80) b |= 2;
if (mousestate.rgbButtons[2] & 0x80) b |= 4;
if (buttons != b) {
mouse_buttons = b;
buttons = b;
}
}
}

View File

@@ -8,7 +8,7 @@
*
* Windows 86Box Settings dialog handler.
*
* Version: @(#)win_settings.c 1.0.62 2019/11/19
* Version: @(#)win_settings.c 1.0.63 2019/12/21
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* David Hrdlička, <hrdlickadavid@outlook.com>
@@ -55,7 +55,6 @@
#include "../network/network.h"
#include "../sound/sound.h"
#include "../sound/midi.h"
#include "../sound/snd_dbopl.h"
#include "../sound/snd_mpu401.h"
#include "../video/video.h"
#include "../video/vid_voodoo.h"
@@ -85,7 +84,7 @@ static int temp_gfxcard, temp_voodoo;
static int temp_mouse, temp_joystick;
/* Sound category */
static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS, temp_opl_type;
static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS;
static int temp_float;
/* Network category */
@@ -223,7 +222,6 @@ win_settings_init(void)
temp_SSI2001 = SSI2001;
temp_GAMEBLASTER = GAMEBLASTER;
temp_GUS = GUS;
temp_opl_type = opl_type;
temp_float = sound_is_float;
/* Network category */
@@ -335,7 +333,6 @@ win_settings_changed(void)
i = i || (SSI2001 != temp_SSI2001);
i = i || (GAMEBLASTER != temp_GAMEBLASTER);
i = i || (GUS != temp_GUS);
i = i || (opl_type != temp_opl_type);
i = i || (sound_is_float != temp_float);
/* Network category */
@@ -438,7 +435,6 @@ win_settings_save(void)
SSI2001 = temp_SSI2001;
GAMEBLASTER = temp_GAMEBLASTER;
GUS = temp_GUS;
opl_type = temp_opl_type;
sound_is_float = temp_float;
/* Network category */
@@ -1215,9 +1211,6 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
h=GetDlgItem(hdlg, IDC_CHECK_SSI);
SendMessage(h, BM_SETCHECK, temp_SSI2001, 0);
h=GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL);
SendMessage(h, BM_SETCHECK, temp_opl_type, 0);
h=GetDlgItem(hdlg, IDC_CHECK_FLOAT);
SendMessage(h, BM_SETCHECK, temp_float, 0);
@@ -1311,9 +1304,6 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
h = GetDlgItem(hdlg, IDC_CHECK_SSI);
temp_SSI2001 = SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL);
temp_opl_type = SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CHECK_FLOAT);
temp_float = SendMessage(h, BM_GETCHECK, 0, 0);