Files
2014-08-09 08:46:27 -07:00

1835 lines
64 KiB
C
Executable File

/*****************************************************************************
** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Board/Machine.c,v $
**
** $Revision: 1.69 $
**
** $Date: 2008-11-23 20:26:12 $
**
** More info: http://www.bluemsx.com
**
** Copyright (C) 2003-2006 Daniel Vik
**
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**
******************************************************************************
*/
#include "Machine.h"
#include "SaveState.h"
#include "IniFileParser.h"
#include "ArchGlob.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "ArchFile.h"
#include "MediaDb.h"
#include "TokenExtract.h"
#include "Disk.h"
#include "unzip.h"
#include "AppConfig.h"
#include "RomLoader.h"
#include "MSXMidi.h"
#include "ramMapper.h"
#include "ramMapperIo.h"
#include "ramNormal.h"
#include "romMapperNormal.h"
#include "romMapperKanji.h"
#include "romMapperKanji12.h"
#include "romMapperBasic.h"
#include "romMapperCasette.h"
#include "romMapperStandard.h"
#include "romMapperMsxDos2.h"
#include "romMapperKonami5.h"
#include "romMapperKonami4.h"
#include "romMapperKoei.h"
#include "romMapperHolyQuran.h"
#include "romMapperMegaRAM.h"
#include "romMapperASCII8.h"
#include "romMapperASCII16.h"
#include "romMapperDisk.h"
#include "romMapperTC8566AF.h"
#include "romMapperMicrosol.h"
#include "romMapperNationalFdc.h"
#include "romMapperPhilipsFdc.h"
#include "romMapperSvi707Fdc.h"
#include "romMapperSvi738Fdc.h"
#include "romMapperGameMaster2.h"
#include "romMapperASCII8sram.h"
#include "romMapperASCII16sram.h"
#include "romMapperASCII16nf.h"
#include "romMapperKonami4nf.h"
#include "romMapperPlain.h"
#include "romMapperHarryFox.h"
#include "romMapperHalnote.h"
#include "romMapperMsxAudio.h"
#include "romMapperRType.h"
#include "romMapperCrossBlaim.h"
#include "romMapperKorean80.h"
#include "romMapperKorean90.h"
#include "romMapperKorean126.h"
#include "romMapperPAC.h"
#include "romMapperFMPAC.h"
#include "romMapperFMPAK.h"
#include "romMapperLodeRunner.h"
#include "romMapperSCCplus.h"
#include "romMapperPanasonic.h"
#include "romMapperNational.h"
#include "sramMapperMatsuchita.h"
#include "romMapperKonamiSynth.h"
#include "romMapperKonamiKeyboardMaster.h"
#include "romMapperKonamiWordPro.h"
#include "romMapperMajutsushi.h"
#include "sramMapperS1985.h"
#include "romMapperS1990.h"
#include "romMapperF4device.h"
#include "romMapperBunsetu.h"
#include "romMapperTurboRTimer.h"
#include "romMapperTurboRPcm.h"
#include "TurboRIO.h"
#include "romMapperSonyHBI55.h"
#include "romMapperMsxMusic.h"
#include "romMapperMsxPrn.h"
#include "romMapperMoonsound.h"
#include "romMapperGameReader.h"
#include "romMapperSvi328Prn.h"
#include "romMapperSvi328Rs232.h"
#include "romMapperSvi328Fdc.h"
#include "romMapperSvi727.h"
#include "ram1kBMirrored.h"
#include "romMapperSunriseIDE.h"
#include "romMapperBeerIDE.h"
#include "romMapperGIDE.h"
#include "romMapperSvi328RsIDE.h"
#include "romMapperMicrosolVmx80.h"
#include "romMapperNms8280VideoDa.h"
#include "romMapperSonyHBIV1.h"
#include "romMapperFmDas.h"
#include "romMapperSfg05.h"
#include "romMapperSf7000Ipl.h"
#include "romMapperPlayBall.h"
#include "romMapperObsonet.h"
#include "romMapperSg1000Castle.h"
#include "romMapperSg1000.h"
#include "romMapperSg1000RamExpander.h"
#include "romMapperSegaBasic.h"
#include "romMapperDumas.h"
#include "sramMapperMegaSCSI.h"
#include "sramMapperEseSCC.h"
#include "romMapperNoWind.h"
#include "romMapperGoudaSCSI.h"
#include "romMapperMegaFlashRomScc.h"
#include "romMapperForteII.h"
#include "romMapperA1FMModem.h"
#include "romMapperA1FM.h"
#include "romMapperDRAM.h"
#include "romMapperMatraINK.h"
#include "romMapperNettouYakyuu.h"
#include "romMapperNet.h"
#include "romMapperJoyrexPsg.h"
#include "romMapperOpcodePsg.h"
#include "romMapperArc.h"
#include "romMapperOpcodeBios.h"
#include "romMapperOpcodeMegaRam.h"
#include "romMapperOpcodeSaveRam.h"
#include "romMapperOpcodeSlotManager.h"
#include "romMapperDooly.h"
#include "romMapperMuPack.h"
// PacketFileSystem.h Need to be included after all other includes
#include "PacketFileSystem.h"
#include "romExclusion.h"
static char machinesDir[PROP_MAXPATH] = "";
int toint(char* buffer)
{
int i;
if (buffer == NULL) {
return -1;
}
for (i = 0; buffer[i]; i++) {
if (!isdigit(buffer[i])) return -1;
}
return atoi(buffer);
}
#ifdef WIN32
char *strcasestr(const char *str1, const char *str2)
{
char *str1copy;
char *str2copy;
char *ptr;
int offset;
if (str1 == NULL || str2 == NULL)
return NULL;
// Create a copy of each
str1copy = _strdup(str1);
str2copy = _strdup(str2);
// Convert both to lowercase
_strlwr(str1copy);
_strlwr(str2copy);
// Find the occurrence in the lowercased version
ptr = strstr(str1copy, str2copy);
// Now that we have the position, contents are not needed
free(str1copy);
free(str2copy);
if (ptr == NULL)
return NULL; // No match
// Compute the offset in the lowercased version
offset = ptr - str1copy;
return (char *)(str1 + offset); // Return the original version + offset
}
#endif
static int readMachine(Machine* machine, const char* machineName, const char* file)
{
static char buffer[10000];
char* slotBuf;
int value;
int i = 0;
IniFile *configIni;
if (machine->isZipped)
configIni = iniFileOpenZipped(machine->zipFile, "config.ini");
else
configIni = iniFileOpen(file);
if (configIni == NULL)
return 0;
strcpy(machine->name, machineName);
// Read board info
iniFileGetString(configIni, "Board", "type", "none", buffer, 10000);
if (0 == strcmp(buffer, "MSX")) machine->board.type = BOARD_MSX;
else if (0 == strcmp(buffer, "MSX-S3527")) machine->board.type = BOARD_MSX_S3527;
else if (0 == strcmp(buffer, "MSX-S1985")) machine->board.type = BOARD_MSX_S1985;
else if (0 == strcmp(buffer, "MSX-T9769B")) machine->board.type = BOARD_MSX_T9769B;
else if (0 == strcmp(buffer, "MSX-T9769C")) machine->board.type = BOARD_MSX_T9769C;
else if (0 == strcmp(buffer, "MSX-ForteII")) machine->board.type = BOARD_MSX_FORTE_II;
else if (0 == strcmp(buffer, "SVI")) machine->board.type = BOARD_SVI;
else if (0 == strcmp(buffer, "ColecoVision")) machine->board.type = BOARD_COLECO;
else if (0 == strcmp(buffer, "ColecoAdam")) machine->board.type = BOARD_COLECOADAM;
else if (0 == strcmp(buffer, "SG-1000")) machine->board.type = BOARD_SG1000;
else if (0 == strcmp(buffer, "SF-7000")) machine->board.type = BOARD_SF7000;
else if (0 == strcmp(buffer, "SC-3000")) machine->board.type = BOARD_SC3000;
else machine->board.type = BOARD_MSX;
// Read video info
iniFileGetString(configIni, "Video", "version", "none", buffer, 10000);
if (0 == strcmp(buffer, "V9938")) machine->video.vdpVersion = VDP_V9938;
else if (0 == strcmp(buffer, "V9958")) machine->video.vdpVersion = VDP_V9958;
else if (0 == strcmp(buffer, "TMS9929A")) machine->video.vdpVersion = VDP_TMS9929A;
else if (0 == strcmp(buffer, "TMS99x8A")) machine->video.vdpVersion = VDP_TMS99x8A;
else { iniFileClose(configIni); return 0; }
iniFileGetString(configIni, "Video", "vram size", "none", buffer, 10000);
if (0 == strcmp(buffer, "16kB")) machine->video.vramSize = 16 * 1024;
else if (0 == strcmp(buffer, "64kB")) machine->video.vramSize = 64 * 1024;
else if (0 == strcmp(buffer, "128kB")) machine->video.vramSize = 128 * 1024;
else if (0 == strcmp(buffer, "192kB")) machine->video.vramSize = 192 * 1024;
else { iniFileClose(configIni); return 0; }
// Read CMOS info
iniFileGetString(configIni, "CMOS", "Enable CMOS", "none", buffer, 10000);
if (0 == strcmp(buffer, "none")) machine->cmos.enable = 1;
else if (0 == strcmp(buffer, "0")) machine->cmos.enable = 0;
else if (0 == strcmp(buffer, "1")) machine->cmos.enable = 1;
else { iniFileClose(configIni); return 0; }
// Read CPU info
iniFileGetString(configIni, "CPU", "Z80 Frequency", "none", buffer, 10000);
if (0 == sscanf(buffer, "%dHz", &value)) {
value = 3579545;
}
machine->cpu.freqZ80 = value;
// Read CPU info
iniFileGetString(configIni, "CPU", "R800 Frequency", "none", buffer, 10000);
if (0 == sscanf(buffer, "%dHz", &value)) {
value = 7159090;
}
machine->cpu.freqR800 = value;
// Read FDC info
iniFileGetString(configIni, "FDC", "Count", "none", buffer, 10000);
if (0 == strcmp(buffer, "none")) machine->fdc.count = 2;
else if (0 == strcmp(buffer, "0")) machine->fdc.count = 0;
else if (0 == strcmp(buffer, "1")) machine->fdc.count = 1;
else if (0 == strcmp(buffer, "2")) machine->fdc.count = 2;
else if (0 == strcmp(buffer, "3")) machine->fdc.count = 3;
else if (0 == strcmp(buffer, "4")) machine->fdc.count = 4;
else { iniFileClose(configIni); return 0; }
iniFileGetString(configIni, "CMOS", "Battery Backed", "none", buffer, 10000);
if (0 == strcmp(buffer, "none")) machine->cmos.batteryBacked = 1;
else if (0 == strcmp(buffer, "0")) machine->cmos.batteryBacked = 0;
else if (0 == strcmp(buffer, "1")) machine->cmos.batteryBacked = 1;
else { iniFileClose(configIni); return 0; }
// Read audio info
iniFileGetString(configIni, "AUDIO", "PSG Stereo", "none", buffer, 10000);
if (0 == strcmp(buffer, "none")) machine->audio.psgstereo = 0;
else if (0 == strcmp(buffer, "0")) machine->audio.psgstereo = 0;
else if (0 == strcmp(buffer, "1")) machine->audio.psgstereo = 1;
else { iniFileClose(configIni); return 0; }
for (i = 0; i < sizeof(machine->audio.psgpan) / sizeof(machine->audio.psgpan[0]); i++) {
char s[32];
sprintf(s, "PSG Pan channel %d", i);
iniFileGetString(configIni, "AUDIO", s, "none", buffer, 10000);
if (0 == strcmp(buffer, "none")) machine->audio.psgpan[i] = i == 0 ? 0 : i == 1 ? -1 : 1;
else if (0 == strcmp(buffer, "left")) machine->audio.psgpan[i] = -1;
else if (0 == strcmp(buffer, "center")) machine->audio.psgpan[i] = 0;
else if (0 == strcmp(buffer, "right")) machine->audio.psgpan[i] = 1;
else { iniFileClose(configIni); return 0; }
}
// Read subslot info
iniFileGetString(configIni, "Subslotted Slots", "slot 0", "none", buffer, 10000);
if (0 == strcmp(buffer, "0")) machine->slot[0].subslotted = 0;
else if (0 == strcmp(buffer, "1")) machine->slot[0].subslotted = 1;
else { iniFileClose(configIni); return 0; }
iniFileGetString(configIni, "Subslotted Slots", "slot 1", "none", buffer, 10000);
if (0 == strcmp(buffer, "0")) machine->slot[1].subslotted = 0;
else if (0 == strcmp(buffer, "1")) machine->slot[1].subslotted = 1;
else { iniFileClose(configIni); return 0; }
iniFileGetString(configIni, "Subslotted Slots", "slot 2", "none", buffer, 10000);
if (0 == strcmp(buffer, "0")) machine->slot[2].subslotted = 0;
else if (0 == strcmp(buffer, "1")) machine->slot[2].subslotted = 1;
else { iniFileClose(configIni); return 0; }
iniFileGetString(configIni, "Subslotted Slots", "slot 3", "none", buffer, 10000);
if (0 == strcmp(buffer, "0")) machine->slot[3].subslotted = 0;
else if (0 == strcmp(buffer, "1")) machine->slot[3].subslotted = 1;
else { iniFileClose(configIni); return 0; }
// Read external slot info
iniFileGetString(configIni, "External Slots", "slot A", "none", buffer, 10000);
machine->cart[0].slot = toint(extractToken(buffer, 0));
machine->cart[0].subslot = toint(extractToken(buffer, 1));
if (machine->cart[0].slot < 0 || machine->cart[0].slot >= 4) { iniFileClose(configIni); return 0; }
if (machine->cart[0].subslot < 0 || machine->cart[0].subslot >= 4) { iniFileClose(configIni); return 0; }
iniFileGetString(configIni, "External Slots", "slot B", "none", buffer, 10000);
machine->cart[1].slot = toint(extractToken(buffer, 0));
machine->cart[1].subslot = toint(extractToken(buffer, 1));
if (machine->cart[1].slot < 0 || machine->cart[1].slot >= 4) { iniFileClose(configIni); return 0; }
if (machine->cart[1].subslot < 0 || machine->cart[1].subslot >= 4) { iniFileClose(configIni); return 0; }
// Read slots
iniFileGetSection(configIni, "Slots", buffer, 10000);
slotBuf = buffer;
machine->cpu.hasR800 = 0;
machine->fdc.enabled = 0;
for (i = 0; i < sizeof(machine->slotInfo) / sizeof(SlotInfo) && *slotBuf; i++) {
char* arg;
char slotInfoName[512];
char *slotFilename;
machine->slotInfo[i].slot = toint(extractToken(slotBuf, 0));
machine->slotInfo[i].subslot = toint(extractToken(slotBuf, 1));
machine->slotInfo[i].startPage = toint(extractToken(slotBuf, 2));
machine->slotInfo[i].pageCount = toint(extractToken(slotBuf, 3));
machine->slotInfo[i].romType = toint(extractToken(slotBuf, 4));
machine->cpu.hasR800 |= machine->slotInfo[i].romType == ROM_S1990;
machine->fdc.enabled |= machine->slotInfo[i].romType == ROM_DISKPATCH ||
machine->slotInfo[i].romType == ROM_TC8566AF ||
machine->slotInfo[i].romType == ROM_TC8566AF_TR ||
machine->slotInfo[i].romType == ROM_MICROSOL ||
machine->slotInfo[i].romType == ROM_NATIONALFDC ||
machine->slotInfo[i].romType == ROM_PHILIPSFDC ||
machine->slotInfo[i].romType == ROM_SVI328FDC ||
machine->slotInfo[i].romType == ROM_SVI707FDC ||
machine->slotInfo[i].romType == ROM_SVI738FDC;
arg = extractToken(slotBuf, 5);
strcpy(machine->slotInfo[i].name, arg ? arg : "");
arg = extractToken(slotBuf, 6);
strcpy(machine->slotInfo[i].inZipName, arg ? arg : "");
if (machine->slotInfo[i].slot < 0 || machine->slotInfo[i].slot >= 4) { iniFileClose(configIni); return 0; }
if (machine->slotInfo[i].subslot < 0 || machine->slotInfo[i].subslot >= 4) { iniFileClose(configIni); return 0; }
if (machine->slotInfo[i].startPage < 0 || machine->slotInfo[i].startPage >= 8) { iniFileClose(configIni); return 0; }
if (machine->slotInfo[i].pageCount == -1) { iniFileClose(configIni); return 0; }
if (machine->slotInfo[i].romType < 1 || machine->slotInfo[i].romType > ROM_MAXROMID) { iniFileClose(configIni); return 0; }
slotBuf += strlen(slotBuf) + 1;
strcpy(slotInfoName, machine->slotInfo[i].name);
slotFilename = strrchr(slotInfoName, '/');
if (slotFilename == NULL)
slotFilename = strrchr(slotInfoName, '\\');
if (slotFilename == NULL)
slotFilename = slotInfoName;
else
slotFilename++;
if (!machine->isZipped)
{
// Convert the relative path into absolute
if (strcasestr(machine->slotInfo[i].name, "Machines/") == machine->slotInfo[i].name ||
strcasestr(machine->slotInfo[i].name, "Machines\\") == machine->slotInfo[i].name)
{
char expandedPath[1024];
sprintf(expandedPath, "%s/%s", machinesDir, machine->slotInfo[i].name + 9);
strcpy(machine->slotInfo[i].name, expandedPath);
}
}
else if (*machine->slotInfo[i].name)
{
char iniFilePath[512];
char *parentDir;
strcpy(iniFilePath, iniFileGetFilePath(configIni));
parentDir = strrchr(iniFilePath, '/');
if (parentDir == NULL)
parentDir = strrchr(iniFilePath, '\\');
if (parentDir == NULL)
parentDir = iniFilePath;
else
*(parentDir + 1) = '\0';
strcpy(machine->slotInfo[i].name, machine->zipFile);
sprintf(machine->slotInfo[i].inZipName, "%s%s",
iniFilePath, slotFilename);
}
#ifdef __APPLE__
// On OS X, replace all backslashes with slashes
for (char *ch = machine->slotInfo[i].name; *ch; ch++)
if (*ch == '\\') *ch = '/';
#endif
}
machine->slotInfoCount = i;
iniFileClose(configIni);
return 1;
}
void machineSave(Machine* machine)
{
char dir[512];
char file[512];
char buffer[10000];
int size = 0;
int i;
IniFile *configIni;
sprintf(dir, "%s/%s", machinesDir, machine->name);
archCreateDirectory(dir);
sprintf(file, "%s/%s/config.ini", machinesDir, machine->name);
configIni = iniFileOpen(file);
if (configIni == NULL)
return;
// Write CMOS info
iniFileWriteString(configIni, "CMOS", "Enable CMOS", machine->cmos.enable ? "1" : "0");
iniFileWriteString(configIni, "CMOS", "Battery Backed", machine->cmos.batteryBacked ? "1" : "0");
// Write Audio info
iniFileWriteString(configIni, "AUDIO", "PSG Stereo", machine->audio.psgstereo ? "1" : "0");
if (machine->audio.psgstereo) {
for (i = 0; i < sizeof(machine->audio.psgpan) / sizeof(machine->audio.psgpan[0]); i++) {
char s[32];
int pan = machine->audio.psgpan[i];
sprintf(s, "PSG Pan channel %d", i);
iniFileWriteString(configIni, "AUDIO", s, pan < 0 ? "left" : pan > 0 ? "right" : "center");
}
}
// Write FDC info
sprintf(buffer, "%d", machine->fdc.count);
iniFileWriteString(configIni, "FDC", "Count", buffer);
// Write CPU info
sprintf(buffer, "%dHz", machine->cpu.freqZ80);
iniFileWriteString(configIni, "CPU", "Z80 Frequency", buffer);
if (machine->cpu.hasR800) {
sprintf(buffer, "%dHz", machine->cpu.freqR800);
iniFileWriteString(configIni, "CPU", "R800 Frequency", buffer);
}
// Write Board info
switch (machine->board.type) {
case BOARD_MSX: iniFileWriteString(configIni, "Board", "type", "MSX"); break;
case BOARD_MSX_S3527: iniFileWriteString(configIni, "Board", "type", "MSX-S3527"); break;
case BOARD_MSX_S1985: iniFileWriteString(configIni, "Board", "type", "MSX-S1985"); break;
case BOARD_MSX_T9769B: iniFileWriteString(configIni, "Board", "type", "MSX-T9769B"); break;
case BOARD_MSX_T9769C: iniFileWriteString(configIni, "Board", "type", "MSX-T9769C"); break;
case BOARD_MSX_FORTE_II: iniFileWriteString(configIni, "Board", "type", "MSX-ForteII"); break;
case BOARD_SVI: iniFileWriteString(configIni, "Board", "type", "SVI"); break;
case BOARD_COLECO: iniFileWriteString(configIni, "Board", "type", "ColecoVision"); break;
case BOARD_COLECOADAM: iniFileWriteString(configIni, "Board", "type", "ColecoAdam"); break;
case BOARD_SG1000: iniFileWriteString(configIni, "Board", "type", "SG-1000"); break;
case BOARD_SF7000: iniFileWriteString(configIni, "Board", "type", "SF-7000"); break;
case BOARD_SC3000: iniFileWriteString(configIni, "Board", "type", "SC-3000"); break;
}
// Write video info
switch (machine->video.vdpVersion) {
case VDP_V9958: iniFileWriteString(configIni, "Video", "version", "V9958"); break;
case VDP_V9938: iniFileWriteString(configIni, "Video", "version", "V9938"); break;
case VDP_TMS9929A: iniFileWriteString(configIni, "Video", "version", "TMS9929A"); break;
case VDP_TMS99x8A: iniFileWriteString(configIni, "Video", "version", "TMS99x8A"); break;
}
sprintf(buffer, "%dkB", machine->video.vramSize / 0x400);
iniFileWriteString(configIni, "Video", "vram size", buffer);
// Write subslot info
iniFileWriteString(configIni, "Subslotted Slots", "slot 0", machine->slot[0].subslotted ? "1" : "0");
iniFileWriteString(configIni, "Subslotted Slots", "slot 1", machine->slot[1].subslotted ? "1" : "0");
iniFileWriteString(configIni, "Subslotted Slots", "slot 2", machine->slot[2].subslotted ? "1" : "0");
iniFileWriteString(configIni, "Subslotted Slots", "slot 3", machine->slot[3].subslotted ? "1" : "0");
// Write external slot info
sprintf(buffer, "%d %d", machine->cart[0].slot, machine->cart[0].subslot);
iniFileWriteString(configIni, "External Slots", "slot A", buffer);
sprintf(buffer, "%d %d", machine->cart[1].slot, machine->cart[1].subslot);
iniFileWriteString(configIni, "External Slots", "slot B", buffer);
// Write slots
for (i = 0; i < machine->slotInfoCount; i++) {
size += sprintf(buffer + size, "%d %d %d %d %d \"%s\" \"%s\"",
machine->slotInfo[i].slot,
machine->slotInfo[i].subslot,
machine->slotInfo[i].startPage,
machine->slotInfo[i].pageCount,
machine->slotInfo[i].romType,
machine->slotInfo[i].name,
machine->slotInfo[i].inZipName);
buffer[size++] = 0;
}
buffer[size++] = 0;
buffer[size++] = 0;
// iniFileWriteString("Slots", NULL, NULL);
iniFileWriteSection(configIni, "Slots", buffer);
iniFileClose(configIni);
}
Machine* machineCreate(const char* machineName)
{
char configIni[512];
Machine* machine;
int success;
FILE *file;
machine = (Machine *)malloc(sizeof(Machine));
if (machine == NULL)
return NULL;
machine->zipFile = NULL;
machine->isZipped = 0;
sprintf(configIni, "%s/%s/config.ini", machinesDir, machineName);
file = fopen(configIni, "rb");
if (file != NULL)
{
fclose(file);
}
else
{
// No config.ini. Is it compressed?
char zipFile[512];
sprintf(zipFile, "%s/%s.zip", machinesDir, machineName);
file = fopen(zipFile, "rb");
if (file == NULL)
{
machineDestroy(machine);
return NULL; // Not compressed and no config.ini
}
fclose(file);
machine->zipFile = (char *)calloc(strlen(zipFile) + 1, sizeof(char));
strcpy(machine->zipFile, zipFile);
machine->isZipped = 1;
}
success = readMachine(machine, machineName, configIni);
if (!success)
{
machineDestroy(machine);
return NULL;
}
machineUpdate(machine);
return machine;
}
void machineDestroy(Machine* machine)
{
if (machine->zipFile)
free(machine->zipFile);
free(machine);
}
int machineIsValid(const char* machineName, int checkRoms)
{
Machine* machine = machineCreate(machineName);
int i;
int success = 1;
if (machine == NULL) {
return 0;
}
if (checkRoms)
{
unzFile zippedMachine = 0;
#ifdef COCOAMSX
if ((machine->board.type & BOARD_MASK) != BOARD_MSX)
success = 0;
#endif
if (success)
{
if (machine->isZipped)
{
zippedMachine = unzOpen(machine->zipFile);
if (!zippedMachine)
success = 0;
}
if (success)
{
for (i = 0; i < machine->slotInfoCount; i++) {
if (strlen(machine->slotInfo[i].name) ||
strlen(machine->slotInfo[i].inZipName))
{
if (machine->isZipped)
{
#ifdef __APPLE__
int location = unzLocateFile(zippedMachine,
machine->slotInfo[i].inZipName, 2);
#else
int location = unzLocateFile(zippedMachine,
machine->slotInfo[i].inZipName, 0);
#endif
if (location == UNZ_END_OF_LIST_OF_FILE)
success = 0;
}
else
{
FILE* file = fopen(machine->slotInfo[i].name, "r");
if (file == NULL)
{
success = 0;
continue;
}
fclose(file);
}
}
}
}
if (zippedMachine)
unzClose(zippedMachine);
}
}
machineDestroy(machine);
return success;
}
void machineFillAvailable(ArrayList *list, int checkRoms)
{
const char* machineName = appConfigGetString("singlemachine", NULL);
const int maxNameLength = 512;
if (machineName != NULL) {
char filename[128];
FILE* file;
sprintf(filename, "%s/%s/config.ini", machinesDir, machineName);
file = fopen(filename, "rb");
if (file != NULL) {
if (machineIsValid(machineName, checkRoms)) {
char *name = (char *)calloc(512, sizeof(char));
strncpy(name, machineName, maxNameLength - 1);
arrayListAppend(list, name, 1);
}
fclose(file);
}
}
else {
char globPath[PROP_MAXPATH];
ArchGlob* glob;
int i;
sprintf(globPath, "%s/*", machinesDir);
glob = archGlob(globPath, ARCH_GLOB_DIRS);
if (glob == NULL)
return;
for (i = 0; i < glob->count; i++) {
char fileName[512];
FILE* file;
sprintf(fileName, "%s/config.ini", glob->pathVector[i]);
file = fopen(fileName, "rb");
if (file != NULL) {
const char* machineName = strrchr(glob->pathVector[i], '/');
if (machineName == NULL) {
machineName = strrchr(glob->pathVector[i], '\\');
}
if (machineName == NULL) {
machineName = glob->pathVector[i] - 1;
}
machineName++;
if (machineIsValid(machineName, checkRoms)) {
char *name = (char *)calloc(512, sizeof(char));
strncpy(name, machineName, maxNameLength - 1);
arrayListAppend(list, name, 1);
}
fclose(file);
}
}
archGlobFree(glob);
// Check ZIP sets
sprintf(globPath, "%s/*.zip", machinesDir);
glob = archGlob(globPath, ARCH_GLOB_FILES);
if (glob == NULL)
return;
for (i = 0; i < glob->count; i++) {
char buffer[512];
char *extension;
char *machineName;
strcpy(buffer, glob->pathVector[i]);
extension = strrchr(buffer, '.');
if (extension != NULL)
*extension = '\0';
machineName = strrchr(buffer, '/');
if (machineName == NULL) {
machineName = strrchr(buffer, '\\');
}
if (machineName == NULL) {
machineName = buffer - 1;
}
machineName++;
if (machineIsValid(machineName, checkRoms))
{
char *name = (char *)calloc(512, sizeof(char));
strncpy(name, machineName, maxNameLength - 1);
arrayListAppend(list, name, 1);
}
}
archGlobFree(glob);
}
}
void machineUpdate(Machine* machine)
{
int entry;
int i;
for (entry = 0; entry < machine->slotInfoCount; entry++) {
machine->slotInfo[entry].error = 0;
if (machine->slotInfo[entry].subslot && !machine->slot[machine->slotInfo[entry].slot].subslotted) {
machine->slotInfo[entry].error = 1;
}
if (machine->slotInfo[entry].pageCount > 0) {
for (i = 0; i < entry; i++) {
if (machine->slotInfo[i].slot == machine->slotInfo[entry].slot &&
machine->slotInfo[i].subslot == machine->slotInfo[entry].subslot &&
machine->slotInfo[i].pageCount > 0)
{
int tstStart = machine->slotInfo[entry].startPage;
int tstEnd = tstStart + machine->slotInfo[entry].pageCount;
int start = machine->slotInfo[i].startPage;
int end = start + machine->slotInfo[i].pageCount;
if (tstStart >= start && tstStart < end) {
machine->slotInfo[entry].error = 1;
}
if (tstEnd > start && tstEnd <= end) {
machine->slotInfo[entry].error = 1;
}
}
}
}
}
for (i = 0; i < machine->slotInfoCount; i++) {
for (entry = 0; entry < machine->slotInfoCount - 1; entry++) {
SlotInfo* si1 = &machine->slotInfo[entry];
SlotInfo* si2 = &machine->slotInfo[entry + 1];
int tst1 = (si1->slot << 24) + (si1->subslot << 20) +
(si1->startPage << 12) + si1->pageCount;
int tst2 = (si2->slot << 24) + (si2->subslot << 20) +
(si2->startPage << 12) + si2->pageCount;
if (tst2 < tst1) {
SlotInfo tmp;
memcpy(&tmp, si1, sizeof(SlotInfo));
memcpy(si1, si2, sizeof(SlotInfo));
memcpy(si2, &tmp, sizeof(SlotInfo));
}
}
}
// Check R800 and FDC enable
machine->cpu.hasR800 = 0;
machine->fdc.enabled = 0;
for (i = 0; i < machine->slotInfoCount; i++) {
machine->cpu.hasR800 |= machine->slotInfo[i].romType == ROM_S1990;
machine->fdc.enabled |= machine->slotInfo[i].romType == ROM_DISKPATCH ||
machine->slotInfo[i].romType == ROM_TC8566AF ||
machine->slotInfo[i].romType == ROM_TC8566AF_TR ||
machine->slotInfo[i].romType == ROM_MICROSOL ||
machine->slotInfo[i].romType == ROM_NATIONALFDC ||
machine->slotInfo[i].romType == ROM_PHILIPSFDC ||
machine->slotInfo[i].romType == ROM_SVI328FDC ||
machine->slotInfo[i].romType == ROM_SVI707FDC ||
machine->slotInfo[i].romType == ROM_SVI738FDC;
}
// Check VRAM size
if (machine->video.vdpVersion == VDP_V9938) {
if (machine->video.vramSize >= 128 * 1024) {
machine->video.vramSize = 128 * 1024;
}
else if (machine->video.vramSize >= 64 * 1024) {
machine->video.vramSize = 64 * 1024;
}
else if (machine->video.vramSize >= 32 * 1024) {
machine->video.vramSize = 32 * 1024;
}
else {
machine->video.vramSize = 16 * 1024;
}
}
else if (machine->video.vdpVersion == VDP_V9958) {
if (machine->video.vramSize >= 192 * 1024) {
machine->video.vramSize = 192 * 1024;
}
else {
machine->video.vramSize = 128 * 1024;
}
}
else {
machine->video.vramSize = 16 * 1024;
}
}
void machineLoadState(Machine* machine)
{
SaveState* state = saveStateOpenForRead("machine");
int hasR800 = 0;
int i;
saveStateGetBuffer(state, "name", machine->name, sizeof(machine->name));
machine->board.type = saveStateGet(state, "boardType", BOARD_MSX);
machine->slot[0].subslotted = saveStateGet(state, "subslotted00", 0);
machine->slot[1].subslotted = saveStateGet(state, "subslotted01", 0);
machine->slot[2].subslotted = saveStateGet(state, "subslotted02", 0);
machine->slot[3].subslotted = saveStateGet(state, "subslotted03", 0);
machine->cart[0].slot = saveStateGet(state, "cartSlot00", 0);
machine->cart[0].subslot = saveStateGet(state, "cartSubslot00", 0);
machine->cart[1].slot = saveStateGet(state, "cartSlot01", 0);
machine->cart[1].subslot = saveStateGet(state, "cartSubslot01", 0);
machine->video.vdpVersion = saveStateGet(state, "videoVersion", 0);
machine->video.vramSize = saveStateGet(state, "videoVramSize", 0x10000);
machine->cmos.enable = saveStateGet(state, "cmosEnable", 0);
machine->cmos.batteryBacked = saveStateGet(state, "cmosBatteryBacked", 0);
machine->audio.psgstereo = saveStateGet(state, "audioPsgStereo", 0);
for (i = 0; i < sizeof(machine->audio.psgpan) / sizeof(machine->audio.psgpan[0]); i++) {
char s[32];
sprintf(s, "audioPsgStereo%d", i);
machine->audio.psgpan[i] = saveStateGet(state, s, i == 0 ? 0 : i == 1 ? -1 : 1);
}
machine->fdc.count = saveStateGet(state, "fdcCount", 2);
machine->cpu.freqZ80 = saveStateGet(state, "cpuFreqZ80", 3579545);
machine->cpu.freqR800 = saveStateGet(state, "cpuFreqR800", 7159090);
machine->slotInfoCount = saveStateGet(state, "slotInfoCount", 0);
for (i = 0; i < sizeof(machine->slotInfo) / sizeof(machine->slotInfo[0]); i++) {
char tag[32];
sprintf(tag, "slotRomType%.2d", i);
machine->slotInfo[i].romType = saveStateGet(state, tag, 0);
hasR800 |= machine->slotInfo[i].romType == ROM_S1990;
sprintf(tag, "slot%.2d", i);
machine->slotInfo[i].slot = saveStateGet(state, tag, 0);
sprintf(tag, "subslot%.2d", i);
machine->slotInfo[i].subslot = saveStateGet(state, tag, 0);
sprintf(tag, "slotStartPage%.2d", i);
machine->slotInfo[i].startPage = saveStateGet(state, tag, 0);
sprintf(tag, "slotPageCount%.2d", i);
machine->slotInfo[i].pageCount = saveStateGet(state, tag, 0);
sprintf(tag, "slotError%.2d", i);
machine->slotInfo[i].error = saveStateGet(state, tag, 0);
sprintf(tag, "slotName%.2d", i);
saveStateGetBuffer(state, tag, machine->slotInfo[i].name, 512);
sprintf(tag, "slotInZipName%.2d", i);
saveStateGetBuffer(state, tag, machine->slotInfo[i].inZipName, 128);
}
machine->cpu.hasR800 = hasR800;
saveStateClose(state);
machineUpdate(machine);
}
void machineSaveState(Machine* machine)
{
SaveState* state = saveStateOpenForWrite("machine");
int i;
saveStateSetBuffer(state, "name", machine->name, sizeof(machine->name));
saveStateSet(state, "boardType", machine->board.type);
saveStateSet(state, "subslotted00", machine->slot[0].subslotted);
saveStateSet(state, "subslotted01", machine->slot[1].subslotted);
saveStateSet(state, "subslotted02", machine->slot[2].subslotted);
saveStateSet(state, "subslotted03", machine->slot[3].subslotted);
saveStateSet(state, "cartSlot00", machine->cart[0].slot);
saveStateSet(state, "cartSubslot00", machine->cart[0].subslot);
saveStateSet(state, "cartSlot01", machine->cart[1].slot);
saveStateSet(state, "cartSubslot01", machine->cart[1].subslot);
saveStateSet(state, "videoVersion", machine->video.vdpVersion);
saveStateSet(state, "videoVramSize", machine->video.vramSize);
saveStateSet(state, "cmosEnable", machine->cmos.enable);
saveStateSet(state, "cmosBatteryBacked", machine->cmos.batteryBacked);
saveStateSet(state, "audioPsgStereo", machine->audio.psgstereo);
for (i = 0; i < sizeof(machine->audio.psgpan) / sizeof(machine->audio.psgpan[0]); i++) {
char s[32];
sprintf(s, "audioPsgStereo%d", i);
saveStateSet(state, s, machine->audio.psgpan[i]);
}
saveStateSet(state, "fdcCount", machine->fdc.count);
saveStateSet(state, "cpuFreqZ80", machine->cpu.freqZ80);
saveStateSet(state, "cpuFreqR800", machine->cpu.freqR800);
saveStateSet(state, "slotInfoCount", machine->slotInfoCount);
for (i = 0; i < sizeof(machine->slotInfo) / sizeof(machine->slotInfo[0]); i++) {
char tag[32];
sprintf(tag, "slotRomType%.2d", i);
saveStateSet(state, tag, machine->slotInfo[i].romType);
sprintf(tag, "slot%.2d", i);
saveStateSet(state, tag, machine->slotInfo[i].slot);
sprintf(tag, "subslot%.2d", i);
saveStateSet(state, tag, machine->slotInfo[i].subslot);
sprintf(tag, "slotStartPage%.2d", i);
saveStateSet(state, tag, machine->slotInfo[i].startPage);
sprintf(tag, "slotPageCount%.2d", i);
saveStateSet(state, tag, machine->slotInfo[i].pageCount);
sprintf(tag, "slotError%.2d", i);
saveStateSet(state, tag, machine->slotInfo[i].error);
sprintf(tag, "slotName%.2d", i);
saveStateSetBuffer(state, tag, machine->slotInfo[i].name, 512);
sprintf(tag, "slotInZipName%.2d", i);
saveStateSetBuffer(state, tag, machine->slotInfo[i].inZipName, 128);
}
saveStateClose(state);
}
int machineInitialize(Machine* machine, UInt8** mainRam, UInt32* mainRamSize, UInt32* mainRamStart)
{
UInt8* ram = NULL;
UInt32 ramSize = 0;
UInt32 ramStart = 0;
UInt8* ram2 = NULL;
UInt32 ram2Size = 0;
UInt32 ram2Start = 0;
void* jisyoRom = NULL;
int jisyoRomSize = 0;
int success = 1;
int hdId = FIRST_INTERNAL_HD_INDEX;
UInt8* buf;
int size;
int i;
// Prioritize 1kB Mirrored ram as main ram (works good with coleco style
// systems with expansion ram but maybe main ram type should be an arg instead?).
for (i = 0; i < machine->slotInfoCount; i++) {
int slot;
int subslot;
int startPage;
char* romName;
// Don't map slots with error
if (machine->slotInfo[i].error) {
continue;
}
romName = strlen(machine->slotInfo[i].inZipName) ? machine->slotInfo[i].inZipName : machine->slotInfo[i].name;
slot = machine->slotInfo[i].slot;
subslot = machine->slotInfo[i].subslot;
startPage = machine->slotInfo[i].startPage;
size = 0x2000 * machine->slotInfo[i].pageCount;
if (machine->slotInfo[i].romType == RAM_1KB_MIRRORED) {
success &= ramMirroredCreate(size, slot, subslot, startPage, 0x400, &ram, &ramSize);
ramStart = startPage * 0x2000;
continue;
}
if (machine->slotInfo[i].romType == RAM_2KB_MIRRORED) {
success &= ramMirroredCreate(size, slot, subslot, startPage, 0x800, &ram, &ramSize);
ramStart = startPage * 0x2000;
continue;
}
}
/* Initialize RAM and 'imlicit' rom types */
for (i = 0; i < machine->slotInfoCount; i++) {
int slot;
int subslot;
int startPage;
char* romName;
// Don't map slots with error
if (machine->slotInfo[i].error) {
continue;
}
romName = strlen(machine->slotInfo[i].inZipName) ? machine->slotInfo[i].inZipName : machine->slotInfo[i].name;
slot = machine->slotInfo[i].slot;
subslot = machine->slotInfo[i].subslot;
startPage = machine->slotInfo[i].startPage;
size = 0x2000 * machine->slotInfo[i].pageCount;
if (machine->slotInfo[i].romType == RAM_NORMAL) {
if (ram == NULL && startPage == 0) {
success &= ramNormalCreate(size, slot, subslot, startPage, &ram, &ramSize);
ramStart = startPage * 0x2000;
}
else {
success &= ramNormalCreate(size, slot, subslot, startPage, &ram2, &ram2Size);
ram2Start = startPage * 0x2000;
}
continue;
}
if (machine->slotInfo[i].romType == RAM_MAPPER) {
if (ram == NULL && startPage == 0) {
success &= ramMapperCreate(size, slot, subslot, startPage, &ram, &ramSize);
}
else {
success &= ramMapperCreate(size, slot, subslot, startPage, NULL, NULL);
}
continue;
}
if (machine->slotInfo[i].romType == ROM_JISYO) {
if (jisyoRom == NULL) {
jisyoRom = romLoad(machine->slotInfo[i].name, machine->slotInfo[i].inZipName, &jisyoRomSize);
if (jisyoRom == NULL) {
success = 0;
continue;
}
}
continue;
}
}
if (ram == NULL) {
ram = ram2;
ramSize = ram2Size;
ramStart = ram2Start;
}
if (ram == NULL) {
return 0;
}
for (i = 0; i < machine->slotInfoCount; i++) {
int slot;
int subslot;
int startPage;
char* romName;
// Don't map slots with error
if (machine->slotInfo[i].error) {
continue;
}
romName = strlen(machine->slotInfo[i].inZipName) ? machine->slotInfo[i].inZipName : machine->slotInfo[i].name;
slot = machine->slotInfo[i].slot;
subslot = machine->slotInfo[i].subslot;
startPage = machine->slotInfo[i].startPage;
size = 0x2000 * machine->slotInfo[i].pageCount;
if (machine->slotInfo[i].romType == RAM_1KB_MIRRORED) {
continue;
}
if (machine->slotInfo[i].romType == RAM_2KB_MIRRORED) {
continue;
}
if (machine->slotInfo[i].romType == RAM_NORMAL) {
continue;
}
if (machine->slotInfo[i].romType == RAM_MAPPER) {
continue;
}
if (machine->slotInfo[i].romType == ROM_JISYO) {
continue;
}
if (machine->slotInfo[i].romType == ROM_SNATCHER) {
success &= romMapperSCCplusCreate(NULL, NULL, 0, slot, subslot, startPage, SCC_SNATCHER);
continue;
}
if (machine->slotInfo[i].romType == ROM_SDSNATCHER) {
success &= romMapperSCCplusCreate(NULL, NULL, 0, slot, subslot, startPage, SCC_SDSNATCHER);
continue;
}
if (machine->slotInfo[i].romType == ROM_SCCMIRRORED) {
success &= romMapperSCCplusCreate(NULL, NULL, 0, slot, subslot, startPage, SCC_MIRRORED);
continue;
}
if (machine->slotInfo[i].romType == ROM_SCCEXTENDED) {
success &= romMapperSCCplusCreate(NULL, NULL, 0, slot, subslot, startPage, SCC_EXTENDED);
continue;
}
if (machine->slotInfo[i].romType == ROM_PAC) {
success &= romMapperPACCreate("Pac.rom", NULL, 0, slot, subslot, startPage);
continue;
}
if (machine->slotInfo[i].romType == ROM_EXTRAM) {
success &= ramMapperCreate(size, slot, subslot, startPage, NULL, NULL);
continue;
}
if (machine->slotInfo[i].romType == ROM_MEGARAM) {
success &= romMapperMegaRAMCreate(size, slot, subslot, startPage);
continue;
}
if (machine->slotInfo[i].romType == SRAM_MATSUCHITA) {
success &= sramMapperMatsushitaCreate(0);
continue;
}
if (machine->slotInfo[i].romType == SRAM_MATSUCHITA_INV) {
success &= sramMapperMatsushitaCreate(1);
continue;
}
if (machine->slotInfo[i].romType == SRAM_S1985) {
success &= sramMapperS1985Create();
continue;
}
if (machine->slotInfo[i].romType == ROM_S1990) {
success &= romMapperS1990Create();
continue;
}
if (machine->slotInfo[i].romType == ROM_TURBORTIMER) {
success &= romMapperTurboRTimerCreate(0);
continue;
}
if (machine->slotInfo[i].romType == ROM_TURBORIO) {
success &= romMapperTurboRIOCreate();
continue;
}
if (machine->slotInfo[i].romType == ROM_F4DEVICE) {
success &= romMapperF4deviceCreate(0);
continue;
}
if (machine->slotInfo[i].romType == ROM_MSXMIDI) {
success &= MSXMidiCreate(0);
continue;
}
if (machine->slotInfo[i].romType == ROM_MSXMIDI_EXTERNAL) {
success &= MSXMidiCreate(1);
continue;
}
if (machine->slotInfo[i].romType == ROM_F4INVERTED) {
success &= romMapperF4deviceCreate(1);
continue;
}
if (machine->slotInfo[i].romType == ROM_NMS8280DIGI) {
success &= romMapperNms8280VideoDaCreate();
continue;
}
if (machine->slotInfo[i].romType == ROM_GIDE) {
success &= romMapperGIdeCreate(hdId++);
continue;
}
if (machine->slotInfo[i].romType == ROM_SONYHBI55) {
success &= romMapperSonyHBI55Create();
continue;
}
if (machine->slotInfo[i].romType == ROM_MSXAUDIODEV) {
success &= romMapperMsxAudioCreate(NULL, NULL, 0, 0, 0, 0);
continue;
}
if (machine->slotInfo[i].romType == ROM_JOYREXPSG) {
success &= romMapperJoyrexPsgCreate();
continue;
}
if (machine->slotInfo[i].romType == ROM_OPCODEPSG) {
success &= romMapperOpcodePsgCreate();
continue;
}
if (machine->slotInfo[i].romType == ROM_TURBORPCM) {
success &= romMapperTurboRPcmCreate();
continue;
}
if (machine->slotInfo[i].romType == ROM_MSXPRN) {
success &= romMapperMsxPrnCreate();
continue;
}
// --------- ColecoVision Super Expansion Module specific mappers
if (machine->slotInfo[i].romType == ROM_OPCODEMEGA) {
success &= romMapperOpcodeMegaRamCreate(slot, subslot, startPage);
continue;
}
if (machine->slotInfo[i].romType == ROM_OPCODESAVE) {
success &= romMapperOpcodeSaveRamCreate(slot, subslot, startPage);
continue;
}
if (machine->slotInfo[i].romType == ROM_OPCODESLOT) {
success &= romMapperOpcodeSlotManagerCreate();
continue;
}
// --------- SVI specific mappers
if (machine->slotInfo[i].romType == ROM_SVI328FDC) {
success &= svi328FdcCreate();
continue;
}
if (machine->slotInfo[i].romType == ROM_SVI328PRN) {
success &= romMapperSvi328PrnCreate();
continue;
}
if (machine->slotInfo[i].romType == ROM_SVI328RS232) {
success &= romMapperSvi328Rs232Create(SVI328_RS232);
continue;
}
if (machine->slotInfo[i].romType == ROM_SVI328RSIDE) {
success &= romMapperSvi328RsIdeCreate(hdId++);
continue;
}
// -------------------------------
// MEGA-SCSI etc
switch (machine->slotInfo[i].romType) {
case SRAM_MEGASCSI:
case SRAM_ESERAM:
case SRAM_WAVESCSI:
case SRAM_ESESCC:
buf = NULL;
if (strlen(romName)) {
buf = romLoad(machine->slotInfo[i].name, machine->slotInfo[i].inZipName, &size);
if (buf == NULL) {
success = 0;
continue;
}
}
{
int mode = strlen(machine->slotInfo[i].inZipName) ? 0x80 : 0;
if (machine->slotInfo[i].romType == SRAM_MEGASCSI ||
machine->slotInfo[i].romType == SRAM_WAVESCSI) {
mode++;
}
if (machine->slotInfo[i].romType == SRAM_WAVESCSI ||
machine->slotInfo[i].romType == SRAM_ESESCC) {
success &= sramMapperEseSCCCreate
(romName, buf, size, slot, subslot, startPage,
machine->slotInfo[i].romType == SRAM_WAVESCSI ? hdId++ : 0, mode);
} else {
success &= sramMapperMegaSCSICreate
(romName, buf, size, slot, subslot, startPage,
machine->slotInfo[i].romType == SRAM_MEGASCSI ? hdId++ : 0, mode);
}
if (buf) free(buf);
}
continue;
}
// -------------------------------
buf = romLoad(machine->slotInfo[i].name, machine->slotInfo[i].inZipName, &size);
if (buf == NULL) {
switch (machine->slotInfo[i].romType) {
case ROM_MEGAFLSHSCC:
success &= romMapperMegaFlashRomSccCreate("Manbow2.rom", NULL, 0, slot, subslot, startPage, 0, 0x80000, 0);
break;
default:
success = 0;
break;
}
continue;
}
switch (machine->slotInfo[i].romType) {
case ROM_0x4000:
success &= romMapperNormalCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_0xC000:
success &= romMapperNormalCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_BASIC:
success &= romMapperBasicCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_PLAIN:
success &= romMapperPlainCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_NETTOUYAKYUU:
success &= romMapperNettouYakyuuCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_MATRAINK:
success &= romMapperMatraINKCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_FORTEII:
success &= romMapperForteIICreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_FMDAS:
success &= romMapperFmDasCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_STANDARD:
success &= romMapperStandardCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_MSXDOS2:
success &= romMapperMsxDos2Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_MUPACK:
success &= romMapperMuPackCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KONAMI5:
success &= romMapperKonami5Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_MANBOW2:
if (size > 0x70000) size = 0x70000;
success &= romMapperMegaFlashRomSccCreate(romName, buf, size, slot, subslot, startPage, 0x7f, 0x80000, 0);
break;
case ROM_MANBOW2_V2:
success &= romMapperMegaFlashRomSccCreate(romName, buf, size, slot, subslot, startPage, 0x7f, 0x100000, 1);
break;
case ROM_HAMARAJANIGHT:
success &= romMapperMegaFlashRomSccCreate(romName, buf, size, slot, subslot, startPage, 0xcf, 0x100000, 1);
break;
case ROM_MEGAFLSHSCC:
success &= romMapperMegaFlashRomSccCreate(romName, buf, size, slot, subslot, startPage, 0, 0x80000, 0);
break;
case ROM_MEGAFLSHSCCPLUS:
success &= romMapperMegaFlashRomSccCreate(romName, buf, size, slot, subslot, startPage, 0, 0x100000, 1);
break;
case ROM_OBSONET:
success &= romMapperObsonetCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_NOWIND:
success &= romMapperNoWindCreate(hdId++, romName, buf, size, slot, subslot, startPage);
break;
case ROM_DUMAS:
{
char eepromName[512];
int eepromSize = 0;
UInt8* eepromData;
int j;
strcpy(eepromName, machine->slotInfo[i].name);
for (j = strlen(eepromName); j > 0 && eepromName[j] != '.'; j--);
eepromName[j] = 0;
strcat(eepromName, "_eeprom.rom");
eepromData = romLoad(eepromName, NULL, &eepromSize);
success &= romMapperDumasCreate(romName, buf, size, slot, subslot, startPage,
eepromData, eepromSize);
if (eepromData != NULL) {
free(eepromData);
}
}
break;
case ROM_MOONSOUND:
success &= romMapperMoonsoundCreate(romName, buf, size, 640);
buf = NULL; // Ownership transferred to emulation of moonsound
break;
case ROM_SCC:
success &= romMapperSCCplusCreate(romName, buf, size, slot, subslot, startPage, SCC_EXTENDED);
break;
case ROM_SCCPLUS:
success &= romMapperSCCplusCreate(romName, buf, size, slot, subslot, startPage, SCCP_EXTENDED);
break;
case ROM_KONAMI4:
success &= romMapperKonami4Create(romName, buf, size, slot, subslot, startPage);
break;
#ifdef WIN32
case ROM_GAMEREADER:
success &= romMapperGameReaderCreate(0, slot, subslot);
break;
#endif
case ROM_MAJUTSUSHI:
success &= romMapperMajutsushiCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_HOLYQURAN:
success &= romMapperHolyQuranCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KONAMISYNTH:
success &= romMapperKonamiSynthCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KONWORDPRO:
success &= romMapperKonamiWordProCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KONAMKBDMAS:
{
char voiceName[512];
int voiceSize = 0;
UInt8* voiceData;
int j;
strcpy(voiceName, machine->slotInfo[i].name);
for (j = strlen(voiceName); j > 0 && voiceName[j] != '.'; j--);
voiceName[j] = 0;
strcat(voiceName, "_voice.rom");
voiceData = romLoad(voiceName, NULL, &voiceSize);
success &= romMapperKonamiKeyboardMasterCreate(romName, buf, size,
slot, subslot, startPage,
voiceData, voiceSize);
if (voiceData != NULL) {
free(voiceData);
}
}
break;
case ROM_ASCII8:
success &= romMapperASCII8Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_ASCII16:
success &= romMapperASCII16Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_PANASONIC8:
success &= romMapperA1FMCreate(romName, buf, size, slot, subslot, startPage, 0x2000);
break;
case ROM_PANASONICWX16:
success &= romMapperPanasonicCreate(romName, buf, size, slot, subslot, startPage, 0x4000, 6);
break;
case ROM_PANASONIC16:
success &= romMapperPanasonicCreate(romName, buf, size, slot, subslot, startPage, 0x4000, 8);
break;
case ROM_PANASONIC32:
success &= romMapperPanasonicCreate(romName, buf, size, slot, subslot, startPage, 0x8000, 8);
break;
case ROM_FSA1FMMODEM:
success &= romMapperA1FMModemCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_ASCII8SRAM:
success &= romMapperASCII8sramCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_ASCII16SRAM:
success &= romMapperASCII16sramCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_MSXAUDIO:
success &= romMapperMsxAudioCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_YAMAHASFG01:
success &= romMapperSfg05Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_YAMAHASFG05:
success &= romMapperSfg05Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_YAMAHANET:
success &= romMapperNetCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_SF7000IPL:
success &= romMapperSf7000IplCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KOEI:
success &= romMapperKoeiCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_NATIONAL:
success &= romMapperNationalCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KONAMI4NF:
success &= romMapperKonami4nfCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_ASCII16NF:
success &= romMapperASCII16nfCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_GAMEMASTER2:
success &= romMapperGameMaster2Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_HARRYFOX:
success &= romMapperHarryFoxCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_HALNOTE:
success &= romMapperHalnoteCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_RTYPE:
success &= romMapperRTypeCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_CROSSBLAIM:
success &= romMapperCrossBlaimCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_LODERUNNER:
success &= romMapperLodeRunnerCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KOREAN80:
success &= romMapperKorean80Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KOREAN90:
success &= romMapperKorean90Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KOREAN126:
success &= romMapperKorean126Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_FMPAK:
success &= romMapperFMPAKCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_FMPAC:
success &= romMapperFMPACCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_MSXMUSIC:
success &= romMapperMsxMusicCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_NORMAL:
success &= romMapperNormalCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_DRAM:
success &= romMapperDramCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_SG1000:
case ROM_SC3000:
success &= romMapperSg1000Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_SG1000_RAMEXPANDER_A:
success &= romMapperSg1000RamExpanderCreate(romName, buf, size, slot, subslot, startPage, ROM_SG1000_RAMEXPANDER_A);
break;
case ROM_SG1000_RAMEXPANDER_B:
success &= romMapperSg1000RamExpanderCreate(romName, buf, size, slot, subslot, startPage, ROM_SG1000_RAMEXPANDER_B);
break;
case ROM_SG1000CASTLE:
success &= romMapperSg1000CastleCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_SEGABASIC:
success &= romMapperSegaBasicCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_CASPATCH:
success &= romMapperCasetteCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_DISKPATCH:
success &= romMapperDiskCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_TC8566AF:
success &= romMapperTC8566AFCreate(romName, buf, size, slot, subslot, startPage, ROM_TC8566AF);
break;
case ROM_TC8566AF_TR:
success &= romMapperTC8566AFCreate(romName, buf, size, slot, subslot, startPage, ROM_TC8566AF_TR);
break;
case ROM_MICROSOL:
success &= romMapperMicrosolCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_ARC:
success &= romMapperArcCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_NATIONALFDC:
success &= romMapperNationalFdcCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_PHILIPSFDC:
success &= romMapperPhilipsFdcCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_SVI707FDC:
success &= romMapperSvi707FdcCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_SVI738FDC:
success &= romMapperSvi738FdcCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_KANJI:
success &= romMapperKanjiCreate(buf, size);
break;
case ROM_KANJI12:
success &= romMapperKanji12Create(buf, size);
break;
case ROM_BUNSETU:
success &= romMapperBunsetuCreate(romName, buf, size, slot, subslot, startPage, jisyoRom, jisyoRomSize);
break;
case ROM_SUNRISEIDE:
success &= romMapperSunriseIdeCreate(hdId++, romName, buf, size, slot, subslot, startPage);
break;
case ROM_BEERIDE:
success &= romMapperBeerIdeCreate(hdId++, romName, buf, size, slot, subslot, startPage);
break;
case ROM_GOUDASCSI:
success &= romMapperGoudaSCSICreate(hdId++, romName, buf, size, slot, subslot, startPage);
break;
case ROM_SONYHBIV1:
success &= romMapperSonyHbiV1Create(romName, buf, size, slot, subslot, startPage);
break;
case ROM_PLAYBALL:
success &= romMapperPlayBallCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_DOOLY:
success &= romMapperDoolyCreate(romName, buf, size, slot, subslot, startPage);
case ROM_OPCODEBIOS:
success &= romMapperOpcodeBiosCreate(romName, buf, size, slot, subslot, startPage);
break;
case ROM_MICROSOL80:
{
char charName[512];
int charSize = 0;
UInt8* charData;
int j;
strcpy(charName, machine->slotInfo[i].name);
for (j = strlen(charName); j > 0 && charName[j] != '.'; j--);
charName[j] = 0;
strcat(charName, "_char.rom");
charData = romLoad(charName, NULL, &charSize);
success &= romMapperMicrosolVmx80Create(romName, buf, size,
slot, subslot, startPage,
charData, charSize);
if (charData != NULL) {
free(charData);
}
}
break;
case ROM_SVI727COL80:
success &= romMapperSvi727Col80Create(romName, buf, size, slot, subslot, startPage);
break;
}
if( buf != NULL ) {
free(buf);
}
}
if (jisyoRom != NULL) {
free(jisyoRom);
}
if (mainRam != NULL) {
*mainRam = ram;
}
if (mainRamSize != NULL) {
*mainRamSize = ramSize;
}
if (mainRamStart != NULL) {
*mainRamStart = ramStart;
}
return success;
}
void machineSetDirectory(const char* dir)
{
strcpy(machinesDir, dir);
}