38 Commits

Author SHA1 Message Date
clobber 8e4ee19963 Bump version 2023-06-21 22:28:36 -06:00
clobber fc7c85f773 Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/4bb149ba0b798294fbfc51de31a97af08c018542 2023-06-20 21:29:58 -06:00
clobber 171f2425a5 Merge pull request #9 from ShutOstrich/master
Sync with upstream ekeeke/Genesis-Plus-GX@1db51e2
2023-04-29 20:42:37 -06:00
ShutOstrich d7d25b7b60 Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/1db51e2c5fb29fb1305683705e8f007a18341d97 2023-04-30 00:32:22 +02:00
clobber 86a6ea8f0e Update Multitaps and Six Button Controller override database 2022-12-28 01:16:37 -07:00
clobber d661a9fb57 SG/MD/SCD/MCD: Fix EA 4-Way Play 2022-12-28 01:15:20 -07:00
clobber 01cfb4aa37 Cleanup 2022-12-28 01:12:53 -07:00
clobber 0c30f64676 Fix -ringBufferAtIndex: deprecation warning. 2022-12-24 17:10:51 -07:00
clobber 692374aa07 Bump version for sparkle updater 2022-12-23 10:52:24 -07:00
clobber 36de3d745f Fix comparison warning.
warning: bitwise comparison always evaluates to false [-Wtautological-compare]
2022-12-22 22:23:39 -07:00
clobber 3f33e549a5 Fix some problems with Genesis cheat support. 2022-12-22 22:02:02 -07:00
clobber fd3846df6e Fix indentation. 2022-12-21 21:18:45 -07:00
clobber 188663033a Sync with the latest cheat code support. 2022-12-21 19:39:22 -07:00
clobber c1a7cda4fb Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/350be7731ccb8767b9abdb5ba567a899bc66e05f 2022-12-19 16:19:10 -07:00
clobber 3ebf7e57eb Bump version for sparkle updater 2021-09-17 00:27:33 -06:00
clobber 576e14d64c Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/35ed78cc71f6b2c69b1377c9520416d0253b6633 2021-09-17 00:24:44 -06:00
C.W. Betts 95b9099b3e Change crc32 to be/take unsigned int instead of unsigned long.
This'll make crc_table smaller.
2020-10-19 17:05:00 -06:00
C.W. Betts 90c519eb1e Poke the plists: get the development language from Xcode build. 2020-10-01 01:51:37 -06:00
C.W. Betts 779baa7fca Fix locations of the system plugin headers.
Minor Xcode maintenance.
2020-10-01 01:26:41 -06:00
C.W. Betts 4f13fea4e2 Fix Xcode 12 build failure. 2020-09-22 14:13:55 -06:00
clobber 17f423cfbd Bump version for sparkle updater 2020-08-28 15:10:36 -05:00
clobber 975a3e3266 Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/f8a8046948aedc9d96ad81b3894c55d914dbef0f 2020-08-28 15:10:11 -05:00
clobber 17788c3ddd Bump version for sparkle updater 2020-08-19 14:47:23 -05:00
clobber 15af996d79 Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/15722b16ab5a539b14dba024bb008b5c6f22c202 2020-08-19 14:46:59 -05:00
C.W. Betts 2c0279c0ac Update language resources.
This quiets warnings in newer Xcode releases.

Also update framework locations.
2020-01-08 01:15:51 -07:00
clobber 6863200707 Bump version for sparkle updater 2019-10-23 11:44:33 -05:00
clobber 35889724f4 Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/5b1271e4770412f47a6170b8f925905a9f46e5ef 2019-10-23 11:44:03 -05:00
clobber 41577e1fa5 Fix typo. 2019-10-21 11:09:07 -05:00
clobber 02499a735b Bump version for sparkle updater 2018-11-26 23:18:38 -06:00
clobber 2875815a60 GG: Add display mode change support 2018-11-26 23:17:54 -06:00
clobber f1828430d3 Cleanup 2018-11-26 21:10:10 -06:00
clobber 682625653b Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/2ab02c8122d5127fe4a884ed8b65a3c767c90fb9 2018-11-26 18:54:25 -06:00
clobber 38c438243e Bump version for sparkle updater 2018-09-17 16:14:52 -05:00
clobber 25933fefad Sync with upstream https://github.com/ekeeke/Genesis-Plus-GX/commit/a4255fafc2f649faca84126ebab1c5cb99fc5df3 2018-09-17 16:13:37 -05:00
clobber 20a3b05782 Cleanup 2018-09-17 16:12:32 -05:00
clobber c5df0565e6 Bump version for sparkle updater 2018-03-18 14:28:39 -05:00
clobber c06e10d458 SG/MD/SCD/MCD: Fix PAR 2018-03-18 14:28:11 -05:00
clobber 0419c81f9e Sync with https://github.com/ekeeke/Genesis-Plus-GX/commit/726b7112d806ae23694b2a1634d8d866c87c4864 2018-03-18 13:43:08 -05:00
93 changed files with 7501 additions and 2417 deletions
Binary file not shown.
+459 -271
View File
File diff suppressed because it is too large Load Diff
+22 -13
View File
@@ -36,6 +36,7 @@
/* Begin PBXBuildFile section */
82287C39101E9DB40072172D /* GenPlusGameCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 82287C34101E9DB40072172D /* GenPlusGameCore.m */; };
87709EF32950DA090084AEE0 /* megasd.c in Sources */ = {isa = PBXBuildFile; fileRef = 87709EF22950DA090084AEE0 /* megasd.c */; };
879243AE1C0D044B0064C515 /* xe_1ap.c in Sources */ = {isa = PBXBuildFile; fileRef = 879243AC1C0D044B0064C515 /* xe_1ap.c */; };
879243B11C0D05120064C515 /* graphic_board.c in Sources */ = {isa = PBXBuildFile; fileRef = 879243AF1C0D05120064C515 /* graphic_board.c */; };
87E0514D1B18092700E870E1 /* scrc32.c in Sources */ = {isa = PBXBuildFile; fileRef = 87E0514B1B18092700E870E1 /* scrc32.c */; };
@@ -126,21 +127,23 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
089C167EFE841241C02AAC07 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
82287C08101E9C2C0072172D /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
82287C33101E9DB40072172D /* GenPlusGameCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenPlusGameCore.h; sourceTree = "<group>"; };
82287C34101E9DB40072172D /* GenPlusGameCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GenPlusGameCore.m; sourceTree = "<group>"; };
825C7E44101FAB7F0072187B /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
87709EF12950DA080084AEE0 /* megasd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = megasd.h; sourceTree = "<group>"; };
87709EF22950DA090084AEE0 /* megasd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = megasd.c; sourceTree = "<group>"; };
879243AC1C0D044B0064C515 /* xe_1ap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xe_1ap.c; sourceTree = "<group>"; };
879243AD1C0D044B0064C515 /* xe_1ap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xe_1ap.h; sourceTree = "<group>"; };
879243AF1C0D05120064C515 /* graphic_board.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = graphic_board.c; sourceTree = "<group>"; };
879243B01C0D05120064C515 /* graphic_board.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graphic_board.h; sourceTree = "<group>"; };
87D7BFC01F9841EE000B38DE /* OESMSSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESMSSystemResponderClient.h; path = ../OpenEmu/SegaMasterSystem/OESMSSystemResponderClient.h; sourceTree = "<group>"; };
87D7BFC11F9841F8000B38DE /* OEGGSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OEGGSystemResponderClient.h; path = ../OpenEmu/GameGear/OEGGSystemResponderClient.h; sourceTree = "<group>"; };
87D7BFC21F984206000B38DE /* OESG1000SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESG1000SystemResponderClient.h; path = "../OpenEmu/SG-1000/OESG1000SystemResponderClient.h"; sourceTree = "<group>"; };
87D7BFC01F9841EE000B38DE /* OESMSSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESMSSystemResponderClient.h; path = ../OpenEmu/SystemPlugins/SegaMasterSystem/OESMSSystemResponderClient.h; sourceTree = "<group>"; };
87D7BFC11F9841F8000B38DE /* OEGGSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OEGGSystemResponderClient.h; path = ../OpenEmu/SystemPlugins/GameGear/OEGGSystemResponderClient.h; sourceTree = "<group>"; };
87D7BFC21F984206000B38DE /* OESG1000SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESG1000SystemResponderClient.h; path = "../OpenEmu/SystemPlugins/SG-1000/OESG1000SystemResponderClient.h"; sourceTree = "<group>"; };
87E0514A1B18092700E870E1 /* osd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = osd.h; sourceTree = "<group>"; };
87E0514B1B18092700E870E1 /* scrc32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scrc32.c; sourceTree = "<group>"; };
87E0514C1B18092700E870E1 /* scrc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scrc32.h; sourceTree = "<group>"; };
@@ -156,7 +159,7 @@
941FF4F8162A4BAE005A9427 /* eeprom_spi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eeprom_spi.h; sourceTree = "<group>"; };
941FF4FC162A4BE1005A9427 /* blip_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blip_buf.c; sourceTree = "<group>"; };
941FF4FD162A4BE1005A9427 /* blip_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blip_buf.h; sourceTree = "<group>"; };
946C18AE17148D5200C64BF9 /* OESegaCDSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESegaCDSystemResponderClient.h; path = "../OpenEmu/Sega CD/OESegaCDSystemResponderClient.h"; sourceTree = "<group>"; };
946C18AE17148D5200C64BF9 /* OESegaCDSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESegaCDSystemResponderClient.h; path = "../OpenEmu/SystemPlugins/Sega CD/OESegaCDSystemResponderClient.h"; sourceTree = "<group>"; };
948DA2A115AB906400C0EA78 /* cd_cart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cd_cart.c; sourceTree = "<group>"; };
948DA2A215AB906400C0EA78 /* cd_cart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cd_cart.h; sourceTree = "<group>"; };
948DA2A315AB906400C0EA78 /* cdc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cdc.c; sourceTree = "<group>"; };
@@ -256,9 +259,9 @@
94ED8A8514CF933700FF8901 /* osd_cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = osd_cpu.h; sourceTree = "<group>"; };
94ED8A8614CF933700FF8901 /* z80.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = z80.c; sourceTree = "<group>"; };
94ED8A8714CF933700FF8901 /* z80.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = z80.h; sourceTree = "<group>"; };
C6B948191365164700A425F0 /* OEGenesisSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OEGenesisSystemResponderClient.h; path = ../OpenEmu/Genesis/OEGenesisSystemResponderClient.h; sourceTree = "<group>"; };
C6B948191365164700A425F0 /* OEGenesisSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OEGenesisSystemResponderClient.h; path = ../OpenEmu/SystemPlugins/Genesis/OEGenesisSystemResponderClient.h; sourceTree = "<group>"; };
C6D120F1171130E700E868A8 /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OpenEmuBase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -431,6 +434,8 @@
94ED896F14CF933600FF8901 /* ggenie.h */,
94ED897014CF933600FF8901 /* md_cart.c */,
94ED897114CF933600FF8901 /* md_cart.h */,
87709EF22950DA090084AEE0 /* megasd.c */,
87709EF12950DA080084AEE0 /* megasd.h */,
94ED897214CF933600FF8901 /* sms_cart.c */,
94ED897314CF933600FF8901 /* sms_cart.h */,
94ED897414CF933600FF8901 /* sram.c */,
@@ -570,12 +575,11 @@
089C1669FE841209C02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 0700;
};
buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "GenesisPlus" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 1;
knownRegions = (
en,
@@ -674,6 +678,7 @@
94ED8B2914CF933800FF8901 /* membnk.c in Sources */,
94ED8B2A14CF933800FF8901 /* memz80.c in Sources */,
94ED8B3714CF933800FF8901 /* state.c in Sources */,
87709EF32950DA090084AEE0 /* megasd.c in Sources */,
94ED8B3814CF933800FF8901 /* system.c in Sources */,
87E0514D1B18092700E870E1 /* scrc32.c in Sources */,
94ED8B4D14CF933800FF8901 /* vdp_ctrl.c in Sources */,
@@ -714,7 +719,7 @@
089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C167EFE841241C02AAC07 /* English */,
089C167EFE841241C02AAC07 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
@@ -734,6 +739,8 @@
OTHER_CFLAGS = (
"-DLSB_FIRST",
"-DUSE_32BPP_RENDERING",
"-DMAXROMSIZE=33554432",
"-DENABLE_SUB_68K_ADDRESS_ERROR_EXCEPTIONS",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
PRODUCT_NAME = GenesisPlus;
@@ -754,6 +761,8 @@
OTHER_CFLAGS = (
"-DLSB_FIRST",
"-DUSE_32BPP_RENDERING",
"-DMAXROMSIZE=33554432",
"-DENABLE_SUB_68K_ADDRESS_ERROR_EXCEPTIONS",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
PRODUCT_NAME = GenesisPlus;
+5 -3
View File
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
@@ -19,7 +19,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.7.4.7</string>
<string>1.7.5</string>
<key>NSPrincipalClass</key>
<string>OEGameCoreController</string>
<key>OEGameCoreClass</key>
@@ -34,6 +34,8 @@
<integer>0</integer>
<key>OEGameCoreSupportsCheatCode</key>
<true/>
<key>OEGameCoreSupportsDisplayModeChange</key>
<true/>
<key>OEGameCoreSupportsRewinding</key>
<true/>
</dict>
@@ -120,7 +122,7 @@
<key>OEGameCorePlayerCount</key>
<string>8</string>
<key>OEProjectURL</key>
<string>http://code.google.com/p/genplus-gx</string>
<string>https://github.com/ekeeke/Genesis-Plus-GX</string>
<key>OESystemIdentifiers</key>
<array>
<string>openemu.system.sg1000</string>
+2
View File
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
+38 -58
View File
@@ -1,8 +1,8 @@
/****************************************************************************
* Genesis Plus
* Action Replay / Pro Action Replay emulation
* Action Replay / Pro Action Replay hardware support
*
* Copyright (C) 2009-2014 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -45,8 +45,7 @@ static struct
{
uint8 enabled;
uint8 status;
uint8 *rom;
uint8 *ram;
uint8 ram[0x10000];
uint16 regs[13];
uint16 old[4];
uint16 data[4];
@@ -54,64 +53,52 @@ static struct
} action_replay;
static void ar_write_regs(uint32 address, uint32 data);
static void ar_write_regs_2(uint32 address, uint32 data);
static void ar2_write_reg(uint32 address, uint32 data);
static void ar_write_ram_8(uint32 address, uint32 data);
void areplay_init(void)
{
int size;
memset(&action_replay,0,sizeof(action_replay));
action_replay.enabled = action_replay.status = 0;
/* store Action replay ROM (max. 128k) & RAM (64k) above cartridge ROM + SRAM area */
if (cart.romsize > 0x810000) return;
action_replay.rom = cart.rom + 0x810000;
action_replay.ram = cart.rom + 0x830000;
/* try to load Action Replay ROM file */
size = load_archive(AR_ROM, action_replay.rom, 0x20000, NULL);
/* detect Action Replay board type */
switch (size)
/* try to load Action Replay ROM file (max. 64KB) */
if (load_archive(AR_ROM, cart.lockrom, 0x10000, NULL) > 0)
{
case 0x8000:
/* detect Action Replay board type */
if (!memcmp(cart.lockrom + 0x120, "ACTION REPLAY ", 16))
{
if (!memcmp(action_replay.rom + 0x120, "ACTION REPLAY ", 16))
{
/* normal Action Replay (32K) */
action_replay.enabled = TYPE_AR;
/* internal registers mapped at $010000-$01ffff */
m68k.memory_map[0x01].write16 = ar_write_regs;
break;
}
}
/* normal Action Replay (32KB ROM) */
action_replay.enabled = TYPE_AR;
case 0x10000:
case 0x20000:
/* $0000-$7fff mirrored into $8000-$ffff */
memcpy(cart.lockrom + 0x8000, cart.lockrom, 0x8000);
/* internal registers mapped at $010000-$01ffff */
m68k.memory_map[0x01].write16 = ar_write_regs;
}
else
{
/* Read stack pointer MSB */
uint8 sp = READ_BYTE(action_replay.rom, 0x01);
uint8 sp = cart.lockrom[0x01];
/* Detect board version */
if ((sp == 0x42) && !memcmp(action_replay.rom + 0x120, "ACTION REPLAY 2 ", 16))
if ((sp == 0x42) && !memcmp(cart.lockrom + 0x120, "ACTION REPLAY 2 ", 16))
{
/* PRO Action Replay 1 (64/128K) */
/* PRO Action Replay (2x32KB ROM) */
action_replay.enabled = TYPE_PRO1;
/* internal registers mapped at $010000-$01ffff */
m68k.memory_map[0x01].write16 = ar_write_regs;
}
else if ((sp == 0x60) && !memcmp(action_replay.rom + 0x3c6, "ACTION REPLAY II", 16))
else if ((sp == 0x60) && !memcmp(cart.lockrom + 0x3c6, "ACTION REPLAY II", 16))
{
/* PRO Action Replay 2 (64K) */
/* PRO Action Replay 2 (2x32KB ROM) */
action_replay.enabled = TYPE_PRO2;
/* internal registers mapped at $100000-$10ffff */
m68k.memory_map[0x10].write16 = ar_write_regs_2;
/* internal register mapped at $100000-$10ffff */
m68k.memory_map[0x10].write16 = ar2_write_reg;
}
/* internal RAM (64k), mapped at $420000-$42ffff or $600000-$60ffff */
/* internal RAM (64KB), mapped at $420000-$42ffff or $600000-$60ffff */
if (action_replay.enabled)
{
m68k.memory_map[sp].base = action_replay.ram;
@@ -120,28 +107,22 @@ void areplay_init(void)
m68k.memory_map[sp].write8 = ar_write_ram_8;
m68k.memory_map[sp].write16 = NULL;
}
break;
}
default:
{
break;
}
}
#ifdef LSB_FIRST
if (action_replay.enabled)
{
int i;
for (i= 0; i<size; i+=2)
if (action_replay.enabled)
{
/* Byteswap ROM */
uint8 temp = action_replay.rom[i];
action_replay.rom[i] = action_replay.rom[i+1];
action_replay.rom[i+1] = temp;
int i;
for (i= 0; i<0x10000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.lockrom[i];
cart.lockrom[i] = cart.lockrom[i+1];
cart.lockrom[i+1] = temp;
}
}
}
#endif
}
}
void areplay_shutdown(void)
@@ -166,7 +147,7 @@ void areplay_reset(int hard)
memset(action_replay.addr, 0, sizeof(action_replay.addr));
/* by default, internal ROM is mapped at $000000-$00FFFF */
m68k.memory_map[0].base = action_replay.rom;
m68k.memory_map[0].base = cart.lockrom;
/* reset internal RAM on power-on */
if (hard)
@@ -287,7 +268,7 @@ static void ar_write_regs(uint32 address, uint32 data)
}
}
static void ar_write_regs_2(uint32 address, uint32 data)
static void ar2_write_reg(uint32 address, uint32 data)
{
/* enable Cartridge ROM */
if (((address & 0xff) == 0x78) && (data == 0xffff))
@@ -301,4 +282,3 @@ static void ar_write_ram_8(uint32 address, uint32 data)
/* byte writes are handled as word writes, with LSB duplicated in MSB (/LWR is not used) */
*(uint16 *)(action_replay.ram + (address & 0xfffe)) = (data | (data << 8));
}
+2 -2
View File
@@ -1,8 +1,8 @@
/****************************************************************************
* Genesis Plus
* DATEL Action Replay / Pro Action Replay emulation
* Action Replay / Pro Action Replay hardware support
*
* Copyright (C) 2009-2014 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+1 -1
View File
@@ -47,7 +47,7 @@
T_EEPROM_93C eeprom_93c;
void eeprom_93c_init()
void eeprom_93c_init(void)
{
/* default eeprom state */
memset(&eeprom_93c, 0, sizeof(T_EEPROM_93C));
+1 -1
View File
@@ -65,7 +65,7 @@ typedef struct
extern T_EEPROM_93C eeprom_93c;
/* Function prototypes */
extern void eeprom_93c_init();
extern void eeprom_93c_init(void);
extern void eeprom_93c_write(unsigned char data);
extern unsigned char eeprom_93c_read(void);
+3 -3
View File
@@ -179,7 +179,7 @@ static struct
/* I2C EEPROM mapper initialization */
/********************************************************************/
void eeprom_i2c_init()
void eeprom_i2c_init(void)
{
int i = sizeof(i2c_database) / sizeof(T_I2C_GAME) - 1;
@@ -246,7 +246,7 @@ void eeprom_i2c_init()
/* I2C EEPROM internal */
/********************************************************************/
INLINE void Detect_START()
INLINE void Detect_START(void)
{
/* detect SDA HIGH to LOW transition while SCL is held HIGH */
if (eeprom_i2c.old_scl && eeprom_i2c.scl)
@@ -273,7 +273,7 @@ INLINE void Detect_START()
}
}
INLINE void Detect_STOP()
INLINE void Detect_STOP(void)
{
/* detect SDA LOW to HIGH transition while SCL is held HIGH */
if (eeprom_i2c.old_scl && eeprom_i2c.scl)
+1 -1
View File
@@ -40,6 +40,6 @@
#define _EEPROM_I2C_H_
/* Function prototypes */
extern void eeprom_i2c_init();
extern void eeprom_i2c_init(void);
#endif
+1 -1
View File
@@ -72,7 +72,7 @@ typedef struct
static T_EEPROM_SPI spi_eeprom;
void eeprom_spi_init()
void eeprom_spi_init(void)
{
/* reset eeprom state */
memset(&spi_eeprom, 0, sizeof(T_EEPROM_SPI));
+1 -1
View File
@@ -40,7 +40,7 @@
#define _EEPROM_SPI_H_
/* Function prototypes */
extern void eeprom_spi_init();
extern void eeprom_spi_init(void);
extern void eeprom_spi_write(unsigned char data);
extern unsigned int eeprom_spi_read(unsigned int address);
+12 -17
View File
@@ -1,8 +1,8 @@
/****************************************************************************
* Genesis Plus
* Game Genie Hardware emulation
* Game Genie hardware support
*
* Copyright (C) 2009-2014 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*
* Based on documentation from Charles McDonald
* (http://cgfm2.emuviews.com/txt/genie.txt)
@@ -44,7 +44,6 @@
static struct
{
uint8 enabled;
uint8 *rom;
uint16 regs[0x20];
uint16 old[6];
uint16 data[6];
@@ -58,29 +57,25 @@ static void ggenie_write_word(unsigned int address, unsigned int data);
static void ggenie_write_regs(unsigned int offset, unsigned int data);
void ggenie_init(void)
{
memset(&ggenie,0,sizeof(ggenie));
{
ggenie.enabled = 0;
/* Store Game Genie ROM (32k) above cartridge ROM + SRAM area */
if (cart.romsize > 0x810000) return;
ggenie.rom = cart.rom + 0x810000;
/* Try to load Game Genie ROM file */
if (load_archive(GG_ROM, ggenie.rom, 0x8000, NULL) > 0)
/* Try to load Game Genie ROM file (32KB) */
if (load_archive(GG_ROM, cart.lockrom, 0x8000, NULL) > 0)
{
#ifdef LSB_FIRST
int i;
for (i=0; i<0x8000; i+=2)
{
/* Byteswap ROM */
uint8 temp = ggenie.rom[i];
ggenie.rom[i] = ggenie.rom[i+1];
ggenie.rom[i+1] = temp;
uint8 temp = cart.lockrom[i];
cart.lockrom[i] = cart.lockrom[i+1];
cart.lockrom[i+1] = temp;
}
#endif
/* $0000-$7fff mirrored into $8000-$ffff */
memcpy(ggenie.rom + 0x8000, ggenie.rom, 0x8000);
memcpy(cart.lockrom + 0x8000, cart.lockrom, 0x8000);
/* Game Genie hardware is enabled */
ggenie.enabled = 1;
@@ -113,7 +108,7 @@ void ggenie_reset(int hard)
}
/* Game Genie ROM is mapped at $000000-$007fff */
m68k.memory_map[0].base = ggenie.rom;
m68k.memory_map[0].base = cart.lockrom;
/* Internal registers are mapped at $000000-$00001f */
m68k.memory_map[0].write8 = ggenie_write_byte;
@@ -214,7 +209,7 @@ static void ggenie_write_regs(unsigned int offset, unsigned int data)
else
{
/* $0000-$7ffff reads mapped to Game Genie ROM */
m68k.memory_map[0].base = ggenie.rom;
m68k.memory_map[0].base = cart.lockrom;
m68k.memory_map[0].read8 = NULL;
m68k.memory_map[0].read16 = NULL;
+2 -2
View File
@@ -1,8 +1,8 @@
/****************************************************************************
* Genesis Plus
* Game Genie Hardware emulation
* Game Genie hardware support
*
* Copyright (C) 2009-2014 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*
* Based on documentation from Charles McDonald
* (http://cgfm2.emuviews.com/txt/genie.txt)
+526 -150
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Mega Drive cartridge hardware support
*
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
*
* Many cartridge protections were initially documented by Haze
* (http://haze.mameworld.info/)
@@ -44,6 +44,7 @@
#include "shared.h"
#include "eeprom_i2c.h"
#include "eeprom_spi.h"
#include "megasd.h"
/* Cart database entry */
typedef struct
@@ -70,11 +71,17 @@ static uint32 mapper_flashkit_r(uint32 address);
static uint32 mapper_smw_64_r(uint32 address);
static void mapper_smw_64_w(uint32 address, uint32 data);
static void mapper_realtec_w(uint32 address, uint32 data);
static uint32 mapper_realtec_r(uint32 address);
static void mapper_seganet_w(uint32 address, uint32 data);
static void mapper_32k_w(uint32 data);
static void mapper_64k_w(uint32 data);
static void mapper_64k_multi_w(uint32 address);
static uint32 mapper_radica_r(uint32 address);
static uint32 mapper_128k_multi_r(uint32 address);
static void mapper_256k_multi_w(uint32 address, uint32 data);
static void mapper_wd1601_w(uint32 address, uint32 data);
static uint32 mapper_64k_radica_r(uint32 address);
static uint32 mapper_128k_radica_r(uint32 address);
static void mapper_sr16v1_w(uint32 address, uint32 data);
static void default_time_w(uint32 address, uint32 data);
static void default_regs_w(uint32 address, uint32 data);
static uint32 default_regs_r(uint32 address);
@@ -102,13 +109,26 @@ static const md_entry_t rom_database[] =
/* Tom Clown */
{0x0000,0xc0cd,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,0,NULL,NULL,NULL,mapper_realtec_w}},
/* 1800-in-1 */
{0x3296,0x2370,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,mapper_128k_multi_r,m68k_unused_8_w,NULL,NULL}},
/* Golden Mega 250-in-1 */
{0xe43c,0x886f,0x08,0x08,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,NULL,m68k_unused_8_w,NULL,mapper_256k_multi_w}},
/* RADICA (Volume 1) (bad dump ?) */
{0x0000,0x2326,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,mapper_radica_r,NULL,NULL,NULL}},
{0x0000,0x2326,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,mapper_64k_radica_r,m68k_unused_8_w,NULL,NULL}},
/* RADICA (Volume 1) */
{0x24f4,0xfc84,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
{0x24f4,0xfc84,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_64k_radica_r,m68k_unused_8_w,NULL,NULL}},
/* RADICA (Volume 2) */
{0x104f,0x32e9,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
{0xd951,0x78d0,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_64k_radica_r,m68k_unused_8_w,NULL,NULL}},
/* RADICA (Volume 3 - Super Sonic Gold edition) */
{0x0000,0x1f25,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_64k_radica_r,m68k_unused_8_w,NULL,NULL}},
/* RADICA (Street Fighter II CE edition) */
{0x1add,0xa838,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_64k_radica_r,m68k_unused_8_w,NULL,NULL}},
/* RADICA (Street Fighter II CE edition) (PAL) */
{0x104f,0x32e9,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_64k_radica_r,m68k_unused_8_w,NULL,NULL}},
/* RADICA (Sensible Soccer Plus edition) (PAL) */
{0x0000,0x1f7f,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_128k_radica_r,m68k_unused_8_w,NULL,NULL}},
/* Tenchi wo Kurau III: Sangokushi Gaiden - Chinese Fighter */
@@ -210,6 +230,12 @@ static const md_entry_t rom_database[] =
{0x0000,0xd0a0,0x48,0x4f,{{0x00,0x00,0xaa,0xf0},{0xffffff,0xffffff,0xfc0000,0xfc0000},{0x000000,0x000000,0x480000,0x4c0000},0,0,NULL,NULL,default_regs_r,NULL}},
/* Rock Heaven */
{0x6cca,0x2395,0x50,0x50,{{0x50,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x500008,0x000000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
/* Rock World */
{0x3547,0xa3da,0x50,0x50,{{0x50,0xa0,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x500008,0x500208,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
/* Rockman X3 (bootleg version ? two last register returned values are ignored, note that 0xaa/0x18 would work as well) */
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x00,0xc9,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x400004,0x400006},0,0,default_regs_r,NULL,default_regs_r,NULL}},
@@ -352,20 +378,20 @@ void md_cart_init(void)
zbank_memory_map[i].write = zbank_unused_w;
}
/* support for Quackshot REV 01 (real) dump */
if (strstr(rominfo.product,"00004054-01") && (cart.romsize == 0x80000))
/* support for Quackshot REV A original ROM dump (512KB) */
if (strstr(rominfo.product,"00004054-01") && (cart.romsize == 0x80000) && (rominfo.checksum == 0xa4b3))
{
/* $000000-$0fffff: first 256K mirrored (A18 not connected to ROM chip, A19 not decoded) */
/* $000000-$0fffff: lower 256KB mirrored (VA18 and VA19 not connected to ROM chip) */
for (i=0x00; i<0x10; i++)
{
/* $200000-$3fffff: mirror of $000000-$1fffff (A21 not decoded) */
/* $200000-$3fffff: mirror of $000000-$1fffff (VA21 not connected to ROM chip) */
m68k.memory_map[i].base = m68k.memory_map[i + 0x20].base = cart.rom + ((i & 0x03) << 16);
}
/* $100000-$1fffff: second 256K mirrored (A20 connected to ROM chip A18) */
/* $100000-$1fffff: upper 256KB mirrored (VA20 connected to ROM chip A19) */
for (i=0x10; i<0x20; i++)
{
/* $200000-$3fffff: mirror of $000000-$1fffff (A21 not decoded) */
/* $200000-$3fffff: mirror of $000000-$1fffff (VA21 not connected to ROM chip) */
m68k.memory_map[i].base = m68k.memory_map[i + 0x20].base = cart.rom + 0x40000 + ((i & 0x03) << 16);
}
}
@@ -376,101 +402,59 @@ void md_cart_init(void)
sram_init();
eeprom_i2c_init();
/* external SRAM */
/* memory-mapped SRAM */
if (sram.on && !sram.custom)
{
/* initialize default memory mapping for SRAM */
m68k.memory_map[sram.start >> 16].base = sram.sram;
m68k.memory_map[sram.start >> 16].read8 = sram_read_byte;
m68k.memory_map[sram.start >> 16].read16 = sram_read_word;
m68k.memory_map[sram.start >> 16].write8 = sram_write_byte;
m68k.memory_map[sram.start >> 16].write16 = sram_write_word;
zbank_memory_map[sram.start >> 16].read = sram_read_byte;
zbank_memory_map[sram.start >> 16].write = sram_write_byte;
/* SRAM is mapped by default unless it overlaps with ROM area (Phantasy Star 4, Beyond Oasis/Legend of Thor, World Series Baseball 9x, Duke Nukem 3D,...) */
if (sram.start >= cart.romsize)
{
m68k.memory_map[sram.start >> 16].base = sram.sram;
m68k.memory_map[sram.start >> 16].read8 = sram_read_byte;
m68k.memory_map[sram.start >> 16].read16 = sram_read_word;
m68k.memory_map[sram.start >> 16].write8 = sram_write_byte;
m68k.memory_map[sram.start >> 16].write16 = sram_write_word;
zbank_memory_map[sram.start >> 16].read = sram_read_byte;
zbank_memory_map[sram.start >> 16].write = sram_write_byte;
}
/* support for Triple Play 96 & Triple Play - Gold Edition mapping */
else if ((strstr(rominfo.product,"T-172026") != NULL) || (strstr(rominfo.product,"T-172116") != NULL))
{
/* $000000-$1fffff: cartridge ROM (lower 2MB) */
/* $200000-$2fffff: SRAM (32KB mirrored) */
/* NB: existing 4MB ROM dumps include SRAM data at ROM offsets 0x200000-0x2fffff */
for (i=0x20; i<0x30; i++)
{
m68k.memory_map[i].base = sram.sram;
m68k.memory_map[i].read8 = sram_read_byte;
m68k.memory_map[i].read16 = sram_read_word;
m68k.memory_map[i].write8 = sram_write_byte;
m68k.memory_map[i].write16 = sram_write_word;
zbank_memory_map[i].read = sram_read_byte;
zbank_memory_map[i].write = sram_write_byte;
}
/* $300000-$3fffff: cartridge ROM (upper 1MB) */
/* NB: only real (3MB) Mask ROM dumps need ROM offsets 0x200000-0x2fffff to be remapped to this area */
if (READ_BYTE(cart.rom, 0x200000) != 0xFF)
{
for (i=0x30; i<0x40; i++)
{
m68k.memory_map[i].base = cart.rom + ((i - 0x10) << 16);
}
}
}
}
/**********************************************
SVP CHIP
***********************************************/
svp = NULL;
if (strstr(rominfo.international,"Virtua Racing"))
if ((READ_BYTE(cart.rom, 0x1c8) == 'S') && (READ_BYTE(cart.rom, 0x1c9) == 'V'))
{
svp_init();
}
/**********************************************
LOCK-ON
***********************************************/
/* clear existing patches */
ggenie_shutdown();
areplay_shutdown();
/* initialize extra hardware */
switch (config.lock_on)
{
case TYPE_GG:
{
ggenie_init();
break;
}
case TYPE_AR:
{
areplay_init();
break;
}
case TYPE_SK:
{
/* store S&K ROM above cartridge ROM (and before backup memory) */
if (cart.romsize > 0x600000) break;
/* try to load Sonic & Knuckles ROM file (2 MB) */
if (load_archive(SK_ROM, cart.rom + 0x600000, 0x200000, NULL) == 0x200000)
{
/* check ROM header */
if (!memcmp(cart.rom + 0x600000 + 0x120, "SONIC & KNUCKLES",16))
{
/* try to load Sonic 2 & Knuckles UPMEM ROM (256 KB) */
if (load_archive(SK_UPMEM, cart.rom + 0x900000, 0x40000, NULL) == 0x40000)
{
/* $000000-$1FFFFF is mapped to S&K ROM */
for (i=0x00; i<0x20; i++)
{
m68k.memory_map[i].base = cart.rom + 0x600000 + (i << 16);
}
#ifdef LSB_FIRST
for (i=0; i<0x200000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x600000];
cart.rom[i + 0x600000] = cart.rom[i + 0x600000 + 1];
cart.rom[i + 0x600000 + 1] = temp;
}
for (i=0; i<0x40000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x900000];
cart.rom[i + 0x900000] = cart.rom[i + 0x900000 + 1];
cart.rom[i + 0x900000 + 1] = temp;
}
#endif
cart.special |= HW_LOCK_ON;
}
}
}
break;
}
default:
{
break;
}
}
/**********************************************
CARTRIDGE EXTRA HARDWARE
***********************************************/
@@ -514,21 +498,18 @@ void md_cart_init(void)
/* Realtec mapper */
if (cart.hw.realtec)
{
/* 8k BOOT ROM */
/* copy 8KB Boot ROM after cartridge ROM area */
for (i=0; i<8; i++)
{
memcpy(cart.rom + 0x900000 + i*0x2000, cart.rom + 0x7e000, 0x2000);
memcpy(cart.rom + 0x400000 + i*0x2000, cart.rom + 0x7e000, 0x2000);
}
/* BOOT ROM is mapped to $000000-$3FFFFF */
for (i=0x00; i<0x40; i++)
{
m68k.memory_map[i].base = cart.rom + 0x900000;
}
/* specific read handler for ROM header area */
m68k.memory_map[0].read16 = mapper_realtec_r;
}
/* detect specific mappers */
if (strstr(rominfo.consoletype,"SEGA SSF"))
else if (strstr(rominfo.consoletype,"SEGA SSF"))
{
/* Everdrive extended SSF mapper */
cart.hw.time_w = mapper_512k_w;
@@ -536,6 +517,21 @@ void md_cart_init(void)
/* cartridge ROM mapping is reinitialized on /VRES */
cart.hw.bankshift = 1;
}
else if ((strstr(rominfo.consoletype,"SEGA SSF2") != NULL) && (cart.romsize <= 0x800000))
{
/* MegaSD enhanced SSF2 mapper (max. 8MB ROM) */
cart.special |= HW_MEGASD;
cart.hw.time_w = megasd_enhanced_ssf2_mapper_w;
/* cartridge ROM mapping is reinitialized on /VRES */
cart.hw.bankshift = 1;
}
else if ((strstr(rominfo.consoletype,"SEGA MEGASD") != NULL) && (cart.romsize <= 0x400000))
{
/* MegaSD ROM write mapper (max. 4MB ROM) */
cart.special |= HW_MEGASD;
cart.hw.time_w = megasd_rom_mapper_w;
}
else if (strstr(rominfo.domestic,"SUPER STREET FIGHTER2"))
{
/* SSF2 mapper */
@@ -637,6 +633,20 @@ void md_cart_init(void)
m68k.memory_map[0x00].write16 = mapper_flashkit_w;
zbank_memory_map[0x00].write = mapper_flashkit_w;
}
else if ((cart.romsize == 0x400000) &&
(READ_BYTE(cart.rom, 0x200150) == 'C') &&
(READ_BYTE(cart.rom, 0x200151) == 'A') &&
(READ_BYTE(cart.rom, 0x200152) == 'N') &&
(READ_BYTE(cart.rom, 0x200153) == 'O') &&
(READ_BYTE(cart.rom, 0x200154) == 'N'))
{
/* Canon - Legend of the new Gods (4MB dump) */
cart.hw.time_w = mapper_wd1601_w;
cart.hw.bankshift = 1;
sram.on = 1;
sram.start = 0x200000;
sram.end = 0x201fff;
}
else if ((*(uint16 *)(cart.rom + 0x08) == 0x6000) && (*(uint16 *)(cart.rom + 0x0a) == 0x01f6) && (rominfo.realchecksum == 0xf894))
{
/* Super Mario World 64 (unlicensed) mapper */
@@ -669,6 +679,11 @@ void md_cart_init(void)
zbank_memory_map[i].write = mapper_smw_64_w;
}
}
else if ((*(uint16 *)(cart.rom + 0x04) == 0x0000) && (*(uint16 *)(cart.rom + 0x06) == 0x0104) && (rominfo.checksum == 0x31fc))
{
/* Micro Machines (USA) custom TMSS bypass logic */
m68k.memory_map[0xa1].write8 = mapper_sr16v1_w;
}
else if (cart.romsize > 0x400000)
{
/* assume linear ROM mapping by default (max. 10MB) */
@@ -686,6 +701,99 @@ void md_cart_init(void)
{
cart.hw.time_w = default_time_w;
}
/**********************************************
LOCK-ON
***********************************************/
/* clear existing patches */
ggenie_shutdown();
areplay_shutdown();
/* initialize extra hardware */
switch (config.lock_on)
{
case TYPE_GG:
{
ggenie_init();
break;
}
case TYPE_AR:
{
areplay_init();
break;
}
case TYPE_SK:
{
/* store Sonic & Knuckles ROM files after cartridge ROM area */
if (cart.romsize > 0x400000) break;
/* try to load Sonic & Knuckles ROM file (2MB) */
if (load_archive(SK_ROM, cart.rom + 0x400000, 0x200000, NULL) == 0x200000)
{
/* check ROM header */
if (!memcmp(cart.rom + 0x400000 + 0x120, "SONIC & KNUCKLES",16))
{
/* try to load Sonic 2 & Knuckles upmem ROM file (256KB) */
if (load_archive(SK_UPMEM, cart.rom + 0x600000, 0x40000, NULL) == 0x40000)
{
/* $000000-$1FFFFF is mapped to S&K ROM */
for (i=0x00; i<0x20; i++)
{
m68k.memory_map[i].base = cart.rom + 0x400000 + (i << 16);
}
#ifdef LSB_FIRST
for (i=0; i<0x200000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x400000];
cart.rom[i + 0x400000] = cart.rom[i + 0x400000 + 1];
cart.rom[i + 0x400000 + 1] = temp;
}
for (i=0; i<0x40000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x600000];
cart.rom[i + 0x600000] = cart.rom[i + 0x600000 + 1];
cart.rom[i + 0x600000 + 1] = temp;
}
#endif
cart.special |= HW_LOCK_ON;
}
}
}
break;
}
default:
{
break;
}
}
/**********************************************
MEGASD ADD-ON
***********************************************/
/* enable MegaSD overlay for cartridge ROM (max. 8MB) when Mega CD hardware is disabled and either MegaSD add-on is forced enabled or automatic add-on detection is enabled and MegaSD compatible disc image is loaded */
if ((cart.romsize <= 0x800000) && (system_hw == SYSTEM_MD) && ((config.add_on == HW_ADDON_MEGASD) || ((config.add_on | cdd.loaded) == HW_ADDON_MEGASD)))
{
cart.special |= HW_MEGASD;
}
/* force Mega CD sound hardware initialization when MegaSD overlay is enabled (if not already initialized) */
if ((cart.special & HW_MEGASD) && !snd.blips[1] && !snd.blips[2])
{
/* allocate blip buffers for PCM and CD-DA audio streams */
snd.blips[1] = blip_new(snd.sample_rate / 10);
snd.blips[2] = blip_new(snd.sample_rate / 10);
/* initialize PCM and CD-DA audio */
audio_set_rate(snd.sample_rate, snd.frame_rate);
}
}
/* hardware that need to be reseted on power on */
@@ -693,15 +801,36 @@ void md_cart_reset(int hard_reset)
{
int i;
/* Realtec mapper */
if (cart.hw.realtec)
{
/* Boot ROM (8KB mirrored) is mapped to $000000-$3FFFFF */
for (i=0x00; i<0x40; i++)
{
m68k.memory_map[i].base = cart.rom + 0x400000;
}
/* Reset mapper */
cart.hw.regs[0] = 0;
cart.hw.regs[1] = 0;
cart.hw.regs[2] = 0;
}
/* reset cartridge mapping */
if (cart.hw.bankshift)
else if (cart.hw.bankshift)
{
for (i=0x00; i<0x40; i++)
{
m68k.memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
}
}
/* MegaSD hardware */
if (cart.special & HW_MEGASD)
{
megasd_reset();
}
/* SVP chip */
if (svp)
{
@@ -754,15 +883,20 @@ int md_cart_context_save(uint8 *state)
{
/* get base address */
base = m68k.memory_map[i].base;
if (base == sram.sram)
{
/* SRAM */
state[bufferptr++] = 0xff;
}
else if (base == boot_rom)
{
/* Boot ROM */
state[bufferptr++] = 0xfe;
}
else
{
/* ROM */
/* Cartridge ROM */
state[bufferptr++] = ((base - cart.rom) >> 16) & 0xff;
}
}
@@ -778,6 +912,12 @@ int md_cart_context_save(uint8 *state)
save_param(&svp->ssp1601,sizeof(ssp1601_t));
}
/* MegaSD hardware */
if (cart.special & HW_MEGASD)
{
bufferptr += megasd_context_save(&state[bufferptr]);
}
return bufferptr;
}
@@ -819,7 +959,7 @@ int md_cart_context_load(uint8 *state)
}
/* ROM */
m68k.memory_map[i].base = cart.rom + (offset << 16);
m68k.memory_map[i].base = (offset == 0xfe) ? boot_rom : (cart.rom + (offset << 16));
}
}
@@ -834,6 +974,12 @@ int md_cart_context_load(uint8 *state)
load_param(&svp->ssp1601,sizeof(ssp1601_t));
}
/* MegaSD hardware */
if (cart.special & HW_MEGASD)
{
bufferptr += megasd_context_load(&state[bufferptr]);
}
return bufferptr;
}
@@ -853,7 +999,6 @@ static void mapper_sega_w(uint32 data)
if (sram.on)
{
/* Backup RAM mapped to $200000-$20ffff (normally mirrored up to $3fffff but this breaks Sonic Megamix and no game need it) */
m68k.memory_map[0x20].base = sram.sram;
m68k.memory_map[0x20].read8 = sram_read_byte;
m68k.memory_map[0x20].read16 = sram_read_word;
zbank_memory_map[0x20].read = sram_read_byte;
@@ -874,28 +1019,24 @@ static void mapper_sega_w(uint32 data)
}
/* S&K lock-on chip */
if ((cart.special & HW_LOCK_ON) && (config.lock_on == TYPE_SK))
if (cart.special & HW_LOCK_ON)
{
/* S2K upmem chip mapped to $300000-$3fffff (256K mirrored) */
/* S2K upmem chip mapped to $300000-$3fffff (256KB mirrored) */
for (i=0x30; i<0x40; i++)
{
m68k.memory_map[i].base = (cart.rom + 0x900000) + ((i & 3) << 16);
m68k.memory_map[i].base = (cart.rom + 0x600000) + ((i & 3) << 16);
}
}
}
else
{
/* cartridge ROM mapped to $200000-$3fffff */
for (i=0x20; i<0x40; i++)
{
m68k.memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
m68k.memory_map[i].read8 = NULL;
m68k.memory_map[i].read16 = NULL;
zbank_memory_map[i].read = NULL;
m68k.memory_map[i].write8 = m68k_unused_8_w;
m68k.memory_map[i].write16 = m68k_unused_16_w;
zbank_memory_map[i].write = zbank_unused_w;
}
/* cartridge ROM mapped to $200000-$20ffff */
m68k.memory_map[0x20].read8 = NULL;
m68k.memory_map[0x20].read16 = NULL;
zbank_memory_map[0x20].read = NULL;
m68k.memory_map[0x20].write8 = m68k_unused_8_w;
m68k.memory_map[0x20].write16 = m68k_unused_16_w;
zbank_memory_map[0x20].write = zbank_unused_w;
}
}
@@ -908,7 +1049,7 @@ static void mapper_512k_w(uint32 address, uint32 data)
uint32 i;
/* 512K ROM paging */
uint8 *src = cart.rom + (data << 19);
uint8 *src = cart.rom + ((data << 19) & cart.mask);
/* cartridge area ($000000-$3FFFFF) is divided into 8 x 512K banks */
address = (address << 2) & 0x38;
@@ -1482,43 +1623,56 @@ static uint32 mapper_smw_64_r(uint32 address)
}
/*
Realtec ROM bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
(Note: register usage is inverted in TascoDlx documentation)
Realtec ROM bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter, Tom Clown)
Verified with real cartridge hardware (slightly different from behavior described in TascoDlx documentation)
*/
static void mapper_realtec_w(uint32 address, uint32 data)
{
switch (address)
{
case 0x402000:
case 0x402000:
{
/* number of mapped 64k blocks (the written value is a number of 128k blocks) */
cart.hw.regs[2] = data << 1;
/* fixed ROM bank size */
/* when bit 0 is set, ROM A16 pin is forced to value configured in register below (connected to VA17 otherwise) */
/* when bit 1 is set, ROM A17 pin is forced to value configured in register below (connected to VA18 otherwise) */
/* other bits have no effect */
cart.hw.regs[1] = (data & 3) << 1;
return;
}
case 0x404000:
case 0x404000:
{
/* 00000xxx */
cart.hw.regs[0] = data & 7;
/* fixed ROM bank selection (4 x 128KB banks) */
/* bit 0 corresponds to ROM A16 pin value when forced */
/* bit 1 corresponds to ROM A17 pin value when forced */
/* other bits have no effect */
cart.hw.regs[2] = (data & 3) << 1;
return;
}
case 0x400000:
{
/* 00000yy1 */
cart.hw.regs[1] = data & 6;
/* ensure mapped size is not null */
if (cart.hw.regs[2])
/* ROM access enable */
/* when bit 0 is set, ROM A17/A16 pins are set according to above registers and ROM A15/A12 pins are connected to VA16-VA13 (forced to 1 on reset) */
/* other bits have no effect */
if (data & 0x01)
{
/* mapped start address is 00yy xxx0 0000 0000 0000 0000 */
uint32 base = (cart.hw.regs[0] << 1) | (cart.hw.regs[1] << 3);
/* selected blocks are mirrored into the whole cartridge area */
int i;
for (i=0x00; i<0x40; i++)
/* once ROM access is enabled, ROM mapping can not be modified until next reset */
if (!cart.hw.regs[0])
{
m68k.memory_map[i].base = &cart.rom[(base + (i % cart.hw.regs[2])) << 16];
int i;
for (i=0x00; i<0x40; i++)
{
/* 0x000000-0x07ffff mapped area is mirrored in 4MB cartridge range (VA21-VA19 not connected) */
uint32 base = i & 7;
/* adjust 64k mapped area ROM base address according to fixed ROM bank configuration (see above) */
base = (base & ~cart.hw.regs[1]) | (cart.hw.regs[2] & cart.hw.regs[1]);
m68k.memory_map[i].base = &cart.rom[base << 16];
}
cart.hw.regs[0] = data;
}
}
return;
@@ -1526,6 +1680,19 @@ static void mapper_realtec_w(uint32 address, uint32 data)
}
}
static uint32 mapper_realtec_r(uint32 address)
{
/* /VRES is asserted to bypass TMSS licensing screen when first read access to cartridge ROM header is detected */
if ((address == 0x100) && (m68k.memory_map[0].base = cart.base))
{
/* asserting /VRES from cartridge should only reset 68k CPU (TODO: confirm this on real hardware) */
m68k_pulse_reset();
}
/* default ROM area read handler */
return *(uint16 *)(m68k.memory_map[0].base + (address & 0xfffe));
}
/* Game no Kanzume Otokuyou ROM Mapper */
static void mapper_seganet_w(uint32 address, uint32 data)
{
@@ -1621,27 +1788,232 @@ static void mapper_64k_multi_w(uint32 address)
/* 64 x 64k banks */
for (i=0; i<64; i++)
{
m68k.memory_map[i].base = &cart.rom[((address++) & 0x3f) << 16];
m68k.memory_map[i].base = &cart.rom[((address + i) & 0x3f) << 16];
}
}
/*
Custom ROM Bankswitch used in pirate "1800-in-1" cartridge
*/
static uint32 mapper_128k_multi_r(uint32 address)
{
int i;
/* 16 x 128k banks (2MB ROM) */
/* Bank index (B3 B2 B1 B0) is encoded in address lower byte = {0 X B0 B1 X B2 B3 0} */
/* Note: {0 B0 X B1 X B2 B3 0} also works, see below for the 9 unique values being used for all menu entries
read16 00A13000 (0002FBEE) => 0x000000-0x03ffff (2x128KB)
read16 00A13018 (00FF2056) => 0x040000-0x07ffff (2x128KB)
read16 00A13004 (00FF2120) => 0x080000-0x0bffff (2x128KB)
read16 00A1301C (00FF20A6) => 0x0c0000-0x0fffff (2x128KB)
read16 00A1300A (00FF20BA) => 0x100000-0x13ffff (2x128KB)
read16 00A1301A (00FF20CE) => 0x140000-0x17ffff (2x128KB)
read16 00A1300E (00FF20F4) => 0x180000-0x1bffff (2x128KB)
read16 00A1301E (00FF2136) => 0x1c0000-0x1dffff (1x128KB)
read16 00A1307E (00FF2142) => 0x1e0000-0x1fffff (1x128KB)
*/
int bank = ((address & 0x02) << 2) | (address & 0x04) | ((address & 0x10) >> 3) | ((address & 0x20) >> 5);
/* remap cartridge area (64 x 64k banks) */
address = bank << 1;
for (i=0x00; i<0x40; i++)
{
m68k.memory_map[i].base = &cart.rom[((address + i) & 0x3f) << 16];
}
/* returned value changes the menu title and number of entries in the 'game' list (the number of distinct games does not change though) */
/* 0x00 => 9-in-1 */
/* 0x01 => 190-in-1 */
/* 0x02 => 888-in-1 */
/* 0x03 => 1800-in-1 */
/* real cartridge board has switches to select between the four different menus but here we force the largest menu selection (each other menus being a subset of the next larger menu) */
return 0x03;
}
/*
Custom ROM Bankswitch used in pirate "Golden Mega 250-in-1" cartridge
*/
static void mapper_256k_multi_w(uint32 address, uint32 data)
{
int i;
/* 8 x 256k banks (2MB ROM) */
/* Bank index (B2 B1 B0) is encoded in data lower byte = {B1 B0 X X 0 0 0 B2} */
/* Note: {X B0 B1 B2 0 0 0 X}, {B1 B0 X B2 0 0 0 X} or {X B0 B1 X 0 0 0 B2} also work, see below for the 4 unique values being used for all menu entries
write16 00089000 = 0000 (00FF0006) => 0x000000-0x03ffff (1x256KB)
write16 00089000 = 0040 (00FF0006) => 0x040000-0x07ffff (1x256KB)
write16 00089000 = 00A0 (00FF0006) => 0x080000-0x0fffff (2x256KB)
write16 00089000 = 0011 (00FF0006) => 0x100000-0x1fffff (4x256KB)
*/
int bank = ((data & 0x01) << 2) | ((data & 0xc0) >> 6);
/* remap cartridge area (64 x 64k banks) */
address = bank << 2;
for (i=0x00; i<0x40; i++)
{
m68k.memory_map[i].base = &cart.rom[((address + i) & 0x3f) << 16];
}
}
/*
Custom ROM Bankswitch used in "Canon - Legend of the New Gods"
(uses WD1601 QFPL V1.01 board also used in chinese X-in-1 pirates sold by mindkids)
*/
static void mapper_wd1601_w(uint32 address, uint32 data)
{
int i;
/* !TIME write16 0xA13002 = 0x3002 (00FFFE0C) */
/* The board probably allows up to 256MB Flash ROM remapping but this game only has 4MB ROM chip */
if ((address & 0xfe) == 0x02)
{
/* upper 2MB ROM mapped to $000000-$1fffff */
for (i=0; i<0x20; i++)
{
m68k.memory_map[i].base = &cart.rom[(0x20 + i) << 16];
}
/* backup RAM (8KB) mapped to $2000000-$3fffff */
for (i=0x20; i<0x40; i++)
{
m68k.memory_map[i].base = sram.sram;
m68k.memory_map[i].read8 = sram_read_byte;
m68k.memory_map[i].read16 = sram_read_word;
m68k.memory_map[i].write8 = sram_write_byte;
m68k.memory_map[i].write16 = sram_write_word;
zbank_memory_map[i].read = sram_read_byte;
zbank_memory_map[i].write = sram_write_byte;
}
}
}
/*
Custom ROM Bankswitch used in RADICA cartridges
+++++++++++++++++++++++++++++++++++++++++++++++
Two different boards seem to exist (one with support for 64KB banks mapping and another one supporting 128KB banks + battery-RAM).
Radica Volume 1 requires 64KB banks mapping as the menu is located at a 64KB boundary.
Sensible Soccer Plus edition requires 128KB banks mapping with only VA6-VA2 being used to select bank index (VA1 is ignored).
Sensible Soccer Plus edition also requires 8KB backup RAM to be mapped in higher 2MB range.
Other games support both 64KB or 128KB mapping so it's not clear what exact board they are using but none require SRAM so we use 64KB mapper by default.
Note that Radica Volume 3 uses similar ROM mapping as Sensible Soccer Plus edition so it might be using same 128KB board, without any SRAM chip connected.
*/
static uint32 mapper_radica_r(uint32 address)
static uint32 mapper_64k_radica_r(uint32 address)
{
int i = 0;
address = (address >> 1);
/* 64 x 64k banks */
for (i = 0; i < 64; i++)
/*
Volume 1
--------
000000h-0fffffh: Kid Chameleon : !TIME read16 0xA13000 (00FF103A)
100000h-1fffffh: Dr Robotnik's Mean Bean Machine : !TIME read16 0xA13020 (00FF101E)
200000h-27ffffh: Sonic The Hedgehog : !TIME read16 0xA13040 (00FF101E)
280000h-2fffffh: Golden Axe : !TIME read16 0xA13050 (00FF101E)
300000h-37ffffh: Altered Beast : !TIME read16 0xA13060 (00FF101E)
380000h-39ffffh: Flicky : !TIME read16 0xA13070 (00FF101E)
3a0000h-3effffh: N/A : N/A
3f0000h-3fffffh: Radica Menu (64 KB) : !TIME read16 0xA1307E (00FF1006)
Volume 2
--------
000000h-0fffffh: Sonic The Hedgehog 2 : !TIME read16 0xA13000 (00FF103A)
100000h-1fffffh: The Ooze : !TIME read16 0xA13020 (00FF101E)
200000h-2fffffh: Ecco The Dolphin : !TIME read16 0xA13040 (00FF101E)
300000h-37ffffh: Gain Ground : !TIME read16 0xA13060 (00FF101E)
380000h-3bffffh: Alex Kidd in Enchanted Castle : !TIME read16 0xA13070 (00FF101E)
3c0000h-3dffffh: Columns : !TIME read16 0xA13078 (00FF101E)
3e0000h-3fffffh: Radica Menu (128 KB) : !TIME read16 0xA1307C (00FF1006)
Volume 3 - Super Sonic Gold edition
-----------------------------------
000000h-01ffffh: Radica Menu (128 KB) : N/A
020000h-07ffffh: N/A : N/A
080000h-0fffffh: Sonic The Hedgehog : !TIME read16 0xA13010 (00FF1012)
100000h-1fffffh: Sonic The Hedgehog 2 : !TIME read16 0xA13020 (00FF1012)
200000h-2fffffh: Sonic Spinball : !TIME read16 0xA13040 (00FF1012)
300000h-3fffffh: Dr Robotnik's Mean Bean Machine : !TIME read16 0xA13060 (00FF1012)
Street Fighter 2 CE edition
---------------------------
000000h-2fffffh: Street Fighter 2 CE : !TIME read16 0xA13000 (00FF103A)
300000h-3bffffh: Ghouls'n Ghosts : !TIME read16 0xA13060 (00FF101E)
3c0000h-3dffffh: Radica Menu (128 KB) : !TIME read16 0xA13078 (00FF1006)
3e0000h-3fffffh: N/A : N/A
*/
int index = (address >> 1) & 0x3F;
/* $000000-$3fffff area is mapped to selected banks (OR gates between VA21-VA16 and selected index) */
for (i = 0x00; i < 0x40; i++)
{
m68k.memory_map[i].base = &cart.rom[((address++)& 0x3f)<< 16];
m68k.memory_map[i].base = &cart.rom[(index | i) << 16];
}
return 0xffff;
}
static uint32 mapper_128k_radica_r(uint32 address)
{
int i = 0;
/* 32 x 128k banks */
/*
Sensible Soccer Plus edition
----------------------------
000000h-01ffffh: Radica Menu (128 KB) : N/A
020000h-07ffffh: N/A : N/A
080000h-0fffffh: Sensible Soccer : !TIME read16 0xA13010 (00FF1012)
100000h-1fffffh: Mega-Lo-Mania : !TIME read16 0xA13022 (00FF1012)
200000h-37ffffh: Cannon Fodder : !TIME read16 0xA13042 (00FF1012)
380000h-3fffffh: N/A : N/A
Note: address bit 1 is ignored for bank selection but might be used to enable/disable SRAM mapping ?
*/
int index = (address >> 1) & 0x3E;
/* $000000-$1fffff area is mapped to selected banks (OR gates between VA20-VA17 and selected index) */
for (i = 0x00; i < 0x20; i++)
{
m68k.memory_map[i].base = &cart.rom[(index | i) << 16];
}
/* $200000-$3fffff area is mapped to 8KB SRAM (mirrored) */
for (i = 0x20; i < 0x40; i++)
{
m68k.memory_map[i].base = sram.sram;
m68k.memory_map[i].read8 = sram_read_byte;
m68k.memory_map[i].read16 = sram_read_word;
m68k.memory_map[i].write8 = sram_write_byte;
m68k.memory_map[i].write16 = sram_write_word;
zbank_memory_map[i].read = sram_read_byte;
zbank_memory_map[i].write = sram_write_byte;
}
return 0xffff;
}
/*
Custom logic (ST 16S25HB1 PAL) used in Micro Machines USA cartridge (SR16V1.1 board)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/VRES is asserted to bypass TMSS security checks when write access to 0xA141xx
with D0=1 is detected (access to cartridge ROM enabled instead of TMSS Boot ROM)
*/
static void mapper_sr16v1_w(uint32 address, uint32 data)
{
/* default I/O and Control registers write handler */
ctrl_io_write_byte(address, data);
/* cartridge uses /LWR, /AS and VA1-VA18 (only VA8-VA17 are required to decode access to TMSS bankswitch register) */
if ((address & 0xff01) == 0x4101)
{
/* check if cartridge ROM is enabled (D0=1) */
if (data & 0x01)
{
/* asserting /VRES from cartridge should only reset 68k CPU (TODO: confirm this on real hardware) */
m68k_pulse_reset();
}
}
}
/************************************************************
default !TIME signal handler
@@ -1650,9 +2022,13 @@ static uint32 mapper_radica_r(uint32 address)
static void default_time_w(uint32 address, uint32 data)
{
/* enable multi-game cartridge mapper by default */
if (address < 0xa13040)
if (address < 0xa13060)
{
mapper_64k_multi_w(address);
/* cartridge ROM mapping is reinitialized on /VRES */
cart.hw.bankshift = 1;
return;
}
+10 -3
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Mega Drive cartridge hardware support
*
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
*
* Most cartridge protections were initially documented by Haze
* (http://haze.mameworld.info/)
@@ -55,9 +55,16 @@
#define TYPE_AR 0x02 /* (Pro) Action Replay */
#define TYPE_SK 0x03 /* Sonic & Knuckles */
/* CD hardware add-on (MD mode) */
#define HW_ADDON_AUTO 0x00
#define HW_ADDON_MEGACD 0x01
#define HW_ADDON_MEGASD 0x02
#define HW_ADDON_NONE 0x03
/* Special hardware (0x01 & 0x02 reserved for Master System 3-D glasses & Terebi Oekaki) */
#define HW_J_CART 0x04
#define HW_LOCK_ON 0x08
#define HW_MEGASD 0x10
/* Cartridge extra hardware */
typedef struct
@@ -81,10 +88,10 @@ typedef struct
uint32 mask; /* ROM mask */
uint8 special; /* custom external hardware (Lock-On, J-Cart, 3-D glasses, Terebi Oekaki,...) */
cart_hw_t hw; /* cartridge internal hardware */
uint8 rom[MAXROMSIZE]; /* ROM area */
uint8 lockrom[0x10000]; /* Game Genie / (Pro) Action Replay Lock-On ROM area (max 64KB) */
uint8 rom[MAXROMSIZE]; /* cartridge ROM area */
} md_cart_t;
/* Function prototypes */
extern void md_cart_init(void);
extern void md_cart_reset(int hard_reset);
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
/****************************************************************************
* Genesis Plus
* MegaSD flashcart CD hardware interface overlay & enhanced ROM mappers
*
* Copyright (C) 2020-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
*
* - Redistributions may not be sold, nor may they be used in a commercial
* product or activity.
*
* - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable.
*
* - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************************/
#ifndef _MEGASD_H_
#define _MEGASD_H_
#include "shared.h"
extern void megasd_reset(void);
extern void megasd_rom_mapper_w(unsigned int address, unsigned int data);
extern void megasd_enhanced_ssf2_mapper_w(unsigned int address, unsigned int data);
extern void megasd_update_cdda(unsigned int samples);
extern int megasd_context_save(uint8 *state);
extern int megasd_context_load(uint8 *state);
#endif
+509 -88
View File
@@ -2,7 +2,10 @@
* Genesis Plus
* SG-1000, Master System & Game Gear cartridge hardware support
*
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
*
* Credits to Ben Sittler and Omar Cornut at smspower.org for Korean mappers
* reverse-engineering and description
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -40,23 +43,27 @@
#include "eeprom_93c.h"
#include "terebi_oekaki.h"
#define MAPPER_NONE (0x00)
#define MAPPER_TEREBI (0x01)
#define MAPPER_RAM_2K (0x02)
#define MAPPER_RAM_8K (0x03)
#define MAPPER_RAM_8K_EXT1 (0x04)
#define MAPPER_RAM_8K_EXT2 (0x05)
#define MAPPER_SEGA (0x10)
#define MAPPER_SEGA_X (0x11)
#define MAPPER_93C46 (0x12)
#define MAPPER_CODIES (0x13)
#define MAPPER_MULTI_16K (0x14)
#define MAPPER_KOREA (0x15)
#define MAPPER_KOREA_16K (0x16)
#define MAPPER_KOREA_8K (0x20)
#define MAPPER_MSX (0x21)
#define MAPPER_MSX_NEMESIS (0x22)
#define MAPPER_MULTI_32K (0x40)
#define MAPPER_NONE (0x00)
#define MAPPER_TEREBI (0x01)
#define MAPPER_RAM_2K (0x02)
#define MAPPER_RAM_8K (0x03)
#define MAPPER_RAM_8K_EXT1 (0x04)
#define MAPPER_SEGA (0x10)
#define MAPPER_SEGA_X (0x11)
#define MAPPER_93C46 (0x12)
#define MAPPER_CODIES (0x13)
#define MAPPER_MULTI_16K (0x14)
#define MAPPER_KOREA (0x15)
#define MAPPER_KOREA_16K (0x16)
#define MAPPER_MULTI_2x16K_V1 (0x17)
#define MAPPER_MULTI_2x16K_V2 (0x18)
#define MAPPER_MULTI_32K_16K (0x19)
#define MAPPER_KOREA_8K (0x20)
#define MAPPER_MSX (0x21)
#define MAPPER_MSX_NEMESIS (0x22)
#define MAPPER_MULTI_8K (0x23)
#define MAPPER_MULTI_4x8K (0x24)
#define MAPPER_MULTI_32K (0x40)
typedef struct
{
@@ -92,33 +99,50 @@ static const rominfo_t game_list[] =
{0x23BAC434, 0, 0, 0, MAPPER_SEGA_X, SYSTEM_GG, REGION_USA}, /* Shining Force Gaiden - Final Conflict (JP) [T-Eng] */
/* games using "Korean" mappers */
{0x445525E2, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Penguin Adventure (KR) */
{0x83F0EEDE, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Street Master (KR) */
{0xA05258F5, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Won-Si-In (KR) */
{0x06965ED9, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* F-1 Spirit - The way to Formula-1 (KR) */
{0x77EFE84A, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Cyborg Z (KR) */
{0xF89AF3CC, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Knightmare II - The Maze of Galious (KR) */
{0x9195C34C, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Boy 3 (KR) */
{0xE316C06D, 0, 0, 0, MAPPER_MSX_NEMESIS, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis (KR) */
{0x0A77FA5E, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis 2 (KR) */
{0x89B79E77, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Dodgeball King (KR) */
{0x929222C4, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung II (KR) */
{0x18FB98A3, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung 3 (KR) */
{0x97D03541, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Sangokushi 3 (KR) */
{0x192949D5, 0, 0, 0, MAPPER_KOREA_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Janggun-ui Adeul (KR) */
{0x76C5BDFB, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Jang Pung II [SMS-GG] (KR) */
{0x9FA727A0, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 0] [SMS-GG] (US) */
{0xFB481971, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 1] [SMS-GG] (US) */
{0xA67F2A5C, 0, 0, 0, MAPPER_MULTI_16K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* 4-Pak All Action (KR) */
{0x98AF0236, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 1) (KR) */
{0x6EBFE1C3, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 2) (KR) */
{0x81A36A4F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 3) (KR) */
{0x8D2D695D, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 4) (KR) */
{0x82C09B57, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 5) (KR) */
{0x4088EEB4, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 6) (KR) */
{0xFBA94148, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 1) (KR) */
{0x8333C86E, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 2) (KR) */
{0x00E9809F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 3) (KR) */
{0x445525E2, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Penguin Adventure (KR) */
{0x83F0EEDE, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Street Master (KR) */
{0xA05258F5, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Wonsiin (KR) */
{0x06965ED9, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* F-1 Spirit - The way to Formula-1 (KR) */
{0x77EFE84A, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Cyborg Z (KR) */
{0xF89AF3CC, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Knightmare II: The Maze of Galious (KR) */
{0x9195C34C, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Boy 3 (KR) */
{0xE316C06D, 0, 0, 0, MAPPER_MSX_NEMESIS, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis (KR) */
{0x0A77FA5E, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis 2 (KR) */
{0x89B79E77, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Dodgeball King (KR) */
{0x929222C4, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung II (KR) */
{0x18FB98A3, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung 3 (KR) */
{0x97D03541, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Sangokushi 3 (KR) */
{0x192949D5, 0, 0, 0, MAPPER_KOREA_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Janggun-ui Adeul (KR) */
{0x76C5BDFB, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Jang Pung II [SMS-GG] (KR) */
{0x01A2D595, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Battle [Proto] [SMS-GG] (US) */
{0x9FA727A0, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 0] [SMS-GG] (US) */
{0xFB481971, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 1] [SMS-GG] (US) */
{0xA67F2A5C, 0, 0, 0, MAPPER_MULTI_16K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* 4-Pak All Action (KR) */
{0x98AF0236, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 1) (KR) */
{0x6EBFE1C3, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 2) (KR) */
{0x81A36A4F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 3) (KR) */
{0x8D2D695D, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 4) (KR) */
{0x82C09B57, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 5) (KR) */
{0x4088EEB4, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 6) (KR) */
{0xFBA94148, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 1) (KR) */
{0x8333C86E, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 2) (KR) */
{0x00E9809F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 3) (KR) */
{0xBA5EC0E3, 0, 0, 0, MAPPER_MULTI_4x8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* 128 Hap (KR) */
{0x380D7400, 0, 0, 0, MAPPER_MULTI_4x8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game Mo-eumjip 188 Hap [v0] (KR) */
{0xC76601E0, 0, 0, 0, MAPPER_MULTI_4x8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game Mo-eumjip 188 Hap [v1] (KR) */
{0x38B3A72F, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game Chongjiphap 200 (KR).sms */
{0xD3056492, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 270 Hap ~ Jaemissneun-270 (KR) */
{0xAB07ECD4, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game World 260 Hap (KR) */
{0x0CDE0938, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game World 30 Hap (KR) */
{0xC29BB8CD, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game World 75 Hap (KR) */
{0x660BF6EC, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Multi Game - Super 75 in 1 (KR) */
{0xEB7790DE, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Multi Game - Super 125 in 1 (KR) */
{0xE6AD4D4B, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super World 30 Hap (KR) */
{0xEDB13847, 0, 0, 0, MAPPER_MULTI_2x16K_V1, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 45 (KR) */
{0xA841C0B7, 0, 0, 0, MAPPER_MULTI_2x16K_V2, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 52 Hap (KR) */
{0x4E202AA2, 0, 0, 0, MAPPER_MULTI_2x16K_V2, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 180 (KR) */
{0xBA5D2776, 0, 0, 0, MAPPER_MULTI_2x16K_V2, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 200 (KR) */
{0xC0AC6956, 0, 0, 0, MAPPER_MULTI_32K_16K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Pigu-Wang 7 Hap - Jaemiiss-neun Game Mo-eumjip (KR) */
/* games using Codemaster mapper */
{0x29822980, 0, 0, 0, MAPPER_CODIES, SYSTEM_SMS2, REGION_EUROPE}, /* Cosmic Spacehead */
@@ -133,12 +157,16 @@ static const rominfo_t game_list[] =
{0x5E53C7F7, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* Ernie Els Golf */
{0xD9A7F170, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* Man Overboard! */
{0xF7C524F6, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* Micro Machines [GG] */
{0xC21E6CD0, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* Micro Machines [GG] [Proto] */
{0xDBE8895C, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* Micro Machines 2 - Turbo Tournament */
{0xC1756BEE, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* Pete Sampras Tennis */
{0x72981057, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* CJ Elephant Fugitive */
{0x3ACE6335, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* CJ Elephant Fugitive [Proto] */
{0x2306AAF4, 0, 0, 0, MAPPER_CODIES, SYSTEM_GG, REGION_USA}, /* Dinobasher - Starring Bignose the Caveman [GG] [Proto] */
/* games using serial EEPROM */
{0x36EBCD6D, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* Majors Pro Baseball */
{0x2DA8E943, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* Pro Yakyuu GG League */
{0x3D8D0DD6, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* World Series Baseball [v0] */
{0xBB38CFD7, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* World Series Baseball [v1] */
{0x578A8A38, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* World Series Baseball '95 */
@@ -153,23 +181,27 @@ static const rominfo_t game_list[] =
/* games using 8KB external RAM (volatile) */
{0x092F29D6, 0, 0, 0, MAPPER_RAM_8K, SYSTEM_SG, REGION_JAPAN_NTSC}, /* The Castle (J) */
/* games requiring SG-1000 II 8K RAM extension adapters */
/* games requiring SG-1000 II 8K RAM extension adapter (type A) */
{0x16F240D3, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Adventure Island [DahJee] (TW) */
{0xCE5648C3, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Bomberman Special [DahJee] (TW) */
{0x223397A1, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* King's Valley (TW) */
{0x281D2888, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Knightmare (TW) */
{0x281D2888, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Knightmare [Jumbo] (TW) */
{0x306D5F78, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Rally-X [DahJee] (TW) */
{0x29E047CC, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Road Fighter (TW) */
{0x5CBD1163, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Tank Battalion (TW) */
{0x40414556, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* The Goonies (TW) */
{0x2E7166D5, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* The Legend of Kage (TW) */
{0xC550B4F0, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* TwinBee (TW) */
{0xFC87463C, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Yie Ar Kung-Fu II (TW) */
{0xDF7CBFA5, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Pippols (TW) */
{0xE0816BB7, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Star Soldier (TW) */
{0x69FC1494, 0, 0, 0, MAPPER_RAM_8K_EXT2, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Bomberman Special (TW) */
{0xFFC4EE3F, 0, 0, 0, MAPPER_RAM_8K_EXT2, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Magical Kid Wiz (TW) */
{0x2E366CCF, 0, 0, 0, MAPPER_RAM_8K_EXT2, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* The Castle (TW) */
{0xAAAC12CF, 0, 0, 0, MAPPER_RAM_8K_EXT2, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Rally-X (TW) */
{0xD2EDD329, 0, 0, 0, MAPPER_RAM_8K_EXT2, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Road Fighter (TW) */
{0xE0816BB7, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Star Soldier [DahJee] (TW) */
/* games requiring SG-1000 II 8K RAM extension adapter (type B) */
{0x69FC1494, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Bomberman Special (TW) */
{0xFFC4EE3F, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Magical Kid Wiz (TW) */
{0x2E366CCF, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* The Castle [MSX] (TW) */
{0xAAAC12CF, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Rally-X (TW) */
{0xD2EDD329, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Road Fighter (TW) */
/* games requiring 2KB internal RAM (SG-1000 II clone hardware) */
{0x7F7F009D, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Circus Charlie (KR) */
@@ -196,6 +228,7 @@ static const rominfo_t game_list[] =
{0xC0E25D62, 0, 0, 0, MAPPER_SEGA, SYSTEM_SMS2, REGION_EUROPE}, /* California Games II */
{0x45C50294, 0, 0, 0, MAPPER_SEGA, SYSTEM_SMS2, REGION_EUROPE}, /* Jogos de Verao II (BR) */
{0xC9DBF936, 0, 0, 0, MAPPER_SEGA, SYSTEM_SMS2, REGION_EUROPE}, /* Home Alone */
{0xA109A6FE, 0, 0, 0, MAPPER_SEGA, SYSTEM_SMS2, REGION_EUROPE}, /* Power Strike II */
{0x0047B615, 0, 0, 0, MAPPER_SEGA, SYSTEM_SMS2, REGION_EUROPE}, /* Predator2 */
{0xF42E145C, 0, 0, 0, MAPPER_SEGA, SYSTEM_SMS2, REGION_EUROPE}, /* Quest for the Shaven Yak Starring Ren Hoek & Stimpy (BR) */
{0x9F951756, 0, 0, 0, MAPPER_SEGA, SYSTEM_SMS2, REGION_EUROPE}, /* RoboCop 3 */
@@ -210,9 +243,7 @@ static const rominfo_t game_list[] =
/* games running in Game Gear MS compatibility mode */
{0x59840FD6, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Castle of Illusion - Starring Mickey Mouse [SMS-GG] */
{0x9C76FB3A, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Rastan Saga [SMS-GG] */
{0xC8381DEF, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Taito Chase H.Q [SMS-GG] */
{0xDA8E95A9, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* WWF Wrestlemania Steel Cage Challenge [SMS-GG] */
{0xCC521975, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Cave Dude [Proto] [SMS-GG] */
{0x1D93246E, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Olympic Gold [A][SMS-GG] */
{0xA2F9C7AF, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Olympic Gold [B][SMS-GG] */
{0x01EAB89D, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Out Run Europa [SMS-GG] */
@@ -222,10 +253,39 @@ static const rominfo_t game_list[] =
{0x45F058D6, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Prince of Persia [B][SMS-GG] */
{0x56201996, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* R.C. Grand Prix [SMS-GG] */
{0x10DBBEF4, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Super Kick Off [SMS-GG] */
{0x9942B69B, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Castle of Illusion - Starring Mickey Mouse (J) [SMS-GG] */
{0x7BB81E3D, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Taito Chase H.Q (J) [SMS-GG] */
{0xC8381DEF, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* Taito Chase H.Q [SMS-GG] */
{0xDA8E95A9, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_USA}, /* WWF Wrestlemania Steel Cage Challenge [SMS-GG] */
{0x6630E5FD, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Aerial Assault (TW) [SMS-GG] */
{0x6F8E46CF, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Alex Kidd in Miracle World (TW) [SMS-GG] */
{0x5E4B454E, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Argos no Juujiken (TW) [SMS-GG] */
{0x98F64975, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Black Belt (TW) [SMS-GG] */
{0x9942B69B, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Castle of Illusion - Starring Mickey Mouse (J) [SMS-GG] */
{0x55F929CE, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Choplifter (TW) [SMS-GG] */
{0xAD9FF469, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Cyber Shinobi, The (TW) [SMS-GG] */
{0xFB163003, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Doki Doki Penguin Land - Uchuu-Daibouken (TW) [SMS-GG] */
{0xF4F848C2, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Double Dragon (TW) [SMS-GG] */
{0x96E16FE4, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* E-SWAT [v1] (TW) [SMS-GG] */
{0xB948752E, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Final Bubble Bobble (TW) [SMS-GG] */
{0x44136A72, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Forgotten Worlds (TW) [SMS-GG] */
{0x6FE448A5, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Great Basketball (TW) [SMS-GG] */
{0xB6207F0D, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Hokuto no Ken (TW) [SMS-GG] */
{0x4762E022, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Kung Fu Kid (TW) [SMS-GG] */
{0x7EAED675, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Lord of Sword (TW) [SMS-GG] */
{0x3382D73F, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Olympic Gold (TW) [SMS-GG] */
{0x354BEE78, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Paperboy [v1] (TW) [SMS-GG] */
{0xCAFD2D83, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Prince of Persia (TW) [SMS-GG] */
{0xCACDF759, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Quartet (TW) [SMS-GG] */
{0xE532716F, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* R-Type (TW) [SMS-GG] */
{0x9C76FB3A, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Rastan Saga (J) [SMS-GG] */
{0x7D59283B, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Scramble Spirits (TW) [SMS-GG] */
{0x89EFCC22, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Secret Command (TW) [SMS-GG] */
{0xD0263024, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Seishun Scandal (TW) [SMS-GG] */
{0xAB67C6BD, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Shadow Dancer - The Secret Of Shinobi (TW) [SMS-GG] */
{0xAC2EA669, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Shadow of the Beast (TW) [SMS-GG] */
{0x63A7F906, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Strider (TW) [SMS-GG] */
{0xD282EF71, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Submarine Attack (TW) [SMS-GG] */
{0x7BB81E3D, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Taito Chase H.Q (J) [SMS-GG] */
{0x98CF1254, 0, 0, 0, MAPPER_SEGA, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Thunder Blade (TW) [SMS-GG] */
/* games requiring 3-D Glasses */
{0x6BD5C2BF, 1, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Space Harrier 3-D */
@@ -237,12 +297,15 @@ static const rominfo_t game_list[] =
{0xA3EF13CB, 1, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Zaxxon 3-D */
{0xBBA74147, 1, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Zaxxon 3-D [Proto] */
{0xD6F43DDA, 1, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Out Run 3-D */
{0x4E684EC0, 1, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Out Run 3-D [Proto] */
{0x871562b0, 1, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Maze Walker */
{0x156948f9, 1, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Space Harrier 3-D (J) */
/* games requiring 3-D Glasses & Sega Light Phaser */
{0xFBE5CFBB, 1, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Missile Defense 3D */
{0xE79BB689, 1, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Missile Defense 3D [BIOS] */
{0x43DEF05D, 1, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Missile Defense 3D [Proto] */
{0x56DCB2D4, 1, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* 3D Gunner [Proto] */
/* games requiring Sega Light Phaser */
{0x861B6E79, 0, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, SYSTEM_SMS, REGION_USA}, /* Assault City [Light Phaser] */
@@ -337,6 +400,8 @@ static const rominfo_t game_list[] =
{0x56BD2455, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Doki Doki Penguin Land - Uchuu-Daibouken [Proto] */
{0xC722FB42, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Fantasy Zone II (J) */
{0x7ABC70E9, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Family Games (Party Games) */
{0x9AFAB511, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game De Check! Koutsuu Anzen [Proto] (JP) */
{0x9E9DEB18, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game De Check! Koutsuu Anzen [Proto] (JP) [T-Eng] */
{0x6586BD1F, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Masters Golf */
{0x4847BC91, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Masters Golf [Proto] */
{0xB9FDF6D9, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Haja no Fuuin */
@@ -349,6 +414,8 @@ static const rominfo_t game_list[] =
{0x5B5F9106, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nekyuu Kousien */
{0xBEA27D5C, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Opa Opa */
{0x6605D36A, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Phantasy Star (J) */
{0x70E89681, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Phantasy Star (J) [T-Eng v1.02] */
{0xA04CF71A, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Phantasy Star (J) [T-Eng v2.00] */
{0xE1FFF1BB, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Shinobi (J) */
{0x11645549, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Solomon no Kagi - Oujo Rihita no Namida */
{0x7E0EF8CB, 0, 1, 0, MAPPER_SEGA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Racing */
@@ -384,13 +451,19 @@ static void write_mapper_korea_8k(unsigned int address, unsigned char data);
static void write_mapper_korea_16k(unsigned int address, unsigned char data);
static void write_mapper_msx(unsigned int address, unsigned char data);
static void write_mapper_multi_16k(unsigned int address, unsigned char data);
static void write_mapper_multi_2x16k_v1(unsigned int address, unsigned char data);
static void write_mapper_multi_2x16k_v2(unsigned int address, unsigned char data);
static void write_mapper_multi_32k_16k(unsigned int address, unsigned char data);
static void write_mapper_multi_32k(unsigned int address, unsigned char data);
static void write_mapper_multi_8k(unsigned int address, unsigned char data);
static void write_mapper_multi_4x8k(unsigned int address, unsigned char data);
static void write_mapper_93c46(unsigned int address, unsigned char data);
static void write_mapper_terebi(unsigned int address, unsigned char data);
static unsigned char read_mapper_93c46(unsigned int address);
static unsigned char read_mapper_terebi(unsigned int address);
static unsigned char read_mapper_korea_8k(unsigned int address);
static unsigned char read_mapper_default(unsigned int address);
static unsigned char read_mapper_none(unsigned int address);
void sms_cart_init(void)
{
@@ -571,6 +644,8 @@ void sms_cart_reset(void)
case MAPPER_KOREA_8K:
case MAPPER_MSX:
case MAPPER_MSX_NEMESIS:
case MAPPER_MULTI_4x8K:
case MAPPER_MULTI_8K:
cart_rom.fcr[0] = 0;
cart_rom.fcr[1] = 0;
cart_rom.fcr[2] = 0;
@@ -609,9 +684,6 @@ void sms_cart_reset(void)
}
}
/* reset Memory Control register (RAM & I/O are enabled, either BIOS or Cartridge ROM are enabled) */
io_reg[0x0E] = bios_rom.pages ? 0xE0 : 0xA8;
/* reset Z80 memory map */
mapper_reset();
@@ -694,6 +766,24 @@ void sms_cart_switch(uint8 mode)
}
}
int sms_cart_ram_size(void)
{
if ((cart_rom.mapper == MAPPER_RAM_8K) || (cart_rom.mapper == MAPPER_RAM_8K_EXT1))
{
/* 8KB on-board RAM */
return 0x2000;
}
if (cart_rom.mapper == MAPPER_RAM_2K)
{
/* 2KB on-board RAM */
return 0x800;
}
/* no on-board RAM by default */
return 0;
}
int sms_cart_region_detect(void)
{
int i = sizeof(game_list) / sizeof(rominfo_t) - 1;
@@ -718,10 +808,21 @@ int sms_cart_region_detect(void)
while(i--);
/* Mark-III hardware */
if (system_hw == SYSTEM_MARKIII)
if (config.system == SYSTEM_MARKIII)
{
/* Japan */
return REGION_JAPAN_NTSC;
/* Japan only */
region_code = REGION_JAPAN_NTSC;
}
/* Master System / Game Gear ROM file */
if (system_hw >= SYSTEM_SMS)
{
/* missing header or valid header with Japan region code */
if (!rominfo.country[0] || !memcmp(rominfo.country,"SMS Japan",9) || !memcmp(rominfo.country,"GG Japan",8))
{
/* assume Japan region (fixes BIOS support) */
return REGION_JAPAN_NTSC;
}
}
/* default region */
@@ -731,14 +832,98 @@ int sms_cart_region_detect(void)
int sms_cart_context_save(uint8 *state)
{
int bufferptr = 0;
save_param(slot.fcr, 4);
/* check if cartridge ROM is disabled */
if (io_reg[0x0E] & 0x40)
{
/* save Boot ROM mapper settings */
save_param(bios_rom.fcr, 4);
}
else
{
/* save cartridge mapper settings */
save_param(cart_rom.fcr, 4);
}
/* support for SG-1000 games with extra RAM */
if ((cart_rom.mapper == MAPPER_RAM_8K) || (cart_rom.mapper == MAPPER_RAM_8K_EXT1))
{
/* 8KB extra RAM */
save_param(work_ram + 0x2000, 0x2000);
}
else if (cart_rom.mapper == MAPPER_RAM_2K)
{
/* 2KB extra RAM */
save_param(work_ram + 0x2000, 0x800);
}
return bufferptr;
}
int sms_cart_context_load(uint8 *state)
{
int bufferptr = 0;
load_param(slot.fcr, 4);
/* check if cartridge ROM is disabled */
if (io_reg[0x0E] & 0x40)
{
/* load Boot ROM mapper settings */
load_param(bios_rom.fcr, 4);
/* set default cartridge ROM paging */
switch (cart_rom.mapper)
{
case MAPPER_SEGA:
case MAPPER_SEGA_X:
cart_rom.fcr[0] = 0;
cart_rom.fcr[1] = 0;
cart_rom.fcr[2] = 1;
cart_rom.fcr[3] = 2;
break;
case MAPPER_KOREA_8K:
case MAPPER_MSX:
case MAPPER_MSX_NEMESIS:
case MAPPER_MULTI_4x8K:
case MAPPER_MULTI_8K:
cart_rom.fcr[0] = 0;
cart_rom.fcr[1] = 0;
cart_rom.fcr[2] = 0;
cart_rom.fcr[3] = 0;
break;
default:
cart_rom.fcr[0] = 0;
cart_rom.fcr[1] = 0;
cart_rom.fcr[2] = 1;
cart_rom.fcr[3] = 0;
break;
}
}
else
{
/* load cartridge mapper settings */
load_param(cart_rom.fcr, 4);
/* set default BIOS ROM paging (SEGA mapper by default) */
bios_rom.fcr[0] = 0;
bios_rom.fcr[1] = 0;
bios_rom.fcr[2] = 1;
bios_rom.fcr[3] = 2;
}
/* support for SG-1000 games with extra RAM */
if ((cart_rom.mapper == MAPPER_RAM_8K) || (cart_rom.mapper == MAPPER_RAM_8K_EXT1))
{
/* 8KB extra RAM */
load_param(work_ram + 0x2000, 0x2000);
}
else if (cart_rom.mapper == MAPPER_RAM_2K)
{
/* 2KB extra RAM */
load_param(work_ram + 0x2000, 0x800);
}
return bufferptr;
}
@@ -747,13 +932,13 @@ static void mapper_reset(void)
int i;
/* reset $C000-$FFFF mapping */
if (cart_rom.mapper == MAPPER_RAM_8K_EXT2)
if (system_hw == SYSTEM_SG)
{
/* 8KB RAM extension adapter (type B) */
/* original SG-1000 hardware has only 1KB internal RAM */
for (i = 0x30; i < 0x40; i++)
{
/* $C000-$FFFF mapped to 8KB external RAM (mirrored) */
z80_readmap[i] = z80_writemap[i] = &work_ram[(i & 0x07) << 10];
/* $C000-$FFFF mapped to 1KB internal RAM (mirrored) */
z80_readmap[i] = z80_writemap[i] = &work_ram[0];
}
}
else if (system_hw == SYSTEM_SGII)
@@ -765,18 +950,9 @@ static void mapper_reset(void)
z80_readmap[i] = z80_writemap[i] = &work_ram[(i & 0x01) << 10];
}
}
else if (system_hw == SYSTEM_SG)
{
/* default SG-1000 hardware has only 1KB internal RAM */
for (i = 0x30; i < 0x40; i++)
{
/* $C000-$FFFF mapped to 1KB internal RAM (mirrored) */
z80_readmap[i] = z80_writemap[i] = &work_ram[0];
}
}
else
{
/* Mark III / Master System / Game Gear hardware */
/* Mark III / Master System / Game Gear hardware or SG-1000 II hardware with 8KB RAM extension adapter (type B) */
for (i = 0x30; i < 0x40; i++)
{
/* $C000-$FFFF mapped to 8KB internal RAM (mirrored) */
@@ -795,7 +971,7 @@ static void mapper_reset(void)
}
/* set default Z80 memory handlers */
z80_readmem = read_mapper_default;
z80_readmem = read_mapper_none;
z80_writemem = write_mapper_none;
return;
}
@@ -883,7 +1059,7 @@ static void mapper_reset(void)
/* "Nemesis" mapper specific */
if (slot.mapper == MAPPER_MSX_NEMESIS)
{
/* first 8KB page is mapped to last 8KB ROM bank */
/* first 8KB page ($0000-$1FFF) is mapped to last 8KB ROM bank */
for (i = 0x00; i < 0x08; i++)
{
z80_readmap[i] = &slot.rom[(0x0f << 13) | ((i & 0x07) << 10)];
@@ -898,10 +1074,24 @@ static void mapper_reset(void)
else
{
/* 16KB pages */
mapper_16k_w(0,slot.fcr[0]);
mapper_16k_w(1,slot.fcr[1]);
mapper_16k_w(2,slot.fcr[2]);
mapper_16k_w(3,slot.fcr[3]);
if ((slot.mapper == MAPPER_MULTI_2x16K_V1) || (slot.mapper == MAPPER_MULTI_2x16K_V2))
{
mapper_16k_w(1,slot.fcr[1]);
mapper_16k_w(2,slot.fcr[2]);
}
else if (slot.mapper == MAPPER_MULTI_32K_16K)
{
mapper_16k_w(1,slot.fcr[1]);
mapper_16k_w(2,slot.fcr[2]);
mapper_16k_w(3,slot.fcr[3]);
}
else
{
mapper_16k_w(0,slot.fcr[0]);
mapper_16k_w(1,slot.fcr[1]);
mapper_16k_w(2,slot.fcr[2]);
mapper_16k_w(3,slot.fcr[3]);
}
}
}
@@ -945,11 +1135,36 @@ static void mapper_reset(void)
z80_writemem = write_mapper_multi_16k;
break;
case MAPPER_MULTI_2x16K_V1:
z80_readmem = read_mapper_default;
z80_writemem = write_mapper_multi_2x16k_v1;
break;
case MAPPER_MULTI_2x16K_V2:
z80_readmem = read_mapper_default;
z80_writemem = write_mapper_multi_2x16k_v2;
break;
case MAPPER_MULTI_32K_16K:
z80_readmem = read_mapper_default;
z80_writemem = write_mapper_multi_32k_16k;
break;
case MAPPER_MULTI_32K:
z80_readmem = read_mapper_default;
z80_writemem = write_mapper_multi_32k;
break;
case MAPPER_MULTI_8K:
z80_readmem = read_mapper_default;
z80_writemem = write_mapper_multi_8k;
break;
case MAPPER_MULTI_4x8K:
z80_readmem = read_mapper_default;
z80_writemem = write_mapper_multi_4x8k;
break;
case MAPPER_93C46:
z80_readmem = read_mapper_93c46;
z80_writemem = write_mapper_93c46;
@@ -995,6 +1210,17 @@ static void mapper_8k_w(int offset, unsigned char data)
{
z80_readmap[i] = &page[(i & 0x07) << 10];
}
/* Multi Korean mapper specific */
if (slot.mapper == MAPPER_MULTI_8K)
{
/* $2000-$3FFF is mirror of $A000-$BFFF */
for (i = 0x08; i < 0x10; i++)
{
z80_readmap[i] = z80_readmap[0x20 + i];
}
}
break;
}
@@ -1092,7 +1318,7 @@ static void mapper_16k_w(int offset, unsigned char data)
case 1: /* cartridge ROM bank (16KB) at $0000-$3FFF */
{
/* first 1KB is not fixed (CODEMASTER or MULTI mappers only) */
if ((slot.mapper == MAPPER_CODIES) || (slot.mapper == MAPPER_MULTI_16K))
if (slot.mapper >= MAPPER_CODIES)
{
z80_readmap[0] = &slot.rom[(page << 14)];
}
@@ -1135,13 +1361,66 @@ static void mapper_16k_w(int offset, unsigned char data)
}
}
}
/* Multi Korean mappers specific */
else if (slot.mapper == MAPPER_MULTI_2x16K_V1)
{
if (slot.fcr[0] != 0x01)
{
/* $8000-$BFFF is not mapped to cartridge ROM (unused area) */
for (i = 0x20; i < 0x30; i++)
{
z80_readmap[i] = cart.rom + 0x510400;
}
}
else
{
/* $8000-$9FFF is mirror of $6000-$7FFF */
for (i = 0x20; i < 0x28; i++)
{
z80_readmap[i] = z80_readmap[i - 0x08];
}
/* $A000-$BFFF is mirror of $4000-$5FFF */
for (i = 0x28; i < 0x30; i++)
{
z80_readmap[i] = z80_readmap[i - 0x18];
}
}
}
else if (slot.mapper == MAPPER_MULTI_2x16K_V2)
{
if (slot.fcr[0] != 0x03)
{
/* $8000-$BFFF is not mapped to cartridge ROM (unused area) */
for (i = 0x20; i < 0x30; i++)
{
z80_readmap[i] = cart.rom + 0x510400;
}
}
else
{
/* $8000-$9FFF is mirror of $6000-$7FFF */
for (i = 0x20; i < 0x28; i++)
{
z80_readmap[i] = z80_readmap[i - 0x08];
}
/* $A000-$BFFF is mirror of $4000-$5FFF */
for (i = 0x28; i < 0x30; i++)
{
z80_readmap[i] = z80_readmap[i - 0x18];
}
}
}
break;
}
case 3: /* cartridge ROM bank (16KB) at $8000-$BFFF */
{
/* check that external RAM (16KB) is not mapped at $8000-$BFFF (SEGA mapper only) */
if ((slot.fcr[0] & 0x08)) break;
if ((slot.fcr[0] & 0x08) && (slot.mapper != MAPPER_MULTI_32K_16K)) break;
/* first 8KB */
for (i = 0x20; i < 0x28; i++)
@@ -1256,6 +1535,94 @@ static void write_mapper_multi_16k(unsigned int address, unsigned char data)
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_multi_2x16k_v1(unsigned int address, unsigned char data)
{
if (address == 0xFFFE)
{
/* save mapper configuration to unused register */
slot.fcr[0] = (data >> 5) & 0x03;
if (slot.fcr[0] & 0x02)
{
data &= 0x1e;
mapper_16k_w(1,data);
mapper_16k_w(2,data+1);
}
else
{
data &= 0x1f;
mapper_16k_w(1,0x00);
mapper_16k_w(2,data);
}
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_multi_2x16k_v2(unsigned int address, unsigned char data)
{
if (address == 0xBFFC)
{
/* save mapper configuration to unused register */
slot.fcr[0] = (data >> 6) & 0x03;
switch (slot.fcr[0])
{
case 0x00:
{
data &= 0x3e;
mapper_16k_w(1,data);
mapper_16k_w(2,data+1);
return;
}
case 0x01:
{
data &= 0x3f;
mapper_16k_w(1,data);
mapper_16k_w(2,data);
return;
}
default:
{
data &= 0x3f;
mapper_16k_w(1,0x20);
mapper_16k_w(2,data);
return;
}
}
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_multi_32k_16k(unsigned int address, unsigned char data)
{
z80_writemap[address >> 10][address & 0x03FF] = data;
address &= 0xBFEF;
if (address == 0xBFE5)
{
/* save 16K bank index to unused register */
slot.fcr[0] = (data & 0x3f) << 1;
mapper_16k_w(1,slot.fcr[0]);
mapper_16k_w(2,slot.fcr[0]+1);
mapper_16k_w(3,slot.fcr[0]+1);
}
else if (address == 0xBFEE)
{
data &= 0x1f;
mapper_16k_w(2,slot.fcr[0]+data);
}
else if (address == 0xBFEF)
{
data &= 0x1f;
mapper_16k_w(3,slot.fcr[0]+data);
}
}
static void write_mapper_multi_32k(unsigned int address, unsigned char data)
{
if (address == 0xFFFF)
@@ -1266,6 +1633,49 @@ static void write_mapper_multi_32k(unsigned int address, unsigned char data)
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_multi_8k(unsigned int address, unsigned char data)
{
if (address == 0x0000)
{
mapper_8k_w(0,data);
return;
}
if (address == 0x0100)
{
mapper_8k_w(2,data);
return;
}
if (address == 0x0200)
{
mapper_8k_w(1,data);
return;
}
if (address == 0x0300)
{
mapper_8k_w(3,data);
return;
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_multi_4x8k(unsigned int address, unsigned char data)
{
if (address == 0x2000)
{
mapper_8k_w(2,data ^ 0x1f);
mapper_8k_w(3,data ^ 0x1e);
mapper_8k_w(0,data ^ 0x1d);
mapper_8k_w(1,data ^ 0x1c);
return;
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_korea(unsigned int address, unsigned char data)
{
if (address == 0xA000)
@@ -1442,3 +1852,14 @@ static unsigned char read_mapper_default(unsigned int address)
{
return z80_readmap[address >> 10][address & 0x03FF];
}
static unsigned char read_mapper_none(unsigned int address)
{
if (address >= 0xC000)
{
return z80_readmap[address >> 10][address & 0x03FF];
}
/* return last fetched z80 instruction / data */
return z80_last_fetch;
}
+2 -1
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* SG-1000, Master System & Game Gear cartridge hardware support
*
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -47,6 +47,7 @@
extern void sms_cart_init(void);
extern void sms_cart_reset(void);
extern void sms_cart_switch(uint8 mode);
extern int sms_cart_ram_size(void);
extern int sms_cart_region_detect(void);
extern int sms_cart_context_save(uint8 *state);
extern int sms_cart_context_load(uint8 *state);
+13 -12
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Backup RAM support
*
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -59,13 +59,10 @@ T_SRAM sram;
*
* Assuming max. 64k backup RAM throughout
****************************************************************************/
void sram_init()
void sram_init(void)
{
memset(&sram, 0, sizeof (T_SRAM));
/* backup RAM data is stored above cartridge ROM area, at $800000-$80FFFF (max. 64K) */
if (cart.romsize > 0x800000) return;
sram.sram = cart.rom + 0x800000;
/* disable Backup RAM by default */
sram.detected = sram.on = sram.custom = sram.start = sram.end = 0;
/* initialize Backup RAM */
if (strstr(rominfo.international,"Sonic 1 Remastered"))
@@ -147,6 +144,13 @@ void sram_init()
sram.start = 0x400001;
sram.end = 0x40ffff;
}
else if ((rominfo.checksum == 0x0000) && (rominfo.realchecksum == 0x1f7f) && (READ_BYTE(cart.rom + 0x80000,0x1b0) == 0x52) && (READ_BYTE(cart.rom + 0x80000,0x1b1) == 0x41))
{
/* Radica - Sensible Soccer Plus edition (use bankswitching) */
sram.on = 1;
sram.start = 0x200001;
sram.end = 0x203fff;
}
else if ((strstr(rominfo.ROMType,"SF") != NULL) && (strstr(rominfo.product,"001") != NULL))
{
/* SF-001 */
@@ -214,8 +218,7 @@ unsigned int sram_read_byte(unsigned int address)
unsigned int sram_read_word(unsigned int address)
{
address &= 0xfffe;
return (sram.sram[address + 1] | (sram.sram[address] << 8));
return READ_WORD(sram.sram, address & 0xfffe);
}
void sram_write_byte(unsigned int address, unsigned int data)
@@ -225,7 +228,5 @@ void sram_write_byte(unsigned int address, unsigned int data)
void sram_write_word(unsigned int address, unsigned int data)
{
address &= 0xfffe;
sram.sram[address] = data >> 8;
sram.sram[address + 1] = data & 0xff;
WRITE_WORD(sram.sram, address & 0xfffe, data);
}
+3 -3
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Backup RAM support
*
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -47,11 +47,11 @@ typedef struct
uint32 start;
uint32 end;
uint32 crc;
uint8 *sram;
uint8 sram[0x10000];
} T_SRAM;
/* Function prototypes */
extern void sram_init();
extern void sram_init(void);
extern unsigned int sram_read_byte(unsigned int address);
extern unsigned int sram_read_word(unsigned int address);
extern void sram_write_byte(unsigned int address, unsigned int data);
+1 -4
View File
@@ -555,11 +555,8 @@ static u32 pm_io(int reg, int write, u32 d)
elprintf(EL_SVP, "ssp ROM r [%06x] %04x", CADDR,
((unsigned short *)cart.rom)[addr|((mode&0xf)<<16)]);
#endif
/*if ((signed int)ssp->pmac_read[reg] >> 16 == -1) ssp->pmac_read[reg]++;
ssp->pmac_read[reg] += 1<<16;*/
if ((signed int)(ssp->pmac[0][reg] & 0xffff) == -1) ssp->pmac[0][reg] += 1<<16;
ssp->pmac[0][reg] ++;
d = ((unsigned short *)cart.rom)[addr|((mode&0xf)<<16)];
}
else if ((mode & 0x47ff) == 0x0018) /* DRAM */
+1 -2
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* CD compatible ROM/RAM cartridge support
*
* Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -38,7 +38,6 @@
#include "shared.h"
/*--------------------------------------------------------------------------*/
/* backup RAM cartridge (max. 512KB) */
/*--------------------------------------------------------------------------*/
+3 -2
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* CD compatible ROM/RAM cartridge support
*
* Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -40,7 +40,8 @@
/* CD compatible ROM/RAM cartridge */
typedef struct
{
uint8 area[0x840080]; /* cartridge ROM/RAM area (max. 8MB ROM + 64KB backup memory + Pro Action Replay 128KB ROM / 64KB RAM + cartridge infos) */
uint8 reserved[0x80]; /* reserved for ROM cartridge infos (see md_cart.h) */
uint8 area[0x810000]; /* cartridge ROM/RAM area (max. 8MB ROM + Pro Action Replay 64KB ROM) */
uint8 boot; /* cartridge boot mode (0x00: boot from CD with ROM/RAM cartridge enabled, 0x40: boot from ROM cartridge with CD enabled) */
uint8 id; /* RAM cartridge ID (related to RAM size, 0 if disabled) */
uint8 prot; /* RAM cartridge write protection */
+53 -27
View File
@@ -1,8 +1,8 @@
/***************************************************************************************
* Genesis Plus
* CD data controller (LC89510 compatible)
* CD data controller (LC8951x compatible)
*
* Copyright (C) 2012-2015 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2019 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -51,7 +51,6 @@
/* CTRL0 register bitmasks */
#define BIT_DECEN 0x80
#define BIT_E01RQ 0x20
#define BIT_AUTORQ 0x10
#define BIT_WRRQ 0x04
@@ -60,7 +59,7 @@
#define BIT_FORMRQ 0x04
#define BIT_SHDREN 0x01
/* CTRL2 register bitmask */
/* STAT3 register bitmask */
#define BIT_VALST 0x80
/* TODO: figure exact DMA transfer rate */
@@ -248,7 +247,7 @@ void cdc_decoder_update(uint32 header)
/* data decoding enabled ? */
if (cdc.ctrl[0] & BIT_DECEN)
{
/* update HEAD registers */
/* update HEADx registers with current block header */
*(uint32 *)(cdc.head[0]) = header;
/* set !VALST */
@@ -285,18 +284,50 @@ void cdc_decoder_update(uint32 header)
/* CDC buffer address */
offset = cdc.pt.w & 0x3fff;
/* write CDD block header (4 bytes) */
/* write current block header to RAM buffer (4 bytes) */
*(uint32 *)(cdc.ram + offset) = header;
offset += 4;
/* write CDD block data (2048 bytes) */
cdd_read_data(cdc.ram + 4 + offset);
/* check decoded block mode */
if (cdc.head[0][3] == 0x01)
{
/* write Mode 1 user data to RAM buffer (2048 bytes) */
cdd_read_data(cdc.ram + offset, NULL);
offset += 2048;
}
else
{
/* check if CD-ROM Mode 2 decoding is enabled */
if (cdc.ctrl[1] & BIT_MODRQ)
{
/* update HEADx registers with current block sub-header & write Mode 2 user data to RAM buffer (max 2328 bytes) */
cdd_read_data(cdc.ram + offset + 8, cdc.head[1]);
/* write current block sub-header to RAM buffer (4 bytes x 2) */
*(uint32 *)(cdc.ram + offset) = *(uint32 *)(cdc.head[1]);
*(uint32 *)(cdc.ram + offset + 4) = *(uint32 *)(cdc.head[1]);
offset += 2336;
}
else
{
/* update HEADx registers with current block sub-header & write Mode 2 user data to RAM buffer (max 2328 bytes) */
/* NB: when Mode 2 decoding is disabled, sub-header is apparently not written to RAM buffer (required by Wonder Library) */
cdd_read_data(cdc.ram + offset, cdc.head[1]);
offset += 2328;
}
/* set STAT2 register FORM bit according to sub-header FORM bit when CTRL0 register AUTORQ bit is set */
if (cdc.ctrl[0] & BIT_AUTORQ)
{
cdc.stat[2] = (cdc.ctrl[1] & BIT_MODRQ) | ((cdc.head[1][2] & 0x20) >> 3);
}
}
/* take care of buffer overrun */
offset = offset + 2048 + 4 - 0x4000;
if (offset > 0)
if (offset > 0x4000)
{
/* data should be written at the start of buffer */
memcpy(cdc.ram, cdc.ram + 0x4000, offset);
memcpy(cdc.ram, cdc.ram + 0x4000, offset - 0x4000);
}
}
}
@@ -484,15 +515,15 @@ void cdc_reg_w(unsigned char data)
/* set CRCOK bit only if decoding is enabled */
cdc.stat[0] = data & BIT_DECEN;
/* update decoding mode */
/* update STAT2 register */
if (data & BIT_AUTORQ)
{
/* set MODE bit according to CTRL1 register & clear FORM bit */
cdc.stat[2] = cdc.ctrl[1] & BIT_MODRQ;
/* set MODE bit according to CTRL1 register MODRQ bit & set FORM bit according to sub-header FORM bit*/
cdc.stat[2] = (cdc.ctrl[1] & BIT_MODRQ) | ((cdc.head[1][2] & 0x20) >> 3);
}
else
{
/* set MODE & FORM bits according to CTRL1 register */
/* set MODE & FORM bits according to CTRL1 register MODRQ & FORMRQ bits */
cdc.stat[2] = cdc.ctrl[1] & (BIT_MODRQ | BIT_FORMRQ);
}
@@ -503,15 +534,15 @@ void cdc_reg_w(unsigned char data)
case 0x0b: /* CTRL1 */
{
/* update decoding mode */
/* update STAT2 register */
if (cdc.ctrl[0] & BIT_AUTORQ)
{
/* set MODE bit according to CTRL1 register & clear FORM bit */
cdc.stat[2] = data & BIT_MODRQ;
/* set MODE bit according to CTRL1 register MODRQ bit & set FORM bit according to sub-header FORM bit*/
cdc.stat[2] = (data & BIT_MODRQ) | ((cdc.head[1][2] & 0x20) >> 3);
}
else
{
/* set MODE & FORM bits according to CTRL1 register */
/* set MODE & FORM bits according to CTRL1 register MODRQ & FORMRQ bits */
cdc.stat[2] = data & (BIT_MODRQ | BIT_FORMRQ);
}
@@ -612,7 +643,7 @@ unsigned char cdc_reg_r(void)
/* clear pending decoder interrupt */
cdc.ifstat |= BIT_DECI;
#if 0
/* no pending data transfer end interrupt */
if ((cdc.ifstat | BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN))
@@ -639,13 +670,8 @@ unsigned short cdc_host_r(void)
/* check if data is available */
if (scd.regs[0x04>>1].byte.h & 0x40)
{
/* read data word from CDC RAM buffer */
uint16 data = *(uint16 *)(cdc.ram + (cdc.dac.w & 0x3ffe));
#ifdef LSB_FIRST
/* source data is stored in big endian format */
data = ((data >> 8) | (data << 8)) & 0xffff;
#endif
/* read 16-bit word from CDC RAM buffer (big-endian format) */
uint16 data = READ_WORD(cdc.ram, cdc.dac.w & 0x3ffe);
#ifdef LOG_CDC
error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac.w, data, cdc.dbc.w, s68k.pc);
+2 -2
View File
@@ -1,8 +1,8 @@
/***************************************************************************************
* Genesis Plus
* CD data controller (LC89510 compatible)
* CD data controller (LC8951x compatible)
*
* Copyright (C) 2012-2015 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2019 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
File diff suppressed because it is too large Load Diff
+29 -13
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* CD drive processor & CD-DA fader
*
* Copyright (C) 2012-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2023 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -54,15 +54,26 @@
#define cdd scd.cdd_hw
/* CDD status */
#define CD_BUSY 0x00
#define CD_PLAY 0x01
#define CD_SEEK 0x02
#define CD_SCAN 0x03
#define CD_PAUSE 0x04
#define CD_OPEN 0x05
#define CD_STOP 0x09
#define NO_DISC 0x0B
#define CD_END 0x0C
#define CD_STOP 0x00
#define CD_PLAY 0x01
#define CD_SEEK 0x02
#define CD_SCAN 0x03
#define CD_PAUSE 0x04
#define CD_OPEN 0x05
#define NO_VALID_CHK 0x06 /* unused */
#define NO_VALID_CMD 0x07 /* unused */
#define CD_ERROR 0x08 /* unused */
#define CD_TOC 0x09
#define CD_TRACK_MOVE 0x0A /* unused */
#define NO_DISC 0x0B
#define CD_END 0x0C
#define CD_TRAY 0x0E /* unused */
#define CD_TEST 0x0F /* unusec */
/* CD-DA digital filter types */
#define CD_TYPE_DEFAULT 0x00
#define CD_TYPE_WONDERMEGA 0x01
#define CD_TYPE_WONDERMEGA_M2 0x02
/* CD track */
typedef struct
@@ -75,6 +86,8 @@ typedef struct
int start;
int end;
int type;
int loopEnabled;
int loopOffset;
} track_t;
/* CD TOC */
@@ -103,11 +116,12 @@ typedef struct
{
uint32 cycles;
uint32 latency;
int type;
int loaded;
int index;
int lba;
int scanOffset;
int volume;
uint16 fader[2];
uint8 status;
uint16 sectorSize;
toc_t toc;
@@ -121,11 +135,13 @@ typedef struct
extern void cdd_init(int samplerate);
extern void cdd_reset(void);
extern int cdd_context_save(uint8 *state);
extern int cdd_context_load(uint8 *state);
extern int cdd_context_load(uint8 *state, char *version);
extern int cdd_load(char *filename, char *header);
extern void cdd_unload(void);
extern void cdd_read_data(uint8 *dst);
extern void cdd_read_data(uint8 *dst, uint8 *subheader);
extern void cdd_seek_audio(int index, int lba);
extern void cdd_read_audio(unsigned int samples);
extern void cdd_update_audio(unsigned int samples);
extern void cdd_update(void);
extern void cdd_process(void);
+135 -133
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* CD graphics processor
*
* Copyright (C) 2012 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -47,10 +47,10 @@ void word_ram_0_dma_w(unsigned int words)
/* CDC buffer source address */
uint16 src_index = cdc.dac.w & 0x3ffe;
/* WORD-RAM destination address*/
uint32 dst_index = (scd.regs[0x0a>>1].w << 3) & 0x1fffe;
/* update DMA destination address */
scd.regs[0x0a>>1].w += (words >> 2);
@@ -60,13 +60,8 @@ void word_ram_0_dma_w(unsigned int words)
/* DMA transfer */
while (words--)
{
/* read 16-bit word from CDC buffer */
data = *(uint16 *)(cdc.ram + src_index);
#ifdef LSB_FIRST
/* source data is stored in big endian format */
data = ((data >> 8) | (data << 8)) & 0xffff;
#endif
/* read 16-bit word from CDC RAM buffer (big-endian format) */
data = READ_WORD(cdc.ram, src_index);
/* write 16-bit word to WORD-RAM */
*(uint16 *)(scd.word_ram[0] + dst_index) = data ;
@@ -85,10 +80,10 @@ void word_ram_1_dma_w(unsigned int words)
/* CDC buffer source address */
uint16 src_index = cdc.dac.w & 0x3ffe;
/* WORD-RAM destination address*/
uint32 dst_index = ((scd.regs[0x0a>>1].w << 3) & 0x1fffe);
/* update DMA destination address */
scd.regs[0x0a>>1].w += (words >> 2);
@@ -98,13 +93,8 @@ void word_ram_1_dma_w(unsigned int words)
/* DMA transfer */
while (words--)
{
/* read 16-bit word from CDC buffer */
data = *(uint16 *)(cdc.ram + src_index);
#ifdef LSB_FIRST
/* source data is stored in big endian format */
data = ((data >> 8) | (data << 8)) & 0xffff;
#endif
/* read 16-bit word from CDC RAM buffer (big-endian format) */
data = READ_WORD(cdc.ram, src_index);
/* write 16-bit word to WORD-RAM */
*(uint16 *)(scd.word_ram[1] + dst_index) = data ;
@@ -123,10 +113,10 @@ void word_ram_2M_dma_w(unsigned int words)
/* CDC buffer source address */
uint16 src_index = cdc.dac.w & 0x3ffe;
/* WORD-RAM destination address*/
uint32 dst_index = (scd.regs[0x0a>>1].w << 3) & 0x3fffe;
/* update DMA destination address */
scd.regs[0x0a>>1].w += (words >> 2);
@@ -136,13 +126,8 @@ void word_ram_2M_dma_w(unsigned int words)
/* DMA transfer */
while (words--)
{
/* read 16-bit word from CDC buffer */
data = *(uint16 *)(cdc.ram + src_index);
#ifdef LSB_FIRST
/* source data is stored in big endian format */
data = ((data >> 8) | (data << 8)) & 0xffff;
#endif
/* read 16-bit word from CDC RAM buffer (big-endian format) */
data = READ_WORD(cdc.ram, src_index);
/* write 16-bit word to WORD-RAM */
*(uint16 *)(scd.word_ram_2M + dst_index) = data ;
@@ -475,6 +460,9 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
uint16 stamp_data;
uint32 stamp_index;
/* bits [1:0] of 32x32 pixels stamp index are masked (see Chuck Rock II - Son of Chuck) */
uint32 stamp_mask = (scd.regs[0x58>>1].byte.l & 0x02) ? 0x7fc : 0x7ff;
/* pixel map start position for current line (13.3 format converted to 13.11) */
uint32 xpos = *gfx.tracePtr++ << 8;
uint32 ypos = *gfx.tracePtr++ << 8;
@@ -517,7 +505,7 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
/* c = cell offset (0-3 for 16x16, 0-15 for 32x32) */
/* yyy = line offset (0-7) */
/* xxx = pixel offset (0-7) */
stamp_index = (stamp_data & 0x7ff) << 8;
stamp_index = (stamp_data & stamp_mask) << 8;
if (stamp_index)
{
@@ -598,132 +586,146 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
void gfx_start(unsigned int base, int cycles)
{
/* make sure 2M mode is enabled */
if (!(scd.regs[0x02>>1].byte.l & 0x04))
uint32 mask;
/* trace vector pointer */
gfx.tracePtr = (uint16 *)(scd.word_ram_2M + ((base << 2) & 0x3fff8));
/* stamps & stamp map size */
switch ((scd.regs[0x58>>1].byte.l >> 1) & 0x03)
{
uint32 mask;
/* trace vector pointer */
gfx.tracePtr = (uint16 *)(scd.word_ram_2M + ((base << 2) & 0x3fff8));
case 0:
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
gfx.mapShift = 4; /* 16x16 stamps/map */
mask = 0x3fe00; /* 512 bytes/table */
break;
/* stamps & stamp map size */
switch ((scd.regs[0x58>>1].byte.l >> 1) & 0x03)
{
case 0:
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
gfx.mapShift = 4; /* 16x16 stamps/map */
mask = 0x3fe00; /* 512 bytes/table */
break;
case 1:
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
gfx.mapShift = 3; /* 8x8 stamps/map */
mask = 0x3ff80; /* 128 bytes/table */
break;
case 1:
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
gfx.mapShift = 3; /* 8x8 stamps/map */
mask = 0x3ff80; /* 128 bytes/table */
break;
case 2:
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
gfx.mapShift = 8; /* 256x256 stamps/map */
mask = 0x20000; /* 131072 bytes/table */
break;
case 2:
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
gfx.mapShift = 8; /* 256x256 stamps/map */
mask = 0x20000; /* 131072 bytes/table */
break;
case 3:
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
gfx.mapShift = 7; /* 128x128 stamps/map */
mask = 0x38000; /* 32768 bytes/table */
break;
}
/* stamp map table base address */
gfx.mapPtr = (uint16 *)(scd.word_ram_2M + ((scd.regs[0x5a>>1].w << 2) & mask));
/* image buffer column offset (64 pixels/cell, minus 7 pixels to restart at cell beginning) */
gfx.bufferOffset = (((scd.regs[0x5c>>1].byte.l & 0x1f) + 1) << 6) - 7;
/* image buffer start index in dot units (2 pixels/byte) */
gfx.bufferStart = (scd.regs[0x5e>>1].w << 3) & 0x7ffc0;
/* add image buffer horizontal dot offset */
gfx.bufferStart += (scd.regs[0x60>>1].byte.l & 0x3f);
/* reset GFX chip cycle counter */
gfx.cycles = cycles;
/* update GFX chip timings (see AC3:Thunderhawk / Thunderstrike) */
gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w;
/* start graphics operation */
scd.regs[0x58>>1].byte.h = 0x80;
case 3:
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
gfx.mapShift = 7; /* 128x128 stamps/map */
mask = 0x38000; /* 32768 bytes/table */
break;
}
/* stamp map table base address */
gfx.mapPtr = (uint16 *)(scd.word_ram_2M + ((scd.regs[0x5a>>1].w << 2) & mask));
/* image buffer column offset (64 pixels/cell, minus 7 pixels to restart at cell beginning) */
gfx.bufferOffset = (((scd.regs[0x5c>>1].byte.l & 0x1f) + 1) << 6) - 7;
/* image buffer start index in dot units (2 pixels/byte) */
gfx.bufferStart = (scd.regs[0x5e>>1].w << 3) & 0x7ffc0;
/* add image buffer horizontal dot offset */
gfx.bufferStart += (scd.regs[0x60>>1].byte.l & 0x3f);
/* reset GFX chip cycle counter */
gfx.cycles = cycles;
/* update GFX chip timings (see AC3:Thunderhawk / Thunderstrike, Night Striker) */
/* number of Word-RAM accesses per image buffer rendered line: */
/* . 4 initial read accesses (Xposition, Yposition, Xoffset and Yoffset) */
/* . 2 read accesses per rendered pixels (stamp map + stamp pixel data) */
/* . 1 read-modify-write access per group of 4 rendered pixels */
/* each access (read or read-modify-write) takes 3 SUB-CPU cycles by default */
/* each access can be delayed by 1 to 3 CPU cycles in case of refresh or SUB-CPU access occuring on the same Word-RAM bank (not emulated) */
/* reference: https://github.com/MiSTer-devel/MegaCD_MiSTer/blob/master/docs/mcd%20logs/graphics_operations_and_68k_wordram_access.jpg */
/* TODO: figure what happen exactly when pixel offset is different from 0 */
/* for the moment, one additional read-modify-write access is assumed at the start if pixel offset is not aligned to 4 pixels */
gfx.cyclesPerLine = 4 * 3 * (4 + 2 * scd.regs[0x62>>1].w + ((scd.regs[0x62>>1].w + (scd.regs[0x60>>1].byte.l & 0x03) + 3) >> 2));
/* start graphics operation */
scd.regs[0x58>>1].byte.h = 0x80;
}
void gfx_update(int cycles)
{
/* synchronize GFX chip with SUB-CPU */
cycles -= gfx.cycles;
/* make sure SUB-CPU is ahead */
if (cycles > 0)
/* make sure Word-RAM is assigned to SUB-CPU in 2M mode */
if ((scd.regs[0x02>>1].byte.l & 0x05) != 0x01)
{
/* number of lines to process */
unsigned int lines = (cycles + gfx.cyclesPerLine - 1) / gfx.cyclesPerLine;
/* synchronize GFX processing with SUB-CPU */
cycles -= gfx.cycles;
/* check against remaining lines */
if (lines < scd.regs[0x64>>1].byte.l)
/* make sure SUB-CPU is ahead */
if (cycles > 0)
{
/* update Vdot remaining size */
scd.regs[0x64>>1].byte.l -= lines;
/* number of lines to process */
unsigned int lines = (cycles + gfx.cyclesPerLine - 1) / gfx.cyclesPerLine;
/* increment cycle counter */
gfx.cycles += lines * gfx.cyclesPerLine;
}
else
{
/* process remaining lines */
lines = scd.regs[0x64>>1].byte.l;
/* clear Vdot remaining size */
scd.regs[0x64>>1].byte.l = 0;
/* end of graphics operation */
scd.regs[0x58>>1].byte.h = 0;
/* SUB-CPU idle on register $58 polling ? */
if (s68k.stopped & (1<<0x08))
/* check against remaining lines */
if (lines < scd.regs[0x64>>1].byte.l)
{
/* sync SUB-CPU with GFX chip */
s68k.cycles = scd.cycles;
/* update Vdot remaining size */
scd.regs[0x64>>1].byte.l -= lines;
/* restart SUB-CPU */
s68k.stopped = 0;
/* increment cycle counter */
gfx.cycles += lines * gfx.cyclesPerLine;
}
else
{
/* process remaining lines */
lines = scd.regs[0x64>>1].byte.l;
/* clear Vdot remaining size */
scd.regs[0x64>>1].byte.l = 0;
/* end of graphics operation */
scd.regs[0x58>>1].byte.h = 0;
/* SUB-CPU idle on register $58 polling ? */
if (s68k.stopped & (1<<0x08))
{
/* sync SUB-CPU with GFX chip */
s68k.cycles = scd.cycles;
/* restart SUB-CPU */
s68k.stopped = 0;
#ifdef LOG_SCD
error("s68k started from %d cycles\n", s68k.cycles);
error("s68k started from %d cycles\n", s68k.cycles);
#endif
}
/* level 1 interrupt enabled ? */
if (scd.regs[0x32>>1].byte.l & 0x02)
{
/* trigger level 1 interrupt */
scd.pending |= (1 << 1);
/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
}
}
/* level 1 interrupt enabled ? */
if (scd.regs[0x32>>1].byte.l & 0x02)
/* render lines */
while (lines--)
{
/* trigger level 1 interrupt */
scd.pending |= (1 << 1);
/* process dots to image buffer */
gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w);
/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
/* increment image buffer start index for next line (8 pixels/line) */
gfx.bufferStart += 8;
}
}
/* render lines */
while (lines--)
{
/* process dots to image buffer */
gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w);
/* increment image buffer start index for next line (8 pixels/line) */
gfx.bufferStart += 8;
}
}
else
{
/* GFX processing is halted */
gfx.cycles = cycles;
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* CD graphics processor
*
* Copyright (C) 2012 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -39,7 +39,7 @@
#include <stdlib.h>
#include <string.h>
#if defined(_MSC_VER) && !defined(_XBOX)
#if defined(_MSC_VER) && !defined(_XBOX) && _MSC_VER > 1310
# include <intrin.h> /* for __cpuid() and _xgetbv() */
#endif
@@ -49,11 +49,6 @@
#ifdef DEBUG
#include <stdio.h>
#define dfprintf fprintf
#else
/* This is bad practice, it should be a static void empty function */
#define dfprintf(file, format, ...)
#endif
@@ -138,21 +133,23 @@ ia32_cpu_info (FLAC__CPUInfo *info)
info->ia32.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 ) ? true : false;
}
dfprintf(stderr, "CPU info (IA-32):\n");
dfprintf(stderr, " CMOV ....... %c\n", info->ia32.cmov ? 'Y' : 'n');
dfprintf(stderr, " MMX ........ %c\n", info->ia32.mmx ? 'Y' : 'n');
dfprintf(stderr, " SSE ........ %c\n", info->ia32.sse ? 'Y' : 'n');
dfprintf(stderr, " SSE2 ....... %c\n", info->ia32.sse2 ? 'Y' : 'n');
dfprintf(stderr, " SSE3 ....... %c\n", info->ia32.sse3 ? 'Y' : 'n');
dfprintf(stderr, " SSSE3 ...... %c\n", info->ia32.ssse3 ? 'Y' : 'n');
dfprintf(stderr, " SSE41 ...... %c\n", info->ia32.sse41 ? 'Y' : 'n');
dfprintf(stderr, " SSE42 ...... %c\n", info->ia32.sse42 ? 'Y' : 'n');
#ifdef DEBUG
fprintf(stderr, "CPU info (IA-32):\n");
fprintf(stderr, " CMOV ....... %c\n", info->ia32.cmov ? 'Y' : 'n');
fprintf(stderr, " MMX ........ %c\n", info->ia32.mmx ? 'Y' : 'n');
fprintf(stderr, " SSE ........ %c\n", info->ia32.sse ? 'Y' : 'n');
fprintf(stderr, " SSE2 ....... %c\n", info->ia32.sse2 ? 'Y' : 'n');
fprintf(stderr, " SSE3 ....... %c\n", info->ia32.sse3 ? 'Y' : 'n');
fprintf(stderr, " SSSE3 ...... %c\n", info->ia32.ssse3 ? 'Y' : 'n');
fprintf(stderr, " SSE41 ...... %c\n", info->ia32.sse41 ? 'Y' : 'n');
fprintf(stderr, " SSE42 ...... %c\n", info->ia32.sse42 ? 'Y' : 'n');
if (FLAC__HAS_X86INTRIN && FLAC__AVX_SUPPORTED) {
dfprintf(stderr, " AVX ........ %c\n", info->ia32.avx ? 'Y' : 'n');
dfprintf(stderr, " FMA ........ %c\n", info->ia32.fma ? 'Y' : 'n');
dfprintf(stderr, " AVX2 ....... %c\n", info->ia32.avx2 ? 'Y' : 'n');
fprintf(stderr, " AVX ........ %c\n", info->ia32.avx ? 'Y' : 'n');
fprintf(stderr, " FMA ........ %c\n", info->ia32.fma ? 'Y' : 'n');
fprintf(stderr, " AVX2 ....... %c\n", info->ia32.avx2 ? 'Y' : 'n');
}
#endif
/*
* now have to check for OS support of AVX instructions
@@ -164,9 +161,10 @@ ia32_cpu_info (FLAC__CPUInfo *info)
info->ia32.fma = false;
}
if (FLAC__HAS_X86INTRIN && FLAC__AVX_SUPPORTED) {
dfprintf(stderr, " AVX OS sup . %c\n", info->ia32.avx ? 'Y' : 'n');
}
#ifdef DEBUG
if (FLAC__HAS_X86INTRIN && FLAC__AVX_SUPPORTED)
fprintf(stderr, " AVX OS sup . %c\n", info->ia32.avx ? 'Y' : 'n');
#endif
#else
info->use_asm = false;
#endif
@@ -199,17 +197,20 @@ x86_64_cpu_info (FLAC__CPUInfo *info)
info->x86.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 ) ? true : false;
}
dfprintf(stderr, "CPU info (x86-64):\n");
dfprintf(stderr, " SSE3 ....... %c\n", info->x86.sse3 ? 'Y' : 'n');
dfprintf(stderr, " SSSE3 ...... %c\n", info->x86.ssse3 ? 'Y' : 'n');
dfprintf(stderr, " SSE41 ...... %c\n", info->x86.sse41 ? 'Y' : 'n');
dfprintf(stderr, " SSE42 ...... %c\n", info->x86.sse42 ? 'Y' : 'n');
#ifdef DEBUG
fprintf(stderr, "CPU info (x86-64):\n");
fprintf(stderr, " SSE3 ....... %c\n", info->x86.sse3 ? 'Y' : 'n');
fprintf(stderr, " SSSE3 ...... %c\n", info->x86.ssse3 ? 'Y' : 'n');
fprintf(stderr, " SSE41 ...... %c\n", info->x86.sse41 ? 'Y' : 'n');
fprintf(stderr, " SSE42 ...... %c\n", info->x86.sse42 ? 'Y' : 'n');
if (FLAC__AVX_SUPPORTED) {
dfprintf(stderr, " AVX ........ %c\n", info->x86.avx ? 'Y' : 'n');
dfprintf(stderr, " FMA ........ %c\n", info->x86.fma ? 'Y' : 'n');
dfprintf(stderr, " AVX2 ....... %c\n", info->x86.avx2 ? 'Y' : 'n');
if (FLAC__AVX_SUPPORTED)
{
fprintf(stderr, " AVX ........ %c\n", info->x86.avx ? 'Y' : 'n');
fprintf(stderr, " FMA ........ %c\n", info->x86.fma ? 'Y' : 'n');
fprintf(stderr, " AVX2 ....... %c\n", info->x86.avx2 ? 'Y' : 'n');
}
#endif
/*
* now have to check for OS support of AVX instructions
@@ -221,9 +222,10 @@ x86_64_cpu_info (FLAC__CPUInfo *info)
info->x86.fma = false;
}
if (FLAC__AVX_SUPPORTED) {
dfprintf(stderr, " AVX OS sup . %c\n", info->x86.avx ? 'Y' : 'n');
}
#ifdef DEBUG
if (FLAC__AVX_SUPPORTED)
fprintf(stderr, " AVX OS sup . %c\n", info->x86.avx ? 'Y' : 'n');
#endif
#else
/* Silence compiler warnings. */
(void) info;
@@ -38,7 +38,7 @@
#include "share/compat.h"
#if defined(_MSC_VER) && !defined(_XBOX)
#if defined(_MSC_VER) && !defined(_XBOX) && _MSC_VER > 1310
#include <intrin.h> /* for _BitScanReverse* */
#endif
@@ -49,11 +49,11 @@
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
#include <sys/types.h> /* for off_t */
#define FLAC__off_t __int64 /* use this instead of off_t to fix the 2 GB limit */
#if !defined __MINGW32__
#if !defined __MINGW32__ && _MSC_VER && _MSC_VER > 1310
#define fseeko _fseeki64
#define ftello _ftelli64
#else /* MinGW */
#if !defined(HAVE_FSEEKO)
#if !defined(HAVE_FSEEKO) && !defined(__MINGW64_VERSION_MAJOR)
#define fseeko fseeko64
#define ftello ftello64
#endif
+46 -17
View File
@@ -201,6 +201,7 @@ typedef struct _zlib_allocator zlib_allocator;
struct _zlib_allocator
{
UINT32 * allocptr[MAX_ZLIB_ALLOCS];
UINT32 * allocptr2[MAX_ZLIB_ALLOCS];
};
typedef struct _zlib_codec_data zlib_codec_data;
@@ -220,10 +221,11 @@ struct _lzma_allocator
void (*Free)(void *p, void *address); /* address can be 0 */
void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
uint32_t* allocptr[MAX_LZMA_ALLOCS];
uint32_t* allocptr2[MAX_LZMA_ALLOCS];
};
typedef struct _lzma_codec_data lzma_codec_data;
struct _lzma_codec_data
struct _lzma_codec_data
{
CLzmaDec decoder;
lzma_allocator allocator;
@@ -375,6 +377,7 @@ void lzma_allocator_init(void* p)
/* reset pointer list */
memset(codec->allocptr, 0, sizeof(codec->allocptr));
memset(codec->allocptr2, 0, sizeof(codec->allocptr2));
codec->Alloc = lzma_fast_alloc;
codec->Free = lzma_fast_free;
}
@@ -403,11 +406,16 @@ void lzma_allocator_free(void* p )
*-------------------------------------------------
*/
/* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
#define LZMA_MIN_ALIGNMENT_BITS 512
#define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
void *lzma_fast_alloc(void *p, size_t size)
{
int scan;
uint32_t *addr;
uint32_t *addr = NULL;
lzma_allocator *codec = (lzma_allocator *)(p);
uintptr_t vaddr = 0;
/* compute the size, rounding to the nearest 1k */
size = (size + 0x3ff) & ~0x3ff;
@@ -420,28 +428,37 @@ void *lzma_fast_alloc(void *p, size_t size)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
/* return aligned address of the block */
return codec->allocptr2[scan];
}
}
/* alloc a new one and put it into the list */
addr = (uint32_t *)malloc(sizeof(uint8_t) * (size + sizeof(uint32_t)));
addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
if (addr==NULL)
return NULL;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (codec->allocptr[scan] == NULL)
{
/* store block address */
codec->allocptr[scan] = addr;
/* compute aligned address, store it */
vaddr = (uintptr_t)addr;
vaddr = (vaddr + sizeof(uint32_t) + (LZMA_MIN_ALIGNMENT_BYTES-1)) & (~(LZMA_MIN_ALIGNMENT_BYTES-1));
codec->allocptr2[scan] = (uint32_t*)vaddr;
break;
}
}
/* set the low bit of the size so we don't match next time */
*addr = size | 1;
return addr + 1;
}
/* return aligned address */
return (void*)vaddr;
}
/*-------------------------------------------------
* lzma_fast_free - fast free for lzma, which
@@ -452,21 +469,22 @@ void *lzma_fast_alloc(void *p, size_t size)
void lzma_fast_free(void *p, void *address)
{
int scan;
uint32_t *ptr;
lzma_allocator *codec;
uint32_t *ptr = NULL;
lzma_allocator *codec = NULL;
if (address == NULL)
return;
codec = (lzma_allocator *)(p);
/* find the hunk */
ptr = (uint32_t *)(address) - 1;
ptr = (uint32_t *)address;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (ptr == codec->allocptr[scan])
if (ptr == codec->allocptr2[scan])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
*codec->allocptr[scan] &= ~1;
return;
}
}
@@ -2458,9 +2476,14 @@ static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t
allocates and frees memory frequently
-------------------------------------------------*/
/* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
#define ZLIB_MIN_ALIGNMENT_BITS 512
#define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
uintptr_t paddr = 0;
UINT32 *ptr;
int i;
@@ -2475,12 +2498,14 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
/* return aligned block address */
return (voidpf)(alloc->allocptr2[i]);
}
}
/* alloc a new one */
ptr = (UINT32 *)malloc(size + sizeof(UINT32));
ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
if (!ptr)
return NULL;
@@ -2489,12 +2514,16 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
if (!alloc->allocptr[i])
{
alloc->allocptr[i] = ptr;
paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
alloc->allocptr2[i] = (uint32_t*)paddr;
break;
}
/* set the low bit of the size so we don't match next time */
*ptr = size | 1;
return ptr + 1;
/* return aligned block address */
return (voidpf)paddr;
}
@@ -2506,15 +2535,15 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
static void zlib_fast_free(voidpf opaque, voidpf address)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
UINT32 *ptr = (UINT32 *)address - 1;
UINT32 *ptr = (UINT32 *)address;
int i;
/* find the hunk */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (ptr == alloc->allocptr[i])
if (ptr == alloc->allocptr2[i])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
*(alloc->allocptr[i]) &= ~1;
return;
}
}
+11 -7
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* PCM sound chip (315-5476A) (RF5C164 compatible)
*
* Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -183,7 +183,11 @@ void pcm_run(unsigned int length)
if (r < -32768) r = -32768;
else if (r > 32767) r = 32767;
/* update Blip Buffer */
/* PCM output mixing level (0-100%) */
l = (l * config.pcm_volume) / 100;
r = (r * config.pcm_volume) / 100;
/* update blip buffer */
blip_add_delta_fast(snd.blips[1], i, l-prev_l, r-prev_r);
prev_l = l;
prev_r = r;
@@ -226,10 +230,10 @@ void pcm_update(unsigned int samples)
pcm.cycles = 0;
}
void pcm_write(unsigned int address, unsigned char data)
void pcm_write(unsigned int address, unsigned char data, unsigned int cycles)
{
/* synchronize PCM chip with SUB-CPU */
int clocks = s68k.cycles - pcm.cycles;
/* synchronize PCM chip with CPU */
int clocks = cycles - pcm.cycles;
if (clocks > 0)
{
/* number of internal clocks (samples) to run */
@@ -350,10 +354,10 @@ void pcm_write(unsigned int address, unsigned char data)
}
}
unsigned char pcm_read(unsigned int address)
unsigned char pcm_read(unsigned int address, unsigned int cycles)
{
/* synchronize PCM chip with SUB-CPU */
int clocks = s68k.cycles - pcm.cycles;
int clocks = cycles - pcm.cycles;
if (clocks > 0)
{
/* number of internal clocks (samples) to run */
+3 -3
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* PCM sound chip (315-5476A) (RF5C164 compatible)
*
* Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -70,8 +70,8 @@ extern void pcm_reset(void);
extern int pcm_context_save(uint8 *state);
extern int pcm_context_load(uint8 *state);
extern void pcm_update(unsigned int samples);
extern void pcm_write(unsigned int address, unsigned char data);
extern unsigned char pcm_read(unsigned int address);
extern void pcm_write(unsigned int address, unsigned char data, unsigned int cycles);
extern unsigned char pcm_read(unsigned int address, unsigned int cycles);
extern void pcm_ram_dma_w(unsigned int words);
#endif
+176 -99
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Mega CD / Sega CD hardware
*
* Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -101,13 +101,8 @@ void prg_ram_dma_w(unsigned int words)
/* DMA transfer */
while (words--)
{
/* read 16-bit word from CDC buffer */
data = *(uint16 *)(cdc.ram + src_index);
#ifdef LSB_FIRST
/* source data is stored in big endian format */
data = ((data >> 8) | (data << 8)) & 0xffff;
#endif
/* read 16-bit word from CDC RAM buffer (big-endian format) */
data = READ_WORD(cdc.ram, src_index);
/* write 16-bit word to PRG-RAM */
*(uint16 *)(scd.prg_ram + dst_index) = data ;
@@ -255,7 +250,7 @@ static void word_ram_z80_write_byte(unsigned int address, unsigned int data)
}
else
{
WRITE_BYTE(m68k.memory_map[offset].base, address & 0xffff, data);
*(uint16 *)(m68k.memory_map[offset].base + (address & 0xfffe)) = data | (data << 8);
}
}
@@ -293,7 +288,7 @@ static void word_ram_m68k_write_byte(unsigned int address, unsigned int data)
}
else
{
WRITE_BYTE(m68k.memory_map[offset].base, address & 0xffff, data);
*(uint16 *)(m68k.memory_map[offset].base + (address & 0xfffe)) = data | (data << 8);
}
}
@@ -345,7 +340,7 @@ static void word_ram_s68k_write_byte(unsigned int address, unsigned int data)
}
else
{
WRITE_BYTE(s68k.memory_map[offset].base, address & 0xffff, data);
*(uint16 *)(s68k.memory_map[offset].base + (address & 0xfffe)) = data | (data << 8);
}
}
@@ -445,10 +440,16 @@ static void s68k_poll_sync(unsigned int reg_mask)
/* relative MAIN-CPU cycle counter */
unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE;
/* sync MAIN-CPU with SUB-CPU */
if (!m68k.stopped)
{
/* save current MAIN-CPU end cycle count (recursive execution is possible) */
int end_cycle = m68k.cycle_end;
/* sync MAIN-CPU with SUB-CPU */
m68k_run(cycles);
/* restore MAIN-CPU end cycle count */
m68k.cycle_end = end_cycle;
}
/* MAIN-CPU idle on register polling ? */
@@ -481,7 +482,7 @@ static unsigned int scd_read_byte(unsigned int address)
/* get /LDS only */
if (address & 1)
{
return pcm_read((address >> 1) & 0x1fff);
return pcm_read((address >> 1) & 0x1fff, s68k.cycles);
}
return s68k_read_bus_8(address);
@@ -547,7 +548,7 @@ static unsigned int scd_read_byte(unsigned int address)
}
/* Font data */
if ((address >= 0x50) && (address <= 0x56))
if ((address >= 0x50) && (address <= 0x57))
{
/* shifted 4-bit input (xxxx00) */
uint8 bits = (scd.regs[0x4e>>1].w >> (((address & 6) ^ 6) << 1)) << 2;
@@ -600,7 +601,7 @@ static unsigned int scd_read_word(unsigned int address)
if (!(address & 0x8000))
{
/* get /LDS only */
return pcm_read((address >> 1) & 0x1fff);
return pcm_read((address >> 1) & 0x1fff, s68k.cycles);
}
#ifdef LOG_SCD
@@ -669,8 +670,14 @@ static unsigned int scd_read_word(unsigned int address)
/* relative MAIN-CPU cycle counter */
unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE;
/* save current MAIN-CPU end cycle count (recursive execution is possible) */
int end_cycle = m68k.cycle_end;
/* sync MAIN-CPU with SUB-CPU (Mighty Morphin Power Rangers) */
m68k_run(cycles);
/* restore MAIN-CPU end cycle count */
m68k.cycle_end = end_cycle;
}
s68k_poll_detect(3 << (address & 0x1e));
@@ -757,7 +764,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
/* get /LDS only */
if (address & 1)
{
pcm_write((address >> 1) & 0x1fff, data);
pcm_write((address >> 1) & 0x1fff, data, s68k.cycles);
return;
}
@@ -781,7 +788,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
case 0x01: /* RESET status */
{
/* RESET bit cleared ? */
/* RESET bit cleared ? */
if (!(data & 0x01))
{
/* reset CD hardware */
@@ -791,6 +798,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
}
case 0x03: /* Memory Mode */
case 0x02: /* !LDS and !UDS are ignored (verified on real hardware, cf. Krikzz's mcd-verificator) */
{
s68k_poll_sync(1<<0x03);
@@ -924,6 +932,13 @@ static void scd_write_byte(unsigned int address, unsigned int data)
/* RET bit set in 2M mode */
if (data & 0x01)
{
/* check if graphics operation is running */
if (scd.regs[0x58>>1].byte.h & 0x80)
{
/* synchronize GFX processing with SUB-CPU */
gfx_update(s68k.cycles);
}
/* Word-RAM is returned to MAIN-CPU */
scd.dmna = 0;
@@ -945,8 +960,8 @@ static void scd_write_byte(unsigned int address, unsigned int data)
return;
}
case 0x0e: /* SUB-CPU communication flags */
case 0x0f: /* !LWR is ignored (Space Ace, Dragon's Lair) */
case 0x0f: /* SUB-CPU communication flags */
case 0x0e: /* !LDS and !UDS are ignored (verified on real hardware, cf. Krikzz's mcd-verificator, Space Ace, Dragon's Lair) */
{
s68k_poll_sync(1<<0x0f);
scd.regs[0x0f>>1].byte.l = data;
@@ -954,6 +969,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
}
case 0x31: /* Timer */
case 0x30: /* !LDS and !UDS are ignored (verified on real hardware, cf. Krikzz's mcd-verificator) */
{
/* reload timer (one timer clock = 384 CPU cycles) */
scd.timer = data * TIMERS_SCYCLES_RATIO;
@@ -985,26 +1001,11 @@ static void scd_write_byte(unsigned int address, unsigned int data)
return;
}
case 0x37: /* CDD control (controlled by BIOS, byte access only ?) */
case 0x4d: /* Font Color */
case 0x4c: /* !LDS and !UDS are ignored (verified on real hardware, cf. Krikzz's mcd-verificator) */
{
/* CDD communication started ? */
if ((data & 0x04) && !(scd.regs[0x37>>1].byte.l & 0x04))
{
/* reset CDD cycle counter */
cdd.cycles = (scd.cycles - s68k.cycles) * 3;
/* set pending interrupt level 4 */
scd.pending |= (1 << 4);
/* update IRQ level if interrupt is enabled */
if (scd.regs[0x32>>1].byte.l & 0x10)
{
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
}
}
scd.regs[0x37>>1].byte.l = data;
return;
scd.regs[0x4c>>1].byte.l = data;
break;
}
default:
@@ -1043,7 +1044,7 @@ static void scd_write_word(unsigned int address, unsigned int data)
if (!(address & 0x8000))
{
/* get /LDS only */
pcm_write((address >> 1) & 0x1fff, data);
pcm_write((address >> 1) & 0x1fff, data & 0xff, s68k.cycles);
return;
}
@@ -1059,7 +1060,7 @@ static void scd_write_word(unsigned int address, unsigned int data)
/* only update LED status (register $00 is reserved for MAIN-CPU, use $06 instead) */
scd.regs[0x06>>1].byte.h = data >> 8;
/* RESET bit cleared ? */
/* RESET bit cleared ? */
if (!(data & 0x01))
{
/* reset CD hardware */
@@ -1202,6 +1203,13 @@ static void scd_write_word(unsigned int address, unsigned int data)
/* RET bit set in 2M mode */
if (data & 0x01)
{
/* check if graphics operation is running */
if (scd.regs[0x58>>1].byte.h & 0x80)
{
/* synchronize GFX processing with SUB-CPU */
gfx_update(s68k.cycles);
}
/* Word-RAM is returned to MAIN-CPU */
scd.dmna = 0;
@@ -1281,6 +1289,53 @@ static void scd_write_word(unsigned int address, unsigned int data)
return;
}
case 0x34: /* CD Fader */
{
/* Wondermega hardware (CXD2554M digital filter) */
if (cdd.type == CD_TYPE_WONDERMEGA)
{
/* only MSB is latched by CXD2554M chip, LSB is ignored (8-bit digital filter) */
/* attenuator data is 7-bit only (bits 0-7) */
data = (data >> 8) & 0x7f;
/* scale CXD2554M volume (0-127) to full (LC7883KM compatible) volume range (0-1024) */
cdd.fader[1] = (1024 * data) / 127 ;
}
/* Wondermega M2 / X'Eye hardware (SM5841A digital filter) */
else if (cdd.type == CD_TYPE_WONDERMEGA_M2)
{
/* only MSB is latched by SM5841A chip, LSB is ignored (8-bit digital filter) */
data = data >> 8;
/* attenuator data is set only when command bit (bit 0) is cleared (other commands are ignored) */
if (data & 0x01) return;
/* attenuator data is 7-bit only (bits 8-1) and reverted (bit 1 = msb) */
/* bit reversing formula taken from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits */
data = (((((data * 0x0802) & 0x22110) | ((data * 0x8020) & 0x88440)) * 0x10101) >> 16) & 0x7f;
/* convert & scale SM5841A attenuation (127-0) to full (LC7883KM compatible) volume range (0-1024) */
cdd.fader[1] = (1024 * (127 - data)) / 127 ;
}
/* default CD hardware (LC7883KM digital filter) */
else
{
/* get LC7883KM volume data (12-bit) */
cdd.fader[1] = data >> 4 ;
}
return;
}
case 0x36: /* CDD control */
{
/* only bit 2 is writable (bits [1:0] forced to 0 by default) */
scd.regs[0x37>>1].byte.l = data & 0x04;
return;
}
case 0x4a: /* CDD command 9 (controlled by BIOS, word access only ?) */
{
scd.regs[0x4a>>1].w = 0;
@@ -1532,7 +1587,6 @@ void scd_init(void)
void scd_reset(int hard)
{
/* TODO: figure what exactly is resetted when RESET bit is cleared by SUB-CPU */
if (hard)
{
/* Clear all ASIC registers by default */
@@ -1542,7 +1596,6 @@ void scd_reset(int hard)
scd.dmna = 0;
/* H-INT default vector */
*(uint16 *)(m68k.memory_map[scd.cartridge.boot].base + 0x70) = 0x00FF;
*(uint16 *)(m68k.memory_map[scd.cartridge.boot].base + 0x72) = 0xFFFF;
/* Power ON initial values (MAIN-CPU side) */
@@ -1574,11 +1627,17 @@ void scd_reset(int hard)
s68k.cycles = 0;
s68k_pulse_reset();
s68k_pulse_halt();
/* Reset frame cycle counter */
scd.cycles = 0;
}
else
{
/* Clear only SUB-CPU side registers */
memset(&scd.regs[0x04>>1], 0, sizeof(scd.regs) - 4);
/* TODO: figure what exactly is reset when RESET bit is cleared by SUB-CPU */
/* Clear only SUB-CPU side registers (communication registers are not cleared, see msu-md-sample.bin) */
scd.regs[0x04>>1].w = 0x0000;
scd.regs[0x0c>>1].w = 0x0000;
memset(&scd.regs[0x30>>1], 0, sizeof(scd.regs) - 0x30);
}
/* SUB-CPU side default values */
@@ -1597,10 +1656,7 @@ void scd_reset(int hard)
/* Reset Timer & Stopwatch counters */
scd.timer = 0;
scd.stopwatch = 0;
/* Reset frame cycle counter */
scd.cycles = 0;
scd.stopwatch = s68k.cycles;
/* Clear pending interrupts */
scd.pending = 0;
@@ -1609,6 +1665,9 @@ void scd_reset(int hard)
memset(&m68k.poll, 0, sizeof(m68k.poll));
memset(&s68k.poll, 0, sizeof(s68k.poll));
/* reset CDD cycle counter */
cdd.cycles = (scd.cycles - s68k.cycles) * 3;
/* Reset CD hardware */
cdd_reset();
cdc_reset();
@@ -1618,6 +1677,10 @@ void scd_reset(int hard)
void scd_update(unsigned int cycles)
{
int m68k_end_cycles;
int s68k_run_cycles;
int s68k_end_cycles = scd.cycles + SCYCLES_PER_LINE;
/* update CDC DMA transfer */
if (cdc.dma_w)
{
@@ -1627,63 +1690,77 @@ void scd_update(unsigned int cycles)
/* run both CPU in sync until end of line */
do
{
m68k_run(cycles);
s68k_run(scd.cycles + SCYCLES_PER_LINE);
}
while ((m68k.cycles < cycles) || (s68k.cycles < (scd.cycles + SCYCLES_PER_LINE)));
/* CD hardware remaining cycles until end of line */
s68k_run_cycles = s68k_end_cycles - scd.cycles;
/* increment CD hardware cycle counter */
scd.cycles += SCYCLES_PER_LINE;
/* CDD processing at 75Hz (one clock = 12500000/75 = 500000/3 CPU clocks) */
cdd.cycles += (SCYCLES_PER_LINE * 3);
if (cdd.cycles >= (500000 * 4))
{
/* reload CDD cycle counter */
cdd.cycles -= (500000 * 4);
/* update CDD sector */
cdd_update();
/* check if a new CDD command has been processed */
if (!(scd.regs[0x4a>>1].byte.l & 0xf0))
/* check Timer interrupt occurence */
if ((scd.timer > 0) && (scd.timer < s68k_run_cycles))
{
/* reset CDD command wait flag */
scd.regs[0x4a>>1].byte.l = 0xf0;
/* adjust Sub-CPU and Main-CPU end cycle counters up to Timer interrupt occurence */
s68k_run_cycles = scd.timer;
m68k_end_cycles = mcycles_vdp + ((s68k_run_cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE);
}
else
{
/* default Main-CPU end cycle counter (end of line) */
m68k_end_cycles = cycles;
}
/* pending level 4 interrupt */
scd.pending |= (1 << 4);
/* run both CPU in sync until required cycle counters */
m68k_run(m68k_end_cycles);
s68k_run(scd.cycles + s68k_run_cycles);
/* level 4 interrupt enabled */
if (scd.regs[0x32>>1].byte.l & 0x10)
/* increment CD hardware cycle counter */
scd.cycles += s68k_run_cycles;
/* CDD processing at 75Hz (one clock = 12500000/75 = 500000/3 CPU clocks) */
cdd.cycles += (s68k_run_cycles * 3);
if (cdd.cycles >= (500000 * 4))
{
/* reload CDD cycle counter */
cdd.cycles -= (500000 * 4);
/* update CDD sector */
cdd_update();
/* check if CDD communication is enabled */
if (scd.regs[0x37>>1].byte.l & 0x04)
{
/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
}
}
}
/* Timer */
if (scd.timer)
{
/* decrement timer */
scd.timer -= SCYCLES_PER_LINE;
if (scd.timer <= 0)
{
/* reload timer (one timer clock = 384 CPU cycles) */
scd.timer += (scd.regs[0x30>>1].byte.l * TIMERS_SCYCLES_RATIO);
/* level 3 interrupt enabled ? */
if (scd.regs[0x32>>1].byte.l & 0x08)
{
/* trigger level 3 interrupt */
scd.pending |= (1 << 3);
/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
/* pending level 4 interrupt */
scd.pending |= (1 << 4);
/* level 4 interrupt enabled */
if (scd.regs[0x32>>1].byte.l & 0x10)
{
/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
}
}
}
/* Timer */
if (scd.timer)
{
/* decrement timer */
scd.timer -= s68k_run_cycles;
if (scd.timer <= 0)
{
/* reload timer (one timer clock = 384 CPU cycles) */
scd.timer += (scd.regs[0x30>>1].byte.l * TIMERS_SCYCLES_RATIO);
/* level 3 interrupt enabled ? */
if (scd.regs[0x32>>1].byte.l & 0x08)
{
/* trigger level 3 interrupt */
scd.pending |= (1 << 3);
/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
}
}
}
}
while ((m68k.cycles < cycles) || (s68k.cycles < s68k_end_cycles));
/* GFX processing */
if (scd.regs[0x58>>1].byte.h & 0x80)
@@ -1796,7 +1873,7 @@ int scd_context_save(uint8 *state)
return bufferptr;
}
int scd_context_load(uint8 *state)
int scd_context_load(uint8 *state, char *version)
{
int i;
uint16 tmp16;
@@ -1818,7 +1895,7 @@ int scd_context_load(uint8 *state)
bufferptr += cdc_context_load(&state[bufferptr]);
/* CD Drive processor */
bufferptr += cdd_context_load(&state[bufferptr]);
bufferptr += cdd_context_load(&state[bufferptr], version);
/* PCM chip */
bufferptr += pcm_context_load(&state[bufferptr]);
+2 -2
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Mega CD / Sega CD hardware
*
* Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -87,7 +87,7 @@ extern void scd_init(void);
extern void scd_reset(int hard);
extern void scd_update(unsigned int cycles);
extern void scd_end_frame(unsigned int cycles);
extern int scd_context_load(uint8 *state);
extern int scd_context_load(uint8 *state, char *version);
extern int scd_context_save(uint8 *state);
extern int scd_68k_irq_ack(int level);
extern void prg_ram_dma_w(unsigned int words);
+53
View File
@@ -0,0 +1,53 @@
/***************************************************************************************
* Genesis Plus GX
* CPU hooking support
*
* HOOK_CPU should be defined in a makefile or MSVC project to enable this functionality
*
* Copyright feos (2019)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
*
* - Redistributions may not be sold, nor may they be used in a commercial
* product or activity.
*
* - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable.
*
* - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************************/
#ifdef HOOK_CPU
#include <stdio.h>
#include "cpuhook.h"
void(*cpu_hook)(hook_type_t type, int width, unsigned int address, unsigned int value) = NULL;
void set_cpu_hook(void(*hook)(hook_type_t type, int width, unsigned int address, unsigned int value))
{
cpu_hook = hook;
}
#endif /* HOOK_CPU */
+91
View File
@@ -0,0 +1,91 @@
/***************************************************************************************
* Genesis Plus GX
* CPU hooking support
*
* HOOK_CPU should be defined in a makefile or MSVC project to enable this functionality
*
* Copyright DrMefistO (2018-2019)
*
* Copyright feos (2019)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
*
* - Redistributions may not be sold, nor may they be used in a commercial
* product or activity.
*
* - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable.
*
* - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************************/
#ifndef _CPUHOOK_H_
#define _CPUHOOK_H_
typedef enum {
HOOK_ANY = (0 << 0),
// M68K
HOOK_M68K_E = (1 << 0),
HOOK_M68K_R = (1 << 1),
HOOK_M68K_W = (1 << 2),
HOOK_M68K_RW = HOOK_M68K_R | HOOK_M68K_W,
// VDP
HOOK_VRAM_R = (1 << 3),
HOOK_VRAM_W = (1 << 4),
HOOK_VRAM_RW = HOOK_VRAM_R | HOOK_VRAM_W,
HOOK_CRAM_R = (1 << 5),
HOOK_CRAM_W = (1 << 6),
HOOK_CRAM_RW = HOOK_CRAM_R | HOOK_CRAM_W,
HOOK_VSRAM_R = (1 << 7),
HOOK_VSRAM_W = (1 << 8),
HOOK_VSRAM_RW = HOOK_VSRAM_R | HOOK_VSRAM_W,
// Z80
HOOK_Z80_E = (1 << 9),
HOOK_Z80_R = (1 << 10),
HOOK_Z80_W = (1 << 11),
HOOK_Z80_RW = HOOK_Z80_R | HOOK_Z80_W,
// REGS
HOOK_VDP_REG = (1 << 12),
HOOK_M68K_REG = (1 << 13),
} hook_type_t;
/* CPU hook is called on read, write, and execute.
*/
void (*cpu_hook)(hook_type_t type, int width, unsigned int address, unsigned int value);
/* Use set_cpu_hook() to assign a callback that can process the data provided
* by cpu_hook().
*/
void set_cpu_hook(void(*hook)(hook_type_t type, int width, unsigned int address, unsigned int value));
#endif /* _CPUHOOK_H_ */
+19 -9
View File
@@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -50,7 +50,7 @@ uint8 boot_rom[0x800]; /* Genesis BOOT ROM */
uint8 work_ram[0x10000]; /* 68K RAM */
uint8 zram[0x2000]; /* Z80 RAM */
uint32 zbank; /* Z80 bank window address */
uint8 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */
uint8 zstate; /* Z80 bus state (d0 = /RESET, d1 = BUSACK) */
uint8 pico_current; /* PICO current page */
static uint8 tmss[4]; /* TMSS security register */
@@ -161,6 +161,7 @@ void gen_init(void)
{
/* initialize SUB-CPU */
s68k_init();
s68k.aerr_enabled = config.addr_error;
/* initialize CD hardware */
scd_init();
@@ -220,6 +221,7 @@ void gen_init(void)
/* SG-1000 hardware */
case SYSTEM_SG:
case SYSTEM_SGII:
case SYSTEM_SGII_RAM_EXT:
{
z80_writeport = z80_sg_port_w;
z80_readport = z80_sg_port_r;
@@ -279,10 +281,18 @@ void gen_reset(int hard_reset)
/* reset CD hardware */
scd_reset(1);
}
/* reset MD cartridge hardware (only when booting from cartridge) */
if (scd.cartridge.boot)
{
md_cart_reset(hard_reset);
}
}
else
{
/* reset MD cartridge hardware */
md_cart_reset(hard_reset);
}
/* reset MD cartridge hardware */
md_cart_reset(hard_reset);
/* Z80 bus is released & Z80 is reseted */
m68k.memory_map[0xa0].read8 = m68k_read_bus_8;
@@ -474,8 +484,8 @@ void gen_zbusreq_w(unsigned int data, unsigned int cycles)
/* check if Z80 is going to be restarted */
if (zstate == 3)
{
/* resynchronize with 68k */
Z80.cycles = cycles;
/* resynchronize with 68k (Z80 cycles should remain a multiple of 15 MClocks) */
Z80.cycles = ((cycles + 14) / 15) * 15;
/* disable 68k access to Z80 bus */
m68k.memory_map[0xa0].read8 = m68k_read_bus_8;
@@ -496,8 +506,8 @@ void gen_zreset_w(unsigned int data, unsigned int cycles)
/* check if Z80 is going to be restarted */
if (zstate == 0)
{
/* resynchronize with 68k */
Z80.cycles = cycles;
/* resynchronize with 68k (Z80 cycles should remain a multiple of 15 MClocks) */
Z80.cycles = ((cycles + 14) / 15) * 15;
/* reset Z80 & YM2612 */
z80_reset();
+1 -1
View File
@@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+28 -32
View File
@@ -3,7 +3,7 @@
* 2-Buttons, 3-Buttons & 6-Buttons controller support
* with support for J-Cart, 4-Way Play & Master Tap adapters
*
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2019 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -122,37 +122,25 @@ INLINE unsigned char gamepad_read(int port)
/* D-PAD or extra buttons status is returned on D3-D0 (active low) */
switch (step)
{
case 1: /*** First High ***/
case 3: /*** Second High ***/
case 5: /*** Third High ***/
{
/* TH = 1 : ?1CBRLDU */
data &= ~(pad & 0x3F);
break;
}
/* From gen_hw.txt (*):
case 0: /*** 3-button only ***/
case 2: /*** First Low ***/
case 4: /*** Second Low ***/
{
/* TH = 0 : ?0SA00DU */
data &= ~((pad & 0x03) | ((pad >> 2) & 0x30) | 0x0C);
break;
}
A 6-button gamepad allows the extra buttons to be read based on how
many times TH is switched from 0 to 1. Observe the following sequence:
/* A 6-button gamepad allows the extra buttons to be read based on how */
/* many times TH is switched from 1 to 0. Observe the following sequence */
/*
TH = 1 : ?1CBRLDU 3-button pad return value
TH = 0 : ?0SA00DU 3-button pad return value
TH = 1 : ?1CBRLDU 3-button pad return value
TH = 0 : ?0SA00DU 3-button pad return value
TH = 1 : ?1CBRLDU 3-button pad return value (*)
TH = 0 : ?0SA00DU 3-button pad return value (*)
TH = 1 : ?1CBRLDU 3-button pad return value
TH = 0 : ?0SA0000 D3-D0 are forced to '0'
TH = 1 : ?1CBMXYZ Extra buttons returned in D3-0
TH = 0 : ?0SA1111 D3-D0 are forced to '1'
From this point on, the standard 3-button pad values will be returned if any further TH transitions are done.
(*) additional High-to-Low transition is necessary to access extra buttons according to official MK-1653-50 specification
*/
case 6: /*** Third Low ***/
case 4: /*** Third Low ***/
{
/* TH = 0 : ?0SA0000 D3-D0 forced to '0' */
data &= ~(((pad >> 2) & 0x30) | 0x0F);
@@ -166,18 +154,26 @@ INLINE unsigned char gamepad_read(int port)
break;
}
default: /*** D3-D0 forced to '1' ***/
case 6: /*** Fourth Low ***/
{
if (data & 0x40)
/* TH = 0 : ?0SA1111 D3-D0 forced to '1' */
data &= ~((pad >> 2) & 0x30);
break;
}
default: /*** 3-button mode ***/
{
if (step & 1)
{
/* TH = 1 : ?0CB1111 */
data &= ~(pad & 0x30);
/* TH = 1 : ?1CBRLDU */
data &= ~(pad & 0x3F);
}
else
{
/* TH = 0 : ?0SA1111 */
data &= ~((pad >> 2) & 0x30);
/* TH = 0 : ?0SA00DU */
data &= ~((pad & 0x03) | ((pad >> 2) & 0x30) | 0x0C);
}
break;
}
}
@@ -196,10 +192,10 @@ INLINE void gamepad_write(int port, unsigned char data, unsigned char mask)
gamepad[port].Latency = 0;
/* 6-Buttons controller specific */
if (input.dev[port] == DEVICE_PAD6B)
if ((input.dev[port] == DEVICE_PAD6B) && (gamepad[port].Counter < 8))
{
/* TH 1->0 transition */
if (!data && gamepad[port].State)
/* TH 0->1 transition */
if (data && !gamepad[port].State)
{
gamepad[port].Counter += 2;
gamepad[port].Timeout = 0;
+1 -1
View File
@@ -3,7 +3,7 @@
* 2-Buttons, 3-Buttons & 6-Buttons controller support
* with support for J-Cart, 4-Way Play & Master Tap adapters
*
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2019 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+1 -1
View File
@@ -56,7 +56,7 @@ void mouse_reset(int port)
mouse.Port = port;
}
unsigned char mouse_read()
unsigned char mouse_read(void)
{
unsigned int temp = 0x00;
int x = input.analog[mouse.Port][0];
+2 -2
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* XE-1AP analog controller support
*
* Copyright (C) 2011-2015 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2011-2023 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -96,7 +96,7 @@ INLINE unsigned char xe_1ap_read(int index)
case 9: /* CH3 low (Throttle vertical or horizontal direction) */
data = input.analog[port+1][0] & 0x0F;
break;
case 10: /* A B A' B' buttons status (active low) */
case 11: /* A B A' B' buttons status (active low) */
data = (~input.pad[port] >> 6) & 0x0F;
break;
default: /* N/A */
+1 -1
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* XE-1AP analog controller support
*
* Copyright (C) 2011-2015 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2011-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+60 -7
View File
@@ -5,7 +5,7 @@
* Support for Master System (315-5216, 315-5237 & 315-5297), Game Gear & Mega Drive I/O chips
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2019 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -321,13 +321,27 @@ void io_reset(void)
io_reg[0x0D] |= IO_CONT1_HI;
}
/* Control registers */
io_reg[0x0E] = 0x00;
io_reg[0x0F] = 0xFF;
/* on SG-1000 & Mark-III, TH is not connected (always return 1) */
if (system_hw < SYSTEM_SMS)
/* Memory Control register (Master System and Game Gear hardware only) */
if ((system_hw & SYSTEM_SMS) || (system_hw & SYSTEM_GG))
{
/* RAM, I/O and either BIOS or Cartridge ROM are enabled */
io_reg[0x0E] = (z80_readmap[0] == cart.rom + 0x400000) ? 0xE0 : 0xA8;
}
else
{
/* default value (no Memory Control register) */
io_reg[0x0E] = 0x00;
}
/* I/O control register (Master System, Mega Drive and Game Gear hardware only) */
if (system_hw >= SYSTEM_SMS)
{
/* on power-on, TR and TH are configured as inputs */
io_reg[0x0F] = 0xFF;
}
else
{
/* on SG-1000 & Mark-III, TR is always an input and TH is not connected (always return 1) */
io_reg[0x0F] = 0xF5;
}
}
@@ -350,6 +364,16 @@ void io_68k_write(unsigned int offset, unsigned int data)
case 0x02: /* Port B Data */
case 0x03: /* Port C Data */
{
/*
D7 : Unused. This bit will return any value written to it
D6 : TH pin output level (1=high, 0=low)
D5 : TR pin output level (1=high, 0=low)
D4 : TL pin output level (1=high, 0=low)
D3 : D3 pin output level (1=high, 0=low)
D2 : D2 pin output level (1=high, 0=low)
D1 : D1 pin output level (1=high, 0=low)
D0 : D0 pin output level (1=high, 0=low)
*/
io_reg[offset] = data;
port[offset-1].data_w(data, io_reg[offset + 3]);
return;
@@ -359,6 +383,16 @@ void io_68k_write(unsigned int offset, unsigned int data)
case 0x05: /* Port B Ctrl */
case 0x06: /* Port C Ctrl */
{
/*
D7 : /HL output control (1=TH input level, 0=forced high)
D6 : TH pin is 1=output, 0=input
D5 : TR pin is 1=output, 0=input
D4 : TL pin is 1=output, 0=input
D3 : D3 pin is 1=output, 0=input
D2 : D2 pin is 1=output, 0=input
D1 : D1 pin is 1=output, 0=input
D0 : D0 pin is 1=output, 0=input
*/
if (data != io_reg[offset])
{
io_reg[offset] = data;
@@ -379,6 +413,15 @@ void io_68k_write(unsigned int offset, unsigned int data)
case 0x0C: /* Port B S-Ctrl */
case 0x0F: /* Port C S-Ctrl */
{
/*
D7-D6 : Serial baud rate (00= 4800 bps, 01= 2400 bps, 10= 1200 bps, 11= 300 bps)
D5 : TR pin functions as 1= serial input pin, 0= normal
D4 : TL pin functions as 1= serial output pin, 0= normal
D3 : 1= Make I/O chip strobe /HL low when a byte has been received, 0= Do nothing
D2 : read-only (on read, 1= Error receiving current byte, 0= No error)
D1 : read-only (on read, 1= Rxd buffer is ready to read, 0= Rxd buffer isn't ready)
D0 : read-only (on read, 1= Txd buffer is full, 0= Can write to Txd buffer)
*/
io_reg[offset] = data & 0xF8;
return;
}
@@ -398,6 +441,16 @@ unsigned int io_68k_read(unsigned int offset)
case 0x02: /* Port B Data */
case 0x03: /* Port C Data */
{
/*
D7 : Unused. This bit will return any value written to it
D6 : TH pin input level (1=high, 0=low)
D5 : TR pin input level (1=high, 0=low)
D4 : TL pin input level (1=high, 0=low)
D3 : D3 pin input level (1=high, 0=low)
D2 : D2 pin input level (1=high, 0=low)
D1 : D1 pin input level (1=high, 0=low)
D0 : D0 pin input level (1=high, 0=low)
*/
unsigned int mask = 0x80 | io_reg[offset + 3];
unsigned int data = port[offset-1].data_r();
return (io_reg[offset] & mask) | (data & ~mask);
+1 -1
View File
@@ -5,7 +5,7 @@
* Support for Master System (315-5216, 315-5237 & 315-5297), Game Gear & Mega Drive I/O chips
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2019 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+102 -72
View File
@@ -3,7 +3,7 @@
* ROM Loading Support
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -58,20 +58,21 @@
#define ROMMEMO 456
#define ROMCOUNTRY 496
#define P3BUTTONS 1
#define P6BUTTONS 2
#define PKEYBOARD 4
#define PPRINTER 8
#define PBALL 16
#define PFLOPPY 32
#define PACTIVATOR 64
#define PTEAMPLAYER 128
#define PMSYSTEMPAD 256
#define PSERIAL 512
#define PTABLET 1024
#define PPADDLE 2048
#define PCDROM 4096
#define PMOUSE 8192
#define P3BUTTONS 0x0001
#define P6BUTTONS 0x0002
#define PKEYBOARD 0x0004
#define PPRINTER 0x0008
#define PBALL 0x0010
#define PFLOPPY 0x0020
#define PACTIVATOR 0x0040
#define PTEAMPLAYER 0x0080
#define PMSYSTEMPAD 0x0100
#define PSERIAL 0x0200
#define PTABLET 0x0400
#define PPADDLE 0x0800
#define PCDROM 0x1000
#define PMOUSE 0x2000
#define PMENACER 0x4000
#define MAXCOMPANY 64
#define MAXPERIPHERALS 15
@@ -288,7 +289,7 @@ void getrominfo(char *romheader)
/* Supported peripherals */
rominfo.peripherals = 0;
for (i = 0; i < 14; i++)
for (j=0; j < 14; j++)
for (j=0; j < MAXPERIPHERALS; j++)
if (romheader[ROMIOSUPPORT+i] == peripheralinfo[j].pID[0])
rominfo.peripherals |= (1 << j);
}
@@ -311,7 +312,7 @@ void getrominfo(char *romheader)
}
/* if found, get infos from header */
if (offset)
if ((offset > 0) && (offset < cart.romsize))
{
/* checksum */
rominfo.checksum = romheader[offset + 0x0a] | (romheader[offset + 0x0b] << 8);
@@ -417,6 +418,23 @@ int load_bios(int system)
/* CD BOOTROM loaded ? */
if (size > 0)
{
/* auto-detect CD hardware model */
if (!memcmp (&scd.bootrom[0x120], "WONDER-MEGA BOOT", 16))
{
/* Wondermega CD hardware */
cdd.type = CD_TYPE_WONDERMEGA;
}
else if (!memcmp (&scd.bootrom[0x120], "WONDERMEGA2 BOOT", 16))
{
/* Wondermega M2 / X'Eye CD hardware */
cdd.type = CD_TYPE_WONDERMEGA_M2;
}
else
{
/* default CD hardware */
cdd.type = CD_TYPE_DEFAULT;
}
#ifdef LSB_FIRST
/* Byteswap ROM to optimize 16-bit access */
int i;
@@ -564,9 +582,6 @@ int load_rom(char *filename)
{
/* enable CD hardware */
system_hw = SYSTEM_MCD;
/* boot from CD hardware */
scd.cartridge.boot = 0x00;
}
else
{
@@ -630,7 +645,9 @@ int load_rom(char *filename)
/* auto-detect byte-swapped dumps */
if (!memcmp((char *)(cart.rom + 0x100),"ESAGM GE ARDVI E", 16) ||
!memcmp((char *)(cart.rom + 0x100),"ESAGG NESESI", 12))
!memcmp((char *)(cart.rom + 0x100),"ESAGG NESESI", 12) ||
!memcmp((char *)(cart.rom + 0x80000 + 0x100),"ESAGM GE ARDVI E", 16) ||
!memcmp((char *)(cart.rom + 0x80000 + 0x100),"ESAGG NESESI", 12))
{
for(i = 0; i < size; i += 2)
{
@@ -691,10 +708,10 @@ int load_rom(char *filename)
/* Save auto-detected system hardware */
romtype = system_hw;
/* CD image file */
if (system_hw == SYSTEM_MCD)
{
{
/* try to load CD BOOTROM for selected region */
if (!load_bios(SYSTEM_MCD))
{
@@ -704,65 +721,52 @@ int load_rom(char *filename)
/* error booting from CD */
return (0);
}
}
/* CD BOOTROM */
else if (strstr(rominfo.ROMType, "BR") != NULL)
{
/* enable CD hardware */
system_hw = SYSTEM_MCD;
/* boot from CD hardware */
scd.cartridge.boot = 0x00;
/* copy ROM to BOOTROM area */
memcpy(scd.bootrom, cart.rom, sizeof(scd.bootrom));
/* mark CD BIOS as being loaded */
system_bios = system_bios | 0x10;
/* loaded CD BIOS region */
system_bios = (system_bios & 0xf0) | (region_code >> 4);
}
/* ROM cartridge (max. 8MB) with CD loaded */
else if ((cart.romsize <= 0x800000) && cdd.loaded)
/* 16-bit ROM cartridge (max. 8MB) with optional CD hardware add-on support enabled */
else if ((system_hw == SYSTEM_MD) && (cart.romsize <= 0x800000) && (config.add_on != HW_ADDON_NONE))
{
/* try to load CD BOOTROM */
if (load_bios(SYSTEM_MCD))
{
/* enable CD hardware */
system_hw = SYSTEM_MCD;
int len;
char fname[256];
/* boot from cartridge */
scd.cartridge.boot = 0x40;
#if defined(USE_LIBCHDR)
/* automatically try to load associated .chd file if no .cue file CD image loaded yet */
if (!cdd.loaded)
{
len = strlen(filename);
while ((len && (filename[len] != '.')) || (len > 251)) len--;
strncpy(fname, filename, len);
strcpy(&fname[len], ".chd");
fname[len+4] = 0;
cdd_load(fname, (char *)cdc.ram);
}
else
#endif
/* automatically enable CD hardware emulation (Mode 1) in case : */
/* - loaded ROM has known CD hardware support */
/* or */
/* - CD hardware emulation is forced on */
/* or */
/* - MegaSD add-on emulation is disabled and normal CD image file is loaded */
if ((rominfo.peripherals & PCDROM) || (strstr(rominfo.domestic,"FLUX") != NULL) ||
(config.add_on == HW_ADDON_MEGACD) || ((config.add_on | cdd.loaded) == HW_ADDON_MEGACD))
{
/* unmount CD image */
cdd_unload();
}
}
/* ROM cartridge with CD support */
else if ((strstr(rominfo.domestic,"FLUX") != NULL) ||
(strstr(rominfo.domestic,"WONDER LIBRARY") != NULL) ||
(strstr(rominfo.product,"T-5740") != NULL))
{
/* check if console hardware is set to AUTO */
if (!config.system)
{
/* try to load CD BOOTROM */
/* try to load CD BOOTROM for selected region */
if (load_bios(SYSTEM_MCD))
{
char fname[256];
int len = strlen(filename);
/* automatically try to load associated .iso file */
while ((len && (filename[len] != '.')) || (len > 251)) len--;
strncpy(fname, filename, len);
strcpy(&fname[len], ".iso");
cdd_load(fname, (char *)cdc.ram);
/* automatically try to load associated .iso file if no CD image loaded yet */
if (!cdd.loaded)
{
len = strlen(filename);
while ((len && (filename[len] != '.')) || (len > 251)) len--;
strncpy(fname, filename, len);
strcpy(&fname[len], ".iso");
fname[len+4] = 0;
cdd_load(fname, (char *)cdc.ram);
}
/* enable CD hardware */
system_hw = SYSTEM_MCD;
@@ -770,6 +774,30 @@ int load_rom(char *filename)
/* boot from cartridge */
scd.cartridge.boot = 0x40;
}
else
{
/* unmount any loaded CD image */
cdd_unload();
}
}
/* CD BOOTROM */
else if (strstr(rominfo.ROMType, "BR") != NULL)
{
/* enable CD hardware */
system_hw = SYSTEM_MCD;
/* boot from CD hardware */
scd.cartridge.boot = 0x00;
/* copy ROM to BOOTROM area */
memcpy(scd.bootrom, cart.rom, sizeof(scd.bootrom));
/* mark CD BIOS as being loaded */
system_bios = system_bios | 0x10;
/* loaded CD BIOS region */
system_bios = (system_bios & 0xf0) | (region_code >> 4);
}
}
@@ -1059,7 +1087,9 @@ void get_region(char *romheader)
(strstr(rominfo.product,"T-69046-50") != NULL) || /* Back to the Future III (Europe) */
(strstr(rominfo.product,"T-120106-00") != NULL) || /* Brian Lara Cricket (Europe) */
(strstr(rominfo.product,"T-97126 -50") != NULL) || /* Williams Arcade's Greatest Hits (Europe) */
(strstr(rominfo.product,"T-70096 -00") != NULL)) /* Muhammad Ali Heavyweight Boxing (Europe) */
(strstr(rominfo.product,"T-113026-50") != NULL) || /* Wiz'n'Liz - The Frantic Wabbit Wescue (Europe) */
(strstr(rominfo.product,"T-70096 -00") != NULL) || /* Muhammad Ali Heavyweight Boxing (Europe) */
((rominfo.checksum == 0x0000) && (rominfo.realchecksum == 0x1f7f))) /* Radica - Sensible Soccer Plus edition */
{
/* need PAL settings */
region_code = REGION_EUROPE;
+1 -1
View File
@@ -3,7 +3,7 @@
* ROM Loading Support
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+3
View File
@@ -43,6 +43,9 @@
#include <setjmp.h>
#include "macros.h"
#ifdef HOOK_CPU
#include "cpuhook.h"
#endif
/* ======================================================================== */
/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
+15 -8
View File
@@ -188,7 +188,8 @@ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
}
#endif
#ifdef LOGVDP
#ifdef LOGERROR
extern void error(char *format, ...);
extern uint16 v_counter;
#endif
@@ -202,8 +203,8 @@ void m68k_update_irq(unsigned int mask)
/* Update IRQ level */
CPU_INT_LEVEL |= (mask << 8);
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
#ifdef LOGERROR
error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
#endif
}
@@ -212,8 +213,8 @@ void m68k_set_irq(unsigned int int_level)
/* Set IRQ level */
CPU_INT_LEVEL = int_level << 8;
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
#ifdef LOGERROR
error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
#endif
}
@@ -245,8 +246,8 @@ void m68k_set_irq_delay(unsigned int int_level)
CPU_INT_LEVEL = int_level << 8;
}
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
#ifdef LOGERROR
error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC));
#endif
/* Check interrupt mask to process IRQ */
@@ -277,7 +278,7 @@ void m68k_run(unsigned int cycles)
/* Return point for when we have an address error (TODO: use goto) */
m68ki_set_address_error_trap() /* auto-disable (see m68kcpu.h) */
#ifdef LOGVDP
#ifdef LOGERROR
error("[%d][%d] m68k run to %d cycles (%x), irq mask = %x (%x)\n", v_counter, m68k.cycles, cycles, m68k.pc,FLAG_INT_MASK, CPU_INT_LEVEL);
#endif
@@ -289,6 +290,12 @@ void m68k_run(unsigned int cycles)
/* Set the address space for reads */
m68ki_use_data_space() /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU
/* Trigger execution hook */
if (cpu_hook)
cpu_hook(HOOK_M68K_E, 0, REG_PC, 0);
#endif
/* Decode next instruction */
REG_IR = m68ki_read_imm_16();
+49 -10
View File
@@ -596,12 +596,12 @@ static const uint16 m68ki_exception_cycle_table[256] =
50*MUL, /* 3: Address Error (unemulated) */
34*MUL, /* 4: Illegal Instruction */
38*MUL, /* 5: Divide by Zero -- ASG: changed from 42 */
40*MUL, /* 6: CHK -- ASG: chanaged from 44 */
38*MUL, /* 6: CHK -- ASG: changed from 44 */
34*MUL, /* 7: TRAPV */
34*MUL, /* 8: Privilege Violation */
34*MUL, /* 9: Trace */
4*MUL, /* 10: 1010 */
4*MUL, /* 11: 1111 */
34*MUL, /* 10: 1010 */
34*MUL, /* 11: 1111 */
4*MUL, /* 12: RESERVED */
4*MUL, /* 13: Coprocessor Protocol Violation (unemulated) */
4*MUL, /* 14: Format Error */
@@ -849,36 +849,60 @@ INLINE uint m68ki_read_imm_32(void)
*/
INLINE uint m68ki_read_8(uint address)
{
cpu_memory_map *temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];;
cpu_memory_map *temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];
uint val;
m68ki_set_fc(FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */
if (temp->read8) return (*temp->read8)(ADDRESS_68K(address));
else return READ_BYTE(temp->base, (address) & 0xffff);
if (temp->read8) val = (*temp->read8)(ADDRESS_68K(address));
else val = READ_BYTE(temp->base, (address) & 0xffff);
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_M68K_R, 1, address, val);
#endif
return val;
}
INLINE uint m68ki_read_16(uint address)
{
cpu_memory_map *temp;
uint val;
m68ki_set_fc(FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_READ, FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */
temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];
if (temp->read16) return (*temp->read16)(ADDRESS_68K(address));
else return *(uint16 *)(temp->base + ((address) & 0xffff));
if (temp->read16) val = (*temp->read16)(ADDRESS_68K(address));
else val = *(uint16 *)(temp->base + ((address) & 0xffff));
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_M68K_R, 2, address, val);
#endif
return val;
}
INLINE uint m68ki_read_32(uint address)
{
cpu_memory_map *temp;
uint val;
m68ki_set_fc(FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_READ, FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */
temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];
if (temp->read16) return ((*temp->read16)(ADDRESS_68K(address)) << 16) | ((*temp->read16)(ADDRESS_68K(address + 2)));
else return m68k_read_immediate_32(address);
if (temp->read16) val = ((*temp->read16)(ADDRESS_68K(address)) << 16) | ((*temp->read16)(ADDRESS_68K(address + 2)));
else val = m68k_read_immediate_32(address);
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_M68K_R, 4, address, val);
#endif
return val;
}
INLINE void m68ki_write_8(uint address, uint value)
@@ -887,6 +911,11 @@ INLINE void m68ki_write_8(uint address, uint value)
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_M68K_W, 1, address, value);
#endif
temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];
if (temp->write8) (*temp->write8)(ADDRESS_68K(address),value);
else WRITE_BYTE(temp->base, (address) & 0xffff, value);
@@ -899,6 +928,11 @@ INLINE void m68ki_write_16(uint address, uint value)
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA); /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_M68K_W, 2, address, value);
#endif
temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];
if (temp->write16) (*temp->write16)(ADDRESS_68K(address),value);
else *(uint16 *)(temp->base + ((address) & 0xffff)) = value;
@@ -911,6 +945,11 @@ INLINE void m68ki_write_32(uint address, uint value)
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_M68K_W, 4, address, value);
#endif
temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];
if (temp->write16) (*temp->write16)(ADDRESS_68K(address),value>>16);
else *(uint16 *)(temp->base + ((address) & 0xffff)) = value >> 16;
+115 -115
View File
@@ -19,16 +19,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -40,7 +40,7 @@ static const unsigned char m68ki_cycles[0x10000] =
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7,
22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 20*7, 24*7, 0*7, 0*7, 20*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7, 28*7,
30*7, 30*7, 30*7, 30*7, 30*7, 30*7, 30*7, 30*7, 32*7, 32*7, 32*7, 32*7, 32*7, 32*7, 32*7, 32*7,
34*7, 34*7, 34*7, 34*7, 34*7, 34*7, 34*7, 34*7, 32*7, 36*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -51,16 +51,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -83,16 +83,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -115,16 +115,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -132,31 +132,31 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 16*7, 18*7, 0*7, 0*7, 0*7, 0*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7,
22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 20*7, 24*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7,
22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 20*7, 24*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7,
22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 20*7, 24*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7,
22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 20*7, 24*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -179,16 +179,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -211,16 +211,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -243,16 +243,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 8*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 12*7, 16*7, 12*7, 14*7, 10*7, 0*7, 0*7, 0*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1048,10 +1048,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
@@ -1080,10 +1080,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
@@ -1112,10 +1112,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
@@ -1144,10 +1144,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
@@ -1176,10 +1176,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
@@ -1197,25 +1197,9 @@ static const unsigned char m68ki_cycles[0x10000] =
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7, 22*7,
24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 24*7, 22*7, 26*7, 0*7, 0*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 8*7, 12*7, 8*7, 12*7, 0*7, 0*7, 0*7, 0*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 0*7, 0*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1225,37 +1209,53 @@ static const unsigned char m68ki_cycles[0x10000] =
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 16*7, 18*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 16*7, 18*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 8*7, 12*7, 8*7, 12*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 8*7, 12*7, 8*7, 12*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 16*7, 18*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 16*7, 18*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 8*7, 12*7, 8*7, 12*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
0*7, 4*7, 4*7, 20*7, 0*7, 16*7, 4*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 4*7, 4*7, 20*7, 0*7, 16*7, 0*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
@@ -1272,10 +1272,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7,
16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7,
20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 20*7, 18*7, 22*7, 18*7, 20*7, 14*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 6*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 10*7, 8*7, 12*7, 8*7, 10*7, 4*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
@@ -1284,7 +1284,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1316,7 +1316,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1348,7 +1348,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1380,7 +1380,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1412,7 +1412,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1444,7 +1444,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1476,7 +1476,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
@@ -1508,7 +1508,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7,
4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 4*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7, 8*7,
12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7, 12*7,
14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 14*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7, 16*7,
18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 18*7, 16*7, 20*7, 0*7, 0*7, 0*7, 0*7, 0*7, 0*7,
+143 -54
View File
@@ -4661,6 +4661,11 @@ static void m68k_op_bchg_32_r_d(void)
uint* r_dst = &DY;
uint mask = 1 << (DX & 0x1f);
if (mask & 0xffff0000)
{
USE_CYCLES(2 * MUL);
}
FLAG_Z = *r_dst & mask;
*r_dst ^= mask;
}
@@ -4770,6 +4775,11 @@ static void m68k_op_bchg_32_s_d(void)
uint* r_dst = &DY;
uint mask = 1 << (OPER_I_8() & 0x1f);
if (mask & 0xffff0000)
{
USE_CYCLES(2 * MUL);
}
FLAG_Z = *r_dst & mask;
*r_dst ^= mask;
}
@@ -4879,6 +4889,11 @@ static void m68k_op_bclr_32_r_d(void)
uint* r_dst = &DY;
uint mask = 1 << (DX & 0x1f);
if (mask & 0xffff0000)
{
USE_CYCLES(2 * MUL);
}
FLAG_Z = *r_dst & mask;
*r_dst &= ~mask;
}
@@ -4988,6 +5003,11 @@ static void m68k_op_bclr_32_s_d(void)
uint* r_dst = &DY;
uint mask = 1 << (OPER_I_8() & 0x1f);
if (mask & 0xffff0000)
{
USE_CYCLES(2 * MUL);
}
FLAG_Z = *r_dst & mask;
*r_dst &= ~mask;
}
@@ -5117,6 +5137,11 @@ static void m68k_op_bset_32_r_d(void)
uint* r_dst = &DY;
uint mask = 1 << (DX & 0x1f);
if (mask & 0xffff0000)
{
USE_CYCLES(2 * MUL);
}
FLAG_Z = *r_dst & mask;
*r_dst |= mask;
}
@@ -5226,6 +5251,11 @@ static void m68k_op_bset_32_s_d(void)
uint* r_dst = &DY;
uint mask = 1 << (OPER_I_8() & 0x1f);
if (mask & 0xffff0000)
{
USE_CYCLES(2 * MUL);
}
FLAG_Z = *r_dst & mask;
*r_dst |= mask;
}
@@ -5536,9 +5566,14 @@ static void m68k_op_chk_16_d(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5554,9 +5589,14 @@ static void m68k_op_chk_16_ai(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5572,9 +5612,14 @@ static void m68k_op_chk_16_pi(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5590,9 +5635,14 @@ static void m68k_op_chk_16_pd(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5608,9 +5658,14 @@ static void m68k_op_chk_16_di(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5626,9 +5681,14 @@ static void m68k_op_chk_16_ix(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5644,9 +5704,14 @@ static void m68k_op_chk_16_aw(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5662,9 +5727,14 @@ static void m68k_op_chk_16_al(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5680,9 +5750,14 @@ static void m68k_op_chk_16_pcdi(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5698,9 +5773,14 @@ static void m68k_op_chk_16_pcix(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -5716,9 +5796,14 @@ static void m68k_op_chk_16_i(void)
if(src >= 0 && src <= bound)
{
USE_CYCLES(10 * MUL);
return;
}
FLAG_N = (src < 0)<<7;
if(src < 0)
{
FLAG_N = 1<<7;
USE_CYCLES(2 * MUL);
}
m68ki_exception_trap(EXCEPTION_CHK);
}
@@ -8117,7 +8202,7 @@ static void m68k_op_divu_16_d(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8148,7 +8233,7 @@ static void m68k_op_divu_16_ai(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8179,7 +8264,7 @@ static void m68k_op_divu_16_pi(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 *10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8210,7 +8295,7 @@ static void m68k_op_divu_16_pd(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8241,7 +8326,7 @@ static void m68k_op_divu_16_di(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8272,7 +8357,7 @@ static void m68k_op_divu_16_ix(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8303,7 +8388,7 @@ static void m68k_op_divu_16_aw(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8334,7 +8419,7 @@ static void m68k_op_divu_16_al(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8365,7 +8450,7 @@ static void m68k_op_divu_16_pcdi(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8396,7 +8481,7 @@ static void m68k_op_divu_16_pcix(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -8427,7 +8512,7 @@ static void m68k_op_divu_16_i(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return;
}
USE_CYCLES(7 * 10);
USE_CYCLES(MUL * 10);
FLAG_V = VFLAG_SET;
FLAG_N = NFLAG_SET; /* undocumented behavior (fixes Blood Shot on Genesis) */
FLAG_C = CFLAG_CLEAR;
@@ -20967,7 +21052,10 @@ static void m68k_op_stop(void)
uint new_sr = OPER_I_16();
CPU_STOPPED |= STOP_LEVEL_STOP;
m68ki_set_sr(new_sr);
SET_CYCLES(m68ki_cpu.cycle_end - 4*MUL);
if (CPU_STOPPED)
{
SET_CYCLES(m68ki_cpu.cycle_end - 4*MUL);
}
return;
}
m68ki_exception_privilege_violation();
@@ -23355,6 +23443,7 @@ static void m68k_op_trapv(void)
{
if(COND_VC())
{
USE_CYCLES (4 * MUL);
return;
}
m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */
@@ -23714,21 +23803,21 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_btst_8_r_pd , 0xf1f8, 0x0120, 10},
{m68k_op_btst_8_r_di , 0xf1f8, 0x0128, 12},
{m68k_op_btst_8_r_ix , 0xf1f8, 0x0130, 14},
{m68k_op_bchg_32_r_d , 0xf1f8, 0x0140, 8},
{m68k_op_bchg_32_r_d , 0xf1f8, 0x0140, 6},
{m68k_op_movep_32_er , 0xf1f8, 0x0148, 24},
{m68k_op_bchg_8_r_ai , 0xf1f8, 0x0150, 12},
{m68k_op_bchg_8_r_pi , 0xf1f8, 0x0158, 12},
{m68k_op_bchg_8_r_pd , 0xf1f8, 0x0160, 14},
{m68k_op_bchg_8_r_di , 0xf1f8, 0x0168, 16},
{m68k_op_bchg_8_r_ix , 0xf1f8, 0x0170, 18},
{m68k_op_bclr_32_r_d , 0xf1f8, 0x0180, 10},
{m68k_op_bclr_32_r_d , 0xf1f8, 0x0180, 8},
{m68k_op_movep_16_re , 0xf1f8, 0x0188, 16},
{m68k_op_bclr_8_r_ai , 0xf1f8, 0x0190, 12},
{m68k_op_bclr_8_r_pi , 0xf1f8, 0x0198, 12},
{m68k_op_bclr_8_r_pd , 0xf1f8, 0x01a0, 14},
{m68k_op_bclr_8_r_di , 0xf1f8, 0x01a8, 16},
{m68k_op_bclr_8_r_ix , 0xf1f8, 0x01b0, 18},
{m68k_op_bset_32_r_d , 0xf1f8, 0x01c0, 8},
{m68k_op_bset_32_r_d , 0xf1f8, 0x01c0, 6},
{m68k_op_movep_32_re , 0xf1f8, 0x01c8, 24},
{m68k_op_bset_8_r_ai , 0xf1f8, 0x01d0, 12},
{m68k_op_bset_8_r_pi , 0xf1f8, 0x01d8, 12},
@@ -23869,12 +23958,12 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_move_16_ix_pd , 0xf1f8, 0x31a0, 20},
{m68k_op_move_16_ix_di , 0xf1f8, 0x31a8, 22},
{m68k_op_move_16_ix_ix , 0xf1f8, 0x31b0, 24},
{m68k_op_chk_16_d , 0xf1f8, 0x4180, 10},
{m68k_op_chk_16_ai , 0xf1f8, 0x4190, 14},
{m68k_op_chk_16_pi , 0xf1f8, 0x4198, 14},
{m68k_op_chk_16_pd , 0xf1f8, 0x41a0, 16},
{m68k_op_chk_16_di , 0xf1f8, 0x41a8, 18},
{m68k_op_chk_16_ix , 0xf1f8, 0x41b0, 20},
{m68k_op_chk_16_d , 0xf1f8, 0x4180, 0},
{m68k_op_chk_16_ai , 0xf1f8, 0x4190, 4},
{m68k_op_chk_16_pi , 0xf1f8, 0x4198, 4},
{m68k_op_chk_16_pd , 0xf1f8, 0x41a0, 6},
{m68k_op_chk_16_di , 0xf1f8, 0x41a8, 8},
{m68k_op_chk_16_ix , 0xf1f8, 0x41b0, 10},
{m68k_op_lea_32_ai , 0xf1f8, 0x41d0, 4},
{m68k_op_lea_32_di , 0xf1f8, 0x41e8, 8},
{m68k_op_lea_32_ix , 0xf1f8, 0x41f0, 12},
@@ -23885,7 +23974,7 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_addq_8_di , 0xf1f8, 0x5028, 16},
{m68k_op_addq_8_ix , 0xf1f8, 0x5030, 18},
{m68k_op_addq_16_d , 0xf1f8, 0x5040, 4},
{m68k_op_addq_16_a , 0xf1f8, 0x5048, 4},
{m68k_op_addq_16_a , 0xf1f8, 0x5048, 8}, /* see Yacht.txt */
{m68k_op_addq_16_ai , 0xf1f8, 0x5050, 12},
{m68k_op_addq_16_pi , 0xf1f8, 0x5058, 12},
{m68k_op_addq_16_pd , 0xf1f8, 0x5060, 14},
@@ -24228,14 +24317,14 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_lsl_32_r , 0xf1f8, 0xe1a8, 8},
{m68k_op_roxl_32_r , 0xf1f8, 0xe1b0, 8},
{m68k_op_rol_32_r , 0xf1f8, 0xe1b8, 8},
{m68k_op_trap , 0xfff0, 0x4e40, 4},
{m68k_op_trap , 0xfff0, 0x4e40, 0},
{m68k_op_btst_8_r_pi7 , 0xf1ff, 0x011f, 8},
{m68k_op_btst_8_r_pd7 , 0xf1ff, 0x0127, 10},
{m68k_op_btst_8_r_aw , 0xf1ff, 0x0138, 12},
{m68k_op_btst_8_r_al , 0xf1ff, 0x0139, 16},
{m68k_op_btst_8_r_pcdi , 0xf1ff, 0x013a, 12},
{m68k_op_btst_8_r_pcix , 0xf1ff, 0x013b, 14},
{m68k_op_btst_8_r_i , 0xf1ff, 0x013c, 8},
{m68k_op_btst_8_r_i , 0xf1ff, 0x013c, 10},
{m68k_op_bchg_8_r_pi7 , 0xf1ff, 0x015f, 12},
{m68k_op_bchg_8_r_pd7 , 0xf1ff, 0x0167, 14},
{m68k_op_bchg_8_r_aw , 0xf1ff, 0x0178, 16},
@@ -24360,11 +24449,11 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_move_16_ix_pcdi , 0xf1ff, 0x31ba, 22},
{m68k_op_move_16_ix_pcix , 0xf1ff, 0x31bb, 24},
{m68k_op_move_16_ix_i , 0xf1ff, 0x31bc, 18},
{m68k_op_chk_16_aw , 0xf1ff, 0x41b8, 18},
{m68k_op_chk_16_al , 0xf1ff, 0x41b9, 22},
{m68k_op_chk_16_pcdi , 0xf1ff, 0x41ba, 18},
{m68k_op_chk_16_pcix , 0xf1ff, 0x41bb, 20},
{m68k_op_chk_16_i , 0xf1ff, 0x41bc, 14},
{m68k_op_chk_16_aw , 0xf1ff, 0x41b8, 8},
{m68k_op_chk_16_al , 0xf1ff, 0x41b9, 12},
{m68k_op_chk_16_pcdi , 0xf1ff, 0x41ba, 8},
{m68k_op_chk_16_pcix , 0xf1ff, 0x41bb, 10},
{m68k_op_chk_16_i , 0xf1ff, 0x41bc, 4},
{m68k_op_lea_32_aw , 0xf1ff, 0x41f8, 8},
{m68k_op_lea_32_al , 0xf1ff, 0x41f9, 12},
{m68k_op_lea_32_pcdi , 0xf1ff, 0x41fa, 8},
@@ -24595,7 +24684,7 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_andi_16_pd , 0xfff8, 0x0260, 18},
{m68k_op_andi_16_di , 0xfff8, 0x0268, 20},
{m68k_op_andi_16_ix , 0xfff8, 0x0270, 22},
{m68k_op_andi_32_d , 0xfff8, 0x0280, 14},
{m68k_op_andi_32_d , 0xfff8, 0x0280, 16}, /* see Yacht.txt */
{m68k_op_andi_32_ai , 0xfff8, 0x0290, 28},
{m68k_op_andi_32_pi , 0xfff8, 0x0298, 28},
{m68k_op_andi_32_pd , 0xfff8, 0x02a0, 30},
@@ -24643,19 +24732,19 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_btst_8_s_pd , 0xfff8, 0x0820, 14},
{m68k_op_btst_8_s_di , 0xfff8, 0x0828, 16},
{m68k_op_btst_8_s_ix , 0xfff8, 0x0830, 18},
{m68k_op_bchg_32_s_d , 0xfff8, 0x0840, 12},
{m68k_op_bchg_32_s_d , 0xfff8, 0x0840, 10},
{m68k_op_bchg_8_s_ai , 0xfff8, 0x0850, 16},
{m68k_op_bchg_8_s_pi , 0xfff8, 0x0858, 16},
{m68k_op_bchg_8_s_pd , 0xfff8, 0x0860, 18},
{m68k_op_bchg_8_s_di , 0xfff8, 0x0868, 20},
{m68k_op_bchg_8_s_ix , 0xfff8, 0x0870, 22},
{m68k_op_bclr_32_s_d , 0xfff8, 0x0880, 14},
{m68k_op_bclr_32_s_d , 0xfff8, 0x0880, 12},
{m68k_op_bclr_8_s_ai , 0xfff8, 0x0890, 16},
{m68k_op_bclr_8_s_pi , 0xfff8, 0x0898, 16},
{m68k_op_bclr_8_s_pd , 0xfff8, 0x08a0, 18},
{m68k_op_bclr_8_s_di , 0xfff8, 0x08a8, 20},
{m68k_op_bclr_8_s_ix , 0xfff8, 0x08b0, 22},
{m68k_op_bset_32_s_d , 0xfff8, 0x08c0, 12},
{m68k_op_bset_32_s_d , 0xfff8, 0x08c0, 10},
{m68k_op_bset_8_s_ai , 0xfff8, 0x08d0, 16},
{m68k_op_bset_8_s_pi , 0xfff8, 0x08d8, 16},
{m68k_op_bset_8_s_pd , 0xfff8, 0x08e0, 18},
@@ -24878,11 +24967,11 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_tst_32_di , 0xfff8, 0x4aa8, 16},
{m68k_op_tst_32_ix , 0xfff8, 0x4ab0, 18},
{m68k_op_tas_8_d , 0xfff8, 0x4ac0, 4},
{m68k_op_tas_8_ai , 0xfff8, 0x4ad0, 18},
{m68k_op_tas_8_pi , 0xfff8, 0x4ad8, 18},
{m68k_op_tas_8_pd , 0xfff8, 0x4ae0, 20},
{m68k_op_tas_8_di , 0xfff8, 0x4ae8, 22},
{m68k_op_tas_8_ix , 0xfff8, 0x4af0, 24},
{m68k_op_tas_8_ai , 0xfff8, 0x4ad0, 14}, /* see Yacht.txt */
{m68k_op_tas_8_pi , 0xfff8, 0x4ad8, 14}, /* see Yacht.txt */
{m68k_op_tas_8_pd , 0xfff8, 0x4ae0, 16}, /* see Yacht.txt */
{m68k_op_tas_8_di , 0xfff8, 0x4ae8, 18}, /* see Yacht.txt */
{m68k_op_tas_8_ix , 0xfff8, 0x4af0, 20}, /* see Yacht.txt */
{m68k_op_movem_16_er_ai , 0xfff8, 0x4c90, 12},
{m68k_op_movem_16_er_pi , 0xfff8, 0x4c98, 12},
{m68k_op_movem_16_er_di , 0xfff8, 0x4ca8, 16},
@@ -25242,10 +25331,10 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_tst_16_al , 0xffff, 0x4a79, 16},
{m68k_op_tst_32_aw , 0xffff, 0x4ab8, 16},
{m68k_op_tst_32_al , 0xffff, 0x4ab9, 20},
{m68k_op_tas_8_pi7 , 0xffff, 0x4adf, 18},
{m68k_op_tas_8_pd7 , 0xffff, 0x4ae7, 20},
{m68k_op_tas_8_aw , 0xffff, 0x4af8, 22},
{m68k_op_tas_8_al , 0xffff, 0x4af9, 26},
{m68k_op_tas_8_pi7 , 0xffff, 0x4adf, 14}, /* see Yacht.txt */
{m68k_op_tas_8_pd7 , 0xffff, 0x4ae7, 16}, /* see Yacht.txt */
{m68k_op_tas_8_aw , 0xffff, 0x4af8, 18}, /* see Yacht.txt */
{m68k_op_tas_8_al , 0xffff, 0x4af9, 22}, /* see Yacht.txt */
{m68k_op_illegal , 0xffff, 0x4afc, 4},
{m68k_op_movem_16_er_aw , 0xffff, 0x4cb8, 16},
{m68k_op_movem_16_er_al , 0xffff, 0x4cb9, 20},
@@ -25262,7 +25351,7 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_stop , 0xffff, 0x4e72, 4},
{m68k_op_rte_32 , 0xffff, 0x4e73, 20},
{m68k_op_rts_32 , 0xffff, 0x4e75, 16},
{m68k_op_trapv , 0xffff, 0x4e76, 4},
{m68k_op_trapv , 0xffff, 0x4e76, 0},
{m68k_op_rtr_32 , 0xffff, 0x4e77, 20},
{m68k_op_jsr_32_aw , 0xffff, 0x4eb8, 18},
{m68k_op_jsr_32_al , 0xffff, 0x4eb9, 20},
+4
View File
@@ -62,7 +62,11 @@
* access a word or longword at an odd address.
* NOTE: This is only emulated properly for 68000 mode.
*/
#ifdef ENABLE_SUB_68K_ADDRESS_ERROR_EXCEPTIONS
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
#else
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
#endif
/* If ON and previous option is also ON, address error exceptions will
also be checked when fetching instructions. Disabling this can help
+2 -2
View File
@@ -213,7 +213,7 @@ void s68k_update_irq(unsigned int mask)
CPU_INT_LEVEL = mask << 8;
#ifdef LOG_SCD
error("[%d][%d] IRQ Level = %d(0x%02x) (%x)\n", v_counter, s68k.cycles, CPU_INT_LEVEL>>8,FLAG_INT_MASK,s68k.pc);
error("[%d][%d] s68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, s68k.cycles, CPU_INT_LEVEL>>8,FLAG_INT_MASK,s68k.pc);
#endif
}
@@ -348,7 +348,7 @@ void s68k_pulse_halt(void)
CPU_STOPPED |= STOP_LEVEL_HALT;
}
void s68k_clear_halt()
void s68k_clear_halt(void)
{
/* Clear the HALT line on the CPU */
CPU_STOPPED &= ~STOP_LEVEL_HALT;
+115 -115
View File
@@ -19,16 +19,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -40,7 +40,7 @@ static const unsigned char m68ki_cycles[0x10000] =
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4,
22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 20*4, 24*4, 0*4, 0*4, 20*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4, 28*4,
30*4, 30*4, 30*4, 30*4, 30*4, 30*4, 30*4, 30*4, 32*4, 32*4, 32*4, 32*4, 32*4, 32*4, 32*4, 32*4,
34*4, 34*4, 34*4, 34*4, 34*4, 34*4, 34*4, 34*4, 32*4, 36*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -51,16 +51,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -83,16 +83,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -115,16 +115,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -132,31 +132,31 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 16*4, 18*4, 0*4, 0*4, 0*4, 0*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4,
22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 20*4, 24*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4,
22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 20*4, 24*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4,
22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 20*4, 24*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4,
22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 20*4, 24*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -179,16 +179,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -211,16 +211,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -243,16 +243,16 @@ static const unsigned char m68ki_cycles[0x10000] =
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 8*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 12*4, 16*4, 12*4, 14*4, 10*4, 0*4, 0*4, 0*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1048,10 +1048,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
@@ -1080,10 +1080,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
@@ -1112,10 +1112,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
@@ -1144,10 +1144,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
@@ -1176,10 +1176,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
@@ -1197,25 +1197,9 @@ static const unsigned char m68ki_cycles[0x10000] =
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4, 22*4,
24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 24*4, 22*4, 26*4, 0*4, 0*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 8*4, 12*4, 8*4, 12*4, 0*4, 0*4, 0*4, 0*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 0*4, 0*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1225,37 +1209,53 @@ static const unsigned char m68ki_cycles[0x10000] =
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 16*4, 18*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 16*4, 18*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 8*4, 12*4, 8*4, 12*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 8*4, 12*4, 8*4, 12*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 16*4, 18*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 16*4, 18*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 8*4, 12*4, 8*4, 12*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
0*4, 4*4, 4*4, 20*4, 0*4, 16*4, 4*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 4*4, 4*4, 20*4, 0*4, 16*4, 0*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
@@ -1272,10 +1272,10 @@ static const unsigned char m68ki_cycles[0x10000] =
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4,
16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4,
20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 20*4, 18*4, 22*4, 18*4, 20*4, 14*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 6*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 10*4, 8*4, 12*4, 8*4, 10*4, 4*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
@@ -1284,7 +1284,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1316,7 +1316,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1348,7 +1348,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1380,7 +1380,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1412,7 +1412,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1444,7 +1444,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1476,7 +1476,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
@@ -1508,7 +1508,7 @@ static const unsigned char m68ki_cycles[0x10000] =
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4,
4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 4*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4, 8*4,
12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4, 12*4,
14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 14*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4, 16*4,
18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 18*4, 16*4, 20*4, 0*4, 0*4, 0*4, 0*4, 0*4, 0*4,
+60 -10
View File
@@ -3,7 +3,7 @@
* Main 68k bus handlers
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -268,10 +268,16 @@ static void m68k_poll_sync(unsigned int reg_mask)
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
/* sync SUB-CPU with MAIN-CPU */
if (!s68k.stopped)
{
/* save current SUB-CPU end cycle count (recursive execution is possible) */
int end_cycle = s68k.cycle_end;
/* sync SUB-CPU with MAIN-CPU */
s68k_run(cycles);
/* restore SUB-CPU end cycle count */
s68k.cycle_end = end_cycle;
}
/* SUB-CPU idle on register polling ? */
@@ -354,8 +360,14 @@ unsigned int ctrl_io_read_byte(unsigned int address)
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
/* save current SUB-CPU end cycle count (recursive execution is possible) */
int end_cycle = s68k.cycle_end;
/* sync SUB-CPU with MAIN-CPU (Dracula Unleashed w/ Sega CD Model 2 Boot ROM) */
s68k_run(cycles);
/* restore SUB-CPU end cycle count */
s68k.cycle_end = end_cycle;
}
m68k_poll_detect(1<<0x0f);
@@ -527,8 +539,14 @@ unsigned int ctrl_io_read_word(unsigned int address)
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
/* save current SUB-CPU end cycle count (recursive execution is possible) */
int end_cycle = s68k.cycle_end;
/* sync SUB-CPU with MAIN-CPU (Soul Star) */
s68k_run(cycles);
/* restore SUB-CPU end cycle count */
s68k.cycle_end = end_cycle;
}
m68k_poll_detect(3 << (index - 0x10));
@@ -646,8 +664,14 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
/* save current SUB-CPU end cycle count (recursive execution is possible) */
int end_cycle = s68k.cycle_end;
/* sync SUB-CPU with MAIN-CPU (Earnest Evans, Fhey Area) */
s68k_run(cycles);
/* restore SUB-CPU end cycle count */
s68k.cycle_end = end_cycle;
}
/* set IFL2 flag */
@@ -753,7 +777,7 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
}
else
{
/* writing 0 to DMNA in 1M mode actually set DMNA bit */
/* writing 0 to DMNA in 1M mode actually sets DMNA bit */
data |= 0x02;
/* update BK0-1 & DMNA bits */
@@ -763,19 +787,32 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
}
else
{
/* writing 0 in 2M mode does nothing */
/* writing 0 to DMNA in 2M mode does nothing */
if (data & 0x02)
{
/* Word-RAM is assigned to SUB-CPU */
scd.dmna = 1;
/* clear RET bit */
/* clear RET bit and update BK0-1 & DMNA bits */
scd.regs[0x03>>1].byte.l = (scd.regs[0x03>>1].byte.l & ~0xc3) | (data & 0xc2);
/* check if graphics operation is running */
if (scd.regs[0x58>>1].byte.h & 0x80)
{
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
/* synchronize GFX processing with SUB-CPU (only if not already ahead) */
if (gfx.cycles < cycles)
{
gfx.cycles = cycles;
}
}
return;
}
}
/* update BK0-1 bits */
/* update BK0-1 bits only */
scd.regs[0x03>>1].byte.l = (scd.regs[0x02>>1].byte.l & ~0xc0) | (data & 0xc0);
return;
}
@@ -990,7 +1027,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
}
else
{
/* writing 0 to DMNA in 1M mode actually set DMNA bit */
/* writing 0 to DMNA in 1M mode actually sets DMNA bit */
data |= 0x02;
/* update WP0-7, BK0-1 & DMNA bits */
@@ -1000,19 +1037,32 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
}
else
{
/* writing 0 in 2M mode does nothing */
/* writing 0 to DMNA in 2M mode does nothing */
if (data & 0x02)
{
/* Word-RAM is assigned to SUB-CPU */
scd.dmna = 1;
/* clear RET bit */
/* clear RET bit and update WP0-7 & BK0-1 bits */
scd.regs[0x02>>1].w = (scd.regs[0x02>>1].w & ~0xffc3) | (data & 0xffc2);
/* check if graphics operation is running */
if (scd.regs[0x58>>1].byte.h & 0x80)
{
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
/* synchronize GFX processing with SUB-CPU (only if not already ahead) */
if (gfx.cycles < cycles)
{
gfx.cycles = cycles;
}
}
return;
}
}
/* update WP0-7 & BK0-1 bits */
/* update WP0-7 & BK0-1 bits only */
scd.regs[0x02>>1].w = (scd.regs[0x02>>1].w & ~0xffc0) | (data & 0xffc0);
return;
}
+1 -1
View File
@@ -3,7 +3,7 @@
* Main 68k bus handlers
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+4 -1
View File
@@ -3,7 +3,7 @@
* Z80 bank access to 68k bus
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2020 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -39,6 +39,9 @@
#include "shared.h"
t_zbank_memory_map zbank_memory_map[256];
/*
Handlers for access to unused addresses and those which make the
machine lock up.
+5 -3
View File
@@ -3,7 +3,7 @@
* Z80 bank access to 68k bus
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2020 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -49,10 +49,12 @@ extern void zbank_write_ctrl_io(unsigned int address, unsigned int data);
extern unsigned int zbank_read_vdp(unsigned int address);
extern void zbank_write_vdp(unsigned int address, unsigned int data);
struct _zbank_memory_map
typedef struct
{
unsigned int (*read)(unsigned int address);
void (*write)(unsigned int address, unsigned int data);
} zbank_memory_map[256];
} t_zbank_memory_map;
extern t_zbank_memory_map zbank_memory_map[256];
#endif /* _MEMBNK_H_ */
+24 -7
View File
@@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear & Mega Drive ports access
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -111,6 +111,8 @@ unsigned char z80_memory_r(unsigned int address)
{
if ((address >> 8) == 0x7F)
{
/* average Z80 wait-states when accessing 68k area */
Z80.cycles += 3 * 15;
return (*zbank_memory_map[0xc0].read)(address);
}
return z80_unused_r(address);
@@ -118,6 +120,9 @@ unsigned char z80_memory_r(unsigned int address)
default: /* $8000-$FFFF: 68k bank (32K) */
{
/* average Z80 wait-states when accessing 68k area */
Z80.cycles += 3 * 15;
address = zbank | (address & 0x7FFF);
if (zbank_memory_map[address >> 16].read)
{
@@ -158,6 +163,8 @@ void z80_memory_w(unsigned int address, unsigned char data)
case 0x7F: /* $7F00-$7FFF: VDP */
{
/* average Z80 wait-states when accessing 68k area */
Z80.cycles += 3 * 15;
(*zbank_memory_map[0xc0].write)(address, data);
return;
}
@@ -172,6 +179,9 @@ void z80_memory_w(unsigned int address, unsigned char data)
default: /* $8000-$FFFF: 68k bank (32K) */
{
/* average Z80 wait-states when accessing 68k area */
Z80.cycles += 3 * 15;
address = zbank | (address & 0x7FFF);
if (zbank_memory_map[address >> 16].write)
{
@@ -300,7 +310,7 @@ unsigned char z80_md_port_r(unsigned int port)
/* read FM chip if enabled */
if ((port >= 0xF0) && (config.ym2413 & 1))
{
return YM2413Read();
return fm_read(Z80.cycles, port);
}
return z80_unused_port_r(port);
@@ -578,7 +588,7 @@ unsigned char z80_ms_port_r(unsigned int port)
/* read FM board if enabled */
if (!(port & 4) && (config.ym2413 & 1))
{
data = YM2413Read();
data = fm_read(Z80.cycles, port);
}
/* read I/O ports if enabled */
@@ -629,10 +639,17 @@ void z80_m3_port_w(unsigned int port, unsigned char data)
default:
{
/* write FM chip if enabled */
/* write to FM sound unit (FM-70) if enabled */
if (!(port & 4) && (config.ym2413 & 1))
{
fm_write(Z80.cycles, port, data);
/* FM output control "register" */
if (port & 2)
{
/* PSG output is automatically disabled (resp. enabled) by FM sound unit hardware if FM output is enabled (resp. disabled) */
psg_config(Z80.cycles, config.psg_preamp, (data & 0x01) ? 0x00 : 0xff);
}
return;
}
@@ -674,11 +691,11 @@ unsigned char z80_m3_port_r(unsigned int port)
default:
{
/* read FM chip if enabled */
/* read FM sound unit (FM-70) if enabled */
if (!(port & 4) && (config.ym2413 & 1))
{
/* I/O ports are automatically disabled by hardware */
return YM2413Read();
/* I/O ports are automatically disabled by FM sound unit hardware */
return fm_read(Z80.cycles, port);
}
/* read I/O ports */
+1 -1
View File
@@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear & Mega Drive ports access
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+2 -2
View File
@@ -88,6 +88,7 @@ void sms_ntsc_init( sms_ntsc_t* ntsc, sms_ntsc_setup_t const* setup )
void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned char* input,
int in_width, int vline)
{
int n;
int const chunk_count = in_width / sms_ntsc_in_chunk;
/* handle extra 0, 1, or 2 pixels by placing them at beginning of row */
@@ -102,9 +103,8 @@ void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned
(SMS_NTSC_ADJ_IN( table[input[0]] )) & extra2,
(SMS_NTSC_ADJ_IN( table[input[extra2 & 1]] )) & extra1 );
sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*)(&bitmap.data[(vline * bitmap.pitch)]);
sms_ntsc_out_t* line_out = (sms_ntsc_out_t*)(&bitmap.data[(vline * bitmap.pitch)]);
int n;
input += in_extra;
for ( n = chunk_count; n; --n )
+3
View File
@@ -28,6 +28,9 @@
#ifdef HAVE_YM3438_CORE
#include "ym3438.h"
#endif
#ifdef HAVE_OPLL_CORE
#include "opll.h"
#endif
#include "sram.h"
#include "ggenie.h"
#include "areplay.h"
File diff suppressed because it is too large Load Diff
+215
View File
@@ -0,0 +1,215 @@
/*
* Copyright (C) 2019 Nuke.YKT
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
*
* - Redistributions may not be sold, nor may they be used in a commercial
* product or activity.
*
* - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable.
*
* - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* Yamaha YM2413 emulator
* Thanks:
* siliconpr0n.org(digshadow, John McMaster):
* VRC VII decap and die shot.
*
* version: 1.0
*/
#ifndef OPLL_H
#define OPLL_H
#include <stdint.h>
enum {
opll_type_ym2413 = 0x00, /* Yamaha YM2413 */
opll_type_ds1001, /* Konami VRC VII */
opll_type_ym2413b /* Yamaha YM2413B */
};
enum {
opll_patch_1 = 0x00,
opll_patch_2,
opll_patch_3,
opll_patch_4,
opll_patch_5,
opll_patch_6,
opll_patch_7,
opll_patch_8,
opll_patch_9,
opll_patch_10,
opll_patch_11,
opll_patch_12,
opll_patch_13,
opll_patch_14,
opll_patch_15,
opll_patch_drum_0,
opll_patch_drum_1,
opll_patch_drum_2,
opll_patch_drum_3,
opll_patch_drum_4,
opll_patch_drum_5,
opll_patch_max
};
typedef struct {
uint8_t tl;
uint8_t dc;
uint8_t dm;
uint8_t fb;
uint8_t am[2];
uint8_t vib[2];
uint8_t et[2];
uint8_t ksr[2];
uint8_t multi[2];
uint8_t ksl[2];
uint8_t ar[2];
uint8_t dr[2];
uint8_t sl[2];
uint8_t rr[2];
} opll_patch_t;
typedef struct {
uint32_t chip_type;
uint32_t cycles;
uint32_t slot;
const opll_patch_t *patchrom;
/* IO */
uint8_t write_data;
uint8_t write_a;
uint8_t write_d;
uint8_t write_a_en;
uint8_t write_d_en;
uint8_t write_fm_address;
uint8_t write_fm_data;
uint8_t write_mode_address;
uint8_t address;
uint8_t data;
/* Envelope generator */
uint8_t eg_counter_state;
uint8_t eg_counter_state_prev;
uint32_t eg_timer;
uint8_t eg_timer_low_lock;
uint8_t eg_timer_carry;
uint8_t eg_timer_shift;
uint8_t eg_timer_shift_lock;
uint8_t eg_timer_shift_stop;
uint8_t eg_state[18];
uint8_t eg_level[18];
uint8_t eg_kon;
uint32_t eg_dokon;
uint8_t eg_off;
uint8_t eg_rate;
uint8_t eg_maxrate;
uint8_t eg_zerorate;
uint8_t eg_inc_lo;
uint8_t eg_inc_hi;
uint8_t eg_rate_hi;
uint16_t eg_sl;
uint16_t eg_ksltl;
uint8_t eg_out;
uint8_t eg_silent;
/* Phase generator */
uint16_t pg_fnum;
uint8_t pg_block;
uint16_t pg_out;
uint32_t pg_inc;
uint32_t pg_phase[18];
uint32_t pg_phase_next;
/* Operator */
int16_t op_fb1[9];
int16_t op_fb2[9];
int16_t op_fbsum;
int16_t op_mod;
uint8_t op_neg;
uint16_t op_logsin;
uint16_t op_exp_m;
uint16_t op_exp_s;
/* Channel */
int16_t ch_out;
int16_t ch_out_hh;
int16_t ch_out_tm;
int16_t ch_out_bd;
int16_t ch_out_sd;
int16_t ch_out_tc;
/* LFO */
uint16_t lfo_counter;
uint8_t lfo_vib_counter;
uint16_t lfo_am_counter;
uint8_t lfo_am_step;
uint8_t lfo_am_dir;
uint8_t lfo_am_car;
uint8_t lfo_am_out;
/* Register set */
uint16_t fnum[9];
uint8_t block[9];
uint8_t kon[9];
uint8_t son[9];
uint8_t vol[9];
uint8_t inst[9];
uint8_t rhythm;
uint8_t testmode;
opll_patch_t patch;
uint8_t c_instr;
uint8_t c_op;
uint8_t c_tl;
uint8_t c_dc;
uint8_t c_dm;
uint8_t c_fb;
uint8_t c_am;
uint8_t c_vib;
uint8_t c_et;
uint8_t c_ksr;
uint8_t c_ksr_freq;
uint8_t c_ksl_freq;
uint8_t c_ksl_block;
uint8_t c_multi;
uint8_t c_ksl;
uint8_t c_adrr[3];
uint8_t c_sl;
uint16_t c_fnum;
uint16_t c_block;
/* Rhythm mode */
int8_t rm_enable;
uint32_t rm_noise;
uint32_t rm_select;
uint8_t rm_hh_bit2;
uint8_t rm_hh_bit3;
uint8_t rm_hh_bit7;
uint8_t rm_hh_bit8;
uint8_t rm_tc_bit3;
uint8_t rm_tc_bit5;
int16_t output_m;
int16_t output_r;
} opll_t;
void OPLL_Reset(opll_t *chip, uint32_t chip_type);
void OPLL_Clock(opll_t *chip, int32_t *buffer);
void OPLL_Write(opll_t *chip, uint32_t port, uint8_t data);
#endif
+1 -1
View File
@@ -112,7 +112,7 @@ void psg_init(PSG_TYPE type)
psg.noiseBitMask = noiseBitMask[type];
}
void psg_reset()
void psg_reset(void)
{
int i;
+327 -136
View File
@@ -3,7 +3,7 @@
* Sound Hardware
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2020 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -40,8 +40,11 @@
#include "shared.h"
#include "blip_buf.h"
/* YM2612 internal clock = input clock / 6 = (master clock / 7) / 6 */
#define YM2612_CLOCK_RATIO (7*6)
/* FM output buffer (large enough to hold a whole frame at original chips rate) */
#ifdef HAVE_YM3438_CORE
#if defined(HAVE_YM3438_CORE) || defined(HAVE_OPLL_CORE)
static int fm_buffer[1080 * 2 * 24];
#else
static int fm_buffer[1080 * 2];
@@ -51,28 +54,134 @@ static int fm_last[2];
static int *fm_ptr;
/* Cycle-accurate FM samples */
static uint32 fm_cycles_ratio;
static uint32 fm_cycles_start;
static uint32 fm_cycles_count;
static int fm_cycles_ratio;
static int fm_cycles_start;
static int fm_cycles_count;
static int fm_cycles_busy;
/* YM chip function pointers */
static void (*YM_Reset)(void);
static void (*YM_Update)(int *buffer, int length);
static void (*YM_Write)(unsigned int a, unsigned int v);
static unsigned int (*YM_Read)(unsigned int a);
void (*fm_reset)(unsigned int cycles);
void (*fm_write)(unsigned int cycles, unsigned int address, unsigned int data);
unsigned int (*fm_read)(unsigned int cycles, unsigned int address);
#ifdef HAVE_YM3438_CORE
static ym3438_t ym3438;
static int ym3438_accm[24][2];
static short ym3438_accm[24][2];
static int ym3438_sample[2];
static unsigned int ym3438_cycles;
static int ym3438_cycles;
#endif
void YM3438_Reset(void)
#ifdef HAVE_OPLL_CORE
static opll_t opll;
static int opll_accm[18][2];
static int opll_sample;
static int opll_cycles;
static int opll_status;
#endif
/* Run FM chip until required M-cycles */
INLINE void fm_update(int cycles)
{
OPN2_Reset(&ym3438);
if (cycles > fm_cycles_count)
{
/* number of samples to run */
int samples = (cycles - fm_cycles_count + fm_cycles_ratio - 1) / fm_cycles_ratio;
/* run FM chip to sample buffer */
YM_Update(fm_ptr, samples);
/* update FM buffer pointer */
fm_ptr += (samples * 2);
/* update FM cycle counter */
fm_cycles_count += (samples * fm_cycles_ratio);
}
}
void YM3438_Update(int *buffer, int length)
static void YM2612_Reset(unsigned int cycles)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* reset FM chip */
YM2612ResetChip();
fm_cycles_busy = 0;
}
static void YM2612_Write(unsigned int cycles, unsigned int a, unsigned int v)
{
/* detect DATA port write */
if (a & 1)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* set FM BUSY end cycle (discrete or ASIC-integrated YM2612 chip only) */
if (config.ym2612 < YM2612_ENHANCED)
{
fm_cycles_busy = (((cycles + YM2612_CLOCK_RATIO - 1) / YM2612_CLOCK_RATIO) + 32) * YM2612_CLOCK_RATIO;
}
}
/* write FM register */
YM2612Write(a, v);
}
static unsigned int YM2612_Read(unsigned int cycles, unsigned int a)
{
/* FM status can only be read from (A0,A1)=(0,0) on discrete YM2612 */
if ((a == 0) || (config.ym2612 > YM2612_DISCRETE))
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* read FM status */
if (cycles >= fm_cycles_busy)
{
/* BUSY flag cleared */
return YM2612Read();
}
else
{
/* BUSY flag set */
return YM2612Read() | 0x80;
}
}
/* invalid FM status address */
return 0x00;
}
static void YM2413_Reset(unsigned int cycles)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* reset FM chip */
YM2413ResetChip();
}
static void YM2413_Write(unsigned int cycles, unsigned int a, unsigned int v)
{
/* detect DATA port write */
if (a & 1)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
}
/* write FM register */
YM2413Write(a, v);
}
static unsigned int YM2413_Read(unsigned int cycles, unsigned int a)
{
return YM2413Read();
}
#ifdef HAVE_YM3438_CORE
static void YM3438_Update(int *buffer, int length)
{
int i, j;
for (i = 0; i < length; i++)
@@ -94,36 +203,87 @@ void YM3438_Update(int *buffer, int length)
}
}
void YM3438_Write(unsigned int a, unsigned int v)
static void YM3438_Reset(unsigned int cycles)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* reset FM chip */
OPN2_Reset(&ym3438);
}
static void YM3438_Write(unsigned int cycles, unsigned int a, unsigned int v)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* write FM register */
OPN2_Write(&ym3438, a, v);
}
unsigned int YM3438_Read(unsigned int a)
static unsigned int YM3438_Read(unsigned int cycles, unsigned int a)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* read FM status */
return OPN2_Read(&ym3438, a);
}
#endif
/* Run FM chip until required M-cycles */
INLINE void fm_update(unsigned int cycles)
#ifdef HAVE_OPLL_CORE
static void OPLL2413_Update(int* buffer, int length)
{
if (cycles > fm_cycles_count)
int i, j;
for (i = 0; i < length; i++)
{
/* number of samples to run */
unsigned int samples = (cycles - fm_cycles_count + fm_cycles_ratio - 1) / fm_cycles_ratio;
/* run FM chip to sample buffer */
YM_Update(fm_ptr, samples);
/* update FM buffer pointer */
fm_ptr += (samples << 1);
/* update FM cycle counter */
fm_cycles_count += samples * fm_cycles_ratio;
OPLL_Clock(&opll, opll_accm[opll_cycles]);
opll_cycles = (opll_cycles + 1) % 18;
if (opll_cycles == 0)
{
opll_sample = 0;
for (j = 0; j < 18; j++)
{
opll_sample += opll_accm[j][0] + opll_accm[j][1];
}
}
*buffer++ = opll_sample * 16 * opll_status;
*buffer++ = opll_sample * 16 * opll_status;
}
}
static void OPLL2413_Reset(unsigned int cycles)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* reset FM chip */
OPLL_Reset(&opll, opll_type_ym2413);
}
static void OPLL2413_Write(unsigned int cycles, unsigned int a, unsigned int v)
{
if (!(a&2))
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* write FM register */
OPLL_Write(&opll, a, v);
}
else
{
opll_status = v&1;
}
}
static unsigned int OPLL2413_Read(unsigned int cycles, unsigned int a)
{
return 0xf8 | opll_status;
}
#endif
void sound_init( void )
{
/* Initialize FM chip */
@@ -137,40 +297,60 @@ void sound_init( void )
memset(&ym3438, 0, sizeof(ym3438));
memset(&ym3438_sample, 0, sizeof(ym3438_sample));
memset(&ym3438_accm, 0, sizeof(ym3438_accm));
YM_Reset = YM3438_Reset;
YM_Update = YM3438_Update;
YM_Write = YM3438_Write;
YM_Read = YM3438_Read;
fm_reset = YM3438_Reset;
fm_write = YM3438_Write;
fm_read = YM3438_Read;
/* chip is running at VCLK / 6 = MCLK / 7 / 6 */
fm_cycles_ratio = 6 * 7;
/* chip is running at internal clock */
fm_cycles_ratio = YM2612_CLOCK_RATIO;
}
else
#endif
{
/* MAME */
/* MAME OPN2*/
YM2612Init();
YM2612Config(config.dac_bits);
YM_Reset = YM2612ResetChip;
YM2612Config(config.ym2612);
YM_Update = YM2612Update;
YM_Write = YM2612Write;
YM_Read = YM2612Read;
fm_reset = YM2612_Reset;
fm_write = YM2612_Write;
fm_read = YM2612_Read;
/* chip is running at VCLK / 144 = MCLK / 7 / 144 */
fm_cycles_ratio = 144 * 7;
/* chip is running at sample clock */
fm_cycles_ratio = YM2612_CLOCK_RATIO * 24;
}
}
else
{
/* YM2413 */
YM2413Init();
YM_Reset = YM2413ResetChip;
YM_Update = YM2413Update;
YM_Write = YM2413Write;
YM_Read = NULL;
#ifdef HAVE_OPLL_CORE
if (config.opll)
{
/* Nuked OPLL */
memset(&opll, 0, sizeof(opll));
memset(&opll_accm, 0, sizeof(opll_accm));
opll_sample = 0;
opll_status = 0;
YM_Update = (config.ym2413 & 1) ? OPLL2413_Update : NULL;
fm_reset = OPLL2413_Reset;
fm_write = OPLL2413_Write;
fm_read = OPLL2413_Read;
/* chip is running at ZCLK / 72 = MCLK / 15 / 72 */
fm_cycles_ratio = 72 * 15;
/* chip is running at internal clock */
fm_cycles_ratio = 4 * 15;
}
else
#endif
{
YM2413Init();
YM_Update = (config.ym2413 & 1) ? YM2413Update : NULL;
fm_reset = YM2413_Reset;
fm_write = YM2413_Write;
fm_read = YM2413_Read;
/* chip is running at ZCLK / 72 = MCLK / 15 / 72 */
fm_cycles_ratio = 72 * 15;
}
}
/* Initialize PSG chip */
@@ -180,7 +360,7 @@ void sound_init( void )
void sound_reset(void)
{
/* reset sound chips */
YM_Reset();
fm_reset(0);
psg_reset();
psg_config(0, config.psg_preamp, 0xff);
@@ -196,73 +376,85 @@ void sound_reset(void)
int sound_update(unsigned int cycles)
{
int prev_l, prev_r, preamp, time, l, r, *ptr;
/* Run PSG chip until end of frame */
psg_end_frame(cycles);
/* Run FM chip until end of frame */
fm_update(cycles);
/* FM output pre-amplification */
preamp = config.fm_preamp;
/* FM frame initial timestamp */
time = fm_cycles_start;
/* Restore last FM outputs from previous frame */
prev_l = fm_last[0];
prev_r = fm_last[1];
/* FM buffer start pointer */
ptr = fm_buffer;
/* flush FM samples */
if (config.hq_fm)
/* FM chip is enabled ? */
if (YM_Update)
{
/* high-quality Band-Limited synthesis */
do
int prev_l, prev_r, preamp, time, l, r, *ptr;
/* Run FM chip until end of frame */
fm_update(cycles);
/* FM output pre-amplification */
preamp = config.fm_preamp;
/* FM frame initial timestamp */
time = fm_cycles_start;
/* Restore last FM outputs from previous frame */
prev_l = fm_last[0];
prev_r = fm_last[1];
/* FM buffer start pointer */
ptr = fm_buffer;
/* flush FM samples */
if (config.hq_fm)
{
/* left & right channels */
l = ((*ptr++ * preamp) / 100);
r = ((*ptr++ * preamp) / 100);
blip_add_delta(snd.blips[0], time, l-prev_l, r-prev_r);
prev_l = l;
prev_r = r;
/* high-quality Band-Limited synthesis */
do
{
/* left & right channels */
l = ((*ptr++ * preamp) / 100);
r = ((*ptr++ * preamp) / 100);
blip_add_delta(snd.blips[0], time, l-prev_l, r-prev_r);
prev_l = l;
prev_r = r;
/* increment time counter */
time += fm_cycles_ratio;
/* increment time counter */
time += fm_cycles_ratio;
}
while (time < cycles);
}
while (time < cycles);
}
else
{
/* faster Linear Interpolation */
do
else
{
/* left & right channels */
l = ((*ptr++ * preamp) / 100);
r = ((*ptr++ * preamp) / 100);
blip_add_delta_fast(snd.blips[0], time, l-prev_l, r-prev_r);
prev_l = l;
prev_r = r;
/* faster Linear Interpolation */
do
{
/* left & right channels */
l = ((*ptr++ * preamp) / 100);
r = ((*ptr++ * preamp) / 100);
blip_add_delta_fast(snd.blips[0], time, l-prev_l, r-prev_r);
prev_l = l;
prev_r = r;
/* increment time counter */
time += fm_cycles_ratio;
/* increment time counter */
time += fm_cycles_ratio;
}
while (time < cycles);
}
/* reset FM buffer pointer */
fm_ptr = fm_buffer;
/* save last FM output for next frame */
fm_last[0] = prev_l;
fm_last[1] = prev_r;
/* adjust FM cycle counters for next frame */
fm_cycles_count = fm_cycles_start = time - cycles;
if (fm_cycles_busy > cycles)
{
fm_cycles_busy -= cycles;
}
else
{
fm_cycles_busy = 0;
}
while (time < cycles);
}
/* reset FM buffer pointer */
fm_ptr = fm_buffer;
/* save last FM output for next frame */
fm_last[0] = prev_l;
fm_last[1] = prev_r;
/* adjust FM cycle counters for next frame */
fm_cycles_count = fm_cycles_start = time - cycles;
/* end of blip buffer time frame */
blip_end_frame(snd.blips[0], cycles);
@@ -288,7 +480,6 @@ int sound_context_save(uint8 *state)
else
{
bufferptr += YM2612SaveContext(state + sizeof(config.ym3438));
YM2612Config(config.dac_bits);
}
#else
bufferptr = YM2612SaveContext(state);
@@ -296,7 +487,21 @@ int sound_context_save(uint8 *state)
}
else
{
save_param(YM2413GetContextPtr(),YM2413GetContextSize());
#ifdef HAVE_OPLL_CORE
save_param(&config.opll, sizeof(config.opll));
if (config.opll)
{
save_param(&opll, sizeof(opll));
save_param(&opll_accm, sizeof(opll_accm));
save_param(&opll_sample, sizeof(opll_sample));
save_param(&opll_cycles, sizeof(opll_cycles));
save_param(&opll_status, sizeof(opll_status));
}
else
#endif
{
save_param(YM2413GetContextPtr(),YM2413GetContextSize());
}
}
bufferptr += psg_context_save(&state[bufferptr]);
@@ -325,16 +530,29 @@ int sound_context_load(uint8 *state)
else
{
bufferptr += YM2612LoadContext(state + sizeof(config_ym3438));
YM2612Config(config.dac_bits);
}
#else
bufferptr = YM2612LoadContext(state);
YM2612Config(config.dac_bits);
#endif
}
else
{
load_param(YM2413GetContextPtr(),YM2413GetContextSize());
#ifdef HAVE_OPLL_CORE
uint8 config_opll;
load_param(&config_opll, sizeof(config_opll));
if (config_opll)
{
load_param(&opll, sizeof(opll));
load_param(&opll_accm, sizeof(opll_accm));
load_param(&opll_sample, sizeof(opll_sample));
load_param(&opll_cycles, sizeof(opll_cycles));
load_param(&opll_status, sizeof(opll_status));
}
else
#endif
{
load_param(YM2413GetContextPtr(),YM2413GetContextSize());
}
}
bufferptr += psg_context_load(&state[bufferptr]);
@@ -344,30 +562,3 @@ int sound_context_load(uint8 *state)
return bufferptr;
}
void fm_reset(unsigned int cycles)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* reset FM chip */
YM_Reset();
}
void fm_write(unsigned int cycles, unsigned int address, unsigned int data)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* write FM register */
YM_Write(address, data);
}
unsigned int fm_read(unsigned int cycles, unsigned int address)
{
/* synchronize FM chip with CPU */
fm_update(cycles);
/* read FM status (YM2612 only) */
return YM_Read(address);
}
+4 -4
View File
@@ -3,7 +3,7 @@
* Sound Hardware
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2020 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -46,8 +46,8 @@ extern void sound_reset(void);
extern int sound_context_save(uint8 *state);
extern int sound_context_load(uint8 *state);
extern int sound_update(unsigned int cycles);
extern void fm_reset(unsigned int cycles);
extern void fm_write(unsigned int cycles, unsigned int address, unsigned int data);
extern unsigned int fm_read(unsigned int cycles, unsigned int address);
extern void (*fm_reset)(unsigned int cycles);
extern void (*fm_write)(unsigned int cycles, unsigned int address, unsigned int data);
extern unsigned int (*fm_read)(unsigned int cycles, unsigned int address);
#endif /* _SOUND_H_ */
+246 -138
View File
@@ -25,7 +25,22 @@ to do:
*/
/** EkeEke (2011): removed multiple chips support, cleaned code & added FM board interface for Genesis Plus GX **/
/************************************************/
/** Modifications for Genesis Plus GX (EkeEke) **/
/************************************************/
/** 2011/xx/xx: removed multiple chips support, cleaned code & added FM board interface **/
/** 2021/04/23: fixed synchronization of carrier/modulator phase reset after channel Key ON (fixes Japanese Master System BIOS music) **/
/** 2021/04/24: fixed intruments ROM (verified on YM2413B die, cf. https://siliconpr0n.org/archive/doku.php?id=vendor:yamaha:opl2#ym2413_instrument_rom) **/
/** 2021/04/24: fixed EG resolution bits (verified on YM2413B die, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2015-03-20) **/
/** 2021/04/24: fixed EG dump rate (verified on YM2413 real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2015-12-31) **/
/** 2021/04/25: fixed EG behavior for fastest attack rates (verified on YM2413 real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2017-01-26) **/
/** 2021/04/25: fixed EG behavior when SL = 0 (verified on YM2413 real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2015-12-24) **/
/** 2021/04/25: improved EG sustain phase transition comparator accuracy (verified on YM2413 real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2015-12-31) **/
/** 2021/05/04: improved EG increment steps accuracy (verified on YM2413 real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2015-03-20) **/
/** 2021/05/08: improved EG transitions accuracy (verified against https://github.com/nukeykt/Nuked-OPLL/blob/master/opll.c) **/
/** 2021/05/11: improved EG attack phase algorithm accuracy (verified on YM2413 real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2017-01-26) **/
/** 2022/08/07: fixed operator ouput when EG is off **/
/************************************************/
#include "shared.h"
@@ -40,7 +55,7 @@ to do:
#define ENV_LEN (1<<ENV_BITS)
#define ENV_STEP (128.0/ENV_LEN)
#define MAX_ATT_INDEX ((1<<(ENV_BITS-2))-1) /*255*/
#define MAX_ATT_INDEX ((1<<(ENV_BITS-3))-1) /*127*/
#define MIN_ATT_INDEX (0)
/* sinwave entries */
@@ -89,7 +104,7 @@ typedef struct
UINT8 eg_sh_dp; /* (dump state) */
UINT8 eg_sel_dp; /* (dump state) */
UINT8 eg_sh_ar; /* (attack state) */
UINT8 eg_sel_ar; /* (attack state) */
UINT16 eg_sel_ar; /* (attack state) */
UINT8 eg_sh_dr; /* (decay state) */
UINT8 eg_sel_dr; /* (decay state) */
UINT8 eg_sh_rr; /* (release state for non-perc.) */
@@ -219,67 +234,100 @@ static const UINT32 sl_tab[16]={
#undef SC
#define RATE_STEPS (8)
static const unsigned char eg_inc[15*RATE_STEPS]={
#define RATE_STEPS (16)
/*cycle:0 1 2 3 4 5 6 7*/
static const unsigned char eg_inc[14*RATE_STEPS]={
/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */
/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */
/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */
/*cycle:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15*/
/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */
/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */
/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */
/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */
/* 0 */ 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, /* infinity rates for decay(s) */
/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */
/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */
/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */
/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */
/* 1 */ 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, /* rates 01..12 0 for decay(s) (increment by 0 or 1) */
/* 2 */ 0,1, 1,1, 0,1, 0,1, 0,1, 1,1, 0,1, 0,1, /* rates 01..12 1 for decay(s) */
/* 3 */ 0,1, 1,1, 0,1, 1,1, 0,1, 1,1, 0,1, 1,1, /* rates 01..12 2 for decay(s) */
/* 4 */ 0,1, 1,1, 1,1, 1,1, 0,1, 1,1, 1,1, 1,1, /* rates 01..12 3 for decay(s) */
/* 5 */ 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, /* rate 13 0 for decay(s) (increment by 0 or 1) */
/* 6 */ 0,1, 0,1, 1,1, 1,1, 0,1, 0,1, 0,1, 0,1, /* rate 13 1 for decay(s) */
/* 7 */ 0,1, 0,1, 1,1, 1,1, 0,1, 0,1, 1,1, 1,1, /* rate 13 2 for decay(s) */
/* 8 */ 0,1, 0,1, 1,1, 1,1, 1,1, 1,1, 1,1, 1,1, /* rate 13 3 for decay(s) */
/* 9 */ 1,1, 1,1, 1,1, 1,1, 1,1, 1,1, 1,1, 1,1, /* rate 14 0 for decay(s) (increment by 1) */
/*10 */ 1,1, 1,1, 2,2, 2,2, 1,1, 1,1, 1,1, 1,1, /* rate 14 1 for decay(s) */
/*11 */ 1,1, 1,1, 2,2, 2,2, 1,1, 1,1, 2,2, 2,2, /* rate 14 2 for decay(s) */
/*12 */ 1,1, 1,1, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, /* rate 14 3 for decay(s) */
/*13 */ 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, /* rates 15 0, 15 1, 15 2, 15 3 for decay(s) (increment by 2) */
/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */
/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */
/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
};
static const unsigned char eg_mul[17*RATE_STEPS]={
/*cycle:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15*/
/* 0 */ 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack */
/* 1 */ 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1, /* rates 01..11 0 for attack */
/* 2 */ 0,1, 1,1, 0,1, 0,1, 0,1, 1,1, 0,1, 0,1, /* rates 01..11 1 for attack */
/* 3 */ 0,1, 1,1, 0,1, 1,1, 0,1, 1,1, 0,1, 1,1, /* rates 01..11 2 for attack */
/* 4 */ 0,1, 1,1, 1,1, 1,1, 0,1, 1,1, 1,1, 1,1, /* rates 01..11 3 for attack */
/* 5 */ 1,1, 1,1, 1,1, 1,1, 1,1, 1,1, 1,1, 1,1, /* rate 12 0 for attack */
/* 6 */ 1,1, 1,1, 2,2, 2,2, 1,1, 1,1, 1,1, 1,1, /* rate 12 1 for attack */
/* 7 */ 1,1, 1,1, 2,2, 2,2, 1,1, 1,1, 2,2, 2,2, /* rate 12 2 for attack */
/* 8 */ 1,1, 1,1, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, /* rate 12 3 for attack */
/* 9 */ 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, /* rate 13 0 for attack */
/*10 */ 2,2, 2,2, 4,4, 4,4, 2,2, 2,2, 2,2, 2,2, /* rate 13 1 for attack */
/*11 */ 2,2, 2,2, 4,4, 4,4, 2,2, 2,2, 4,4, 4,4, /* rate 13 2 for attack */
/*12 */ 2,2, 2,2, 4,4, 4,4, 4,4, 4,4, 4,4, 4,4, /* rate 13 3 for attack */
/*13 */ 4,4, 4,4, 4,4, 4,4, 4,4, 4,4, 4,4, 4,4, /* rate 14 0 for attack */
/*14 */ 4,4, 4,4, 8,8, 8,8, 4,4, 4,4, 4,4, 4,4, /* rate 14 1 for attack */
/*15 */ 4,4, 4,4, 8,8, 8,8, 4,4, 4,4, 8,8, 8,8, /* rate 14 2 for attack */
/*16 */ 4,4, 4,4, 8,8, 8,8, 8,8, 8,8, 8,8, 8,8, /* rate 14 3 for attack */
};
#define O(a) (a*RATE_STEPS)
/*note that there is no O(13) in this table - it's directly in the code */
static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */
/* 16 infinite time rates */
O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
/* rates 00-12 */
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
/* rate 00 */
O( 0),O( 0),O( 0),O( 0), /* never used since infinite time rates are directly forced in the code for rate 00 */
/* rate 13 */
O( 4),O( 5),O( 6),O( 7),
/* rates 01-11 */
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
O( 1),O( 2),O( 3),O( 4),
/* rate 14 */
O( 8),O( 9),O(10),O(11),
/* rate 12 */ /* only used for decay(s), handled directly in the code for attack */
O( 1),O( 2),O( 3),O( 4),
/* rate 15 */
O(12),O(12),O(12),O(12),
/* rate 13 */ /* only used for decay(s), handled directly in the code for attack */
O( 5),O( 6),O( 7),O( 8),
/* rate 14 */ /* only used for decay(s), handled directly in the code for attack */
O( 9),O(10),O(11),O(12),
/* rate 15 */ /* only used for decay(s), handled directly in the code for attack */
O(13),O(13),O(13),O(13),
/* 16 dummy rates (same as 15 3) */
O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
O(13),O(13),O(13),O(13),O(13),O(13),O(13),O(13),
O(13),O(13),O(13),O(13),O(13),O(13),O(13),O(13),
};
#undef O
@@ -287,15 +335,19 @@ O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */
/*shift 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0 */
/*mask 8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0 */
/*NB: for attack, above mask values lower 2 bits are cleared and rate 12 shift value is equal to 0 */
#define O(a) (a*1)
static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
/* 16 infinite time rates */
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
/* rates 00-12 */
O(13),O(13),O(13),O(13),
/* 16 infinite time rates */
O(13),O(13),O(13),O(13),O(13),O(13),O(13),O(13),
O(13),O(13),O(13),O(13),O(13),O(13),O(13),O(13),
/* rate 00 */
O(13),O(13),O(13),O(13), /* never used since infinite time rates are directly forced in the code for rate 00 */
/* rates 01-11 */
O(12),O(12),O(12),O(12),
O(11),O(11),O(11),O(11),
O(10),O(10),O(10),O(10),
@@ -307,15 +359,17 @@ O( 5),O( 5),O( 5),O( 5),
O( 4),O( 4),O( 4),O( 4),
O( 3),O( 3),O( 3),O( 3),
O( 2),O( 2),O( 2),O( 2),
/* rate 12 */ /* only used for decay(s), handled directly in the code for attack */
O( 1),O( 1),O( 1),O( 1),
/* rate 13 */
/* rate 13 */ /* only used for decay(s), handled directly in the code for attack */
O( 0),O( 0),O( 0),O( 0),
/* rate 14 */
/* rate 14 */ /* only used for decay(s), handled directly in the code for attack */
O( 0),O( 0),O( 0),O( 0),
/* rate 15 */
/* rate 15 */ /* only used for decay(s), handled directly in the code for attack */
O( 0),O( 0),O( 0),O( 0),
/* 16 dummy rates (same as 15 3) */
@@ -455,45 +509,71 @@ static const INT8 lfo_pm_table[8*8] = {
- LFO PM and AM enable are 100% correct
- waveform DC and DM select are 100% correct
*/
/* 2021/04/23: corrected with values extracted from YM2413 instrument ROM, cf. https://siliconpr0n.org/archive/doku.php?id=vendor:yamaha:opl2#ym2413_instrument_rom */
static unsigned char table[19][8] = {
/* MULT MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */
/* 0 1 2 3 4 5 6 7 */
{0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 }, /* 0 */
/*{0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 }, */ /* 0 */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 0 */
{0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 }, /* 1 */
{0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 }, /* 2 */
{0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 }, /* 3 */
{0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 }, /* 4 */
/*{0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 }, */ /* 1 */
{0x71, 0x61, 0x1e, 0x17, 0xd0, 0x78, 0x00, 0x17 }, /* 1 */
/*{0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 }, */ /* 2 */
{0x13, 0x41, 0x1a, 0x0d, 0xd8, 0xf7, 0x23, 0x13 }, /* 2 */
/*{0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 }, */ /* 3 */
{0x13, 0x01, 0x99, 0x00, 0xf2, 0xc4, 0x11, 0x23 }, /* 3 */
/*{0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 }, */ /* 4 */
{0x31, 0x61, 0x0e, 0x07, 0xa8, 0x64, 0x70, 0x27 }, /* 4 */
/*{0x22, 0x21, 0x1e, 0x09, 0xf0, 0x76, 0x08, 0x28 }, */ /* 5 */
{0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 }, /* 5 */
/*{0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 }, */ /* 5 */
{0x32, 0x21, 0x1e, 0x06, 0xe0, 0x76, 0x00, 0x28 }, /* 5 */
/*{0x31, 0x22, 0x16, 0x09, 0x90, 0x7f, 0x00, 0x08 }, */ /* 6 */
{0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 }, /* 6 */
/*{0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 }, */ /* 6 */
{0x31, 0x22, 0x16, 0x05, 0xe0, 0x71, 0x00, 0x18 }, /* 6 */
{0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 }, /* 7 */
{0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 }, /* 8 */
{0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 }, /* 9 */
/*{0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 }, */ /* 7 */
{0x21, 0x61, 0x1d, 0x07, 0x82, 0x81, 0x10, 0x07 }, /* 7 */
/* {0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 }, */ /* A */
{0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 }, /* A */
/*{0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 }, */ /* 8 */
{0x23, 0x21, 0x2d, 0x14, 0xa2, 0x72, 0x00, 0x07 }, /* 8 */
{0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 }, /* B */
{0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 }, /* C */
{0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 }, /* 9 */
/* {0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 }, */ /* D */
{0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 }, /* D */
/*{0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 }, */ /* A */
/*{0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 }, */ /* A */
{0x41, 0x61, 0x0b, 0x18, 0x85, 0xf7, 0x71, 0x07 }, /* A */
{0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 }, /* E */
{0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 }, /* F */
/*{0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 }, */ /* B */
{0x13, 0x01, 0x83, 0x11, 0xfa, 0xe4, 0x10, 0x04 }, /* B */
/*{0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 }, */ /* C */
{0x17, 0xc1, 0x24, 0x07, 0xf8, 0xf8, 0x22, 0x12 }, /* C */
/*{0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 }, */ /* D */
/*{0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 }, */ /* D */
{0x61, 0x50, 0x0c, 0x05, 0xc2, 0xf5, 0x20, 0x42 }, /* D */
/*{0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 }, */ /* E */
{0x01, 0x01, 0x55, 0x03, 0xc9, 0x95, 0x03, 0x02 }, /* E */
/*{0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 }, */ /* F */
{0x61, 0x41, 0x89, 0x03, 0xf1, 0xe4, 0x40, 0x13 }, /* F */
/* drum instruments definitions */
/* MULTI MULTI modTL xxx AR/DR AR/DR SL/RR SL/RR */
/* 0 1 2 3 4 5 6 7 */
{0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },/* BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed) */
{0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },/* HH(multi verified), SD(multi not used) */
{0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },/* TOM(multi,env verified), TOP CYM(multi verified, env verified) */
/*{0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },*/ /* BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed) */
/*{0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },*/ /* HH(multi verified), SD(multi not used) */
/*{0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },*/ /* TOM(multi,env verified), TOP CYM(multi verified, env verified) */
{0x01, 0x01, 0x18, 0x0f, 0xdf, 0xf8, 0x6a, 0x6d }, /* BD */
{0x01, 0x01, 0x00, 0x00, 0xc8, 0xd8, 0xa7, 0x48 }, /* HH, SD */
{0x05, 0x01, 0x00, 0x00, 0xf8, 0xaa, 0x59, 0x55 } /* TOM, TOP CYM */
};
static signed int output[2];
@@ -542,47 +622,55 @@ INLINE void advance(void)
switch(op->state)
{
case EG_DMP: /* dump phase */
/*dump phase is performed by both operators in each channel*/
/*when CARRIER envelope gets down to zero level,
** phases in BOTH opearators are reset (at the same time ?)
*/
if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_dp)-1) ) )
case EG_DMP: /* dump phase */
if ( (op->volume & ~3) == (MAX_ATT_INDEX & ~3) ) /* envelope level lowest 2 bits are ignored by the comparator */
{
op->volume += eg_inc[op->eg_sel_dp + ((ym2413.eg_cnt>>op->eg_sh_dp)&7)];
op->state = EG_ATT;
if ( op->volume >= MAX_ATT_INDEX )
/* force envelope to zero when attack rate is set to 15.0-15.3 */
if ((op->ar + op->ksr) >= 16+60)
{
op->volume = MAX_ATT_INDEX;
op->state = EG_ATT;
/* restart Phase Generator */
op->phase = 0;
op->volume = MIN_ATT_INDEX;
}
/*dump phase is performed by both operators in each channel*/
/*when CARRIER envelope gets down to zero level,
*phases in BOTH operators are reset (at the same time ?)
*/
if (i&1)
{
CH->SLOT[0].phase = CH->SLOT[1].phase = 0;
}
}
else if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_dp)-1) ) )
{
op->volume += eg_inc[op->eg_sel_dp + ((ym2413.eg_cnt>>op->eg_sh_dp)&15)];
}
break;
case EG_ATT: /* attack phase */
if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_ar)-1) ) )
case EG_ATT: /* attack phase */
if (op->volume == MIN_ATT_INDEX)
{
op->volume += (~op->volume *
(eg_inc[op->eg_sel_ar + ((ym2413.eg_cnt>>op->eg_sh_ar)&7)])
) >>2;
if (op->volume <= MIN_ATT_INDEX)
{
op->volume = MIN_ATT_INDEX;
op->state = EG_DEC;
}
op->state = EG_DEC;
}
else if ( !(ym2413.eg_cnt & (((1<<op->eg_sh_ar)-1) & ~3)) )
{
op->volume += (~op->volume * (eg_mul[op->eg_sel_ar + ((ym2413.eg_cnt>>op->eg_sh_ar)&15)]))>>4;
}
break;
case EG_DEC: /* decay phase */
if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_dr)-1) ) )
if ( (op->volume & ~7) == op->sl ) /* envelope level lowest 3 bits are ignored by the comparator */
{
op->volume += eg_inc[op->eg_sel_dr + ((ym2413.eg_cnt>>op->eg_sh_dr)&7)];
if ( op->volume >= op->sl )
op->state = EG_SUS;
op->state = EG_SUS;
}
else if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_dr)-1) ) )
{
op->volume += eg_inc[op->eg_sel_dr + ((ym2413.eg_cnt>>op->eg_sh_dr)&15)];
if ( (op->volume & ~3) == (MAX_ATT_INDEX & ~3) ) /* envelope level lowest 2 bits are ignored by the comparator */
{
op->state = EG_OFF;
}
}
break;
@@ -591,19 +679,20 @@ INLINE void advance(void)
one can change percusive/non-percussive modes on the fly and
the chip will remain in sustain phase - verified on real YM3812 */
if(op->eg_type) /* non-percussive mode (sustained tone) */
if (op->eg_type) /* non-percussive mode (sustained tone) */
{
/* do nothing */
}
else /* percussive mode */
else /* percussive mode */
{
/* during sustain phase chip adds Release Rate (in percussive mode) */
if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
{
op->volume += eg_inc[op->eg_sel_rr + ((ym2413.eg_cnt>>op->eg_sh_rr)&7)];
if ( op->volume >= MAX_ATT_INDEX )
op->volume = MAX_ATT_INDEX;
op->volume += eg_inc[op->eg_sel_rr + ((ym2413.eg_cnt>>op->eg_sh_rr)&15)];
if ( (op->volume & ~3) == (MAX_ATT_INDEX & ~3) ) /* envelope level lowest 2 bits are ignored by the comparator */
{
op->state = EG_OFF;
}
}
/* else do nothing in sustain phase */
}
@@ -629,7 +718,7 @@ INLINE void advance(void)
*/
if ( (i&1) || ((ym2413.rhythm&0x20) && (i>=12)) )/* exclude modulators */
{
if(op->eg_type) /* non-percussive mode (sustained tone) */
if (op->eg_type) /* non-percussive mode (sustained tone) */
/*this is correct: use RR when SUS = OFF*/
/*and use RS when SUS = ON*/
{
@@ -637,10 +726,9 @@ INLINE void advance(void)
{
if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_rs)-1) ) )
{
op->volume += eg_inc[op->eg_sel_rs + ((ym2413.eg_cnt>>op->eg_sh_rs)&7)];
if ( op->volume >= MAX_ATT_INDEX )
op->volume += eg_inc[op->eg_sel_rs + ((ym2413.eg_cnt>>op->eg_sh_rs)&15)];
if ( (op->volume & ~3) == (MAX_ATT_INDEX & ~3) ) /* envelope level lowest 2 bits are ignored by the comparator */
{
op->volume = MAX_ATT_INDEX;
op->state = EG_OFF;
}
}
@@ -649,23 +737,21 @@ INLINE void advance(void)
{
if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
{
op->volume += eg_inc[op->eg_sel_rr + ((ym2413.eg_cnt>>op->eg_sh_rr)&7)];
if ( op->volume >= MAX_ATT_INDEX )
op->volume += eg_inc[op->eg_sel_rr + ((ym2413.eg_cnt>>op->eg_sh_rr)&15)];
if ( (op->volume & ~3) == (MAX_ATT_INDEX & ~3) ) /* envelope level lowest 2 bits are ignored by the comparator */
{
op->volume = MAX_ATT_INDEX;
op->state = EG_OFF;
}
}
}
}
else /* percussive mode */
else /* percussive mode */
{
if ( !(ym2413.eg_cnt & ((1<<op->eg_sh_rs)-1) ) )
{
op->volume += eg_inc[op->eg_sel_rs + ((ym2413.eg_cnt>>op->eg_sh_rs)&7)];
if ( op->volume >= MAX_ATT_INDEX )
op->volume += eg_inc[op->eg_sel_rs + ((ym2413.eg_cnt>>op->eg_sh_rs)&15)];
if ( (op->volume & ~3) == (MAX_ATT_INDEX & ~3) ) /* envelope level lowest 2 bits are ignored by the comparator */
{
op->volume = MAX_ATT_INDEX;
op->state = EG_OFF;
}
}
@@ -673,8 +759,12 @@ INLINE void advance(void)
}
break;
default:
break;
case EG_OFF: /* envelope off */
op->volume = MAX_ATT_INDEX;
break;
default:
break;
}
}
}
@@ -766,7 +856,7 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsign
return tl_tab[p];
}
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
#define volume_calc(OP) (((OP)-> state != EG_OFF) ? (OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask) : ENV_QUIET)
/* calculate output */
INLINE void chan_calc( YM2413_OPLL_CH *CH )
@@ -1119,9 +1209,8 @@ INLINE void KEY_OFF(YM2413_OPLL_SLOT *SLOT, UINT32 key_clr)
if( !SLOT->key )
{
/* phase -> Release */
if (SLOT->state>EG_REL)
SLOT->state = EG_REL;
/* phase -> Release (forced off if already at maximal attenuation level) */
SLOT->state = ( (SLOT->volume & ~3) == (MAX_ATT_INDEX & ~3) ) ? EG_OFF : EG_REL;
}
}
}
@@ -1142,21 +1231,30 @@ INLINE void CALC_FCSLOT(YM2413_OPLL_CH *CH,YM2413_OPLL_SLOT *SLOT)
SLOT->ksr = ksr;
/* calculate envelope generator rates */
if ((SLOT->ar + SLOT->ksr) < 16+62)
if ((SLOT->ar + SLOT->ksr) >= 16+60)
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
/* attack phase is skipped in case attack rate is set to 15.0-15.3 before attack phase is started */
/* during attack phase, in case attack rate is changed to 15.0-15.3, attack phase is blocked */
/* (verified on real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2017-01-26) */
SLOT->eg_sh_ar = 13;
SLOT->eg_sel_ar = 0 * RATE_STEPS;
}
else
else if ((SLOT->ar + SLOT->ksr) >= 16+48)
{
/* attack rates 12.0 to 14.3 have similar specific behavior */
/* (verified on real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2017-01-26) */
SLOT->eg_sh_ar = 0;
SLOT->eg_sel_ar = 13*RATE_STEPS;
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr] + (4 * RATE_STEPS);
}
else
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr];
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr];
}
SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
}
if (CH->sus)
@@ -1167,7 +1265,7 @@ INLINE void CALC_FCSLOT(YM2413_OPLL_CH *CH,YM2413_OPLL_SLOT *SLOT)
SLOT->eg_sh_rs = eg_rate_shift [SLOT_rs + SLOT->ksr ];
SLOT->eg_sel_rs = eg_rate_select[SLOT_rs + SLOT->ksr ];
SLOT_dp = 16 + (13<<2);
SLOT_dp = 16 + (12<<2);
SLOT->eg_sh_dp = eg_rate_shift [SLOT_dp + SLOT->ksr ];
SLOT->eg_sel_dp = eg_rate_select[SLOT_dp + SLOT->ksr ];
}
@@ -1225,15 +1323,25 @@ INLINE void set_ar_dr(int slot,int v)
SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0;
if ((SLOT->ar + SLOT->ksr) < 16+62)
if ((SLOT->ar + SLOT->ksr) >= 16+60)
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
/* attack phase is skipped in case attack rate is set to 15.0-15.3 before attack phase is started */
/* during attack phase, in case attack rate is changed to 15.0-15.3, attack phase is blocked */
/* (verified on real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2017-01-26) */
SLOT->eg_sh_ar = 13;
SLOT->eg_sel_ar = 0 * RATE_STEPS;
}
else
else if ((SLOT->ar + SLOT->ksr) >= 16+48)
{
/* attack rates 12.0 to 14.3 have similar specific behavior */
/* (verified on real hardware, cf. https://www.smspower.org/Development/YM2413ReverseEngineeringNotes2017-01-26) */
SLOT->eg_sh_ar = 0;
SLOT->eg_sel_ar = 13*RATE_STEPS;
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr] + (4 * RATE_STEPS);
}
else
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr];
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr];
}
SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
+118 -51
View File
@@ -15,15 +15,19 @@
** Additional info from YM2612 die shot analysis by Sauraen
** See http://gendev.spritesmind.net/forum/viewtopic.php?t=386
**
** TODO:
** - better documentation
** - BUSY flag emulation
** - accurate DAC output
*/
/*
** CHANGELOG:
**
** 11-05-2021 Eke-Eke (Genesis Plus GX):
** - fixed potential issue with SSG-EG inverted attenuation level on Key OFF
**
** 03-12-2017 Eke-Eke (Genesis Plus GX):
** - improved 9-bit DAC emulation accuracy
** - added discrete YM2612 DAC distortion emulation ("ladder effect")
** - replaced configurable DAC depth with configurable chip types (discrete, integrated or enhanced)
**
** 26-09-2017 Eke-Eke (Genesis Plus GX):
** - fixed EG counter loopback behavior (verified on YM3438 die)
** - reverted changes to EG rates 2-7 increment values
@@ -626,8 +630,11 @@ static YM2612 ym2612;
/* current chip state */
static INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
static INT32 mem; /* one sample delay memory */
static INT32 out_fm[8]; /* outputs of working channels */
static UINT32 bitmask; /* working channels output bitmasking (DAC quantization) */
static INT32 out_fm[6]; /* outputs of working channels */
/* chip type */
static UINT32 op_mask[8][4]; /* operator output bitmasking (DAC quantization) */
static int chip_type = YM2612_DISCRETE;
INLINE void FM_KEYON(FM_CH *CH , int s )
@@ -680,7 +687,7 @@ INLINE void FM_KEYOFF(FM_CH *CH , int s )
{
/* convert EG attenuation level */
if (SLOT->ssgn ^ (SLOT->ssg&0x04))
SLOT->volume = (0x200 - SLOT->volume);
SLOT->volume = (0x200 - SLOT->volume) & MAX_ATT_INDEX;
/* force EG attenuation level */
if (SLOT->volume >= 0x200)
@@ -745,7 +752,7 @@ INLINE void FM_KEYOFF_CSM(FM_CH *CH , int s )
{
/* convert EG attenuation level */
if (SLOT->ssgn ^ (SLOT->ssg&0x04))
SLOT->volume = (0x200 - SLOT->volume);
SLOT->volume = (0x200 - SLOT->volume) & MAX_ATT_INDEX;
/* force EG attenuation level */
if (SLOT->volume >= 0x200)
@@ -772,7 +779,7 @@ INLINE void CSMKeyControll(FM_CH *CH)
ym2612.OPN.SL3.key_csm = 1;
}
INLINE void INTERNAL_TIMER_A()
INLINE void INTERNAL_TIMER_A(void)
{
if (ym2612.OPN.ST.mode & 0x01)
{
@@ -1027,7 +1034,7 @@ INLINE void set_sl_rr(FM_SLOT *SLOT,int v)
}
/* advance LFO to next sample */
INLINE void advance_lfo()
INLINE void advance_lfo(void)
{
if (ym2612.OPN.lfo_timer_overflow) /* LFO enabled ? */
{
@@ -1408,22 +1415,22 @@ INLINE void refresh_fc_eg_chan(FM_CH *CH )
#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask))
INLINE signed int op_calc(UINT32 phase, unsigned int env, unsigned int pm)
INLINE signed int op_calc(UINT32 phase, unsigned int env, unsigned int pm, unsigned int opmask)
{
UINT32 p = (env<<3) + sin_tab[ ( (phase >> SIN_BITS) + (pm >> 1) ) & SIN_MASK ];
if (p >= TL_TAB_LEN)
return 0;
return tl_tab[p];
return (tl_tab[p] & opmask);
}
INLINE signed int op_calc1(UINT32 phase, unsigned int env, unsigned int pm)
INLINE signed int op_calc1(UINT32 phase, unsigned int env, unsigned int pm, unsigned int opmask)
{
UINT32 p = (env<<3) + sin_tab[ ( ( phase >> SIN_BITS ) + pm ) & SIN_MASK ];
if (p >= TL_TAB_LEN)
return 0;
return tl_tab[p];
return (tl_tab[p] & opmask);
}
INLINE void chan_calc(FM_CH *CH, int num)
@@ -1433,6 +1440,7 @@ INLINE void chan_calc(FM_CH *CH, int num)
INT32 out = 0;
UINT32 AM = ym2612.OPN.LFO_AM >> CH->ams;
unsigned int eg_out = volume_calc(&CH->SLOT[SLOT1]);
UINT32 *mask = op_mask[CH->ALGO];
m2 = c1 = c2 = mem = 0;
@@ -1443,7 +1451,7 @@ INLINE void chan_calc(FM_CH *CH, int num)
if (CH->FB < SIN_BITS)
out = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
out = op_calc1(CH->SLOT[SLOT1].phase, eg_out, out );
out = op_calc1(CH->SLOT[SLOT1].phase, eg_out, out, mask[0]);
}
CH->op1_out[0] = CH->op1_out[1];
@@ -1459,22 +1467,21 @@ INLINE void chan_calc(FM_CH *CH, int num)
eg_out = volume_calc(&CH->SLOT[SLOT3]);
if( eg_out < ENV_QUIET ) /* SLOT 3 */
*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2);
*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2, mask[2]);
eg_out = volume_calc(&CH->SLOT[SLOT2]);
if( eg_out < ENV_QUIET ) /* SLOT 2 */
*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1);
*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1, mask[1]);
eg_out = volume_calc(&CH->SLOT[SLOT4]);
if( eg_out < ENV_QUIET ) /* SLOT 4 */
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2);
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2, mask[3]);
/* store current MEM */
CH->mem_value = mem;
/* update phase counters AFTER output calculations */
if(CH->pms)
if (CH->pms)
{
/* 3-slot mode */
if ((ym2612.OPN.ST.mode & 0xC0) && (CH == &ym2612.CH[2]))
@@ -1515,7 +1522,7 @@ INLINE void OPNWriteMode(int r, int v)
case 0x21: /* Test */
break;
case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/ym2612) */
case 0x22: /* LFO FREQ */
if (v&8) /* LFO enabled ? */
{
ym2612.OPN.lfo_timer_overflow = lfo_samples_per_step[v&7];
@@ -1550,7 +1557,6 @@ INLINE void OPNWriteMode(int r, int v)
if( c == 3 ) break;
if (v&0x04) c+=3; /* CH 4-6 */
CH = &ym2612.CH[c];
if (v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
if (v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
if (v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
@@ -1686,8 +1692,6 @@ INLINE void OPNWriteReg(int r, int v)
That is not necessary, but then EG will be generating Attack phase.
*/
break;
case 0xa0:
@@ -1722,7 +1726,7 @@ INLINE void OPNWriteReg(int r, int v)
ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;
ym2612.CH[2].SLOT[SLOT1].Incr=-1;
}
break;
break;
case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
if(r < 0x100)
ym2612.OPN.SL3.fn_h = v&0x3f;
@@ -1737,7 +1741,7 @@ INLINE void OPNWriteReg(int r, int v)
CH->ALGO = v&7;
CH->FB = SIN_BITS - ((v>>3)&7);
setup_connection( CH, c );
break;
break;
}
case 1: /* 0xb4-0xb6 : L , R , AMS , PMS */
/* b0-2 PMS */
@@ -1747,8 +1751,8 @@ INLINE void OPNWriteReg(int r, int v)
CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03];
/* PAN : b7 = L, b6 = R */
ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? bitmask : 0;
ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? bitmask : 0;
ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? 0xffffffff : 0;
ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? 0xffffffff : 0;
break;
}
break;
@@ -1884,6 +1888,15 @@ static void init_tables(void)
}
}
/* build default OP mask table */
for (i = 0;i < 8;i++)
{
for (d = 0;d < 4;d++)
{
op_mask[i][d] = 0xffffffff;
}
}
}
@@ -1984,9 +1997,9 @@ void YM2612Write(unsigned int a, unsigned int v)
}
}
unsigned int YM2612Read(unsigned int a)
unsigned int YM2612Read(void)
{
return ym2612.OPN.ST.status & 0xff;
return ym2612.OPN.ST.status;
}
/* Generate samples for ym2612 */
@@ -2020,7 +2033,7 @@ void YM2612Update(int *buffer, int length)
refresh_fc_eg_chan(&ym2612.CH[5]);
/* buffering */
for(i=0; i<length ; i++)
for(i=0; i<length; i++)
{
/* clear outputs */
out_fm[0] = 0;
@@ -2066,21 +2079,21 @@ void YM2612Update(int *buffer, int length)
advance_eg_channels(&ym2612.CH[0], ym2612.OPN.eg_cnt);
}
/* 14-bit accumulator channels outputs (range is -8192;+8192) */
if (out_fm[0] > 8192) out_fm[0] = 8192;
/* channels accumulator output clipping (14-bit max) */
if (out_fm[0] > 8191) out_fm[0] = 8191;
else if (out_fm[0] < -8192) out_fm[0] = -8192;
if (out_fm[1] > 8192) out_fm[1] = 8192;
if (out_fm[1] > 8191) out_fm[1] = 8191;
else if (out_fm[1] < -8192) out_fm[1] = -8192;
if (out_fm[2] > 8192) out_fm[2] = 8192;
if (out_fm[2] > 8191) out_fm[2] = 8191;
else if (out_fm[2] < -8192) out_fm[2] = -8192;
if (out_fm[3] > 8192) out_fm[3] = 8192;
if (out_fm[3] > 8191) out_fm[3] = 8191;
else if (out_fm[3] < -8192) out_fm[3] = -8192;
if (out_fm[4] > 8192) out_fm[4] = 8192;
if (out_fm[4] > 8191) out_fm[4] = 8191;
else if (out_fm[4] < -8192) out_fm[4] = -8192;
if (out_fm[5] > 8192) out_fm[5] = 8192;
if (out_fm[5] > 8191) out_fm[5] = 8191;
else if (out_fm[5] < -8192) out_fm[5] = -8192;
/* stereo DAC channels outputs mixing */
/* stereo DAC output panning & mixing */
lt = ((out_fm[0]) & ym2612.OPN.pan[0]);
rt = ((out_fm[0]) & ym2612.OPN.pan[1]);
lt += ((out_fm[1]) & ym2612.OPN.pan[2]);
@@ -2094,11 +2107,34 @@ void YM2612Update(int *buffer, int length)
lt += ((out_fm[5]) & ym2612.OPN.pan[10]);
rt += ((out_fm[5]) & ym2612.OPN.pan[11]);
/* discrete YM2612 DAC */
if (chip_type == YM2612_DISCRETE)
{
int i;
/* DAC 'ladder effect' */
for (i=0; i<6; i++)
{
if (out_fm[i] < 0)
{
/* -4 offset (-3 when not muted) on negative channel output (9-bit) */
lt -= ((4 - (ym2612.OPN.pan[(2*i)+0] & 1)) << 5);
rt -= ((4 - (ym2612.OPN.pan[(2*i)+1] & 1)) << 5);
}
else
{
/* +4 offset (when muted or not) on positive channel output (9-bit) */
lt += (4 << 5);
rt += (4 << 5);
}
}
}
/* buffering */
*buffer++ = lt;
*buffer++ = rt;
/* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */
/* CSM mode: if CSM Key ON has occurred, CSM Key OFF need to be sent */
/* only if Timer A does not overflow again (i.e CSM Key ON not set again) */
ym2612.OPN.SL3.key_csm <<= 1;
@@ -2121,20 +2157,51 @@ void YM2612Update(int *buffer, int length)
INTERNAL_TIMER_B(length);
}
void YM2612Config(unsigned char dac_bits)
void YM2612Config(int type)
{
int i;
/* YM2612 chip type */
chip_type = type;
/* DAC precision (normally 9-bit on real hardware, implemented through simple 14-bit channel output bitmasking) */
bitmask = ~((1 << (TL_BITS - dac_bits)) - 1);
/* update L/R panning bitmasks */
for (i=0; i<2*6; i++)
/* carrier operator outputs bitmask */
if (chip_type < YM2612_ENHANCED)
{
if (ym2612.OPN.pan[i])
{
ym2612.OPN.pan[i] = bitmask;
}
/* 9-bit DAC */
op_mask[0][3] = 0xffffffe0;
op_mask[1][3] = 0xffffffe0;
op_mask[2][3] = 0xffffffe0;
op_mask[3][3] = 0xffffffe0;
op_mask[4][1] = 0xffffffe0;
op_mask[4][3] = 0xffffffe0;
op_mask[5][1] = 0xffffffe0;
op_mask[5][2] = 0xffffffe0;
op_mask[5][3] = 0xffffffe0;
op_mask[6][1] = 0xffffffe0;
op_mask[6][2] = 0xffffffe0;
op_mask[6][3] = 0xffffffe0;
op_mask[7][0] = 0xffffffe0;
op_mask[7][1] = 0xffffffe0;
op_mask[7][2] = 0xffffffe0;
op_mask[7][3] = 0xffffffe0;
}
else
{
/* 14-bit DAC */
op_mask[0][3] = 0xffffffff;
op_mask[1][3] = 0xffffffff;
op_mask[2][3] = 0xffffffff;
op_mask[3][3] = 0xffffffff;
op_mask[4][1] = 0xffffffff;
op_mask[4][3] = 0xffffffff;
op_mask[5][1] = 0xffffffff;
op_mask[5][2] = 0xffffffff;
op_mask[5][3] = 0xffffffff;
op_mask[6][1] = 0xffffffff;
op_mask[6][2] = 0xffffffff;
op_mask[6][3] = 0xffffffff;
op_mask[7][0] = 0xffffffff;
op_mask[7][1] = 0xffffffff;
op_mask[7][2] = 0xffffffff;
op_mask[7][3] = 0xffffffff;
}
}
+8 -2
View File
@@ -16,12 +16,18 @@
#ifndef _H_YM2612_
#define _H_YM2612_
enum {
YM2612_DISCRETE = 0,
YM2612_INTEGRATED,
YM2612_ENHANCED
};
extern void YM2612Init(void);
extern void YM2612Config(unsigned char dac_bits);
extern void YM2612Config(int type);
extern void YM2612ResetChip(void);
extern void YM2612Update(int *buffer, int length);
extern void YM2612Write(unsigned int a, unsigned int v);
extern unsigned int YM2612Read(unsigned int a);
extern unsigned int YM2612Read(void);
extern int YM2612LoadContext(unsigned char *state);
extern int YM2612SaveContext(unsigned char *state);
+78 -62
View File
@@ -1,6 +1,6 @@
#ifdef HAVE_YM3438_CORE
/*
* Copyright (C) 2017 Alexey Khokholov (Nuke.YKT)
* Copyright (C) 2017-2018 Alexey Khokholov (Nuke.YKT)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -40,7 +40,7 @@
* OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
* OPL2 ROMs.
*
* version: 1.0.7
* version: 1.0.10
*/
#include <string.h>
@@ -233,9 +233,9 @@ static const Bit32u fm_algorithm[4][6][8] = {
}
};
static Bit32u chip_type = ym3438_type_discrete;
static Bit32u chip_type = ym3438_mode_readmode;
void OPN2_DoIO(ym3438_t *chip)
static void OPN2_DoIO(ym3438_t *chip)
{
/* Write signal check */
chip->write_a_en = (chip->write_a & 0x03) == 0x01;
@@ -249,10 +249,10 @@ void OPN2_DoIO(ym3438_t *chip)
chip->write_busy_cnt &= 0x1f;
}
void OPN2_DoRegWrite(ym3438_t *chip)
static void OPN2_DoRegWrite(ym3438_t *chip)
{
Bit32u i;
Bit32u slot = chip->slot % 12;
Bit32u slot = chip->cycles % 12;
Bit32u address;
Bit32u channel = chip->channel;
/* Update registers */
@@ -379,7 +379,7 @@ void OPN2_DoRegWrite(ym3438_t *chip)
/* Data */
if (chip->write_d_en && (chip->write_data & 0x100) == 0)
{
switch (chip->address)
switch (chip->write_fm_mode_a)
{
case 0x21: /* LSI test 1 */
for (i = 0; i < 8; i++)
@@ -458,7 +458,7 @@ void OPN2_DoRegWrite(ym3438_t *chip)
/* Address */
if (chip->write_a_en)
{
chip->write_fm_mode_a = chip->write_data & 0xff;
chip->write_fm_mode_a = chip->write_data & 0x1ff;
}
}
@@ -468,16 +468,18 @@ void OPN2_DoRegWrite(ym3438_t *chip)
}
}
void OPN2_PhaseCalcIncrement(ym3438_t *chip)
static void OPN2_PhaseCalcIncrement(ym3438_t *chip)
{
Bit32u chan = chip->channel;
Bit32u slot = chip->cycles;
Bit32u fnum = chip->pg_fnum;
Bit32u fnum_h = fnum >> 4;
Bit32u fm;
Bit32u basefreq;
Bit8u lfo = chip->lfo_pm;
Bit8u lfo_l = lfo & 0x0f;
Bit8u pms = chip->pms[chip->channel];
Bit8u dt = chip->dt[chip->slot];
Bit8u pms = chip->pms[chan];
Bit8u dt = chip->dt[slot];
Bit8u dt_l = dt & 0x03;
Bit8u detune = 0;
Bit8u block, note;
@@ -531,32 +533,32 @@ void OPN2_PhaseCalcIncrement(ym3438_t *chip)
basefreq += detune;
}
basefreq &= 0x1ffff;
chip->pg_inc[chip->slot] = (basefreq * chip->multi[chip->slot]) >> 1;
chip->pg_inc[chip->slot] &= 0xfffff;
chip->pg_inc[slot] = (basefreq * chip->multi[slot]) >> 1;
chip->pg_inc[slot] &= 0xfffff;
}
void OPN2_PhaseGenerate(ym3438_t *chip)
static void OPN2_PhaseGenerate(ym3438_t *chip)
{
Bit32u slot;
/* Mask increment */
slot = (chip->slot + 20) % 24;
slot = (chip->cycles + 20) % 24;
if (chip->pg_reset[slot])
{
chip->pg_inc[slot] = 0;
}
/* Phase step */
slot = (chip->slot + 19) % 24;
chip->pg_phase[slot] += chip->pg_inc[slot];
chip->pg_phase[slot] &= 0xfffff;
slot = (chip->cycles + 19) % 24;
if (chip->pg_reset[slot] || chip->mode_test_21[3])
{
chip->pg_phase[slot] = 0;
}
chip->pg_phase[slot] += chip->pg_inc[slot];
chip->pg_phase[slot] &= 0xfffff;
}
void OPN2_EnvelopeSSGEG(ym3438_t *chip)
static void OPN2_EnvelopeSSGEG(ym3438_t *chip)
{
Bit32u slot = chip->slot;
Bit32u slot = chip->cycles;
Bit8u direction = 0;
chip->eg_ssg_pgrst_latch[slot] = 0;
chip->eg_ssg_repeat_latch[slot] = 0;
@@ -601,9 +603,9 @@ void OPN2_EnvelopeSSGEG(ym3438_t *chip)
chip->eg_ssg_enable[slot] = (chip->ssg_eg[slot] >> 3) & 0x01;
}
void OPN2_EnvelopeADSR(ym3438_t *chip)
static void OPN2_EnvelopeADSR(ym3438_t *chip)
{
Bit32u slot = (chip->slot + 22) % 24;
Bit32u slot = (chip->cycles + 22) % 24;
Bit8u nkon = chip->eg_kon_latch[slot];
Bit8u okon = chip->eg_kon[slot];
@@ -725,12 +727,12 @@ void OPN2_EnvelopeADSR(ym3438_t *chip)
chip->eg_state[slot] = nextstate;
}
void OPN2_EnvelopePrepare(ym3438_t *chip)
static void OPN2_EnvelopePrepare(ym3438_t *chip)
{
Bit8u rate;
Bit8u sum;
Bit8u inc = 0;
Bit32u slot = chip->slot;
Bit32u slot = chip->cycles;
Bit8u rate_sel;
/* Prepare increment */
@@ -813,9 +815,9 @@ void OPN2_EnvelopePrepare(ym3438_t *chip)
chip->eg_sl[0] = chip->sl[slot];
}
void OPN2_EnvelopeGenerate(ym3438_t *chip)
static void OPN2_EnvelopeGenerate(ym3438_t *chip)
{
Bit32u slot = (chip->slot + 23) % 24;
Bit32u slot = (chip->cycles + 23) % 24;
Bit16u level;
level = chip->eg_level[slot];
@@ -846,7 +848,7 @@ void OPN2_EnvelopeGenerate(ym3438_t *chip)
chip->eg_out[slot] = level;
}
void OPN2_UpdateLFO(ym3438_t *chip)
static void OPN2_UpdateLFO(ym3438_t *chip)
{
if ((chip->lfo_quotient & lfo_cycles[chip->lfo_freq]) == lfo_cycles[chip->lfo_freq])
{
@@ -860,14 +862,14 @@ void OPN2_UpdateLFO(ym3438_t *chip)
chip->lfo_cnt &= chip->lfo_en;
}
void OPN2_FMPrepare(ym3438_t *chip)
static void OPN2_FMPrepare(ym3438_t *chip)
{
Bit32u slot = (chip->slot + 6) % 24;
Bit32u slot = (chip->cycles + 6) % 24;
Bit32u channel = chip->channel;
Bit16s mod, mod1, mod2;
Bit32u op = slot / 6;
Bit8u connect = chip->connect[channel];
Bit32u prevslot = (chip->slot + 18) % 24;
Bit32u prevslot = (chip->cycles + 18) % 24;
/* Calculate modulation */
mod1 = mod2 = 0;
@@ -908,7 +910,7 @@ void OPN2_FMPrepare(ym3438_t *chip)
}
chip->fm_mod[slot] = mod;
slot = (chip->slot + 18) % 24;
slot = (chip->cycles + 18) % 24;
/* OP1 */
if (slot / 6 == 0)
{
@@ -922,9 +924,9 @@ void OPN2_FMPrepare(ym3438_t *chip)
}
}
void OPN2_ChGenerate(ym3438_t *chip)
static void OPN2_ChGenerate(ym3438_t *chip)
{
Bit32u slot = (chip->slot + 18) % 24;
Bit32u slot = (chip->cycles + 18) % 24;
Bit32u channel = chip->channel;
Bit32u op = slot / 6;
Bit32u test_dac = chip->mode_test_2c[5];
@@ -957,16 +959,17 @@ void OPN2_ChGenerate(ym3438_t *chip)
chip->ch_acc[channel] = sum;
}
void OPN2_ChOutput(ym3438_t *chip)
static void OPN2_ChOutput(ym3438_t *chip)
{
Bit32u cycles = chip->cycles;
Bit32u slot = chip->cycles;
Bit32u channel = chip->channel;
Bit32u test_dac = chip->mode_test_2c[5];
Bit16s out;
Bit16s sign;
Bit32u out_en;
chip->ch_read = chip->ch_lock;
if (chip->slot < 12)
if (slot < 12)
{
/* Ch 4,5,6 */
channel++;
@@ -995,7 +998,7 @@ void OPN2_ChOutput(ym3438_t *chip)
chip->mol = 0;
chip->mor = 0;
if (chip_type == ym3438_type_ym2612)
if (chip_type & ym3438_mode_ym2612)
{
out_en = ((cycles & 3) == 3) || test_dac;
/* YM2612 DAC emulation(not verified) */
@@ -1028,11 +1031,6 @@ void OPN2_ChOutput(ym3438_t *chip)
else
{
out_en = ((cycles & 3) != 0) || test_dac;
/* Discrete YM3438 seems has the ladder effect too */
if (out >= 0 && chip_type == ym3438_type_discrete)
{
out++;
}
if (chip->ch_lock_l && out_en)
{
chip->mol = out;
@@ -1044,9 +1042,9 @@ void OPN2_ChOutput(ym3438_t *chip)
}
}
void OPN2_FMGenerate(ym3438_t *chip)
static void OPN2_FMGenerate(ym3438_t *chip)
{
Bit32u slot = (chip->slot + 19) % 24;
Bit32u slot = (chip->cycles + 19) % 24;
/* Calculate phase */
Bit16u phase = (chip->fm_mod[slot] + (chip->pg_phase[slot] >> 10)) & 0x3ff;
Bit16u quarter;
@@ -1082,7 +1080,7 @@ void OPN2_FMGenerate(ym3438_t *chip)
chip->fm_out[slot] = output;
}
void OPN2_DoTimerA(ym3438_t *chip)
static void OPN2_DoTimerA(ym3438_t *chip)
{
Bit16u time;
Bit8u load;
@@ -1131,7 +1129,7 @@ void OPN2_DoTimerA(ym3438_t *chip)
chip->timer_a_cnt = time & 0x3ff;
}
void OPN2_DoTimerB(ym3438_t *chip)
static void OPN2_DoTimerB(ym3438_t *chip)
{
Bit16u time;
Bit8u load;
@@ -1176,27 +1174,29 @@ void OPN2_DoTimerB(ym3438_t *chip)
chip->timer_b_cnt = time & 0xff;
}
void OPN2_KeyOn(ym3438_t*chip)
static void OPN2_KeyOn(ym3438_t*chip)
{
Bit32u slot = chip->cycles;
Bit32u chan = chip->channel;
/* Key On */
chip->eg_kon_latch[chip->slot] = chip->mode_kon[chip->slot];
chip->eg_kon_csm[chip->slot] = 0;
chip->eg_kon_latch[slot] = chip->mode_kon[slot];
chip->eg_kon_csm[slot] = 0;
if (chip->channel == 2 && chip->mode_kon_csm)
{
/* CSM Key On */
chip->eg_kon_latch[chip->slot] = 1;
chip->eg_kon_csm[chip->slot] = 1;
chip->eg_kon_latch[slot] = 1;
chip->eg_kon_csm[slot] = 1;
}
if (chip->cycles == chip->mode_kon_channel)
{
/* OP1 */
chip->mode_kon[chip->channel] = chip->mode_kon_operator[0];
chip->mode_kon[chan] = chip->mode_kon_operator[0];
/* OP2 */
chip->mode_kon[chip->channel + 12] = chip->mode_kon_operator[1];
chip->mode_kon[chan + 12] = chip->mode_kon_operator[1];
/* OP3 */
chip->mode_kon[chip->channel + 6] = chip->mode_kon_operator[2];
chip->mode_kon[chan + 6] = chip->mode_kon_operator[2];
/* OP4 */
chip->mode_kon[chip->channel + 18] = chip->mode_kon_operator[3];
chip->mode_kon[chan + 18] = chip->mode_kon_operator[3];
}
}
@@ -1223,8 +1223,9 @@ void OPN2_SetChipType(Bit32u type)
chip_type = type;
}
void OPN2_Clock(ym3438_t *chip, Bit32u *buffer)
void OPN2_Clock(ym3438_t *chip, Bit16s *buffer)
{
Bit32u slot = chip->cycles;
chip->lfo_inc = chip->mode_test_21[1];
chip->pg_read >>= 1;
chip->eg_read[1] >>= 1;
@@ -1315,7 +1316,7 @@ void OPN2_Clock(ym3438_t *chip, Bit32u *buffer)
if (chip->mode_ch3)
{
/* Channel 3 special mode */
switch (chip->slot)
switch (slot)
{
case 1: /* OP1 */
chip->pg_fnum = chip->fnum_3ch[1];
@@ -1350,11 +1351,13 @@ void OPN2_Clock(ym3438_t *chip, Bit32u *buffer)
OPN2_UpdateLFO(chip);
OPN2_DoRegWrite(chip);
chip->cycles = (chip->cycles + 1) % 24;
chip->slot = chip->cycles;
chip->channel = chip->cycles % 6;
buffer[0] = chip->mol;
buffer[1] = chip->mor;
if (chip->status_time)
chip->status_time--;
}
void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data)
@@ -1394,11 +1397,12 @@ Bit32u OPN2_ReadIRQPin(ym3438_t *chip)
Bit8u OPN2_Read(ym3438_t *chip, Bit32u port)
{
if ((port & 3) == 0 || chip_type == ym3438_type_asic)
if ((port & 3) == 0 || (chip_type & ym3438_mode_readmode))
{
if (chip->mode_test_21[6])
{
/* Read test data */
Bit32u slot = (chip->cycles + 18) % 24;
Bit16u testdata = ((chip->pg_read & 0x01) << 15)
| ((chip->eg_read[chip->mode_test_21[0]] & 0x01) << 14);
if (chip->mode_test_2c[4])
@@ -1407,22 +1411,34 @@ Bit8u OPN2_Read(ym3438_t *chip, Bit32u port)
}
else
{
testdata |= chip->fm_out[(chip->slot + 18) % 24] & 0x3fff;
testdata |= chip->fm_out[slot] & 0x3fff;
}
if (chip->mode_test_21[7])
{
return testdata & 0xff;
chip->status = testdata & 0xff;
}
else
{
return testdata >> 8;
chip->status = testdata >> 8;
}
}
else
{
return (chip->busy << 7) | (chip->timer_b_overflow_flag << 1)
chip->status = (chip->busy << 7) | (chip->timer_b_overflow_flag << 1)
| chip->timer_a_overflow_flag;
}
if (chip_type & ym3438_mode_ym2612)
{
chip->status_time = 300000;
}
else
{
chip->status_time = 40000000;
}
}
if (chip->status_time)
{
return chip->status;
}
return 0;
}
+21 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Alexey Khokholov (Nuke.YKT)
* Copyright (C) 2017-2018 Alexey Khokholov (Nuke.YKT)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -39,16 +39,19 @@
* OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
* OPL2 ROMs.
*
* version: 1.0.7
* version: 1.0.9
*/
#ifndef YM3438_H
#define YM3438_H
#ifdef __cplusplus
extern "C" {
#endif
enum {
ym3438_type_discrete = 0, /* Discrete YM3438 (Teradrive) */
ym3438_type_asic = 1, /* ASIC YM3438 (MD1 VA7, MD2, MD3, etc) */
ym3438_type_ym2612 = 2 /* YM2612 (MD1, MD2 VA2) */
ym3438_mode_ym2612 = 0x01, /* Enables YM2612 emulation (MD1, MD2 VA2) */
ym3438_mode_readmode = 0x02 /* Enables status read on any port (TeraDrive, MD1 VA7, MD2, etc) */
};
#include <stdint.h>
@@ -67,7 +70,6 @@ typedef int8_t Bit8s;
typedef struct
{
Bit32u cycles;
Bit32u slot;
Bit32u channel;
Bit16s mol, mor;
/* IO */
@@ -80,7 +82,7 @@ typedef struct
Bit8u write_busy_cnt;
Bit8u write_fm_address;
Bit8u write_fm_data;
Bit8u write_fm_mode_a;
Bit16u write_fm_mode_a;
Bit16u address;
Bit8u data;
Bit8u pin_test_in;
@@ -156,7 +158,7 @@ typedef struct
Bit8u timer_a_load_latch;
Bit8u timer_a_overflow_flag;
Bit8u timer_a_overflow;
Bit16u timer_b_cnt;
Bit8u timer_b_subcnt;
Bit16u timer_b_reg;
@@ -167,7 +169,7 @@ typedef struct
Bit8u timer_b_load_latch;
Bit8u timer_b_overflow_flag;
Bit8u timer_b_overflow;
/* Register set */
Bit8u mode_test_21[8];
Bit8u mode_test_2c[8];
@@ -179,7 +181,7 @@ typedef struct
Bit8u mode_kon_csm;
Bit8u dacen;
Bit16s dacdata;
Bit8u ks[24];
Bit8u ar[24];
Bit8u sr[24];
@@ -191,7 +193,7 @@ typedef struct
Bit8u am[24];
Bit8u tl[24];
Bit8u ssg_eg[24];
Bit16u fnum[6];
Bit8u block[6];
Bit8u kcode[6];
@@ -205,14 +207,21 @@ typedef struct
Bit8u pan_l[6], pan_r[6];
Bit8u ams[6];
Bit8u pms[6];
Bit8u status;
Bit32u status_time;
} ym3438_t;
void OPN2_Reset(ym3438_t *chip);
void OPN2_SetChipType(Bit32u type);
void OPN2_Clock(ym3438_t *chip, Bit32u *buffer);
void OPN2_Clock(ym3438_t *chip, Bit16s *buffer);
void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data);
void OPN2_SetTestPin(ym3438_t *chip, Bit32u value);
Bit32u OPN2_ReadTestPin(ym3438_t *chip);
Bit32u OPN2_ReadIRQPin(ym3438_t *chip);
Bit8u OPN2_Read(ym3438_t *chip, Bit32u port);
#ifdef __cplusplus
}
#endif
#endif
+6 -6
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Savestate support
*
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -149,7 +149,7 @@ int state_load(unsigned char *state)
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_USP,tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_ISP,tmp32);
load_param(&m68k.cycles, sizeof(m68k.cycles));
load_param(&m68k.cycles, sizeof(m68k.cycles));
load_param(&m68k.int_level, sizeof(m68k.int_level));
load_param(&m68k.stopped, sizeof(m68k.stopped));
}
@@ -173,7 +173,7 @@ int state_load(unsigned char *state)
}
/* CD hardware */
bufferptr += scd_context_load(&state[bufferptr]);
bufferptr += scd_context_load(&state[bufferptr], version);
}
else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{
@@ -197,7 +197,7 @@ int state_save(unsigned char *state)
/* version string */
char version[16];
strncpy(version,STATE_VERSION,16);
memcpy(version,STATE_VERSION,16);
save_param(version, 16);
/* GENESIS */
@@ -260,8 +260,8 @@ int state_save(unsigned char *state)
if (system_hw == SYSTEM_MCD)
{
/* CD hardware ID flag */
char id[5];
strncpy(id,"SCD!",4);
char id[4];
memcpy(id,"SCD!",4);
save_param(id, 4);
/* CD hardware */
+2 -2
View File
@@ -2,7 +2,7 @@
* Genesis Plus
* Savestate support
*
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -40,7 +40,7 @@
#define _STATE_H_
#define STATE_SIZE 0xfd000
#define STATE_VERSION "GENPLUS-GX 1.7.5"
#define STATE_VERSION "GENPLUS-GX 1.7.6"
#define load_param(param, size) \
memcpy(param, &state[bufferptr], size); \
+7 -47
View File
@@ -5,7 +5,7 @@
* Support for 16-bit & 8-bit hardware modes
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2021 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -130,8 +130,8 @@ void audio_set_rate(int samplerate, double framerate)
/* resampled to desired rate at the end of each frame, using Blip Buffer. */
blip_set_rates(snd.blips[0], mclk, samplerate);
/* Mega CD sound hardware */
if (system_hw == SYSTEM_MCD)
/* Mega CD sound hardware enabled ? */
if (snd.blips[1] && snd.blips[2])
{
/* number of SCD master clocks run per second */
mclk = (mclk / system_clock) * SCD_CLOCK;
@@ -195,14 +195,14 @@ int audio_update(int16 *buffer)
/* run sound chips until end of frame */
int size = sound_update(mcycles_vdp);
/* Mega CD specific */
if (system_hw == SYSTEM_MCD)
/* Mega CD sound hardware enabled ? */
if (snd.blips[1] && snd.blips[2])
{
/* sync PCM chip with other sound chips */
pcm_update(size);
/* read CDDA samples */
cdd_read_audio(size);
/* read CD-DA samples */
cdd_update_audio(size);
#ifdef ALIGN_SND
/* return an aligned number of samples if required */
@@ -467,10 +467,6 @@ void system_frame_gen(int do_skip)
{
z80_run(788);
}
else
{
Z80.cycles = 788;
}
/* set VINT flag */
status |= 0x80;
@@ -493,10 +489,6 @@ void system_frame_gen(int do_skip)
{
z80_run(MCYCLES_PER_LINE);
}
else
{
Z80.cycles = MCYCLES_PER_LINE;
}
/* Z80 interrupt is cleared at the end of the line */
Z80.irq_state = CLEAR_LINE;
@@ -538,10 +530,6 @@ void system_frame_gen(int do_skip)
{
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
}
else
{
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
}
/* run SVP chip */
if (svp)
@@ -590,10 +578,6 @@ void system_frame_gen(int do_skip)
{
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
}
else
{
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
}
/* run SVP chip */
if (svp)
@@ -654,10 +638,6 @@ void system_frame_gen(int do_skip)
{
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
}
else
{
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
}
/* run SVP chip */
if (svp)
@@ -826,10 +806,6 @@ void system_frame_scd(int do_skip)
{
z80_run(788);
}
else
{
Z80.cycles = 788;
}
/* set VINT flag */
status |= 0x80;
@@ -854,10 +830,6 @@ void system_frame_scd(int do_skip)
{
z80_run(MCYCLES_PER_LINE);
}
else
{
Z80.cycles = MCYCLES_PER_LINE;
}
/* Z80 interrupt is cleared at the end of the line */
Z80.irq_state = CLEAR_LINE;
@@ -895,10 +867,6 @@ void system_frame_scd(int do_skip)
{
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
}
else
{
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
}
/* update VDP cycle count */
mcycles_vdp += MCYCLES_PER_LINE;
@@ -943,10 +911,6 @@ void system_frame_scd(int do_skip)
{
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
}
else
{
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
}
/* update VDP cycle count */
mcycles_vdp += MCYCLES_PER_LINE;
@@ -1003,10 +967,6 @@ void system_frame_scd(int do_skip)
{
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
}
else
{
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
}
/* update VDP cycle count */
mcycles_vdp += MCYCLES_PER_LINE;
+13 -12
View File
@@ -5,7 +5,7 @@
* Support for 16-bit & 8-bit hardware modes
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -45,17 +45,18 @@
#include "blip_buf.h"
/* Supported hardware models */
#define SYSTEM_SG 0x10
#define SYSTEM_SGII 0x11
#define SYSTEM_MARKIII 0x12
#define SYSTEM_SMS 0x20
#define SYSTEM_SMS2 0x21
#define SYSTEM_GG 0x40
#define SYSTEM_GGMS 0x41
#define SYSTEM_MD 0x80
#define SYSTEM_PBC 0x81
#define SYSTEM_PICO 0x82
#define SYSTEM_MCD 0x84
#define SYSTEM_SG 0x01
#define SYSTEM_SGII 0x02
#define SYSTEM_SGII_RAM_EXT 0x03
#define SYSTEM_MARKIII 0x10
#define SYSTEM_SMS 0x20
#define SYSTEM_SMS2 0x21
#define SYSTEM_GG 0x40
#define SYSTEM_GGMS 0x41
#define SYSTEM_MD 0x80
#define SYSTEM_PBC 0x81
#define SYSTEM_PICO 0x82
#define SYSTEM_MCD 0x84
/* NTSC & PAL Master Clock frequencies */
#define MCLOCK_NTSC 53693175
+6
View File
@@ -1,3 +1,7 @@
#ifndef _TYPES_H_
#define _TYPES_H_
#undef uint8
#undef uint16
#undef uint32
@@ -27,3 +31,5 @@ typedef union
} byte;
} reg16_t;
#endif /* _TYPES_H_ */
+74 -14
View File
@@ -5,7 +5,7 @@
* Support for SG-1000 (TMS99xx & 315-5066), Master System (315-5124 & 315-5246), Game Gear & Mega Drive VDP
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -53,6 +53,12 @@
bg_name_dirty[name] |= (1 << ((addr >> 2) & 7)); \
}
/* HBLANK flag timings */
#define HBLANK_H32_START_MCYCLE (280)
#define HBLANK_H32_END_MCYCLE (860)
#define HBLANK_H40_START_MCYCLE (228)
#define HBLANK_H40_END_MCYCLE (872)
/* VDP context */
uint8 ALIGNED_(4) sat[0x400]; /* Internal copy of sprite attribute table */
uint8 ALIGNED_(4) vram[0x10000]; /* Video RAM (64K x 8-bit) */
@@ -142,6 +148,8 @@ static int fifo_idx; /* FIFO write index */
static int fifo_byte_access; /* FIFO byte access flag */
static uint32 fifo_cycles; /* FIFO next access cycle */
static int *fifo_timing; /* FIFO slots timing table */
static int hblank_start_cycle; /* HBLANK flag set cycle */
static int hblank_end_cycle; /* HBLANK flag clear cycle */
/* set Z80 or 68k interrupt lines */
static void (*set_irq_line)(unsigned int level);
@@ -323,6 +331,10 @@ void vdp_reset(void)
/* default FIFO access slots timings */
fifo_timing = (int *)fifo_timing_h32;
/* default HBLANK flag timings */
hblank_start_cycle = HBLANK_H32_START_MCYCLE;
hblank_end_cycle = HBLANK_H32_END_MCYCLE;
/* default overscan area */
if ((system_hw == SYSTEM_GG) && !config.gg_extra)
{
@@ -362,6 +374,7 @@ void vdp_reset(void)
{
case SYSTEM_SG:
case SYSTEM_SGII:
case SYSTEM_SGII_RAM_EXT:
{
/* SG-1000 (TMS99xx) or SG-1000 II (315-5066) VDP */
vdp_z80_data_w = vdp_z80_data_w_sg;
@@ -708,6 +721,10 @@ void vdp_68k_ctrl_w(unsigned int data)
}
}
/* Update address and code registers */
addr = addr_latch | (data & 0x3FFF);
code = ((code & 0x3C) | ((data >> 14) & 0x03));
/* Check CD0-CD1 bits */
if ((data & 0xC000) == 0x8000)
{
@@ -719,10 +736,6 @@ void vdp_68k_ctrl_w(unsigned int data)
/* Set pending flag (Mode 5 only) */
pending = reg[1] & 4;
}
/* Update address and code registers */
addr = addr_latch | (data & 0x3FFF);
code = ((code & 0x3C) | ((data >> 14) & 0x03));
}
else
{
@@ -1186,9 +1199,12 @@ unsigned int vdp_68k_ctrl_r(unsigned int cycles)
temp |= 0x08;
}
/* Adjust cycle count relatively to start of line */
cycles -= mcycles_vdp;
/* Cycle-accurate VINT flag (Ex-Mutants, Tyrant / Mega-Lo-Mania, Marvel Land) */
/* this allows VINT flag to be read just before vertical interrupt is being triggered */
if ((v_counter == bitmap.viewport.h) && (cycles >= (mcycles_vdp + 788)))
if ((v_counter == bitmap.viewport.h) && (cycles >= 788))
{
/* check Z80 interrupt state to assure VINT has not already been triggered (and flag cleared) */
if (Z80.irq_state != ASSERT_LINE)
@@ -1197,15 +1213,14 @@ unsigned int vdp_68k_ctrl_r(unsigned int cycles)
}
}
/* Cycle-accurate HBLANK flag (Sonic 3 & Sonic 2 "VS Modes", Bugs Bunny Double Trouble, Lemmings 2, Mega Turrican, V.R Troopers, Gouketsuji Ichizoku,...) */
/* NB: this is not 100% accurate (see hvc.h for horizontal events timings in H32 and H40 mode) but is close enough to make no noticeable difference for games */
if ((cycles % MCYCLES_PER_LINE) < 588)
/* Cycle-accurate HBLANK flag (Sonic 3 & Sonic 2 "VS Modes", Bugs Bunny Double Trouble, Lemmings 2, Mega Turrican, V.R Troopers, Gouketsuji Ichizoku, Ultraverse Prime, ...) */
if ((cycles >= hblank_start_cycle) && (cycles < hblank_end_cycle))
{
temp |= 0x04;
}
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VDP 68k status read -> 0x%x (0x%x) (%x)\n", v_counter, (v_counter + (cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, temp, status, m68k_get_reg(M68K_REG_PC));
error("[%d(%d)][%d(%d)] VDP 68k status read -> 0x%x (0x%x) (%x)\n", v_counter, (v_counter + cycles/MCYCLES_PER_LINE)%lines_per_frame, cycles + mcycles_vdp, cycles%MCYCLES_PER_LINE, temp, status, m68k_get_reg(M68K_REG_PC));
#endif
return (temp);
}
@@ -1691,7 +1706,7 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
}
else
{
render_bg = (reg[11] & 0x04) ? render_bg_m5_vs : render_bg_m5;
render_bg = (reg[11] & 0x04) ? (config.enhanced_vscroll ? render_bg_m5_vs_enhanced : render_bg_m5_vs) : render_bg_m5;
render_obj = (reg[12] & 0x08) ? render_obj_m5_ste : render_obj_m5;
}
@@ -1902,7 +1917,7 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
/* Vertical Scrolling mode */
if (d & 0x04)
{
render_bg = im2_flag ? render_bg_m5_im2_vs : render_bg_m5_vs;
render_bg = im2_flag ? render_bg_m5_im2_vs : (config.enhanced_vscroll ? render_bg_m5_vs_enhanced : render_bg_m5_vs);
}
else
{
@@ -1975,6 +1990,10 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
/* FIFO access slots timings */
fifo_timing = (int *)fifo_timing_h40;
/* HBLANK flag timings */
hblank_start_cycle = HBLANK_H32_START_MCYCLE;
hblank_end_cycle = HBLANK_H32_END_MCYCLE;
}
else
{
@@ -1995,6 +2014,10 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
/* FIFO access slots timings */
fifo_timing = (int *)fifo_timing_h32;
/* HBLANK flag timings */
hblank_start_cycle = HBLANK_H40_START_MCYCLE;
hblank_end_cycle = HBLANK_H40_END_MCYCLE;
}
/* Active screen width modified during VBLANK will be applied on upcoming frame */
@@ -2167,6 +2190,11 @@ static void vdp_bus_w(unsigned int data)
MARK_BG_DIRTY (index);
}
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_VRAM_W, 2, addr, data);
#endif
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, (v_counter + (m68k.cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
@@ -2203,13 +2231,19 @@ static void vdp_bus_w(unsigned int data)
color_update_m5(0x00, data);
}
/* CRAM modified during HBLANK (Striker, Zero the Kamikaze, etc) */
if ((v_counter < bitmap.viewport.h) && (reg[1] & 0x40) && (m68k.cycles <= (mcycles_vdp + 860)))
/* CRAM modified during HBLANK (Striker, Zero the Kamikaze, Yuu Yuu Hakusho, etc) */
if ((v_counter < bitmap.viewport.h) && (m68k.cycles <= (mcycles_vdp + 860)) && ((reg[1] & 0x40) || (index == border)))
{
/* Remap current line */
remap_line(v_counter);
}
}
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_CRAM_W, 2, addr, data);
#endif
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, (v_counter + (m68k.cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
@@ -2230,6 +2264,12 @@ static void vdp_bus_w(unsigned int data)
render_line(v_counter);
}
}
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_VSRAM_W, 2, addr, data);
#endif
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VSRAM 0x%x write -> 0x%x (%x)\n", v_counter, (v_counter + (m68k.cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
@@ -2434,6 +2474,11 @@ static unsigned int vdp_68k_data_r_m5(void)
/* read two bytes from VRAM */
data = *(uint16 *)&vram[addr & 0xFFFE];
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_VRAM_R, 2, addr, data);
#endif
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x read -> 0x%x (%x)\n", v_counter, (v_counter + (m68k.cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
@@ -2458,6 +2503,11 @@ static unsigned int vdp_68k_data_r_m5(void)
/* Unused bits are set using data from next available FIFO entry */
data |= (fifo[fifo_idx] & ~0x7FF);
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_VSRAM_R, 2, addr, data);
#endif
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VSRAM 0x%x read -> 0x%x (%x)\n", v_counter, (v_counter + (m68k.cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
@@ -2475,6 +2525,11 @@ static unsigned int vdp_68k_data_r_m5(void)
/* Unused bits are set using data from next available FIFO entry */
data |= (fifo[fifo_idx] & ~0xEEE);
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_CRAM_R, 2, addr, data);
#endif
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] CRAM 0x%x read -> 0x%x (%x)\n", v_counter, (v_counter + (m68k.cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
@@ -2489,6 +2544,11 @@ static unsigned int vdp_68k_data_r_m5(void)
/* Unused bits are set using data from next available FIFO entry */
data |= (fifo[fifo_idx] & ~0xFF);
#ifdef HOOK_CPU
if (cpu_hook)
cpu_hook(HOOK_VRAM_R, 2, addr, data);
#endif
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] 8-bit VRAM 0x%x read -> 0x%x (%x)\n", v_counter, (v_counter + (m68k.cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
+1 -1
View File
@@ -5,7 +5,7 @@
* Support for SG-1000 (TMS99xx & 315-5066), Master System (315-5124 & 315-5246), Game Gear & Mega Drive VDP
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
+631 -1
View File
@@ -6,6 +6,7 @@
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2022 AlexKiri (enhanced vscroll mode rendering function)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -1035,6 +1036,7 @@ void color_update_m4(int index, unsigned int data)
case SYSTEM_SG:
case SYSTEM_SGII:
case SYSTEM_SGII_RAM_EXT:
{
/* Fixed TMS99xx palette */
if (index & 0x0F)
@@ -1847,6 +1849,295 @@ void render_bg_m5_vs(int line)
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
}
/* Enhanced function that allows each cell to be vscrolled individually, instead of being limited to 2-cell */
void render_bg_m5_vs_enhanced(int line)
{
int column;
uint32 atex, atbuf, *src, *dst;
uint32 v_line, next_v_line, *nt;
/* Vertical scroll offset */
int v_offset = 0;
/* Common data */
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = 0;
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0];
/* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
/* Plane B width */
int start = 0;
int end = bitmap.viewport.w >> 4;
/* Plane B horizontal scroll */
#ifdef LSB_FIRST
uint32 shift = (xscroll >> 16) & 0x0F;
uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
#else
uint32 shift = (xscroll & 0x0F);
uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif
/* Left-most column vertical scrolling when partially shown horizontally (verified on PAL MD2) */
/* TODO: check on Genesis 3 models since it apparently behaves differently */
/* In H32 mode, vertical scrolling is disabled, in H40 mode, same value is used for both planes */
/* See Formula One / Kawasaki Superbike Challenge (H32) & Gynoug / Cutie Suzuki no Ringside Angel (H40) */
if (reg[12] & 1)
{
yscroll = vs[19] & (vs[19] >> 16);
}
if(shift)
{
/* Plane B vertical scroll */
v_line = (line + yscroll) & pf_row_mask;
/* Plane B name table */
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
/* Plane B line buffer */
dst = (uint32 *)&linebuf[0][0x10 + shift];
atbuf = nt[(index - 1) & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
else
{
/* Plane B line buffer */
dst = (uint32 *)&linebuf[0][0x20];
}
for(column = 0; column < end; column++, index++)
{
/* Plane B vertical scroll */
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
next_v_line = (line + (vs[column + 1] >> 16)) & pf_row_mask;
#else
v_line = (line + vs[column]) & pf_row_mask;
next_v_line = (line + vs[column + 1]) & pf_row_mask;
#endif
if (column != end - 1)
{
/* The offset of the intermediary cell is an average of the offsets of the current 2-cell and the next 2-cell. */
/* For the last column, the previously calculated offset is used */
v_offset = ((int)next_v_line - (int)v_line) / 2;
v_offset = (abs(v_offset) >= config.enhanced_vscroll_limit) ? 0 : v_offset;
}
/* Plane B name table */
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
#ifdef LSB_FIRST
GET_LSB_TILE(atbuf, v_line)
#else
GET_MSB_TILE(atbuf, v_line)
#endif
#ifdef ALIGN_LONG
WRITE_LONG(dst, src[0] | atex);
dst++;
WRITE_LONG(dst, src[1] | atex);
dst++;
#else
*dst++ = (src[0] | atex);
*dst++ = (src[1] | atex);
#endif
#ifdef LSB_FIRST
v_line = (line + v_offset + (vs[column] >> 16)) & pf_row_mask;
#else
v_line = (line + v_offset + vs[column]) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
#ifdef LSB_FIRST
GET_MSB_TILE(atbuf, v_line)
#else
GET_LSB_TILE(atbuf, v_line)
#endif
#ifdef ALIGN_LONG
WRITE_LONG(dst, src[0] | atex);
dst++;
WRITE_LONG(dst, src[1] | atex);
dst++;
#else
*dst++ = (src[0] | atex);
*dst++ = (src[1] | atex);
#endif
}
if (w == (line >= a))
{
/* Window takes up entire line */
a = 0;
w = 1;
}
else
{
/* Window and Plane A share the line */
a = clip[0].enable;
w = clip[1].enable;
}
/* Plane A */
if (a)
{
/* Plane A width */
start = clip[0].left;
end = clip[0].right;
/* Plane A horizontal scroll */
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
#endif
if(shift)
{
/* Plane A vertical scroll */
v_line = (line + yscroll) & pf_row_mask;
/* Plane A name table */
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
/* Window bug */
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index - 1) & pf_col_mask];
}
DRAW_COLUMN(atbuf, v_line)
}
else
{
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
}
for(column = start; column < end; column++, index++)
{
/* Plane A vertical scroll */
#ifdef LSB_FIRST
v_line = (line + vs[column]) & pf_row_mask;
next_v_line = (line + vs[column + 1]) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
next_v_line = (line + (vs[column + 1] >> 16)) & pf_row_mask;
#endif
if (column != end - 1)
{
v_offset = ((int)next_v_line - (int)v_line) / 2;
v_offset = (abs(v_offset) >= config.enhanced_vscroll_limit) ? 0 : v_offset;
}
/* Plane A name table */
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
#ifdef LSB_FIRST
GET_LSB_TILE(atbuf, v_line)
#else
GET_MSB_TILE(atbuf, v_line)
#endif
#ifdef ALIGN_LONG
WRITE_LONG(dst, src[0] | atex);
dst++;
WRITE_LONG(dst, src[1] | atex);
dst++;
#else
*dst++ = (src[0] | atex);
*dst++ = (src[1] | atex);
#endif
#ifdef LSB_FIRST
v_line = (line + v_offset + vs[column]) & pf_row_mask;
#else
v_line = (line + v_offset + (vs[column] >> 16)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
#ifdef LSB_FIRST
GET_MSB_TILE(atbuf, v_line)
#else
GET_LSB_TILE(atbuf, v_line)
#endif
#ifdef ALIGN_LONG
WRITE_LONG(dst, src[0] | atex);
dst++;
WRITE_LONG(dst, src[1] | atex);
dst++;
#else
*dst++ = (src[0] | atex);
*dst++ = (src[1] | atex);
#endif
}
/* Window width */
start = clip[1].left;
end = clip[1].right;
}
/* Window */
if (w)
{
/* Window name table */
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
/* Pattern row index */
v_line = (line & 7) << 3;
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN(atbuf, v_line)
}
}
/* Merge background layers */
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
}
void render_bg_m5_im2(int line)
{
int column;
@@ -2543,6 +2834,345 @@ void render_bg_m5_vs(int line)
}
}
void render_bg_m5_vs_enhanced(int line)
{
int column, start, end;
uint32 atex, atbuf, *src, *dst;
uint32 shift, index, v_line, next_v_line, *nt;
uint8 *lb;
/* Vertical scroll offset */
int v_offset = 0;
/* Scroll Planes common data */
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = 0;
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0];
/* Number of columns to draw */
int width = bitmap.viewport.w >> 4;
/* Layer priority table */
uint8 *table = lut[(reg[12] & 8) >> 2];
/* Window vertical range (cell 0-31) */
int a = (reg[18] & 0x1F) << 3;
/* Window position (0=top, 1=bottom) */
int w = (reg[18] >> 7) & 1;
/* Test against current line */
if (w == (line >= a))
{
/* Window takes up entire line */
a = 0;
w = 1;
}
else
{
/* Window and Plane A share the line */
a = clip[0].enable;
w = clip[1].enable;
}
/* Left-most column vertical scrolling when partially shown horizontally */
/* Same value for both planes, only in 40-cell mode, verified on PAL MD2 */
/* See Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge */
if (reg[12] & 1)
{
yscroll = vs[19] & (vs[19] >> 16);
}
/* Plane A*/
if (a)
{
/* Plane A width */
start = clip[0].left;
end = clip[0].right;
/* Plane A horizontal scroll */
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
#endif
/* Background line buffer */
dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
if(shift)
{
/* Left-most column is partially shown */
dst -= 4;
/* Plane A vertical scroll */
v_line = (line + yscroll) & pf_row_mask;
/* Plane A name table */
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
/* Window bug */
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index-1) & pf_col_mask];
}
DRAW_COLUMN(atbuf, v_line)
}
for(column = start; column < end; column++, index++)
{
/* Plane A vertical scroll */
#ifdef LSB_FIRST
v_line = (line + vs[column]) & pf_row_mask;
next_v_line = (line + vs[column + 1]) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
next_v_line = (line + (vs[column + 1] >> 16)) & pf_row_mask;
#endif
if (column != end - 1)
{
v_offset = ((int)next_v_line - (int)v_line) / 2;
v_offset = (abs(v_offset) >= config.enhanced_vscroll_limit) ? 0 : v_offset;
}
/* Plane A name table */
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
#ifdef LSB_FIRST
GET_LSB_TILE(atbuf, v_line)
#else
GET_MSB_TILE(atbuf, v_line)
#endif
#ifdef ALIGN_LONG
WRITE_LONG(dst, src[0] | atex);
dst++;
WRITE_LONG(dst, src[1] | atex);
dst++;
#else
*dst++ = (src[0] | atex);
*dst++ = (src[1] | atex);
#endif
#ifdef LSB_FIRST
v_line = (line + v_offset + vs[column]) & pf_row_mask;
#else
v_line = (line + v_offset + (vs[column] >> 16)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
#ifdef LSB_FIRST
GET_MSB_TILE(atbuf, v_line)
#else
GET_LSB_TILE(atbuf, v_line)
#endif
#ifdef ALIGN_LONG
WRITE_LONG(dst, src[0] | atex);
dst++;
WRITE_LONG(dst, src[1] | atex);
dst++;
#else
*dst++ = (src[0] | atex);
*dst++ = (src[1] | atex);
#endif
}
/* Window width */
start = clip[1].left;
end = clip[1].right;
}
else
{
/* Window width */
start = 0;
end = width;
}
/* Window Plane */
if (w)
{
/* Background line buffer */
dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
/* Window name table */
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
/* Pattern row index */
v_line = (line & 7) << 3;
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN(atbuf, v_line)
}
}
/* Plane B horizontal scroll */
#ifdef LSB_FIRST
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
#else
shift = (xscroll & 0x0F);
index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif
/* Background line buffer */
lb = &linebuf[0][0x20];
if(shift)
{
/* Left-most column is partially shown */
lb -= (0x10 - shift);
/* Plane B vertical scroll */
v_line = (line + yscroll) & pf_row_mask;
/* Plane B name table */
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
atbuf = nt[(index-1) & pf_col_mask];
DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
}
for(column = 0; column < width; column++, index++)
{
/* Plane B vertical scroll */
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
next_v_line = (line + (vs[column + 1] >> 16)) & pf_row_mask;
#else
v_line = (line + vs[column]) & pf_row_mask;
next_v_line = (line + vs[column + 1]) & pf_row_mask;
#endif
if (column != width - 1)
{
v_offset = ((int)next_v_line - (int)v_line) / 2;
v_offset = (abs(v_offset) >= config.enhanced_vscroll_limit) ? 0 : v_offset;
}
/* Plane B name table */
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
#ifdef ALIGN_LONG
#ifdef LSB_FIRST
GET_LSB_TILE(atbuf, v_line)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
v_line = (line + v_offset + (vs[column] >> 16)) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
GET_MSB_TILE(atbuf, v_line)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
#else
GET_MSB_TILE(atbuf, v_line)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
v_line = (line + vs[column]) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
GET_LSB_TILE(atbuf, v_line)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = READ_LONG((uint32 *)lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
#endif
#else /* NOT ALIGNED */
#ifdef LSB_FIRST
GET_LSB_TILE(atbuf, v_line)
xscroll = *(uint32 *)(lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = *(uint32 *)(lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
v_line = (line + v_offset + (vs[column] >> 16)) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
GET_MSB_TILE(atbuf, v_line)
xscroll = *(uint32 *)(lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = *(uint32 *)(lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
#else
GET_MSB_TILE(atbuf, v_line)
xscroll = *(uint32 *)(lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = *(uint32 *)(lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
v_line = (line + vs[column]) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
GET_LSB_TILE(atbuf, v_line)
xscroll = *(uint32 *)(lb);
yscroll = (src[0] | atex);
DRAW_BG_TILE(xscroll, yscroll)
xscroll = *(uint32 *)(lb);
yscroll = (src[1] | atex);
DRAW_BG_TILE(xscroll, yscroll)
#endif
#endif /* ALIGN_LONG */
}
}
void render_bg_m5_im2(int line)
{
int column, start, end;
@@ -4125,7 +4755,7 @@ void render_line(int line)
/* Left-most column blanking */
if (reg[0] & 0x20)
{
if (system_hw > SYSTEM_SGII)
if (system_hw >= SYSTEM_MARKIII)
{
memset(&linebuf[0][0x20], 0x40, 8);
}
+2
View File
@@ -6,6 +6,7 @@
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2022 AlexKiri (enhanced vscroll mode rendering function)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@@ -118,6 +119,7 @@ extern void render_bg_inv(int line);
extern void render_bg_m4(int line);
extern void render_bg_m5(int line);
extern void render_bg_m5_vs(int line);
extern void render_bg_m5_vs_enhanced(int line);
extern void render_bg_m5_im2(int line);
extern void render_bg_m5_im2_vs(int line);
extern void render_obj_tms(int line);
+22 -8
View File
@@ -38,6 +38,7 @@
* - Implemented cycle-accurate INI/IND (needed by SMS emulation)
* - Fixed Z80 reset
* - Made SZHVC_add & SZHVC_sub tables statically allocated
* - Fixed compiler warning when BIG_SWITCH is defined
* Changes in 3.9:
* - Fixed cycle counts for LD IYL/IXL/IYH/IXH,n [Marshmellow]
* - Fixed X/Y flags in CCF/SCF/BIT, ZEXALL is happy now [hap]
@@ -209,6 +210,7 @@ UINT32 z80_cycle_ratio;
#endif
Z80_Regs Z80;
UINT8 z80_last_fetch;
unsigned char *z80_readmap[64];
unsigned char *z80_writemap[64];
@@ -428,7 +430,9 @@ typedef void (*funcptr)(void);
INLINE void prefix##_f0(void); INLINE void prefix##_f1(void); INLINE void prefix##_f2(void); INLINE void prefix##_f3(void); \
INLINE void prefix##_f4(void); INLINE void prefix##_f5(void); INLINE void prefix##_f6(void); INLINE void prefix##_f7(void); \
INLINE void prefix##_f8(void); INLINE void prefix##_f9(void); INLINE void prefix##_fa(void); INLINE void prefix##_fb(void); \
INLINE void prefix##_fc(void); INLINE void prefix##_fd(void); INLINE void prefix##_fe(void); INLINE void prefix##_ff(void); \
INLINE void prefix##_fc(void); INLINE void prefix##_fd(void); INLINE void prefix##_fe(void); INLINE void prefix##_ff(void);
#define FUNCTABLE(tablename,prefix) \
static const funcptr tablename[0x100] = { \
prefix##_00,prefix##_01,prefix##_02,prefix##_03,prefix##_04,prefix##_05,prefix##_06,prefix##_07, \
prefix##_08,prefix##_09,prefix##_0a,prefix##_0b,prefix##_0c,prefix##_0d,prefix##_0e,prefix##_0f, \
@@ -464,12 +468,21 @@ static const funcptr tablename[0x100] = { \
prefix##_f8,prefix##_f9,prefix##_fa,prefix##_fb,prefix##_fc,prefix##_fd,prefix##_fe,prefix##_ff \
}
PROTOTYPES(Z80op,op);
PROTOTYPES(Z80cb,cb);
PROTOTYPES(Z80dd,dd);
PROTOTYPES(Z80ed,ed);
PROTOTYPES(Z80fd,fd);
PROTOTYPES(Z80xycb,xycb);
PROTOTYPES(Z80op,op)
PROTOTYPES(Z80cb,cb)
PROTOTYPES(Z80dd,dd)
PROTOTYPES(Z80ed,ed)
PROTOTYPES(Z80fd,fd)
PROTOTYPES(Z80xycb,xycb)
#ifndef BIG_SWITCH
FUNCTABLE(Z80op,op);
#endif
FUNCTABLE(Z80cb,cb);
FUNCTABLE(Z80dd,dd);
FUNCTABLE(Z80ed,ed);
FUNCTABLE(Z80fd,fd);
FUNCTABLE(Z80xycb,xycb);
/****************************************************************************/
/* Burn an odd amount of cycles, that is instructions taking something */
@@ -648,7 +661,8 @@ INLINE UINT8 ROP(void)
{
unsigned pc = PCD;
PC++;
return cpu_readop(pc);
z80_last_fetch = cpu_readop(pc);
return z80_last_fetch;
}
/****************************************************************
+1
View File
@@ -50,6 +50,7 @@ typedef struct
extern Z80_Regs Z80;
extern UINT8 z80_last_fetch;
#ifdef Z80_OVERCLOCK_SHIFT
extern UINT32 z80_cycle_ratio;
+29 -29
View File
@@ -1,45 +1,43 @@
#ifndef _OSD_H
#define _OSD_H
#ifndef _OSD_H_
#define _OSD_H_
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "scrc32.h"
#define MAX_INPUTS 8
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef M_PI
#define M_PI 3.1415926535897932385
#endif
#define CHEATS_UPDATE() ROMCheatUpdate()
typedef struct
void osd_input_update(void);
int load_archive(char*, unsigned char*, int, char *);
extern void ROMCheatUpdate(void);
typedef struct
{
int8 device;
uint8 port;
uint8 padtype;
} t_input_config;
struct
typedef struct
{
char version[16];
uint8 hq_fm;
uint8 filter;
uint8 hq_psg;
uint8 dac_bits;
uint8 ym2612;
uint8 ym2413;
uint8 cd_latency;
#ifdef HAVE_YM3438_CORE
uint8 ym3438;
#endif
#ifdef HAVE_OPLL_CORE
uint8 opll;
#endif
uint8 mono;
int16 psg_preamp;
int16 fm_preamp;
int16 lp_range;
int16 cdda_volume;
int16 pcm_volume;
uint16 lp_range;
int16 low_freq;
int16 high_freq;
int16 lg;
@@ -53,19 +51,25 @@ struct
uint8 addr_error;
uint8 bios;
uint8 lock_on;
uint8 add_on;
uint8 overscan;
uint8 gg_extra;
uint8 ntsc;
uint8 lcd;
uint8 gg_extra;
uint8 render;
uint8 enhanced_vscroll;
uint8 enhanced_vscroll_limit;
t_input_config input[MAX_INPUTS];
} config;
} t_config;
extern t_config config;
extern char GG_ROM[256];
extern char AR_ROM[256];
extern char SK_ROM[256];
extern char SK_UPMEM[256];
extern char GG_BIOS[256];
extern char MD_BIOS[256];
extern char CD_BIOS_EU[256];
extern char CD_BIOS_US[256];
extern char CD_BIOS_JP[256];
@@ -73,8 +77,4 @@ extern char MS_BIOS_US[256];
extern char MS_BIOS_EU[256];
extern char MS_BIOS_JP[256];
void osd_input_update(void);
int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension);
extern void ROMCheatUpdate(void);
#endif /* _OSD_H */
#endif /* _OSD_H_ */
+2 -2
View File
@@ -1,7 +1,7 @@
#ifndef _S_CRC32_H
#define _S_CRC32_H
static const unsigned long crc_table[256] = {
static const unsigned int crc_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
@@ -61,7 +61,7 @@ static const unsigned long crc_table[256] = {
#define DO4_CRC32(buf) DO2_CRC32(buf); DO2_CRC32(buf);
#define DO8_CRC32(buf) DO4_CRC32(buf); DO4_CRC32(buf);
unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len)
unsigned int crc32(unsigned int crc, const unsigned char *buf, unsigned int len)
{
if (buf == 0) return 0L;
crc = crc ^ 0xffffffffL;
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef _S_CRC32_H
#define _S_CRC32_H
unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len);
unsigned int crc32(unsigned int crc, const unsigned char *buf, unsigned int len);
#endif